Advertisement
Froredion

DanceController

Dec 27th, 2024 (edited)
21
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 18.70 KB | None | 0 0
  1. -- Services
  2. local GuiService = game:GetService("GuiService")
  3. local RunService = game:GetService("RunService")
  4. local ReplicatedStorage = game:GetService("ReplicatedStorage")
  5. local TweenService = game:GetService("TweenService")
  6. local Players = game:GetService("Players")
  7.  
  8. local player = Players.LocalPlayer
  9. local playerGui = player.PlayerGui
  10.  
  11. local favoriteCooldown = 0.5
  12.  
  13. -- Modules
  14. local Knit = require(ReplicatedStorage.Packages.Knit)
  15. local EffectsUtil = require(ReplicatedStorage.SharedSource.Externals.Utilities.Effects)
  16. local OthersUtil = require(ReplicatedStorage.SharedSource.Externals.Utilities.Others)
  17. local FXSoundsUtil = EffectsUtil.Sounds
  18. local FXGuiUtil = EffectsUtil.GUI
  19. local DancesDatas = require(ReplicatedStorage.SharedSource.Datas:WaitForChild("DancesDatas"))
  20. local assets = ReplicatedStorage:WaitForChild("Assets")
  21. local animsDatas = DancesDatas.Animations
  22. local sounds = DancesDatas.Sounds
  23.  
  24. local clickSound = assets.Sounds.Click
  25.  
  26. local DanceGui = playerGui:WaitForChild("DanceGui")
  27. local danceFrame = DanceGui:WaitForChild("DanceFrame")
  28. local danceSearchBar = danceFrame.SearchBar
  29. local danceScroll = danceFrame.DanceScroll
  30. local promptFrame = danceFrame.PromptFrame
  31. local templateButton = assets.GUIs.Dances.DanceButtonTemplate
  32.  
  33. local tweenInfo = TweenInfo.new(0.5, Enum.EasingStyle.Sine, Enum.EasingDirection.Out)
  34.  
  35. local plr = game.Players.LocalPlayer
  36.  
  37. local DanceController = Knit.CreateController({
  38.     Name = "DanceController",
  39.  
  40.     -- other
  41.     CurrentPromptFrame = nil,
  42.     IsPurchaseInProgress = false,
  43.     IsPromptActive = false,
  44.     IsProccessing = false,
  45.     DanceOrder = {},
  46. })
  47.  
  48. ---- Services
  49. local DanceService, ProfileService
  50.  
  51. ---- Controllers
  52. local DataController, WarningsController, GuiController, AnimSoundController
  53.  
  54. local ProfileData
  55. local DancesUnlocked
  56. local favoriteDances
  57.  
  58. function DanceController:FindDancesDataByName(name)
  59.     for i, data in ipairs(DancesDatas.Animations) do
  60.         if data.Name == name then
  61.             return data, i
  62.         end
  63.     end
  64.     for _, data in ipairs(DancesDatas["Gacha Animations"]) do
  65.         if data.Name == name then
  66.             return data
  67.         end
  68.     end
  69.     for _, data in ipairs(DancesDatas["Roblox-Made Animations"]) do
  70.         if data.Name == name then
  71.             return data
  72.         end
  73.     end
  74.     return nil -- Return nil if no match is found
  75. end
  76.  
  77. function DanceController:GetSortedDancesDatas()
  78.     local unlockableDatas = table.clone(DancesDatas["Gacha Animations"])
  79.    
  80.     local unlockedDatas = {}
  81.     local i = 1  -- Initialize the counter
  82.  
  83.     while i <= #DancesDatas.Animations or i <= #DancesDatas["Roblox-Made Animations"] do
  84.         -- Add from Animations if it exists.
  85.         if DancesDatas.Animations[i] then
  86.             table.insert(unlockedDatas, DancesDatas.Animations[i])
  87.         end
  88.  
  89.         -- Add from Roblox-Made Animations if it exists.
  90.         if DancesDatas["Roblox-Made Animations"][i] then
  91.             table.insert(unlockedDatas, DancesDatas["Roblox-Made Animations"][i])
  92.         end
  93.  
  94.         i = i + 1  -- Increment the counter
  95.     end
  96.     local lockedDatas = {}
  97.     for i=1, #unlockableDatas do
  98.         local danceData = unlockableDatas[i]
  99.         if DanceController:IsDanceOwned(danceData.Name) then
  100.             table.insert(unlockedDatas, danceData)
  101.         else
  102.             table.insert(lockedDatas, danceData)
  103.         end
  104.     end
  105.    
  106.     local sortedData = {}
  107.     for i=1,#unlockedDatas do
  108.         table.insert(sortedData, unlockedDatas[i])
  109.     end
  110.     for i=1,#lockedDatas do
  111.         table.insert(sortedData, lockedDatas[i])
  112.     end
  113.    
  114.     local lockedDatasNames = {}
  115.     local unlockedDatasNames = {}
  116.     for i=1,#lockedDatas do
  117.         table.insert(lockedDatasNames, lockedDatas[i].Name)
  118.     end
  119.     for i=1,#unlockedDatas do
  120.         table.insert(unlockedDatasNames, unlockedDatas[i].Name)
  121.     end
  122.    
  123.     return sortedData, unlockedDatasNames, lockedDatasNames
  124. end
  125.  
  126. function DanceController:IsDanceOwned(danceName)
  127.     ProfileData = DataController.Data
  128.     -- update
  129.     DancesUnlocked = DataController.Data.DancesUnlocked
  130.     -- check purchased Dance
  131.     return table.find(ProfileData.DancesUnlocked, danceName)
  132. end
  133.  
  134. function DanceController:IsDanceFavorited(danceName)
  135.     ProfileData = DataController.Data
  136.     -- update
  137.     favoriteDances = DataController.Data.FavoriteDances
  138.     -- check purchased Dance
  139.     return favoriteDances[danceName] == true
  140. end
  141.  
  142. local function SetDanceLayoutOrder(templateClone, danceName, val0, val1)
  143.     local isDanceOwned = DanceController:IsDanceOwned(danceName)
  144.     if isDanceOwned then
  145.         templateClone.LayoutOrder = val0
  146.     else
  147.         templateClone.LayoutOrder = val1
  148.     end
  149. end
  150.  
  151. function DanceController:UpdateOrderDance()
  152.     DanceController.DanceOrder = {}
  153.  
  154.     for danceName, isFavorited in pairs(favoriteDances) do
  155.         if isFavorited then
  156.             table.insert(DanceController.DanceOrder, danceName)
  157.         end
  158.     end
  159.  
  160.     for _, data in pairs(animsDatas) do
  161.         local danceName = data.Name
  162.         if not favoriteDances[danceName] then
  163.             table.insert(DanceController.DanceOrder, danceName)
  164.         end
  165.     end
  166. end
  167.  
  168. function DanceController:ReorderDances()
  169.     for _, danceName in pairs(DanceController.DanceOrder) do
  170.         local isFavorited = DanceController:IsDanceFavorited(danceName)
  171.         local isDanceOwned = DanceController:IsDanceOwned(danceName)
  172.  
  173.         local templateClone = danceScroll:WaitForChild(danceName)
  174.         local favoriteButton = templateClone:WaitForChild("FavoriteButton")
  175.  
  176.         if isFavorited then
  177.             favoriteButton.Image = "rbxassetid://1178571805"
  178.             SetDanceLayoutOrder(templateClone, danceName, -3, -1)
  179.         else
  180.             favoriteButton.Image = "rbxassetid://279798627"
  181.             SetDanceLayoutOrder(templateClone, danceName, -2, 0)
  182.         end
  183.  
  184.         if isDanceOwned then
  185.             templateClone.TextLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
  186.             templateClone.TextLabel.TextTransparency = 0
  187.             if isFavorited then
  188.                 templateClone.LayoutOrder = -3
  189.             else
  190.                 templateClone.LayoutOrder = -2
  191.             end
  192.         else
  193.             templateClone.TextLabel.TextColor3 = Color3.fromRGB(144, 144, 144)
  194.             templateClone.TextLabel.TextTransparency = 0.5
  195.             if isFavorited then
  196.                 templateClone.LayoutOrder = -1
  197.             else
  198.                 templateClone.LayoutOrder = -0
  199.             end
  200.         end
  201.     end
  202. end
  203.  
  204. local function createTemplateClone(template, parent, templateName, text, additionalText, imageId)
  205.     local templateClone = template:Clone()
  206.     templateClone.Name = templateName
  207.     if text then
  208.         templateClone.Text = ""
  209.         if additionalText then
  210.             templateClone.TextLabel.Text = text .. additionalText
  211.         else
  212.             templateClone.TextLabel.Text = text
  213.         end
  214.     elseif imageId then
  215.         templateClone.Image = imageId
  216.     end
  217.     templateClone.Parent = parent
  218.     return templateClone
  219. end
  220.  
  221. function DanceController:FindCarryAnimationDataByName(name)
  222.     for _, data in ipairs(animsDatas) do
  223.         if data.Name == name then
  224.             return data
  225.         end
  226.     end
  227.     return nil -- Return nil if no match is found
  228. end
  229.  
  230. function DanceController:Dance(danceName)
  231.     local animData = DanceController:FindCarryAnimationDataByName(danceName)
  232.     local soundData = sounds[danceName]
  233.  
  234.     DanceService.SyncDance:Fire()
  235.     DanceController:SyncDance(nil, player)
  236.     local track, sound = AnimSoundController:PlayAnimationAndSound(animData, soundData, danceName, true)
  237.     if track then
  238.         DanceService.ChangeDance:Fire(danceName)
  239.     else
  240.         DanceService.ChangeDance:Fire()
  241.     end
  242. end
  243.  
  244. local favoriteMouseConnections = {}
  245. local templateMouseConnections = {}
  246. function DanceController:CreateDances()
  247.     for _, danceName in ipairs(DanceController.DanceOrder) do
  248.         local animData = DanceController:FindCarryAnimationDataByName(danceName)
  249.         local soundData = sounds[danceName]
  250.         if animData then
  251.             local char = player.Character or player.CharacterAdded:Wait()
  252.             local humanoid = char:WaitForChild("Humanoid")
  253.  
  254.             local templateClone = danceScroll:FindFirstChild(danceName)
  255.             if not templateClone then
  256.                 templateClone =
  257.                     createTemplateClone(templateButton, danceScroll, danceName, danceName, nil)
  258.             end
  259.  
  260.             local favoriteButton = templateClone:WaitForChild("FavoriteButton")
  261.  
  262.             -- Favorite Dance
  263.             if not favoriteMouseConnections[danceName] then
  264.                 favoriteMouseConnections[danceName] = favoriteButton.Activated:Connect(function()
  265.                     AnimSoundController:FavoriteAnimationAndSound(favoriteButton, favoriteDances, "Dances")
  266.                 end)
  267.             end
  268.  
  269.             -- Buying Dance Proccess
  270.             if not templateMouseConnections[danceName] then
  271.                 templateMouseConnections[danceName] = templateClone.Activated:Connect(function()
  272.                     local isDanceOwned = DanceController:IsDanceOwned(danceName)
  273.  
  274.                     if isDanceOwned then
  275.                         DanceController:Dance(danceName)
  276.                     end
  277.                 end)
  278.             end
  279.         end
  280.     end
  281. end
  282.  
  283. function DanceController:LoadAnimation()
  284.     -- no preload needed
  285.    
  286.     --for _, animationName in pairs(DanceController.DanceOrder) do
  287.     --  local animData =  DanceController:FindCarryAnimationDataByName(animationName)
  288.     --  if animData then
  289.     --      AnimSoundController:LoadAnimation(animData, animationName)
  290.     --  end
  291.     --end
  292. end
  293.  
  294. function DanceController:TweenToLeft(toTween, goal)
  295.     local tweenInfo = TweenInfo.new(0.5, Enum.EasingStyle.Sine, Enum.EasingDirection.Out)
  296.     local tween = TweenService:Create(toTween, tweenInfo, goal)
  297.     return tween
  298. end
  299.  
  300. function DanceController:ToggleFrameVisible(frame, boolVal, isTweenToLeft, goal)
  301.     local tween
  302.     if isTweenToLeft and goal then
  303.         tween = DanceController:TweenToLeft(frame, goal)
  304.         tween:Play()
  305.         if boolVal == true then
  306.             frame.Visible = boolVal
  307.             return
  308.         end
  309.         tween.Completed:Wait()
  310.     end
  311.     frame.Visible = boolVal
  312. end
  313.  
  314. -- Function to check if an animation is a dance
  315. function DanceController:IsDancing(humanoid)
  316.     for _, danceTrack in pairs(humanoid:GetPlayingAnimationTracks()) do
  317.         for i=1,#DancesDatas.Animations do
  318.             local animData = DancesDatas.Animations[i]
  319.             local animIds = {
  320.                 "Id",
  321.                 "WalkId",
  322.                 "LoopId"
  323.             }
  324.             local danceName = animData.Name
  325.             for i2=1,#animIds do
  326.                 local dataName = animIds[i2]
  327.                 if animData[dataName] == danceTrack.Animation.AnimationId then
  328.                     return true, danceName, danceTrack
  329.                 end
  330.             end
  331.         end
  332.     end
  333.     return false
  334. end
  335.  
  336. local function stopDances(humanoid)
  337.     local bool, danceName, danceTrack
  338.     repeat
  339.         task.wait()
  340.         bool, danceName, danceTrack = DanceController:IsDancing(humanoid)
  341.         if danceTrack then
  342.             danceTrack:Stop()
  343.             AnimSoundController:StopSound(humanoid.Parent.HumanoidRootPart, danceName)
  344.         end
  345.     until not bool
  346. end
  347.  
  348. local syncDanceThreads = {}
  349. local syncDanceThreads2 = {}
  350. function DanceController:SyncDance(player2,
  351.     specificPlayer,
  352.     dontDestroyThreads -- true = threads won't get destroyed
  353. )
  354.     if not player2 then
  355.         stopDances(specificPlayer.Character.Humanoid)
  356.         if not dontDestroyThreads then
  357.             if syncDanceThreads[specificPlayer] and coroutine.status(syncDanceThreads[specificPlayer]) ~= "dead" then
  358.                 task.cancel(syncDanceThreads[specificPlayer])
  359.                 syncDanceThreads[specificPlayer] = nil
  360.             end
  361.             if syncDanceThreads2[specificPlayer] and coroutine.status(syncDanceThreads2[specificPlayer]) ~= "dead" then
  362.                 task.cancel(syncDanceThreads2[specificPlayer])
  363.                 syncDanceThreads2[specificPlayer] = nil
  364.             end
  365.         else
  366.             if specificPlayer == player then
  367.                 AnimSoundController:StopAnimationAndSound(specificPlayer.Character.HumanoidRootPart, AnimSoundController.CurrentSoundName)
  368.             end
  369.         end
  370.         return
  371.     end
  372.    
  373.     local character = player2.Character
  374.     local humanoid = character and character:FindFirstChild("Humanoid")
  375.    
  376.     if humanoid then
  377.         local bool, danceName, danceTrack
  378.         local animData
  379.         for i=1, 10 do
  380.             bool, danceName, danceTrack = DanceController:IsDancing(humanoid)
  381.             animData = DanceController:FindCarryAnimationDataByName(danceName)
  382.             if animData then
  383.                 break
  384.             end
  385.             task.wait(0.1)
  386.         end
  387.        
  388.        
  389.         local targetPlayer = player
  390.         if specificPlayer then
  391.             targetPlayer = specificPlayer
  392.            
  393.             if specificPlayer == player then
  394.                 specificPlayer = nil
  395.             end
  396.         end
  397.        
  398.         if syncDanceThreads[targetPlayer] and coroutine.status(syncDanceThreads[targetPlayer]) ~= "dead" then
  399.             task.cancel(syncDanceThreads[targetPlayer])
  400.         end
  401.         syncDanceThreads[targetPlayer] = task.spawn(function()
  402.             if specificPlayer then
  403.                 -- other players
  404.                 local track = specificPlayer.Character.Humanoid:WaitForChild("Animator"):LoadAnimation(danceTrack.Animation)
  405.                 repeat task.wait() until track.Length ~= 0
  406.                 track:Play()
  407.                 track.TimePosition = danceTrack.TimePosition
  408.             else
  409.                 -- self
  410.                 local loadedAnimTrack = AnimSoundController:LoadAnimation(animData, danceName)
  411.                 repeat task.wait() until loadedAnimTrack.Length ~= 0
  412.  
  413.                 local soundData = sounds[danceName]
  414.                 local track, sound = AnimSoundController:PlayAnimationAndSound(animData, soundData, danceName, true)
  415.                 if track then
  416.                     track.TimePosition = danceTrack.TimePosition
  417.                     if sound then
  418.                         sound.TimePosition = danceTrack.TimePosition
  419.                     end
  420.                     DanceService.SyncDance:Fire(player2)
  421.                 else
  422.                     DanceService.SyncDance:Fire()
  423.                     DanceController:SyncDance(nil, player, true)
  424.                     if syncDanceThreads2[targetPlayer] and coroutine.status(syncDanceThreads2[targetPlayer]) ~= "dead" then
  425.                         task.cancel(syncDanceThreads2[targetPlayer])
  426.                     end
  427.                     return
  428.                 end
  429.                
  430.                 if syncDanceThreads2[targetPlayer] and coroutine.status(syncDanceThreads2[targetPlayer]) ~= "dead" then
  431.                     task.cancel(syncDanceThreads2[targetPlayer])
  432.                 end
  433.                 syncDanceThreads2[targetPlayer] = task.spawn(function()
  434.                     while true do
  435.                         task.wait(0.1)
  436.                         local bool2, danceName2, danceTrack2 = DanceController:IsDancing(humanoid)
  437.                         if not bool2 then
  438.                             stopDances(player.Character.Humanoid)
  439.                         elseif danceName2 ~= danceName then
  440.                             -- resets dance syncer when player2 changes dance
  441.                             task.delay(0.1, function()
  442.                                 if bool then
  443.                                     DanceController:SyncDance(player2, specificPlayer)
  444.                                 else
  445.                                     AnimSoundController:StopAnimationAndSound(player.Character.HumanoidRootPart, AnimSoundController.CurrentSoundName)
  446.                                 end
  447.                             end)
  448.                             if bool then
  449.                                 return
  450.                             end
  451.                         end
  452.                     end
  453.                 end)
  454.             end
  455.         end)
  456.     end
  457. end
  458.  
  459. function DanceController:SetupSyncDanceButton(player2, bool, danceName)
  460.     local char = player2.Character
  461.     local syncDancePrompt = char.HumanoidRootPart:FindFirstChild("SyncDancePrompt")
  462.     if bool then
  463.         if not syncDancePrompt then
  464.             syncDancePrompt = Instance.new("ProximityPrompt")
  465.             syncDancePrompt.Name = "SyncDancePrompt"
  466.             syncDancePrompt.ActionText = "Sync Dance"
  467.             syncDancePrompt.ObjectText = danceName or ""
  468.             syncDancePrompt.Style = Enum.ProximityPromptStyle.Custom
  469.             syncDancePrompt.KeyboardKeyCode = Enum.KeyCode.F
  470.             syncDancePrompt.GamepadKeyCode = Enum.KeyCode.DPadUp
  471.             syncDancePrompt.RequiresLineOfSight = false
  472.             syncDancePrompt.Parent = char.HumanoidRootPart
  473.             syncDancePrompt.Triggered:Connect(function()
  474.                 clickSound:Play()          
  475.  
  476.                 DanceService:GetSyncedDancers(player2):andThen(function(player2_syncedDanceTable)
  477.                     local toSync = player2_syncedDanceTable.ToSync or player2
  478.                     if toSync == player then
  479.                         WarningsController:WarnPlayer("This player is currently dance-synced to you. Failed to sync.", Color3.fromRGB(255, 0, 0),{
  480.                             Duration = 4
  481.                         })
  482.                         return
  483.                     end
  484.                     DanceController:SyncDance(toSync)
  485.                 end)
  486.             end)
  487.  
  488.             -- repositions all proximity prompt
  489.             OthersUtil.ProximityPromptSetup(char.HumanoidRootPart, nil, Vector2.new(0, 60))
  490.         end
  491.     else
  492.         if syncDancePrompt then
  493.             syncDancePrompt:Destroy()
  494.            
  495.             -- repositions all proximity prompt
  496.             OthersUtil.ProximityPromptSetup(char.HumanoidRootPart)
  497.         end
  498.     end
  499. end
  500.  
  501.  
  502.  
  503. function DanceController:KnitStart()
  504.     -- waits for profile to load on client
  505.     DataController:WaitUntilProfileLoaded()
  506.     ProfileData = DataController.Data
  507.     DancesUnlocked = ProfileData.DancesUnlocked
  508.     favoriteDances = ProfileData.FavoriteDances
  509.  
  510.     DanceController:UpdateOrderDance()
  511.     DanceController:LoadAnimation()
  512.     DanceController:CreateDances()
  513.     DanceController:ReorderDances()
  514.  
  515.     player.CharacterAdded:Connect(function(character)
  516.         repeat
  517.             task.wait()
  518.         until not character or character.Parent == workspace.Characters
  519.         if not character then
  520.             return
  521.         end
  522.         DanceController:LoadAnimation()
  523.     end)
  524.    
  525.     local danceGui = playerGui:WaitForChild("DanceGui")
  526.     local DanceFrame = danceGui:WaitForChild("DanceFrame")
  527.  
  528.     local ToHideLeftValue = { Position = UDim2.new(-0.16, 0, 0.25, 0) }
  529.     local ToShowLeftValue = { Position = UDim2.new(0.137, 0, 0.25, 0) }
  530.     local isTweening = false
  531.     local function ShowLeftFrame(frame1)
  532.         if not isTweening then
  533.             isTweening = true
  534.             FXSoundsUtil.CreateSoundThenPlay(clickSound, {}, plr, 2)
  535.             if frame1.Visible then
  536.                 -- close frame
  537.                 DanceController:ToggleFrameVisible(frame1, false, true, ToHideLeftValue)
  538.  
  539.                 isTweening = false
  540.             else
  541.                 -- open frame
  542.                 DanceController:ToggleFrameVisible(frame1, true, true, ToShowLeftValue)
  543.                 isTweening = false
  544.             end
  545.         end
  546.     end
  547.    
  548.     local mainGui = playerGui:WaitForChild("MainGui")
  549.     --local openDanceButton = mainGui:WaitForChild("DancesButton")
  550.     --openDanceButton.Activated:Connect(function()
  551.     --  ShowLeftFrame(DanceFrame)
  552.     --end)
  553.    
  554.     danceSearchBar:GetPropertyChangedSignal("Text"):Connect(function()
  555.         local search = string.lower(danceSearchBar.Text)
  556.         for _, Button in pairs(DanceFrame.DanceScroll:GetChildren()) do
  557.             if Button:IsA("GuiButton") then
  558.                 if search ~= "" then
  559.                     local item = string.lower(Button.TextLabel.Text)
  560.                     if string.find(item, search) then
  561.                         Button.Visible = true
  562.                     else
  563.                         Button.Visible = false
  564.                     end
  565.                 else
  566.                     Button.Visible = true
  567.                 end
  568.             end
  569.         end
  570.     end)
  571.    
  572.     ProfileService.UpdateSpecificData:Connect(function(Redirectories,newValue)
  573.         task.wait()
  574.         if Redirectories[1] == "FavoriteDances" or Redirectories[1] == "DancesUnlocked"  then
  575.             DanceController:UpdateOrderDance()
  576.             DanceController:ReorderDances()
  577.         end
  578.     end)
  579.    
  580.     DanceService.SyncDance:Connect(function(...)
  581.         DanceController:SyncDance(...)
  582.     end)
  583.    
  584.     task.spawn(function()
  585.         while true do
  586.             game["Run Service"].RenderStepped:Wait()
  587.             local succ, err = pcall(function()
  588.                 for _,player2 in pairs(game.Players:GetPlayers()) do
  589.                     if player2 ~= plr then
  590.                         local char = player2.Character
  591.                         local HRP = char and char:FindFirstChild("HumanoidRootPart")
  592.                         if not HRP then
  593.                             continue
  594.                         end
  595.  
  596.                         local bool, danceName = DanceController:IsDancing(char.Humanoid)
  597.                         if bool then
  598.                             DanceController:SetupSyncDanceButton(player2, true, danceName)
  599.                         else
  600.                             DanceController:SetupSyncDanceButton(player2, false, danceName)
  601.                         end
  602.                     end
  603.                 end
  604.             end)
  605.             if not succ then
  606.                 warn(err)
  607.             end
  608.         end
  609.     end)
  610. end
  611.  
  612. function DanceController:KnitInit()
  613.     ---- Services
  614.     DanceService = Knit.GetService("DanceService")
  615.     ProfileService = Knit.GetService("ProfileService")
  616.  
  617.     ---- Controllers
  618.     DataController = Knit.GetController("DataController")
  619.     WarningsController = Knit.GetController("WarningsController")
  620.     GuiController = Knit.GetController("GuiController")
  621.     AnimSoundController = Knit.GetController("AnimSoundController")
  622. end
  623.  
  624. return DanceController
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement