Puzzled's Portfolio
Hello! I'm Puzzled (@Puzzled3d)
About me
Over 3 years of Roblox LuaU experience
7 years of general programming experience
UK, GMT+0
Code Snippets
This includes some of my code snippets of my recent projects. I like to keep my code organised, readable and structured.
--// Stat Profiler --//--// Module for Datastore management as a wrapper for ProfileService. --//--// Includes: --//--//--|| Automatic attribute management --//--//--|| Instant updates to profile --//--//--|| Easy way to structure datastore local StatProfiler = {} StatProfiler.Connections = {} --// Update profile with data. Adds to datastore if not already a stat. function StatProfiler.SetStat(player: Player, profile: any, stat: string, value: any): any profile.Data[stat] = value if typeof(value) ~= "table" then player:SetAttribute(stat:gsub("/",""), value) end return value end --// Loads a stat from the datastore. Like getting a stat, except it will create a profile entry if it doesn't already exist. function StatProfiler.LoadStat(player: Player, profile: any, stat: string, default: any?): any local value = StatProfiler.GetStat(player, profile, stat, default) if typeof(value) ~= "table" then player:SetAttribute(stat:gsub("/",""), value) end if not StatProfiler.Connections[player] then StatProfiler.Connections[player] = {} end table.insert(StatProfiler.Connections[player], player:GetAttributeChangedSignal(stat:gsub("/","")):Connect(function() --print("updating stat", stat, "to", player:GetAttribute(stat:gsub("/",""))) StatProfiler.SetStat(player, profile, stat, player:GetAttribute(stat:gsub("/",""))) end)) profile.Data[stat] = value -- added bc i forgor return value end --// Increments a stat. function StatProfiler.IncrementStat(player: Player, profile: any, stat: string, increment: number, default: number?): (any, boolean) local value, existed = StatProfiler.GetStat(player, profile, stat, default) profile.Data[stat] = (value) + increment if typeof(value) ~= "table" then player:SetAttribute(stat:gsub("/",""), profile.Data[stat]) end if not StatProfiler.Connections[player] then StatProfiler.Connections[player] = {} end table.insert(StatProfiler.Connections[player], player:GetAttributeChangedSignal(stat:gsub("/","")):Connect(function() StatProfiler.SetStat(player, profile, stat, player:GetAttribute(stat:gsub("/",""))) end)) return profile.Data[stat], existed end --// Returns the value for a stat or default (if given) function StatProfiler.GetStat(player: Player, profile: any, stat: string, default: any?): (any, boolean) local existed = profile.Data[stat] return existed or player:GetAttribute(stat:gsub("/","")) or default or 0, (not not existed) end --// Creates a leaderstat value for a stat. Also creates the leaderstats folder if it doesn't already exist. function StatProfiler.CreateLeaderstat(player: Player, profile: any, stat: string, typeValue: string, default: any?): Instance local value, _existed = StatProfiler.GetStat(player, profile, stat, default) local leaderstats = player:FindFirstChild("leaderstats") if not leaderstats then leaderstats = Instance.new("Folder") leaderstats.Name = "leaderstats" leaderstats.Parent = player end local statValue = Instance.new(typeValue) statValue.Name = stat statValue.Value = value statValue.Parent = leaderstats statValue:GetPropertyChangedSignal("Value"):Connect(function() StatProfiler.SetStat(player, profile, stat, statValue.Value) end) player:GetAttributeChangedSignal(stat:gsub("/","")):Connect(function() statValue.Value = player:GetAttribute(stat:gsub("/","")) end) return statValue end return StatProfiler
local CollectionService = game:GetService("CollectionService") local Players = game:GetService("Players") local ReplicatedStorage = game:GetService("ReplicatedStorage") local RunService = game:GetService("RunService") local UserInputService = game:GetService("UserInputService") local Packages = ReplicatedStorage.Packages local Knit = require(Packages.Knit) local KeycodeImages = require(Packages.KeycodeImages) local Camera = workspace.CurrentCamera local InputController = Knit.CreateController { Name = "InputController"; CurrentInteractions = {1}; Interactions = {}; CurrentConnections = {}; MaxInteractUUID = 0; } function InputController:KnitInit() self._InteractService = Knit.GetService("InteractService") self.Player = Players.LocalPlayer local InteractGUI = self.Player:WaitForChild("PlayerGui"):WaitForChild("Interact").Frame local InteractFrame = InteractGUI.Frame InteractFrame.Parent = script InteractGUI.Parent.Enabled = true InteractGUI.Visible = true RunService.Heartbeat:Connect(function(deltaTime) local CurrentInteractions = self:GetCurrentInteractions() for Keycode,InteractionData in pairs(CurrentInteractions) do if InteractionData.RemoveCondition(unpack(InteractionData.Args)) then self:RemoveInteract(InteractionData.UUID) continue end local CurrentConnection = self.CurrentConnections[Keycode] if CurrentConnection and CurrentConnection.UUID == Keycode then return end if CurrentConnection then CurrentConnection.InputBegan:Disconnect() CurrentConnection.Frame:Destroy() self.CurrentConnections[Keycode] = nil end local Frame = InteractFrame:Clone() local ConnectionData = { InputBegan = UserInputService.InputBegan:Connect(function(inputObject) if inputObject.KeyCode == Keycode then self:Interact(InteractionData.UUID) end end); Frame = Frame; UUID = InteractionData.UUID; } self.CurrentConnections[Keycode] = ConnectionData Frame.KeycodeImage.Image = "rbxassetid://"..tostring(KeycodeImages[Keycode] or KeycodeImages[Enum.KeyCode.Unknown] or 15664197440) Frame.InteractLabel.Text = InteractionData.Name Frame.Visible = not self.Player.Character:GetAttribute("IsInteracting") Frame.Parent = InteractGUI InteractionData.RemoveEvent.Event:Once(function() ConnectionData.InputBegan:Disconnect() Frame:Destroy() self.CurrentConnections[Keycode] = nil end) end end) -- Other interactions local ClimbInteraction local function HandleRope(Rope) local Collider = Rope:FindFirstChild("Collider") if not Collider then print(Rope,"has no collider") return end Collider.Touched:Connect(function(otherPart) if ClimbInteraction then return end if otherPart.Name ~= "Head" then return end local Character = self.Player.Character if not Character then return end if not otherPart:IsDescendantOf(Character) then return end ClimbInteraction = self:GetInteractionData(self:AddInteract( "Climb", Enum.KeyCode.Space, 3, function(Collider, otherPart) local collidingParts = Collider:GetTouchingParts() if #collidingParts == 0 or not table.find(collidingParts, otherPart) then return true end end, -- Args Collider, otherPart )) ClimbInteraction.RemoveEvent.Event:Once(function() ClimbInteraction = nil end) end) end for _,Rope in pairs(workspace.Ropes:GetChildren()) do HandleRope(Rope) end workspace.Ropes.ChildAdded:Connect(HandleRope) end function InputController:GetCurrentInteractions() local AllInteractions = {}; for Key,InteractionData in pairs(self.Interactions) do if InteractionData.RemoveCondition(unpack(InteractionData.Args)) then self:RemoveInteract(InteractionData.UUID) continue end AllInteractions[InteractionData.KeyCode] = AllInteractions[InteractionData.KeyCode] or {} table.insert(AllInteractions[InteractionData.KeyCode], InteractionData) end local CurrentInteractions = {}; for KeyCode,Interactions in pairs(AllInteractions) do local ThisInteraction if #Interactions == 1 then ThisInteraction = Interactions[1] else local HighestPriority = -1 for _,InteractionData in pairs(Interactions) do if InteractionData.Priority >= HighestPriority then HighestPriority = InteractionData.Priority ThisInteraction = InteractionData end end end if not ThisInteraction then print("THERE IS NO",KeyCode,Interactions) continue end CurrentInteractions[KeyCode] = ThisInteraction end return CurrentInteractions end function InputController:GetInteractionData(UUID) for Key,InteractionData in pairs(self.Interactions) do if InteractionData.UUID == UUID then return InteractionData, Key end end end function InputController:AddInteract(Name, KeyCode, Priority, RemoveCondition, ...) local InteractionData = { Name = Name; KeyCode = KeyCode; Priority = Priority; Args = {...}; UUID = self.MaxInteractUUID + 1; RemoveCondition = RemoveCondition; RemoveEvent = Instance.new("BindableEvent"); } self.MaxInteractUUID += 1 table.insert(self.Interactions, InteractionData) return InteractionData.UUID end function InputController:RemoveInteract(UUID) local InteractionData,Key = self:GetInteractionData(UUID) if not InteractionData or not Key then return end self.Interactions[Key] = nil local CurrentConnection = self.CurrentConnections[InteractionData.Keycode] if CurrentConnection and CurrentConnection.UUID == UUID then CurrentConnection.InputBegan:Disconnect() CurrentConnection.Frame:Destroy() self.CurrentConnections[InteractionData.Keycode] = nil end InteractionData.RemoveEvent:Fire() end function InputController:Interact(UUID) if self.Player.Character:GetAttribute("IsInteracting") then return end local InteractionData = self:GetInteractionData(UUID) if not InteractionData then return end local Name, Args = InteractionData.Name, InteractionData.Args self:RemoveInteract(UUID) self._InteractService:Interact(Name, unpack(Args)) end return InputController
local module = {} local switch = {} switch.__index = switch module.__call = function(t, var): Switch local switchObject = {} switchObject.var = var setmetatable(switchObject, switch) return switchObject end function switch:case(value: any, callback: ()->(), ...): Switch if self.expired then return self end if self.var == value then self.returned = {callback(...)} self.expired = true end return self end function switch:otherwise(callback: ()->(), ...): Switch-- Cannot use name "else" because it is a reserved keyword if self.expired then return self end self.returned = {callback(...)} self.expired = true return self end -- Aliases switch.other = switch.otherwise switch.except = switch.otherwise switch.unless = switch.otherwise switch.match = switch.case type case = (any, (any?)->(any?), any?) -> Switch type otherwise = ((any?)->(any?), any?) -> Switch export type Switch = { case: case, match: case, otherwise: otherwise, other: otherwise, except: otherwise, unless: otherwise } return setmetatable(module, module)
local HttpService = game:GetService("HttpService") local SequenceProvider = game:GetService("KeyframeSequenceProvider") local Players = game:GetService("Players") local ReplicatedStorage = game:GetService("ReplicatedStorage") local Packages = ReplicatedStorage.Packages local Knit = require(Packages.Knit) local AnimationService = Knit.CreateService { Name = "AnimationService"; Client = { StartAnim = Knit.CreateSignal(); ExecuteFunction = Knit.CreateSignal(); }; } function AnimationService:KnitStart() print("AnimationService Started!") end function AnimationService:KnitInit() print("AnimationService Initialised!") Players.PlayerAdded:Connect(function(player) player.CharacterAdded:Connect(function(character) local Humanoid = character:WaitForChild("Humanoid") local Animator = Humanoid:FindFirstChildOfClass("Animator") or Instance.new("Animator", Humanoid) end) end) for _,Enemy in pairs(workspace.Enemies:GetChildren()) do local Humanoid = Enemy:WaitForChild("Humanoid") local Animator = Humanoid:FindFirstChildOfClass("Animator") or Instance.new("Animator", Humanoid) end self.LengthCache = {} end function AnimationService:AddAnimationModel(Character, Mesh, ParentPart) local Mesh = Mesh:Clone() Mesh.Anchored = false Mesh:PivotTo(ParentPart:GetPivot()) local Motor6D = Instance.new("Motor6D") Motor6D.Part0 = ParentPart Motor6D.Part1 = Mesh Motor6D.C0 = Mesh:GetAttribute("C0") or CFrame.new(0,0,0) Motor6D.C1 = Mesh:GetAttribute("C1") or CFrame.new(0,0,0) Motor6D.Parent = Mesh Mesh.Parent = Character return Mesh end function AnimationService:LoadAnimation(Animator:Animator, AnimationId:string, Properties:{[string]:any}) Properties = Properties or {} local Animation = Instance.new("Animation") Animation.AnimationId = AnimationId Animation.Parent = workspace local AnimTrack = Animator:LoadAnimation(Animation) for Property, Value in pairs(Properties) do local Success, Error = pcall(function() AnimTrack[Property] = Value end) if not Success then warn("AnimTrack has no property", Property,"| Attempted to set to",Value) end end return AnimTrack, Animation end function AnimationService:AnimateModel(Model:Model, AnimationId:string, Properties:{[string]:any}) Properties = Properties or {} local AnimController = Model:FindFirstChildOfClass("AnimationController") -- Ironically also the name of the module lol if not AnimController then warn(Model,"has no AnimationController") return end local Animator = AnimController:FindFirstChildOfClass("Animator") if not Animator then warn(Model,">",AnimController,"has no Animator") return end local AnimTrack, Animation = self:LoadAnimation(Animator, AnimationId, Properties) AnimTrack:Play() return AnimTrack, Animation end function AnimationService:AnimateHumanoid(Character:Model, AnimationId:string, Properties:{[string]:any}) Properties = Properties or {} local Humanoid = Character:FindFirstChildOfClass("Humanoid") if not Humanoid then warn(Character,"is not a Humanoid, attempting to animate as a Model") return self:AnimateModel(Character, AnimationId, Properties) end local Animator = Humanoid:FindFirstChildOfClass("Animator") if not Animator then warn(Character,">",Humanoid,"has no Animator") return end local AnimTrack, Animation = self:LoadAnimation(Animator, AnimationId, Properties) AnimTrack:Play() return AnimTrack, Animation end function AnimationService:GetAnimLength(AnimTrack, Timeout) local ID = AnimTrack.Animation.AnimationId local Length = self.LengthCache[ID] if not Length or Length == 0 then Timeout = Timeout or 1 local Begin = os.clock() repeat Length = AnimTrack.Length task.wait() until Length ~= 0 or (os.clock() - Begin) >= Timeout end if Length ~= 0 then self.LengthCache[ID] = Length end return Length end function AnimationService:GetAnimMarkers(ID: string): {string?} local Markers = {} local KeyframeSequence: KeyframeSequence = SequenceProvider:GetKeyframeSequenceAsync(ID) local function Recurse(Parent) for _, Child in pairs(Parent:GetChildren()) do if (Child:IsA("KeyframeMarker")) then table.insert(Markers, Child) end if (#Child:GetChildren() > 0) then Recurse(Child) end end end Recurse(KeyframeSequence) return Markers end function AnimationService:Animate(...) local LongestLength = 0 self:LockCamera() for _,AnimData:AnimData in pairs({...}) do local Model, ID, Properties, MarkerData = AnimData.Model, AnimData.ID, AnimData.Properties or {}, AnimData.MarkerData or {} local AnimTrack, Animation local Humanoid = Model:FindFirstChildOfClass("Humanoid") if Humanoid then AnimTrack, Animation = self:AnimateHumanoid(Model, ID, Properties) else AnimTrack, Animation = self:AnimateModel(Model, ID, Properties) end local Length = self:GetAnimLength(AnimTrack, 0.5) if Length == 0 then Length = 1 end if Length > LongestLength then LongestLength = Length end local MarkerConnections = {} local Markers = self:GetAnimMarkers(ID) local Sounds = Model:FindFirstChild("Sounds", true) or Instance.new("Folder") local Particles = Model:FindFirstChild("Particles", true) or Instance.new("Folder") for _,Sound in pairs(Sounds:GetChildren()) do if Sound.Name ~= "Start" then continue end if not Sound:IsA("Sound") then continue end Sound:Play() end for _,Emitter in pairs(Particles:GetChildren()) do if Emitter.Name ~= "Start" then continue end if not Emitter:IsA("ParticleEmitter") then continue end Emitter.Enabled = true task.delay(Emitter:GetAttribute("Length") or (Emitter:FindFirstChild("Length") and Emitter:FindFirstChild("Length").Value) or 1, function() Emitter.Enabled = false end) end for _,Marker in pairs(Markers) do Marker = Marker.Name table.insert(MarkerConnections, AnimTrack:GetMarkerReachedSignal(Marker):Connect(function(paramString) local Length = tonumber(paramString) if MarkerData[Marker] then MarkerData[Marker].Payload(Model, ID, Properties, MarkerData, Length) if not MarkerData[Marker].Continue then return end end for _,Sound in pairs(Sounds:GetChildren()) do if Sound.Name ~= Marker then continue end if not Sound:IsA("Sound") then continue end Sound:Play() end for _,Emitter in pairs(Particles:GetChildren()) do if Emitter.Name ~= Marker then continue end if not Emitter:IsA("ParticleEmitter") then continue end Emitter.Enabled = true task.delay(Length or Emitter:GetAttribute("Length") or (Emitter:FindFirstChild("Length") and Emitter:FindFirstChild("Length").Value) or 1, function() Emitter.Enabled = false end) end end)) end AnimTrack:Play() AnimTrack.Stopped:Once(function() Animation:Destroy() for _, Connection in pairs(MarkerConnections) do if Connection and Connection.Connected then Connection:Disconnect() end end end) end self:UnlockCamera() return LongestLength end function AnimationService:ClientExecute(Player, FunctionName, ...) local CallbackEvent = Instance.new("RemoteEvent", workspace) self.Client.ExecuteFunction:Fire(Player, CallbackEvent, FunctionName, ...) local ReturnValues = {CallbackEvent.OnServerEvent:Wait()} table.remove(ReturnValues, 1) CallbackEvent:Destroy() return unpack(ReturnValues) end function AnimationService:AnimatePlayer(TargetPlayer:Player, PlayerData:AnimData, GlobalData:AnimData) -- Player Data is the animations played locally, GlobalData is the animation played to other clients GlobalData = GlobalData or PlayerData local LongestLength = 0 for _, Player in pairs(Players:GetChildren()) do local Length = self:ClientExecute(Player, "Animate", unpack(if Player==TargetPlayer then PlayerData else GlobalData)) if Length > LongestLength then LongestLength = Length end end return LongestLength end export type AnimData = {ID:string,Model:Model,Properties:{[any]:any},MarkerData:{[string]:{Payload:(Model,string,{[any]:any},table,number)->{},Continue:boolean}}} return AnimationService