Collectable items book where you can track plants you find

Hey y’all,
As you can probably tell I’m a novice scripter with little knowledge.
I’m thinking of a game where you’d walk around an open world, finding, collecting, and logging plants you find by walking close and clicking on them. This mechanic would be simmilar to the “harvestables” of Fantastic Frontier, but the issue is that I’m not sure how I’d make it. Firstly, I’m not sure how to detect if there’s something nearby, or how to click on something and keep track of the number. Secondly, I’m not sure how to make the GUI for the “journal” and how to turn empty slots into picture of the plants. I’ve looked for tutorials on collectible items online but haven’t found any, and searched the developer hub for related topics but to my knowledge none were available. Do any of you know any resources, tutorials, or could give me so to help me?

Synopsis: System to create a collectible items log and be able to collect items
Link to Fantastic Frontier: https://www.roblox.com/games/510411669/Fantastic-Frontier

1 Like

If you want to make it so you can detect things nearby you either want to use a custom hit box or use magnitude(magnitude, in simpler terms is the distance in studs between 2 parts)
For example a part at a position of 1,0, 0 and another part in a position of 2, 0,0 will have a magnitude of 1
But, since you said that you wanted them to only click at a certain distance, you can inset a click detector and set the max activation distance to 5 to 10 (pretty close to the plant)
But, you may be asking, what is magnitude used for?
Well, that’s to create special effects such as making the plant glow when a player get near
I can’t really he you on any other parts because I don’t know, I hope this info helps

2 Likes

Ok, thanks for the info @VegetationBush ! Now thats one part of the problem solved…

I can think of a way for the journal, but you have to use leaderstats and I don’t think it’s the most efficient way: you make a book value leaderstats(bool means yes or no) names whatever the plant you want it to be, and then set it to false, and when you discover that plant, you make it true, and you’ll have a up that detects if it’s true, and if it is, it will be, “discovered” you can use viewport frames to put plant images in there. So make the image color black, and when it’s discovered, set it to white again

1 Like

I will definitely try that out. I’ll try tutorials on those topics, thanks!

I would recommend you not do that as you may have a ton of items to discover. Instead what you should do is store list of items that the player has discovered and each time they find and item check if its already in the list, and if its not you add it. After you can just save that table in a datastore, Also I would recommend that you give each item a special numerical Id instead of just saving the name to cut-down on the size of the table.

Another tip is to tag all the items that can be discovered, via the collection service so that fetching all these items will be much quicker and not constrained by any hierarchical relationships.

Here is a link to the Collection Service = https://developer.roblox.com/en-us/api-reference/class/CollectionService, and to tag items I would recommend that you install the tag editor plugin, or else you will have to use the command bar. https://devforum.roblox.com/t/tag-editor-v2-released/101133

So this is a basic implementation of how could implement the system:

--Server script
local ItemsDiscoveredRecords = {} -- A table to hold records of all the items found
local CollectionService = game:GetService("CollectionService")
local ITEM_TAG = "Discoverable" --here you put the tag you assigned to the items
game.Players.PlayerAdded:Connect(function(Player)
    ItemsDiscoveredRecords[tostring(Player.UserId)] = {} --adding a table items for the player that has joined
end)

local function UpdateItemsFromPlayer(Player,ItemName)
  if ItemsDiscoveredRecords[tostring(Player.UserId)] then
     for Index,ItemDiscovered in ipairs(ItemsDiscoveredRecords[tostring(Player.UserId)] )do
        if ItemDiscovered == ItemName then 
           --checking if the item already exists and if it does then we return from the function
           return
        end
     end
     table.insert(ItemsDiscoveredRecords[tostring(Player.UserId)],ItemName) --adding the item to the table since it does not exist
  end
end

local function DetectTouch(Item)
   --assuming all items are parts if they are model says Item.PrimaryPart.Touched, and you must set a primary part
   Item.Touched:Connect(function(hit)
      if hit.Parent:FindFirstChild("Humanoid") then
          local Character = hit.Parent
          local Player = game:GetService("Players"):GetPlayerFromCharacter(Character)
          UpdateItemsFromPlayer(Player,Item.Name)
      end
   end)
end

for _, Item in pairs(CollectionService:GetTagged(ITEM_TAG) do
   DetectTouch(Item)
end

This is just a simple illustration of how this can be implemented, also to update the table on the client you can use a remote event to send over the item added to table. You will have to implement some system of saving the table. Also, if you have any questions about this in the future feel free to ask for more help in scripting support.

2 Likes

Wow, thanks a lot! That was quite in depth, and I’ll probably try this in the near future (It’s the weekday and it’s past midnight)

1 Like