How can I save if a player owns a trail or not

Hey, I am making a trail system, and I want to be able to save if a player has a trail or not. I don’t know how I would do this. I cant use the MarketPlaceService since this isn’t a gamepass. I thought of simply adding a folder into a player with a bunch of Bool Values with a bool value named [trailname] and the value being true if they have it. I thought this would be too much coding though for something simple. Thank you for your time.

1 Like

Whenever a player purchases a trail → add the name of the trail to a table (preferably have all the players datastore under one dictionary/table) → when the player attempts to equip a trail → check their PlayersData.OwnedTrails (this is an example) table and see if the trail they are trying to equip exist!

I wrote some pseudocode to give you a visual example:

local ZetsuData = { -- Example of player data table 
	-- Random values below to give u a better picture
	Level = 1;
	XP = 240;
	
	Pets = {"Rainbow pet", "Water Dog"};
	
	-- Trails
	Trails = {"Flame Trail"}; -- Example of trails the player owners
};


if table.find(ZetsuData.Trails, "Flame Trail") then 	 -- Exist so give them the trail
	print("Player has flame trail... Giving it...")
end;


if table.find(ZetsuData.Trails, "Poop Trail") then 	 -- Does NOT exist so it won't run!
	print("This won't print cause they don't have the poop trail :(... Do nothing...");
else -- this mean's we didn't find it
	warn("Player does not own the Poop trail");
end;


function Save(PlayerData)
	-- Your datastore saving method here
	print("Saving players data", PlayerData)
end;

function Load()
	-- Your datastore loading method here
	print("Got player data.. Loading..")	
end

-- If the player leaves then just save the table
Save(ZetsuData);

-- and if player joins just load the data as normal
Load();

2 Likes

ok i have a few questions:

  • how would i make the template for whenever a player first joins
  • how would i add to the table
  • would there be a way to update the table if there was a new feature added without wiping all of the player’s existing data

im not kidding when i say my head is hurting thinking about this

1 Like

I wrote a bit more pseudocode so you can understand it a little better, but basically you really only want to save/load the player’s data to the actual datastore whenever they join or leave (and maybe occasionally like every 2 - 3 mins just incase server crashes). So you might ask “well how do I save or edit their data in real time?”. Good question! Its actually highly recommended that you store all players data in a table → any time you need to edit or access that data → you reference that table instead of making a datastore request → you then would save that data table when the player leaves and remove the players data from said table!

Note that this is just pseudocode. It isn’t tested and may not use best practices (I pointed some of them out so you can add them in)

local DatastoreService = game:GetService("DataStoreService");
local MyGamesDatastore = DatastoreService:GetDataStore("AllPlayersData"); -- This basically holds all the players data, if u change this. Everything will reset (unless u revert it back to the original name)

local PlayerData = {} -- This will hold everyones data that is currently in the server. This way u dont have to make so many datastore request!

-- Default --
local DefaultTable = { -- The default stats every player gets
	Level = 1;
	XP = 0;
	
	Weapon = {"Default Sword"};
	Trails = {};	
};

-- An example load function
function LoadData(Player)
	local Success, Data = pcall(function() -- always wrap datastore request in pcall cause they can error from roblox's end!
		return MyGamesDatastore:GetAsync(Player.UserId);
	end);

	if Success and Data then 
		-- Success is what pcall returns if the function given executed with no errors. Its either true or false
		-- Data is the what our :GetAsync call returned. If its nil then the player is new! Otherwise just load normally
		print(Player.Name.." has data loading..");
		PlayerData[Player.UserId] = Data; -- We now add the players data using their userId (as a reference) to the PlayerData table!
	elseif Success and not Data then
		PlayerData[Player.UserId] = DefaultTable; -- Since the player has no data (first time playing), set data to default
	end;
	
	-- Please note that sometimes the datastore call might error so don't just set the table to default instantly. Always check to make sure it was successful and if not just re-try!
	-- Otherwise I would just kick the player from the game so their data is corrupted
end;

-- An example of save function
function SaveData(Player)
	local Success, Error = pcall(function() -- again always use pcalls for datastore request!
		MyGamesDatastore:SetAsync(Player.UserId, PlayerData[Player.UserId]) -- Get the players data and saves it
	end);
	
	if not Success then
		print("Warning: Could not save players data. You should try to save the data again!", Error);
	else -- If it was successful 
		PlayerData[Player.UserId] = nil; -- remove the players data from the session to avoid memory leaks!
	end;
	
	-- If it errors for whatever reason. Try and save the players data again!
end;

-- Example of editting/adding stuff
function GiveNewTrail(Player, TrailName)
	if PlayerData[Player.UserId] then -- Means the players data exist in the table
		table.insert(PlayerData[Player.UserId].Trails, TrailName);
		print(Player.Name.." has unlocked the "..TrailName.." trail!");
	end;
end;

GiveNewTrail(Ze_tsu, "Flame Trail");

-- Another example of changing something:
PlayerData[Player.UserId].Level = 2;
PlayerData[Player.UserId].Mana = 4; -- You can directly set a new value (that wasn't in default) 

print(PlayerData[Player.UserId].Mana);

-- Note that I recommend that when the player joins AND their data loads -> you loop over the default table
-- and add any new values or features that are missing from the players current data and simple just add them in like above


Hope this makes things more clear!

3 Likes

my view on DataStoreService is forever going to me changed; thank you somuch

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