Advertisement
IHATEMICROWAVEOVEN

pa costume system implementation guide

Dec 22nd, 2023 (edited)
120
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.70 KB | None | 0 0
  1. How to implement my PA Costume System!!! (as of 12/22/23)
  2.  
  3. Reminders for after you read this guide:
  4. - Edit the Leaderboard object parented to GameGui to your liking
  5. - Remember to make it so when you click the Leaderboard button, it runs UpdateCostumes() (edit to LocalScript)
  6. - - - (by default, it runs UpdateLeaderboard(), so you can ctrl f for that)
  7. - Remember to make "Costumes" not detected by the evolution-detecting algorithm (edit to LocalScript)
  8. - Be wary of mechanics that evolve the player automatically (e.g. Palafin, and de-megaing).
  9. - - - Well, you only need to be wary of having a costume accessible by 1 form but not the other.
  10. - - - If the user has the costumes panel open during the evo, then they can cause an error by turning into a nonexistent morph.
  11. - - - The costumes panel is coded not to function when evolution takes place, so that edge case is avoided.
  12. - VERY VERY IMPORTANT NOTICE RELATED TO THE ABOVE BULLET BUT PLEASE READ
  13. - AGAIN VERY IMPORTANT
  14. - AGAIN VERY IMPORTANT OK READ IT NOW
  15. - - - Keep in mind that the costumes panel auto-disables by checking SLP. You should keep this in mind when designing the panel.
  16.  
  17.  
  18. What is the architecture?
  19. This is explained in the image attached externally.
  20. However, if you are a random person who found this suddenly:
  21. - Under each Pokemon for which you hope to give a costume to, create a folder called Costumes.
  22. - Inside the Costumes folder, create folders named after the costumes. For example, "Classic" (no quotes... or els
  23. - Inside each of these folders, create two StringValues:
  24. - - - One is named "Req". This is not optional. Type the stat required for using the costume as the Value.
  25. - - - - - (The req is not displayed to the player, so feel free to use ridiculous stat names!)
  26. - - - One is named "Image". This is optional. Type the number ID of the image that is displayed for the costume.
  27. - - - - - (If this doesn't exist, a ? will be substituted in its place (you can change this in the GetCostumes conditional)
  28. - This will set it up correctly.
  29.  
  30.  
  31.  
  32. Code to insert:
  33.  
  34.  
  35. 1. In ServerScriptService > Stats > StarterData, add this as a stat:
  36. PASTE BEGIN
  37. ["EquippedCostume"] = {
  38. ["Permament"] = false;
  39. ["DefaultValue"] = "";
  40. ["Special"] = nil
  41. }
  42. PASTE END
  43. Furthermore, ensure that it is made to reset on spawn.
  44. So, change the dictionary at the bottom of StarterData and also in ServerHandler > Settings.
  45. The default costume is stored simply as "" (a length 0 string).
  46.  
  47.  
  48. 2. In big LocalScript, do ctrl+f "UpdateLeaderboard". Insert this directly underneath its end:
  49. PASTE BEGIN
  50. local function UpdateCostumes()
  51.  
  52. if CallServer("GetStat", "SLP") == 1 then return end
  53.  
  54. -- Creates a Frame that represents a row: ImageLabel on the left, TextButton on the right
  55. local function createText(num, imageID)
  56. print(imageID)
  57. local frame = Instance.new("Frame")
  58. frame.Position, frame.Size =
  59. UDim2.new(0, 0, (num - 1) * 0.1, 0), UDim2.new(1, 0, 0.1, 0)
  60. frame.BackgroundColor3, frame.BorderColor3, frame.BorderSizePixel =
  61. Color3.new(61/255, 61/255, 61/255), Color3.new(0,0,0), 2
  62. local height = script.Parent.Leaderboard.Frame.AbsoluteSize.Y*0.1 -- used to make image square and displace text accordingly
  63. height = 36.59 -- oops
  64. local width = 619.2 -- oops 2
  65. local image = Instance.new("ImageLabel")
  66. image.Position, image.Size, image.BackgroundTransparency, image.Image =
  67. UDim2.new(0, 0, 0, 0), UDim2.new(0, height, 1, 0), 1, imageID
  68. image.Parent = frame
  69. local textbutton = Instance.new("TextButton")
  70. textbutton.BackgroundTransparency, textbutton.Position, textbutton.Size =
  71. 1, UDim2.new(0,height,0,0), UDim2.new(0, width-height, 1, 0)
  72. textbutton.TextColor3, textbutton.TextScaled, textbutton.Font =
  73. Color3.new(1,1,1), true, Enum.Font.ArialBold
  74. textbutton.Parent = frame
  75. frame.Parent = script.Parent.Leaderboard.Frame
  76. return textbutton
  77. end
  78.  
  79. do
  80. local cCostume = CallServer("GetStat", "EquippedCostume")
  81. script.Parent.Leaderboard.Points.Text = "Equipped Costume: "..tostring(cCostume~="" and cCostume or "Default (No Costume)")
  82. end
  83.  
  84. for _, i in pairs(script.Parent.Leaderboard.Frame:GetChildren()) do
  85. i:Destroy()
  86. end
  87. local pages = CallServer("GetCostumes")
  88. if pages ~= nil then
  89. local debounce = false
  90. for i, haveAndImage in pairs(pages) do
  91. --[[
  92. haveAndImage is an array that contains:
  93. 1: costume's name as a string
  94. 2: whether or not the user has the required item for the costume
  95. 3: the image of the costume, in form "rbxassetid://[idnumber]"" ]]
  96. print(i..": ")
  97. print(haveAndImage[1])
  98. print(haveAndImage[2])
  99. print(haveAndImage[3])
  100. print()
  101. local theTextButton = createText(i, haveAndImage[3])
  102. if haveAndImage[2] then
  103. theTextButton.Text = haveAndImage[1].." (Owned)"
  104. local onClick onClick = theTextButton.MouseButton1Down:Connect(function()
  105. if CallServer("GetStat", "SLP") == 1 then onClick:Disconnect() return end
  106. if not debounce then
  107. debounce = true
  108. CallServer("ChangeCostumeMode", haveAndImage[1]=="Default (No Costume)" and "" or haveAndImage[1])
  109. UpdateCostumes()
  110. debounce = false
  111. end
  112. end)
  113. else
  114. theTextButton.Text = haveAndImage[1].." (Not Owned ❌)"
  115. end
  116. end
  117. else
  118. local theTextButton = createText(1, "rbxassetid://15709415914")
  119. theTextButton.Text = "No costumes...yet!"
  120. end
  121.  
  122. end
  123. PASTE END
  124.  
  125.  
  126. 3. In ServerScriptService > ServerHandler, find the ScanForPokes function and change this:
  127. LOOK-AT-THIS BEGIN
  128. if i:IsA'Folder' and i.Name ~= "SetStatsOnSpawn" and i.Name ~= "Weapons" and i.Name ~= "Spawns" then
  129. LOOK-AT-THIS END
  130. ...into this:
  131. PASTE BEGIN
  132. if i:IsA'Folder' and i.Name ~= "SetStatsOnSpawn" and i.Name ~= "Weapons" and i.Name ~= "Spawns" and i.Name ~= "Costumes" then
  133. PASTE END
  134. (This makes sure the game doesn't mistake the Costumes folder for a Pokemon.)
  135.  
  136.  
  137. 4. In ServerHandler, insert this to replace the "local Morph" line at the top of the MegaEvolve conditional statement:
  138. PASTE BEGIN
  139. local Morph
  140. do
  141. local equipped = Stats.GetStat(args[1], "EquippedCostume")
  142. if equipped ~="" then
  143. if script.Pokemon[Name]:FindFirstChild("Costumes") and
  144. script.Pokemon[Name].Costumes:FindFirstChild(equipped) and
  145. Stats.GetStat(args[1], script.Pokemon[Name].Costumes[equipped].Req.Value)>0 then
  146. Morph = game.ServerStorage.MegaMorphs:FindFirstChild(Name.." ("..equipped..")")
  147. else
  148. Morph = game.ServerStorage.MegaMorphs:FindFirstChild(Name)
  149. Stats.SetStat(args[1], "EquippedCostume", "")
  150. end
  151. else
  152. Morph = game.ServerStorage.MegaMorphs:FindFirstChild(Name)
  153. Stats.SetStat(args[1], "EquippedCostume", "")
  154. end
  155. end
  156. PASTE END
  157.  
  158.  
  159. 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:
  160. PASTE BEGIN
  161. do
  162. local equipped = Stats.GetStat(args[1], "EquippedCostume")
  163. if equipped ~="" then
  164. if script.Pokemon[Name]:FindFirstChild("Costumes") and
  165. script.Pokemon[Name].Costumes:FindFirstChild(equipped) and
  166. Stats.GetStat(args[1], script.Pokemon[Name].Costumes[equipped].Req.Value)>0 then
  167. Morph = game.ServerStorage.Morphs:FindFirstChild(Name.." ("..equipped..")")
  168. else
  169. Morph = game.ServerStorage.Morphs:FindFirstChild(Name)
  170. Stats.SetStat(args[1], "EquippedCostume", "")
  171. end
  172. else
  173. Morph = game.ServerStorage.Morphs:FindFirstChild(Name)
  174. Stats.SetStat(args[1], "EquippedCostume", "")
  175. end
  176. end
  177. PASTE END
  178.  
  179.  
  180. 6. In ServerHandler, put this at the VERY VERY top of the SpawnPokemon conditional statement:
  181. PASTE BEGIN
  182. Stats.SetStat(args[1], "EquippedCostume", "")
  183. PASTE END
  184. This is done to simply cover our bases.
  185.  
  186.  
  187. 7. In ServerHandler, add the following conditional statement. I suggest removing all wardrobe-related text.
  188. PASTE BEGIN
  189. elseif args[2] == "ChangeCostumeMode" then
  190.  
  191. if Stats.GetStat(args[1], "EquippedCostume")==args[3] then return end
  192.  
  193. local TweenService = game:GetService("TweenService")
  194. local wardrobe = game.ServerStorage.Items.Wardrobe:Clone()
  195. Stats.SetStat(args[1], "SLP", 1)
  196. Stats.SetStat(args[1], "EquippedCostume", args[3])
  197.  
  198. for i, part in pairs(wardrobe:GetChildren()) do part.Transparency=1 part.CanCollide=false part.Anchored=false part.Massless=true end
  199. wardrobe:PivotTo(args[1].Character.Torso.CFrame*CFrame.new(0, 6.5, 0))
  200. local weld = Instance.new("WeldConstraint")
  201. weld.Part0, weld.Part1 = wardrobe.PrimaryPart, args[1].Character.HumanoidRootPart
  202. weld.Parent = wardrobe.PrimaryPart
  203. for i, part in pairs(wardrobe:GetChildren()) do TweenService:Create(part, TweenInfo.new(0.3), {Transparency = 0}):Play() end
  204. wardrobe.Parent = workspace
  205. task.wait(0.4)
  206.  
  207. args[1].Character:FindFirstChild("Arm1"):Destroy()
  208. args[1].Character:FindFirstChild("Arm2"):Destroy()
  209. args[1].Character:FindFirstChild("Leg1"):Destroy()
  210. args[1].Character:FindFirstChild("Leg2"):Destroy()
  211. args[1].Character:FindFirstChild("Chest"):Destroy()
  212.  
  213. -- CREATING NEW CHARACTER
  214.  
  215. local costumeSuffix = ""
  216. if Stats.GetStat(args[1], "EquippedCostume")~="" then
  217. costumeSuffix = " ("..Stats.GetStat(args[1], "EquippedCostume")..")"
  218. end
  219. local Morph = game.ServerStorage.Morphs:FindFirstChild(Stats.GetStat(args[1], "Current_Pokemon")..costumeSuffix)
  220. if not Morph then
  221. Morph = game.ServerStorage.MegaMorphs:FindFirstChild(Stats.GetStat(args[1], "Current_Pokemon")..costumeSuffix)
  222. end
  223. if not Morph then
  224. print("Costume \""..args[3].."\" doesn't exist on "..Stats.GetStat(args[1], "Current_Pokemon").."? From "..args[1])
  225. return
  226. end
  227.  
  228. do
  229. -- welding (feel free to collapse)
  230. local Char = args[1].Character
  231. if Char:findFirstChild("Humanoid") ~= nil and Char:findFirstChild("Arm1") == nil then
  232. local g = Morph.Arm1:clone()
  233. g.Parent = Char
  234. local C = g:GetChildren()
  235. for i=1, #C do
  236. if C[i].className == "Part" or "UnionOperation" then
  237. local W = Instance.new("Weld")
  238. W.Part0 = g.Middle
  239. W.Part1 = C[i]
  240. local CJ = CFrame.new(g.Middle.Position)
  241. local C0 = g.Middle.CFrame:inverse()*CJ
  242. local C1 = C[i].CFrame:inverse()*CJ
  243. W.C0 = C0
  244. W.C1 = C1
  245. W.Parent = g.Middle
  246. end
  247. local Y = Instance.new("Weld")
  248. Y.Part0 = Char["Left Arm"]
  249. Y.Part1 = g.Middle
  250. Y.C0 = CFrame.new(0, 0, 0)
  251. Y.Parent = Y.Part0
  252. end
  253.  
  254. local h = g:GetChildren()
  255. for i = 1, # h do
  256. h[i].Anchored = false
  257. h[i].CanCollide = false
  258. end
  259.  
  260. end
  261.  
  262.  
  263. if Char:findFirstChild("Humanoid") ~= nil and Char:findFirstChild("Arm2") == nil then
  264. local g = Morph.Arm2:clone()
  265. g.Parent = Char
  266. local C = g:GetChildren()
  267. for i=1, #C do
  268. if C[i].className == "Part" or "UnionOperation" then
  269. local W = Instance.new("Weld")
  270. W.Part0 = g.Middle
  271. W.Part1 = C[i]
  272. local CJ = CFrame.new(g.Middle.Position)
  273. local C0 = g.Middle.CFrame:inverse()*CJ
  274. local C1 = C[i].CFrame:inverse()*CJ
  275. W.C0 = C0
  276. W.C1 = C1
  277. W.Parent = g.Middle
  278. end
  279. local Y = Instance.new("Weld")
  280. Y.Part0 = Char["Right Arm"]
  281. Y.Part1 = g.Middle
  282. Y.C0 = CFrame.new(0, 0, 0)
  283. Y.Parent = Y.Part0
  284. end
  285.  
  286. local h = g:GetChildren()
  287. for i = 1, # h do
  288. h[i].Anchored = false
  289. h[i].CanCollide = false
  290. end
  291.  
  292. end
  293.  
  294. if Char:findFirstChild("Humanoid") ~= nil and Char:findFirstChild("Leg1") == nil then
  295. local g = Morph.Leg1:clone()
  296. g.Parent = Char
  297. local C = g:GetChildren()
  298. for i=1, #C do
  299. if C[i].className == "Part" or "UnionOperation" then
  300. local W = Instance.new("Weld")
  301. W.Part0 = g.Middle
  302. W.Part1 = C[i]
  303. local CJ = CFrame.new(g.Middle.Position)
  304. local C0 = g.Middle.CFrame:inverse()*CJ
  305. local C1 = C[i].CFrame:inverse()*CJ
  306. W.C0 = C0
  307. W.C1 = C1
  308. W.Parent = g.Middle
  309. end
  310. local Y = Instance.new("Weld")
  311. Y.Part0 = Char["Left Leg"]
  312. Y.Part1 = g.Middle
  313. Y.C0 = CFrame.new(0, 0, 0)
  314. Y.Parent = Y.Part0
  315. end
  316.  
  317. local h = g:GetChildren()
  318. for i = 1, # h do
  319. h[i].Anchored = false
  320. h[i].CanCollide = false
  321. end
  322.  
  323. end
  324.  
  325. if Char:findFirstChild("Humanoid") ~= nil and Char:findFirstChild("Leg2") == nil then
  326. local g = Morph.Leg2:clone()
  327. g.Parent = Char
  328. local C = g:GetChildren()
  329. for i=1, #C do
  330. if C[i].className == "Part" or "UnionOperation" then
  331. local W = Instance.new("Weld")
  332. W.Part0 = g.Middle
  333. W.Part1 = C[i]
  334. local CJ = CFrame.new(g.Middle.Position)
  335. local C0 = g.Middle.CFrame:inverse()*CJ
  336. local C1 = C[i].CFrame:inverse()*CJ
  337. W.C0 = C0
  338. W.C1 = C1
  339. W.Parent = g.Middle
  340. end
  341. local Y = Instance.new("Weld")
  342. Y.Part0 = Char["Right Leg"]
  343. Y.Part1 = g.Middle
  344. Y.C0 = CFrame.new(0, 0, 0)
  345. Y.Parent = Y.Part0
  346. end
  347.  
  348. local h = g:GetChildren()
  349. for i = 1, # h do
  350. h[i].Anchored = false
  351. h[i].CanCollide = false
  352. end
  353.  
  354. end
  355. if Char:findFirstChild("Humanoid") ~= nil and Char:findFirstChild("Chest") == nil then
  356. local g = Morph.Chest:clone()
  357. g.Parent = Char
  358. local C = g:GetChildren()
  359. local R = Char:GetChildren()
  360. for i=1, #R do
  361. if R[i].className == "Hat" then
  362. R[i]:remove()
  363. end
  364. end
  365. for i=1, #C do
  366. if C[i].className == "Part" or "UnionOperation" then
  367. local W = Instance.new("Weld")
  368. W.Part0 = g.Middle
  369. W.Part1 = C[i]
  370. local CJ = CFrame.new(g.Middle.Position)
  371. local C0 = g.Middle.CFrame:inverse()*CJ
  372. local C1 = C[i].CFrame:inverse()*CJ
  373. W.C0 = C0
  374. W.C1 = C1
  375. W.Parent = g.Middle
  376. end
  377. local Y = Instance.new("Weld")
  378. Y.Part0 = Char.Torso
  379. Y.Part1 = g.Middle
  380. Y.C0 = CFrame.new(0, 0, 0)
  381. Y.Parent = Y.Part0
  382. end
  383.  
  384. local h = g:GetChildren()
  385. for i = 1, # h do
  386. h[i].Anchored = false
  387. h[i].CanCollide = false
  388. end
  389. end
  390. end
  391.  
  392. wardrobe:PivotTo(wardrobe:GetPivot()*CFrame.Angles(0, 0, math.rad(-30)))
  393. task.wait(0.2)
  394.  
  395. for i = 1, 4 do
  396. wardrobe:PivotTo(wardrobe:GetPivot()*CFrame.Angles(0, 0, math.rad(60)))
  397. task.wait(0.2)
  398. wardrobe:PivotTo(wardrobe:GetPivot()*CFrame.Angles(0, 0, math.rad(-60)))
  399. task.wait(0.2)
  400. end
  401.  
  402. wardrobe:PivotTo(wardrobe:GetPivot()*CFrame.Angles(0, 0, math.rad(30)))
  403. task.wait(0.2)
  404.  
  405. for i, part in pairs(wardrobe:GetChildren()) do TweenService:Create(part, TweenInfo.new(0.3), {Transparency = 1}):Play() end
  406.  
  407. Stats.SetStat(args[1], "SLP", 0)
  408. task.wait(0.6)
  409. wardrobe:Destroy()
  410. PASTE END
  411.  
  412.  
  413. 8. In ServerHandler, add the following conditional statement:
  414. PASTE BEGIN
  415. elseif args[2] == "GetCostumes" then
  416. local cPokemon = Stats.GetStat(args[1], "Current_Pokemon")
  417. if cPokemon ~= nil and string.len(cPokemon)>0 then -- Make sure the player has spawned as a Pokemon
  418. local costumesFolder = script.Pokemon[cPokemon]:FindFirstChild("Costumes")
  419. if costumesFolder then
  420. local costumesOwned = {{"Default (No Costume)", true, "rbxassetid://15709415914"}}
  421. for i, costume in ipairs(costumesFolder:GetChildren()) do
  422. table.insert(costumesOwned, {
  423. costume.Name,
  424. Stats.GetStat(args[1], costume.Req.Value)>0,
  425. costume:FindFirstChild("Image") and "rbxassetid://"..costume.Image.Value or "rbxassetid://792921119"
  426. })
  427. end
  428. return #costumesOwned>1 and costumesOwned or nil -- if no costumes exist, return nothing
  429. else
  430. return nil
  431. end
  432. end
  433. PASTE END
  434. You can edit the images for the default costume and the misc image to your liking!
  435.  
  436.  
  437. 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