Is there any way to make it more simple?

I want to make multiple commands script for my game , everything is fine but i want to write each command as a function, means i don’t want additional things connected to some functions outside the function cause jt makes me feel dizzy, so this is my script , any way to write it more simple ? I mean currentconnection &currentplayer &playerremoving

_G.CurrentConnection=nil
local currentPlayer=''
game.Players.PlayerRemoving:Connect(function(v)
  if v.Name:lower()==currentPlayer then
    workspace.Camera.CameraSubject=game:GetService'Players'.LocalPlayer.Character:FindFirstChild'Humanoid'
  end
end)
local function Split(Text,Value)
  assert(Value)
  if Text:match(Value) then
  local result=Text:gsub('\32',''):sub(Text:gsub('\32',''):find(Value)+rawlen(Value),rawlen(Text:gsub('\32','')))
   return result
  else
    print[[Given Value Was Not In The Text]]
    return nil
  end
end
function OnSpy(Msg)
  if Msg:lower():match'g_spy' then
  Msg=Split(Msg:lower(),'g_spy')
    for i,v in next,game:GetService'Players':GetPlayers() do
        if v.Name:lower():sub(1,#Msg)==Msg then
            workspace.Camera.CameraSubject=v.Character:FindFirstChild'Humanoid';
          currentPlayer=v.Name:lower()
          if _G.CurrentConnection==nil then
            _G.CurrentConnection=v.CharacterAdded:Connect(function(chr)
             workspace.Camera.CameraSubject=chr:WaitForChild'Humanoid';
            end)
            return
          elseif _G.CurrentConnection then
            _G.CurrentConnection:Disconnect()
          end
          _G.CurrentConnection=v.CharacterAdded:Connect(function(chr)
             workspace.Camera.CameraSubject=chr:WaitForChild'Humanoid';
            end)
            return
        elseif v.DisplayName:lower():sub(1,#Msg)==Msg then
            workspace.Camera.CameraSubject=v.Character:FindFirstChild'Humanoid';
          currentPlayer=v.Name:lower()
          if _G.CurrentConnection==nil then
            _G.CurrentConnection=v.CharacterAdded:Connect(function(chr)
             workspace.Camera.CameraSubject=chr:WaitForChild'Humanoid';
            end)
            return
          elseif _G.CurrentConnection then
            _G.CurrentConnection:Disconnect()
          end
          _G.CurrentConnection=v.CharacterAdded:Connect(function(chr)
             workspace.Camera.CameraSubject=chr:WaitForChild'Humanoid';
            end)
          return
       end
    end
  end
end
local CMDS={
  ['g_spy']=OnSpy
}
local function Speaker_Listener(msg)
  for i,v in next,CMDS do
    if msg:lower():find(i:lower()) then
      coroutine.wrap(rawget(CMDS,i))(msg)
    end
  end
end
game:GetService'Players'.LocalPlayer.Chatted:Connect(Speaker_Listener)

Split code into modules, i propose you create command info table where you determine sub class of command (health, moving player, camera ect.) then simply get module of this sub class and call function named command

I wrote you a small command system. You can simply add commands as a child of the modulescript.

Localscript, for activation:

local CheckMessage = require(game.ReplicatedStorage.Commands)


local TextChatService = game:GetService('TextChatService')

TextChatService.OnIncomingMessage = function(message)
	CheckMessage(message.Text)
end

Main modulescript:

local Commands = {}
local Aliases = {}

local prefixChar = '!'
for i,v in script:GetChildren() do
	if v:IsA("ModuleScript") then
		Commands[v.Name] = require(v)
		for x,z in Commands[v.Name].aliases do
			Aliases[z]=v.Name
		end
	end
end

local function CallCommand(command : string, parameters : {string})
	return Commands[command](parameters)
end

function CheckMessage(msg : string)
	local prefix = string.sub(msg, 1, 1)
	if prefix == prefixChar then
		print(msg)
		local commandName = string.match(string.sub(msg,2),"%a+")
		local parameters = string.match(msg,"%s.+") or ""
	
		parameters = string.split(string.sub(parameters,2), ", ")
		if not Commands[commandName] and Commands[Aliases[commandName]] then
			commandName = Aliases[commandName]
		end
		if Commands[commandName] then
			CallCommand(commandName, parameters)
		end
	end
	return false
end


return CheckMessage

Example child modulescript (named countdown)

--[[
Creates a countdown, specify duration as first parameter
]]
return setmetatable({aliases = {string.lower(script.Name), "cd"}}, {__call = function(t,pars)
		task.spawn(function()
			for i = 0,pars[1] or 5 do
				print((pars[1] or 5) - i)
				wait(1)
			end
			print("Countdown ended")
		end)
	end
})

What does ‘%a+’ or ‘%s.+’ format do ?

It’s regex. A specific text pattern, for roblox to try and find. I use them to seperate the command from the parameters.
I start at char #2, because char #1 is the prefix.
From char #2, I get all alphanumerical characters until I reach a white space or the end of the string.

%a means ‘alphanumerical character’
‘+’ means ‘match one or more of the preceding character’

!command parameter, parameter
-- We start our search at position 2
![command parameter, parameter
-- Now it will find all alphanumerical characters until hitting something else
![command] parameter, parameter
-- Result is command

So together, it will match every alphanumerical character until it hits anything that isn’t.

The other one is a little bit more complicated.

%s is for a whitespace. I use this because I know every command will have a whitespace, if it has parameters, between the command and the parameter.

!command parameter, parameter
-- We start our search at the whitespace
!command[ parameter, parameter
-- Now we get all characters until end of string
!command[ parameter, parameter]
-- But we have included the whitespace, so we just do the same thing as before and start from 1 position further
!command [parameter, parameter]
-- And then I just use string split to get the parameters in an array
local p = {parameter, parameter}

That helped me alot tk understand formats

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.