This post has been mirrored from our site.
Hello, and welcome to the 10th devlog for Ardenfall, the Open Ended RPG! I know it seems a bit strange for there to be both a 6 month gap and 8 missing devlogs, but in truth we've been posting on our own personal website, and I had decided to simply not update here. Well,I decided it would probably be a good idea to update on both sites, so here we are!
This is a more technical post, with few gameplay features. However, I hope you can still enjoy reading, alongside checking out our last devlog.
New Armor Set
Toshi has done it again, building a new armor set. This time the armor is from the highlands, with a more expensive look. It also brings in the first set of gloves in the game with the new rig, and I personally love them!
New Clutter Meshes
Some new clutter meshes have been added – first some spools and spindles, and then some fish. Both of these are going to be used to give the various spinners and fishermen of the swamps some nice decorations, as well as drops. I especially like the fish rack, since you can actually collect the fish.
Major Dialog Redesign
Even over the time span of posting devlogs, dialog has had a lot of changes: it started as a graph-based tool using xnode, and then was transformed into a scripting based system instead. I was very excited about having the new format, but after months of working with it, I’ve arrived at the conclusion that it is simply not the direction to go.
Therefore, we’re back to the drawing board. I’m starting work on an entirely new dialog tool, built atop NodeCanvas, and the core functionality (greetings, topics, speech, branching) are all in place. Now I need to add logic blocks, and ways to pass variables around. My goal is to have a functional form of this within a week or two.
This also introduces the change of dropping python scripting entirely for gameplay features. I’m still planning on using python scripting for console commands, debugging, and mod support. But any logic that was once scripted, such as quests or quest related logic, will be moved to visual scripting built on FlowCanvas.
Improved Item Lists
Item Lists are exactly what they sound like: lists of items. They are used to define what characters will have equipped and what they drop, as well as merchant wares and container loot. The previous implementation was tedious and confusing, but they have now been improved.
There are two forms of item lists – Simple, and Graph. Simple lists allow for basic random item selection, but Graphs is where the system truly shines:
In the above example, the item list will grab a helmet, a random chest piece, a random leg piece, and either a random melee weapon, or some arrows plus a bow. This is merely a simple taste of how powerful this tool will be: it also supports sub graphs (graphs inside of graphs), and leveled selection (picking different items depending on character/container level). This system will make it easy to add variance to characters and drops!
Misc Item Generator
Creating simple items (objects that can be picked up) can be a chore, especially when there are dozens of them to be made. Thus, I built a tool that can make it easier. All you need to do is determine its name, visual, weight, and cost: the rest, including the save path, is automated.
This also marks the beginning of the large creation of items. Before, objects such as plates, cups, baskets, etc were all static meshes. I now plan on making these all physics items. This removes the odd “Why are some small objects items and others are not” issue, as well as adding interactivity to the world, as well as junk to containers and character drops.
After doing some tests, I realized interiors are quite expensive. Our goal is to build towns and even small cities, so it’s very important for such buildings to be as optimized as possible. Unlike games such as Elder Scrolls, most interiors are not hidden behind a loading screen. This makes gameplay smoother, but means being careful with lighting and other things is incredibly important. I implemented several optimizations:
I built a small tool that automatically packs all static meshes into a LODGroup, which then sets it up to fade away to cull. In other words, I attach this to the root of the interior objects, and it will automatically fade away the meshes when the player is a certain distance away!
Light Culling + Light Importance
The most expensive part of interiors is by far the lighting, especially if they are casting shadows. This tool solves this, by fading away lights when the player is a certain distance away.
In my last devlog I added shadow importance, where objects tagged as unimportant will only have shadows on high end devices. I did the same with lights this time around, so now I can have extra lights (such as candles) without needing to worry as much about lower end devices: they’ll just disable in that case.
I also built an automated mesh merger, that merges static meshes into a few meshes, one mesh per material. I haven’t done enough testing to see if this is actually valuable, since the alternative is to simply let the static batcher do its job. Regardless, it’s a good tool to have!
This house is merged into 3 objects: exterior architecture, exterior decor, and interior decor
One trick I like to use is to spread loading over several frames. I already do this with the spawning of dynamic scene objects, such as item pickups, and this time around I used it a few more times.
Character Streaming: When streaming, NPC’s now have a frame to themselves. In the future I plan on copying the system I used for items, which actually weighs it depending on the number of items being loaded. This means if there are a huge number of npc’s to load, it doesn’t take forever to stream in.
Object Streaming: I can now add a “StreamedObject” component to an object, and during the prefab bake this streamed object would be converted into its own prefab. Then, during runtime, it’s streamed in on its own frame. I’m currently using this trick for houses, since they’re prebuilt prefabs and are kinda their own little world. This approach would of course not work if there are any scene references to outside of the house! I plan on adding a safety feature that scans all of the components in the scene to detect any references between the scene and the streamed object, to ensure there aren’t any. It wouldn’t be perfect, but I think it would be a helpful tool regardless.
Shorter Nakiban Ceilings
I lowered the ceilings in the Nakiban style housing, which made the scaling feel a lot better. I was worried this change would be a huge pain to implement, but it wasn’t!
Item Visual Variants
I’ve started adding support to have items have multiple meshes. For example, I have several cup meshes, and I would rather not create an individual item for each one. This would clutter up the project, and just be a mess. Instead, all of these mesh possibilities would be stored in a single item dataset, and then during spawn it would select a random one, or the developer could alternatively decide which one they desire.
I now store references to nearly all generated assets (assets that are not stored on source control), such as generated prefab cells, distant cells, and so on in a large scriptable object. This object is also not stored on source control, which means generating assets will cause no changes, from git’s perspective. This is really good, since before I stored the reference in the celldata asset, meaning every time I generated a prefab cell, the celldata was being marked as modified. No more!
I’ve started to jump into certain areas of my code to refactor and redesign. This is mostly the character related code, which is over 4000 lines in total, when counting the CharacterBase, NonPlayerCharacter, and PlayerCharacter classes. This is clearly not the ideal, and so far I’ve managed to move over 1000 lines of code into separate classes. So far so good!
And that is that! I hope you enjoyed the article, even though it was much more technical than usual. If you’re interested in learning more about Ardenfall, be sure to check out our Twitter and join our Discord. Have a wonderful day 🙂