Chat Commands
Overview
In this tutorial you are going to create chat commands that can be typed into the chat that will perform an action if the player has permission, by using chat hooks. You will be creating some general commands that can be useful for most games. You will also be creating commands that are aimed specifically at some of the frameworks to show how commands can be used to help test your game.
- Completion Time: ~1 hour
- Knowledge Level: It is recommended to have completed the Scripting Beginner and Scripting Intermediate tutorials.
- Skills you will learn:
- Requiring the Command Parser API.
- Creating permissions.
- Writing custom commands.
Import Asset from Community Content
You will be importing an asset from Community Content that will help you create the admin commands by providing you an API to speed up development.
- Open the Community Content window.
- Search for
Chat Commands
by CoreAcademy. - Click Import.
Enable Player Storage
The Command Parser will need to save the permission for the player persistently when you promote / demote a player. Make sure to enable Player Storage in the Properties window for the Game Settings object.
Requiring the Command Parser API
To create commands, you will need to require the CommandParser script so you have access to all the functions in the API.
Create CommandParser Custom Property
Drag and drop the CommandParser script on to the script you want to use to create commands.
Context
The script that you will be using to create the commands should be in a server context. If you need to create client side commands, then it is recommended to create a separate script. In a later section, server vs client commands will be discussed.
Require the CommandParser API
By requiring the Command Parser API at the top of your script, you will then have access to the functions and permissions. By default the Command Parser comes with the promote
and demote
commands, these can be found in the CommandParser script.
local CommandParser = require(script:GetCustomProperty("CommandParser"))
Using Permissions
The Command Parser comes with a basic permission system that allows for special players (usually the creator) to promote and demote other players. For example, if you want to add a moderator to your game that has access to certain commands, you can easily promote a player by using the promote command.
/promote player permission
The permissions system will use player storage to save the permission, and also setup a player resource with the permission key. This can then be used client side if you would like to show which players have certain permissions (i.e. in a player list).
The permission system comes with 3 default permissions:
CREATOR
ADMIN
MODERATOR
Open up the CommandPermissions script to see how the permissions are set up.
Set Creators
The CREATORS
permission is special. It has no priority
property, only an array of player names. These player names are what you would consider to be root admins. Any player name in the names
array will have access to all commands.
Only add player names to the array that you trust (i.e. co-creators of the game). It is generally a good idea to just have your own name here, and use the promote
command to promote trusted players to regular admins.
CREATOR = {
names = { "CommanderFoo" },
name = "Creator"
},
Add New Permission
The priority
value is important, as it determines if the player has access to all the permissions that have a lower priority. For example, the ADMIN
permission has a priority of 50
, this means any permission with a lower number that 50
will be granted to the player. If you have a command that is available for players with the MODERATOR
permission, then players with the ADMIN
permission would also be allowed to use that command.
For example, adding a new permission called HEAD_MODERATOR
with a priority
of 40
, would allow access to all MODERATOR
commands, because the MODERATOR
permission has a lower priority
value of 30
, but the HEAD_MODERATOR
would not have access to the commands for ADMIN
or CREATOR
.
HEAD_MODERATOR = {
priority = 40,
name = "Head Moderator"
},
Promote Player
Players with the CREATOR
permission are allowed to promote other players by using the promote
command.
The permission
value of the command, is the key for the permission. So for example, if you want to promote the player Bob
to Admin
, you would type the following command into the chat.
/promote Bob admin
The permission value (admin
for the above example) for the command is case insensitive.
Demote Player
Players with the CREATOR
permission are allowed to demote other players by using the demote
command. This will remove the permission from the player, and revert them back to a regular player on the server.
/demote Bob
Creating Custom Commands
In this section you will learn how to use the Command Parser to create your own commands.
Create a Print Command
You will create a print
command that will demonstrate how to create a single command that will print a message to the Event Log.
CommandParser.AddCommand("print", function(sender, params, status)
print("Hello World!")
end)
Test the Command
Run the command /print
in the chat, and see the Event Log.
Check Permission
Right now, the print
command will work for any player that enters it into the chat. You will be changing the print
command so that it only works for players that have the CREATOR
permission.
The CommandParser has a function called HasPermission
that accepts 2 arguments:
Argument | Description |
---|---|
sender |
The player who issued the command in the chat. |
permission |
The permission to check against the sender . |
All the permissions can be accessed via the permissions
property of the CommandParser
. By passing in the CREATOR
permission to the HasPermission
function, either true
or false
will be returned if the sender
has permission to use the command.
CommandParser.AddCommand("print", function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.CREATOR) then
print("Hello World!")
end
end)
Provide Command Feedback
It may be useful to know if the command was successful or not. The function callback for each command has 3 parameters.
Parameter | Description |
---|---|
sender |
The player who issued the command in the chat. |
params |
The parameters for the command. params[1] is the command name. |
status |
The status table for this command. |
The status
parameter is a table that is passed in by reference, which allows you to change the properties on this table and the callee will use those values to provide feedback to the sender and receiver if set.
Property | Description |
---|---|
status.success |
Either true or false if the command was successful or not. Default is false . |
status.senderMessage |
A message that will be displayed in the chat for the sender of the command. |
status.receiverPlayer |
The player who will receive the message. |
status.receiverMessage |
If status.success is true , and a receiverPlayer is set, then the receiver will receive the message in chat. |
For example, take the basic print
command created early and add feedback to the sender.
CommandParser.AddCommand("print", function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.CREATOR) then
print("Hello World!")
status.success = true
status.senderMessage = "Print command was successful."
end
end)
Test the command and make sure a message is received back in the chat.
Create Print Sub Commands
So far the print
command is a single command. You will change the print
command to have 2 sub commands. A sub command is a keyword that follows the main command. For example, print time
, print
is the main command, time
is the sub command.
Instead of passing in a function as the second argument of the AddCommand
function, a table can be passed in that is made up of key value pairs, where the value is a function.
You will create 2 sub commands.
Command | Description |
---|---|
time |
Prints the current local time in the chat. |
word |
Prints the word entered as the 3rd parameter of the chat command. By using the params parameter, you have access to each section of the command. |
CommandParser.AddCommand("print", {
time = function(sender, params, status)
status.success = true
status.senderMessage = "Time is: " .. tostring(DateTime.CurrentTime({ isLocal = true })) .. "."
end,
word = function(sender, params, status)
if params[3] ~= nil then
status.success = true
status.senderMessage = "The word was: " .. params[3]
end
end
})
Commands that don't need the permission to be checked, like the print
command above, can be placed into a separate script that is in a client context. The CommandParser will check what environment it is being executed in.
Test both commands:
/print time
/print word Hello
Creating General Commands
In this section you will create general commands that could be useful for most games. Try to keep all your general commands in a separate script, and any game specific commands in another script. This will be more modular for when you need to extract just the general commands to be used in another game.
Teleport
Being able to teleport to a player, or teleporting a player to another player can be a useful command, especially when you need to do some debugging in a published game.
The command needs to support 2 variations.
- Teleporting the sender to a specific player.
- Teleporting a player to another player.
To do this, you will need to look at params[2]
and params[3]
. If params[3]
doesn't exist, then you will assume the command sender is the player being teleported.
The Command Parser has a helper function called GetPlayer
that will validate the value and find a player that matches the name entered in the command.
An extra quality of life addition, is to match the rotation of the player being teleported too.
-- /tp toplayer
-- /tp player toplayer
CommandParser.AddCommand("tp", function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.MODERATOR) then
local playerA = CommandParser.GetPlayer(params[2])
local playerB = CommandParser.GetPlayer(params[3])
if playerA ~= nil then
if playerB ~= nil then
playerA:SetWorldPosition(playerB:GetWorldPosition())
playerA:SetWorldRotation(playerB:GetWorldRotation())
else
sender:SetWorldPosition(playerA:GetWorldPosition())
sender:SetWorldRotation(playerA:GetWorldRotation())
end
status.success = true
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end)
Test the command in multiplayer preview mode.
- Test the sender of the command can teleport to a player.
- Test the sender of the command can teleport a player to another player.
- Test the permission of the command.
Kick
Being able to kick a player from a server for being a nuisance is a good command for moderators to have. This command will be basic and just kick the player to Core World. They have the ability to rejoin, so as a challenge, try and improve on the command by auto kicking them when they rejoin within a certain time frame. This could done by storing a future timestamps and when a player joins, check if the current time is less that the future time. This could be a good way to have a cooling off period of that player.
An additional sub command to kick all players on the server apart from the sender could be good as well. This would allow you to kick all the players and possibly close the server from accepting players so you can do some testing.
By using the TransferToGame
function, you can transfer a player, or all players to a specific game if you have the game ID. In this case, the game ID will be Core World.
-- /kick player
-- /kick all
CommandParser.AddCommand("kick", function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.MODERATOR) then
local who = CommandParser.ParamIsValid(params[2])
if who ~= nil then
if who == "all" then
for k, player in ipairs(Game.GetPlayers()) do
if player ~= sender then
player:TransferToGame("e39f3e/core-world")
end
end
status.success = true
status.senderMessage = "All players kicked."
else
who = CommandParser.GetPlayer(params[2])
if who ~= nil then
who:TransferToGame("e39f3e/core-world")
status.success = true
status.senderMessage = "Player kicked."
end
end
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end)
The function TransferToGame
will not work in local preview. You can still try the command and see if the correct response is displayed. To test this properly, you would need to publish your game and get another player to help, or kick yourself.
Close Server
Debugging a published game could be disruptive to other players on the server. Being able to close a server instance from accepting players is a very useful command. Combined with the kick
command, it allows you to test a specific instance without disrupting players trying to play the game.
By using StopAcceptingPlayers
, the server instance will close, meaning no other player can join.
-- /closeserver
CommandParser.AddCommand("closeserver", function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
Game.StopAcceptingPlayers()
status.success = true
status.senderMessage = "Server closed."
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end)
Test the command in local multiplayer preview by loading up 1 player. After issuing the command, try to add another player. You will notice a message letting you know the instance is not accepting any more players.
Fly
Being able to fly can be useful to get to locations quickly in your game. This is really easy to add as a command, as you can use the ActivateFlying
function to fly, and ActivateWalking
function to turn it off.
-- /fly on
-- /fly off
CommandParser.AddCommand("fly", {
on = function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
sender:ActivateFlying()
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end,
off = function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
sender:ActivateWalking()
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end
})
Test the command and make sure you can turn fly on and off.
Speed
If you have a large open world game, then travelling could take quite a while. This time all adds up when you are trying to get to a specific area in your game to test something in a published game. Being able to set the speed of your character could be a useful way to save time.
You will create the command so it can also be applied to any player. It will accept a walkspeed
parameter that will modify the maxWalkSpeed
property of the player
.
-- /speed player walkspeed
CommandParser.AddCommand("speed", function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.MODERATOR) then
local player = CommandParser.GetPlayer(params[2])
if player ~= nil then
player.maxWalkSpeed = tonumber(params[3]) or player.maxWalkSpeed
status.success = true
status.senderMessage = "Player speed set."
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end)
Test the command by entering a speed that is higher than your current walk speed (default is 640
).
Kill
Being able to kill a player can be useful if they are in a bad state where teleporting them won't solve the issue. This can also be useful for testing round end conditions.
By calling the Die
function on a player
, it will kill them. You can also check if params[3]
is a player or all
. If it is all
, then all players on the server excluding the sender
will be killed.
-- /kill all
-- /kill player
CommandParser.AddCommand("kill", function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
local who = CommandParser.ParamIsValid(params[2])
if who ~= nil then
if who == "all" then
for k, player in ipairs(Game.GetPlayers()) do
if player ~= sender then
player:Die()
end
end
status.success = true
status.senderMessage = "All players killed."
else
who = CommandParser.GetPlayer(params[2])
if who ~= nil then
who:Die()
status.success = true
status.senderMessage = "Player killed."
end
end
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end)
Test the command in local multiplayer preview. Try killing one player, then trying kill all players using the all
keyword.
Mute
Being able to mute a player, or all players can be useful if you need to talk to people on the server without being over talked. This command will mute the player in all the channels. As a challenge, you could have it setup to automatically mute people as they join the server. For example, maybe you have a music event in progress, and want to use the in game chat as a way to broadcast the music to the players on the server.
The command will need support for muting all players, and specific players. It would also be nice to have an unmute
version of the command as well.
By looping over the voice channels using the GetChannels
function, you can mute the player in those channels by calling the MutePlayer
function with the player as the argument.
-- /voice mute all
-- /voice mute player
-- /voice unmute all
-- /voice unmute player
CommandParser.AddCommand("voice", {
mute = function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.MODERATOR) then
local who = CommandParser.ParamIsValid(params[3])
if who ~= nil then
if who == "all" then
for k, player in ipairs(Game.GetPlayers()) do
if player ~= sender then
for i, c in pairs(VoiceChat.GetChannels()) do
c:MutePlayer(player)
end
end
end
status.success = true
status.senderMessage = "All players muted."
else
who = CommandParser.GetPlayer(params[3])
if who ~= nil then
for i, c in pairs(VoiceChat.GetChannels()) do
c:MutePlayer(who)
end
status.success = true
status.senderMessage = "Player muted."
end
end
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end,
unmute = function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.MODERATOR) then
local who = CommandParser.ParamIsValid(params[3])
if who ~= nil then
if who == "all" then
for k, player in ipairs(Game.GetPlayers()) do
if player ~= sender then
for i, c in pairs(VoiceChat.GetChannels()) do
c:UnmutePlayer(player)
end
end
end
status.success = true
status.senderMessage = "All players unmuted."
else
who = CommandParser.GetPlayer(params[3])
if who ~= nil then
for i, c in pairs(VoiceChat.GetChannels()) do
c:UnmutePlayer(who)
end
status.success = true
status.senderMessage = "Player unmuted."
end
end
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end
})
This command would need to be tested in published game. You can test it locally to see if it executes correctly.
Grant Reward Points
If you are in the Perks Program, then you will have the ability to grant reward points to players. This could be login based, or granted based on what the player does in game (i.e. finish a mission). Having the option to reward points could be useful.
By using the GrantRewardPoints
function, you can grant reward points to a player. You can also turn this command into an all
command, so that it can be applied to all players on the server.
If a specific player is receiving the reward points, then by setting a receiverMessage
value and receiverPlayer
value, that player will receive a message that they were granted points.
-- /grantrp player amount
-- /grantrp all amount
CommandParser.AddCommand("grantrp", function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
local who = CommandParser.ParamIsValid(params[2])
if who ~= nil then
local amount = tonumber(params[3]) or 250
if who == "all" then
for k, player in ipairs(Game.GetPlayers()) do
player:GrantRewardPoints(amount, "Awarded Points")
end
status.success = true
status.senderMessage = "All players granted reward points."
else
who = CommandParser.GetPlayer(params[2])
if who ~= nil then
who:GrantRewardPoints(amount, "Awarded Points")
status.success = true
status.senderMessage = "Player granted reward points."
status.receiverMessage = "You have been granted " .. tostring(amount) .. " reward points."
status.receiverPlayer = who
end
end
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end)
The command will work even if the player has reached the creators maximum points amount, they just won't receive any more points.
Reset Storage
Sometimes player data can get into a bad state, or even in testing features, it would be nice to have an option to reset the storage data for a player.
This command will accept either a specific player, or reset all players storage who are on the current server instance. This is done by setting the player's data to an empty table, and calling SetPlayerData
.
-- /resetstorage player
-- /resetstorage all
CommandParser.AddCommand("resetstorage", function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
local who = CommandParser.ParamIsValid(params[2])
if who ~= nil then
if who == "all" then
for k, player in ipairs(Game.GetPlayers()) do
if player ~= sender then
Storage.SetPlayerData(player, {})
end
end
status.success = true
status.senderMessage = "All players reset."
else
who = CommandParser.GetPlayer(params[2])
if who ~= nil then
Storage.SetPlayerData(who, {})
status.success = true
status.senderMessage = "Player reset."
status.receiverMessage = "You have been reset."
status.receiverPlayer = who
end
end
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end)
Invisible
A useful moderating command that can be used to watch players, is the option to go invisible to other players in the game. This can be useful to watch how players are playing your game, especially when combined with commands such as fly
.
By setting the isVisible
property of the sender, the sender's character can be hidden to other players on the server.
-- /invisible on
-- /invisible off
CommandParser.AddCommand("invisible", {
on = function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
sender.isVisible = false
end
end,
off = function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
sender.isVisible = true
end
end
})
Test the command to make sure your player's character can go invisible and visible.
Give
The give
command can be used to give items to player. In this example, you will write a command that will allow you to give specific resources to players. If you would like to give perks to players, take a look at the Perks Part 2 Tutorial.
Any resource that can be given to a player needs to have data set. This is so that the give
command can work for a wide range of resources, and so that the command callback can retrieve the data about the resource being given to the player.
Commands can access data from a lookup table. That data is supplied by you by using the AddCommandData
function that accepts 2 arguments.
- The key for this data.
- A table with the data.
For example, if there is resources for coins and gems in your game:
CommandParser.AddCommandData("coins", {
name = "Coins",
resourceKey = "coins",
storageKey = "c"
})
CommandParser.AddCommandData("gems", {
name = "Gems",
resourceKey = "gems",
storageKey = "g"
})
By using the GetCommandData
function and passing in the key. The data will be retrieved for you. This helps with creating just a single command instead of multiple commands for each resource.
-- /give resource player resourcekey amount
CommandParser.AddCommand("give", {
resource = function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.MODERATOR) then
local who = CommandParser.GetPlayer(CommandParser.ParamIsValid(params[3]))
if who ~= nil then
local commandData = CommandParser.GetCommandData(params[4])
if commandData ~= nil then
local playerData = Storage.GetPlayerData(who)
local amount = tonumber(params[5]) or 0
who:AddResource(commandData.resourceKey, amount)
if not playerData[commandData.storageKey] then
playerData[commandData.storageKey] = amount
else
playerData[commandData.storageKey] = playerData[commandData.storageKey] + amount
end
Storage.SetPlayerData(who, playerData)
status.success = true
status.senderMessage = "Resource successfully given."
status.receiverMessage = "You have been gifted " .. tostring(amount) .. " " .. commandData.name .. "."
status.receiverPlayer = who
else
status.senderMessage = "Command data \"" .. item .. "\" does not exist."
end
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end
})
Test the command by giving the player either of the resources setup. In the video below, a script in a client context was created to display the amount of resources the player has in the Event Log when the resource changes.
Help
A useful command that will display a list of the commands in the chat, is a help
command. This command will loop through the main commands that have been registered, and broadcast it to the sender of the command.
The key for each command is inserted into the msg
table. Before it is broadcasted, each entry in the msg
table is concatenated with a new line.
-- /help
CommandParser.AddCommand("help", function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.MODERATOR) then
local msg = { "Commands:" }
for k, c in pairs(CommandParser.commands) do
table.insert(msg, "/" .. k)
end
if #msg > 0 then
Chat.BroadcastMessage(table.concat(msg, "\n"), { players = sender })
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end)
Test the command to make sure all the commands are listed in the chat. If you have a lot of commands, then the message may get cropped if it exceeds the maximum message length of 280 characters.
The Server Commands Script
Here are all the commands that was created above.
Server Commands
local CommandParser = require(script:GetCustomProperty("CommandParser"))
-- /tp toplayer
-- /tp player toplayer
CommandParser.AddCommand("tp", function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.MODERATOR) then
local playerA = CommandParser.GetPlayer(params[2])
local playerB = CommandParser.GetPlayer(params[3])
if playerA ~= nil then
if playerB ~= nil then
playerA:SetWorldPosition(playerB:GetWorldPosition())
playerA:SetWorldRotation(playerB:GetWorldRotation())
else
sender:SetWorldPosition(playerA:GetWorldPosition())
sender:SetWorldRotation(playerA:GetWorldRotation())
end
status.success = true
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end)
-- /kick player
-- /kick all
CommandParser.AddCommand("kick", function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.MODERATOR) then
local who = CommandParser.ParamIsValid(params[2])
if who ~= nil then
if who == "all" then
for k, player in ipairs(Game.GetPlayers()) do
if player ~= sender then
player:TransferToGame("e39f3e/core-world")
end
end
status.success = true
status.senderMessage = "All players kicked."
else
who = CommandParser.GetPlayer(params[2])
if who ~= nil then
who:TransferToGame("e39f3e/core-world")
status.success = true
status.senderMessage = "Player kicked."
end
end
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end)
-- /closeserver
CommandParser.AddCommand("closeserver", function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
Game.StopAcceptingPlayers()
status.success = true
status.senderMessage = "Server closed."
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end)
-- /fly on
-- /fly off
CommandParser.AddCommand("fly", {
on = function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
sender:ActivateFlying()
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end,
off = function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
sender:ActivateWalking()
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end
})
-- /voice mute all
-- /voice mute player
-- /voice unmute all
-- /voice unmute player
CommandParser.AddCommand("voice", {
mute = function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.MODERATOR) then
local who = CommandParser.ParamIsValid(params[3])
if who ~= nil then
if who == "all" then
for k, player in ipairs(Game.GetPlayers()) do
if player ~= sender then
for i, c in pairs(VoiceChat.GetChannels()) do
c:MutePlayer(player)
end
end
end
status.success = true
status.senderMessage = "All players muted."
else
who = CommandParser.GetPlayer(params[3])
if who ~= nil then
for i, c in pairs(VoiceChat.GetChannels()) do
c:MutePlayer(who)
end
status.success = true
status.senderMessage = "Player muted."
end
end
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end,
unmute = function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.MODERATOR) then
local who = CommandParser.ParamIsValid(params[3])
if who ~= nil then
if who == "all" then
for k, player in ipairs(Game.GetPlayers()) do
if player ~= sender then
for i, c in pairs(VoiceChat.GetChannels()) do
c:UnmutePlayer(player)
end
end
end
status.success = true
status.senderMessage = "All players unmuted."
else
who = CommandParser.GetPlayer(params[3])
if who ~= nil then
for i, c in pairs(VoiceChat.GetChannels()) do
c:UnmutePlayer(who)
end
status.success = true
status.senderMessage = "Player unmuted."
end
end
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end
})
-- /speed player walkspeed
CommandParser.AddCommand("speed", function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.MODERATOR) then
local player = CommandParser.GetPlayer(params[2])
if player ~= nil then
player.maxWalkSpeed = tonumber(params[3]) or player.maxWalkSpeed
status.success = true
status.senderMessage = "Player speed set."
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end)
-- /kill all
-- /kill player
CommandParser.AddCommand("kill", function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
local who = CommandParser.ParamIsValid(params[2])
if who ~= nil then
if who == "all" then
for k, player in ipairs(Game.GetPlayers()) do
if player ~= sender then
player:Die()
end
end
status.success = true
status.senderMessage = "All players killed."
else
who = CommandParser.GetPlayer(params[2])
if who ~= nil then
who:Die()
status.success = true
status.senderMessage = "Player killed."
end
end
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end)
CommandParser.AddCommand("grantrp", function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
local who = CommandParser.ParamIsValid(params[2])
if who ~= nil then
local amount = tonumber(params[3]) or 250
if who == "all" then
for k, player in ipairs(Game.GetPlayers()) do
player:GrantRewardPoints(amount, "Awarded Points")
end
status.success = true
status.senderMessage = "All players granted reward points."
else
who = CommandParser.GetPlayer(params[2])
if who ~= nil then
who:GrantRewardPoints(amount, "Awarded Points")
status.success = true
status.senderMessage = "Player granted reward points."
status.receiverMessage = "You have been granted " .. tostring(amount) .. " reward points."
status.receiverPlayer = who
end
end
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end)
CommandParser.AddCommand("invisible", {
on = function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
sender.isVisible = false
end
end,
off = function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
sender.isVisible = true
end
end
})
CommandParser.AddCommand("resetstorage", function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
local who = CommandParser.ParamIsValid(params[2])
if who ~= nil then
if who == "all" then
for k, player in ipairs(Game.GetPlayers()) do
if player ~= sender then
Storage.SetPlayerData(player, {})
end
end
status.success = true
status.senderMessage = "All players reset."
else
who = CommandParser.GetPlayer(params[2])
if who ~= nil then
Storage.SetPlayerData(who, {})
status.success = true
status.senderMessage = "Player reset."
status.receiverMessage = "You have been reset."
status.receiverPlayer = who
end
end
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end)
CommandParser.AddCommandData("coins", {
name = "Coins",
resourceKey = "coins",
storageKey = "c"
})
CommandParser.AddCommandData("gems", {
name = "Gems",
resourceKey = "gems",
storageKey = "g"
})
CommandParser.AddCommand("give", {
resource = function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.MODERATOR) then
local who = CommandParser.GetPlayer(CommandParser.ParamIsValid(params[3]))
if who ~= nil then
local commandData = CommandParser.GetCommandData(params[4])
if commandData ~= nil then
local playerData = Storage.GetPlayerData(who)
local amount = tonumber(params[5]) or 0
who:AddResource(commandData.resourceKey, amount)
if not playerData[commandData.storageKey] then
playerData[commandData.storageKey] = amount
else
playerData[commandData.storageKey] = playerData[commandData.storageKey] + amount
end
Storage.SetPlayerData(who, playerData)
status.success = true
status.senderMessage = "Resource successfully given."
status.receiverMessage = "You have been gifted " .. tostring(amount) .. " " .. commandData.name .. "."
status.receiverPlayer = who
else
status.senderMessage = "Command data \"" .. item .. "\" does not exist."
end
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end
})
CommandParser.AddCommand("help", function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.MODERATOR) then
local msg = { "Commands:" }
for k, c in pairs(CommandParser.commands) do
table.insert(msg, "/" .. k)
end
if #msg > 0 then
Chat.BroadcastMessage(table.concat(msg, "\n"), { players = sender })
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end)
Creating Dungeon Crawler Commands
In this section you will be creating commands that can help with testing the Dungeon Crawler Framework. These commands could easily be adapted to suit your game.
Give
The Dungeon Crawler has 2 main resources the player can earn.
- XP which is used to level up the player so they can equipment higher gear.
- Coins which can be used to purchase better gear.
The give
command will have 2 sub commands to award these resources to the player. Having these 2 commands will allow you to test the weapons, and difficulty of the enemies to see how much damage they are doing to the player.
The benefit of having commands to alter these resources, is that you aren't modifying the Dungeon Crawler code directly, which keeps it clean.
-- /give xp player amount
-- /give coins player amount
CommandParser.AddCommand("give", {
xp = function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
local who = CommandParser.GetPlayer(params[3])
if who ~= nil then
local amount = tonumber(params[4])
if amount > 0 then
CommandParser.AddResource(who, "XP", "XP", amount)
status.success = true
status.senderMessage = "Player given XP."
else
status.senderMessage = CommandParser.error.INVALID_VALUE
end
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end,
coins = function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
local who = CommandParser.GetPlayer(params[3])
if who ~= nil then
local amount = tonumber(params[4])
if amount > 0 then
CommandParser.AddResource(who, "Coins", "Coins", amount)
status.success = true
status.senderMessage = "Player given Coins."
else
status.senderMessage = CommandParser.error.INVALID_VALUE
end
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end
})
By giving yourself XP and Coins, you can test to make sure unlocking and purchasing weapons works correctly.
Reset
Being able to reset your level and coins would also be a good idea to help with testing unlocking and purchasing weapons.
You can set the players resource to 0
to reset it. The Dungeon Crawler is listening for when the player's resources for XP and Coins has changed, so the UI and in world items will react.
-- /reset level player
-- /reset coins player
CommandParser.AddCommand("reset", {
level = function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
local who = CommandParser.GetPlayer(params[3])
if who ~= nil then
CommandParser.SetResource(who, "XP", "XP", 0)
status.success = true
status.senderMessage = "Player level reset."
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end,
coins = function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
local who = CommandParser.GetPlayer(params[3])
if who ~= nil then
CommandParser.SetResource(who, "Coins", "Coins", 0)
status.success = true
status.senderMessage = "Player coins reset."
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end
})
Heal
When fighting the enemies, it would be good to have a heal command so you can test the damage of the enemies to make sure they aren't too difficult to fight based on the player's level.
By applying a negative damage amount, it will heal the player instead of causing damage.
CommandParser.AddCommand("heal", function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
local who = CommandParser.GetPlayer(params[2]) or sender
if who ~= nil then
who:ApplyDamage(Damage.New(-1000))
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end)
Regen Health
Having to constantly type the heal
command can be awkward if you are testing combat mechanics out with the enemies. A better way would be to have a command that can regenerate the health of the player automatically.
This command can be turn on and off, and also apply to any player. A task will be spawned that will run every half a second, and heal all players that are in the regen_players
table. The regen_task
is self cancelling, meaning that it will cancel its self if there are no players in the regen_players
table to heal.
When the off
sub command is executed, it will remove the player from the regen_players
table.
local regen_players = {}
local regen_task = nil
-- /regen on player
-- /regen off player
CommandParser.AddCommand("regen", {
on = function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
local who = CommandParser.GetPlayer(params[3]) or sender
if who ~= nil then
status.success = true
if regen_players[who.id] == nil then
regen_players[who.id] = who
status.senderMessage = "Health regen turned on."
else
status.senderMessage = "Health regen already on."
return
end
if regen_task == nil then
regen_task = Task.Spawn(function()
local count = 0
for id, player in pairs(regen_players) do
if Object.IsValid(player) then
player:ApplyDamage(Damage.New(-1000))
count = count + 1
end
end
if count == 0 then
regen_task:Cancel()
regen_task = nil
regen_players = {}
end
end)
regen_task.repeatCount = -1
regen_task.repeatInterval = .5
end
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end,
off = function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
local who = CommandParser.GetPlayer(params[3]) or sender
if who ~= nil then
status.success = true
if regen_players[who.id] ~= nil then
regen_players[who.id] = nil
status.senderMessage = "Health regen turned off."
else
status.senderMessage = "Health regen already off."
end
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end
})
Kill NPCs
It would be useful to have a command to kill all the currently spawned enemies. This could be used to test enemy drops, or to clear out basic enemies just to get to the final boss quicker for testing.
The Dungeon Crawler uses the NPC AI Kit from Community Content for the enemies. These get spawned in the Hierarchy root, and each enemy has NPC in the name. What you will need to do is get all the children in the Hierarchy, see which of those children contain NPC in the name, and then find the NPCAttackServer script.
The NPCAttackServer script exposes a function called ApplyDamage
that accepts a Damage
object, and player. You can access the global ApplyDamage
function by accessing the context
of the script. In doing so, you can apply enough damage to the enemy to kill them.
CommandParser.AddCommand("killnpcs", function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
local objs = World.GetRootObject():GetChildren()
local count = 0
for i, c in ipairs(objs) do
if c.name:find("NPC") then
local attackServer = c:FindChildByName("NPCAttackServer")
if attackServer ~= nil then
attackServer.context.ApplyDamage(Damage.New(50000), sender)
count = count + 1
end
end
end
status.success = true
status.senderMessage = "NPC's killed " .. tostring(count) .. "."
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end)
Server Commands Script
Server Commands
local CommandParser = require(script:GetCustomProperty("CommandParser"))
-- /give xp player amount
-- /give coins player amount
CommandParser.AddCommand("give", {
xp = function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
local who = CommandParser.GetPlayer(params[3])
if who ~= nil then
local amount = tonumber(params[4])
if amount > 0 then
CommandParser.AddResource(who, "XP", "XP", amount)
status.success = true
status.senderMessage = "Player given XP."
else
status.senderMessage = CommandParser.error.INVALID_VALUE
end
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end,
coins = function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
local who = CommandParser.GetPlayer(params[3])
if who ~= nil then
local amount = tonumber(params[4])
if amount > 0 then
CommandParser.AddResource(who, "Coins", "Coins", amount)
status.success = true
status.senderMessage = "Player given Coins."
else
status.senderMessage = CommandParser.error.INVALID_VALUE
end
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end
})
-- /reset level player
-- /reset coins player
CommandParser.AddCommand("reset", {
level = function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
local who = CommandParser.GetPlayer(params[3])
if who ~= nil then
CommandParser.SetResource(who, "XP", "XP", 0)
status.success = true
status.senderMessage = "Player level reset."
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end,
coins = function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
local who = CommandParser.GetPlayer(params[3])
if who ~= nil then
CommandParser.SetResource(who, "Coins", "Coins", 0)
status.success = true
status.senderMessage = "Player coins reset."
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end
})
-- /heal player
CommandParser.AddCommand("heal", function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
local who = CommandParser.GetPlayer(params[2]) or sender
if who ~= nil then
who:ApplyDamage(Damage.New(-1000))
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end)
local regen_players = {}
local regen_task = nil
-- /regen on player
-- /regen off player
CommandParser.AddCommand("regen", {
on = function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
local who = CommandParser.GetPlayer(params[3]) or sender
if who ~= nil then
status.success = true
if regen_players[who.id] == nil then
regen_players[who.id] = who
status.senderMessage = "Health regen turned on."
else
status.senderMessage = "Health regen already on."
return
end
if regen_task == nil then
regen_task = Task.Spawn(function()
local count = 0
for id, player in pairs(regen_players) do
if Object.IsValid(player) then
player:ApplyDamage(Damage.New(-1000))
count = count + 1
end
end
if count == 0 then
regen_task:Cancel()
regen_task = nil
regen_players = {}
end
end)
regen_task.repeatCount = -1
regen_task.repeatInterval = .5
end
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end,
off = function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
local who = CommandParser.GetPlayer(params[3]) or sender
if who ~= nil then
status.success = true
if regen_players[who.id] ~= nil then
regen_players[who.id] = nil
status.senderMessage = "Health regen turned off."
else
status.senderMessage = "Health regen already off."
end
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end
})
-- /killnpcs
CommandParser.AddCommand("killnpcs", function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
local objs = World.GetRootObject():GetChildren()
local count = 0
for i, c in ipairs(objs) do
if c.name:find("NPC") then
local attackServer = c:FindChildByName("NPCAttackServer")
if attackServer ~= nil then
attackServer.context.ApplyDamage(Damage.New(50000), sender)
count = count + 1
end
end
end
status.success = true
status.senderMessage = "NPC's killed " .. tostring(count) .. "."
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end)
Creating Capture and Hold Commands
In this section you will be creating commands that can help with testing the Capture and Hold Framework. Since this is a team based framework, having commands that can help with team testing can be helpful.
Set Team
Being able to change team will help you test things like the team scoring, making sure that the capture points can be captured by each team.
By setting the team
property for the player to either 1
or 2
, will switch that player to that team.
-- /setteam player team
CommandParser.AddCommand("setteam", function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
local player = CommandParser.GetPlayer(params[2])
if player ~= nil then
player.team = tonumber(params[3]) or player.team
status.success = true
status.senderMessage = "Player team set."
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end)
Set Team Score
Being able to set the team score will help you test things such as victory screens, making sure the correct team wins the round.
By using the SetTeamScore
function, you can enter a team ID and a score, and the game will update the score for that team.
-- /setscore team score
CommandParser.AddCommand("setscore", function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
Game.SetTeamScore(tonumber(params[2]), tonumber(params[3]))
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end)
End Round
Being able to end a round quickly can help test ending round conditions, and to make sure that game correctly starts a new round. Combined with the setscore
command, this can be a fast way to test various win, lose conditions.
The Capture and Hold framework uses the Basic Game State component. To be able to correctly end a round, you need to use the API. Instead of modifying the framework code, you can simply require the APIBasicGameState script so you can use it in the command.
The command will also need to correctly broadcast the winning team. This can be done by checking the score of each team. If the score is the same, then a tie is declared.
local ABGS = require(script:GetCustomProperty("APIBasicGameState"))
-- /endround
CommandParser.AddCommand("endround", function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
if Game.GetTeamScore(1) > Game.GetTeamScore(2) then
Events.Broadcast("TeamVictory", 1)
elseif Game.GetTeamScore(2) > Game.GetTeamScore(1) then
Events.Broadcast("TeamVictory", 2)
else
Events.Broadcast("TieVictory")
end
ABGS.SetGameState(ABGS.GAME_STATE_ROUND_END)
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end)
Server Commands Script
Server Commands
local CommandParser = require(script:GetCustomProperty("CommandParser"))
local ABGS = require(script:GetCustomProperty("APIBasicGameState"))
-- /setteam player team
CommandParser.AddCommand("setteam", function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
local player = CommandParser.GetPlayer(params[2])
if player ~= nil then
player.team = tonumber(params[3]) or player.team
status.success = true
status.senderMessage = "Player team set."
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end)
-- /setscore team score
CommandParser.AddCommand("setscore", function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
Game.SetTeamScore(tonumber(params[2]), tonumber(params[3]))
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end)
-- /endround
CommandParser.AddCommand("endround", function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
if Game.GetTeamScore(1) > Game.GetTeamScore(2) then
Events.Broadcast("TeamVictory", 1)
elseif Game.GetTeamScore(2) > Game.GetTeamScore(1) then
Events.Broadcast("TeamVictory", 2)
else
Events.Broadcast("TieVictory")
end
ABGS.SetGameState(ABGS.GAME_STATE_ROUND_END)
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end)
Fun Commands
In this section you will create some fun commands that you can use on yourself or other players for a bit of fun.
Push
This command will allow you to push players around. If you see them on the edge of a platform, give them a friendly nudge.
By getting setting the player's velocity combined with a direction, it can be easy to launch a player in a certain direction.
-- /push player direction amount
CommandParser.AddCommand("push", function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
local who = CommandParser.GetPlayer(CommandParser.ParamIsValid(params[2]))
if who ~= nil then
local direction = CommandParser.ParamIsValid(params[3])
local currentVel = who:GetVelocity()
local dirVector = who:GetWorldTransform():GetUpVector()
local amount = tonumber(params[3]) or 2000
if direction == "left" then
dirVector = -who:GetWorldTransform():GetRightVector()
elseif direction == "right" then
dirVector = who:GetWorldTransform():GetRightVector()
elseif direction == "forward" then
dirVector = who:GetWorldTransform():GetForwardVector()
elseif direction == "back" then
dirVector = -who:GetWorldTransform():GetForwardVector()
end
who:SetVelocity(currentVel + dirVector * amount)
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end)
Ragdoll
Ragdoll physics can be a lot of fun. This command will enable the ragdoll physics for a few sockets.
By calling the EnableRagdoll
function on the player, you can specify a socket and weight.
-- /ragdoll on player
-- /ragdoll off player
CommandParser.AddCommand("ragdoll", {
on = function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
local who = CommandParser.GetPlayer(CommandParser.ParamIsValid(params[3]))
if who ~= nil then
who:EnableRagdoll("lower_spine", .5)
who:EnableRagdoll("right_shoulder", .5)
who:EnableRagdoll("left_shoulder", .5)
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end,
off = function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
local who = CommandParser.GetPlayer(CommandParser.ParamIsValid(params[3]))
if who ~= nil then
who:DisableRagdoll("lower_spine")
who:DisableRagdoll("right_shoulder")
who:DisableRagdoll("left_shoulder")
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end
})
Jump Count
This command will allow you to set the amount of times a player can jump before needing to touch the ground.
By setting the maxJumpCount
property for the player, you can control how many times they can jump.
-- /jumpcount player amount
CommandParser.AddCommand("jumpcount", function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
local who = CommandParser.GetPlayer(CommandParser.ParamIsValid(params[2]))
if who ~= nil then
who.maxJumpCount = tonumber(params[3]) or 1
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end)
Jump Height
This command will allow you to set the height of a jump for a player.
By setting the jumpVelocity
property for the player, you can control how high their jump will go.
-- /jumpheight player height
CommandParser.AddCommand("jumpheight", function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
local who = CommandParser.GetPlayer(CommandParser.ParamIsValid(params[2]))
if who ~= nil then
who.jumpVelocity = tonumber(params[3]) or 900
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end)
Server Commands Script
Server Commands
-- /push player direction amount
CommandParser.AddCommand("push", function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
local who = CommandParser.GetPlayer(CommandParser.ParamIsValid(params[2]))
if who ~= nil then
local direction = CommandParser.ParamIsValid(params[3])
local currentVel = who:GetVelocity()
local dirVector = who:GetWorldTransform():GetUpVector()
local amount = tonumber(params[3]) or 2000
if direction == "left" then
dirVector = -who:GetWorldTransform():GetRightVector()
elseif direction == "right" then
dirVector = who:GetWorldTransform():GetRightVector()
elseif direction == "forward" then
dirVector = who:GetWorldTransform():GetForwardVector()
elseif direction == "back" then
dirVector = -who:GetWorldTransform():GetForwardVector()
end
who:SetVelocity(currentVel + dirVector * amount)
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end)
-- /ragdoll on player
CommandParser.AddCommand("ragdoll", {
on = function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
local who = CommandParser.GetPlayer(CommandParser.ParamIsValid(params[3]))
if who ~= nil then
who:EnableRagdoll("lower_spine", .5)
who:EnableRagdoll("right_shoulder", .5)
who:EnableRagdoll("left_shoulder", .5)
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end,
off = function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
local who = CommandParser.GetPlayer(CommandParser.ParamIsValid(params[3]))
if who ~= nil then
who:DisableRagdoll("lower_spine")
who:DisableRagdoll("right_shoulder")
who:DisableRagdoll("left_shoulder")
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end
})
-- /jumpcount player amount
CommandParser.AddCommand("jumpcount", function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
local who = CommandParser.GetPlayer(CommandParser.ParamIsValid(params[2]))
if who ~= nil then
who.maxJumpCount = tonumber(params[3]) or 1
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end)
-- /jumpheight player height
CommandParser.AddCommand("jumpheight", function(sender, params, status)
if CommandParser.HasPermission(sender, CommandParser.permissions.ADMIN) then
local who = CommandParser.GetPlayer(CommandParser.ParamIsValid(params[2]))
if who ~= nil then
who.jumpVelocity = tonumber(params[3]) or 900
else
status.senderMessage = CommandParser.error.INVALID_PLAYER
end
else
status.senderMessage = CommandParser.error.NO_PERMISSION
end
end)
Summary
Having commands in your game can help speed up iteration time when it comes to testing features. Not only does it help with local testing, but also for your published game. It can help reduce the amount of time it takes to republish a new version when tracking down bugs, as you will have the tools to debug on the fly.
Commands also are a good way to help moderate your game. Some of the general commands created earlier in the tutorial can be improved on to help remove nuisance players. By having a permission system, you can promote trusted players to help moderate your game across different timezones, which will create a better experience for your players.
Learn More
Chat Hooks | Chat API | Perks Part 2 | Teams | Player API | Game API | Damage API | Storage API