ModuleScript Not Waiting

Im making a shield script that gets destroyed and stuns the player when the shields health becomes 0. Im using code that changes the baseplates color as a placeholder before writing the actual stun function. The function is inside a ModuleScript, my problem is when the function is fired, instead of waiting the set amount of time, it’ll skip the wait.

Script:

while wait() do                              
			if Health.Value <= 0 then        -- If shields health reaches 0
			
			Health.Value = 0
			
                        ---- Destroy Shield ----
			ShieldClone:Destroy() 
			ShieldWeld:Destroy() 
			ShieldGyro:Destroy()
			ShieldAnim:Stop()
			hum.AutoRotate = true

                        --- Stun Player ---
			local stun = require(game.ServerScriptService.StatusEffectIndex)
            local stuntime = 10
			stun.Stun(stuntime)
		
				break
			end

ModuleScript:

local StatusEffects = {}
	
function StatusEffects.Stun(stuntime)
	print("stunned")
	workspace.BasePlates.Baseplate.BrickColor = BrickColor.new("Baby blue")
	wait(stuntime)
	workspace.BasePlates.Baseplate.BrickColor = BrickColor.new("Really red")
	end
	


return StatusEffects

Video:

As you can see in the video, when the shield is broken(dissapears) the baseplate doesn’t become blue before becoming red. How do I make the ModuleScript wait the given time?

Is there any particular reason why the variable stuntime is an argument passed through the the stun function instead of being declared in the module script? If you change that it could work in your favor.

Also the baseplate is turning blue, but only for maybe a frame or two. I think the variable being passed through the stun function isn’t properly getting through, so maybe print(stuntime) would help debug the code you have.

Arbitrary stun times. You could be having several actions in your game which require the stun function but need it to occur for different lengths of time. It makes more sense to have an outside script tell the function how much time the action should last for instead of making it a declaration in the ModuleScript because that’ll cause all stuns to uniformly wait n seconds.

1 Like

Fair point. I get your reason of thinking.

That being said, I don’t why why this isn’t in the form of a class in that case. They’re far more versatile in this kind of scenario.

An example:

local StatusEffects = {}
StatusEffects.__index = StatusEffects
StatusEffects.StunDuration = 10 -- a default value

function StatusEffects:Stun()
    print("stunned")
    workspace.BasePlates.Baseplate.BrickColor = BrickColor.new("Baby blue")
    wait(self.StunDuration)
    workspace.BasePlates.Baseplate.BrickColor = BrickColor.new("Really red")
    end
end

function StatusEffects.new(stunDuration)
    local self = {}
    if stunDuration then self.StunDuration = stunDuration end -- To account for no input.
    return setmetatable(self, StatusEffects)
end

Then in the script calling this function:

local StatusEffects = require(game.ServerScriptService.StatusEffectIndex).new(10) -- duration of the stun

-- later on
StatusEffects:Stun()

This is by no means a perfect solution but it gets on the right track.

EDIT: I have been told that this is over the top, and after looking at it, I can see why. Thanks for pointing that out

The right value Is shown when I print “stuntime” in both the script and the modulescript

Is there anything else that could be potentially setting the color of the baseplate?

Also, I’m not sure that it’s a good idea to call the function with a loop like this. I’ve seen a few people have issues with it because it sometimes calls the intended functions more than once. Double check to make sure that the function isn’t called more than once.

It’s over the top to be using OOP here. This is a simple stun script. OOP is good for requiring object state and that’s not what’s happening here. Object state isn’t being stored, so there’s no need to have a class here. That’s treading into overengineering grounds.

Really the issue to be tackling here is the wait part.

2 Likes

I don’t think the issue is the wait at this point, the variable is passed successfully, and I can’t see the wait() function failing like this. I suspect that something is up with other parts of the code.

The loop does seem to be the problem because when I call the function outside of the loop the problem doesn’t occur, but the condition inside the loop have to be met in order to stun the player. Is there a way to make sure these conditions are met without using the loop?

So the function works properly without the loop, that’s the issue then. You can use the Changed event to detect any changes.

Here’s an example

local StunModule = require(game.ServerScriptService.StatusEffectIndex)
local stuntime = 10 -- good practice to keep this at the top if they don't change much.

-- code to register shield, I don't know OP's code, so he can handle this.

local connection; connection = Health.Changed:Connect(function(newHealth)
    if newHealth <= 0 then
        connection:Disconnect()
        -- Code to handle shield destruction
        ShieldClone:Destroy() 
        ShieldWeld:Destroy() 
        ShieldGyro:Destroy()
        ShieldAnim:Stop()
        hum.AutoRotate = true
        
        StunModule.Stun(stuntime)
    end
end)

So I tried printing “stuntime” in the ModuleScript again and its printing nil which is strange because I couldv’e swore it wasn’t before. My bad for the false information :sweat_smile:

At least you found a source of your problem. Maybe you can do a check on the function to see if the value given is nil.

Something like this?

if not stuntime then stuntime = 10 end

It’s not a great fix, but until you find the source of the nil arguments, this guard clause should help you out.

Ill figure it out eventually but thanks for all the help, ill use this code until i find the solution.

1 Like