Extra Menu Page?

Hello!

I’m quite out of practice with programming, so there may well be an obvious way to do exactly this that I haven’t yet put together; I appreciate your patience.

My idea is, in essence, creating a duplicate of the Skills or even Inventory section of the Menu. From there, I’d like to rework that duplicate section to serve as a way of tracking your relationship with various NPCs (rather than what the duplicate page originally kept track of)– hence my initially thinking that the Skills section might be a good starting point, since conventional relationship values mechanics tend to note ‘You’re This Close To [The Next Heart]’ or what have you!

Unfortunately, I’m stumbling on how I’d execute that first part! Would it be a matter of making a new YAML file and basically copying the code in the pre-existing [Let’s Say Skills] YAML file with substitutions of Relationships for Skills and then adding a Relationships section to the main config file to direct it? It being that easy felt naive of me, so I got into the narrat-engine and started looking at the src component .vue and config .ts files…which quickly had me realizing I was punching above my weight class and should ask for help before I start copy-pasting wily-nily and break the whole thing. C:

Thank you!

Yeah it’s definitely not that easy, but it’s possible with the plugin system. The skills/inventory sections of the menu are just pieces of UI, but they need to plug into data. The yaml files are just config files for the features, but well the engine needs to know how to use them. Creating new yaml files wouldn’t do anything, yaml is just to store settings, it’s not code.

The way most things work in narrat is that there are data stores more or less separated for each feature. Those stores keep track of data, and also can generate the save data, and reload it when you load a save. So each feature is split into its own logical area.

Then, the actual .Vue code (which is basically the UI code) mostly just displays data from those data stores, and interacts with them if needed.

So to add a relationship feature, you’d want:

  • A new UI component to display relationships (which yes would be similar to skills or something, but obviously would need different logic and layout still)
  • A data store to manage the actual data for it
  • Some new narrat commands for game scripts to interact with that new system

The plugin system can do all those things, because plugins can:

  • Add new data stores
  • Register new tabs in the menu, with their own custom UI component
  • Add new narrat commands.

The best example is the simple counter plugin example, which is a plugin that does all those things but in a very simple way. It:

  • Adds a counter-store that stores data about a counter
  • Adds a counter UI which displays the counter
  • Adds a custom command to increase the counter, so that narrat scripts can interact with it.

So it’s definitely doable, but you’d need to know how to write the code and UI for it to add the feature, which is probably more complex than what you want. It’s definitely not a matter of just copy pasting the skills system (though it would be a good source of inspiration for writing UI and data store, if you feel like trying).

Possible alternatives:

  • Just have relationships as HUD stats numbers that would be displayed by that existing system on the top of the screen
  • Manage relationships in your scripts yourself, and present them to the player in text somehow, by maybe having a button that makes them be printed out
  • have some way to see them in your game displaying it in the viewport by creating sprites and text. Relatedly, the spoon survival game I made uses sprites to display a basic sims-like mood UI, which is a similar problem. It’s a bit of work but it’s doable within the existing narrat systems without needing to add new features to the engine
2 Likes

Also, a relationships feature is something that could make sense as a built-in narrat feature, since many games might want to use it…

So I might think of implementing one in the near future if I get around to it

4 Likes

This is all very good to know! I’m probably just gonna make everything that I would want to split out items for my jam MVP but I’ll definitely want to split things out more later.

(On a related note, is there a way to quickly change the “Skills”/“Items” designations?)

I don’t mean to necro this thread, but I’m facing a similar problem (though no relationships at all). That being said, I do want to build a plugin, but I’m facing issues with the initial set-up. I’m sure I’d get a lot of the info with the plugin system link, but it’s broken.

What I’m looking to add is a button next to Menu to manage “Buildings/Businesses” in my game. Alternatively I might want to add it inside of the Menu popup as it’s own topline category, with a series of subsections similar to Items.

So here are my initial questions:

  1. Where do I install the plugin? Does it need to be in a separate folder structure from my game or can I bundle it together? If separate how do I resolve the dependency so that the resulting output is included in my game?
  2. How do I correctly include the plugin into my application? I assume it’s similar to the StartButtonsPlugin example.

I’m sure these are silly questions but I come from a backend developer background, this frontend project magic is well magic to me :).

The plugin docs are here

There’s not a ton in there but it should also point you to code to look at to figure out the rest. Plugin can add new tabs to the menu with their own UI so it should be possible, and I think the sample counter plugin adds a menu tab as an example of how to do it

And yeah you can put your plugin code directly in the project, no need to make it a separate project

1 Like

You’re the best Liana. Side question, I couldn’t find a link to your Patreon page. Anyway I can contribute?

So I’ve tried the above, and I’ve managed to add the plugin inside my project and added the button next to Menu. So far so good, but then I hit this problem when trying to use your TabController (and defining my own store). I keep getting the following error thrown at me.

“getActivePinia()” was called but there was no active Pinia. Are you trying to use a store before calling “app.use(pinia)”?

The code that throws it is:
export const useManagementMenu = defineStore(“managementMenu”, {
state: () =>…

Is this a timing issue with the plugins in regards to the whole app or am I just doing something wrong?

did you try to use your store too early? Pinia stores can only be accessed once the app has started, so if something is calling the useManagementMenu() function before narrat has started it won’t work.

in the counter plugin for example it has a reference to useCounter but it doesn’t call it.

Otherwise would need to see more code to know what’s wrong

I’ve removed everything from the function and I still get the error.

export const useManagementMenu = defineStore(“managementMenu”, {});

the error is because something is trying to use the store too early, not something wrong in the store

Ahh sorry, I’m dense this early in the morning.

This is what is calling the function.

<> import { computed, defineComponent } from "vue"; import { useManagementMenu } from "../customStores/managementStore";

export default defineComponent({
setup() {},
});

const managementMenu = useManagementMenu();

Yeah you have a variable inside your file which is calling that function, which means it’s being called basically instantly and before the store exists.

If you want to use the store in your component, the const managementMenu = useManagementMenu(); needs to be inside the setup function of the component

And now I feel really silly. Thanks Liana!

1 Like

So I just moved it into my setup, but when I try to access it (by pressing the menu button) I still get the error.

var managementMenu;

export default defineComponent({
setup() {
managementMenu = useManagementMenu();
},
});

After many tears, I’ve found the issue. I was missing the declaration of my custom store in the constructor. Letting others know in case they hit the same issue.

And as the journey continues a new roadblock emerges.

I’m getting the following error now when I’m attempting a jump.

Uncaught (in promise) TypeError: Cannot set properties of undefined (setting ‘buildings’)

Debugging the code, I saw that it happens while calling the save() in my custom store.

import { defineStore } from “pinia”;

export const useBuildings = defineStore(“buildings”, {
state: () => ({
count: 0,
}),
actions: {
save() {
return {
count: this.count,
};
},
load(data: any) {
this.count = data.count;
},
reset() {
this.count = 0;
},
},
});

Right now it’s only the code from counter, so I assume I’m doing something wrong. Do I need to register my store somewhere?