My client script does a wait function until an attribute changes its value which is through the server. The problem is that while the server changes the attribute’s value, and recognises the change, the client never does, for some reason.
Pls help!
My client script does a wait function until an attribute changes its value which is through the server. The problem is that while the server changes the attribute’s value, and recognises the change, the client never does, for some reason.
Pls help!
Can you please provide the relevant server side and client side code, otherwise we can’t assist further.
alr but the code is really long
Send the relevant parts only then.
Make sure you enclose it in a codeblock.
i.e. (copy and paste the below)
```
– CODE GOES HERE
```
client
-- Function to run the clicked ability in the weapon
local function onButtonActivated()
-- Sends the function to the server via a remote event to run the ability with its settings
ActivateAbility:FireServer(attack, weapon)
-- Setting the cooldown screen and initates cooldown as a coroutine depending on the ability that's getting the cooldown
local function abilitywait(ability, waitingTime)
for i = waitingTime, 0, -0.1 do
-- set the text of the cooldown screen to the current number rounded up to one decimal place
ability.GuiCooldown.Value = i
ability.Shadow.Cooldown.Text = math.ceil(ability.GuiCooldown.Value * 10) / 10
task.wait(0.1)
-- If the existing cooldown is lower than the GuiCooldown value, then drop it to avoid overlapping
if ability.GuiCooldown.Value ~= i then
return
end
end
-- Making the button usable after the cooldown
ability.Active = true
ability.Shadow.Visible = false
end
-- Handles the ability's cooldown as well as preventing other abilities to be run immediately
for i, ability in pairs(button.Parent:GetChildren()) do
if ability:IsA("ImageButton") then
-- Disables all buttons after an ability has been activated
ability.Active = false
ability.Shadow.Visible = true
local boolValueObject = attack:GetAttribute("HoldCooldown")
local function startCooldown()
-- Check which cooldown to apply
if ability == button then
coroutine.wrap(abilitywait)(ability, attackConfig["Cooldown"])
elseif ability.GuiCooldown.Value < 2 then
coroutine.wrap(abilitywait)(ability, 2)
end
end
if boolValueObject == nil or boolValueObject == false then
print(boolValueObject)
startCooldown() -- Start cooldown immediately if no boolValue or it's already false
continue
end
if ability == button then
AddPlaceholderSentry(attack)
-- If the boolValue exists and is true, wait until it's false before starting the cooldown
coroutine.wrap(function()
warn(attack.Parent.Parent.Parent)
-- Wait until the boolValue is false
while boolValueObject == true do
RunService.Heartbeat:Wait()
end
startCooldown() -- Start the cooldown after the boolValue becomes false
end)()
end
end
end
end
if sentryToSpawn and input.UserInputType == Enum.UserInputType.MouseButton1 then
SpawnSentry:FireServer(sentryToSpawn.Name, sentryToSpawn.PrimaryPart.CFrame)
RemovePlaceholderSentry()
end
end)
server
local function SendSentryInfo(player, name, cframe, weapon)
-- Ability will actually place the tower, this is just sending info to the module script
local value1 = Instance.new("StringValue")
value1.Name = "NameValue"
value1.Value = name
value1.Parent = weapon
local value2 = Instance.new("CFrameValue")
value2.Name = "CFrameValue"
value2.Value = cframe
value2.Parent = weapon
local config = nil
-- Allow for client cooldown to start and ability script to place the sentry in the server
for i, v in weapon.Abilities:GetChildren() do
if v.Sentry.Value.Name ~= name then
continue
end
config = v
end
config:SetAttribute("HoldCooldown", false)
warn(config.Parent.Parent.Parent)
end
Players.PlayerAdded:Connect(function(player)
player.CharacterAdded:Connect(function(character)
local backpack = player:WaitForChild("Backpack")
backpack.ChildAdded:Connect(function(weapon)
if not weapon:FindFirstChild("Config") then
SpawnSentry.OnServerEvent:Connect(function(player, name, cframe)
SendSentryInfo(player, name, cframe, weapon)
end)
return
end
end)
end)
end)
module script when the function is stored
["Gun Sentry"] = function(player, attack, config)
print(player, attack, config)
local humanoid = player.Character.Humanoid
local weapon = attack.Parent.Parent
humanoid.WalkSpeed = 0
player.PlayerGui.CharacterGui.Abilities.Template.Modal = true
while attack:GetAttribute("HoldCooldown") ~= false do
wait()
end
warn(attack:GetAttribute("HoldCooldown"))
local name = weapon:WaitForChild("NameValue")
local cframe = weapon:WaitForChild("CFrameValue")
print(name, cframe)
local sentryExists = weapon.Sentries:FindFirstChild(name.Value)
if not sentryExists then
warn("Requested sentry does not exist")
attack:SetAttribute("HoldCooldown", true)
return
end
local newSentry = sentryExists:Clone()
newSentry.HumanoidRootPart.CFrame = cframe.Value
newSentry.Parent = workspace
task.wait() -- the model doesnt actually appear it just fires unless if i add this wait
for i, v in newSentry:GetDescendants() do
if not v:IsA("BasePart") then
continue
end
v.Anchored = true
end
player.PlayerGui.CharacterGui.Abilities.Template.Modal = false
humanoid.WalkSpeed = 25
-- task.wait(0.1)
attack:SetAttribute("HoldCooldown", true)
end,
Its all centred on the hold cooldown value
Are you using Instance:GetAttributeChangedSignal(AttributeName):Wait()
?
nope, is it better to use???
The issue is this (a couple of lines were removed for clarity):
local boolValueObject = attack:GetAttribute("HoldCooldown")
while boolValueObject == true do
RunService.Heartbeat:Wait()
end
You are only ever setting the value of boolValueObject once.
You should instead be doing
local boolValueObject = attack:GetAttribute("HoldCooldown")
while boolValueObject == true do
RunService.Heartbeat:Wait()
boolValueObject = attack:GetAttribute("HoldCooldown")
end
or
local boolValueObject = attack:GetAttribute("HoldCooldown")
while boolValueObject = attack:GetAttribute("HoldCooldown")== true do
RunService.Heartbeat:Wait()
end
or, as suggested by sonic_848:
attack:GetAttributeChangedSignal("HoldCooldown"):Wait()
ok I actually tried this properly and it works
it took me another hour to fully fix the cooldown to how I intended it to be as another problem had sprung up that wasn’t part of the problem I wrote about in the post
onButtonActivated function
-- Function to run the clicked ability in the weapon
local function onButtonActivated()
-- Sends the function to the server via a remote event to run the ability with its settings
ActivateAbility:FireServer(attack, weapon)
-- Setting the cooldown screen and initates cooldown as a coroutine depending on the ability that's getting the cooldown
local function abilitywait(ability, cooldown)
local waitingTime = nil
ability.Shadow.Cooldown.Visible = true
-- Check if the button is the same as the activated button
if ability == button then
waitingTime = cooldown
else
-- Start cooldown with a default value if not
if ability.GuiCooldown.Value < 2 then
waitingTime = 2
end
end
for i = waitingTime, 0, -0.1 do
-- set the text of the cooldown screen to the current number rounded up to one decimal place
ability.GuiCooldown.Value = i
ability.Shadow.Cooldown.Text = math.ceil(ability.GuiCooldown.Value * 10) / 10
task.wait(0.1)
-- If the existing cooldown is lower than the GuiCooldown value, then drop it to avoid overlapping
if ability.GuiCooldown.Value ~= i then
return
end
end
-- Making the button usable after the cooldown
ability.Active = true
ability.Shadow.Visible = false
end
-- Handles the ability's cooldown as well as preventing other abilities to be run immediately
for _, ability in pairs(button.Parent:GetChildren()) do
-- Only process ImageButton abilities
if not ability:IsA("ImageButton") then
continue
end
-- Disable all ability buttons after activation to prevent immediate reactivation
ability.Active = false
ability.Shadow.Visible = true
-- Check if there's a HoldCooldown attribute
local boolValueObject = attack:GetAttribute("HoldCooldown")
-- If no HoldCooldown or it is false, start cooldown immediately
if boolValueObject == nil or boolValueObject == false then
coroutine.wrap(abilitywait)(ability, attackConfig["Cooldown"])
else
-- If the boolValue exists and is true, wait until it's set to false before starting the cooldown
ability.Shadow.Cooldown.Visible = false
if ability == button then
AddPlaceholderSentry(attack) -- Add placeholder sentry for this ability
end
-- Wait for HoldCooldown to change to false, then start cooldown
coroutine.wrap(function()
attack:GetAttributeChangedSignal("HoldCooldown"):Wait()
abilitywait(ability, attackConfig["Cooldown"])
end)()
end
end
end
This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.