Simple Calendar

Share custom commands, script functions, actor implementations and other Naninovel plug-ins you've created.
Post Reply
Nysalie
Posts: 29
Joined: 24 Jun 2020 20:28

Simple Calendar

Post by Nysalie »

I've been studying the engine for this past few days and I've started to work on a simple calendar extension to test things out. The Inventory extension has proven to be an invaluable tool to use as base for this.
I realize that using a simple CustomUI and a couple of variables would be an easier solution (like explained here) but this is mostly a learning exercise, with the potential to evolve into a more fleshed out time based progression system.

Currently, it is extremely bare bones but somewhat functional with some bugs that i'm still trying to understand.

The base ideia is to use a string variable to store a date in the format "yyyy-MM-dd HH:mm:ss", this string will then be parsed on runtime into a DateTime object for manipulation. I feel that this makes it easier to work with dates and time at the same time.

Right now, the only interaction implemented is a simple increment of time based on days and/or hours but this can be scaled to include any DateTime method available (like add/remove months, minutes, seconds, etc.).
This method is extracted into a command that can be used in a Nani script. The command is @addTime and has "hours": and "days:" parameters (non-required, default value for both params is 0).

There are 3 variables accessible from the Nani script:
"gameDate" - string, holding the entire date formatted like mentioned above
"day" - string, current day's number
"month" - string, current month's English name converted from the month number using CultureInfo, all caps

Can be used in script like so (check available example nani script in the project folder):
Today is {month}, {day}.

The UI is a simple black box with 2 serializable text fields that display the day and month variables. I'm also working on UI buttons to increase time through the AddTime method but they aren't working as expected, the text is updated but the date variable isn't getting serialized like it happens when the method is run through the command via Nani script. I suppose it might be related to the asynchronous black magic that i'm still trying to wrap my newbie head around :)

This is a simple rundown of the files available in the project:

Runtime/
CalendarConfiguration.cs: Implements the initial start date variable.
CalendarManager.cs: Creates a Calendar menu in the Naninovel configurations, implementing the previous Configuration. I think that some of the logic on the CalendarUI script would make more sense here but right now it's just a "skeleton file" to implement the configuration.

Runtime/UI/
CalendarControlPanelButton.cs: Simple script to use on a button to toggle visibility of the calendar.
CalendarUI.cs: Where all the logic happens with the ConvertDate, AddTime and UpdateDate methods. Buttons and States are handled here as well. Please let me know if some of the code could be refactored into another class (like the manager).

Runtime/Commands/
AddTime.cs: Implements the Command class on the AddTime method in order to be able to use it in a Nani script.

Editor/
Scripts to handle UI prefab creation when using the Create Asset menu on Unity.

Prefabs/
CalendarUI.prefab: Template prefab with UI. Created when you use the Create Asset menu. Must be assigned on Naninovel's UI Resources.

Scripts/
CalendarTest.nani: Nani script to demo the functionality implemented by the extension.

Check the project here.
Please let me know of ways to improve the code. I'm looking for help with the buttons but the issue can be deeper than that and my implementation of the engine classes might not be correct.

Other than the aforementioned buttons bug, i also noticed that if i run the Nani script (i.e update the date), if i go back to the main menu and start a new game the calendar will display the previous state of the calendar and not the initial date for a new game. Is this related to the StateManager and how it de-/serializes variables or is some fundamental error on my code that i'm not seeing.

I'll be updating the code as i'm working through the bugs.

EDIT: Regarding the state not resetting when going back to the title and starting a New Game, should I use the CalendarManager class to handle all variable logic and use the ResetService method to reset the state? It occurred to me that it might be an option but I haven't tested it yet.
Essentially the CalendarUI class would be used just to display the variables from the CalendarManager.

Elringus
admin
Posts: 521
Joined: 11 May 2020 18:03

Re: Simple Calendar

Post by Elringus »

Nice project, thanks for sharing it here!

Regarding the buttons issue, I didn't dig into the code, but most likely the value is not saved because the state is not in the rollback stack. When you save game, the top rollback snapshot in the stack is serialized. The rollback stack is updated on user interaction (continue reading, choice pick, etc) via IStateManager.PushRollbackSnapshot() method. I'd suggest invoking this method when the buttons to change date are clicked.

Regarding the calendar displaying previous state on a new game, just reset the state in CalendarManager.Reset() method (similar to how the inventory items are reset in InventoryManager.Reset()). To prevent the reset on goto commands, add [Goto.DontReset] attribute to the manager type (the attribute is only available in v1.11 pre-release, which can be downloaded on our Discord via pinned message in #support channel).

Nysalie
Posts: 29
Joined: 24 Jun 2020 20:28

Re: Simple Calendar

Post by Nysalie »

Awesome! Thanks for the tips. I'll try both suggestions. The rollback stack concept makes sense now, I was trying to @addTime on the developer console and the values weren't updating on load as well.

I see, i probably made the edit to my previous post has you were typing your answer but that was actually the direction I was heading with the CalendarManager, I'm more comfortable now knowing that it is the right path to follow. Thank you once again for all the help!

Elringus
admin
Posts: 521
Joined: 11 May 2020 18:03

Re: Simple Calendar

Post by Elringus »

You can handle the logic where you see fit, it's just IEngineService.Reset() method is useful to hook for events when the engine is reset (which happens when loading or starting a new game as well).

Nysalie
Posts: 29
Joined: 24 Jun 2020 20:28

Re: Simple Calendar

Post by Nysalie »

Success! Both of your suggestions worked flawlessly. I pushed the updates to GitHub and the project is working as expected.

For now I kept the logic in the UI class but if it becomes too complex i might refactor some of it into the CalendarManager. I created a ResetDate() method that is called from the CalendarManager.ResetService() method and resets both the variable and the text fields on the UI.

Since i don't load resources I kind of overlooked the whole InventoryManager class but now see the use of it's methods. Learned a lot with this little project, not just about Naninovel but Unity and C# in general.

I'll probably make a TMPro version as well and maybe add some new functionality but the main goal was achieved and this can be used as a simple calendar template to expand on.

Post Reply