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 :)