I developed a system for giving players ranks and auras for this game I’m working on and while it does work. I don’t know if it’s efficient or good on performance
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")
local Manager = require(script.Parent.PlayerData.Manager) --functions for getting and setting player data
local Ranks = require(ReplicatedStorage.Databases.Ranks) --dictionary of all the ranks in the game. each rank holds their names and needed power to get them
local remotes = ReplicatedStorage.Remotes
local auraParticles = ServerStorage.AuraParticles --folder that holds the folders for each auras particles
remotes.rankEvent.Event:Connect(function(player: Player)
--get the players current power value and current rank
local playerPower = Manager.GetPower(player)
local playerRank = Manager.GetRank(player)
--if player doesn't have an aura and their current rank has an aura available for it then give aura and enable boolean value (used for players rejoining the game if they had an aura when they previously left)
if not player.Character.characterStats.hasAura.Value then
local currentRankAura = getAura(playerRank)
if currentRankAura then
player.Character.characterStats.hasAura.Value = true
giveAura(player.Character, playerRank)
end
end
--loop through all ranks in the ranks dictionary
for _, newRank in pairs(Ranks) do
--if player doesn't have enough power for new rank then exit
if playerPower < newRank.NeededPower then continue end
--if new rank has a higher needed power than current rank then the player has ranked up
if newRank.NeededPower > playerRank.NeededPower then
--play rank up sound and display some gui
warn("PLAYER HAS RANKED UP")
--if the new rank has an aura available for it then remove the players current aura if they have one
local newRankAura = getAura(newRank)
if newRankAura then
clearAura(player.Character)
end
--give the player the new ranks aura and set players rank to new rank
giveAura(player.Character, newRank)
Manager.SetRank(player, newRank)
end
end
end)
function clearAura(character: Model)
--if a part is found with the name AuraPartHolder then destroy it
local auraPartHolder = character:FindFirstChild("AuraPartHolder")
if auraPartHolder then
auraPartHolder:Destroy()
end
--loop through all parts in the players character
for _, bodyPart in character:GetChildren() do
--if part found in for loop is not a body part then exit
if not bodyPart:IsA("MeshPart") then continue end
--if there is a particle emitter found OR an attachment with the name particleAttachment is found then destroy it
for _, particle in bodyPart:GetChildren() do
if particle:IsA("ParticleEmitter") or (particle:IsA("Attachment") and particle.Name == "particleAttachment") then
particle:Destroy()
end
end
end
--disable boolean value for player having an active aura
character.characterStats.hasAura.Value = false
end
function getAura(rank: SharedTable)
--loop though the auraParticles table and see if a part of the folders name matches the ranks name
for _, auraFolder: Folder in auraParticles:GetChildren() do
if not auraFolder.Name.match(auraFolder.Name, rank.Name) then continue end
return auraFolder
end
end
function giveAura(character: Model, rank: SharedTable)
--if an aura isnt found then exit
local auraFolder = getAura(rank)
if not auraFolder then return end
--loop though the particleHolder parts (that hold the particle emitters) that are in the aura folder
for _, particleHolder: Part in auraFolder:GetChildren() do
--loop through all parts in the players character
for _, bodyPart in character:GetChildren() do
--loop through all particle emitters or attachments that are in the particleHolder part
for _, particle: ParticleEmitter in particleHolder:GetChildren() do
--if the body part already has a particle emitter in it then exit
if bodyPart:FindFirstChild(particle.Name) then continue end
--if the character already has a part called AuraPartHolder then exit
if character:FindFirstChild(particleHolder.Name) then continue end
if bodyPart:IsA("MeshPart") then
if particleHolder.Name == "Everywhere" then
--parents the cloned particles to each body part of the character
local clone = particle:Clone()
clone.Parent = bodyPart
elseif particleHolder.Name == "Torso" then
--if the body part found in the for loop doesn't have the name UpperTorso then exit
if bodyPart.Name ~= "UpperTorso" then continue end
--parents the cloned particle only to the characters torso
local clone = particle:Clone()
clone.Parent = bodyPart
elseif particleHolder.Name == "Limbs" then
--if the body part found in the for loop does't have one of these 4 names then exit
if bodyPart.Name == "LeftLowerArm" or bodyPart.Name == "LeftLowerLeg" or bodyPart.Name == "RightLowerArm" or bodyPart.Name == "RightLowerLeg" then
--parents the cloned particle only to the characters limbs
local clone = particle:Clone()
clone.Parent = bodyPart
end
end
else
--if the body part found in the for loop is the HumanoidRootPart
if bodyPart == character.PrimaryPart then
--if the particle holder part being looped though has the name AuraPartHolder
if particleHolder.Name == "AuraPartHolder" then
--parent and weld the clone to the character
local holderClone = particleHolder:Clone()
holderClone.CFrame = bodyPart.CFrame * CFrame.new(0, -2, 0)
holderClone.Anchored = false
holderClone.CanCollide = false
holderClone.Parent = character
local weld = Instance.new("WeldConstraint")
weld.Part0 = holderClone
weld.Part1 = bodyPart
weld.Parent = holderClone
end
end
end
--random time for each particle emitter to be cloned to the body parts. adds more visual randomness
task.wait(math.random(0.05, 0.5))
end
end
end
end