Jump to content

Modding a Custom Character with Changing Stats Based on Moon Phase


Recommended Posts

I'm very new to modding, as in first mod I've tried to make new. I've created my own custom character and everything is done - except his special abilities. I'm trying to get it so that his normal health is 150, on a new moon it's 50, on a quarter moon it's 170, on a half moon it's 200, and on a full moon it's 300. I'd also love to have a damage multiplier when it's a half moon and full moon. A very detailed explanation and help would be greatly appreciated!!

Link to comment
Share on other sites

I would also like to know how to change the damage stat. based on times of day. I'm pretty new to modding, and am trying to learn as much as possible!

Edited by GreggZumbari1
I could've worded the last bit better. I have OCD, and I do this a lot. Sorry!
Link to comment
Share on other sites

Hmm, this seems like a tough idea, but it's possible.

I'd take a look at the werebeast, worldstate, and clock components. 

 

Something along the lines of

Spoiler

 

if TheWorld.iswaxingmoon = true then

      inst.components.health:SetMaxHealth(150)

else if TheWorld.isfullmoon = true then

      inst.components.health:SetMaxHealth(300)

else if TheWorld.isnewmoon = true then

      inst.components.health:SetMaxHealth(50)

end


 

Could help you. I doubt this itself will work, this is just a rough idea I have for how it might look.

Link to comment
Share on other sites

@flyingxmango, welcome to the forums!

Add this to your character prefab file before your master_postinit:

local function onmoonphasechange(inst, phase)
	if not inst:HasTag("playerghost")			--only apply if the player is alive
		local health_max = 150
		local damagemult = 1
		
		if phase == "new" then
			health_max = 50
		elseif phase == "quarter" then
			health_max = 170
		elseif phase == "half" then
			health_max = 200
			damagemult = 1.5
		elseif phase == "threequarter" then
			health_max = 250
		elseif phase == "full" then
			health_max = 300
			damagemult = 2
		end
		
		--SetMaxHealth set the current health to the max, so use this workaround to keep the current percentage
		local health_percent = inst.components.health:GetPercent()
		inst.components.health:SetMaxHealth(health_max)
		inst.components.health:SetPercent(health_percent, true)
		
		--we do this check in case there are other multipliers applied
		local newdamagemult = (inst.components.combat.damagemultiplier or 1)
		                     / (inst.moonphasedamagemult or 1)
		                     * damagemult
		
		inst.components.combat.damagemultiplier = newdamagemult
		inst.moonphasedamagemult = damagemult
	end
end

and add this to your master_postinit:

inst:WatchWorldState("moonphase", onmoonphasechange)
onmoonphasechange(inst, TheWorld.state.moonphase)

A world state watcher does what you'd expect: it calls a function when the world state changes passing the state as the second parameter. There are five states for the moonphase: "new", "quarter", "half", "threequarter" and "full". There's a related state you might be interested in, namely iswaxingmoon (TheWorld.state.iswaxingmoon), which can be true or false.

For the health, you need to keep track of the current percentage before changing the maximum health, since SetMaxHealth sets not only the maximum health but also the current health to the new maximum.

For the damage multiplier, since only one bonus multiplier can be applied (other mods, for example), you want to keep track of the multiplier you are applying to then compensate for it, or else it will get messy (and won't work properly).

Also note: all code untested. Might not work.

--

@GreggZumbari1, check out Abigail's prefab file, specifically inst:WatchWorldState("phase", updatedamage) and updatedamage(inst, TheWorld.state.phase) in her fn function and the whole updatedamage(inst, phase) function.

Link to comment
Share on other sites

4 hours ago, alainmcd said:

@flyingxmango, welcome to the forums!

Add this to your character prefab file before your master_postinit:


local function onmoonphasechange(inst, phase)
	if not inst:HasTag("playerghost")			--only apply if the player is alive
		local health_max = 150
		local damagemult = 1
		
		if phase == "new" then
			health_max = 50
		elseif phase == "quarter" then
			health_max = 170
		elseif phase == "half" then
			health_max = 200
			damagemult = 1.5
		elseif phase == "threequarter" then
			health_max = 250
		elseif phase == "full" then
			health_max = 300
			damagemult = 2
		end
		
		--SetMaxHealth set the current health to the max, so use this workaround to keep the current percentage
		local health_percent = inst.components.health:GetPercent()
		inst.components.health:SetMaxHealth(health_max)
		inst.components.health:SetPercent(health_percent, true)
		
		--we do this check in case there are other multipliers applied
		local newdamagemult = (inst.components.combat.damagemultiplier or 1)
		                     / (inst.moonphasedamagemult or 1)
		                     * damagemult
		
		inst.components.combat.damagemultiplier = newdamagemult
		inst.moonphasedamagemult = damagemult
	end
end

and add this to your master_postinit:


inst:WatchWorldState("moonphase", onmoonphasechange)
onmoonphasechange(inst, TheWorld.state.moonphase)

A world state watcher does what you'd expect: it calls a function when the world state changes passing the state as the second parameter. There are five states for the moonphase: "new", "quarter", "half", "threequarter" and "full". There's a related state you might be interested in, namely iswaxingmoon (TheWorld.state.iswaxingmoon), which can be true or false.

For the health, you need to keep track of the current percentage before changing the maximum health, since SetMaxHealth sets not only the maximum health but also the current health to the new maximum.

For the damage multiplier, since only one bonus multiplier can be applied (other mods, for example), you want to keep track of the multiplier you are applying to then compensate for it, or else it will get messy (and won't work properly).

Also note: all code untested. Might not work.

--

@GreggZumbari1, check out Abigail's prefab file, specifically inst:WatchWorldState("phase", updatedamage) and updatedamage(inst, TheWorld.state.phase) in her fn function and the whole updatedamage(inst, phase) function.

You, my friend, are magic.

however, I'm getting an error message when I try to load the character,

[string "scripts/mainfunctions.lue"]:90: Error loading file prefabs/wells
[string ".../mods/wells/scripts/prefabs/wells.lua"]:46: 'then' expected near 'local'
LUA ERROR stack traceback:
    = [C] in function 'assert'
    scripts/mainfunctions.lua(90,1)
    = (tail call) ?
    = [C] in function 'xpcall'
    scripts/mods.lua(131,1)
    scripts/mods.lue(570,1) in function 'RegisterPrefabs'
    scripts/gamelogic.lua(226,1) in function 'LoadAssets'

How could I fix this?

Link to comment
Share on other sites

13 minutes ago, flyingxmango said:

[string ".../mods/wells/scripts/prefabs/wells.lua"]:46: 'then' expected near 'local'

That's a non-workshop mod (probably your character?). It means in the file scripts/prefabs/wells.lua for that wells mod there's somewhere between lines 1 and 46 an if that is expecting a then.

Edited by alainmcd
Link to comment
Share on other sites

11 minutes ago, alainmcd said:

That's a non-workshop mod. It means in the file scripts/prefabs/wells.lua for that wells mod there's somewhere between lines 1 and 46 an if that is expecting a then.

I got it! I just had to add a 'then' in the first line you gave me, thank you! It works perfectly!!

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...