Town Populations

I’ve had my head in the quest system for several months and really needed a short break. I also happened to need a solution for spawning enemies outdoors in cities (for example, the ghosts and wraiths in Daggerfall at night) and noted there was a good amount of overlap between spawning enemies and NPCs in town environments because they all need to avoid placement inside building geometry. And whatever solution I use for placement could probably be used for navigation as well. I had scheduled wandering NPCs for 0.5 cycle, but decided to make an early start on this while solving town placement and navigation. And what better way to test this solution than to actually watch NPCs walk around?

The first problem I had was how to find an appropriate placement position. My initial idea was to use the foliage placement array in exterior data. This formed a nice grid over each block, but it also marched over water and under buildings. That would not be suitable. I considered just dropping in mobiles and using a combination of rays and colliders to refine their position until they found open space, but that approach seemed way too messy and inefficient.

That’s when I had a eureka moment thinking about how perfectly automap image data lined up with the game world. Take the below screenshot as an example. In game, I’m standing outside the Odd Blades looking at the entrance door. On the automap, once unit conversions are done, I’m in exactly the same place.

 

So Daggerfall’s automap perfectly skins building footprints. This should mean I can take the inverse of automap data to work out which parts of the environment are open. I quickly prototype by placing white cubes on open environment and avoiding the building footprints. Take a look at the results.

 

This is beyond perfect. The automap doesn’t just contain data for building footprints, but for flat placement and decorative geometry as well. I have a strong suspicion Daggerfall also uses the automap data in this manner, it’s just too precise and detailed to be a coincidence.

With a solution in mind, I now have to execute the idea. I create a new class called CityNavigation which is added to the location GameObject at scene layout time by StreamingWorld. This constructs a navigation grid at the same time location and automap data is read so only a small amount of additional processing is done per location. With the inverse of automap blocked out, we get the following:

This is good – the white areas can be used for placement and navigation, but it’s not perfect. It also needs to account for tilemap under location. We can’t place NPCs on water tiles, and they should try to avoid those tiles when walking around. Rather than just block out unwalkable tiles, I take this one step further and allocate each tile a specific weight, where a higher weight means the tile is more favourable. Here’s the final navgrid where black areas are “no-go” and brighter areas are preferred over darker areas. You can probably see right away this creates a strong preference for the road network:

 

What you can’t see in the above image is that each weight occupies the upper 4 bits of a single byte. The lower 4 bits are reserved for a flag system, giving me up to 4 bits to control NPC behaviours. This will be important later in this article.

Now that I have a nice procedurally generated map of any exterior location, the next problem is converting between all the different coordinate systems. If you’ve ever tried to make a big world in Unity, you’ll know that precision problems kick in after a few thousand scene units or so from origin (position 0,0,0 in world). This manifests itself through jittery movement and shadows, imprecise feeling of control, and issues with physics system. The game map in Daggerfall rocks in over 819,000 x 409,000 scene units, way beyond what Unity can handle with fine floating-point precision. I overcame this challenge very early on by using a fixed point coordinate system for the world (Daggerfall units) and normal floating point units for the scene (Unity units). The world is built around the player in chunks close to origin, and when player runs too far in one direction, the whole world is brought back towards origin. To the player it feels like they are running continuously through a huge open world, when in fact the world is being constructed around them one chunk at a time. The player never moves more than 1000 units from origin in the X-Z plane.

What does all of this have to do with the navgrid above? Well, now I have yet another coordinate system to glue together. I have not only the Daggerfall units and Unity units, but the X,Y position inside the navgrid array where any virtual mobile objects have to move around. So the next thing I do is write some helpers in CityNavigation to convert from navgrids to world space, world space to scene space, and back again, and so on. This chewed up a solid chunk of Sunday to get working properly, and there’s still a few precision issues due to the large differences in scale. Something to refine down the track.

With all the math out of the way, I can now start placing mobile NPCs into the world. One problem though, I hadn’t written any code to render wandering NPCs yet. So I started with these guys just to confirm the navgrid through scene conversions were working. Sometimes in game development, you have to bust out some programmer art to get the job done.

 

With placement working, next came the process of building the mobile NPC billboard properly – including that stop-and-stare thing they do when you get too close to them.

Town NPC Billboards

With rendering done, I can start moving them around the navgrid using a simple motor. They will generally follow roads when encountered (because roads have a higher weight), but there’s enough randomness to let them change directions and wander around elsewhere on the grid.

And do you remember me mentioning the navgrid can store flags in the lower 4 bits? The first flag I created is an “occupied” bit that lets a mobile claim a navgrid tile before walking into it. This prevents two or more NPCs trying to occupy the same tile at a time. The next clip shows the mobile movement, path following, and dynamic avoidance of each other. I’ve cranked up the spawn count and movement speeds because it helps me observe the behaviour (and it’s kind of fun to watch).

Mobile Pathing and Dynamic Avoidance

Despite everything accomplished, I still have more to do. The next step is working out which races are placed in which towns. I put my travelling boots on and tracked around classic Daggerfall’s world until I found which races appeared in which climate zones. I built this into the helper which returns climate data for texture swaps, etc. and now the correct NPC races (either Redguard, Nord, or Breton) will appear across the game world.

 

The final step was to build a PopulationManager class. This code handles spawning/despawning of NPCs around player as you move through town environments so the location feels populated. After a bit of experimentation, I used a population index per 16 RMB blocks so that small towns feel like they have a smaller overall population than large cities. One of my challenges here is the draw distances in Daggerfall Unity are huge compared to classic Daggerfall. While classic can place NPCs safely in the fog out of sight, in Daggerfall Unity you can see two full city sizes distant across the map. This means that hiding pop-in and pop-out of NPCs is a little trickier. For now, I mitigate this by trying to only show or hide NPCs when player is not looking directly at them (as Daggerfall does) and only allow them to pop-in when a certain distance from player.

There’s still a few bugs to iron out. You can still catch them pop-in nearby if you happen to look in the right direction at the right time, and they sometimes glide slightly in the wrong direction on spawn due to precision issues as they align to the grid. And of course you can’t talk to them yet, because the “talk” system won’t be introduced until 0.5 sometime. But overall, the feeling of crowds is quite satisfactory and Daggerfall-ish, and it’s wonderful to finally see these sprite people bustling around cities.

I hope you enjoyed reading about some of the work that goes into creating even a small feature like this one. If you’d like to read more, I try to post regular micro-updates to my Twitter feed @gav_clayton.

 

Closing The Loop On Quests

For the first time yesterday, I was able to run a full quest in Daggerfall Unity from start to finish, and I’m very happy to say that a sizeable chunk of the quest system is now implemented. Following is another quick visual diary on what I’ve been working on lately. Where possible, I’ll share some information on what the quest system is doing in the background. There’s also a new video at the end.

 

Guild Quests

I have partially implemented guild quests with their usual service providers. Visit the quest-giver NPC in any Fighters or Mages Guild across Illiac Bay to receive a quest from a curated pool that is “mostly working” in Daggerfall Unity. This system helps me set the scope for testers, and introduce new quests over time as more of the quest system is built. Let’s take a look at this in action by following a quest from start to finish.

 

If you have  a sharp eye for Daggerfall quests, or have ever written one yourself, you’ll notice a lot is happening in the screenshots above:

  • Quest-giver NPC is identified by faction ID and the guild service window shows “Get Quest” as it should for that NPC.
  • The quest offer process is in place for you to accept or refuse job offered.
  • Many text macros are expanded automatically – such as random monster name, target location, player’s race, current region, and so on.
  • Reward is being randomly generated based on quest script.
  • Travel time is calculated from world using same logic as travel map, ensuring player has enough time to travel there, find the item, and return back.
  • The quest log information is generated and stored in the journal with current date, return location, quest-giver NPC, target monster, and how long you have to complete quest.
  • The quest-giver (Mordyval Moorhart) has also been tagged as the Questor NPC for this job. The quest system will keep track of your clicks on this person to know when you’ve returned with the wrappings.

If you travel to the named dungeon and explore it thoroughly, you will eventually find the mummy who is the target of this quest. If you don’t want to search you can use the ‘tele2qspawn’ and ‘tele2qitem’ console commands to teleport directly to the target spawn or item markers in dungeon. However you find it, kill the mummy and the target quest item is placed in its inventory for you to loot along with other randomly generated treasure.

Here are some of the things the quest system is doing under the hood in the above screenshots:

  • Tracking when player visits target dungeon and injecting the mummy into world.
  • Capturing script events like “injured foe” and “killed foe”. In this particular the quest, the mummy wrappings are placed on the monster when you injure it.
  • Tracking quest items, setting their background green, and displaying scripted text after picking up the mummy wrappings.

Now it’s time to return to Mordyval Moorhart for our reward.

In this step, the following stuff happens in the background:

  • Quest script detects you have clicked on the Questor NPC with the target item.
  • The QuestCompleted text is shown for a successful outing.
  • A loot container opens with your agreed-upon reward.

In classic Daggerfall, if you accidentally close the loot window without getting your reward that item is lost. I’ve made a small change where the reward is placed into a dropped loot container at your feet if you forget to collect it. This at least gives you a second chance to pickup your loot.

 

With all of the above working, this closes the loop on the quest process for a whole bunch of quests. It’s not just mummy wrappings, a lot of quests involving item hunts and killing monsters all operate inside this same framework. Where things fall down right now is with some of the special script actions that add flavour and complexity to quests. These remaining quest actions and conditions will be built out over time until quest system is at 100%.

 

Escort Quests

Sometimes a quest will ask you to take an NPC somewhere, such as rescuing the below person from a giant slain as part of a Fighters Guild quest. It seems the giant had been keeping this person for a snack.

A lot is happening in the above side-quest:

  • The quest script selects at random from a victim NPC, a map reward, or no map and no victim. In this case, the victim NPC was selected.
  • The random NPC Lysausa Gaerwing and her home town of Crosswold Borough are generated, giving her a bit of a backstory.
  • According the quest log, she wants to be delivered to Lord Mordoryan’s Wares, a shop in Oxville. Note the %g2 pronoun macro isn’t working yet. This is on my todo list.
  • When accepting the escort, a portrait (which usually does not resemble NPC flat in world) is added to your HUD to show this person is journeying with you.
  • The quest system tracks when player enters target building, displays the scripted popup, and removes NPC from your HUD.

 

Artifacts

A smaller task than above, but still necessary for the quest system is the ability to spawn artifact items. These special items are created by merging two sets of template data together to form one very powerful item with a larger than usual number of enchantments. While magic system isn’t in the game yet, certain groundwork still needs to be implemented. Because I’m looking at spells and effects in the update chain immediately after quests, now is a good time to start thinking about this stuff. Artifacts are still at a very early stage, and I might not return to them for a while.

The character above is holding Chrysamere from a quest script intended only to test these items can be generated by quest system. A big thanks to all the people who sent me their saves so I could test artifact import and creation. I still have some bugs to fix, but I’ve made a good start on this.

 

Conclusion

The quest system is doing great. It’s still a ways from being finished, but all the hard problems have been solved and now I’m just building out support for remaining actions and conditions, and fixing bugs along the way. The next items on my list are multi-spawn foes (e.g. kill 6 rats in a house) and more work on text support (like the %g family of pronoun macros). There’s bound to be a few more articles to go before I can call quests complete.

If all goes well, I should have the first real test build with the quest system in current state available in 2-3 weeks. This will have the Fighters and Mages Guild quest system in place for testers to run through available quests and help me find bugs. You’ll also be able to use ‘startquest’ console command to launch whatever quest you wish, even quests you write yourself, but things might not work properly if you go too far off grid for now. I’ll post more about the test build once it’s ready, including any limitations in the build at the time.

Thank you for reading! If you would rather watch quests in action, following is a pure gameplay video of Daggerfall Unity, except I’m using the console cheats to teleport to objectives in dungeons for the sake of brevity.

For more frequent updates on Daggerfall Unity, follow me on Twitter @gav_clayton.

NPCs, Items, Enemies, Quest Debugger

I’ve been hard at work the last couple of weeks, finally making serious inroads into the real meat of the quest system. Here’s a quick diary of my progress since last post. If you follow me on Twitter, you’ve already seen most of this, although there’s a new video at the end you might enjoy.

In the last post, I talked about using buildings as quest sites. This has allowed me to start work on placing NPCs, items, and enemies as part of quests, and to support branching quest execution based on where player is in world.

When a named NPC is reserved by quest system, Daggerfall Unity handles all the book-keeping to move that NPC to the quest site. I tested this out using King Gothryd at first. Once the new quest site is determined and Gothryd is reserved, scene builders will no longer deploy him at the usual home location – unless the quest specifies the atHome flag at time of NPC reservation. In screenshot below, Gothryd has already left for the quest site.

 

The quest system then generates a SiteLink between target Place and Person resources. When the player visits the target location, scene builders need to place Gothryd at that location. Here’s Gothryd at the end of his journey.

 

I wanted to take a short break from NPCs and moved onto items briefly. There’s a few different ways Daggerfall uses Item resources in quests. They might added directly to your inventory, placed in a dungeon, or used as a permanent reward. Different quest conditions will also trigger based on whether player is carrying a certain item or not. I still have a lot to do here, but have made a start on the first case – adding an item directly to player inventory. The parchment with a green background below is the first real quest item in Daggerfall Unity. Specifically, it’s the letter from Brisienna.

 

At this point the quest engine is getting advanced enough that I need more detail on what’s happening under the hood at any time. I put together a quest debugger that shows the various Task and Timer states for a running quest. I plan to make this capable of step-through execution in the short term. The debugger shows which tasks are active/inactive and which timers are pending/running/complete. After setting this up, I could finally resolve many bugs in execution flow. I also added proper support for persist-until tasks, global variable links, and rearming tasks designed to switch on and off.

 

I’m pleased to say the quest system is all coming together rather quickly now. There’s still a huge amount of work to do, but most of the hard problems have been solved now and I’m just building out action support and fixing bugs. Here’s a little video of the current state of the quest system. Some of the early quests are working nicely now.

As a bonus, this video also shows the new skill tracking and player levelling by Allofich. Yep, it’s possible to level-up in Daggerfall Unity now thanks to his efforts. Great work Allofich!

Quest Buildings And PcAt Condition

Now that buildings and NPCs can be identified in the game world, I can finally start linking together parts of quest system to world. The clearest starting point is quest buildings, as a majority of quests in Daggerfall will send player to a building somewhere in the world.

If you’ve been following my progress on quest system for a while, you already know a lot of technical progress has been made on the back-end. Without forcing you to recap on past articles, here’s a brief summary of quest system in its current state:

  • Quest scripts are generated by Template v1.11 by Donald Tipton. This has long been the go-to solution for adding new quests to classic Daggerfall. By adopting this scripting format, it becomes possible to compile scripts between both Daggerfall and Daggerfall Unity for testing. And it means anyone with experience writing quests for Daggerfall can already write quests for Daggerfall Unity.
  • Daggerfall Unity has a JIT quest compiler which builds quest scripts at runtime. This means you can edit, start, and stop quests without once closing the game. This will be even more useful once the Quest Inspector UI is ready.
  • The QuestMachine execution environment runs compiled quests like small virtual machines inside your game session. It interfaces with the world and does all the necessary housekeeping for running quests.
  • Quests are made up of resources (Place, Person, Item, etc.) and Actions (perform some task). Some actions are also conditional (do task when condition is true). Almost all of Daggerfall’s high-level gameplay is driven by the quest system. Even some things you might not expect (such as Lysandus screaming VENGEANCE! at night) are accomplished by quests.

 

When adding building selection to game, one of my first problems was how do I locate the building in whatever town player is in. Daggerfall Unity doesn’t have wandering NPCs to mark buildings on your map quite yet. Not a problem for named buildings like taverns and shops because these are visible on the automap, but what about some random residence in town? How do I get the player there for testing?

The solution I landed on was to add a simple quest compass on the HUD. This will show the direction, name, and distance to target door. Fortunately, I already track building entrances in the world. What’s needed is to build a set of marker positions based on active quests. I start by just adding a test sphere on quest target doors.

 

That blob above sits perfectly on the door to my quest building. Now I need to show that as text and distance. The HUD text overlay below align with doors in camera space and show distance to multiple targets.

 

And finally the building name. This marker can direct quest developers straight to all active quest sites in their current location. Of course, anyone will be able to turn this on from the quest inspector UI if they would like a quest compass. I’m almost certainly going to expand this system out for quest items in dungeons and other targets in the future.

 

I can now enable the quest journal, something Lypyl implemented perfectly some time back. I wire up the keybinds and UI to allow player to open quest journal, and find logged quest information sitting there as expected.

 

What you can’t easily see above is that some text macro support has been added as well. For example, %pcn resolves to player’s full character name, _buildingSymbol_ expands to building name, __buildingSymbol_ expands to location name, and ____buildingSymbol_ expands to region name. This is all part of the text engine inside Daggerfall I’ve had to reimplement in Daggerfall Unity.

With local building support out of the way, the next step is remote buildings elsewhere in the same region. This involves a bit more work, but in a few hours it’s possible to send player anywhere in the game world.

 

The final piece is to implement PcAt conditional action, which detects when player has entered target building and does something. In this test quest, I just display a popup and end the quest.

 

This is an important milestone for questing in Daggerfall Unity. It means a lot of the hard groundwork has been completed and the real work, the stuff visible to the player, can commence. This is a huge relief for me because I can finally show off my progress in a meaningful way with screenshots and videos. As important as all the code back-end is to outcome, its been very difficult to show progress which sometimes makes it feel like nothing is happening.

To celebrate visible progress, here’s the first video of Daggerfall Unity’s fledgling quest system in action.

 

For more frequent updates on Daggerfall Unity, follow me on Twitter @gav_clayton.

Identifying Buildings And NPCs

In my last post, I talked about the “Place” quest resource and merging map-level data down to block-level. The next step from here is to propagate this information to scene-level where the player ultimately lives. I decided to tackle this along with a start on Daggerfall’s interaction modes, i.e. Steal, Grab, Info, Talk which are by default bound to keys F1-F4. What I’m most interested in here is the ability to perform an info click directly on a building to discover its name.

First step was to quickly implement the mode switch itself. Key-kinds were already in place inside the InputManager class, all I needed were a few more lines of code to track which mode player was in and a new HUD label to present switch to user. After several minutes it was possible to flip between the 4 interaction modes.

 

Next, I needed a way of detecting when player clicks on a building. I already track player clicks in PlayerActivate class, and can detect clicks on static scenery and doors, but not on the building model itself. I go to work looking for an efficient way to manage this. Each Daggerfall model contains a radius value stating the overall size from its centre point. This seemed like a good place to start, so I overlay the radius as a sphere collider on test buildings.

 

Keep in mind that I’m not storing individual building models at scene level, the entire block of buildings above is combined into one large model. This is more efficient for rendering and results in fewer draw calls to the graphics card. So I don’t know which building player has clicked on – I just know they’ve clicked a combined block model and I need to resolve that back to a specific building. The sphere colliders would do the job, but they unfortunately suffer from a lot of overlap. Depending on where player is standing and where they clicked on the building, it’s possible for that target point to be inside two or three different building spheres. There are ways of handling this of course, but I decided to go with box colliders instead that will tightly wrap Daggerfall’s little box houses.

Before I can implement boxes, I had to go right back to the procedural mesh builders that extract data from ARCH3D.BSA (Daggerfall’s 3D model archive). During the vertex conversion process, I added some tracking for minimum and maximum vertex positions from origin to get the overall size of models in X, Y, Z space. Because the models are being constructed procedurally, and I have to process that information anyway, this step adds almost no overhead to the job of loading models at runtime. I now have what I need to construct a tight bounding box around any model effectively for free.

Then I just had to pass that information to scene builders. The end result looks like this.

 

Every building now has a nice crisp bounding box trigger collider. While this is great to visualise the bounds, I’m not happy with adding so many GameObjects to scene. A large city like Daggerfall will add around 800+ new collider GameObjects. If a few large cities are in the world at once, then it’s very possible that 2000-3000 colliders would be added to scene, the majority of which will never be used. Not ideal from an optimisation point of view.

To work around this, I used the same solution I came up with for doors. I store the box information for every building on the block GameObject itself using component DaggerfallStaticBuildings. This is just a small amount of raw data stored on each block. When the player clicks on a block in scene level, a single box trigger is instantiated and tested for each of the buildings in that block, usually no more than 5-14 buildings. The world-space point of impact for hit ray is tested against known buildings in that block (and only those buildings). If a hit point intersects with a known building trigger in world space, then everything we need to know about that building from scene layout time is returned to PlayerActivate.

The end result is zero new collider objects in the scene and only a small amount of overhead for storing building data and testing hits, which happens only when the player clicks on a city block. The net result has practically no performance impact and still fits nicely hand in glove with Unity’s physics setup. With all of that in place, player can finally make info clicks on buildings in scene.

While I was working on this, I decided to add shop quality text. When the player enters a shop in Daggerfall, the overall quality level is presented to player as a popup. Each shop has a quality value between 1 and 20 with a total of 5 different quality popups. I’ve long assumed it was just qualityValue/4 to get the popup, but testing proved otherwise. Daggerfall weights the quality text a bit more in the mid-range that the extreme low or high ends. After checking shops in Daggerfall city and Gothway Garden, I think I have the weightings worked out. Anyway, It’s something that can be easily tweaked later if needed. Now when player enters a shop, the quality text will popup like in classic.

 

Because the popup actually prevents player from entering building until they click a second time, I added a quick INI option to present quality text to HUD instead, with a configurable delay. With this option configured in INI (ShopQualityPresentation=1), you can enter every building with a single click and watch the quality text scroll off HUD. You can also set ShopQualityPresentation=2 just to turn off quality text completely.

 

While I was on a roll with the whole info setup, I made a start on identifying static NPCs. These are the flat people standing around inside buildings and interior environments like Daggerfall Castle. This will be critical to dialogue as part of questing system eventually, so might as well break some ground for later. The first part of this was simple, just detecting when player clicks on an NPC.

 

Yep, that’s an NPC alright. Exactly how an NPC is detected had to evolve a little over the process of getting this initial text in place. I previously did this by detecting if the billboard had a faction and a gender – something I assumed only NPC billboards would have. This turned out not to be the case and there are plenty of factionless NPCs standing around. Also, the NPCs in building interiors had a different metadata setup to NPCs in dungeons. Just like Daggerfall to use two different data structures for effectively similar things. I ultimately determined NPC status by the texture archive flat belonged to. There are a small range of NPC-specific texture archives and this served better than faction to determine if player has clicked an NPC or not. In the process of doing all this, I actually gained some better understanding of a particular bitfield and found a new gender bit assigned to NPC records.

Before I can identify an NPC properly, I need to use their faction information. An NPC with faction type=4 is an individual NPC which means their name comes directly from faction data. Other NPCs just get a random name generated based on their gender. So before diving any farther down this rabbit hole, I have to implement factions for the player.

I had written faction file reader around a year ago, but this just reads the initial database from FACTION.TXT in game data. In Daggerfall, this initial faction data is assigned to player character at time of creation and persists with player all through their adventuring career. Every interaction can raise or lower their standing with a particular group. To start tracking faction data properly, and to make this information available to NPC info clicks, I added the PersistentFactionData class to player entity. This class represents the player’s current standing with all factions and provides basic lookup functionality. This has already been wired up to save/load system, so when you save a game in future builds, your faction data will be saved as well. This is also an important milestone for the questing system.

With faction data on the player, we can identify individual NPCs like King Gothryd and Queen Aubk-i.

 

But it means that group-based NPCs don’t resolve properly by faction alone.

 

These NPCs need to have a random name based on gender. Thankfully I’ve already written the random name generators, as these were required for building names and elsewhere. The only thing I’m missing is the correct seed value to generate the exact NPC name that Daggerfall uses. For anyone unfamiliar with random generators, the same seed value will always output the same result. Unfortunately, I wasn’t able to find the seed value Daggerfall was using to name NPCs. You’d think this would be obvious like it was for buildings, but sadly not. I decided that one random name is probably as good as any other for these non-essential NPCs and just used their record offset as a seed value. This means they will always have the same persistent name generated each time, it just won’t be the same name as in classic. If the correct seed value is ever located, I can just feed this into the generator instead and the correct name will pop out. Until then, it probably doesn’t really matter. Say hello to random NPC Alabyval Coppersmith.

 

At the end of this little coding adventure, all of the following has fallen into place:

  • Change activation mode between Steal, Grab, Info, Talk.
  • Identify buildings and static NPCs.
  • Shop quality text is now displayed when entering a shop.
  • Faction data now exists on player entity and persists with your save games.
  • The foundation for checking NPCs in scene are ready for “Person” quest resource.
  • The raw data needed for “Place” quest resource now in scene.

With all that done, I can go back to working on “Place” resource and “pc at” condition for quest system. You can see what a rabbit-hole this whole quest setup is. It touches on so many different parts of gameplay that sometimes I need to go in a different direction for a while before I can loop back and progress on what I’m trying to build. But it all adds up, and every tiny step brings us closer to real gameplay.

For more frequent updates on Daggerfall Unity, follow me on Twitter @gav_clayton.

It Lives!

With some back-end and core actions out of the way, it was incredibly satisfying to watch the quest system spring into life today. The two bootstrap quests are now launched with a new character. They don’t do much more than popup messages right now, but everything starts somewhere.

The work from here is “just” building out all the remaining actions and conditions for quest scripting. I say “just” because it’s still a huge amount of work. But it’s finally starting to feel like I’m getting somewhere!

If this doesn’t look like an awful lot of progress for a few months work, remember it’s a black triangle milestone. This is a pioneer of more interesting stuff to come.

December 2016 Test Build

Hello everyone! This will be my last post for 2016. It’s been a great year for Daggerfall Unity with solid updates across the board. I was hoping to have basic quest support in by now, but sadly not everything goes to plan. This will return as a priority early in 2017 so watch this space!

One thing that always amazes me is the quality of work this community is willing to put back into Daggerfall Unity. It’s always a pleasure to find a new pull request on git from someone willing to contribute their personal time to make this project even better. So this post is going to focus almost exclusively on contributions from community members. It’s time for kudos and credits all around, and you’ll see very little of me this post.

 

Texture & Mesh Replacement

This feature began with Uncanny_Valley and has lately been updated and maintained by TheLacus. It allows for runtime injection of new textures and meshes into Daggerfall Unity’s scene builders, setting the stage for updated models, higher resolution materials, and improvements to Daggerfall’s vanilla UI. It’s still early days but the potential is incredible. Here’s a few screenshots of new assets by community members.

 

At time of writing, mesh and texture replacements aren’t quite ready for download. But now support for this is baked into the core, you should start seeing community-created packs in the near future. You can read more about mesh and texture replacement in this thread on the forums.

 

Early Bow Combat

New contributor electrorobobody added basic bow combat to the lineup of supported weapon animation. No counting arrows yet, and you’ll need to roll a new character for your free silver bow, but it’s awesome to finally burn down enemies with ranged kiting. Looking forward to bows becoming a strong part of the game in future.

 

Save & Load Weather

Daggerfall Unity added basic weather events a while back, but they would not be saved and loaded with your games. Thanks to midopa, the current state of weather will be saved and loaded. This will only get better once correct weather events are wired up based on climate and season.

 

Enemy Steering

Another epic update by midopa. He added a little steering to enemy AI to prevent enemies from stacking on top of small creatures like rats. As hilarious as this problem could be, it’s good to see a workable solution for this bug. It’s still possible for enemies to slightly stack in edge cases, but the problem is much improved and they will no longer ride around on each other (imagine skeletons surfing rats and rat-rat-rat stacks).

 

Potion Recipes

The perennial InconsolableCellist returned with some amazing updates for us. Credit goes completely to him for working out potion recipe format and integrating with Daggerfall Unity. This also means potion recipes will display properly in inventory, and they’re even usable to see the individual ingredients. This is really important ground-work for a bunch of other things down the line.

 

Books

I wrote the initial book reader UI ages ago, but InconsolableCellist wrapped it up along with random book drops in loot, correct tooltips, and all-round awesomeness. Books currently exhibit the same formatting problems as classic (because it’s the same book data). That’s something yet to be fixed.

 

Exterior Automap

Nystul has done it again with the perfect companion UI to his dungeon and interior automap. Yep, exterior automaps are now a thing! It even supports proper tagging of buildings, zoom, and rotation. As always, I’m completely blown away by how complete this is right from the start. It’s still waiting on full building name integration and building identification in scene, but that will come. For now, all the buildings are tagged by type. Go explore!

 

Spotlight: Allofich

I can’t give Allofich high enough praise. He has worked incredibly hard tuning up different areas of Daggerfall Unity to make it more true to the original. He fixed a wide range of UI problems, identified sound effects, linked sounds to their correct actions, fixed clothing and item problems, and so on. Check out his full list of commits here. It’s hard to show these off properly in screenshot form because the changes are either subtle improvements or related to audio, but below is one of the UIs he has cleaned up. Note the poor texture joins in the “before” image (circled). Huge props to Allofich for his work!

 

Thanks To: AnKor

OK this is embarrassing. I was looking everywhere for the animations used when player was riding horse or cart. These turned out to be in the overlooked CFA image file format. Somehow, I had completely disregarded these files which are a format holdover from Arena. Yep, I’m only human. Fortunately, AnKor pointed this out on the forums and I was able to implement CFA support in no time. Now we have this:


It’s only a short jump from here to having these transport options in the game.

 

Thanks To: Testers

I also want to send out a huge thanks to all the amazing people who tested Daggerfall Unity in 2016 and reported the bugs and problems you found. There are simply too many people to list, but you know who you are. You’re on the forums, and Twitter, and Reddit, and sending me emails. You guys rock!

 

Bugs and Problems

Yep, we got ’em! Any large update like this will bring its fair share of new bugs. If you come across a bug during tests and would like to report it, please lodge this in the Bug Reports forum. Don’t forget to read the Guidelines to help you provide the best information to developers.

Contributors, please keep an eye on the Bug Reports forum for anything that might fall into your wheelhouse.

 

Where To Download?

You can always download the latest version of Daggerfall Unity from the Live Builds page. If this is your first time downloading Daggerfall Unity, welcome! Other information on Live Builds page should also help you get started. If you have any troubles, or just want to discuss updates, please go to the December 2016 Test Builds Updated thread on forums.

 

That’s it for 2016! Thank you everyone for visiting and all your kind words of support. Here’s wishing you all a very Merry Christmas and Happy New Year, and all the best for 2017!

 

For more frequent updates on Daggerfall Unity, follow me on Twitter @gav_clayton.

Building Names

One of Daggerfall’s long-running puzzles is how to generate the correct building name for any given building in a location. Daggerfall’s binary data exposes this information only as a seed value with no obvious correlation to the final name. From today, I’m happy to say this has been solved and I will be able to generate proper building names in the future. This article is a summary of the technical journey, minus all the dead ends and frustration.

The seed value used to generate building names has been known about for some time. This can be found in the BuildingData structure (link to UESP). The first step along the way was to generate some known values by changing a known seed value in MAPS.BSA. I started at the location Ashfield Hall in the Daggerfall province, which has a single tavern and some residences. Taverns are a great place to start as they have a very obvious PartA + PartB structure. For example The Bat And Skull. In Ashfield Hall, our single tavern is the The Howling Stag with a name seed value of 27748.

The first thing I did was change the name seed value for The Howling Stag in MAPS.BSA then start up Daggerfall to see how the name changes. Here’s a small sample of names generated from seeds 0-3. Keep this list in mind as we’ll return to it later.

0 = The Dancing Chasm
1 = The Knave and Scorpian
2 = The Pig and Ogre
3 = The Thirsty Fairy

Now I have somewhere to begin. I know the building is a tavern and have a sample group of seeds that result in specific names. The next trick is to work out how Daggerfall derives these names from the seed value.

I open up FALL.EXE in a hex viewer and search through for strings like “The Dancing” and “Chasm”. These strings are easy enough to locate, but these are just resources packed into the executable. What I need is the actual PartA and PartB tables Daggerfall is selecting from at runtime.

To get this information, I first have to use the DOSBox debugger to dump out memory from Daggerfall while it’s running. I can then search not just for strings, but for memory offsets pointing to those strings. I write a small bit of code to do the searches for me, and it doesn’t take long to find the correct offset tables for Part A and Part B of tavern names. Just think of this as a pair of arrays. In this case, both arrays are 36 elements long. Here they are as captured from the spreadsheet I dumped them out to.

TavernNamePartsAB

So how do we go from a seed of 0 to The Dancing Chasm? This is where most of the difficulty started. It was obvious Daggerfall used a random number generator to pick both parts, but the trick was to find the correct random number generator used by Daggerfall’s C compiler circa 1994-1996. Fortunately, I also needed this for correct texture table generation (still an open problem at time of writing) and had previously researched the correct random generator, known as a linear congruential generator, specific to Daggerfall. Here it is for completeness.

static ulong next;
public static void srand(int seed)
{
    next = (uint)seed;
}
public static uint rand()
{
    next = next * 1103515245 + 12345;
    return ((uint)((next >> 16) & 0x7FFF));
}

There are two methods here, one to set the seed (srand) and another to generate the next random number from that seed (rand). This is pretty much the standard ANSI LCG but specific to Daggerfall’s needs. Implementing this manually ensures that critical random number generation will always work just like Daggerfall, regardless of platform.

Now that I have the right random number generator, let’s feed it our test seeds from earlier and see what comes out. Starting with seed=0 and generating two numbers (indices into Part A and Part B name tables above), I get the following results.

PartA = 0
PartB = 12

First obvious thing is the spreadsheet starts from 1, not from 0. Just need to +1 each number to match the tables above (although zero-based arrays will be used in actual code). Matching these numbers to the above name table we get: Chasm The Dancing. OK, so Daggerfall obviously generates PartB first then PartA. Let’s try that again with the +1 and order swapped.

Seed = 0
  PartA = 13 (The Dancing)
  PartB = 1  (Chasm)
  Result: The Dancing Chasm

Using our handy table we can match row 13 with row 1 and we get The Dancing Chasm. Good! Let’s run some more tests and prove the concept.

Seed = 1
  PartA = 35 (The Knave and)
  PartB = 27 (Scorpion)
  Result: The Knave and Scorpion

Seed = 2
  PartA = 30 (The Pig and)
  PartB = 9  (Ogre)
  Result: The Pig and Ogre

Seed = 3
  PartA = 16 (The Thirsty)
  PartB = 36 (Fairy)
  Result: The Thirsty Fairy

So far, so good! Building names are output just like Daggerfall given the same inputs. Let’s try the original, unmodified seed value of 27748 which should give us The Howling Stag.

Seed = 27748
  PartA = 21 (The Howling)
  PartB = 33 (Stag)
  Result: The Howling Stag

And there we have it! Building name generation from initial seed value resulting in a string exactly matching Daggerfall.

From here, I still need to extract hard-coded name tables for other building types like armorers and weapon-smiths. This isn’t hard though, I just need to find the tables using the same methods as taverns. I also need to assign full building data from MAPS.BSA to the correct models in Unity scene and wire up API methods to query this data when inspecting or entering a building. One challenge at a time though.

For regular small updates on Daggerfall Unity, I can be found on Twitter @gav_clayton.

Items Part 3 – Paper Doll

With item bitmaps and dyes out of the way, it’s finally time to begin work on paper dolls. The concept of layering cutouts of clothing and other accessories over a figure is centuries old, and a perfect solution for early video games where memory was at a premium. Daggerfall’s paper doll system is easily one of the most extensive to be found in video games of the time.

Before equipping anything to the paper doll, a few key pieces had to be researched.

  • Body Morphology. Every bit of armour and clothing has 8 variations to suit the male and female body shapes of Argonians, Elves, Humans, and Khajiit. The correct texture set must be mapped to the correct race and gender.
  • Position. The X, Y coordinates of each item on paper doll is coded into their texture files. This is tightly coupled to morphology.
  • Draw Order. Every item template has a value to determine the correct item rendering order on paper doll.
  • Equip Table. The equipment slots available to player and rules for what is equipped where.

I won’t go into detail about the first three, that information is just managed by the API as part of importing or generating items. The equip table is a little interesting however with a total of 27 slots available. I use the same index setup as Daggerfall itself.

  • 00 Amulet0 (amulets, torcs, etc.)
  • 01 Amulet1
  • 02 Bracelet0
  • 03 Bracelet1
  • 04 Ring0
  • 05 Ring1
  • 06 Bracer0
  • 07 Bracer1
  • 08 Mark0
  • 09 Mark1
  • 10 Crystal0
  • 11 Crystal1
  • 12 Head (helms)
  • 13 RightArm (right pauldron)
  • 14 Cloak1 (casual cloak, formal cloak)
  • 15 LeftArm (left pauldron)
  • 16 Cloak2
  • 17 ChestClothes (shirt, straps, armbands, eodorics, tunics, surcoats, robes, etc.)
  • 18 ChestArmor (cuirass)
  • 19 RightHand (right-hand weapon, two-hand weapon)
  • 20 Gloves (gauntlets)
  • 21 LeftHand (left-hand weapon, shield)
  • 22 Unknown1
  • 23 LegsArmor (greaves)
  • 24 LegsClothes (khajiit suits, loincloths, skirts, etc.)
  • 25 Unknown2
  • 26 Boots (boots, shoes, sandals, etc.)

The two unknowns could just be reserved indices as I was unable to find any equipment Daggerfall mapped to these slots. If there’s more to this, I’m confident it will be found in future testing.

As usual the API handles equipping items for developer, it’s easy as calling EquipItem(item) on the entity’s equip table. If an item of that type is already equipped, it will be dropped in the next compatible slot (if one is free) or swap out an existing item based on swap rules for that item template.

Now that we know which items the player has equipped, the textures to use, and their position and draw order, it’s fairly trivial to start layering down bitmaps onto the paper doll. But as usual, a couple of additional problems must be solved.

First up are cloaks, which have both interior and exterior parts drawn at different stages of the build. The below image shows how the two parts work together.

 

Cloak Components

 

The interior is drawn first, then the avatar, then the cloak exteriors. It’s actually possible to wear two formal or casual cloaks in Dagerfall (slots 14 and 16). Note: the above image was taken prior to order being fixed which is why the loincloth is slightly eroded in first and third images.

Our next problem is masking. Daggerfall has a special mask index allocated to hide hair that would otherwise be drawn outside of helmets. During the build process, the mask becomes transparent and overwrites anything else in that position. Masking is used for both helmets and hooded robes/cloaks.

 

Mask Components

 

Other items can then be drawn based on their draw order. The below animation shows a step-by-step paper doll build after sorting items by draw order.

 

 

Now that items are equipped, we need a way of removing them again. Daggerfall allows you to click directly on paper doll itself to remove an item from your avatar. This is accomplished by creating a special selection mask where each pixel is an index mapping to 0-26 on the equip table above. This isn’t actually visible, it’s just an array sampled when player clicks on paper doll. Following is how the selection mask looks when rendered out to an image using grey values to represent indices. Each grey value maps to an item slot on paper doll.

 

 

AvatarAndMask

 

I’m finally nearing the end of initial item support in Daggerfall Unity. There is still much to do (loot tables, shops, dropping items, repairing, storing items, effects, and so on) but those problems can each be tackled in turn. What I want to do now is clean up some code and begin a new test release cycle. This will allow me to fix any early bugs before moving onto the next stage of item support. I will post more news on this soon.

Items Part 2 – Dyes

Before moving on to equipping items, I thought it would be fun to show off the equipment dye system in Daggerfall Unity.

Classic Daggerfall uses a 320*200 pixel 256-colour display – or more specifically a Mode 13h display. Back in this era, bitmap graphics were typically a width*height byte array of indices into a 256-colour RGB palette. One of the coolest tricks available to graphics programmers at the time was to change index ranges to substitute colours, change brightness, animate textures, and so on. Daggerfall uses index changes and palette swaps to accomplish all of these tricks and then some – it would be possible to write a series on that subject alone. This article is just about changing dyes to re-colour weapons, armour, clothing, and how the old index swaps can be realised in a true RGBA renderer like Unity.

If all of that is difficult to visualise, let’s start with an example. Here’s a pair of basic boots without any changes.

dyes1

Every pixel above is just a single byte index into a 256-colour palette. For example, index 0x70 points to RGB #DCDCDC in the default texture palette for a very light grey. For weapons and armour, the 16 indices 0x70 to 0x7F are reserved for index swaps (clothing reserves indices 0x60-0x6F). In the case of these boots every pixel falls between 0x70-0x7F, but that isn’t true of all items. Sometimes only a small part of the image will support dyes. If we just substitute every index between 0x70-0x7F to another random index between 0x00-0xFF we get the below.

dyes2

Quite the mess, but it demonstrates that changing indices can radically change the appearance of an indexed bitmap. The important thing to keep in mind is that every pixel is not by itself a colour. Rather its just an index pointing to a colour.

The first challenge in bringing indexed colours into Unity is that every time we read in a Daggerfall bitmap it must be converted to true 32-bit RGBA values where every pixel actually is a specific colour. Fortunately converting to 32-bit RGBA in Unity isn’t difficult. The general process is:

  1. Allocate a Color32 array with the same number of elements as width*height of source bitmap.
  2. For every pixel index in source bitmap, sample the RGB colour of that index to a Color32 value.
  3. Write colour sampled from palette into correct position in Color32 array.
  4. Create a new Texture2D of same width*height as source bitmap.
  5. Promote Color32 array to our Texture2D using SetPixels32() and Apply().
  6. Use this Texture2D as needed.

When it comes to changing the dyes, all that’s required is to substitute the correct indices in step 2 before sampling palette. So where do these colour swaps come from and how does Daggerfall know which swaps to use for what items? Daggerfall actually has a couple of different methods for generating swaps. Let’s start with weapons and armour.

Buried inside Daggerfall’s executable FALL.EXE at offset 0x1BD1E2 (for DaggerfallSetup version) are the metal swap tables. There is one 16-byte swap table per metal type. For example, when encountering index 0x70 for a Daedric pair of boots, replace 0x70 with swap index found at daedricSwapTable[0]. For index 0x71 replace with index found at daedricSwapTable[1]. And so on. These swaps have been known about for some time and you can find more details on this archived page from the wonderful old Svatopluk site.

Clothing does not appear to use pre-defined tables like metals. Rather, each swap table is just 16x sequential indices. For example, purple is 0x30-0x3F and green is 0xA0-0xAF. Swap tables can be generated on the fly using a dye enum mapped to starting index. Daggerfall appears to do this as these sequences are not found in the executable like metal swap tables.

Armed with the power to create textures and swap indices, we can now generate our final boots image based on metal type. here are some examples.

dyes3

Orcish

dyes4

Dwarven

dyes5

Daedric

 

One benefit of using the same generic process for metals and clothing is that it becomes possible to use clothing dyes on armour, something Daggerfall can probably do but doesn’t make available to players. This could allow for dye station mods down the road for players to further customise their equipment. With Unity using a true 32-bit palette this could extend well beyond Daggerfall’s 256-colours. Anyway, for an example of armour dyed something different:

dyes6

Blue Chain Boots

 

The next challenge now that we’re using true 32-bit textures is a red pair of boots becomes a completely different texture to a green pair of boots. Whereas in Daggerfall the same bitmap can be used both times by just changing indices as described above in the software blitting function. Between this and the inherent (but minor) performance impact of converting indexed bitmaps to Texture2D, we need some way of minimising CPU time and garbage creation. Caching to the rescue.

Daggerfall Tools for Unity (the underlying API suite) already uses texture caching for general world materials, but items have their own set of problems to solve. To this end, I created a new item helper class to serve up equipment icons and handle the caching based on properties unique to items.

Every time an equipment icon is requested, a unique 32-bit key is generated by packing that request’s variables into a bitfield. The packing looks like below.

dye-key-bitfield

  • Colour enum index refers to the swap table in use. This value matches Daggerfall’s own colour enum stored within base item templates.
  • Variant index is an alternate image for this item.
  • Archive index is the texture file number (e.g. TEXTURE.245) containing the icon.
  • Record index is the icon index within the texture archive.
  • Mask bit is used to enable/disable a special mask used to overwrite pixels like hair around helmets. More on this in a later post.
  • There are a few reserved bits to grow the key system later.

It’s worth pointing out the end programmer doesn’t need to worry about how these values are packed. This all happens automatically under the hood when calling GetItemImage(). What matters is the API has a way of uniquely identifying any individual equipment icon based on its display properties.

When calling GetItemImage() the API will first check cache to see if this exact icon has already been converted from Daggerfall’s native file formats. If not, it is converted and stored in the cache for the next time its needed.

To wrap things up, here’s a new gfy showing a variety of dyed items in the inventory UI.

For regular micro-updates on Daggerfall Unity, I can be found on Twitter @gav_clayton.

Items Part 1 – Bootstrapping

Loot. Kit. Swag. Treasure. Whatever you call it, items are an important part of any RPG game loop. They provide the means for your character to defeat ever more powerful foes and create incentive to keep playing in search of the next big upgrade. While Daggerfall’s items don’t quite tickle the reward centres of the brain like Diablo 3 or World of Warcraft, they’re still a vital part of the play experience. Without decent gear and enchantments, you’re unlikely to survive the grueling ordeal of Mantellan Crux.

In this series, I’ll describe the process of adding items to Daggerfall Unity. I wanted to approach items early on as they will be involved at almost every level of the game. Shops sell them, blacksmiths repair them, monsters drop them, quests reward them. Your character may have a special affinity for bladed weapons, or be forbidden the use of shields. Even the biography questions when building a character can grant you items like the near-essential Ebony Dagger. With items embedded in almost every major game system, the hardest part was working out where to begin.

I decided to start with existing items as part of importing classic Daggerfall saves then bootstrap the whole item back-end from there. That way I could be certain I was dealing with the most real-world data possible. Having built support for classic saves in 0.1, I could already identify item records parented to the main character record and visualise them with a custom Unity Editor script. They looked a bit like this at first:

 

Items1

It’s not much, but at least I could find item records belonging to the character. The “Container” record is just a generic parent record. In this context, think of it as the character’s backpack.

The next step was to break apart the item record format. Fortunately the UESP came to the rescue here with most of the bytes already solved, but far from the whole story as you’ll see once the names are revealed:

Items2

A Frosty what of Ice Storms? OK, so there’s more to this than just the save record. How to we go about filling in the blanks? The key here is the “category” 16-bit field in that UESP article. This is actually a pair of 8-bit values. The first byte is the item group, the second byte is a table lookup for the item template within that group. The template indexed by this lookup has all the missing pieces of information we need to complete our item data. Now we have two more problems to solve. Where are the templates, and how to use those category bytes to find them? Let’s start with the templates.

Item templates are actually built into FALL.EXE. The offset is a little different depending on your version, but the easy way to locate them is open a hex editor and search for “ruby”. You will find the following data:

Items3

Here are all the item templates laid out one after the other. They even follow a certain kind of logic, with gems, weapons, armor, etc. all more or less grouped together. Fortunately this isn’t exactly unknown data and the UESP came to the rescue again with a good starting point for these templates. I just had to fill in some blanks.

I didn’t want to keep this data in the .exe however, it’s much harder to modify these templates later. That’s why I exported the item templates to JSON format. Once exported the above data looks like this:

Items4
Much easier to work with. There are still a few unknowns to work out but those will be solved over time. The next problem was how to link up instantiated items like our Frosty %it of Ice Storms back to their original template. I had to reproduce the lookup table Daggerfall was using internally.

It was here Lypyl provided a helping hand thanks to his research into magical items and artifacts. The file format of MAGIC.DEF is very similar to instantiated items found in save games. Furthermore, the creators of old item editors had solved quite a few of these problems back then. Armed with all this, Lypyl could derive enough information to rebuild the group and item tables which he kindly provided to me in C# enums. All I had to do then was link the enums back to their template index in the above JSON file.

The main group enum looks like below. It corresponds to the first byte of the earlier category short.

Items5

For every element in the above enum (such as Armor, Weapons, etc.) there is an enum for every individual item in that group. For example:

Items6

For the item enum, the individual item value is an index back into the template table. The order within the enum corresponds to the second byte of the category short. With a helper class to bring all this together, it was now possible to perform lookups from instantiated items back to their template data. This is how our items viewer looks now:

Items7

Success! We can now resolve an item’s template by type to discover the full name and other useful information. The next step was to determine which items are equipped on the character. Fortunately the “equipped” table is just another record in your save game, and was already known about thanks to that first UESP article. I just had to work out how that table referenced items and I could isolate which were equipped. Items marked by an asterisk are equipped to character.

Items8

There are almost two dozen equipment slots in total that map to specific parts of the character’s body and elsewhere. I will describe this in more detail in a future article.

With all of that research out of the way, my next job was even less visual than above. I had to write support classes such as API helpers and an entity item collection class. I also required a new type of image reader to handle the job of loading and caching item images for the inventory UI, tinting them based on material, cutting out unique alpha indices like the hair mask, and so on. Anyway, boring or not these new classes form the foundation of items in Daggerfall Unity and will continue to grow as needed.

With everything finally in place, I could start building the equipment UI to sort, view, and equip items imported from classic Daggerfall save games. Besides a few UI enhancements and fixes, the following came together fairly quickly.

Some of the enhancements in this gfy include a scrollbar and mouse wheel scrolling. No reason we can’t have a few light modern touches to make our lives easier.

More About Scaling

One of the issues that caught me by surprise was a UI scaling problem. This turned out to be more interesting than expected, so I decided to write up a visual diary post about it.

For those who didn’t experience the problem, this is how it looked (1280×960).

ScaleBug1

What’s happening here isn’t technically a scaling problem, it’s a positioning problem. See, Daggerfall has a fixed-size UI of 320×200 pixels. My custom UI system was designed from the ground up to scale Daggerfall’s fixed UI to any resolution while maintaining correct aspect ratio. Depending on the width to height ratio of your resolution, the fixed UI may need to be pillarboxed (black bars down the sides) or letterboxed (black bars top and bottom). The goal is to fit the entire UI into the display without any clipped off edges and keeping that pixel-perfect ratio.

So what’s going in the screenshot above? The answer is that I forgot to turn on vertical alignment in the UI for the parent panel. This means the UI is stuck to the top of the screen instead of letterboxing like it’s supposed to. This is how the above display should look (1280×960).

ScaleBug2

The scaling and aspect ratio are correct in both cases, just the UI wasn’t centering vertically like it should for the letter-box effect at that resolution.

Unfortunately, it really isn’t possible to avoid pillarboxing or letterboxing with a fixed UI, unless you have a resolution that is an exact multiple of 320×200. For example, the screenshot below is a perfect x4 multiple of 320×200 and fits the frame completely at the correct aspect ratio (1280×800).

ScaleBug3

Now it occurs to me that some people simply don’t want letterboxing or pillarboxing. The best solution I can offer is a new option in the INI called “FreeScaling”. When this is enabled, the GUI will scale width and height independently. Here’s an example with FreeScaling enabled (1280×960).

ScaleBug4

The result is the UI is stretched as required to fill entire viewport. This obviously means the aspect ratio is no longer correct, but the chunky pixels still don’t look that bad with a little stretching. I’m willing to bet a lot of people actually play this way in DOSBox without noticing. It’s all down to personal preference anyway. If you want perfect aspect ratio, just leave things at default and the UI will scale and position itself properly now. If you definitely want to get rid of the black bars, then enable FreeScale and enjoy.

It’s also worth noting this does not apply to the game view rendering, which always fills the entire viewport. Only the classic 320×200 UI has this quirk.

I’m just happy my retro UI system is robust enough to handle all these different resolutions, scales, and positions while still working as it should. That’s an accomplishment by itself.