Advertisement
crusaderevecorp

Untitled

Mar 15th, 2025
5
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.03 KB | None | 0 0
  1. local ProfileService = require(game.ServerScriptService.ProfileService)
  2.  
  3. -----------------------------------------------------------
  4. -- DataStore Configuration
  5. -----------------------------------------------------------
  6. local DataStoreName = "PlayerData_1" -- Change this name to reset all data
  7.  
  8. -- Default data template for new players.
  9. -- If a player joins for the first time, their data will be initialized using these values.
  10. local DataTemplate = {
  11. Coins = 0, -- Integer: Total coins the player has
  12. Loot = {}, -- Dictionary: key = loot name, value = quantity
  13. Weapons = {"Bow"}, -- Array: List of weapon names the player owns (default: "Bow")
  14. Kills = 0, -- Integer: Total number of kills
  15. Equipped_Weapon = "Bow" -- String: The weapon currently equipped (default: "Bow")
  16. }
  17.  
  18. -----------------------------------------------------------
  19. -- Global Variables
  20. -----------------------------------------------------------
  21. local Profiles = {} -- Table to store each player's loaded profile during gameplay
  22.  
  23. -- Create the ProfileStore using ProfileService.
  24. -- This connects to the DataStore using the DataTemplate.
  25. local ProfileStore = ProfileService.GetProfileStore(DataStoreName, DataTemplate)
  26.  
  27. -----------------------------------------------------------
  28. -- Remote Setup for Live Data Updates
  29. -----------------------------------------------------------
  30. local ReplicatedStorage = game:GetService("ReplicatedStorage")
  31. -- Get (or create) the Remotes folder in ReplicatedStorage.
  32. local Remotes = ReplicatedStorage:FindFirstChild("Remotes") or Instance.new("Folder")
  33. Remotes.Name = "Remotes"
  34. Remotes.Parent = ReplicatedStorage
  35.  
  36. -- RemoteEvent to push live data updates to the client.
  37. local UpdateEvent = Remotes:FindFirstChild("UpdatePlayerData") or Instance.new("RemoteEvent")
  38. UpdateEvent.Name = "UpdatePlayerData"
  39. UpdateEvent.Parent = Remotes
  40.  
  41. -- RemoteFunction to allow clients to fetch their data on startup.
  42. local GetDataFunction = Remotes:FindFirstChild("GetPlayerData") or Instance.new("RemoteFunction")
  43. GetDataFunction.Name = "GetPlayerData"
  44. GetDataFunction.Parent = Remotes
  45.  
  46. -----------------------------------------------------------
  47. -- DataManager Table
  48. -----------------------------------------------------------
  49. local DataManager = {}
  50.  
  51. -----------------------------------------------------------
  52. -- Function: DataManager.SendUpdate
  53. -- Description: Sends the current profile data to the specified player's client.
  54. -- Parameters: player (Player) – the player whose data to update.
  55. -----------------------------------------------------------
  56. function DataManager.SendUpdate(player)
  57. local profile = Profiles[player]
  58. if profile then
  59. -- Fire the remote event with the player's current data table.
  60. UpdateEvent:FireClient(player, profile.Data)
  61. end
  62. end
  63.  
  64. -----------------------------------------------------------
  65. -- Function: DataManager.LoadData
  66. -- Description: Loads a player's data using ProfileService when they join.
  67. -- If the player has no previous data, it initializes with DataTemplate.
  68. -- It also sets up a listener to kick the player if the profile is released.
  69. -- Finally, if the player is still in-game, it stores their profile and sends an initial update.
  70. -----------------------------------------------------------
  71. function DataManager.LoadData(player)
  72. -- Attempt to load the player's profile from the DataStore using their UserId.
  73. local profile = ProfileStore:LoadProfileAsync("Player_" .. player.UserId)
  74.  
  75. if profile then
  76. -- Link the profile to the player's UserId.
  77. profile:AddUserId(player.UserId)
  78. -- Reconcile the profile so any missing fields are filled using DataTemplate.
  79. profile:Reconcile()
  80. -- Listen for profile release (e.g. data error) and kick the player if it happens.
  81. profile:ListenToRelease(function()
  82. Profiles[player] = nil
  83. player:Kick("Data Error: Please rejoin!")
  84. end)
  85.  
  86. -- Ensure every field defined in DataTemplate exists in profile.Data.
  87. for key, defaultValue in pairs(DataTemplate) do
  88. if profile.Data[key] == nil then
  89. profile.Data[key] = defaultValue
  90. end
  91. end
  92.  
  93. --print("Data loaded for", player.Name, profile.Data)
  94.  
  95. -- Only store the profile if the player is still in the game.
  96. if player:IsDescendantOf(game.Players) then
  97. Profiles[player] = profile
  98. -- Send the initial data update to the player's client.
  99. DataManager.SendUpdate(player)
  100.  
  101. -- Immediately equip the weapon if the player's character already exists.
  102. if player.Character then
  103. -- Wait a short moment to ensure the Backpack is ready.
  104. local backpack = player:FindFirstChild("Backpack") or player:WaitForChild("Backpack")
  105. task.wait(0.5)
  106. DataManager.EquipWeapon(player, profile.Data.Equipped_Weapon)
  107. end
  108.  
  109. -- Also listen for CharacterAdded to equip weapon on respawn.
  110. player.CharacterAdded:Connect(function(character)
  111. local backpack = player:FindFirstChild("Backpack") or player:WaitForChild("Backpack")
  112. task.wait(0.5) -- Small delay for smooth loading
  113. DataManager.EquipWeapon(player, profile.Data.Equipped_Weapon)
  114. end)
  115. else
  116. profile:Release()
  117. end
  118. else
  119. -- If profile fails to load, kick the player.
  120. player:Kick("Data failed to load. Try rejoining.")
  121. end
  122. end
  123.  
  124. -----------------------------------------------------------
  125. -- Function: DataManager.EquipWeapon
  126. -- Description: Equips a weapon for the player by cloning the weapon tool from ReplicatedStorage.
  127. -- It removes any existing weapon from the player's Backpack, then equips the new weapon.
  128. -- Also updates the player's profile with the newly equipped weapon and sends a UI update.
  129. -- Parameters:
  130. -- player (Player): The player to equip the weapon.
  131. -- weaponName (string): The name of the weapon to equip.
  132. -----------------------------------------------------------
  133. function DataManager.EquipWeapon(player, weaponName)
  134. -- Get the Weapons folder from ReplicatedStorage.
  135. local Weapons = ReplicatedStorage:FindFirstChild("Weapons")
  136. local profile = Profiles[player]
  137. if not Weapons then
  138. warn("Weapons folder missing in ReplicatedStorage!")
  139. return
  140. end
  141.  
  142. -- Find the weapon tool by name.
  143. local clonedWeapon = Weapons:FindFirstChild(weaponName)
  144. -- Wait for the player's Backpack.
  145. local Backpack = player:WaitForChild("Backpack")
  146. local StarterGear = player:WaitForChild("StarterGear")
  147. if clonedWeapon and Backpack then
  148. -- Remove any existing weapon tools from the Backpack.
  149. for _, tool in ipairs(Backpack:GetChildren()) do
  150. if tool:IsA("Tool") then
  151. tool:Destroy()
  152. end
  153. end
  154.  
  155. -- Also clear StarterGear to ensure consistency.
  156. for _, tool in ipairs(StarterGear:GetChildren()) do
  157. if tool:IsA("Tool") then
  158. tool:Destroy()
  159. end
  160. end
  161.  
  162. -- Clone the weapon tool and parent it to the Backpack.
  163. local newWeapon = clonedWeapon:Clone()
  164. newWeapon.Parent = Backpack
  165.  
  166. -- Clone for StarterGear as well.
  167. local starterGearWeapon = clonedWeapon:Clone()
  168. starterGearWeapon.Parent = StarterGear
  169.  
  170. -- Update the player's profile with the newly equipped weapon.
  171. profile.Data.Equipped_Weapon = weaponName
  172.  
  173. -- Send a live update to the client.
  174. DataManager.SendUpdate(player)
  175. -- Debug (optional): print("Equipped", weaponName, "to", player.Name)
  176. else
  177. warn("Could not equip weapon for", player.Name)
  178. end
  179. end
  180.  
  181. -----------------------------------------------------------
  182. -- RemoteFunction: GetDataFunction.OnServerInvoke
  183. -- Description: When the client requests their data, this function waits until the player's profile is loaded
  184. -- (with a maximum wait time) and then returns the stored data. If data isn’t available, it returns the default template.
  185. -----------------------------------------------------------
  186. function GetDataFunction.OnServerInvoke(player)
  187. local totalWait = 0
  188. while not Profiles[player] and totalWait < 5 do
  189. task.wait(0.2)
  190. totalWait = totalWait + 0.2
  191. end
  192. if not Profiles[player] then
  193. return DataTemplate
  194. end
  195. return Profiles[player].Data
  196. end
  197.  
  198. -----------------------------------------------------------
  199. -- Function: DataManager.SaveData
  200. -- Description: Called when a player leaves. It releases their profile, which saves the data.
  201. -----------------------------------------------------------
  202. function DataManager.SaveData(player)
  203. local profile = Profiles[player]
  204. if profile then
  205. profile:Release()
  206. end
  207. end
  208.  
  209. -----------------------------------------------------------
  210. -- Update Methods for Player Data
  211. -----------------------------------------------------------
  212.  
  213. -- Function: DataManager.UpdateStat
  214. -- Updates a specific stat in the player's data, then sends a live update.
  215. function DataManager.UpdateStat(player, stat, value)
  216. local profile = Profiles[player]
  217. if profile and profile.Data[stat] ~= nil then
  218. profile.Data[stat] = value
  219. DataManager.SendUpdate(player)
  220. end
  221. end
  222.  
  223. -- Function: DataManager.AddLoot
  224. -- Adds a specified amount of loot to the player's data if it is obtainable,
  225. -- updates the player's profile, sends a live update, and triggers a GUI popup.
  226. function DataManager.AddLoot(player, lootName, amount)
  227. local obtainableLoot = require(game.ServerScriptService.LootManager).GetObtainableLoot()
  228. local profile = Profiles[player]
  229. -- Only add loot if it's marked as obtainable.
  230. if profile and obtainableLoot[lootName] then
  231. profile.Data.Loot[lootName] = (profile.Data.Loot[lootName] or 0) + amount
  232. DataManager.SendUpdate(player)
  233.  
  234. -- Trigger the loot popup GUI on the client.
  235. local ReplicatedStorage = game:GetService("ReplicatedStorage")
  236. local Remotes = ReplicatedStorage:WaitForChild("Remotes")
  237. local LootPopupEvent = Remotes:FindFirstChild("LootPopupEvent")
  238. if LootPopupEvent then
  239. LootPopupEvent:FireClient(player, lootName, amount)
  240. end
  241. end
  242. end
  243.  
  244. -- Function: DataManager.RemoveLoot
  245. -- Removes a specified amount of loot from the player's data if they have enough.
  246. -- Returns true if successful; false otherwise.
  247. function DataManager.RemoveLoot(player, lootName, amount)
  248. local profile = Profiles[player]
  249. if profile and profile.Data.Loot[lootName] and profile.Data.Loot[lootName] >= amount then
  250. profile.Data.Loot[lootName] = profile.Data.Loot[lootName] - amount
  251. if profile.Data.Loot[lootName] <= 0 then
  252. profile.Data.Loot[lootName] = nil
  253. end
  254. DataManager.SendUpdate(player)
  255. return true
  256. end
  257. return false
  258. end
  259.  
  260. -- Function: DataManager.AddWeapon
  261. -- Adds a weapon to the player's owned list (if they don't already own it) and sends an update.
  262. function DataManager.AddWeapon(player, weaponName)
  263. local profile = Profiles[player]
  264. if profile and not table.find(profile.Data.Weapons, weaponName) then
  265. table.insert(profile.Data.Weapons, weaponName)
  266. DataManager.SendUpdate(player)
  267. end
  268. end
  269.  
  270. -- Function: DataManager.AddCoins
  271. -- Increments the player's coins by the given amount and sends an update.
  272. function DataManager.AddCoins(player, amount)
  273. local profile = Profiles[player]
  274. if profile then
  275. profile.Data.Coins = profile.Data.Coins + amount
  276. DataManager.SendUpdate(player)
  277. end
  278. end
  279.  
  280. -- Function: DataManager.RemoveCoins
  281. -- Deducts coins from the player's data if they have enough.
  282. -- Returns true if successful; false otherwise.
  283. function DataManager.RemoveCoins(player, amount)
  284. local profile = Profiles[player]
  285. if profile and profile.Data.Coins >= amount then
  286. profile.Data.Coins = profile.Data.Coins - amount
  287. DataManager.SendUpdate(player)
  288. return true
  289. end
  290. return false
  291. end
  292.  
  293. -- Function: DataManager.AddKill
  294. -- Increments the player's kill count by one and sends an update.
  295. function DataManager.AddKill(player)
  296. local profile = Profiles[player]
  297. if profile then
  298. profile.Data.Kills = profile.Data.Kills + 1
  299. DataManager.SendUpdate(player)
  300. end
  301. end
  302.  
  303. -----------------------------------------------------------
  304. -- Connect Player Events
  305. -----------------------------------------------------------
  306. game.Players.PlayerAdded:Connect(DataManager.LoadData) -- Load data when a player joins
  307. game.Players.PlayerRemoving:Connect(DataManager.SaveData) -- Save data when a player leaves
  308.  
  309. -----------------------------------------------------------
  310. -- Return the DataManager module
  311. -----------------------------------------------------------
  312. return DataManager
  313.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement