A sort of follow up on my first guide which I recommend reading as well as it teaches you how to make your code coherent
When people are asked “What is Future Proofing?”, they’ll most likely be confused as they may have never heard of that word before or never even thought about it before, or may even give you a correct definition but don’t show it when you see their code. With that out of that way, you may be asking yourself “Embat what are you even going on about?”
Future Proofing is a topic in programming that describe the process of making your code “loose” in order to make adding future code/features easy as pie without breaking existing functionality that the code already has. Now with a definition you may probably not understand immediately, so let’s go into further detail with some examples
Say you want to make it so you and other specific users have 150 MaxHealth instead of 100 on spawn. You say:
“Simple enough”
And in the end you have this
local players = game:GetService("Players")
players.PlayerAdded:Connect(function(plr)
plr.CharacterAdded:Connect(function(char)
local human = char:WaitForChild("Humanoid")
if char.Name == "EmbatTheHybrid" or char.Name == "StrongBigeMan9" then
human.MaxHealth = 150
human.Health = 150
end
end)
end)
It does what you wanted, but there’s 2 issues
Firstly, if anyone does this, don’t try to do something for a specific player by checking their Name
, always use their UserId
. It may be obvious now, but there may be others who still use the old method. The reason this is bad is what if me or StrongBigeMan9 change our usernames? The code wont work for either of us anymore, so we’d have to update it with our new name, which is time consuming than if you used UserId
Secondly, another issue may stem in the future where you may want to give another player this benefit, seems simple enough, just add another condition into the if statement. The issue is the statement will look like this by the time you add 5 players
local players = game:GetService("Players")
players.PlayerAdded:Connect(function(plr)
plr.CharacterAdded:Connect(function(char)
local human = char:WaitForChild("Humanoid")
if char.Name == "EmbatTheHybrid" or char.Name == "StrongBigeMan9" or char.Name == "ROBLOX" or char.Name == "Shedletsky" or char.Name == "CrazyBlox" then
human.MaxHealth = 150
human.Health = 150
end
end)
end)
This is not good practice as all this does is impact readability since now we have a very long if statement that’ll get even longer once we add even more players
“So how do I make it better?”
It’s simple. First we use UserId
instead of the name to avoid conflicts in the future, and we put all the Ids in a table outside of the event and check if the player’s UserId is in that table, indicating they’re one of the special players we want to gie an advantage to
local players = game:GetService("Players")
local playerIds = {
674847948,
638789589,
1,
684497890,
56746878
}
players.PlayerAdded:Connect(function(plr)
plr.CharacterAdded:Connect(function(char)
local human = char:WaitForChild("Humanoid")
if table.find(playerIds, plr.UserId) then
human.MaxHealth = 150
human.Health = 150
end
end)
end)
With a simple change, we have significantly improved the readability of our script, and also made our code simpler to add onto since if we want to add another player to earn this bonus, we just add a new id into playerIds
, effectively Future Proofing it
Let’s go back to the example of giving players a health benefit, what if you decide to give yourself and a friend of yours 200 hp but the others get 150?
“Can’t I just make 2 tables for that?”
local players = game:GetService("Players")
local playerIds200 = {
674847948,
638789589
}
local playerIds150 = {
1,
684497890,
56746878
}
players.PlayerAdded:Connect(function(plr)
plr.CharacterAdded:Connect(function(char)
local human = char:WaitForChild("Humanoid")
if table.find(playerIds200, plr.UserId) then
human.MaxHealth = 200
human.Health = 200
elseif table.find(playerIds150, plr.UserId) then
human.MaxHealth = 150
human.Health = 150
end
end)
end)
This will work as well, but it complicates it more than we need it to be.
“So if this is not the best method, how do I do this?”
A simple way of doing this is with a dictionary that contains the UserId as a key, and the health we want to give them as the value
local players = game:GetService("Players")
local playerHealthIds = {
[674847948] = 200,
[638789589] = 200,
[1] = 150,
[684497890] = 150,
[56746878] = 150
}
players.PlayerAdded:Connect(function(plr)
local idHealth = playerHealthIds[plr.UserId]
if not idHealth then
return
end
plr.CharacterAdded:Connect(function(char)
local human = char:WaitForChild("Humanoid")
human.MaxHealth = idHealth
human.Health = human.MaxHealth
end)
end)
This will do exactly as the previous code, but is even simpler since we don’t need to specify numbers after the if statement, they’re already there in the dictionary. This also has another Future Proofing benefit of being very easy to add another id to this code as we can just add another entry in the dictionary and is extremely easy to change the health one will get by changing their entry’s value.
This works because if it doesn’t find the UserId in the dictionary, it will return nil
, which won’t run the code in the if statement if it is, if it isn’t, then it will run it
Now I want to make it so we each get a tool except ROBLOX, do I just make another dictionary and change my code around?
You could, but there’s a better way to do that by setting the Value as a table with the contents you want to give to that player, which will require changing up the dictionary a bit, but in the end, you’d have something like this
local players = game:GetService("Players")
local playerIds = {
[674847948] = {Health = 200, ToolName = "GravityCoil"},
[638789589] = {Health = 200, ToolName = "GravityCoil"},
[1] = {Health = 150},
[684497890] = {Health = 150, ToolName = "Sword"},
[56746878] = {Health = 150, ToolName = "SpeedCoil"}
}
players.PlayerAdded:Connect(function(plr)
local idtable = playerIds[plr.UserId]
if not idtable then
return
end
local toolname = idtable["ToolName"]
if toolname then
local tool = game.ServerStorage.Tools[toolname]
tool:Clone().Parent = plr.Backpack
tool:Clone().Parent = plr.StarterGear
end
local health = idtable["Health"]
if health then
plr.CharacterAdded:Connect(function(char)
local human = char:WaitForChild("Humanoid")
human.MaxHealth = health
human.Health = human.MaxHealth
end)
end
end)
But wait, won’t it error since ROBLOX doesn’t have ToolName in their table?
It won’t since it checks first if something exists there and if it doesn’t, then it wont try to give a tool, meaning nothing will go wrong unless one of the values in the dictionary is not a table, in that case it will error, OR if you don’t have a tool with that name in the folder, which is probably unlikely since you’d be sure to have tools with those names in the folder
And this also has another benefit since it will only connect the event if they are in the table! Improving it significantly depending on the player amount to reduce the amount of unneeded connections, but if you need to do something for everyone regarldess if they’re in the list or not, then just put the CharacterAdded event outside of the check and just check if idtable
for the userid exists.
With this you now should be able to understand how and when you should Future Proof your code. If you’re still confused on when you should, just think to yourself
If I ever have to add a new condition to this code, would it be difficult and would it affect readability?
“add a new condition” meaning adding something that will cause something to happen, like adding a new UserId like how I did in this example.
If you think about that question and assess the methods of adding a new condition and you answer “Difficult” or “Affects readability”, then it’s a clear indication you need to loosen your code a bit for that situation where you may want to add something in your code in the future to help future you out
Tip: Use :GetService()
when trying to get a Service rather than indexing it, such as using game:GetService("Players")
rather than game.Players
so it can be more consistent with obtaining other Services and will help in the event that there’s something else called Players
, which would error
Thank you for reading my second guide and please reply if you find anything you think it’s wrong so I could fix it