I am trying to make an RPG and I want to have boss fights as a requirement to progress. I don’t want to use a badge to detect if the player has defeated a boss, because I want a player to be able to defeat a boss multiple times in case if I add some rare loot.
I was thinking of doing something with Boolean Values that are named after each boss that become enabled for the player when they beat them for the first time, but I don’t know how I’d be able to save that so they can continue off where they were before.
I was thinking I could put the Boolean Values in StarterPlayerScripts, and then use datastores or something like that, but I don’t know how I’d do it. I don’t even know if this way I am doing is too complex.
I think that’s a simple way to track boss fights. Using boolean value instances seems a little extra, you could just have a ModuleScript that stores the values and handles the datastore at the same time.
I’d love to write a quick example for you, but I genuinely can’t restrain myself from throwing in type checking (which would easily overcomplicate the entire thing for someone who doesn’t use the type engine)
If you want, I can still try and keep it as simple as possible though.
-- ModuleScript somewhere in ServerScriptService
local Players = game:GetService("Players")
local HTTPService = game:GetService("HTTPService") -- For converting data to strings and back
local DSS = game:GetService("DataStoreService")
local BossTrackerStore = DSS:GetDataStore("BossTracker")
local bossTracker = {}
type playerData = {
boss1 : boolean,
boss2 : boolean,
boss3 : boolean
}
bossTracker.Data = {} :: {[number]: playerData} -- Stores the table described above for each userId
-- Load data when player joins
Players.PlayerAdded:Connect(function(player)
-- Create default data
local newData : playerData = {
boss1 = false,
boss2 = false,
boss3 = false
}
-- Try to load data from the datastore
local success, storeData = pcall(function()
return BossTrackerStore:GetAsync(player.UserId)
end)
-- If failed, assign default data
if (not success) or (not storeData) then
print(success, storeData)
bossTracker.Data[player.UserId] = newData
end
-- If data is successfully decoded, assign that data
storeData = HTTPService:JSONDecode(storeData) :: playerData
if storeData then
bossTracker.Data[player.UserId] = storeData
end
end)
-- Save data when player leaves
Players.PlayerRemoving:Connect(function(player)
local currentData = bossTracker.Data[player.UserId] -- Get the data currently in the table
local encoded = HTTPService:JSONEncode(currentData) -- Encode into a string to store in the datastore
local success, err = pcall(function()
BossTrackerStore:SetAsync(player.UserId,encoded)
end)
if not success then print(err) end -- Print the error if it didn't succeed
end)
return bossTracker
-- Some other server-side script
local BossTracker = require(game.ServerScriptService.BossTracker) -- Get the ModuleScript
...
...
local function setBoss1Defeat(player)
BossTracker.Data[player.UserId].boss1 = true -- Set the value of boss1 for the given player to true
end
local function setBoss2Defeat(player)
BossTracker.Data[player.UserId].boss2 = true
end
I’m not exactly experienced with datastores (had to take a look at the documentation) so there might be some hiccups, but this code should work. I also tried to comment it as best as I could to help you understand what’s going on.
If there’s anything else, let me know.
I think I can understand it, it uses booleans to track 3 bosses so far and uses datastores to check if they are completed or not.
Do you know how I’d be able to set these booleans to true when the player beats a boss? The bosses are NPCs with broken AI and buffed health, for context.
And to check if a player has beaten a boss, do I do DSS:GetDataStore(“BossTracker”) (in a different script, in lets say a door), and check if, for example, boss1 = true then the door opens?
That would work, yes, but you don’t have to necessarily call that function, you can just directly do BossTracker.Data[script.Parent.creator.Value.UserId].boss1 = true
It is in Server Script Service. It does not work when I try to use GetService instead. It gives me multiple errors stating “Requested Module was requested recursively”
That error shows when the module you require() also has a require() to a script that (at some point) has a require() back to that module. I don’t know how all of your code looks so I can’t find it for you, you’ll have to find the problem line yourself.