11/22/2014 – State of the Game


It’s been a week of squashing bugs and reading posts. Here are a couple of things I’ve learned from watching everyone play. From roughly MOST to least important:

  • Inventory bugs are the worst bugs. The inventory bugs really seem to spoil everyone’s day. Nobody likes it when their stuff disappears. So I’m putting a lot of work into those. You’re not seeing many big updates, but case by case that stuff is getting fixed. The trickiest part is getting older save games to behave – I’m sort of embracing the challenge of making that work instead of just saying ‘start a new game,’ because I want to preserve save-game integrity after we launch on Early Access.
  • Crashes after the Prologue are far too frequent. The move from the Prologue to the Unviersity is very resource heavy and as a result even mid-range machines are experiencing crashes. My changes to the character textures should help a bit, but I need to do more.
  • Players need more information about basic gameplay. And I don’t mean hand-holding, just information. The Prologue is tiny, self contained and very short. Once that’s over I get the sense that people are overwhelmed by what they don’t know. The game is simple once you know the basics (I think?), so I’m going to write a little guide book similar to the interface guide book. That will be what you find when you wake up in class – it will give you some bullet points on how to play. (I really want to implement some tutorial missions as ‘classes’ in the University, which is something Hannah has suggested. But that’s probably too ambitious.)
  • Saving and loading. It’s getting better. But players should never spawn inside an empty building, it kills the fun dead.
  • Resources aren’t obvious enough. For instance, wild animals are way too good at staying hidden. They’re actually all around you – dozens of them, seriously – but nobody ever sees the frickin’ things. I’m going to make them dumber because they’re intended to be a resource, and you can’t gather what you can’t see. Same goes for mine-able rocks, trees and so on.
  • The main survival elements seem ‘fair’ to most people, but the weather system is confusing. I haven’t heard any complaints about how quickly you get hungry or tired or thirsty, so it seems as though these elements are fairly well balanced. The exception is temperature which (on top of being buggy) seems to just confuse everyone. I need to work on that.
  • People don’t seem to mind buggy updates as long as they’re frequent. I could be misreading this one, but I’ve broken the game several times with my 2-3 builds per day goal, and people haven’t complained. So I’m going to keep doing that. (Now’s your chance to stop me if you were just biting your tongue earlier.)

Alright. I still don’t think we’re ready for an awesome Early Access launch yet, but we’re getting there, especially if this pace keeps up. Several systems have really started to come together since the beta was launched. Onward!

Read more here: 11/22/2014 – State of the Game

11/16/2014 – GitHub: Now what?


Alright, here it is. I’ve chosen GitHub and set up a profile, an organization and a public Repository under the GPL 3.0 license. This is where FRONTIERS’ code is going to be made available for modders and enthusiasts.


Now what? Organizing this is… daunting.

First off, I won’t be uploading the entire project to GitHub because there are third-party libraries that I can’t redistribute (yet). Instead I’ll be uploading the pieces that I know for sure are free and clear. Over time I’ll add dependencies as I secure permission from the authors.

That means people won’t be able to compile something that, you know, runs. They won’t even be able to supply the missing dependencies from a third party because in most cases I’ve modified the middleware I’m using. They’ll just be able to look at pieces. Does this break some kind of GitHub code? Are repositories for projects expected to be complete? I dunno.

Then there’s the problem of how to incorporate other people’s changes back into the main project. (I’m assuming someone, somewhere may actually want to change something.)

Right now I’ve got a local project. I edit that, then commit my changes to a remote CVS repository. Given that setup, what to do if someone out there sees fit to commit a change to GitHub, and I see fit to incorporate that change into my local project? Is it even possible to mix and match two svn repositories at once? If not, what happens if I slip up and don’t commit my local changes to GitHub for a week and that person has now altered an outdated version of a class?

*Mind boggles*

Alright. Well. I’ve created the repository. First step: complete.

Read more here: 11/16/2014 – GitHub: Now what?

11/15/2014 – Day One: *WHEW*


Well, that was a hell of a day. Let’s count off some numbers:

  • 543 keys activated
  • Average number of concurrent players: 20
  • Median play time: 3 hours 5 minutes
  • Number of builds pushed: 4
  • Number of bugs fixed: ~9
  • Number of bugs reported: ~38
  • Number of games saved / loaded (by me): 51
  • Number of pigs killed: 58
  • Number of emails answered: ~60

Overall a good day. Exhausting but good. And I think FRONTIERS held up okay. There were moments where it was creaky – there were even a handful of unfortunate on-board graphics card owners for whom it wouldn’t start up – but it held together slightly better than I’d hoped. And it’s only going to get better as more of these bugs get fixed! Here’s today’s changelog:

Added additional logging to save game process
Containers added to inventory on startup will no longer spawn items when opened
Characters no longer disappear in previously loaded buildings
Switched from SHA256CryptoServiceProvider to SHA256Managed for group hash generation
Switched to .NET 2.0 subset (grr)
Examine no longer opens / closes doors
Fixed startup history book formatting
Changed liquids to require liquid container on removed from container
Changed startup fill categories for Prologue & Act I
Added fill instructions to Canteen on examine
Changed container fill time to OnVisible instead of OnOpen by default
Inventory items can no longer be moved while popup menu is active
Made pig den smaller in prologue to avoid clipping
Fixed motile action start without live target
Creatures can be looted with remove item skill Clean Animal
Removed ‘E:Search’ from HUD on characters before death / unconsciousness
Fixed some (not all) dangly ragdoll bits on characters
Added examine message to drawbridge
Fixed DenSick exception in Creature
People should no longer disappear from Camp Reuna on load
Added FOV setting to cutscenes
Tweaked prologue cutscene intro to make text more readable
Disabled nighttime LUT temporarily
Added nighttime LUT setting to kill over-vibrant greens
Fixed bookcase colliders interfering with item placement
Recepticles only show placement options when placement mode is enabled
Added throwing
Created placement mode toggle
Added ‘Mine’ HUD item for damageable / mineable scenery
Created item placement toggle for recepticles

Wow, what is this feeling? Is that… optimism? It kind of stings.

Read more here: 11/15/2014 – Day One: *WHEW*

9/26/2014 – I'm not dead!


And the beta is coming, scout’s honor! I’ve been adding people to the steam dev list so they can try the beta before it launches.* Just a small handful outside of the regular bug testers. They’re helping me make some choices about what to clean up before I send it out to backers. There’s still a lot to do, a shocking amount in some areas, but more and more I’m setting things aside to be finished ‘during / after the beta’ because I want to get this damn thing out and start getting some real feedback. I’m also getting the Steam bug reporting thing going, which is far FAR superior to the forum-based bug reporting we had on the alpha. And I’m working on a new Kickstarter update. And so on.

I’ve got a devlog about modding code halfway done but I’m putting that on hold because this weekend I’m actually going to a family function. Yes, I am stepping outside of the house. Crazy, right? This is my first outing in 9 months I think (!) so hopefully I still remember how to interact with real live human beings. I guess we’ll see!

*Sorry, I’m still not announcing a release date for the beta. I know that drives y’all crazy. Hang in there.

Read more here: 9/26/2014 – I'm not dead!

8/20/2014 – WTF Windows


It seems like every day I’m fighting with some obscure limitation with the engine or the OS instead of polishing the gameplay or implementing more quest stuff. Really frustrating.

Today I crashed into an absurd limit: the 259 max character limit for file paths in Windows. A exceptionally deep part of my WIGroup hierarchy produced a 160+ character path, which when combined with the path of the project resulted in 263 characters. So the file wouldn’t save, resulting in lost progress and disappearing items.

I briefly considered truncating the offending group names so the items would save. But there’s no arbitrary limit on WIGroup hierarchy depth so that would only be a temporary solution. *sigh* better squash this permanently.

I know for a fact that NTFS file system supports file paths with up to 32,000 characters. So I looked into libraries that circumvented the ridiculous limit that the Windows API forces on you. At that moment I didn’t care that this solution would be Windows-specific – I just wanted the problem gone so I could move forward. But it was a moot point anyway – all of the libraries available required tools that aren’t included in the .NET 2.0 subset that Unity forces me to use. Oh well, whatever. Guess I’ll roll up my sleeves and implement a cross-platform solution. Maybe Unity’s half-assed 2.0 subset actually saved me some trouble down the road.

Soooo I ended up implementing a string compression system that takes these uber-long paths and converts them to a guaranteed-to-be-unique 64-bit integer, which is then converted to hexadecimal for a (semi) readable directory name (eg Root.World.C-2-3-14.WI.AG becomes 9BDB8EA3B81D90AE). Thankfully because I’m not an idiot I funnel every request to save and load through two primary functions, both of which are abstracted to hell before any in-game object touches them. So I was able to make this change relatively painlessly. This setup kind of cramps modding in my opinion (since you could actually browse the hierarchy as it existed in game before, where now you have to jot down IDs to find stuff) but whatever. Gotta do what you gotta do.

Just so we’re clear here: My goal was to save a file to disk.

Save a file.

To disk.

Save. A. File. To. Disk. For fuck’s sake. Could today have been any less productive? I doubt it. Thanks, Windows!

Read more here: 8/20/2014 – WTF Windows

8/9/2014 – Bartering – Let's try that again :)


Bartering is finished! I’m really pleased to check this one off because it ties a lot of other systems together.

On some level most rpgs are about stuff. Finding it, hoarding it, using it, buying it, selling it, stealing it. The buying and the selling is important because it makes every item useful to every player. There are seashells in the game but I’m guessing only 1/100 people will be picking up seashells just to keep them, right? Most of you will sell them at the nearest curio shop.

Bartering is one of the handful of skills you start the game with. It’s also the one place outside of the main quest where your character’s reputation has a real effect on gameplay: prices.

Each item in the world has a base currency value. But your bartering skill combined with your reputation determines how much people are willing to pay for those items. Here’s the math:

Code: Select all
int TotalValuePlayerGoods;
int TotalValueCharacterGoods;
float repPriceModifier = 0f;
float skillPriceModifier = 0f;
float goodsPriceModifier = 0f;

//recalculate the base value of goods in this barter session
int BaseValuePlayerGoods = RecalculateValueOfGoods (BarterParty.Player, BarterSession.PlayerGoods);
int BaseValueCharacterGoods = RecalculateValueOfGoods (BarterParty.Character, BarterSession.CharacterGoods);

//get the player's reputation with the current character (incorporates global reputation)
ReputationState rep = Profile.Get.CurrentGame.Character.Rep.GetReputation (BarteringCharacter.worlditem.FileName);
repPriceModifier = rep.NormalizedOffsetReputation;//this will be a value from -1 to 1
skillPriceModifier = BarterManager.State.NormalizedOffsetUsageLevel;//this will be a value from -1 to 1
goodsPriceModifier = (repPriceModifier + skillPriceModifier) / 2f;
if (BarterManager.HasBeenMastered) {
//mastering the barter skill reduces all penalties to zero
goodsPriceModifier = Mathf.Max (0, goodsPriceModifier);
goodsPriceModifier *= Globals.BarterMaximumPriceModifier;

//divide the final modifier by 2 to get its effects on both sets of goods
TotalValuePlayerGoods = BaseValuePlayerGoods + Mathf.FloorToInt (BaseValuePlayerGoods * (goodsPriceModifier / 2f));
TotalValueCharacterGoods = BaseValueCharacterGoods - Mathf.FloorToInt (BaseValueCharacterGoods * (goodsPriceModifier / 2f));

You won’t see these hard numbers in-game (though they appear in the screenshot for debugging purposes) but you’ll definitely notice when you buy an apple for 5 and can only sell it for 1. This is assuming they’ll barter with you in the first place. If your reputation is bad enough they’ll simply refuse, in which case you’ll have to make a living by stealing. It’s a downward spiral of criminal behavior…

Read more here: 8/9/2014 – Bartering – Let's try that again :)

7/24/2014 – Creature AI Part 2


The Creature AI upgrade stretch goal is now 100% complete. In addition to the behaviors I blogged about earlier we now have companions, stealth and behavior voting.

Companion AI

You can tame animals with their favorite food. If a creature sees you with their favorite food equipped they’ll wait and watch you. If you manage to approach without scaring them – timid creatures will bolt if you do anything but crouch and move slowly – then you can tame them with a context skill. They’ll eat the food and follow you around from that point on.

If any hostiles attack you, they’ll attack the hostiles on your behalf unless they are Timid and spook. If they don’t have hostile capabilities then they’ll just follow you and look at things they find interesting. If the animal has at least average intelligence (the range is ‘Stupid, Average, Smart’) then you can instruct it to wait for you. But it will only wait as long as its short-term memory lasts.

The best part? None of this is hackey or kludgey – it’s all done using the Motile script, two WIScripts (Tameable / Tamed) and a basic Skill script.


Creatures can now ‘hear’ IAudible objects within their hearing range and ‘see’ IVisible objects within their view distance and field of view. IAudible / IVisible objects can influence the effectiveness of the creature’s seeing and hearing by supplying multipliers for these ranges. So if a creature sees the Player (which is both an IAudible and an IVisible) and the player’s combined stealth skills return a 0.5 multiplier on any creature’s visible range, then the creature fails to see the player at any range greater than half its visual range. Separating the visual / audio makes it possible to mix and match stealth skills – Eg the Silent Stalker skill will decrease your audible range while the Hidden skill will decrease your visible range. And creatures who have bad eyesight can have great hearing & vice versa.

By design creatures can’t identify anything based solely on sound, but they can hear just about anything including the rustling of leaves and bushes. If they turn to look at the source of the sound, then they can identify what it is.

Here’s a top-down screenshot from Unity where I’ve turned on visible field of view / audible range for players & creatures:

It’s nothing fancy – there are some really amazingly sophisticated stealth engines out there – but it gets the job done. The only unanticipated downside of all this is that the stealth skills make it harder to train animals, since they have to see you holding the food and a narrowed field of view / reduced visible range makes it harder to get their attention. Not really sure how to fix that one.

Behavior Voting

To keep all these WIScripts (Timid, Aggressive, Hostile) from contradicting each other I’ve created an anonymous voting system. Each Creature has a CollectiveThought object – they can collectively vote on how to react to what they’ve seen. Whenever a Creature is informed that they’ve seen an item of interest, it loads it into its CollectiveThought and invokes its OnCollectiveThoughtStart action. Any WIScripts subscribed to that action can vote on how to react to it. It can also vote multiple times if it’s really serious. Here’s how the TImid script handles a CollectiveThought:

Code: Select all
namespace Frontiers.World
public class Timid : WIScript {

public Creature creature;

public void OnInitialized ( )
creature = worlditem.Get ( );
creature.OnCollectiveThoughtStart += OnCollectiveThoughtStart;


public void OnCollectiveThoughtStart ( )
IItemOfInterest itemOfInterest = creature.CurrentThought.CurrentItemOfInterest;
switch (itemOfInterest.IOIType) {
case ItemOfInterestType.Player:
if (creature.IsFamiliarWith (Player.Local.ID)) {
creature.CurrentThought.Vote = ItemOfInterestReaction.IgnoreIt;
} else {
if (Player.Local.IsCrouching) {
creature.CurrentThought.Vote = ItemOfInterestReaction.FleeFromIt;
} else if (Player.Local.IsWalking) {
creature.CurrentThought.Vote = ItemOfInterestReaction.FleeFromIt;
creature.CurrentThought.Vote = ItemOfInterestReaction.FleeFromIt;
} else if (Player.Local.IsSprinting) {
creature.CurrentThought.Vote = ItemOfInterestReaction.FleeFromIt;
creature.CurrentThought.Vote = ItemOfInterestReaction.FleeFromIt;
creature.CurrentThought.Vote = ItemOfInterestReaction.FleeFromIt;

case ItemOfInterestType.Scenery:
//scenery is things like rustling trees
creature.CurrentThought.Vote = ItemOfInterestReaction.WatchIt;

case ItemOfInterestType.WorldItem:
if (creature.CurrentThought.CurrentItemOfInterest.worlditem.Is () && !creature.Den.BelongsToPack (itemOfInterest.worlditem)) {
creature.CurrentThought.Vote = ItemOfInterestReaction.FleeFromIt;
} else if (itemOfInterest.worlditem.HasAtLeastOne (creature.Props.ThreateningScripts)) {
creature.CurrentThought.Vote = ItemOfInterestReaction.FleeFromIt;

Unless the creature is familiar with the player – this is something the Tamed script is able to modify – the Timid script votes to flee. If the player is acting aggressively – standing or sprinting – it votes to flee multiple times.

And if the creature sees another creature that doesn’t belong to its pack, it votes to flee. Or if it sees a WorldItem that has a script that it finds threatening (eg, Hostile or Fire) it flees. TL;DR – it flees.

But that doesn’t mean that the eventual result will be ‘FleeFromIt’ because other WIScripts are getting in on the voting as well. If (say) I had a Starving script for creatures that hadn’t eaten in a long, long time (I don’t plan to include this but it’s something modders could add) it might vote like this:

Code: Select all
namespace Frontiers.World
public class Starving : WIScript {

public Creature creature;

public FoodStuff ThingToEat;

public void OnInitialized ( )
creature = worlditem.Get ( );
creature.OnCollectiveThoughtStart += OnCollectiveThoughtStart;


public void OnCollectiveThoughtStart ( )
FoodStuff foodStuff = null;
IItemOfInterest itemOfInterest = creature.CurrentThought.CurrentItemOfInterest;
//can we eat it?
if (itemOfInterest.IOIType == ItemOfInterestType.WorldItem && itemOfInterest.worlditem.Is (out foodStuff)) {
ThingToEat = foodStuff;
//we can eat it! vote to eat it
creature.CurrentThought.Vote = ItemOfInterestReaction.EatIt;
if (Stacks.Can.Stack (foodStuff.StackName, creature.Props.FavoriteFood.StackName)) {
//it's our favorite food! oh my god we HAVE to eat this
creature.CurrentThought.Vote = ItemOfInterestReaction.EatIt;
} else if (ThingToEat != null) {
//we don't care WHAT this new thing is, we have a thing to eat
//ignore anything that's not the thing to eat
creature.CurrentThought.Vote = ItemOfInterestReaction.IgnoreIt;
creature.CurrentThought.Vote = ItemOfInterestReaction.IgnoreIt;
creature.CurrentThought.Vote = ItemOfInterestReaction.IgnoreIt;
creature.CurrentThought.Vote = ItemOfInterestReaction.IgnoreIt;
creature.CurrentThought.Vote = ItemOfInterestReaction.IgnoreIt;



If it sees its favorite food it’ll try to eat it – and if anything else comes up while it’s still trying to eat that food, it’ll spam the votes with ‘IgnoreIt’ to keep its Timid nature from winning out. And at no point did I have to coordinate with the Timid script to make sure we don’t contradict each other – the two scripts know nothing about one another.

Read more here: 7/24/2014 – Creature AI Part 2

7/21/2013 – Map Data


I can’t wait to show off my beard in the next KS update. It has become truly absurd.

Every day is a little stream of victories, especially now that Hannah is on organizational duty full-time. (Apart from her day job.) All distractions from my life have been eliminated. It’s get up at first light and chip away until it’s dark – and it’s working.

The main quest is 1/3 playable. Locations built, characters & events scripted, the whole nine yards. I still want to tweak the hell out of it, and there’s plenty of really rough work in there – but it’s playable, dammit. Another 2/3 is ‘playable’ – not as solid, and there are some holes and shortcuts, but it’s getting there. You can go from place to place and make story stuff happen in the right order. And the final 1/3 isn’t playable but it is fully written, and many of the locations are built. The main quest is broken into three acts so that final 1/3 will probably be left out of the beta – it’s a natural stopping point. Stopping there will also make it easier to ensure that beta save files will be usable when the final game is released. (I still have bad memories from the Fallout 2 days when their patches would force me to start from scratch.) The final 1/3 is without a doubt my favorite part of the game and contains some of the biggest surprises so knowing that people will experience it after we’ve squashed all the bugs during beta playtesting helps me relax a bit.

A few days ago I finally managed to pull all the map data – splats, color overlays, region data, audio data – out of the inaccessible Resources folder and into the fully moddable external Mods/ChunkMaps folder. Hooray, fully modifiable world! I also created a couple of master PSD files that automate the slicing up and naming of map data, which again I’ll make available for modders to use. This step has ended up saving me far more time than I had expected. I was editing audio data chunk-by-chunk when needed and it was pretty laborious, but now I can edit whole regions with a single brush stroke and export them as little 64×64 pixel slices.





Coastline / Tide:


Audio Map (Above ground):


Along the way I finally figured out a way to create a usable world map without blowing right past our texture memory limit. FRONTIERS uses color overlays on our terrain and the plan has always been to use those images as map tiles. Actually, let me back up – the plan before discovering my texture memory limitations was to use the hand-drawn map for the world map, but once I realized that wasn’t feasible I decided to use the color overlays. They’re pretty detailed – 512×512 (1024×1024 in file, just in case I can find a way to free up more room for them) but there are a few problems with them. First, they don’t have a coastline, and without a coastline you can’t really tell where you are, especially when you’re zoomed in.


My first thought was to create a mask for the overlays to carve out a coastline, but texture memory was a problem here too – for the mask to look remotely acceptable it had to match the resolution of the overlay textures, so 512×512 per chunk. Even if I just used an alpha-only map that takes a big bite. The other problem is that even at 512×512 the overlay textures start to look pretty chunky when you zoom in far enough to navigate through a city or town. A detail overlay helped a bit but it was still pretty ugly. I decided to shelve the problem for a couple of months while I hammered out other things.

Then about a week ago Hannah suggested that I try to make the chunkiness work for me instead of against me. That gave me an idea. There are a couple of well-known techniques for making an image look like a painting – if you’ve played with Photoshop you’ve seen them in action – and I knew there are screen-space shaders that can do that sort of thing in real time. With an overlay like that big fat pixels don’t matter – they just get rounded off:


Just to be clear, this isn’t a one-time filter that gets applied to the texture – it’s a camera shader, so the look is preserved no matter how far you zoom in or out. This style also lets me to use the 64×64 coastline textures as a mask, since the smooth rounded edges no longer look incongruent with the sharp overlay image.


I can’t say I’m thrilled with the final look of the map – a hand-drawn version would have looked sooo much cooler – but it also doesn’t look like a smeary, unusable mess either. The last thing to work out is the label fading – as you zoom in, labels for larger locations fade out and smaller locations fade in. The code is done but it’s going to take a lot of variable tweaking to get the different fade levels feeling right. I’ll probably save that for the beta, though.

Read more here: 7/21/2013 – Map Data

7/14/2014 – Dungeon Cheat Sheet


Creating dungeons can be complex because of the above ground / below ground transitions. A lot has to go right for everything to work in game – so much that I keep forgetting what steps to take and lose valuable time noodling with the system! So I created a cheat sheet. It explains how all the pieces are organized and what steps I have to take for a dungeon to build properly. I thought some of you might find it interesting:


This won’t make a ton of sense on its own so here’s a screenshot of the hierarchy in the Unity editor:

Read more here: 7/14/2014 – Dungeon Cheat Sheet