Ask a question!
Ep 32. Trading System
When completing a trade, the pets you’ve selected and traded will still appear in your Pet Inventory Gui.
When completing a trade, and then starting another trade, the Completed Frame will still be visible.
Solution
Inside the ServerScriptService/Utils/Utils module script update the PetDelete function:
ServerScriptService/Utils/Utils.lua
function Utils.PetDelete(player: Player, uuid: string)
local pet = player.petInventory:FindFirstChild(uuid)
if not pet then return end
Utils.PetUnfollow(player, uuid)
pet:Destroy()
remotes.PetDelete:FireClient(player, uuid)
endInside the StarterGui/PetInventory/Manager local script add the following to the bottom of your script:
StarterGui/PetInventory/Manager.local.lua
Remotes.PetDelete.OnClientEvent:Connect(function(uuid: string)
local petTemplateInstance = container:FindFirstChild(uuid)
if petTemplateInstance then
petTemplateInstance:Destroy()
end
end)Here is the entire StarterGui/Trade/Manager module script:
StarterGui/Trade/Manager.lua
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Remotes = ReplicatedStorage:WaitForChild("Remotes")
local PetModels = ReplicatedStorage.Pets
local PetsHandler = require(script.Parent.Parent.PetInventory.Handler)
local player = Players.LocalPlayer
local screenGui = script.Parent
local frame = screenGui.Frame
local container = frame.Container.Container
local title = frame.Title
local ourAvatar = frame.OurAvatar
local ourLabel = frame.OurLabel
local ourOffer = frame.OurOffer
local ourAccepted = frame.OurAccepted
local theirAvatar = frame.TheirAvatar
local theirLabel = frame.TheirLabel
local theirOffer = frame.TheirOffer
local theirAccepted = frame.TheirAccepted
local accept = frame.Accept
local decline = frame.Decline
local template = container.Template
local function UnacceptTrade()
Remotes.TradeUnaccept:FireServer()
ourAccepted.Visible = false
accept.Text = "Accept"
end
local function Cleanup()
for _, child in ipairs(ourOffer:GetChildren()) do
if child:IsA("TextButton") then
child:Destroy()
end
end
for _, child in ipairs(theirOffer:GetChildren()) do
if child:IsA("TextButton") then
child:Destroy()
end
end
for _, child in ipairs(container:GetChildren()) do
if child:IsA("TextButton") and child.Visible then
child:Destroy()
end
end
end
local function GeneratePet(petTable, parent: Instance)
local clone = template:Clone()
clone.Visible = true
clone.Parent = parent
clone.Name = petTable.UUID
clone.Holder.PetName.Text = petTable.ID:gsub("_", " ")
clone.Holder.Equipped.Visible = petTable.Equipped
local petModel = PetModels[petTable.ID]:Clone()
PetsHandler.GenerateViewportFrame(clone.Holder.ViewportFrame, petModel)
return clone
end
local function SelectPet(button: TextButton, petTable)
button:SetAttribute("Selected", true)
button.Parent = ourOffer
Remotes.TradeSelectPet:FireServer(petTable.UUID)
end
local function DeselectPet(button: TextButton, petTable)
button:SetAttribute("Selected", false)
button.Parent = container
Remotes.TradeDeselectPet:FireServer(petTable.UUID)
end
local function GenerateOurPets()
for _, pet in ipairs(player.petInventory:GetChildren()) do
local petTable = PetsHandler.PetInstanceToTable(pet)
local pet = GeneratePet(petTable, container)
pet:SetAttribute("Selected", false)
pet.MouseButton1Click:Connect(function()
UnacceptTrade()
if pet:GetAttribute("Selected") then
DeselectPet(pet, petTable)
else
SelectPet(pet, petTable)
end
end)
end
end
local function TraderSelectsPet(petTable)
GeneratePet(petTable, theirOffer)
end
local function TraderDeselectsPet(uuid)
local instance = theirOffer:FindFirstChild(uuid)
if instance then
instance:Destroy()
end
end
local function UpdateLabels(target: Player)
title.Text = "TRADE WITH "..target.DisplayName
theirLabel.Text = target.DisplayName.."'s Offer"
theirAvatar.Image = Players:GetUserThumbnailAsync(target.UserId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size60x60)
end
local function BeginTrade(targetId: number)
local target = Players:GetPlayerByUserId(targetId)
if not target then return end
GenerateOurPets()
UpdateLabels(target)
ourAccepted.Visible = false
theirAccepted.Visible = false
screenGui.Enabled = true
end
local function Startup()
ourLabel.Text = player.DisplayName.."'s Offer"
ourAvatar.Image = Players:GetUserThumbnailAsync(player.UserId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size60x60)
end
Startup()
local function Decline()
Cleanup()
screenGui.Enabled = false
end
local function TraderAccepts()
theirAccepted.Visible = true
end
local function TraderUnaccepts()
theirAccepted.Visible = false
end
accept.MouseButton1Click:Connect(function()
if accept.Text == "Accept" then
Remotes.TradeAccept:FireServer()
ourAccepted.Visible = true
accept.Text = "Unaccept"
else
UnacceptTrade()
end
end)
decline.MouseButton1Click:Connect(function()
Remotes.TradeDeclined:FireServer()
Decline()
end)
Remotes.TradeBegan.OnClientEvent:Connect(BeginTrade)
Remotes.TradeDeclined.OnClientEvent:Connect(Decline)
Remotes.TradeSelectPet.OnClientEvent:Connect(TraderSelectsPet)
Remotes.TradeDeselectPet.OnClientEvent:Connect(TraderDeselectsPet)
Remotes.TradeAccept.OnClientEvent:Connect(TraderAccepts)
Remotes.TradeUnaccept.OnClientEvent:Connect(TraderUnaccepts)
Remotes.TradeCompleted.OnClientEvent:Connect(Decline)EXPAND
Here in the entire ServerScriptService/Trade server script:
ServerScriptService/Trade.lua
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerScriptService = game:GetService("ServerScriptService")
local Rewards = require(ServerScriptService.Utils.Rewards)
local Utils = require(ServerScriptService.Utils.Utils)
local Remotes = ReplicatedStorage.Remotes
local TradeAccepted = {}
local TradeSelected = {}
local TradeRequests = {}
local Trading = {}
local function IsTrading(player: Player)
return Trading[player.UserId]
end
local function IsOnCooldown(playerId, targetId)
local requests = TradeRequests[playerId]
if not requests then return end
return table.find(requests, targetId)
end
local function HasSentRequest(accepterID: number, senderID: number)
local requestTable = TradeRequests[senderID]
if not requestTable then return end
if table.find(requestTable, accepterID) then
return true
end
return false
end
local function SendTradeRequest(player: Player, targetID: number)
local target = Players:GetPlayerByUserId(targetID)
if not target then return end
if IsOnCooldown(player.UserId, targetID) then return end
local playerTable = TradeRequests[player.UserId]
if not playerTable then
TradeRequests[player.UserId] = {}
playerTable = TradeRequests[player.UserId]
end
Remotes.TradeRequestReceived:FireClient(target, player)
table.insert(playerTable, targetID)
task.delay(15, function()
local index = table.find(TradeRequests[player.UserId], targetID)
table.remove(TradeRequests[player.UserId], index)
end)
return true
end
local function AcceptTradeReuqest(player: Player, targetID: number)
local target = Players:GetPlayerByUserId(targetID)
if not target then return end
if IsTrading(player) or IsTrading(target) then return end
if not HasSentRequest(player.UserId, targetID) then return end
Trading[player.UserId] = targetID
Trading[targetID] = player.UserId
Remotes.TradeBegan:FireClient(player, targetID)
Remotes.TradeBegan:FireClient(target, player.UserId)
end
local function TradeDeclined(player: Player)
local targetID = IsTrading(player)
TradeAccepted[player.UserId] = nil
TradeRequests[player.UserId] = nil
Trading[player.UserId] = nil
if not targetID then return end
local target = Players:GetPlayerByUserId(targetID)
if not target then return end
TradeAccepted[targetID] = nil
TradeRequests[targetID] = nil
Trading[targetID] = nil
Remotes.TradeDeclined:FireClient(target, player.UserId)
end
local function TradeSelectPet(player: Player, uuid: string)
local targetID = IsTrading(player)
if not targetID then return end
local target = Players:GetPlayerByUserId(targetID)
if not target then return end
local petInstance = player.petInventory:FindFirstChild(uuid)
if not petInstance then return end
local petTable = {}
petTable.UUID = petInstance.Name
petTable.ID = petInstance.ID.Value
petTable.Rarity = petInstance.Rarity.Value
local selectedPets = TradeSelected[player.UserId]
if not selectedPets then
TradeSelected[player.UserId] = {}
end
table.insert(TradeSelected[player.UserId], uuid)
Remotes.TradeSelectPet:FireClient(target, petTable)
end
local function TradeDeselectPet(player: Player, uuid: string)
local targetID = IsTrading(player)
if not targetID then return end
local target = Players:GetPlayerByUserId(targetID)
if not target then return end
local petInstance = player.petInventory:FindFirstChild(uuid)
if not petInstance then return end
local selectedPets = TradeSelected[player.UserId]
if not selectedPets then return end
local pet = table.find(selectedPets, uuid)
if not pet then return end
table.remove(selectedPets, pet)
Remotes.TradeDeselectPet:FireClient(target, uuid)
end
local function CompleteTrade(player: Player, target: Player)
local playerPets = TradeSelected[player.UserId]
local targetPets = TradeSelected[target.UserId]
if playerPets then
for _, uuid in ipairs(playerPets) do
local petInstance = player.petInventory:FindFirstChild(uuid)
Rewards.Pet(target, petInstance.ID.Value, petInstance.Rarity.Value)
Utils.PetDelete(player, uuid)
end
TradeSelected[player.UserId] = nil
end
if targetPets then
for _, uuid in ipairs(targetPets) do
local petInstance = target.petInventory:FindFirstChild(uuid)
Rewards.Pet(player, petInstance.ID.Value, petInstance.Rarity.Value)
Remotes.PetHatched:FireClient(player, nil, petInstance)
Utils.PetDelete(target, uuid)
end
TradeSelected[target.UserId] = nil
end
TradeAccepted[player.UserId] = nil
TradeRequests[player.UserId] = nil
Trading[player.UserId] = nil
TradeAccepted[target.UserId] = nil
TradeRequests[target.UserId] = nil
Trading[target.UserId] = nil
Remotes.TradeCompleted:FireClient(player)
Remotes.TradeCompleted:FireClient(target)
end
local function TradeAccept(player: Player)
local targetID = IsTrading(player)
if not targetID then return end
local target = Players:GetPlayerByUserId(targetID)
if not target then return end
TradeAccepted[player.UserId] = true
local targetAcceptance = TradeAccepted[targetID]
if targetAcceptance and targetAcceptance == true then
CompleteTrade(player, target)
end
Remotes.TradeAccept:FireClient(target)
end
local function TradeUnaccept(player: Player)
local targetID = IsTrading(player)
if not targetID then return end
local target = Players:GetPlayerByUserId(targetID)
if not target then return end
local acceptance = TradeAccepted[player.UserId]
if acceptance then
TradeAccepted[player.UserId] = nil
end
Remotes.TradeUnaccept:FireClient(target)
end
Players.PlayerRemoving:Connect(TradeDeclined)
Remotes.SendTradeRequest.OnServerInvoke = SendTradeRequest
Remotes.AcceptTradeRequest.OnServerEvent:Connect(AcceptTradeReuqest)
Remotes.TradeDeclined.OnServerEvent:Connect(TradeDeclined)
Remotes.TradeSelectPet.OnServerEvent:Connect(TradeSelectPet)
Remotes.TradeDeselectPet.OnServerEvent:Connect(TradeDeselectPet)
Remotes.TradeAccept.OnServerEvent:Connect(TradeAccept)
Remotes.TradeUnaccept.OnServerEvent:Connect(TradeUnaccept)EXPAND