Faction and weight class system for characters

I’d like some advice regarding how to approach implementing a system like this in UE4. I’m still relatively new to Unreal and am still getting back in the swing of coding, especially in C++, and so wanted to get opinions from more experienced, current developers. I won’t lie- asking questions also helps me think about the problem more. ANyway. here we go, and thanks/apologies to any who read all the way through:

The requirements:

I’d like to implement a faction and weight class system. Each character can belong to 1 of several different factions and 1 of 3 different weight classes.

Factions

  • affect animation (e.g. running, jumping)
  • restrict what equipment is usable
  • control base statistics (e.g. additional health)
  • provide additional abilities beyond the default (e.g. being able to wall jump, having a “mana” resource)
  • influence the character model used

Weight

  • further affects base stats
  • further restricts which equipment is usable
  • influence the character model used

How I’d like to Approach this:

Currently, I have a default character class that contains the basic, vanilla stats and functionality that all characters should have. It has health, it can run/jump/attack, has an inventory, a faction and weight etc etc. To create a new faction, I would extend this default character class to include any new, aforementioned abilities and difference to the vanilla stats and assign a faction type. Based on this new faction class, I would create 3 new blueprint that would further modify stats, as needed, assign a weight class, link the animation blueprint for the faction, and assign the character model created for that weight class/faction combo.

Thinking:

I’d ideally like to approach this by keeping base functionality in code and delegating simple things, like stats, or things related to art content, like which model to use to data blueprints. Furthermore, factions should be modular, with the ability to easily expand on and add to the current roster. Weight classes should be editable on a faction-by-faction basis in order to facilitate balancing.

Is my thinking on this right or is there a better way to approach this in Unreal? Specifically, is there a better way to implement additional character functionality, like the wall jump or “mana” resource? Is the handling of weight classes via blueprints clumsy or bulky?

you could make each faction and weight a separate class, which inherit from a base class, but that isn’t easy to balance or playtest. if you decide to move an ability from one character class to another, you would need to copy over the code and recompile, possibly adding bugs, but if everything is decided from a spreadsheet, you can just update the spreadsheet and start playing again, without any programming or recompiling, which is great if you have game designers who can’t code, but are used to working with spread sheets.


I would make a single character class that can do everything, and give that character a faction Name. then i would make a structure that holds all the variables a faction needs to be different from other factions, and make a datatable out of that structure, where you keep the data for all the different factions.

TeamID, Weight, CharacterMesh, RunSpeed, ReloadSpeed, Health, Ammo, FireDefense, IceDefense, PoisonDefense, bCanRun, bCanJump, bCanGrenade, bCanSniper, bCanWallJump, bCanHasMagic, etc…

as far as weight classes go, you could make each weight class of each faction a separate faction, giving you maximum control over the way weight affects each faction. so CrimsonLight, CrimsonMedium, and CrimsonHeavy could all be different factions, but they can use the same TeamID for friendly fire purposes.

then, making a new faction is as easy as adding 3 new rows to a spread sheet, and filling in the data.

when you spawn a character, you set their Faction name, and use that to read from the data table and initialize their variables. then you check those variables in your input handling state machine, to decide if they are allowed to do things like double jump or sprint or use magic.


using a single character class, initialized by a data table entry, gives you the ultimate mix and match modularity, where your non-technical game designers can create new factions without looking at code, and balance the game without any chance of adding bugs. they just fill out a form and pick from a buffet of choices, to find what is most fun and balanced.

Ah, interesting. That’s a really cool approach. I had eventually wanted to use structures and spreadsheets to allow for easy balancing and, most importantly, easy comparison of stats between faction/weights at a glance, so taking it a step further and putting everything in there from the start makes a lot of sense.

Would this lead to the character class eventually becoming bloated, though? Similarly, would the spreadsheet become too hard to look at once it had numerous bCanUseAttribute values and additional resource values added?

Certainly not early on, but if it had to cover the capabilities of several factions, I feel like it would slowly become a giant mess that would have to be dug through every time a new faction was added. To further clarify- a design emphasis has been placed on a faction being defined by one or multiple traits, like a wall jump or magic, for example, that are unique to the faction and shouldn’t be replicated to other factions as part of the default definitions of the faction.

That italicized bit relates to another system that’s been nagging at me: equipment that can allow character to perform extra abilities, like wall jumping etc, also. I want to ask that in a separate question, though.

As I write this, however, I’m beginning to think that because abilities can be present through a faction or through equipment, it will all need to be added to the character anyway…? I suppose this would also have the benefit of allowing abilities to be changed even between weight classes. I had wanted to consider marrying the data-driven approach you talked about with having classes be per faction, but maybe putting it all in the character and spreadsheets is the better way…?

In any case, thanks for the great answer. Special shout out to the “bCanHasMagic” variable name, haha.

will the character become bloated? i would call it feature rich.

will the spread sheet be hard to read? color code it and play with the font.

will the spread sheet become filled with bCanUseAttributes? if you want, you could combine all the ability permissions into a separate spreadsheet, then in the factions spread sheet, you would just have a single Name variable called permissions, which would reference a row in the other spreadsheet. this would compress the data, but it may make things more complicated for a designer.

to be honest, it doesn’t really matter how ugly the spreadsheet is, since when you are balancing the combat, you will never need to read everything at once, you will always be focused on fixing a specific problem, like opening the spreadsheet to increase the fire rate or reduce the max ammo. TeamID, Weight, and CharacterMesh kinda define each row, so i would put them first, followed by movement and combat statistics, which will be adjusted the most. the boolean options will probably not be adjusted as often as the integers, so they should be put last in the struct. that way, even though they take up alot of room in your spread sheet, they will usually be off the page when editing the important stuff, like combat stats.

i think a bloated stem-cell character that has the potential to become any type of character in the game, is better than a rigid tree-hierarchy of characters, which are hard coded to be a specific type. if DNA is good enough for nature, its good enough for me, even if its hard to read. the flexibility is worth it for the variety of design combinations it can produce.

imagine if your designer asks for a shape-shifter character like Shang Tsung, who can morph into other character classes at will. or imagine a special game mode, where everyone CanHasMagic. with a single bloated character, you just have to edit some data, which is easier than refactoring code.

Really, even though I brought up the size as a concern, I was already interesting in having a go at implementing something like what you suggest. Thanks again for the input! I feel like I can be a bit more confident about diving in to this, now.