SyntacticKitsune's Finmer feature wishlist

Having trouble, or an idea? Share here.
Post Reply
User avatar
SyntacticKitsune
Posts: 22
Joined: 05 Jan 2024, 02:44
Contact:

SyntacticKitsune's Finmer feature wishlist

Post by SyntacticKitsune »

Here's the semi-long-awaited thread containing my various feature requests for things actually usable in modules. (Called wishlist because let's be honest none of these are gonna be terribly high-priority.)

Let's start with a simpler one:

More combat hooks

This one's pretty simple, at least from the description perspective. I would like an additional hook for when a combat participant tries to attack something that fires after damage has been rolled, but before the number is shown or applied. My use case is that I'd like to be able to modify the incoming damage before it's applied as a way of simulating elemental weapons (sort of like if Pokémon was an RPGMaker game).

In other words, I want this:

Code: Select all

combat:BeforeDamage(function(source, target, damage)
	-- Modify and return new damage value.
	-- Returning 0 here could also allow making it a miss.
	return damage * 1.5
end)

Scripted dice rolls

Alright so here's a more interesting one: I want to be able to display dice rolls outside of combat. The use I have for these is stat checks in say, traps (or I guess if someone wanted to use it for a gambling NPC). Now I can already recreate the roll in Lua, but I also want the cool graphical part (which is also arguably the best part).

Anyway, so here's what I'd like to have (wow that's a lot of parameters):

Code: Select all

ShowDiceRoll(
    leftDiceCount,
    leftNumber,
    leftName,
    rightDiceCount,
    rightNumber,
    rightName,
    leftStatus,
    rightStatus,
    leftStyle,
    rightStyle)
Parameters: leftDiceCount (number) - the number of dice to display on the left side
            leftNumber (number) - the total value of the dice on the left side
            leftName (string) - the name to show on the left side
            rightDiceCount (number) - the number of dice to display on the right side
            rightNumber (number) - the total value of the dice on the right side
            rightName (string) - the name to show on the right side
            leftStatus (optional string) - the text to show under the name on the left side, defaults to the one associated with the style (except generic means empty string)
            rightStatus (optional string) - the text to show under the name on the right side, defaults to the one associated with the style (except generic means empty string)
            leftStyle (optional EDiceStyle) - the style of the dice on the left side, defaults to AllyGeneric
            rightStyle (optional EDiceStyle) - the style of the dice on the right side, defaults to EnemyGeneric

Where "EDiceStyle" is:

Code: Select all

enum EDiceStyle
.AllyAttack      the "blue sword" die icon
.AllyDefense     the "blue shield" die icon
.AllyGeneric     the "white-and-black" die icon
.EnemyAttack     the "red sword" die icon
.EnemyDefense    the "red shield" die icon
.EnemyGeneric    the "red-and-white" die icon

Okay, so there's a bit more than a few parameters here. If this were added it may very well be the most parameter-dense Lua-exposed function yet. I've tried to provide some sensible defaults so there's less need to provide all ten parameters, but four of them are still essential and two can't easily have reasonable defaults.

Regardless, the idea is that you invoke the function (probably during a scene, or maybe as part of a combat round) and it'll block execution long enough for it to display the dice and hide itself again. The die icons for each style can be distributed randomly amongst the available dice.

Tables in save data

And we're right back to boring feature requests with this one: tables in save data. I think I talked about this in the DeepForest thread, although I'm pretty sure that got derailed with other feature requests (of varying use). Basically, I want a Storage.SetTable function I can just toss a table into and obtain later using Storage.GetTable. Metatables really need not be preserved — we don't need Lua bytecode in the save files.

Behind the scenes there's probably two options. Option 1 is this table could get serialized to JSON (I'm pretty sure the editor has a JSON library that the game could borrow) and stored as if it were a string.

Alternatively — and I only became aware of this possible option when I messed with save files 1-2 weeks ago — option 2 is more PropertyBag abuse. I know the save format is already structured (and indeed, does support nested 'objects') so this could just be a way of reading/writing full PropertyBags. I think this approach would necessitate additions to the data types a PropertyBag can contain however, since AFAIK they cannot store lists (among other things).

Anyway, I don't imagine many people would use this feature, but I would. Deep Forest would certainly make use of it, and I have at least one other module I'd like to make eventually that would absolutely need it (unless I pack in a second JSON parser).

Obfuscating the day-night cycle

This one's pretty niche, but I'd like the ability to change the texture used for the time spinner so that the player can't easily tell the current time (while still being able to tell that time is passing). The reason I want this is so I can create dungeons that the player can't tell time in, since they wouldn't be able to see the sky (or well, not the same sky).

Logging the log

This isn't exactly a module thing, but I'd like the option to mirror the story output to a file for e.g. debug output that looks really bad without a monospace font. (You won't believe how crunchy the Deep Forest debug output was when I was trying to get the maze generator to behave. Let's just say it was less of a maze and more of a soup.)


Alright I think that's all of the feature requests I have right now. Honorable mentions go to scene patches (which are in progress I think) and bit32, which is actually done now. Neat. Oh yeah and also the asset querying API, which is also done. (Format 21 is no longer just the "whoops your furballs shrunk in the wash" update, it's now also the "self-aware modules" update and the "bits can shift as a treat" update.)

User avatar
Nuntis
Game Creator
Posts: 32
Joined: 11 Nov 2023, 13:27
Contact:

Re: SyntacticKitsune's Finmer feature wishlist

Post by Nuntis »

Okay, there's a lot of fun stuff here!

Damage adjust hook

This is an interesting idea. You mention elemental damage and other such multipliers as a main use case for this. I wonder, would it also solve your use case if the combat system gets built-in support for elemental weaknesses? E.g. since you also mention RPG Maker, I'm thinking something similar to what that system offers: you can define 'elements' somewhere, then specify that a particular weapon deals damage of that type, then specify an effectiveness on any given creature.

Scripted dice roll animations

Interestingly, you're not the first one to ask for this. I agree this would be a useful tool.

Tables in save data

Hm, I think this is doable in terms of implementation work; as you mentioned, PropertyBags are indeed k/v maps so they could be abused for this. But what isn't quite clear to me at the moment is what the use is of storing complex objects in save data. Can you describe the use case you have in mind? Perhaps I can try and help you come up with some alternate solutions that don't involve the nuclear option of JSON serialization either.

Obfuscating the day-night cycle

Interesting idea. I can see how that might be useful. This has a couple of technical caveats; the biggest one by far being that the module needs to store the texture that the script wants to apply, and I am hesitant to add a new 'AssetClock' class for this.

That is, assuming the script needs to apply a different texture at all - just replacing the clock with a built-in 'non-colorful' version and disabling the full-screen background color gradient would also satisfy that use case. Will need to think about this.

Logging the log

Right. I suppose that is pretty much the first step towards an 'auto-walkthrough' mode.


As for format 21, please do keep in mind that the format isn't stable until it's merged to master, so you may want to avoid building content on top of it right now. I may try and start tinkering with scene patches soon.

User avatar
SyntacticKitsune
Posts: 22
Joined: 05 Jan 2024, 02:44
Contact:

Re: SyntacticKitsune's Finmer feature wishlist

Post by SyntacticKitsune »

Nuntis wrote: 16 Jun 2024, 18:35

would it also solve your use case if the combat system gets built-in support for elemental weaknesses?

I think that'd solve it, yeah. I originally wrote that request from the what's the least possible change needed from the engine to support this perspective (back before any of the furball stuff -- I tend to sit on these posts for a while), but this alternative seems like it would be less arcane for the average module author to use, not to mention less of a module-level hack.

Nuntis wrote: 16 Jun 2024, 18:35

Can you describe the use case you have in mind?

Alright so there's two uses I have for this:

Deep Forest's Maze

This data takes the form of a 2D array of 'tiles', each having exit directions. For example, "[[{"e":true,"w":true}]]" represents a maze of one left-to-right tile. (In this case representing a really straightforward path to Rux's place, I suppose.) It's possible to store this data using flat keys (kind of like random character data), but that'd look like this (JSON representation of save data):

Code: Select all

// Not pictured: all of Core's data.
"EXTDATA": {
  "LUA_DEEPFOREST_MAZE_0_0": 0.0,
  "LUA_DEEPFOREST_MAZE_0_1": 3.0
  // etc., up to LUA_DEEPFOREST_MAZE_9_9 (~100 entries)
}

This would also incur the wrath of ≥100 map lookups every time the player goes any direction in the forest, which in practice likely wouldn't be too bad, but it feels wrong. (Not to mention all these packed directions would be floats, because Lua can't store int values in the PropertyBags right now.)

Procedurally-generated Dungeons

This is part of a module I'd like to work on in the future (and I probably hinted at it when I released Deep Forest). If you thought the storage requirements of Deep Forest were ridiculous, this one borders on nightmarish, since not only are there different rooms, but also floors, and room contents:

Code: Select all

"EXTDATA": {
  "LUA_LAYER_1_ROOM_7_0_TYPE": 1.0,
  "LUA_LAYER_1_ROOM_7_0_EXITS": 3.0,
  // Yes, this is a serialized *character*.
  // (Side note: I still haven't investigated
  // whether I can dynamically edit a dummy character.)
  "LUA_LAYER_1_ROOM_7_0_CREATURE_NAME": "otter",
  "LUA_LAYER_1_ROOM_7_0_CREATURE_ALIAS": "the otter",
  "LUA_LAYER_1_ROOM_7_0_CREATURE_GENDER": 1.0,
  "LUA_LAYER_1_ROOM_7_0_CREATURE_AGILITY": 1.0,
  "LUA_LAYER_1_ROOM_7_0_CREATURE_BODY": 2.0,
  "LUA_LAYER_1_ROOM_7_0_CREATURE_STRENGTH": 1.0,
  "LUA_LAYER_1_ROOM_7_0_CREATURE_WITS": 2.0
  // Also, creatures are not the only things to be found in these rooms.
  // I haven't even figured out room descriptions yet.
}

Regardless, storing tables is likely only going to get used for randomly-generated things, like these two layouts or maybe someone in the future trying to perform more complicated character generation (beyond names and genders), although realistically I'm the only person who will ever need this feature. (Because if I can't write vore scenes I may as well make up for it with concerningly overengineered content. It perhaps doesn't come as a surprise that I'm a programmer and not a writer.)

Nuntis wrote: 16 Jun 2024, 18:35

I am hesitant to add a new 'AssetClock' class for this.

That's fair. Another option could be some kind of AssetSprite which could later be hooked up to other things (if anyone wants them) like custom die sprites or maybe Quest games' tendency to plop images on the screen. (Actually now I'm tempted to make an escape room module. Another one for the pile, I guess.)

Nuntis wrote: 16 Jun 2024, 18:35

just replacing the clock with a built-in 'non-colorful' version and disabling the full-screen background color gradient would also satisfy that use case

That'd also probably work. Wait...

Nuntis wrote: 16 Jun 2024, 18:35

background color gradient

There's a time-based gradient??? And now that I look, there it is. Wow, I never noticed that before. (Although it is pretty subtle.)


Nuntis wrote: 16 Jun 2024, 18:35

As for format 21, please do keep in mind that the format isn't stable until it's merged to master, so you may want to avoid building content on top of it right now.

Yeah, I'm aware. (Since if it were considered stable it'd already be in master.) I think the only thing I'd need right now from format 21 is more-complicated scene patches, which aren't in there yet anyway. Smaller furballs are great, but mostly don't matter for anything that isn't Core; asset querying is currently not terribly useful because there just aren't many modules to have special compatibility with (although this will hopefully change in the future); and the bit32 backport will be useful for when I go and break save compat in Deep Forest (which is very not now). Regardless, anyone who'd want to play with any 'experimental' modules (or make their own) would need to build Finmer from source from a different branch.

Maybe when the Complicated Scene Patches drop I'll try prototyping a different module idea I have, which requires scene node script patching to avoid leaking old save data everywhere (probably just some HEAD injects would be needed here -- some good 'ol if-then-return jank). Of course this module isn't going to be published until at least whenever the next build of Finmer comes out (whenever that may be), since I think I'm probably one of very few people willing to compile Finmer from source.

Post Reply