Design/Data Structures

What would be a good way to code up a character class?

Right now I have this:

Entity
Character Extends Entity
Dwarf, Elf and Human all Extend Entity.

This works pretty well. But each race can have skills (some different)
Each race can also have different classes and different classes can have different skills.

Right now I have Classes and Skills as their own classes/objects and add them to race.
Inside Character I have an “array” of skills and classes. It’s kind of muddled though because classes can add skills.

Is there a better way to design this?

A small example:

Dwarf has Defend skills.
Elf has no skills.

Fighter has Attack and Defend skill.
Mage has no skill.

A dwarf fighter would have Attack and 2+Defend.
Mage Elf would have none
Fighter Elf would have Attack and Defend.

Right now all this info is spread all over the place.

I can’t extend the Classes ontop of Race cause each race could be any class.

The way I usually approach this problem is by adding a separate class(or interface) for Race information and another for CharacterClass then these can be member variables for the Entity rather than having to extend the Entity class.

Yeah, I typically will only use subclasses for the more abstract type of object: Entity, DrawnEntity, FriendlyEntity, MonsterEntity, etc. Stuff like that. Then you use data members to decide any specific functionality that is different across each.

Instead of making a different class for every single skill, you’d probably be better off just making most of them individual data members of CombatEntity or something - defend, attack, etc. sound pretty general. The sorts of things you would use subclasses for would be very specific functionality that needs its own way of executing.

I suspect this is a bad approach. It’ll lead you down the old-school approach of a massive inheritance hierarchy for your characters with all the usual problems that brings (some of which you’re already finding with the classes/races setup). In particular it’s nice to be able to swap the race/class at runtime - the classic example being “polymorph self”, where your character becomes a different race/animal for a limited period. That’s easy if the race is a sub-object or data-driven, but very hard if your Character is actually a DwaftCharacter object and you want to change it into a WolfCharacter.

Ascii dreams has this rather interesting approach:

[quote]I suspect that the vast majority of games would be satisfied with five core data structures: player, enemies, playing field, pick-ups and effects. You may even be able to collapse e.g. player and enemy together.
[/quote]
This is exactly what I’m doing for Albion and it’s working quite well so far. I have a single Character class which represents both player characters and monsters (and later, NPCs). All differentiation (skills, racial traits, stats) are either data members or attached sub objects. Your Character could reference a Class and an Race, and both would contribute objects deriving from a Skill interface.

This has parallels with the component-based entity systems that are gaining popularity. You might want to search the forum for the old threads we’ve had on that in the past.

One thing to consider is that you get all sorts of gameplay variety for free if you do what Orangy is describing. If the player/allies and monsters are the same class, that means that you can very easily implement a “capture” or “charm” approach. i.e. you can add any monster or player, anytime, anywhere, to your party. If you end up with an insane class hierarchy, this is not at all easy.

Usually I make everything the same class, except I give them all an integer that determines their allegiance. Then it’s very simple to say if (myAlliegiance != theirAllegiance) {startBattle()} or something similar. That way you also get different factions of enemies fighting each other for free and a whole lot of fun in between. Make your system work for you!

In general, the only time I make a subclass is when I want to limit functionality for the sake of speed/memory or sanity. For example, I usually keep a BackgroundEntity separate from a CombatEntity, because it really doesn’t need the insane number of stats related to combat that a player and monsters need. It also doesn’t need to move, have velocity, etc. That saves me from worrying if a wall is going to start moving around for some reason, as well as adding in a lot of if (canFight) {doSomething} if (canMove) {doSomething}.

The difference between a dwarf and an elf is completely cosmetic. There is no functionality whatsoever to limit between them except for how they’re drawn and perhaps some minor behavioral or stat differences. Therefore, definitely don’t make them different classes!

I use pretty much the same set of classes for all my games, give or take one or two extra bits and bobs:


Entity
  Gidrah
  Bullet
  Player
  Obstacle

like for example I’ve got Buildings in RoTT and each general classification of building has a different class depending on its specifically unique functions. Everything else is basically attributes of those Entities.

Cas :slight_smile:

I spent 8 hours re-writing this last night.

Right now I have:

Entity
Character extends
Player extends Character

Character is just a monster or whatever, player adds player specific functions.
In Character I have a hashmap of “attribute name” and int. This stores basic things like health, xp, level, stength, etc.
Basically anything that can be an int. Works well.

Skill, Feat and Spells, etc are all objects.

Each character has a RaceID and an Array of Classes (I’m going to call them Casts to avoid confusion).

When a character is created with a certain RaceID, it’ll look up all it’s feats, skills, etc from a static final hashmap (but this could be stored in DB, XML, etc backend); it’ll find it’s info and add it. Same when cast is added. it’ll look up all it’s info in the hashmap table and add it based on cast id.

This seems to work well. The only problem is the info for Race, Cast, etc are stored in this huge ulgy static hashmap. It works nice, but doesn’t feel right. Even if I stored it in a DB, xml or cvs, etc - I’d still have to load all this data into some type of structure I could easily access. It doesn’t really and everything uses the same info… so a static final hashmap is the way to store this info? Seems a bit awkward.

One cool thing that I got working is that I can attach a method or jpython script to a feat/skills by a String. So I have feat “Knockdown” that has a string called “RuleSetObject.knockdown(self,other)”. When player uses that feat it looks up that method by string name and executes it. I’ll have to see how fast jpython is, but with this; it’ll be super easy to quickly add new functionality. Also give modders a lot of flexibility since none of the actions are hardcoded, but will be stored in db, xml, etc.

YamlBeans! :slight_smile: See sig.