I wrote a ServerScript that chooses a random ModuleScript from a folder, each of the ModuleScripts in the folder contain different game-modes. The problem I am facing now is that I do not know how to get the ServerScript to know when the selected game-mode has already finished and it is now required to select another ModuleScript from the folder. Basically a Game-Mode system.
How do I get either the ServerScript or ModuleScript to choose another ModuleScript after the game-mode is over?
Server Script:
function StartRound1()
if Playercount >= 1 then
task.wait()
local GM = script.GameModes:GetChildren()
local SelectGamemode = GM[math.random(1, #GM)]
print(SelectGamemode)
local SG = require(SelectGamemode)
else
task.wait(5)
print("StartRound1Loading")
StartRound1()
end
end
StartRound1()
function StartRound2(Round2)
--- I want to start round 2 here
---How do I get the script to detect that the first round is over?
end
You said different ModuleScripts contain different gamemodes, right?
You can do slight modifications to the modules so they return a table instead of a singular function structured like so:
I’d assume your gamemode module looks something like this:
local function gamemode()
-- do gamemode stuff
end
return gamemode
And I’d assume your server script to randomly pick out one of the gamemode modules and calls the returned function. In the current setup there is no way to know when the gamemode is over.
I can think of two solutions on the top of my head:
Solution 1:
Make the gamemode module return a gamemode and a bindable. Fire the bindable when the gamemode ends in the gamemode function itself.
local finishedBindable = Instance.new("BindableEvent")
local function gamemode()
-- do gamemode stuff
-- when gamemode ends,
finishedBindable:Fire()
end
return {Callback = gamemode, Finished = finishedBindable.Event}
and on the server script, you can achieve an infinite loop of random gamemode selection like so:
while true do
local randomModule = getRandomModule()
randomModule.Callback()
randomModule.Finished:Wait()
end
Solution 2:
You can directly make the function return the bindable so you can directly deal with the module in one line:
local finishedEvent = randomModule()
finishedEvent:Wait()
This is my attempt or at least what I understand from Solution 2. No, it doesnt work.
If it helps I can provide you one of the game-mode module scripts.
function StartRound1(SelectGamemode)
if Playercount >= 1 then
task.wait()
local GM = script.GameModes:GetChildren()
local SelectGamemode = GM[math.random(1, #GM)]
print(SelectGamemode)
local SG = require(SelectGamemode)
local FinishedEvent = SelectGamemode()
FinishedEvent:Wait()
else
task.wait(5)
print("StartRound1Loading")
StartRound1()
end
end
StartRound1()
local FinishedEvent = StartRound1()
FinishedEvent:Wait()
function StartRound2()
print("StartRound2")
end
StartRound2()
I don’t quite understand what you’re trying to achieve in the script there. Are you trying to wait in the chosen gamemode itself?
The reason for it to not work: I think you didn’t create a BindableEvent and return it from the gamemode function.
I do apologies if my script seems rather hard to understand, nonetheless I will try my best to break it down.
This StartRound function will run if there are at least 1 player in my game. The function will then retrieve my GameModes folder in ServerReplicatedStorage, the SelectGamemode variable will then randomly pick 1 of the ModuleScripts in my GameModes folder. The SG variable will then require() the chosen gamemode. The code after else basically runs the StartRound1 function again if there are less than 1 players.
For this I really do not understand how to properly use it. I will provide you one of the ModuleScripts that contains the gamemode function. I would really appreciate it if you can point out if there are any flaws or redundancy in my script.
Module Script
---------------------Termination Gamemode--------------------
local module = {}
local GUIT = game:GetService("ReplicatedStorage")["GUI Trigger"]
function ChooseEmployee(ChosenEmployee)
local NOP = game:GetService("Players"):GetChildren()
print(NOP)
if #NOP >= 1 then do
local ChosenEmployee = NOP[math.random(1, #NOP)]
local Announcement = "The Company has deemed the selected Employee as irrelevant.\nPlease terminate them."
GUIT:FireAllClients(Announcement)
print(ChosenEmployee)
local TSE = Instance.new("StringValue")
TSE.Name = "Terminate"
TSE.Parent = ChosenEmployee
local CEName = ChosenEmployee.Name ----- Player Name
local CEChar = game.Workspace:FindFirstChild(CEName) ----- Player's Character
local CEHighlight = Instance.new("Highlight") ----- Character Highli8ght
CEHighlight.DepthMode = "Occluded"
CEHighlight.FillTransparency = 1
CEHighlight.OutlineColor = Color3.new(255, 0, 0)
CEHighlight.OutlineTransparency = 0
CEHighlight.Parent = CEChar
local ETDebounce = false
local function EmployeeTerminated()
while true do
if ETDebounce == false and CEChar:WaitForChild("Humanoid").Health == 0 then
task.wait()
ChosenEmployee.Terminate:Destroy()
ETDebounce = true
local Announcement = "Your cooperation has been noted."
GUIT:FireAllClients(Announcement)
print("Employee Successfully Terminated")
else
task.wait()
EmployeeTerminated()
end
end
end
if ETDebounce == false then
EmployeeTerminated()
end
end
else
task.wait(5)
print("ChosenEmployeeWaiting")
ChosenEmployee(ChosenEmployee)
end
end
ChooseEmployee()
return module
Okay so as far as I understand, you are checking for 2 players to exist in the server and then start selection of random gamemodes.
Your main script can be something like:
local playersService = game:GetService("Players")
local gamemodes = pathToFolder:GetChildren()
local function selectRound()
while true do
local currentGamemode = gamemodes[math.random(#gamemodes)] -- choose random gamemode module
local finished = require(currentGamemode)() -- require module and call module function
finished:Wait() -- wait for event to be fired
end
end
local roundThread -- save thread
-- begin round loop if 2 player eligibility criteria is met
playersService.PlayerAdded:Connect(function()
if not roundThread and #playersService:GetPlayers() >= 2 then
roundThread = task.spawn(selectRound)
end
end)
-- if 2 player eligibility criteria is no longer met, stop round loop
playersService.PlayerRemoving:Connect(function()
if roundThread and #playersService:GetPlayers() < 2 then
task.cancel(roundThread)
roundThread = nil
end
end)
And your gamemode ModuleScript:
local finishedBindable = Instance.new("BindableEvent")
local function gamemode()
-- do gamemode stuff
-- if you want to terminate this gamemode (finish it), call
finishedBindable:Fire()
return finishedBindable.Event
end
return gamemode
Since module scripts can yield scripts, for example
The module script:
task.wait(5)
return 0
The server script
require(ModuleScript) -- this will wait 5 seconds
print("Waited 5 seconds!")
You can technically do
function StartRound1()
if Playercount >= 1 then
task.wait()
local GM = script.GameModes:GetChildren()
local SelectGamemode = GM[math.random(1, #GM)]
print(SelectGamemode)
local SG = require(SelectGamemode)
StartRound2()
else
task.wait(5)
print("StartRound1Loading")
StartRound1()
end
end
StartRound1()
function StartRound2(Round2)
-- round 2 code
end
Tho I may be wrong because I have not read your code all the way trough.
My apologies for the late reply. I am still trying to understand what you have taught me to write in my script.
I realized that I might not need thess lines to run the script, but I can instead op in for a loop that continuously chooses a new random module script.
-- begin round loop if 2 player eligibility criteria is met
playersService.PlayerAdded:Connect(function()
if not roundThread and #playersService:GetPlayers() >= 2 then
roundThread = task.spawn(selectRound)
end
end)
-- if 2 player eligibility criteria is no longer met, stop round loop
playersService.PlayerRemoving:Connect(function()
if roundThread and #playersService:GetPlayers() < 2 then
task.cancel(roundThread)
roundThread = nil
end
end)
I still have some questions that require some further explanations.
What does local finishedBindable = Instance.new("BindableEvent") and finishedBindable:Fire() return finishedBindable.Event do exactly. How does the script communication in this scenario work?
I am still faced with the confusion of what I should put in between the parentheses of require(currentGamemode)(-------what do I put here------)
Why do I need to put return Termination() instead of return Module at the end of the module script. I do not understand to where am I returning the function to.
I intend on replacing this line with a loop function that will wait until the module script is finish, then it will run the loop of choosing another gamemode function. Currently I have no clue on how I should approach this idea of mine, but I believe I must understand what BindableEvent is before knowing what to do next; which brings me back to the 1st question I am asking above.
local roundThread -- save thread
if #Players:GetPlayers() >= 1 then
task.wait(1)
roundThread = task.spawn(selectRound)
end
My Server Script currently:
--------------------------GameModes-----------------------------
wait(15) ---- Wait time to allow players to load first
local gamemodes = game:GetService("ServerScriptService").MainScript.GameModes:GetChildren()
local function selectRound()
while true do
local currentGamemode = gamemodes[math.random(#gamemodes)] -- choose random gamemode module
local finished = require(currentGamemode)() -- require module and call module function
finished:Wait() -- wait for event to be fired
end
end
local roundThread -- save thread
if #Players:GetPlayers() >= 1 then
task.wait(1)
roundThread = task.spawn(selectRound)
end
Module Script: *I copy pasted to test the functionality of the script, currently the module script itself works, but I am unsure if the things you suggested are functioning as intended as the questions I asked above are hindering my understanding.
---------------------Termination Gamemode--------------------
local module = {}
local finishedBindable = Instance.new("BindableEvent")
local GUIT = game:GetService("ReplicatedStorage")["GUI Trigger"]
local function Termination()
local NOP = game:GetService("Players"):GetChildren()
print(NOP)
if #NOP >= 1 then do
local ChosenEmployee = NOP[math.random(1, #NOP)]
local Announcement = "The Company has deemed the selected Employee as irrelevant.\nPlease terminate them."
GUIT:FireAllClients(Announcement)
print(ChosenEmployee)
local TSE = Instance.new("StringValue")
TSE.Name = "Terminate"
TSE.Parent = ChosenEmployee
local CEName = ChosenEmployee.Name ----- Player Name
local CEChar = game.Workspace:FindFirstChild(CEName) ----- Player's Character
local CEHighlight = Instance.new("Highlight") ----- Character Highli8ght
CEHighlight.DepthMode = "Occluded"
CEHighlight.FillTransparency = 1
CEHighlight.OutlineColor = Color3.new(255, 0, 0)
CEHighlight.OutlineTransparency = 0
CEHighlight.Parent = CEChar
local ETDebounce = false
local function EmployeeTerminated()
while true do
if ETDebounce == false and CEChar:WaitForChild("Humanoid").Health == 0 then
task.wait()
ChosenEmployee.Terminate:Destroy()
ETDebounce = true
local Announcement = "Your cooperation has been noted."
GUIT:FireAllClients(Announcement)
print("Employee Successfully Terminated")
else
task.wait()
EmployeeTerminated()
end
end
end
if ETDebounce == false then
EmployeeTerminated()
end
end
else
task.wait(5)
print("ChosenEmployeeWaiting")
Termination()
end
finishedBindable:Fire()
return finishedBindable.Event
end
return Termination()