Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatic terrain transitions with single terrain type #556

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

NQNStudios
Copy link
Collaborator

@NQNStudios NQNStudios commented Jan 30, 2025

I'm in way over my head implementing a possible system for #413.

This is very WIP, I'm hacking things together to demonstrate the proof of concept.

#555 will need to be implemented in order for this feature to actually be added without breaking many many things.

Screenshot 2025-01-29 at 6 39 11 PM

@CelticMinstrel
Copy link
Member

This looks amazing, I never expected even a prototype of it to look so simple.

I assume that's a screenshot of it in action? It definitely doesn't look as good as the precomposed terrains (it's a harder edge) but that's not really a point against it as a prototype.

From the code it also looks like 3-way transitions aren't supported, though again that's not really a point against it as a prototype. An example of a 3-way transition would be cave wall butting up against a boundary between green and grey cave floor.

@NQNStudios
Copy link
Collaborator Author

NQNStudios commented Jan 30, 2025

It doesn't feel simple, it feels like a fever dream. Haha.

And the screenshot, yes, is from VoDT outdoors with the game patch applied and terrain 5 given the SMART_BORDER trim type in the scenario editor.

Only that 1 transition out of the 12 is implemented.

@CelticMinstrel
Copy link
Member

I don't think it's all that simple, but the amount of code changed is far less than I expected, so it looks simple… until you actually examine the new code closely.

@NQNStudios
Copy link
Collaborator Author

I implemented the rest of the smart border types and it seems to work. There's a tricky edge case though, when we have cave entrances which need to be considered as part of the smart border or else we get buggy results:

Image

@NQNStudios
Copy link
Collaborator Author

NQNStudios commented Jan 30, 2025

Incidentally that screenshot with the visual bug, actually contains a noticeable improvement compared with the current master branch:
Screenshot 2025-01-29 at 8 04 59 PM

(with the smart border feature, the cave walls transition to the pit elegantly.)

@NQNStudios
Copy link
Collaborator Author

NQNStudios commented Jan 30, 2025

We could maybe make a trim type that makes that terrain compatible with all smart border terrains. So cave entrances would all get that flag.

@NQNStudios
Copy link
Collaborator Author

NQNStudios commented Jan 30, 2025

As discussed in IRC, cave entrances graphics need to also be lifted off of their floors and made smart transitionable. They need to be able to merge with adjacent smart borders while also remaining able to have the CITY trim type to connect to roads.

Also, WATERFALL trim type should be able to merge with adjacent smart borders so they don't turn into corners.

The cave walls that I'll need to add to this prototype are in ter5.png.

@NQNStudios
Copy link
Collaborator Author

NQNStudios commented Feb 2, 2025

@CelticMinstrel

I think a full version of this system that supports 3-way transitions and floor-agnostic trees etc. (#554) needs 3 conceptual groups that in this prototype I was trying to implement as all the same thing. These 3 categories are not mutually exclusive, a terrain could have 2 or all 3 of them.

  1. Smart border: This terrain detects its edges with other terrains and renders a graphic offset from its base graphic index based on which type of trim it should logically be. Note that this does not involve transparency or detecting what the adjacent ground is. These graphics could be manual transition graphics from 1 terrain exclusively to another, such as currently exist in the graphics sets.
  2. Join with smart borders: This terrain will count as a smart border matching with an adjacent smart border that also has this property. Cave entrances, etc. get this. Wall types would also need to get this if we want to allow making a continuous wall that switches from mountain wall to snow, for example. If they were both distinct smart borders they would not cohere and would render incorrectly where they meet. (Note that even with this feature, such a wall would not in any smart way transition between the two wall types. It would just make sure they both render the right trim variant.)

1 and 2 could be implemented in a PR with elements of this prototype, which wouldn't make anything look worse. We would be able to free up terrain slots in bladbase for new scenarios to take advantage of.

  1. Smart floor: This terrain's graphic contains transparency, and it will intelligently fill in a floor underneath it based on neighbors (also using the smart border system for that floor). I think this is the most complicated part, but this is the feature that would eliminate half the work in creating new terrain transitions and fix things like the VoDT pit->cave wall transition that look bad. Every tree/corpse/furniture graphic could be made this, giving us System to build terrains by combining objects with a floor #554. 3-way transitions would also be solved by this, I think.

The smart floor feature would require a good deal of graphical work to make sure things still look good and to split up every transition we have in the graphics sheets to use the feature.

@CelticMinstrel
Copy link
Member

CelticMinstrel commented Feb 2, 2025

Hmm. Does that mean that 1 is essentially the same sort of logic that the editor already uses to place transitions, but done at runtime? Although it sounds slightly different when you describe it, as in the editor you place tiles like the following:

XXX
XXX
 XXXX
 XXXXX
 XXXXX

And you'll get something like the following:

▗▄▖
▝▜▌
 ▐▙▄▖
 ▐██▙▖
 ▝▀▀▀▘

Whereas with your proposal, it sounds like that same block of base terrain would produce something like the following:

▗▄▄▄▖
▐███▌
▐███▙▄▖
▝▜████▙▖
 ▐█████▌
 ▐█████▌
 ▝▀▀▀▀▀▘

I'm not really sure which of the two is better. Both walkways and trim use the latter method though – the extra diagonals on the walkway and the little trim bits are both placed on tiles adjacent to the base terrain. I think either approach could be implemented here.


For 3, I'm not sure that "smart floor" (auto-detect base terrain) is quite the same as #554, which I'd envisioned as the terrain simply specifying multiple images to stack on that space. But it definitely makes sense to split this task up into the two separate pieces of "dynamically determine the transitions" and "compose the transitions from multiple images". Although I'm more interested in saving space in the terrain sheets than in the terrain types list, as the latter is unlimited while the former is limited to at most 1000 preset images (of which currently only the last 40 can be animated).


I mentioned this on IRC already, but I had considered the idea that the various eTrimType options should actually be independent flags. Some of them do seem mutually exclusive though, so I'm not sure. What you've mentioned here suggests that independent flags are needed for this new feature, at least – the only question is whether eTrimType is obsolete.

@NQNStudios
Copy link
Collaborator Author

(Responding to some of these points haphazardly, will circle back later to make sure I addressed all the threads here.)

The idea of Smart Floor is different from my original conception of #554, but I think serves the intended purpose better. Making it easier for the designer to create 2 separate terrains for "Bed on brick floor" and "Bed on wood floor" is nice, but ultimately it would be better to allow every "Bed" to be the same terrain type, because conceptually they are.

The loss between the Smart Floor idea and the initial pitch for #554 is that, with the original idea, you could have force a 1x1 space to have the right floor under the object. With smart floor, you'd need at least 1 adjacent open floor tile to set the smart floor. Which is janky but I'm not sure there are situations where you'd want 8 walls surrounding a bed/corpse/tree. Would the party even be able to see it?

I didn't know terrain types were unlimited! That probably does change priorities, but I still see a desirable benefit to removing the trim types:

  • For specifying a new terrain with trims, do designers in the current system have to manually make all 12 terrain types? That sounds tedious and error prone. I'd rather specify properties for 1 terrain type that conceptually represents all of them, and know I don't have to change 12 more if the properties need to change.
  • The terrain palette feels cluttered and it can be hard to find what I'm looking for. And since the trims can be placed automatically by the editor (and should be!) then they don't really need to be in the palette.

@CelticMinstrel
Copy link
Member

The loss between the Smart Floor idea and the initial pitch for #554 is that, with the original idea, you could have force a 1x1 space to have the right floor under the object. With smart floor, you'd need at least 1 adjacent open floor tile to set the smart floor. Which is janky but I'm not sure there are situations where you'd want 8 walls surrounding a bed/corpse/tree. Would the party even be able to see it?

I think you might actually be underestimating the loss here. Consider the following layout:

XXXXX
X...X
X...X
XXoXX

Where X is a wall, . is a floor, and o uses transparency. With smart floor, what's the base of o? Is it X (for example, a curtain) or . (for example, a floor mat)?

I'm not sure there are situations where you'd want 8 walls surrounding a bed/corpse/tree.

8 regular walls, sure, there's probably no reason for that; but 7 regular walls and a secret door, or maybe a destructible wall? Or even a regular door? It could happen, I think. Doesn't seem super likely, but…

For specifying a new terrain with trims, do designers in the current system have to manually make all 12 terrain types? That sounds tedious and error prone.

Yes, the current system requires you to manually define all the transition parts. It's not ideal but it at least functions.

I'd rather specify properties for 1 terrain type that conceptually represents all of them, and know I don't have to change 12 more if the properties need to change.

Agreed.

The terrain palette feels cluttered and it can be hard to find what I'm looking for. And since the trims can be placed automatically by the editor (and should be!) then they don't really need to be in the palette.

Also agreed.


Perhaps terrains with transitions could use an interface similar to the "object definition" dialog to define the transition parts. I wonder what's a minimal shape that uses all the transitions… a 3x3 grid is sufficient for all the non-concave transitions, but the most obvious way of fitting in the concave transitions ends up shoving out the non-corner transitions. I guess you could do it with two 3x3 grids where one is the inverse of the other…

Anyway, tangentially related to that, I was thinking of defining a new control to handle such things in dialogs – basically, a "tilemap" control that shows a grid of images. I think it could be useful for specifying transitions as purely graphical embellishments. In the worst-case scenario you could set things up so that the transitions are a property of a pair of terrains rather than a single terrain, though that doesn't meet the desire for proper 3-way transitions…

but ultimately it would be better to allow every "Bed" to be the same terrain type, because conceptually they are.

Actually reaching this goal completely probably requires splitting the terrain into two entirely separate layers, like Avernum does. I'm very, very reluctant to go that far; having 3 different types of bed with different base terrains doesn't seem all that bad. If there's a worry about them getting out of sync, we could add some editor feature whereby editing non-graphical parameters of one terrain in a set will update those parameters on all the terrains in a set. (That would also be useful for the "object" definitions, where two tiles are part of a bigger whole.)

@NQNStudios
Copy link
Collaborator Author

NQNStudios commented Feb 2, 2025 via email

@CelticMinstrel
Copy link
Member

CelticMinstrel commented Feb 2, 2025

Also, even better than the BoA system would be if every tile
is just an arbitrary-size stack of terrains on the tile. Which would just
be a nightmare to handle edge cases for.

That's getting close to how Wesnoth handles terrains, but it even goes further – a terrain can place images on pretty much any tile it wants. And it would certainly be a nightmare to do anything along those lines (I doubt copying Wesnoth's code would work very well, since it uses a hex grid).

I wasn’t thinking of things like a curtain that would want to use the wall
as its base. That does indeed complicate things greatly.

I think nearly all of the add-ons to walls (windows, signs, pictures, etc) are things that would be nice to be able to separate. The doors might be a bit complicated, as they are also sort of transitions (the open door combines a floor and a wall).

@NQNStudios
Copy link
Collaborator Author

NQNStudios commented Feb 2, 2025

Where X is a wall, . is a floor, and o uses transparency. With smart floor, what's the base of o? Is it X (for example, a curtain) or . (for example, a floor mat)?

Potential solution to this: "Smart floor" and "Smart wall" being two separate things.

Another thing: I'm very interested in figuring out how to scope these issues into 2 types of work to correspond with a 2-stage timeline:

  • Things that must be done before a major release in order to prevent having to make breaking changes later when it's worse to do so. (I do these things in the next few weeks.)
  • Things that can be done later to make the new features fully functional and look good. (I don't do these things until after I can make a major release, because I feel I need to course-correct the drift from my initial goal which was a laser focus on making the game playable as-is, to the exclusion of the editors and fancy new features.)

A very rough sketch of a roadmap which takes those things into account:

Phase one

  • Implement Feature flags #555
  • Add a feature flag, "RearrangeTerrainGraphics" with a value of "1" being the default for newly made scenarios. (If we rearrange in the future, its default value becomes "2", etc.)
  • Duplicate the terrain graphic sheets so we keep the original ones in the game. Any time we're running a scenario that doesn't have the "RearrangeTerrainGraphics" feature flag, those are the sheets that are used. When the flag is given, we render from the new ones.
  • Any rearrangements/additions/subtractions we're ready to make at that time (Add new graphics to the bundled terrain sheets, and possibly reorganize the sheets #414), we make them to the v1 sheets and update bladbase so it is compatible with the new sheet layout.

Phase 2:

I suppose the things in Phase 1 don't really even need to come before a major release if we handle feature flags right. So maybe I postpone all of it for now?

@CelticMinstrel
Copy link
Member

Duplicate the terrain graphic sheets so we keep the original ones in the game.

If we're going to go this far, we could pull in the original original terrain sheets. There have been tons and tons of changes to the graphics sheets since the original source code release, with the terrain sheets in particular changing quite a bit. I don't think any specific terrain icon was moved to a different location, but several were "deleted" and then replaced with something completely different, and tons of completely new ones were added too.

Currently, the legacy porting code detects these cases and remaps the icons to a more appropriate one. (For example, there were two copies of the walkway graphic, so the duplicate is remapped to the one that was kept.) Maybe that's good enough for legacy scenarios though… I'm not really sure.

I suppose the things in Phase 1 don't really even need to come before a major release if we handle feature flags right. So maybe I postpone all of it for now?

Good question. I would say that we don't need to try and force auto-transitions onto legacy scenarios, at least – the renderer doesn't need to know that those are transitions at all, because they're already pre-placed, so it can just render them. If we delete the actual transition graphics, there would need to be porting code to recompose them from a stack of existing graphics, but that's not necessary if we keep the original transition graphics.

I don't think many people have actually been using OBoE to create new scenarios – as far as I know, the few people who have been creating new scenarios still use the classic version, since OBoE has never reached a stable state. So maintaining backwards compatibility prior to the 2.0 release doesn't seem that important to me, with the exception of compatibility with legacy BoE, and also compatibility with the one Windows-only release that added a few new features (the prototypical Display Picture node, for example) while still using the same basic legacy scenario format.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants