Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
2

How could I drop specific items from a generic GUI window spawned from a custom inventory?

Asked by
Morficc 36
7 years ago

Sorry about the confusing title. I was not sure how to phrase it. Please bare with me, as I am a beginner at Roblox Lua.

I am trying to create a custom inventory, and am making some progress. I created an "Equipment" GUI that has multiple slots within. Each of these slots have string and numbervalues within, to give items a name and stack values.

I have a wooden sword on the ground. In the sword object, I made a GUI object, and a script that clones the gui object into the playergui when you click on the sword. The GUI object asks if you want to pick up the sword or not, with a script within for the yes/no buttons. If you click yes, it imports the items name into my custom inventory slots.

This part works wellish (Even if not the best way to do it). What I am struggling with now is: I want to click on this item in the custom inventory, and have a prompt that opens on what to do with the item, (Equip, Drop, Delete, etc). As far as my understanding goes, I would need to have a GUI element created for each individual item slot, with the options for equip, delete within each element. This seems rather clunky though. I dont want to have to create that many additional GUI objects, and especially as the inventory grows dynamically, it seems a hassle to have to script it to create a new inventory slot, new inventory slot values, AND a new GUI for that new slot, and clone in the scripts needed.

My main question is that. Is there a way I could have one generic GUI window with the selections for "Equip, Delete, Drop", that opens when you click on any item in my inventory window. But have the generic GUI window know which item you clicked on, so it knows which one to drop/equip?

I hope this makes some sense. Kind of a hard thing to get off my brain, onto "paper". Here are the scripts I am using:

Script within my Wooden Sword tool:

local c =nil
function onClick(click)
for i,v in pairs (script.Parent:GetChildren()) do
    if v.ClassName == "ScreenGui" then
        c = v:Clone()
        c.Parent = click.PlayerGui
    end
end
end
script.Parent.ClickDetector.MouseClick:connect(onClick)

Script within the GUI within my wooden sword that gets cloned to PlayerGUI:

local inv = script.Parent.Parent.Parent.Main.MenuButton.CharacterButton.EquipBox
local invparts = inv:GetChildren()
local plr = game.Players.LocalPlayer


function yes()
script.Parent.yesbutton.Image = "http://www.roblox.com/asset/?id=674373802"
wait(.4)
script.Parent.yesbutton.Image = "http://www.roblox.com/asset/?id=674373565"
wait(.3)
script.Parent.Parent:Destroy()
for i, v in pairs(invparts) do
    wait(0.5)
    if v.SlotValue.Value == "" then
        v.SlotValue.Value = "Wooden Sword"
        v.Amount.Value = "1"
        v.SlotLabel.Text = v.SlotValue.Value
        v.SlotLabel.Visible = true
        break
    end
    end
end

function no()
script.Parent.nobutton.Image = "http://www.roblox.com/asset/?id=674374266"
wait(.4)
script.Parent.nobutton.Image = "http://www.roblox.com/asset/?id=674374562"
wait(.3)
script.Parent.Parent:Destroy()
end

script.Parent.yesbutton.MouseButton1Click:connect(yes)
script.Parent.nobutton.MouseButton1Click:connect(no)

If you would like to see what I have so far, i have the place active. Just click on the back down arrow to open the menu GUI, and then click on the character, and the "Equipment" selection. Then pick up the wooden sword by clicking on it.

https://www.roblox.com/games/671061956/SBOtest

thank you!

1 answer

Log in to vote
2
Answered by 7 years ago

Good job on thinking that there's a better solution.

Instead of hand-creating a GUI for every object, you should instead create a GUI (or perhaps a function that makes a GUI) that works for all of them. In each way an object can differ from another, you will need a variable. You could put these variables in game.ReplicatedStorage (ex the sword variables would go in a "WoodenSword" folder with StringValues and such), but easier to work with is a ModuleScript. You could try to use classes here, but if you don't know how, just use tables instead. Here's a sample ModuleScript to give you the idea:

--Resource Types
local ResourceManager = {}
local resources = {
    WoodSword = {
        Name = "Wooden Sword",
        Image = "",
        Model = game.ServerStorage.WoodenSwordModel,
        --Add any other information you want here, like "IsDroppable" or "IsWeapon", or "DamageAmount". You needn't have all these properties in every resource -- just make sure your code is okay with the value being nil. ex, if "DamageAmount" is nil, your code should simply not display the amount of damage it does (because it probably isn't a weapon).
    },
    ["Object Type With Spaces"] = {
        Name = "(for example)",
        Image = "",
        Model = game.ServerStorage.etc,
    }
}
ResourceManager.Resources = resources --allow other scripts to access this table
--Note that each entry in Resources must be unique, since it's a dictionary. The Names don't have to be, but if you write a NameToData function, you'll have to think about what you want to do if there are multiple data types with the same name.
--example of ImageToData:
local function ResourceManager.ImageToData(image) --This only works if all images are unique. If not, this algorithm should be changed to support returning a list of items.
    for dataName, data in pairs(resources) do
        if data.Image == image then
            return data
        end
    end
end
--But if you regularly need to convert an image back to the data type it came from, you should cache the results in a table, or just make a table of all Image->Data types automatically. Let's also make it return lists of items that the image belongs to, instead of just a single item.
local imageToData = {}
for dataName, data in pairs(resources) do
    if data.Image then
        local t = imageToData[data.Image]
        if not t then
            t = {}
            imageToData[data.Image] = t
        end
        t[#t + 1] = data --same as "table.insert(t, data)"
    end
end
ResourceManager.ImageToData = imageToData
return ResourceManager

A note about the ImageToData: You could use it by saying ImageToData["linkAddress"]; you would get a list of items that that image could refer to (or nil if no object has that linkAddress as its image). I can't see how this is useful, but this concept may be useful for other fields. Your scripts should usually just store the type name ("WoodSword") or the data itself (Resources.WoodSword). Your scripts can get the data like this:

local ResourceManager = require(game.ReplicatedStorage.ResourceManager)
local woodSwordData = ResourceManager.Resources["WoodSword"] --for example

But note that you should only rare have to write out "WoodSword" in most of your code. ex, for your gui code, it should accept a function parameter or StringValue that will contain the ObjectType (which may happen to be WoodSword). Then the script can get the information it needs using the ResourceManager. You should have to say "WoodSword" specifically if you are generating a WoodSword or giving a player one (ex as a quest reward).

To aid in this, models lying in the workspace (that can be clicked on) should all have a StringValue describing its type (ex. "WoodSword").

So, in your gui code, probably the easiest is to put a StringValue as a child of the gui code (unless your gui code is in a ModuleScript and can then receive function arguments).

--In whatever creates a new gui script:
local s = Instance.new("StringValue")
s.Name = "ResourceType"
s.Value = objectType
s.Parent = guiScript

--As first lines of gui script:
local ResourceManager = require(game.ReplicatedStorage.ResourceManager)
local resourceType = script:WaitForChild("ResourceType").Value
local data = ResourceManager.Resources[resourceType]
--Use the data accordingly. ex, to get the image, use "data.Image".

However, it would be faster (in terms of performance and maybe in writing code) to put more of this stuff in ModuleScripts (which can be accessed by other scripts). ex, for your inventory slots, you might use an InventorySlots ModuleScript. It could have functions for adding/dropping/using/equipping items (it may have to work with other scripts to equip something, for instance). With ModuleScripts you don't need to use StringValues (though you may find it easier to do so in some cases).

ex, maybe when the player clicks on InventorySlot 2, you will send information to a different script saying "The player clickedon InventorySlot 2 -- display the options!". That script can request what objectType is in inventory slot #2 by asking the InventorySlots ModuleScript. It can then, if needed, get information about the type from the ResourceManager. It should then have all the information it needs to display "Equip", "Drop", "Use", etc. (well, it may need to ask for more information from other scripts, but hopefully you get the idea). In the end, your gui code need never contain the string "WoodSword".

0
Wow. Thank you very much for the detailed response! I will not lie, 90% of that went right over my head. But I am a quick study, and using your post and other resources, I think I will get it after some practice. I am going to start practicing some ModuleScripts now. I think perhaps starting a custom inventory a couple days after being introduced to Roblox Lua was a bit of a large order, but a goo Morficc 36 — 7y
0
Update: Easier than I thought! Using your examples, I was able to make a ModuleScript to store a couple different sword data. Then made a brick that when clicked on, opened a GUI displaying an items name from my modulescript table. Worked well! Thank you! Morficc 36 — 7y
1
Glad you got it! Feel free to message me on Roblox if you want further explanations/clarifications (though my response time is ~1-2 days). (Also, be careful of the comment's maximum length on this site.) chess123mate 5873 — 7y
Ad

Answer this question