Advertisement
g14ndev

Updated Spin Handler Module for Animal's RNG

Apr 7th, 2024 (edited)
231
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 18.11 KB | Gaming | 0 0
  1. --*This is a spin handler module for a RNG animal game.* --
  2. -- formatting looks off due to pastebin's formatting i dont actually format my code like how pastebin shows --
  3. -- Author: Gixnly ---
  4. local RS = game:GetService("ReplicatedStorage") -- refrence replicated storage
  5. local remotes = RS:WaitForChild("Remotes") -- refrence remotes folder
  6. local Animals = RS:WaitForChild("Animals") -- refrence animals folder
  7. local animalHandler = require(script.Parent.AnimalHandler) -- require animal handler module
  8. local serverScriptService = game:GetService("ServerScriptService") -- refrence server script service
  9. local dataManager = require(serverScriptService:WaitForChild("Modules"):WaitForChild("DataManager")) -- require  data manager module
  10.  
  11. local SpinHandler = {} -- initialize table for this module.
  12.  
  13. -- chose a random animal
  14. function SpinHandler.ChooseAnimal(animals: Folder)
  15.     local animalChildren = animals:GetChildren() -- get a table of animals children
  16.     table.sort(animalChildren, function(a, b) return a.Chance.Value < b.Chance.Value end) -- sort the table based on the children's chance value (lowest to highest)
  17.     local totalEntries = 0 -- initialize entry variable
  18.     -- calculate total entries  for probability calculation
  19.     for _, animal in pairs(animalChildren) do
  20.         totalEntries += 1 / animal.Chance.Value
  21.     end
  22.     local randomEntry = math.random() -- generate a random number between 0 and 1
  23.     local cumulativeEntry = 0 -- initialize cumulativeEntry variable
  24.     local cumulativeEntryForFullRange = 0 -- initialize cumulativeEntryForFullRange variable (used in later calculations to view the cumulative ranges)
  25.     local previousCumulativeEntry = 0 -- initialize previousCumulatievEntry Variable (used so we can see in what range the selected animal was found in)
  26.     local previousCumulativeEntryForFullRange = 0 -- initialize previousCumulativeEntryForFullRange variable (used so we can see the cumulative ranges of each animal without having to return)
  27.     -- Loop through each animal to show the developer the cumuative ranges of each animal
  28.     for _, animal in pairs(animalChildren) do
  29.         previousCumulativeEntryForFullRange = cumulativeEntryForFullRange -- store previous cumulative entry in order to show the range.
  30.         cumulativeEntryForFullRange += 1/ animal.Chance.Value / totalEntries
  31.         -- Calculate the cumulative entry for the current animal by dividing 1 by its chance value and then dividing it by the total entries
  32.         -- This effectively determines the range of probabilities for each animal, ensuring that the sum of all probabilities equals 1
  33.         print(animal.Name.."'s cumulative entry range is: ",tostring(previousCumulativeEntryForFullRange).." to "..tostring(cumulativeEntryForFullRange)) -- print the ranges for the developer to see.
  34.     end
  35.     print("Random number generated is: "..tostring(randomEntry)) -- print the random number for the developer to see.
  36.     for _, animal in pairs(animalChildren) do
  37.         previousCumulativeEntry = cumulativeEntry -- store previous cumulative entry in order to show the range.
  38.         cumulativeEntry += 1/ animal.Chance.Value / totalEntries
  39.         -- Calculate the cumulative entry for the current animal by dividing 1 by its chance value and then dividing it by the total entries
  40.         -- This effectively determines the range of probabilities for each animal, ensuring that the sum of all probabilities equals 1
  41.         print(animal.Name.."'s cumulative entry range is: ",tostring(previousCumulativeEntry).." to "..tostring(cumulativeEntry)) -- print range
  42.         if randomEntry <= cumulativeEntry then -- if the random number falls inside the range then we select the animal that has that range
  43.             print("Random number found in: ",animal.Name,"'s range") -- notify developer of selection
  44.             return animal.Name -- return the animal's name to be used to find said animal in later code
  45.         end
  46.     end
  47. end
  48. -- choose a random animal with double the luck
  49. function SpinHandler.DoubleLuckChooseAnimal(animals: Folder)
  50.     print("Double luck spun") -- print statements for the developer
  51.     local animalChildren = animals:GetChildren() -- get a table of animals children
  52.     table.sort(animalChildren, function(a, b) return a.Chance.Value < b.Chance.Value end) -- sort the table based on the children's chance value (lowest to highest)
  53.     local totalEntries = 0 -- initialize entry variable
  54.     -- calculate total entries  for probability calculation
  55.     for _, animal in pairs(animalChildren) do
  56.         totalEntries += 1 / animal.Chance.Value
  57.     end
  58.     -- generate a random number twice hence giving the player double the luck
  59.     local randomEntry1 = math.random()
  60.     local randomEntry2 = math.random()
  61.     -- assigning random entry to the highest of both random numbers hence giving the player a higher chance of getting a rare animal
  62.     local randomEntry = math.max(randomEntry1, randomEntry2)
  63.     local cumulativeEntry = 0 -- initialize cumulativeEntry variable
  64.     local cumulativeEntryForFullRange = 0 -- initialize cumulativeEntryForFullRange variable (used in later calculations to view the cumulative ranges)
  65.     local previousCumulativeEntry = 0 -- initialize previousCumulatievEntry Variable (used so we can see in what range the selected animal was found in)
  66.     local previousCumulativeEntryForFullRange = 0 -- initialize previousCumulativeEntryForFullRange variable (used so we can see the cumulative ranges of each animal without having to return)
  67.     -- Loop through each animal to show the developer the cumuative ranges of each animal
  68.     for _, animal in pairs(animalChildren) do
  69.         previousCumulativeEntryForFullRange = cumulativeEntryForFullRange -- store previous cumulative entry in order to show the range.
  70.         cumulativeEntryForFullRange += 1/ animal.Chance.Value / totalEntries
  71.         -- Calculate the cumulative entry for the current animal by dividing 1 by its chance value and then dividing it by the total entries
  72.         -- This effectively determines the range of probabilities for each animal, ensuring that the sum of all probabilities equals 1
  73.         print(animal.Name.."'s cumulative entry range is: ",tostring(previousCumulativeEntryForFullRange).." to "..tostring(cumulativeEntryForFullRange)) -- print the ranges for the developer to see.
  74.     end
  75.     print("Random number generated is: "..tostring(randomEntry)) -- print the random number for the developer to see.
  76.     for _, animal in pairs(animalChildren) do
  77.         previousCumulativeEntry = cumulativeEntry -- store previous cumulative entry in order to show the range.
  78.         cumulativeEntry += 1/ animal.Chance.Value / totalEntries
  79.         -- Calculate the cumulative entry for the current animal by dividing 1 by its chance value and then dividing it by the total entries
  80.         -- This effectively determines the range of probabilities for each animal, ensuring that the sum of all probabilities equals 1
  81.         print(animal.Name.."'s cumulative entry range is: ",tostring(previousCumulativeEntry).." to "..tostring(cumulativeEntry)) -- print range
  82.         if randomEntry <= cumulativeEntry then -- if the random number falls inside the range then we select the animal that has that range
  83.             print("Random number found in: ",animal.Name,"'s range")-- notify developer of selection
  84.             return animal.Name -- return the animal's name to be used to find said animal in later code
  85.         end
  86.     end
  87. end
  88. function SpinHandler.GiveAnimalInSpin(selectedAnimal: string) -- returns a specific name of a animal to simulate spinning it.
  89.     return selectedAnimal
  90. end
  91. function SpinHandler.GiveAnimalToPlayer(selectedAnimal: string,player: string) -- take animal name as string and player name
  92.     player = game:GetService("Players"):FindFirstChild(player) -- try to find the player by their name.
  93.     if not player then warn("Player not found in give animal to player, Type:",typeof(player)) return end -- return if player wasnt found and also state the type of the value not found
  94.     if not player.PlayerAnimals:FindFirstChild(selectedAnimal) and Animals:FindFirstChild(selectedAnimal) then -- if they dont have the animal and the animal is in game then give it to them
  95.         local animalString = Instance.new("StringValue",player.PlayerAnimals) -- create string value
  96.         animalString.Name = selectedAnimal -- set its name and value to selectedAnimal
  97.         animalString.Value = selectedAnimal
  98.         print("Successfully gave",selectedAnimal,"to",player.Name.."'s inventory") -- tell the developer that the action was a success.
  99.     else
  100.         warn("Attempted to give "..selectedAnimal.." to "..player.Name,"action failed") -- an error occured; warn the developer
  101.     end
  102. end
  103. function SpinHandler.RemoveAnimalFromPlayer(selectedAnimal: string,player: string) -- take animal name as a string and player instance
  104.     player = game:GetService("Players"):FindFirstChild(player)
  105.     if not player then warn("Player not found in remove animal from player, Type:",typeof(player)) return end -- return if the player wasnt found and also state the type of the value not found
  106.     if player.PlayerAnimals:FindFirstChild(selectedAnimal) then -- if the player has that animal then destroy it
  107.         player.PlayerAnimals:FindFirstChild(selectedAnimal):Destroy()
  108.         print("Successfully removed",selectedAnimal,"from",player.Name.."'s inventory")
  109.     else
  110.         warn("Attempted to remove "..selectedAnimal.." to "..player.Name,"action failed") -- an error occured therefore warn developer
  111.     end
  112. end
  113. function SpinHandler.Spin(player: Player) -- take the player as an argument in order to access many of the players values/gui
  114.     local db = true -- debounce in order to prevent unwanted double creation of animals or any other unwanted issue.
  115.     local selectedAnimal -- initialize selected animal function
  116.     if player:WaitForChild("Double Luck").Value == true then -- check if the player has double luck on.
  117.         selectedAnimal = SpinHandler.DoubleLuckChooseAnimal(Animals) -- if they do fire the doubleluck function
  118.     else -- else use the regular luck function.
  119.         selectedAnimal = SpinHandler.ChooseAnimal(Animals)
  120.     end
  121.     print(selectedAnimal.." was chosen in spin") -- immediately print the selected animals name, makes it easier to debug later code.
  122.     local playerGui = player.PlayerGui -- get the player's gui
  123.     local spinFrame = playerGui.SpinUI.SpinFrame -- get the spin frame
  124.     local loopCount = 0 -- initialize loop count (used for visually spinning)
  125.     local waitTime = 0.15 -- wait time inbetween spins (the spin animation loops through the animals table and shows random animals until finally showing the chosen one)
  126.     local skipConnection -- initialize a connection variable for the skip button of the spin frame
  127.     local equipConnection -- initialiE a connection variable for the equip button of the spin frame
  128.     playerGui.SpinUI.SpinButton.Visible = false -- turn the spin button invisible
  129.     playerGui.SpinUI.DoubleLuckButton.Visible = false -- turn the double luck button invisible
  130.     spinFrame.Visible = true -- turn the spin frame visible
  131.     spinFrame.AnimalChance.Text = "" -- immediatley put the animal chance text and animal unlocked text to empty strings (they have placeholder text so the developer could edit the ui easily)
  132.     spinFrame.AnimalUnlocked.Text = ""
  133.     spinFrame.SkipButton.Visible = false -- make sure the skip button isnt visible
  134.     spinFrame.EquipButton.Visible = false -- make sure the skip button isnt visible
  135.     for i, v in pairs(playerGui.AnimalInventory:GetChildren()) do -- turn off all other gui's
  136.         if v:IsA("GuiBase") then
  137.             if v.Visible == true then
  138.                 v.Visible = false
  139.             end
  140.  
  141.         end
  142.     end
  143.     local profile = dataManager.Profiles[player] -- getting player's profile
  144.     if not profile then return end -- if profile doesnt exist return immediately
  145.     profile.Data.Spins += 1 -- increment spins data by 1
  146.     player.leaderstats.Spins.Value = profile.Data.Spins -- update leaderstats to visually show spins data
  147.     repeat -- reapeat loop for spinning animation
  148.         loopCount += 1 -- increment loop count
  149.         task.wait(waitTime) -- initialize a wait in order to prevent instant text change.
  150.         local randomAnimal = math.round(math.random(1, #Animals:GetChildren())) -- select a random animal from the animals folder
  151.         spinFrame.AnimalUnlocked.Text = Animals:GetChildren()[randomAnimal].Name -- chance animal unlicked text to the animals name
  152.         spinFrame.AnimalUnlocked.TextColor3 = Animals:GetChildren()[randomAnimal].Highlight.OutlineColor -- change the animal unlocked text color to the highlight color of the animal
  153.         spinFrame.AnimalChance.Text = "" -- again making sure the chance text is not visible (an empty string)
  154.         remotes.SpinningForAnimal:FireClient(player) -- fire a remote on the client to play a "tick" sound for each rotation
  155.         -- Gradually increase wait time to slow down the loop if we have passed the half way point of the loop
  156.         if loopCount >= 15 then
  157.             waitTime = waitTime + 0.05
  158.         end
  159.     until loopCount >= 30 -- stop loop once loopCount has reached or surpassed 30.
  160.     spinFrame.AnimalUnlocked.Text = selectedAnimal -- show the animal unlocked text as the selected animal
  161.     spinFrame.AnimalUnlocked.TextColor3 = Animals[selectedAnimal].Highlight.OutlineColor -- change the color to the highlight color of the animal
  162.     local chance =  Animals:FindFirstChild(selectedAnimal).Chance.Value -- get the chance value of the animal
  163.     if chance >= Animals["Mad Cow"].Chance.Value then -- this is specifically for a animal that has a "one in zero" chance since we programattically cannot have a 0 chance we make it close to 0 by having a large number
  164.         spinFrame.AnimalChance.Text = "1 in "..tostring(0) -- chance the animal chance text to the text seen.
  165.     else -- if chance isnt at mad cow's level then simply put the animal chance text to "1 in "..the animals chance
  166.         spinFrame.AnimalChance.Text = "1 in "..tostring(chance)
  167.     end
  168.     spinFrame.AnimalChance.TextColor3 = Animals[selectedAnimal].Highlight.OutlineColor -- chance the animal chance text color to the animals highlight color
  169.     spinFrame.SkipButton.Visible = true -- turn the skip equip buttons visible
  170.     spinFrame.EquipButton.Visible = true
  171.     skipConnection = spinFrame.SkipButton.MouseButton1Click:Once(function() -- initialize a "Once" connection to the click event of the skip button
  172.         print("skip button pressed") -- debug print statements for the developer
  173.         if not player.PlayerAnimals:FindFirstChild(selectedAnimal) and db then -- check if the player's "player animals" already has the selected animal
  174.             db = false -- put db to false to prevent cloning
  175.             -- since the player passed the if statment that means they must not have the animal selected
  176.             local animalString = Instance.new("StringValue",player.PlayerAnimals) -- create a string value and add it to the player's player animals
  177.             animalString.Name = selectedAnimal -- set the string name to the selected animal and also set its value to the selected animal
  178.             animalString.Value = selectedAnimal
  179.             task.delay(1,function() -- delay resetting the debounce
  180.                 db = true
  181.             end)
  182.         end
  183.         task.wait() -- small wait before turning the skip and equip buttons invisible
  184.         spinFrame.SkipButton.Visible = false
  185.         spinFrame.EquipButton.Visible = false
  186.         spinFrame.Visible = false -- turn the spin frame invisible
  187.         task.wait(0.5) -- wait half a second before turning the spin button visible
  188.         playerGui.SpinUI.SpinButton.Visible = true
  189.         playerGui.SpinUI.DoubleLuckButton.Visible = true
  190.         for i, v in pairs(playerGui.AnimalInventory:GetChildren()) do -- turn all the guis that arent the specific guis named from invisble to visible
  191.             if v:IsA("GuiBase")  then
  192.                 if v.Visible == false and v.Name ~= "AnimalsFrame" or v.Name ~= "UnequipButton"  then
  193.                     v.Visible = true
  194.                 end
  195.                 if v.Visible == true and v.Name ~= "InventoryButton" then -- a debug if statement in order to prevent the guis from still being visible and to also only turn the inventory button visible
  196.                     v.Visible = false
  197.                 end
  198.  
  199.             end
  200.         end
  201.         skipConnection:Disconnect() -- disconnect the connection
  202.         skipConnection = nil -- set connection to nil
  203.         selectedAnimal = nil -- set selected animal to nil to prevent unwanted behaviour
  204.         print("skip button disconnected selected animal disconnected") -- print statement for the developer
  205.         return -- immediately return out of the function
  206.     end)
  207.     equipConnection = spinFrame.EquipButton.MouseButton1Click:Once(function() -- initialize a 'Once connection for the equip button click event'
  208.         print("equip button pressed") -- print statement for the developer
  209.         if typeof(selectedAnimal) == "nil" then print("selected animal was attempted to be fired again.") return end -- if selected animal is nil (aka we already skipped and for some reason the equip button was clicked after we skipped) then immediatley return
  210.         if not player.PlayerAnimals:FindFirstChild(selectedAnimal) and db then -- if the selected animal was not already in the player's player animals
  211.             db = false -- set db to false to prevent cloning
  212.             -- if the animal wasnt found that indeed means the player does not have it already.
  213.             local animalString = Instance.new("StringValue",player.PlayerAnimals) -- create string value and parent it to the player's player animals
  214.             animalString.Name = selectedAnimal -- set the string's name and value to the selected animal
  215.             animalString.Value = selectedAnimal
  216.             animalHandler.EquipAnimal(player,player.Character,selectedAnimal) -- equip the animal using the animals handler module
  217.             task.delay(1,function() -- delay resetting the debounce
  218.                 db = true
  219.             end)
  220.         elseif db then
  221.             db = false -- set db to false to prevent double equips
  222.             animalHandler.EquipAnimal(player,player.Character,selectedAnimal) -- equip animal because they already have it
  223.             task.delay(1,function()-- delay resetting the debounce
  224.                 db = true
  225.             end)
  226.         end
  227.         print(spinFrame:GetChildren()," spin frame children, from equip button") -- debung print statement for the developer
  228.         task.wait() -- small wait
  229.         spinFrame.Visible = false -- turn spin frame invisible
  230.         task.wait(0.5) -- wait half a second before turning the spin button visible
  231.         playerGui.SpinUI.SpinButton.Visible = true
  232.         playerGui.SpinUI.DoubleLuckButton.Visible = true
  233.         equipConnection:Disconnect() -- disconnect both the skip and equip connections
  234.         skipConnection:Disconnect()
  235.         equipConnection = nil -- set connections to nil and set selected animal to nil
  236.         skipConnection = nil
  237.         selectedAnimal = nil
  238.         print("equip button disconnected selected animal disconnected") -- print statement for the develop
  239.         return -- return out of function
  240.     end)
  241. end
  242.  
  243. return SpinHandler -- return spin handler
  244.  
Tags: Roblox
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement