Jump to content

Need help with Speed stat related to Wetness


Recommended Posts

So, somehow I'm actually on college to learn programming but LUA's kicking my ass hard.

I need some help making a function (or anything, really) that makes him get a speed boost on two separate wetness levels, as in:

>29, speed is multiplied from 1 to 1.05

>59, speed is multiplied from 1 to 1.2

Everything else on the code is sorted out correctly, this is the only thing that's being a problem to me right now. An optional thing I'd like to add but, once again, is optional and not required, is making held weapons slip more easily than on a vanilla character since he's pretty clumsy.

I tried some codes I found on the forums, but none of them worked properly. One did manage to kiiiind of work, until I got the wetness above 59. Then the game crashed.

Current attempted code screenshots as follows:

BPv7SR2.png

(on local functions before master_postinit)

 

Tu3xFAR.png

inside master_postinit

I've tried other methods but this one was the least buggy one up to now.

 

Edited by Frigfrid
Link to comment
Share on other sites

Note: Please read the last part of the post for an alternative approach, before using these code snippets.

This isn't the prettiest it can be, but it'll work. This is using an event listener, like in your code. What you were lacking, was actually setting the speed modifier on the player.

local function onmoisturedelta(inst)
	if inst.components.moisture:IsWet() then
		-- Remember to give it a default value at the end of such an inline conditional declaration.
		local speed = inst.wetness > 59 and 1.2 or inst.wetness > 29 and 1.05 or 1.0
		if speed == 1.0 then
			-- If speed multiplier is to be 1.0, remove it.
			inst.components.locomotor:RemoveExternalSpeedMultiplier(inst, "myuniquemodifierkey")
		else
			-- When using the same modifier key, it will just replace any existing modifier with the same key.
			inst.components.locomotor:SetExternalSpeedMultiplier(inst, "myuniquemodifierkey", speed)
		end
	else
		-- Remove modifier if the player is no longer wet.
		inst.components.locomotor:RemoveExternalSpeedMultiplier(inst, "myuniquemodifierkey")
	end
end

To save on CPU cycles, we can save the last result and only react when the result changes.

local function onmoisturedelta(inst)
	if inst.components.moisture:IsWet() then
		-- Remember to give it a default value at the end of such an inline conditional declaration.
		local speed = inst.wetness > 59 and 1.2 or inst.wetness > 29 and 1.05 or 1.0
		
		-- If we have a value in the variable inst.myModNameLastSpeedModifierResult, then
		-- we know what the last result was. If the new result is the same, exit early.
		if inst.myModNameLastSpeedModifierResult and speed == inst.myModNameLastSpeedModifierResult then
			return
		end
		
		-- Otherwise, save the new speed value to inst.myModNameLastSpeedModifierResult
		inst.myModNameLastSpeedModifierResult = speed
		
		-- Apply or remove the speed modifier as you see fit.
		if speed == 1.0 then
			-- If speed multiplier is to be 1.0, remove it.
			inst.components.locomotor:RemoveExternalSpeedMultiplier(inst, "myuniquemodifierkey")
		else
			-- When using the same modifier key, it will just replace any existing modifier with the same key.
			inst.components.locomotor:SetExternalSpeedMultiplier(inst, "myuniquemodifierkey", speed)
		end
	else
		-- Remove modifier if the player is no longer wet.
		inst.components.locomotor:RemoveExternalSpeedMultiplier(inst, "myuniquemodifierkey")
	end
end

 

To save even more on CPU cycles, you can use a periodic task instead of ListenForEvent. An event listener listening to changes in such things as temperature, health, sanity, hunger, moisture, etc., is potentially called several times per frame. We do not need buffs like this to be evaluated several times per frame. With a periodic task, we can make it check every 1 second or every 0.5 seconds. Granted, the periodic task then always runs during the summer while the player will never get wet, but the performance impact of such a simple check is negligible when it only happens once every 30 or 60 frames.

Look at this guide for how to make buffs using periodic tasks. There's even a movement speed example.

Edited by Ultroman
Link to comment
Share on other sites

12 hours ago, Ultroman said:

Note: Please read the last part of the post for an alternative approach, before using these code snippets.

This isn't the prettiest it can be, but it'll work. This is using an event listener, like in your code. What you were lacking, was actually setting the speed modifier on the player.


local function onmoisturedelta(inst)
	if inst.components.moisture:IsWet() then
		-- Remember to give it a default value at the end of such an inline conditional declaration.
		local speed = inst.wetness > 59 and 1.2 or inst.wetness > 29 and 1.05 or 1.0
		if speed == 1.0 then
			-- If speed multiplier is to be 1.0, remove it.
			inst.components.locomotor:RemoveExternalSpeedMultiplier(inst, "myuniquemodifierkey")
		else
			-- When using the same modifier key, it will just replace any existing modifier with the same key.
			inst.components.locomotor:SetExternalSpeedMultiplier(inst, "myuniquemodifierkey", speed)
		end
	else
		-- Remove modifier if the player is no longer wet.
		inst.components.locomotor:RemoveExternalSpeedMultiplier(inst, "myuniquemodifierkey")
	end
end

To save on CPU cycles, we can save the last result and only react when the result changes.


local function onmoisturedelta(inst)
	if inst.components.moisture:IsWet() then
		-- Remember to give it a default value at the end of such an inline conditional declaration.
		local speed = inst.wetness > 59 and 1.2 or inst.wetness > 29 and 1.05 or 1.0
		
		-- If we have a value in the variable inst.myModNameLastSpeedModifierResult, then
		-- we know what the last result was. If the new result is the same, exit early.
		if inst.myModNameLastSpeedModifierResult and speed == inst.myModNameLastSpeedModifierResult then
			return
		end
		
		-- Otherwise, save the new speed value to inst.myModNameLastSpeedModifierResult
		inst.myModNameLastSpeedModifierResult = speed
		
		-- Apply or remove the speed modifier as you see fit.
		if speed == 1.0 then
			-- If speed multiplier is to be 1.0, remove it.
			inst.components.locomotor:RemoveExternalSpeedMultiplier(inst, "myuniquemodifierkey")
		else
			-- When using the same modifier key, it will just replace any existing modifier with the same key.
			inst.components.locomotor:SetExternalSpeedMultiplier(inst, "myuniquemodifierkey", speed)
		end
	else
		-- Remove modifier if the player is no longer wet.
		inst.components.locomotor:RemoveExternalSpeedMultiplier(inst, "myuniquemodifierkey")
	end
end

 

To save even more on CPU cycles, you can use a periodic task instead of ListenForEvent. An event listener listening to changes in such things as temperature, health, sanity, hunger, moisture, etc., is potentially called several times per frame. We do not need buffs like this to be evaluated several times per frame. With a periodic task, we can make it check every 1 second or every 0.5 seconds. Granted, the periodic task then always runs during the summer while the player will never get wet, but the performance impact of such a simple check is negligible when it only happens once every 30 or 60 frames.

Look at this guide for how to make buffs using periodic tasks. There's even a movement speed example.

Hey, thanks a lot for replying, this one actually managed to work fine! I'll try to do the other method later on if it's needed (ie, it lags on other computers) since I have a tester with a weaker CPU. This helped me a lot

Thanks once again :')

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
  • Create New...