Team YAG

Yet Another Game

Character Stats Stacking

Posted on September 18, 2015  in Programming

For those who have ever played a Role Playing Game (RPG) either video game or the old fashion paper and dice game you may have seen a character stats change based on many game features.  As a programmer finding some way to track all these changes to a player’s character can be difficult if not done right.  The other day I was reading on one of my favorite forums a post that was about this topic.  There were several ideas that was discussed but one of the best solutions I read was to layer your character statistics.

Before we go any further I want to describe some terms that will be used to discuss this topic.  Let’s start with a game entity which I will use to describe players and NPC or monsters.  Game entities are what make up the world and will need some way to stack character statistics.  Next is what I will call game items which are objects that can be used to enhance the game entities statistics.  These kind of items are like weapons, armor, or even potions.  Last is the character sheets which is a class that has a bunch of attributes that describe the game entities abilities.  Attributes are things like strength, dexterity, etc..

Now that we have the terminology out of the way we can start to discuss how we can program all this into a simple data object that will track all the player changes.  Most RPG have some way to either buy or find new equipment which is the main driving force of RPG games.  As a programmer we will need some way to combine all the RPG elements into a character and provide some modified version of their statistics.  Thinking about this now we need to describe some kind of basic needs and game rules about what can affect the players character sheet.

  • Weapons – This kind of item typically enhances the game entities ability to do damage to other game entities.
  • Armor – Are items that typically enhances our game entities defense rating and could be broken down into multiple objects like helmet, gloves, shoes, and shirts.
  • Potions – Could be items like a healing potion or mana potion that have a temporary affect to the game entity.
  • Jewelry – These items could magically enhance attributes.

Now programmatically we could build each item into their own class that would then modify specific attributes on the game entities.  The problem with this design is that for every object that would be added to the game this would require code for equipping and removing these items.  For a RPG game with thousands of items this could be long and very tedious and buggy.  This is considered code driven inventory which for a small game could be fine but for larger game worlds could be a nightmare to develop.

Instead we should think about driving our game by data because in the end that is all we really care about.  If we assign each game item a character sheet then when we equip the item on the game entity all we do is layer the character sheet.  The best way to layer this is to use a list which is a very solid design pattern.  Now the equip and remove process would only need to track the character sheet and add it or remove it from the list.

Some great things that can now come from this is magical weapons can now affect different attributes with no extra programming needing to be added.  Technically the code could be be now designed using 2 different classes.  These hypothetically could be called GameEntity and GameItem.  But knowing more about RPG games this would be to simplistic and not practical.  There could be many different reasons but for example maybe we would only allow the game entity to only equip on pair of boots.

This problem could be solved either by creating an interface or through inheritance.  For me I typically would solve this by blending both interface an inheritance together to make my game objects.  For example I would create a boot interface so that objects that are a boot would implement this interface but would then inherit from say the item class.

Now hypothetically we could now add code in the game entity class that would handle the equip process like:


class GameEntity
{
	private List<CharacterSheets> _sheetList;

	//...Code snipped for brevity...//
	public void EquipItem(IBoots boots)
	{
		// Check for boots that are already equipped
		if(Find(boots.type))
		{
			// Remove boots from equipment
		}
		_sheetList.Add(boots.sheet)
	}

	public void EquipItem(IWeapon weapon, Hand hand)
	{
		// Code that would equip a weapon in specified hand
	}
}

The nice thing here is now the game entity could use polymorphic methods to handle specific items and add their character sheets to the list.

The complexity though is now we will need a way to add up all these character sheets but also be efficient so that we don’t calculate the sheet every frame.  So we could create a calculate routine on the game entity that would be called when every we update the inventory and then cache the new character sheet.  This would look something like this:


	//...Code snipped for brevity see previous code example...//
	public void EquipItem(IBoots boots)
	{
		// Check for boots that are already equipped
		if(Find(boots.type))
		{
			// Remove boots from equipment
		}
		_sheetList.Add(boots.sheet)
		CalculateSheet();
	}

	private CharacterSheet _activeSheet;
	public CharacterSheet Sheet
	{
		get
		{
			return _activeSheet;
		}
	}

	public void CalculateSheet()
	{
		CharacterSheet lclSheet = new CharacterSheet.Zero;
		//...Need to transfer consumables to new sheet.../
		foreach(CharacterSheet lpSheet in _sheetList)
		{
			lclSheet.Add(lpSheet);
		}
		// Transfer calculate sheet to our active sheet
		_activeSheet = lclSheet;
	}

This code now allows us to track our equipment and special items that enhances our game entities character sheet.  This now allows data to drive the character sheets instead of code which is really what an RPG is about.  As your game gets design creating a good item database will make enhancing character sheets easier and potentially open up your items to a larger variety and versatility.

Now have fun laying your data instead of fighting your code to make these kinds of changes.

, ,