Skip to content

Foundry VTT Module: Fluidly stitch smaller segments of a scene together to simulate a much larger scene.

License

Notifications You must be signed in to change notification settings

ggagnon76/scene-scroller

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

82 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

scene-scroller

Fluidly stitch smaller segments of a scene together to simulate a much larger scene. NOTE: The Scene Scroller Maker module can generate these smaller scene segments from a fully defined existing scene.

Disclaimer

For anyone reading this document, please understand it is written as a brainstorming/design document so I can clarify the features I want and solutions I need by writing them out. For my own convenience, I will try to define all the design elements that I mention in this document, however there may be some that I overlooked that can leave you, a person unfamiliar with this project, confused or unable to fully understand what is being discussed. That being said, the first couple sections are as much for you, as they are for me. But once I get to the nitty gritty details, it'll resemble more a design document than anything else.

Inspiration

I was DM'ing the Out of the Abyss module and in it, there is a chapter called 'The Labyrinth'. I intended to produce map 'squares' (geomorphs) that could be used to assemble a labyrinth on the fly via a Foundry VTT module. I envisioned having each geomorph populated with informative tags which would be used to filter incompatible squares, leaving a list of squares from which the module could randomly choose from to generate the next section of labyrinth.
My players would be rolling survival checks to make their way through the labyrinth, and if they failed more than they succeeded, I intended the module to spit them out of the labyrinth at designated 'encounters', one of which is the labyrinth entrance itself. Each time they failed their survival checks, I (as the DM) would randomly roll for an encounter to resolve, then reduce the survival DC for the next round of checks. To sum up, I wanted to be able to generate a labyrinth that the players would not be able to navigate as the player, having to rely on their character's skills instead. Foundry would, via my module, produce a truly maze-like maze that never looked the same.

While brainstorming and researching existing modules for inspiration or for an already made solution (which I never found), I came across Zeel's Scene-Tiler module. Their module allowed scenes in the Scene folder or in a compendium, to be dragged or programatically imported into the canvas as tiles. The importing automatically created all the placeable objects along with those imported scenes. And it also allowed for those tiles and associated placeables to be easily deleted! This was a huge motivator to undertake my idea, as half the work was already done and available as a module I could simply include as a dependency. I spent several months (I don't get to spend many hours per day, let alone every day to this hobby) to produce a proof of concept, which I called 'scene-zoetrope'. That module was successfully completed and it did what I set out to prove, but it suffered from a couple issues:

  1. I started coding scene-zoetrope at the end of Foundry V7 and finished it just before Foundry V9 was released. Scene-zoetrope suffered from a bug that I thought was related to an existing bug report. I thought when V9 would be released, the issue would be resolved. I added work-arounds (adding delays in the code to give race conditions time to resolve) which worked well enough to see scene-zoetrope work in principle from the DM point of view. However, that code would not work for players. When I fixed it to work for players, it no longer worked for the DM. A frustrating experience indeed.
  2. The framework I implemented was based on fixed size squares in a 3x3 grid. Wonderful for a labyrinth whose design description stated there were no stretches longer than 10 feet before encountering another turn, either left or right, or up or down. I wrote code that moved the Scene-Tiler tiles across this 3x3 grid and if they fell off the grid, I deleted the tile(s). All nice and performant, except when I tried to make map squares for the concept, I found it really difficult to make the maps! And mostly, my vision of breaking up existing maps was beyond difficult to the point of being impractical. No content creators make maps that are neatly symmetric or conveniently arranged across a 3x3 grid!

The whole time I coded scene-zoetrope, I kept coming up with new ideas or solutions for the above (and other) gripes, but set them aside them to avoid feature creep. To sum up here, I ran into a lot of issues that were related to the restrictive framework I devised, I strugged with a particularly annoying bug and I kept having all these ideas for a more flexible implementation of my labyrinth module. So when scene-zoetrope accomplished what it was meant to accomplish, I made a little video to show it off, called it a day and archived it.

P.S. Sadly, my ability to produce the module did not keep pace with my player's progress in the game. I ended up having to 'Theater of the Mind' much of the navigation in The Labyrinth and drop non-labyrinth like maps to resolve the combats. My players never knew about the efforts I undertook that they never got to see, so they still enjoyed the sessions regardless. I was personally very disappointed that I didn't implenent my vision in time to use it in my campaign, but it was extremely liberating to not have to continue devoloping that module with it's severe restrictions (and annoying bug).

New module: Scene-Scroller

Being able to start from scratch and remove the restrictions I self inflicted on myself with scene-zoetrope, I imagined a much more useful implementation that is a re-imagining of Foundry core's concepts for maps. But first...

What's with the name? In my mind's eye, I imagine Scene-Scroller to work like old 2D games where the background scrolls from one side to the other, continously. No loading screens, no map edges. Just freedom to keep going in a particular direction. Another way to describe this is: I imagine the active scene in Foundry to be a viewport looking at a small part of a much bigger map. That bigger map is made up of small chunks of any size, which are stored in compendiums. These chunks of maps have embedded information in them that tells the module how to stitch them together with a neighboring chunk of map.

Back to Foundry's core concepts... The underlying core mechanics assumes that the scene viewport is fixed and sized to the map (the artwork). Moving from one map to another results in a reload of the canvas scene containing a new map background, new placeables, etc... Before V8, it was not possible to have 1 combat across 2 scenes. In V8 it became possible, but wasn't really implemented by core and would still require the DM to juggle multiple scenes. All tokens and placeables locations are saved using a coordinate system related to the map edges and all movement, vision, fog of war is relative to the map (the main scene coordinates).

My vision for Scene-Scroller turns all that on it's head, so it is not a minor undertaking. The brief breakdown follows:

  1. The map pieces with all their placeables are imported as tiles. The location of the tiles can dynamically move across the active scene viewport based on what each player/browser can see.
  2. The active scene viewport can dynamically change size depending on how big it needs to be to fit the stitched together map pieces that any given token can see. The size has to be the same across all players/clients and is as large as the largest combination of sub-scenes.
  3. Everything is saved (on the server) at a fixed location, probably the top left corner. This is a constant that will hopefuly make much of the underlying logic simpler.
  4. Tiles, tokens and placeables all get rearranged to be in their proper position within the active scene viewport, locally by each client. Each piece has flags that informs the module where it needs to be if it is to be active. None of this is saved. To the server, everything remains at Top Left Corner (TLC).
  5. Any tiles, tokens and placeables that are not visible to the active token are suppressed (walls are filtered out of the vision calculations) and all other placeables, including the Scene-Tiler tiles, have their visibility set to False. This will hopefully make large 'intense/complex' scenes possible for users that have potato computers.
  6. Each user (with their token) can head off in different directions and be seeing/rendering different things on their local computers. Combat can occur in multiple areas, but still all in one active scene with one combat tracker!
  7. The player(s) will be able to swap tokens to which they have viewer permission via a token selection window. When a new token is selected, the view will update to show the area around that token. The DM will be able to swap to any token on the canvas with the same menu, but they will also have another menu that allows them to select sub-scenes directly.

JUNE 2022 UPDATE:

The above is generally no longer true. I have moved away from using the Scene Tiler module to import the compendium sub-scene and all related placeables, instead choosing to create everything in local memory only. As far as Foundry is concerned, a Scene Scroller viewport is an empty scene with a few flags in it.

In order to generate everything in local memory, I had to abandon the functionality of the Scene Tiler module. Scene Scroller queries the scene in the compendium to create in-memory versions of everything.

Scene Scroller is being refactored (yet again) to accomplish this. The biggest change is it now contains a class that defines the flag "schema" contained in the viewport, sub-scene tiles and tokens. That class allowed me to iterate rapidy without having to change references all over my code! The refactor also contains a cache (referred to as 'ssc' in code) that holds all the placeable data needed at any given time. The intention is to keep the cache lean by populating it with needed sub-scene data as needed, and clearing out unused data. Each client has their own cache, that contains only what their client needs to be seeing.

Here is a newer list of points the define how it should all be working:

  1. The viewport has two sets of flag data. The first is the ID of the last referenced token. The GM will load up the scene based on this token. The second flag has an array of stringified token data, for each token in the scene, including all player tokens and NPC tokens. When a player loads up the scene, the module will find tokens they have permissions to view and choose the first one. A new menu will allow the players (and GM) to switch between tokens if they can view or control more than one.
  2. The tokens will have flags that contain the UUID to the sub-scene they occupy, and the location in that sub-scene relative to the sub-scene top left corner.
  3. Sub-scenes (which are generated as tiles) will have several different flag data that is used by the module to construct the scene and all the placeables.
  4. Sub-scene "tiles" and regular tiles are differentiated, as the former is just intended to be an image to mimic a background. They should have all their event handlers removed so the GM can't interact with them at all (intentionally or accidentally).

NOMENCLATURE

Things have begun to get a little confusing in the documentation of my code. I've re-written it several times as I've come across issues where many things ended up being called the same thing. For example, not all tiles in a scene are background image tiles. So calling background image tiles and 'normal' tiles tiles got confusing really quickly. The same applies to the Scene Scroller Scene where background tiles move around to show different token views. I also refer to the Foundry core 'Scene' in places as well, and there is a fundamental difference between a Foundry core Scene and a Scene Scroller Scene. A Foundry core scene can be a Scene Scroller Scene, but not always. So yeah, there is a need for some nomenclature here:

  1. SubScene: this refers to a background image tile and all the associated placeables. It has a section of map as a background and contains flags with info linking placeable objects (walls, lights, sounds, notes, drawings, tiles, etc...) to itself. SubScenes are tile versions of scenes from a compendium.
  2. Viewport: The full functionality of Foundry to swap between many scenes remains unchanged. However, some of those scenes can be initialized to be Scene Scroller scenes via this module. When such a scene is initialized, the Foundry core scene effectively becomes a viewport showing a small piece of a much larger map/area. The intention of this module is to mimic being zoomed into a map and scrolling around to traverse the larger map.

About

Foundry VTT Module: Fluidly stitch smaller segments of a scene together to simulate a much larger scene.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published