I have a tree system that is only half working. Problems include:
- Can only pick up one type of collectible.
- On generation, all the tree collectibles are respawned.
- Having multiple trees will spawn collectibles exponentially.
I have been trying for hours to figure out ways to fix these bugs but with no luck.
Server:
local ReplicatedStorage = game:GetService"ReplicatedStorage"
local ServerScriptService = game:GetService"ServerScriptService"
local Knit = require(ReplicatedStorage.Packages.Knit)
local Component = require(ReplicatedStorage.Packages.Component)
local Trove = require(ReplicatedStorage.Packages.Trove)
local Collectables = require(ServerScriptService.Source.Modules.Collectables)
local Generate = ReplicatedStorage:WaitForChild "Remotes".Tree.Generate
local RemoveObject = ReplicatedStorage:WaitForChild "Remotes".Tree.RemoveObject
local Tree = Component.new {
Tag = "Tree"
}
function Tree:Construct()
self._Trove = Trove.new()
self.Random = Random.new()
self.PlayersCooldown = {}
self.ItemData = {}
self.CooldownTime = 1
for _, Player in pairs(game.Players:GetPlayers()) do
self.ItemData[Player.UserId] = {}
end
game.Players.PlayerAdded:Connect(function(Player)
self.ItemData[Player.UserId] = {}
end)
game.Players.PlayerRemoving:Connect(function(Player)
self.ItemData[Player.UserId] = nil
self.PlayersCooldown[Player.UserId] = nil
end)
end
function Tree:RollCollectable()
local Counter = 0
for Index, _ in Collectables do
Counter += Collectables[Index][2]
end
local Chosen = self.Random:NextNumber(0, Counter)
for Index, _ in Collectables do
Counter -= Collectables[Index][2]
if Chosen > Counter then
return Collectables[Index][1]
end
end
end
function Tree:Start()
local Prompt = self.Instance.PrimaryPart.Prompt.ShakePrompt
local DataService = Knit.GetService("DataService")
self._Trove:Add(Prompt.Triggered:Connect(function(Player)
if not self.PlayersCooldown[Player.UserId] then
self.PlayersCooldown[Player.UserId] = os.time() - self.CooldownTime
end
if os.time() - self.PlayersCooldown[Player.UserId] >= self.CooldownTime then
local RandomAmount = self.Random:NextInteger(1, 3)
for _ = 1, RandomAmount do
local Type = self:RollCollectable()
if not self.ItemData[Player.UserId][Type] then
self.ItemData[Player.UserId][Type] = 0
self.ItemData[Player.UserId][Type] += 1
else
self.ItemData[Player.UserId][Type] += 1
end
end
print(self.ItemData) -- {[Player.UserId] = {Apple = 2, Orange = 1}}
Generate:FireClient(Player, self.ItemData[Player.UserId], self.Instance)
self.PlayersCooldown[Player.UserId] = os.time()
end
end))
RemoveObject.OnServerInvoke = function(Player: Player, InstanceName: string)
for Index, Data in self.ItemData[Player.UserId] do
print(self.ItemData[Player.UserId])
print(Index, Data, InstanceName) -- Apple, 2, Orange
if Index == InstanceName then
Data -= 1
local Profile = DataService:Get(Player)
if not Profile.Data.Inventory[InstanceName] then
Profile.Data.Inventory[InstanceName] = 0
else
Profile.Data.Inventory[InstanceName] += 1
end
return true
else
return false
end
end
end
end
function Tree:Stop()
self._Trove:Clean()
end
return Tree
Client:
local ReplicatedStorage = game:GetService"ReplicatedStorage"
local Component = require(ReplicatedStorage.Packages.Component)
local Trove = require(ReplicatedStorage.Packages.Trove)
local Generate = ReplicatedStorage:WaitForChild "Remotes".Tree.Generate
local RemoveObject = ReplicatedStorage:WaitForChild "Remotes".Tree.RemoveObject
local TreeClient = Component.new {
Tag = "Collectable",
Ancestors = {ReplicatedStorage, workspace}
}
function TreeClient:Construct()
self._Trove = Trove.new()
end
function TreeClient:Start()
self._Trove:Add(self.Instance)
self._Trove:Connect(Generate.OnClientEvent, function(ItemData: {[string]: number}, Tree)
for _, _ in Tree.Spawned:GetChildren() do
if not self.Instance.Parent then
return
end
if self.Instance.Parent.Parent == Tree then
self._Trove:Remove(self.Instance)
end
end
for Name, Amount in ItemData do
if self.Instance.Name == Name then
for _ = 1, Amount do
local ClonedObject = self.Instance:Clone()
ClonedObject:PivotTo(Tree.PrimaryPart.CFrame * CFrame.new(math.random(1, 3), 3, math.random(1, 3)))
ClonedObject.Parent = Tree.Spawned
end
end
end
end)
if self.Instance.PrimaryPart then
self._Trove:Add(self.Instance.PrimaryPart.CollectPrompt.Triggered:Connect(function()
local IsToRemove = RemoveObject:InvokeServer(self.Instance.Name)
if IsToRemove then
self._Trove:Remove(self.Instance)
end
end))
else
return
end
end
function TreeClient:Stop()
self._Trove:Clean()
end
return TreeClient
The first issue is in the server script:
RemoveObject.OnServerInvoke = function(Player: Player, InstanceName: string)
for Index, Data in self.ItemData[Player.UserId] do
print(self.ItemData[Player.UserId])
print(Index, Data, InstanceName) -- Apple, 2, Orange
if Index == InstanceName then
Data -= 1
local Profile = DataService:Get(Player)
if not Profile.Data.Inventory[InstanceName] then
Profile.Data.Inventory[InstanceName] = 0
else
Profile.Data.Inventory[InstanceName] += 1
end
return true
else
return false
end
end
end
The commented portion says enough, but for some reason, the index will always be the same depending on which collectible I get first.
The second problem lies in the client, on generation, the ItemData will not account for the already spawned collectibles in the Spawned folder in the tree. I tried subtracting the amount spawned by the current ItemData, however, nothing seemed to work and I do not know the best way of doing it.
I honestly have no idea what is wrong for the third problem to occur.
Any help is helpful, thank you.