I’ve set up an attribute system for a rpg I want to make. I have several local scripts and a server script both calling upon a module script to retrieve the value of whatever attribute that script needs. My server script is the one increasing and decreasing the value of the attributes. I run into issues when functions within the module script, specifically the ones updating the GUIs for my different resource bars, try to update when one of the bar’s maximum resources (e.g. maximum stamina) is lowered. The code doesn’t seem to have any problems when something like maximum stamina is increased however.
Here’s the module script where I’m pretty sure the issue lies within the updateStaminaBar and updateManaBar functions:
local StatManager = {}
-- Usual Variables
StatManager.statsEvent = game.ReplicatedStorage:WaitForChild("StatsEvent")
StatManager.player = game.Players.LocalPlayer
StatManager.character = StatManager.player.Character
StatManager.humanoid = StatManager.character:WaitForChild("Humanoid")
StatManager.statsGui = StatManager.player.PlayerGui:WaitForChild("statsGui")
StatManager.playerGui = StatManager.player.PlayerGui
-- Stat Variables
StatManager.Strength = StatManager.player.Stats.Strength.Value
StatManager.Agility = StatManager.player.Stats.Agility.Value
StatManager.Cunning = StatManager.player.Stats.Cunning.Value
StatManager.Intellect = StatManager.player.Stats.Intellect.Value
StatManager.Willpower = StatManager.player.Stats.Willpower.Value
StatManager.Constitution = StatManager.player.Stats.Constitution.Value
StatManager.Endurance = StatManager.player.Stats.Endurance.Value
StatManager.Presence = StatManager.player.Stats.Presence.Value
StatManager.Fate = StatManager.player.Stats.Fate.Value
-- Stamina Settings
StatManager.staminaText = StatManager.playerGui.resourceGui.staminaBackground:WaitForChild("staminaText")
StatManager.stamina = math.round(100 + StatManager.Endurance + (StatManager.Agility / 2))
StatManager.maxStamina = StatManager.player.Stats.maxStamina.Value
StatManager.speedDifference = math.round(8 + (StatManager.Agility / 2)) -- Difference between walk and sprint speed
StatManager.drainRate = math.round(20 + (StatManager.Strength / 2) - (StatManager.Willpower / 2)) -- How fast stamina drains while sprinting
StatManager.regenRate = math.round(10 + (StatManager.Agility / 4)) -- How fast stamina regenerates while not sprinting
StatManager.staminaRefreshRate = 25 -- Exhaustion point where stamina stops regenerating while moving
-- Magic Settings
StatManager.manaText = StatManager.playerGui.resourceGui.manaBackground:WaitForChild("manaText")
StatManager.mana = 100 + StatManager.Willpower
StatManager.maxMana = StatManager.player.Stats.maxMana.Value
StatManager.manaRegenSpeed = math.round(2 + (StatManager.Intellect / 2))
function StatManager.statsUpdate()
StatManager.statsGui.statsFrame.strengthText.Text = "Strength: ".. StatManager.player.Stats.Strength.Value
StatManager.statsGui.statsFrame.agilityText.Text = "Agility: ".. StatManager.player.Stats.Agility.Value
StatManager.statsGui.statsFrame.cunningText.Text = "Cunning: ".. StatManager.player.Stats.Cunning.Value
StatManager.statsGui.statsFrame.intellectText.Text = "Intellect: ".. StatManager.player.Stats.Intellect.Value
StatManager.statsGui.statsFrame.willpowerText.Text = "Willpower: ".. StatManager.player.Stats.Willpower.Value
StatManager.statsGui.statsFrame.constitutionText.Text = "Constitution: ".. StatManager.player.Stats.Constitution.Value
StatManager.statsGui.statsFrame.enduranceText.Text = "Endurance: ".. StatManager.player.Stats.Endurance.Value
StatManager.statsGui.statsFrame.presenceText.Text = "Presence: ".. StatManager.player.Stats.Presence.Value
StatManager.statsGui.statsFrame.fateText.Text = "Fate: ".. StatManager.player.Stats.Fate.Value
StatManager.statsGui.statsFrame.availablePointsText.Text = "Available Points: ".. StatManager.player.Stats.availablePoints.Value
StatManager.updateStamina()
StatManager.updateStaminaBar()
StatManager.updateManaBar()
end
function StatManager.updateStamina()
local speedDifference = StatManager.speedDifference
local agility = StatManager.Agility
local drainRate = StatManager.drainRate
local strength = StatManager.Strength
local willpower = StatManager.Willpower
local regenRate = StatManager.regenRate
speedDifference += (agility / 2)
drainRate += (strength / 2) - (willpower / 2)
StatManager.regenRate += (agility / 4)
end
function StatManager.updateStaminaBar()
local stamina = StatManager.stamina
local maxStamina = StatManager.getUpdatedStat("maxStamina")
StatManager.playerGui.resourceGui.staminaBackground.staminaBar:TweenSize(UDim2.new(stamina / maxStamina, 0, 1, 0), Enum.EasingDirection.InOut, Enum.EasingStyle.Sine, 0.15, true)
StatManager.staminaText.Text = math.round(stamina).. "/" .. math.round(maxStamina)
end
function StatManager.updateManaBar()
local mana = StatManager.mana
local maxMana = StatManager.maxMana
StatManager.playerGui.resourceGui.manaBackground.manaBar:TweenSize(UDim2.new(mana / maxMana, 0, 1, 0), Enum.EasingDirection.InOut, Enum.EasingStyle.Sine, 0.15, true)
StatManager.manaText.Text = math.round(mana).. "/" .. math.round(maxMana)
end
function StatManager.regenMana(amountToRegen)
StatManager.mana += amountToRegen
end
function StatManager.healPlayer(healAmount)
print("Healing")
StatManager.humanoid.Health += healAmount
end
function StatManager.getUpdatedStat(statName)
local playerStats = game.Players.LocalPlayer.Stats
local Strength = StatManager.player.Stats.Strength.Value
local Agility = StatManager.player.Stats.Agility.Value
local Cunning = StatManager.player.Stats.Cunning.Value
local Intellect = StatManager.player.Stats.Intellect.Value
local Willpower = StatManager.player.Stats.Willpower.Value
local Constitution = StatManager.player.Stats.Constitution.Value
local Endurance = StatManager.player.Stats.Endurance.Value
local Presence = StatManager.player.Stats.Presence.Value
local Fate = StatManager.player.Stats.Fate.Value
local maxStamina = StatManager.player.Stats.maxStamina.Value
local maxMana = StatManager.player.Stats.maxMana.Value
local Level = StatManager.player.Stats.Level.Value
local expPoints = StatManager.player.Stats.expPoints.Value
if statName == "Strength" then return Strength
elseif statName == "Agility" then return Agility
elseif statName == "Cunning" then return Cunning
elseif statName == "Intellect" then return Intellect
elseif statName == "Willpower" then return Willpower
elseif statName == "Constitution" then return Constitution
elseif statName == "Endurance" then return Endurance
elseif statName == "Presence" then return Presence
elseif statName == "Fate" then return Fate
elseif statName == "maxStamina" then return maxStamina
elseif statName == "maxMana" then return maxMana
elseif statName == "Level" then return Level
elseif statName == "expPoints" then return expPoints
end
end
return StatManager
I made the getUpdatedStat(statName) function to see if that would solve my issue, and so far as you can see I’ve only implemented it’s usage in the updateStaminaBar function. This halfway works as when the stats are reset and the maximum stamina is lowered, the stamina bar reads the proper maximum stamina, but the actual stamina value does not change and remains above the maximum value, as well as regenerating to the maximum value. I think that means that the actual maximum stamina value isn’t being changed then, but I don’t know how to fix that.
Here’s the function in the server script that updates the values of each attribute:
statsEvent.OnServerEvent:Connect(function(plr, eventtype, Arg1)
local Character = plr.Character
if eventtype == "addStat" and plr.Stats.availablePoints.Value > 0 then
local statType = Arg1
if statType == "addStrengthButton" then
plr.Stats.availablePoints.Value -= 1
plr.Stats.Strength.Value += 1
statsEvent:FireClient(plr, "strengthUpdate")
elseif statType == "addAgilityButton" then
plr.Stats.availablePoints.Value -= 1
plr.Stats.Agility.Value += 1
statsEvent:FireClient(plr, "agilityUpdate")
elseif statType == "addCunningButton" then
plr.Stats.availablePoints.Value -= 1
plr.Stats.Cunning.Value += 1
statsEvent:FireClient(plr, "cunningUpdate")
elseif statType == "addIntellectButton" then
plr.Stats.availablePoints.Value -= 1
plr.Stats.Intellect.Value += 1
statsEvent:FireClient(plr, "intellectUpdate")
elseif statType == "addWillpowerButton" then
plr.Stats.availablePoints.Value -= 1
plr.Stats.Willpower.Value += 1
statsEvent:FireClient(plr, "willpowerUpdate")
elseif statType == "addConstitutionButton" then
plr.Stats.availablePoints.Value -= 1
plr.Stats.Constitution.Value += 1
statsEvent:FireClient(plr, "constitutionUpdate")
elseif statType == "addEnduranceButton" then
plr.Stats.availablePoints.Value -= 1
plr.Stats.Endurance.Value += 1
statsEvent:FireClient(plr, "enduranceUpdate")
elseif statType == "addPresenceButton" then
plr.Stats.availablePoints.Value -= 1
plr.Stats.Presence.Value += 1
statsEvent:FireClient(plr, "presenceUpdate")
elseif statType == "addFateButton" then
plr.Stats.availablePoints.Value -= 1
plr.Stats.Fate.Value += 1
statsEvent:FireClient(plr, "fateUpdate")
end
end
end)
Here’s the local script function that messes with the different effects that raising an attribute has:
statsEvent.OnClientEvent:Connect(function(eventtype)
if eventtype == "strengthUpdate" then
statManager.statsUpdate()
elseif eventtype == "agilityUpdate" then
statManager.maxStamina += 0.5
Character.Humanoid.WalkSpeed += 0.2
Character.Humanoid.JumpPower += 0.1
statManager.statsUpdate()
elseif eventtype == "cunningUpdate" then
statManager.statsUpdate()
elseif eventtype == "intellectUpdate" then
statManager.statsUpdate()
elseif eventtype == "willpowerUpdate" then
statManager.maxMana += 5
statManager.mana += 5
statManager.statsUpdate()
elseif eventtype == "constitutionUpdate" then
Character.Humanoid.MaxHealth += 5
Character.Humanoid.Health += 5
statManager.statsUpdate()
elseif eventtype == "enduranceUpdate" then
statManager.maxStamina += 1
statManager.statsUpdate()
elseif eventtype == "presenceUpdate" then
statManager.statsUpdate()
elseif eventtype == "fateUpdate" then
statManager.statsUpdate()
end
end)
Finally, here’s the function I’m using for testing purposes that resets all of the player’s attributes to default value. Although as stated above with the function I was using to test updating the stat values, this doesn’t seem to actually update the values of the stats for some reason. (within a server script):
statsEvent.OnServerEvent:Connect(function(plr, eventtype)
local character = plr.Character
if eventtype == "resetAll" then
plr.Stats.Strength.Value = 0
plr.Stats.Agility.Value = 0
plr.Stats.Cunning.Value = 0
plr.Stats.Intellect.Value = 0
plr.Stats.Willpower.Value = 0
plr.Stats.Constitution.Value = 0
plr.Stats.Endurance.Value = 0
plr.Stats.Presence.Value = 0
plr.Stats.Fate.Value = 0
plr.Stats.availablePoints.Value = 0
plr.Stats.maxStamina.Value = 100
plr.Stats.maxMana.Value = 100
plr.Stats.Level.Value = 1
plr.Stats.expPoints.Value = 0
character.Humanoid.MaxHealth = 100
character.Humanoid.Health = 100
wait(1)
expEvent:FireClient(plr, "updateExp")
statsEvent:FireClient(plr, "updateStats")
end
end)
I believe that’s all the relevant code. To summarize the problem I’m having, when I reset all of the stats, the stamina and mana bars do not update properly with the changes, but they do when stats are increased.
It’s also probably important to state that I have a dataStore system set up that saves and loads the player’s stats on connection and updates all of the GUI. After resetting/lowering the player’s stats the GUI doesn’t update, but when reconnecting the GUI does show the proper values that should appear after resetting/lowering the stat values. So, I think that should mean that the values actually are getting changed? I am so lost
I’ve looked at several other people’s stat systems but none of them had their maximum values tied to a stat. I did try to make a function that would fetch the stat values again because I thought maybe the module script stat variables at the top weren’t updating when the values changed. This had some success but just brought up another problem as stated above.
Lukas Raby is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.