Jump to content

Making an item glow depending on moon phase?


Recommended Posts

Hello! I'm creating a character whose perks are heavily depended on the current moon phase. Short story: new moon is good for him and full moon is bad for him. I'm trying to use the codes from the moon dial to do something with one of his character items, a book:

1. It glows with a long radius (like a campfire or something) when it's a new-moon night; shorter radius when it's quarter or half-moon; does not glow on a three-quarter and full moon night

2. If it does glow, it'll glow both on the ground and in player's pocket

3. The name and the description of this book changes on a new-moon night, and will change back when new-moon's over

At the moment I've only attempted to do something to the first perk. It does glow on when I placed it on the ground. But it will just always do that even if it's on a three-quarter moon night. If I leave it on the ground, then it'll stop glowing when the morning arrives. However, if I pick it up and put it down, it will start glowing no matter what moon phase or time of the day it is today. I'm not sure which part of the code am I doing it wrong. I have attached the file underneath. The radius were not corresponding to my perk 1 description because I was trying to test each moon phase see which radius is it showing now (by change each phase to radius 15, which should be very obvious). But the result was none of them! One by one I changed each phase to radius 15, but the book never glows with a 15 radius in the game.

I have no idea how should I do perk 2. I know how to make a glowing tool that glows when held in hands. But this item is a book that I cannot equip in hands, which I'm not too sure how can I make it glow in the pocket.

I've tried to do something to perk 3 in my character's modmain by doing something similar to perk 1. But the game just pop up an error due to 'TheWorld' thing, so maybe I'm doing it totally wrong. A screenshot of it is attached underneath.

image.thumb.png.82b3ba6ec32cc2e5e592c03a3aabec44.png

 

And just wondering if I was on the right track for perk 1 with the coding, can I do something like that to my character's lua file so he can constantly lose sanity during a full moon? If so, how do I code the 'constantly lose sanity' part? I didn't find anything like that except the dapperness component, but that seems to be for equipable items only? 

 

Thank you!

astolfo_book.lua

Link to comment
Share on other sites

Your code for the lightstate switching looks great :) 

6 hours ago, menghuancat said:

I've tried to do something to perk 3 in my character's modmain by doing something similar to perk 1. But the game just pop up an error due to 'TheWorld' thing, so maybe I'm doing it totally wrong. A screenshot of it is attached underneath.

modmain.lua is outside the regular GLOBAL game scope, and as such, when you want to use things like TheWorld, which is a part of that GLOBAL game scope, you need to do GLOBAL.TheWorld. If you use it frequently or in a loop or any continuously called code, you can make a local reference at the top of your modmain.lua as such:

local TheWorld = GLOBAL.TheWorld
-- After the line above, you can now refer to GLOBAL.TheWorld as simply TheWorld

 

In order to get 

6 hours ago, menghuancat said:

And just wondering if I was on the right track for perk 1 with the coding, can I do something like that to my character's lua file so he can constantly lose sanity during a full moon? If so, how do I code the 'constantly lose sanity' part? I didn't find anything like that except the dapperness component, but that seems to be for equipable items only?

Here is a post showing how to do a custom health regen which is enabled and disabled through function calls. You can easily change it to be sanity loss instead, and then use those function calls in your onmoonphasechagned() function, and enable or disable the sanity loss depending on which moonphase it is.

About perk 2, I'm not sure how to best handle making it glow around the player while the book is in their inventory. I can tell you that as long as the book is in the player's inventory, the inventoryitem component of the book will reference the player instance in its "owner" variable. When it is in a chest or backpack, the "owner" variable will reference the instance of the container. When lying on the ground, the "owner" variable should be nil. I can't remember who the owner is when the book is "in the mouse". You will have to make some onpickup and ondropped functions and set those on the book's inventoryitem component (there are functions for that), so you can switch between the different ways of adding a light source around the player. One thing you probably don't want to do, is to use and change the player's own light source, because it is used by the game when they get electrocuted and such. It think it might be best to make your own entity which has a light source, and then move that entity around where the book is (and when the book is in an inventory/container, use the position of the instance of the "owner" variable. If I were you, I'd get the other parts working first, and solve the "glow while in the inventory" last.

Edited by Ultroman
Link to comment
Share on other sites

Thanks for your help!

I've tried adding local TheWorld = GLOBAL.TheWorld at the beginning of the modmain file as you've said, but still got the same TheWorld error (saying it's a nil).

And for both the book file and character file, apparently, I think I'm not handling the "check if it's full moon/new moon" part correctly. Can you please have a look at how can I fix it?

For the book: At the moment, the book is glowing no matter what moon phase it is. Now I disabled all the moon-phase-checking for the book and made it just a glowing book. But it still glows even when I did inst.Light:Enable(false) (trying to disable the glowing). I was just wanted to test which part went wrong, but now it seems like everything is wrong from the beginning.

For the character: My attempt was when it's night time, I call a function that checks if it's full moon or not. If it is, then it will call your function. And when it's day time, it will call the disableRegen() function. However, it's not working, so I must've made mistakes with the checking moon phase part.

 

And thank you for your suggestion with the glowing in pocket :D I'll have look at the heatrock file see if I can do something similar! (hopefully I'll went well with this one ;-;

astolfo.lua

astolfo_book.lua

modmain.lua

Link to comment
Share on other sites

5 hours ago, menghuancat said:

I've tried adding local TheWorld = GLOBAL.TheWorld at the beginning of the modmain file as you've said, but still got the same TheWorld error (saying it's a nil).

The code below reacts to changes in the moon phase, and also makes sure to set the strings immediately when the world has been initialized, instead of waiting for the state to change. This is the same technique used by the Moondial prefab.

Replace this

if TheWorld.state.moonphase == "new" then
	STRINGS.NAMES.ASTOLFO_BOOK = "破却宣言"
	STRINGS.RECIPE_DESC.ASTOLFO_BOOK = "魔女罗杰斯媞拉授予阿斯托尔福的魔导书"
	STRINGS.CHARACTERS.GENERIC.DESCRIBE.ASTOLFO_BOOK = "蕴含着可怕魔力的宝具"
else
	STRINGS.NAMES.ASTOLFO_BOOK = "魔术万能攻略书"
	STRINGS.RECIPE_DESC.ASTOLFO_BOOK = "一本不是特别清楚可以拿来干什么的书"
	STRINGS.CHARACTERS.GENERIC.DESCRIBE.ASTOLFO_BOOK = "看上去好像很厉害的样子"
end

with this

-- The function takes an inst and the current phase as parameters, because those are the parameters
-- passed on to the watcher when the "moonphase" state changes.
local reactToMoonPhase = function(inst, phase)
	-- If there is a value in the "phase" parameter, use that, otherwise read the state directly from the world.
	if phase ~= nil and phase == "new" or TheWorld.state.moonphase == "new" then
		STRINGS.NAMES.ASTOLFO_BOOK = "破却宣言"
		STRINGS.RECIPE_DESC.ASTOLFO_BOOK = "魔女罗杰斯媞拉授予阿斯托尔福的魔导书"
		STRINGS.CHARACTERS.GENERIC.DESCRIBE.ASTOLFO_BOOK = "蕴含着可怕魔力的宝具"
	else
		STRINGS.NAMES.ASTOLFO_BOOK = "魔术万能攻略书"
		STRINGS.RECIPE_DESC.ASTOLFO_BOOK = "一本不是特别清楚可以拿来干什么的书"
		STRINGS.CHARACTERS.GENERIC.DESCRIBE.ASTOLFO_BOOK = "看上去好像很厉害的样子"
	end
end

AddPrefabPostInit("world", function(inst)
	-- We set up a watcher which calls the given function whenever the "moonphase" state changes.
	inst:WatchWorldState("moonphase", reactToMoonPhase)
	-- Since we want to start off with the right setting, we also call our function as soon as the world
	-- has been initialized, instead of waiting for the watcher to be triggered.
	-- We don't have a value to pass as the "phase" parameter, so we leave it blank. The function
	-- will then instead fetch the current state directly from TheWorld.
	reactToMoonPhase(inst)
end)
Edited by Ultroman
Link to comment
Share on other sites

6 hours ago, menghuancat said:

And for both the book file and character file, apparently, I think I'm not handling the "check if it's full moon/new moon" part correctly. Can you please have a look at how can I fix it?

You are using the wrong casing for the event names.

Instead of

inst:WatchWorldState("isDay", OnIsDay)

it's

inst:WatchWorldState("isday", OnIsDay)

You can use a similar code-structure as I did in the STRINGS-code above, in both your character and your book.

Just like the lines you have commented out in your book's fn() right now, and the lightstate code you have. Replace those with my equivalents below, and your book should work:

local lightstates =
{
    new                 = {override=0.50,   enabled=true,  radius=25.00},
    quarter             = {override=0.00,   enabled=false,  radius=0.00},
    half                = {override=0.00,   enabled=false,   radius=0.00},
    threequarter        = {override=0.00,   enabled=false,   radius=0.00},
    full                = {override=0.00,   enabled=false,   radius=0.00},
}

local function reactToNight(inst)
	local lightstate = lightstates[TheWorld.state.moonphase]
	-- Not sure if you need this first light override for the anim. It is in the moondial code, so maybe.
	inst.AnimState:SetLightOverride(lightstate.override)
	inst.Light:Enable(lightstate.enabled)
	inst.Light:SetRadius(lightstate.radius)
end

local function reactToDay(inst)
	inst.Light:Enable(false)
end

And then in the fn():

-- We set up watchers which call the given function whenever the given state is changed to "true".
inst:WatchWorldState("isnight", reactToNight)
inst:WatchWorldState("isday", reactToDay)

-- Since we want to start off with the right setting, we also call one of our functions as soon as the
-- world has been initialized, instead of waiting for the watchers to be triggered.
-- We don't have to pass any values to these, except for the inst, since these particular watchers
-- just trigger when the state is set to "true", so there is no other information for them to pass.
-- If it is currently night, then we call our night-function, and otherwise we call our day-function,
-- just in case.
if TheWorld.state.isnight then
	reactToNight(inst)
else
	reactToDay(inst)
end

 

As for your character's code, there are two problems. This is your current code:

inst:WatchWorldState("isNight", isitfullmoon(inst))	
inst:WatchWorldState("isDay",disableRegen())
  1. Same problem as before. "isNight" should be "isnight" and "isDay" should be "isday".
  2. When hooking up functions using WatchWorldState or ListenForEvent, you must NOT include the parentheses for the functions you pass.

This is how it should look:

inst:WatchWorldState("isnight", isitfullmoon)	
inst:WatchWorldState("isday", disableRegen)

Other than that, your character's code should work.

Edited by Ultroman
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...