Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- How to implement my PA Costume System!!! (as of 12/22/23)
- Reminders for after you read this guide:
- - Edit the Leaderboard object parented to GameGui to your liking
- - Remember to make it so when you click the Leaderboard button, it runs UpdateCostumes() (edit to LocalScript)
- - - - (by default, it runs UpdateLeaderboard(), so you can ctrl f for that)
- - Remember to make "Costumes" not detected by the evolution-detecting algorithm (edit to LocalScript)
- - Be wary of mechanics that evolve the player automatically (e.g. Palafin, and de-megaing).
- - - - Well, you only need to be wary of having a costume accessible by 1 form but not the other.
- - - - If the user has the costumes panel open during the evo, then they can cause an error by turning into a nonexistent morph.
- - - - The costumes panel is coded not to function when evolution takes place, so that edge case is avoided.
- - VERY VERY IMPORTANT NOTICE RELATED TO THE ABOVE BULLET BUT PLEASE READ
- - AGAIN VERY IMPORTANT
- - AGAIN VERY IMPORTANT OK READ IT NOW
- - - - Keep in mind that the costumes panel auto-disables by checking SLP. You should keep this in mind when designing the panel.
- What is the architecture?
- This is explained in the image attached externally.
- However, if you are a random person who found this suddenly:
- - Under each Pokemon for which you hope to give a costume to, create a folder called Costumes.
- - Inside the Costumes folder, create folders named after the costumes. For example, "Classic" (no quotes... or els
- - Inside each of these folders, create two StringValues:
- - - - One is named "Req". This is not optional. Type the stat required for using the costume as the Value.
- - - - - - (The req is not displayed to the player, so feel free to use ridiculous stat names!)
- - - - One is named "Image". This is optional. Type the number ID of the image that is displayed for the costume.
- - - - - - (If this doesn't exist, a ? will be substituted in its place (you can change this in the GetCostumes conditional)
- - This will set it up correctly.
- Code to insert:
- 1. In ServerScriptService > Stats > StarterData, add this as a stat:
- PASTE BEGIN
- ["EquippedCostume"] = {
- ["Permament"] = false;
- ["DefaultValue"] = "";
- ["Special"] = nil
- }
- PASTE END
- Furthermore, ensure that it is made to reset on spawn.
- So, change the dictionary at the bottom of StarterData and also in ServerHandler > Settings.
- The default costume is stored simply as "" (a length 0 string).
- 2. In big LocalScript, do ctrl+f "UpdateLeaderboard". Insert this directly underneath its end:
- PASTE BEGIN
- local function UpdateCostumes()
- if CallServer("GetStat", "SLP") == 1 then return end
- -- Creates a Frame that represents a row: ImageLabel on the left, TextButton on the right
- local function createText(num, imageID)
- print(imageID)
- local frame = Instance.new("Frame")
- frame.Position, frame.Size =
- UDim2.new(0, 0, (num - 1) * 0.1, 0), UDim2.new(1, 0, 0.1, 0)
- frame.BackgroundColor3, frame.BorderColor3, frame.BorderSizePixel =
- Color3.new(61/255, 61/255, 61/255), Color3.new(0,0,0), 2
- local height = script.Parent.Leaderboard.Frame.AbsoluteSize.Y*0.1 -- used to make image square and displace text accordingly
- height = 36.59 -- oops
- local width = 619.2 -- oops 2
- local image = Instance.new("ImageLabel")
- image.Position, image.Size, image.BackgroundTransparency, image.Image =
- UDim2.new(0, 0, 0, 0), UDim2.new(0, height, 1, 0), 1, imageID
- image.Parent = frame
- local textbutton = Instance.new("TextButton")
- textbutton.BackgroundTransparency, textbutton.Position, textbutton.Size =
- 1, UDim2.new(0,height,0,0), UDim2.new(0, width-height, 1, 0)
- textbutton.TextColor3, textbutton.TextScaled, textbutton.Font =
- Color3.new(1,1,1), true, Enum.Font.ArialBold
- textbutton.Parent = frame
- frame.Parent = script.Parent.Leaderboard.Frame
- return textbutton
- end
- do
- local cCostume = CallServer("GetStat", "EquippedCostume")
- script.Parent.Leaderboard.Points.Text = "Equipped Costume: "..tostring(cCostume~="" and cCostume or "Default (No Costume)")
- end
- for _, i in pairs(script.Parent.Leaderboard.Frame:GetChildren()) do
- i:Destroy()
- end
- local pages = CallServer("GetCostumes")
- if pages ~= nil then
- local debounce = false
- for i, haveAndImage in pairs(pages) do
- --[[
- haveAndImage is an array that contains:
- 1: costume's name as a string
- 2: whether or not the user has the required item for the costume
- 3: the image of the costume, in form "rbxassetid://[idnumber]"" ]]
- print(i..": ")
- print(haveAndImage[1])
- print(haveAndImage[2])
- print(haveAndImage[3])
- print()
- local theTextButton = createText(i, haveAndImage[3])
- if haveAndImage[2] then
- theTextButton.Text = haveAndImage[1].." (Owned)"
- local onClick onClick = theTextButton.MouseButton1Down:Connect(function()
- if CallServer("GetStat", "SLP") == 1 then onClick:Disconnect() return end
- if not debounce then
- debounce = true
- CallServer("ChangeCostumeMode", haveAndImage[1]=="Default (No Costume)" and "" or haveAndImage[1])
- UpdateCostumes()
- debounce = false
- end
- end)
- else
- theTextButton.Text = haveAndImage[1].." (Not Owned ❌)"
- end
- end
- else
- local theTextButton = createText(1, "rbxassetid://15709415914")
- theTextButton.Text = "No costumes...yet!"
- end
- end
- PASTE END
- 3. In ServerScriptService > ServerHandler, find the ScanForPokes function and change this:
- LOOK-AT-THIS BEGIN
- if i:IsA'Folder' and i.Name ~= "SetStatsOnSpawn" and i.Name ~= "Weapons" and i.Name ~= "Spawns" then
- LOOK-AT-THIS END
- ...into this:
- PASTE BEGIN
- if i:IsA'Folder' and i.Name ~= "SetStatsOnSpawn" and i.Name ~= "Weapons" and i.Name ~= "Spawns" and i.Name ~= "Costumes" then
- PASTE END
- (This makes sure the game doesn't mistake the Costumes folder for a Pokemon.)
- 4. In ServerHandler, insert this to replace the "local Morph" line at the top of the MegaEvolve conditional statement:
- PASTE BEGIN
- local Morph
- do
- local equipped = Stats.GetStat(args[1], "EquippedCostume")
- if equipped ~="" then
- if script.Pokemon[Name]:FindFirstChild("Costumes") and
- script.Pokemon[Name].Costumes:FindFirstChild(equipped) and
- Stats.GetStat(args[1], script.Pokemon[Name].Costumes[equipped].Req.Value)>0 then
- Morph = game.ServerStorage.MegaMorphs:FindFirstChild(Name.." ("..equipped..")")
- else
- Morph = game.ServerStorage.MegaMorphs:FindFirstChild(Name)
- Stats.SetStat(args[1], "EquippedCostume", "")
- end
- else
- Morph = game.ServerStorage.MegaMorphs:FindFirstChild(Name)
- Stats.SetStat(args[1], "EquippedCostume", "")
- end
- end
- PASTE END
- 5. In ServerHandler, put this right below the "plrspoke[args[1].Name] = Name" line at the top (inside an if-statement) in the Evolve conditional statement:
- PASTE BEGIN
- do
- local equipped = Stats.GetStat(args[1], "EquippedCostume")
- if equipped ~="" then
- if script.Pokemon[Name]:FindFirstChild("Costumes") and
- script.Pokemon[Name].Costumes:FindFirstChild(equipped) and
- Stats.GetStat(args[1], script.Pokemon[Name].Costumes[equipped].Req.Value)>0 then
- Morph = game.ServerStorage.Morphs:FindFirstChild(Name.." ("..equipped..")")
- else
- Morph = game.ServerStorage.Morphs:FindFirstChild(Name)
- Stats.SetStat(args[1], "EquippedCostume", "")
- end
- else
- Morph = game.ServerStorage.Morphs:FindFirstChild(Name)
- Stats.SetStat(args[1], "EquippedCostume", "")
- end
- end
- PASTE END
- 6. In ServerHandler, put this at the VERY VERY top of the SpawnPokemon conditional statement:
- PASTE BEGIN
- Stats.SetStat(args[1], "EquippedCostume", "")
- PASTE END
- This is done to simply cover our bases.
- 7. In ServerHandler, add the following conditional statement. I suggest removing all wardrobe-related text.
- PASTE BEGIN
- elseif args[2] == "ChangeCostumeMode" then
- if Stats.GetStat(args[1], "EquippedCostume")==args[3] then return end
- local TweenService = game:GetService("TweenService")
- local wardrobe = game.ServerStorage.Items.Wardrobe:Clone()
- Stats.SetStat(args[1], "SLP", 1)
- Stats.SetStat(args[1], "EquippedCostume", args[3])
- for i, part in pairs(wardrobe:GetChildren()) do part.Transparency=1 part.CanCollide=false part.Anchored=false part.Massless=true end
- wardrobe:PivotTo(args[1].Character.Torso.CFrame*CFrame.new(0, 6.5, 0))
- local weld = Instance.new("WeldConstraint")
- weld.Part0, weld.Part1 = wardrobe.PrimaryPart, args[1].Character.HumanoidRootPart
- weld.Parent = wardrobe.PrimaryPart
- for i, part in pairs(wardrobe:GetChildren()) do TweenService:Create(part, TweenInfo.new(0.3), {Transparency = 0}):Play() end
- wardrobe.Parent = workspace
- task.wait(0.4)
- args[1].Character:FindFirstChild("Arm1"):Destroy()
- args[1].Character:FindFirstChild("Arm2"):Destroy()
- args[1].Character:FindFirstChild("Leg1"):Destroy()
- args[1].Character:FindFirstChild("Leg2"):Destroy()
- args[1].Character:FindFirstChild("Chest"):Destroy()
- -- CREATING NEW CHARACTER
- local costumeSuffix = ""
- if Stats.GetStat(args[1], "EquippedCostume")~="" then
- costumeSuffix = " ("..Stats.GetStat(args[1], "EquippedCostume")..")"
- end
- local Morph = game.ServerStorage.Morphs:FindFirstChild(Stats.GetStat(args[1], "Current_Pokemon")..costumeSuffix)
- if not Morph then
- Morph = game.ServerStorage.MegaMorphs:FindFirstChild(Stats.GetStat(args[1], "Current_Pokemon")..costumeSuffix)
- end
- if not Morph then
- print("Costume \""..args[3].."\" doesn't exist on "..Stats.GetStat(args[1], "Current_Pokemon").."? From "..args[1])
- return
- end
- do
- -- welding (feel free to collapse)
- local Char = args[1].Character
- if Char:findFirstChild("Humanoid") ~= nil and Char:findFirstChild("Arm1") == nil then
- local g = Morph.Arm1:clone()
- g.Parent = Char
- local C = g:GetChildren()
- for i=1, #C do
- if C[i].className == "Part" or "UnionOperation" then
- local W = Instance.new("Weld")
- W.Part0 = g.Middle
- W.Part1 = C[i]
- local CJ = CFrame.new(g.Middle.Position)
- local C0 = g.Middle.CFrame:inverse()*CJ
- local C1 = C[i].CFrame:inverse()*CJ
- W.C0 = C0
- W.C1 = C1
- W.Parent = g.Middle
- end
- local Y = Instance.new("Weld")
- Y.Part0 = Char["Left Arm"]
- Y.Part1 = g.Middle
- Y.C0 = CFrame.new(0, 0, 0)
- Y.Parent = Y.Part0
- end
- local h = g:GetChildren()
- for i = 1, # h do
- h[i].Anchored = false
- h[i].CanCollide = false
- end
- end
- if Char:findFirstChild("Humanoid") ~= nil and Char:findFirstChild("Arm2") == nil then
- local g = Morph.Arm2:clone()
- g.Parent = Char
- local C = g:GetChildren()
- for i=1, #C do
- if C[i].className == "Part" or "UnionOperation" then
- local W = Instance.new("Weld")
- W.Part0 = g.Middle
- W.Part1 = C[i]
- local CJ = CFrame.new(g.Middle.Position)
- local C0 = g.Middle.CFrame:inverse()*CJ
- local C1 = C[i].CFrame:inverse()*CJ
- W.C0 = C0
- W.C1 = C1
- W.Parent = g.Middle
- end
- local Y = Instance.new("Weld")
- Y.Part0 = Char["Right Arm"]
- Y.Part1 = g.Middle
- Y.C0 = CFrame.new(0, 0, 0)
- Y.Parent = Y.Part0
- end
- local h = g:GetChildren()
- for i = 1, # h do
- h[i].Anchored = false
- h[i].CanCollide = false
- end
- end
- if Char:findFirstChild("Humanoid") ~= nil and Char:findFirstChild("Leg1") == nil then
- local g = Morph.Leg1:clone()
- g.Parent = Char
- local C = g:GetChildren()
- for i=1, #C do
- if C[i].className == "Part" or "UnionOperation" then
- local W = Instance.new("Weld")
- W.Part0 = g.Middle
- W.Part1 = C[i]
- local CJ = CFrame.new(g.Middle.Position)
- local C0 = g.Middle.CFrame:inverse()*CJ
- local C1 = C[i].CFrame:inverse()*CJ
- W.C0 = C0
- W.C1 = C1
- W.Parent = g.Middle
- end
- local Y = Instance.new("Weld")
- Y.Part0 = Char["Left Leg"]
- Y.Part1 = g.Middle
- Y.C0 = CFrame.new(0, 0, 0)
- Y.Parent = Y.Part0
- end
- local h = g:GetChildren()
- for i = 1, # h do
- h[i].Anchored = false
- h[i].CanCollide = false
- end
- end
- if Char:findFirstChild("Humanoid") ~= nil and Char:findFirstChild("Leg2") == nil then
- local g = Morph.Leg2:clone()
- g.Parent = Char
- local C = g:GetChildren()
- for i=1, #C do
- if C[i].className == "Part" or "UnionOperation" then
- local W = Instance.new("Weld")
- W.Part0 = g.Middle
- W.Part1 = C[i]
- local CJ = CFrame.new(g.Middle.Position)
- local C0 = g.Middle.CFrame:inverse()*CJ
- local C1 = C[i].CFrame:inverse()*CJ
- W.C0 = C0
- W.C1 = C1
- W.Parent = g.Middle
- end
- local Y = Instance.new("Weld")
- Y.Part0 = Char["Right Leg"]
- Y.Part1 = g.Middle
- Y.C0 = CFrame.new(0, 0, 0)
- Y.Parent = Y.Part0
- end
- local h = g:GetChildren()
- for i = 1, # h do
- h[i].Anchored = false
- h[i].CanCollide = false
- end
- end
- if Char:findFirstChild("Humanoid") ~= nil and Char:findFirstChild("Chest") == nil then
- local g = Morph.Chest:clone()
- g.Parent = Char
- local C = g:GetChildren()
- local R = Char:GetChildren()
- for i=1, #R do
- if R[i].className == "Hat" then
- R[i]:remove()
- end
- end
- for i=1, #C do
- if C[i].className == "Part" or "UnionOperation" then
- local W = Instance.new("Weld")
- W.Part0 = g.Middle
- W.Part1 = C[i]
- local CJ = CFrame.new(g.Middle.Position)
- local C0 = g.Middle.CFrame:inverse()*CJ
- local C1 = C[i].CFrame:inverse()*CJ
- W.C0 = C0
- W.C1 = C1
- W.Parent = g.Middle
- end
- local Y = Instance.new("Weld")
- Y.Part0 = Char.Torso
- Y.Part1 = g.Middle
- Y.C0 = CFrame.new(0, 0, 0)
- Y.Parent = Y.Part0
- end
- local h = g:GetChildren()
- for i = 1, # h do
- h[i].Anchored = false
- h[i].CanCollide = false
- end
- end
- end
- wardrobe:PivotTo(wardrobe:GetPivot()*CFrame.Angles(0, 0, math.rad(-30)))
- task.wait(0.2)
- for i = 1, 4 do
- wardrobe:PivotTo(wardrobe:GetPivot()*CFrame.Angles(0, 0, math.rad(60)))
- task.wait(0.2)
- wardrobe:PivotTo(wardrobe:GetPivot()*CFrame.Angles(0, 0, math.rad(-60)))
- task.wait(0.2)
- end
- wardrobe:PivotTo(wardrobe:GetPivot()*CFrame.Angles(0, 0, math.rad(30)))
- task.wait(0.2)
- for i, part in pairs(wardrobe:GetChildren()) do TweenService:Create(part, TweenInfo.new(0.3), {Transparency = 1}):Play() end
- Stats.SetStat(args[1], "SLP", 0)
- task.wait(0.6)
- wardrobe:Destroy()
- PASTE END
- 8. In ServerHandler, add the following conditional statement:
- PASTE BEGIN
- elseif args[2] == "GetCostumes" then
- local cPokemon = Stats.GetStat(args[1], "Current_Pokemon")
- if cPokemon ~= nil and string.len(cPokemon)>0 then -- Make sure the player has spawned as a Pokemon
- local costumesFolder = script.Pokemon[cPokemon]:FindFirstChild("Costumes")
- if costumesFolder then
- local costumesOwned = {{"Default (No Costume)", true, "rbxassetid://15709415914"}}
- for i, costume in ipairs(costumesFolder:GetChildren()) do
- table.insert(costumesOwned, {
- costume.Name,
- Stats.GetStat(args[1], costume.Req.Value)>0,
- costume:FindFirstChild("Image") and "rbxassetid://"..costume.Image.Value or "rbxassetid://792921119"
- })
- end
- return #costumesOwned>1 and costumesOwned or nil -- if no costumes exist, return nothing
- else
- return nil
- end
- end
- PASTE END
- You can edit the images for the default costume and the misc image to your liking!
- 9. Happy costuming! The system is fully implemented. Thank you for following my guide, and I hope you likI HOPE YOU LIKE IT!!!!!!!!!!!!!!! THANKS FOR COMING
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement