Open quisquous opened 1 year ago
I agree that a lot of things you list and I've listed are nice, but I also still don't feel like any of them are "this is a major unsolved problem that merits rewriting the world" either. Many of them still feel like they can be solved within the bounds of the existing format.
Here's what I'm looking for:
I think I'm just trying to think practically about this. I (personally) don't feel invested in a rewrite everything project, and so if somebody wants to do it, I'd need them to drive the vast bulk of the work. Sorry if I am coming off as negative here, it's more just that I am always a practical engineer at heart (so I need to understand the motivation for larger rewrites) and also that I see my own time and energy limits (and don't want to be left holding somebody else's half-finished feature, I say as I just PR'd finishing up netparams for regexes <_<).
I think my biggest issues with the current format (aside from what you already mentioned) can be summarized as:
- There's no way to handle logic as part of the timeline. Something like GolbezEx would benefit greatly from some sort of logic control due to the way the stored mechanics work, similarly with e12s's stored mechanics
Yeah, this is what I meant by there's no state other than "what is the current time"
, like you're in a choose your own adventure book. I don't have a good picture of what this would look like in the current format or even in a new format. It seems hard to do in the existing format, for sure. There's also stuff like xp's work that reads the timeline format in Java, so inserting something like TypeScript/JavaScript into the timeline itself starts being iffy if we don't want to cause them extra work.
There's no way for a trigger to interact with the timeline (be that a normal
triggers
trigger, or atimelineTriggers
trigger).
- By interact, I mean something like:
- check some conditions, and jump to this time
- alter the text of this timeline entry based on some condition
- hide this timeline entry based on some condition
- adjust the duration of this timer bar based on some condition
The one use case of this that I have encountered so far is that I half-solved the Castrum Lacus Litore first boss "are you up or down" by injecting a "is your player name hit by an aoe" into the timeline. This sometimes doens't work (because there's too many people and you get missed). But, that's the only time this has come up for me.
I think "alter the text of this timeline entry" is largely "hey we found out this was a stack earlier, and now this later thing is a spread". It's a minor nicety, but I feel like triggers largely handle this, and so it's largely fine for me if the timeline is still general.
It's not impossible, but I think we could add timeline controller hooks hanging off of data
to jump / change text / etc from triggers. In some ways it seems like the same correspondence problem as "how to reference a specific timeline entry".
- There's no good way to reference a specific timeline entry. e.g. let's say I want to change the p9s
272.2 "Gluttony's Augur"
entry to be something like272.2 "Gluttony's Augur (heal check)"
, there's no way to target that specific timeline entry and override it without also clobbering any other entry with the same text ofGluttony's Augur
I think this is less about the timeline format and more about overrides (and convenience/implementation of doing them).
You could (technically but awkwardly) do this now with existing tools by hiding the other Gluttony's Augur entries and adding custom entries with the text you wanted. Another technically existing solution is that you (as a cactbot developer) could send a PR to number anything you think needs to be handled differently (like I numbered Ultimas in P12S2 so I personally could remember which ones I was mitting) and then the different text would let you do this.
In terms of how to add this to the UI for everybody, I think it then gets into a correspondence problem of how to refer to this particular Gluttony's Augur (and have it continue to correspond across future changes). I deliberately sidestepped this problem by making people override the the text globally instead. Here's some ideas, though:
(272.2, "Gluttony's Augur")
(i.e a time + text pair): I think this is pretty plausible, but timelines sometimes get shuffled around and so this would break overrides, but hopefully this doesn't happen often(3, "Gluttony's Augur")
where we implicitly count which one this is and let you change the "3rd" one (whichever that is); I think this would probably work across most changes, although rarely sometimes there's a timeline typo and an ability is forgotten and this would cause them to get renumbered?In either case, somebody would need to add some config UI for this. But, I think either of these is plausible within the existing timeline format.
From the brief glance at whatever xml (Lemegeton?) timeline format went by (and also a long time ago cactbot request from xp that I said no to), it looks like they are solving this by adding ids to every single timeline entry. (I wonder if maybe this is what you're getting at in terms of why "ways to specify a timeline entry" is part of a discussion of timeline format.) I (personally) find this unpleasant, hard to write, hard to read, hard to review. One thing I really like about the timeline format is that it's easy to digest visually as a programmer and I don't need extra tools, and extra stuff like an id on every single line is not a desired solution for me. I also don't know that this necessarily solves the correspondence problem either, as if somebody adds a fork to a timeline or collapses a loop or something then what happens to those ids?
The timeline format really doesn't handle multiple different encounters in the same zone very well. e.g:
- the variant dungeon conversation that was part of the discord conversation you linked
- something like Delubrum Reginae where parties are handling different sets of mechanics
The Copied Factory
'sHobbes
fight
I don't know that any of these examples really feel that compelling to me. For Hobbes, I don't know that you need to see what the other parties are doing as you don't interact at all. Similarly, DRS has one person doing a solo fight while the other folks fight the second boss and it doesn't need to be simultaneous. Variant dungeon also ended up fine in the end and didn't need this sort of thing. The only fight that even remotely feels like multiple timelines would be helpful to me would be a8s where there's multiple robots with different push times.
I think to me this feels currently like an edge case and not something to build an entire format around. Even if we did have multiple timelines, I'd also want to think about the UI to present them, as maybe we'd want a second timeline next to the first instead of squishing them together?
As for discussion about a new format, I remember some other conversation in Discord where some new example formats were thrown about, something about a yml type format and something else that I can't recall off the top of my head. Discord search is just as bad as always though and I can't find them.
Yeah, I can't find it either.
@xiashtra comment link
- jumps to numbers is fragile (we could probably add named labels)
I haven't thought too much about what would be nice to have in the timeline format, but being able to jump to a label instead of a time would definitely be on the list. It's very easy to modify a timeline and forget to adjust the jumps currently. It also feels kind of hacky right now the way encounters in the same zone have to be separated by arbitrarily increasing the times of the subsequent encounters. If there was a way to say, label an encounter block and then jump to that block at the appropriate time, instead of increasing the later encounters by +1000, +2000, etc., like we currently do. Bozjan Southern Front and Zadnor are good examples of where it would be really useful.
Here's an example, BLOCKSTART
and BLOCKEND
is not how I would suggest to write this but just as a hypothetical for discussion:
# Lapis Manalis
0.0 "--sync--" sync / 00:0839::The Silvan Throne will be sealed off/ window 0,1 jump "albion"
0.0 "--sync--" sync / 00:0839::The Forum Messorum will be sealed off/ window 0,1 jump "galatea"
0.0 "--sync--" sync / 00:0839::Deepspine will be sealed off/ window 0,1 jump "cagnazzo"
BLOCKSTART
0.0 label "albion"
0.0 "--sync--" sync / 00:0839::The Silvan Throne will be sealed off/ window 0,1
6.0 "--sync--" sync / 1[56]:[^:]*:Albion:802C:/
10.6 "Call of the Mountain" sync / 1[56]:[^:]*:Albion:7A7C:/
# etc
BLOCKEND
BLOCKSTART
0.0 label "galatea"
0.0 "--sync--" sync / 00:0839::The Forum Messorum will be sealed off/ window 0,1
10.2 "--sync--" sync / 1[56]:[^:]*:Galatea Magna:7F71:/ # manually added for early sync
15.2 "Waxing Cycle/Waning Cycle" sync / 1[56]:[^:]*:Galatea Magna:(7A91|7F6E):/
#etc
BLOCKEND
BLOCKSTART
0.0 label "cagnazzo"
0.0 "--sync--" sync / 00:0839::Deepspine will be sealed off/ window 0,1
15.6 "Stygian Deluge" sync / 1[56]:[^:]*:Cagnazzo:79A3:/
25.4 "--sync--" sync / 1[56]:[^:]*:Cagnazzo:798F:/
38.0 "Antediluvian 1" sync / 1[56]:[^:]*:Cagnazzo:7990:/
#etc
BLOCKEND
5760 adds named labels as a draft. I think a reasonable followup here is what @xiashtra is suggesting to add "named blocks". In my mind, a named block is some number of lines in a timeline grouped together. However, its times are in a parallel universe from the normal timeline. It can't be jumped into or out of other than via jump to label. This would allow for having a bunch of encounters in a dungeon that all start at "0". This would also reduce the number of global active syncs (since you'd have a couple of syncs at the beginning rather than syncs that cover all fights). This could theoretically be used in some very hypothetical system to play multiple timelines at once.
Here's an example,
BLOCKSTART
andBLOCKEND
is not how I would suggest to write this but just as a hypothetical for discussion:
This is pretty much exactly what I was thinking of.
Blocks are nice. I think they could be enhanced further by giving the block itself a name, rather than just relying on labels within the block. You could then have a "blockname:labelname" syntax for jumps, so that simple label names can still be re-used for multiple fights (like "start"). If a jump is unqualified, a matching label within the same block would take precedence, i.e. "start" would jump to the start of the current block, while "phase2:start" would jump to "start" in "phase2". Maybe have a "blockname:" syntax to just go to the start of a block.
Regarding state, loops, branching, etc:
I see the value in having a fancier syntax, especially with regards to branching mechanics and loops. For that, a "composition" approach might be nice. For something like P8S1, rather than the current approach of having two timelines copy-pasted with times changed, you could just make each mechanic its own named block, and then instead of two gigantic timelines, you just have 8 or so lines for each one, and you don't have to worry about editing both if you want to add or correct something.
A way to handle some of the delayed mechanics could be a "mixin" approach, where you tell it to add a named block to the current timeline entries, rather than jumping to it.
now that we've established that there's plenty of technical ways that timelines could be better, there's the question of how fancy they should get. One of the popular uses of timeline editing is to throw your mitigations and such onto the timeline. You might need to have a different mit plan for different branches (e.g. P8S dog first vs snake first), or use different mits on different iterations of a looping mechanic. Then, as mentioned in other comments, you have to have some way of visualizing all of that in an editor.
If new functionality can be unrolled entirely with pre-processing, then it shouldn't affect users much, since you could just pre-unroll the whole thing and let them edit as it was previously, while still reducing the effort.
There's also stuff like xp's work that reads the timeline format in Java, so inserting something like TypeScript/JavaScript into the timeline itself starts being iffy if we don't want to cause them extra work.
There are some ways to handle this which range from decent to downright cursed (JCEF, J2V8, only allow JS syntax that is also valid Groovy, etc) but I'd be more worried about the fact that this sounds like it would involve eval()
in some form. Also it would make the timeline parsing itself more complex if you wanted to support multiline expressions.
I'm breaking this off from #5577.
Restating the discussion here:
@valarnin comment link
@quisquous comment link
@valarnin comment link
@xiashtra comment link