1. What do you want to achieve?
I’d like the model to be displayed in the viewport constantly (i.e., not needing the mouse to hover over the item) and I’d like the correct model to be displayed in the viewportframe 100% of the time.
2. What is the issue?
Here’s a video that shows the functionality and the issues:
The model displayed in the viewportframe does either of the following:
- It doesn’t even appear within the viewportframe (happens occasionally)
- The wrong model is displayed in the viewportframe (aka, it doesn’t correspond to the model within the ObjectDisplay part)
3. What solutions have you tried so far?
I tried adding a part in the GUI ClientScripts that checks the Num.Value in a SpecialDisplay model to make sure the item corresponds with the ObjectDisplay part within the SpecialDisplay mode; however, this seems to not be successful…
Workspace setup: ShopGUIs
*I created two separate GUIs for each SpecialDisplay model since I wasn’t sure how I’d go about only using one, I’m a new scripter so my knowledge is very limited; hence, I used two.
ShopGUI ClientScript
*Only going to put one of them (ie. “SpecialShopItem1GUI”) into this post since they’re basically the same
local function playSound()
script.AddSound:Play()
end
-- Get the ItemDesc object from the parent of the script
local Info = script.Parent.ItemDesc
local objDisplay
for _, specialDisplay in ipairs(game.Workspace:GetDescendants()) do
if specialDisplay.Name == "SpecialDisplay" then --specialDisplay:IsA("Folder") and
local numValue = specialDisplay:FindFirstChild("Num")
if numValue and numValue:IsA("NumberValue") and numValue.Value == 1 then
objDisplay = specialDisplay:FindFirstChild("ObjectDisplay")
print(objDisplay)
break
end
end
end
-- Loop through each slot in the grid
for i, slot in ipairs(script.Parent.Slots:GetChildren()) do
-- Check if the slot is a Frame object
if slot:IsA("Frame") then
-- Add a MouseEnter event listener to the slot
slot.MouseEnter:Connect(function()
-- Clone the first child and set its parent to the ViewportFrame.Model property of the specific slot
local firstChild = objDisplay:GetChildren()[1]
print(firstChild) -- check the value of firstChild
-- Get the first child of the ObjectDisplay part and set the ItemName object in the Info variable to its Name property
Info.ItemName.Text = firstChild.Name
Info.ItemDescription.Text = firstChild:FindFirstChild("Desc").Value
script.Parent.Slots.Cost.Text = "Coins: ".. firstChild:FindFirstChild("Cost").Value --added
-- Clone the first child and set its parent to the ViewportFrame.Model property of the specific slot
local clonedChild = objDisplay:GetChildren()[1]:Clone()
clonedChild.Parent = slot.ViewportFrame.Model
print(clonedChild)
-- Set the Visible property of the Info object to true
Info.Visible = true
end)
-- Add a MouseLeave event listener to the slot
slot.MouseLeave:Connect(function()
-- Set the Visible property of the Info object to false
Info.Visible = false
end)
local slotframe = script.Parent.Slots
local function update(specific)
-- Disable and re-enable the RotateVis script under the specific slot's parent
local rotateVis = slotframe:FindFirstChild(specific).RotateVis
rotateVis.Disabled = true
rotateVis.Disabled = false
end
local slots = script.Parent.Slots
--// glowing selection reset
slots.Primary.ImageButton.Transparency =1
local equipped = true
for i, slot in ipairs(script.Parent.Slots:GetChildren()) do
-- Check if the slot is a Frame object
if slot:IsA("Frame") then
-- Add a MouseClick event listener to the slot
slot.ImageButton.MouseButton1Click:Connect(function(player)
-- Get the first child of the ViewportFrame.Model and set the itemName variable to its Name property
local itemModel = slot.ViewportFrame.Model:GetChildren()[1]
local itemName = itemModel.Name
print(itemModel)
local player = game.Players.LocalPlayer
print(player) -- This will print the value of player in the console
print(player.leaderstats)
-- Check if the slot has an item equipped
local shopitem = objDisplay:GetChildren()[1]
local itemcost = shopitem:FindFirstChild("Cost").Value
print(shopitem)
if equipped == true and itemcost > player.leaderstats:FindFirstChild("Coins").Value then
player.PlayerGui.GameInventory.DeleteOneMsg.Visible = true
player.PlayerGui.GameInventory.DeleteOneMsg.Msg.Text = "You don't have enough coins."
--player.PlayerGui.GameInventory.Frame.Visible = true
wait(2)
player.PlayerGui.GameInventory.DeleteOneMsg.Visible = false
else
if equipped == true and itemcost <= player.leaderstats:FindFirstChild("Coins").Value then
local event = game.ReplicatedStorage.InvEvents.PickUp
local purchaseitem = game.ReplicatedStorage.ShopEvents.Purchase
local item = itemName
local firstChild = itemModel
local itemdescription = firstChild:FindFirstChild("Desc").Value
event:FireServer(item, itemdescription)
purchaseitem:FireServer(itemcost)
-- Set the Equipped value of the item to false and hide the item in the slot
equipped = false
slot.Visible = false
-- Clear the model of the slot to remove the item from the slot
slot.ViewportFrame.Model:ClearAllChildren()
-- Update the value in the settings for the slot
if slot == slotframe.Primary then
script.Parent.Settings.Primary.Value = ''
end
end
-- Play a sound
playSound()
script.Parent.Parent.Parent:Destroy()
end
end)
end
end
end
end
Workspace setup: GUI/ViewportFrame
*Again, the other GUI has the same setup
*The model displayed in the viewportframe is parented to the “Model”
Workspace setup: SpecialDisplay Object/Model
*All SpecialDisplay Objects/Models have the same setup, just different Num.Value
*The Num.Value = 1
SpecialDisplay ProximityPrompt Script
local cooldown = 1800
local canUse = true
script.Parent.Triggered:Connect(function(player)
if canUse then
local card_stat = player.Data_Folder.MAX_CARD_STORAGE
local current_card = player.Data_Folder.CurrentCardStorage
local art_stat = player.Data_Folder.MAX_ART_STORAGE
local current_art = player.Data_Folder.CurrentArtStorage
if current_card.Value >= card_stat.Value or current_art.Value >= art_stat.Value then
-- Show the delete message for a few seconds
player.PlayerGui.GameInventory.DeleteOneMsg.Visible = true
player.PlayerGui.GameInventory.DeleteOneMsg.Msg.Text = "You must remove ONE item from your inventory."
wait(2)
player.PlayerGui.GameInventory.DeleteOneMsg.Visible = false
else
if current_card.Value < card_stat.Value or current_art.Value < art_stat.Value then
-- Hide the delete message if it's still visible
player.PlayerGui.GameInventory.DeleteOneMsg.Visible = false
-- Open the card selection GUI
local gui = game.ReplicatedStorage.GUIs.SpecialShopItem2GUI:Clone()
gui.Parent = player.PlayerGui
end
end
canUse = false
script.Parent.Enabled = false
wait(cooldown)
canUse = true
script.Parent.Enabled = true
end
end)
ObjectDisplayScript in ServerScriptService
*Basically tells the game. what to put into the ObjectDisplayPart of a SpecialDisplay Model/Object
local replicatedStorage = game:GetService("ReplicatedStorage")
local shopFolder = replicatedStorage:WaitForChild("Shop")
local workspace = game:GetService("Workspace")
-- Define the items and their rarities
--I'll change rarities so that they all add up to 100 once all the items are finished
local Items = {
Crate = 30, --l
Emerald = 30, --c
Diamond = 30, --r
Sapphire = 30, --uc
Rock = 30, --c
Wood = 30, --uc
Leaf = 30, --r
Strawberry = 30, --l
Leg = 30, --c
Arm = 30, --uc
Ribs = 30, --r
Skull = 30, --l
["Beast Sense I"] = 15,
["Resistance I"] = 15,
["Soul Seeker I"] = 15,
["Loot Finder I"] = 20,
["Stealth I"] = 20,
["Beast Sense II"] = 10,
["Resistance II"] = 10,
["Soul Seeker II"] = 10,
["Loot Finder II"] = 10,
["Stealth II"] = 10,
["Soul Seeker III"] = 5,
["Resistance III"] = 5,
["Loot Finder III"] = 5,
["Beast Sense III"] = 5,
["Stealth III"] = 5,
}
local Seed = Random.new(tick())
local function PickItem(RarityList: {[string]: number}): string
local Num = Seed:NextNumber(0, 100)
local Int = 0
for Item, Chance in pairs(Items) do
Int += Chance
if Num <= Int then
return Item
end
end
end
local ChosenItem = PickItem(Items)
print(ChosenItem) -- 66% chance to be Crate, 33% chance to be Stealth, 1% chance to be Loot Finder
-- Find all the SpecialDisplay1 objects in the workspace
local specialDisplays = workspace:GetDescendants()
for _, obj in ipairs(specialDisplays) do
if obj.Name == "SpecialDisplay" then
-- Find all the ObjectDisplay children of each SpecialDisplay1 object
local objectDisplays = obj:GetDescendants()
for _, child in ipairs(objectDisplays) do
if child.Name == "ObjectDisplay" then
-- Spawn a random model for each ObjectDisplay child
local function spawnRandomModel()
-- Select a random rarity level first
local ItemName = PickItem(Items)
local ItemModel = shopFolder[ItemName]:Clone()
local randomModel = shopFolder:FindFirstChild(ItemName)
if randomModel == nil then
print("Model not found for item "..ItemName..".")
return
--end
else
local clonedModel = randomModel:Clone()
-- Find the root part of the cloned model
local rootPart = clonedModel.PrimaryPart.CFrame.Position
-- Calculate the offset between the root part and the ObjectDisplay child
local offset = child.Position - rootPart
-- Parent the cloned model to the ObjectDisplay child and move it to the correct position
clonedModel.Parent = child
clonedModel:SetPrimaryPartCFrame(CFrame.new(child.Position)) --+ offset))
end
end --added
-- Spawn a random model immediately for each ObjectDisplay child
spawnRandomModel()
-- Spawn a new random model for each ObjectDisplay child every 30 minutes
--while true do
-- wait(30 * 60)
-- spawnRandomModel()
-- end
-- end --added
end
end
end
end
Let me know if you need more information!