Design pattern for RPG skills (good, bad, horrible?)

My RPG has Skills in it like “Fireball”, “Heal” etc. Until yesterday, I did a straight forward approach of every Fighter entity (i.e. enemies and heroes) having a List of Skills and every List consisting of instances of “Fireball” and so on, so if I have a hundred Fighters who have learned Fireball, I will have a hundred Fireball objects.

I realized that all those FireballSkill objects are virtually the same, except for one field, “level” so now I had the idea of only creating one “FireballSkill”, one “HealSkill”… and instead give the Fighters a class “LearnedSkill” (name pending…) which has but the field’s name, level and Skill. So if a Hero has a “LearnedSkill fireball (FireballSkill, level 3)” and does an attack with it, the LearnedSkill will tell FireballSkill to do whatever it does at level 3 via fireball.runSkill(3, targetFighter) or similar.

To me, that seems neater but I really don’t know if saving memory space outweighs the need for referencing to the “MotherSkill” with every skill use?

Does this make sense? I think this question will teach me some general understanding as well.
I won’t save on the number of objects needed (in fact it’s the old number +1 lol), but the object sizes are much smaller, LearnedSkill has 3 fields while FireballSkill has its own “evolution” inside, i.e. level 5 doesn’t only mean damage goes up by lvl*x but it can also change targeting at level 10, throw 3 fireballs at level 15 and so on.

Another idea I just had (just writing it down without thinking about it, I need to leave), maybe let everyone have their own FireballSkill, but have all FireballSkills reference the same FireballEvolutionRoadmap? Then if a FireballSkill gets leveled up, it will get its leveling instructions from its roadmap via fireball.setLevel(3)? This still leaves me with the same number of objects but now at least they are reasonably different. The objects are still much bigger than LearnedSkills, but smaller than the old FireBallSkill. There would still be a lot of redundant code stored in those objects though, even at different skill levels, like 80% of each FireballSkill’s fields would still always stay the same.

If the differences are small but existing, I’d still want to do the more optimal way since this is primarily a learning experience.

Actually, the 3rd way doesn’t really help much about my problem since it will simply make the game from having 1000 of the same FireBallSkill to having hundreds of the same FireBallSkill (100 level 1’s, 200 level 2’s…) and this still goes against my kneejerk reaction of trying to avoid anything redundant.

If I stay with solution 1, I’ll still implement this for readability reasons though, so at least something good will come out of this, either way :smiley:

I would start by doing some reading around the composite pattern.

SwampChicken beat me to it!

Here a good link:

http://www.tutorialspoint.com/design_pattern/composite_pattern.htm

This seems to be a case for the “flyweight” pattern.

Thanks all!

SwampChicken, steveyg90,

I’m not yet versed in the vocabulary but after SC’s post I found stevey’s link as well. I understand what it does and can see use cases for it, but I don’t understand how it applies to my situation. That’s not a dig at you, I’m sure it does - I just don’t see it.

Varkas,

this seems to be a good way to reduce the number of FireBalls drastically, if I got it correctly it’s pretty close to my “LearnedSkill idea” though, with the difference being that I will end up with one each of “Fireball lvl1”, “Fireball lvl2”… instead of one “FireballSkill”, especially if I apply the Flyweight pattern to the LearnedSkills in my idea?

It also seems to be especially useful if you don’t know the amount of different flyweight objects beforehand, but in my case I do; it’d be the sum of all skills times the number of levels and I’d eventually need all of them anyway, so why generate them dynamically at all?

So I guess taking that further would be creating one of each “Fireball lvl1”, “Fireball lvl2” and then having Fighters reference those? Not yet convinced why that’s better than having one one “FireballSkill” to be referenced, which can dynamically act as the Fighter’s skill at a level which it gets from the Fighter itself?

If the skill effect is a function of the level (eg. more range, more damage), you don’t need a separate object for each skill level. You can use one Fireball skill object with a method like

public Result apply(Target target, int level);

and pass the actual skill level as parameter. The method then multiplies the base damage or the base range with the level and applies it to the target. Probably you need more parameters, specific to your project, but the example is just to should the basic idea.

Right, but isn’t that exactly why I’m trying to say?

Only that each Fighter doesn’t have

int fireBallSkillLevel;
int healSkillLevel;

but instead has an array of SkillLevel where SkillLevel holds an int level and a String SkillName to look up Fireball etc?
That way I don’t have dozens of potentially unused int skillLevel fields per Fighter.

If you just have an array of ints all the skills will be closer together in memory, which should help performance at the expense of (possibly) using a bit more memory.

I’ve had a bit of a problem to understand your mesages, I must admit. Some days I just can’t cut through text and find the meaning of it. So, sorry, if I just told you what you had figured out already.

You can move those skill variables to class, lets call it SkillSet, which is independent from the fighter class, and pass the SkillSet as parameter to the apply() method of a skill. If you do this, you can give players and monsters SkillSets and use the same code for their skills, too. This will streamline a lot of your code.

PS: Don’t worry about unused fields. They are a very minor problem. I think in most RPGs item and other stat tables consist of a lot of zero entries, since every instance only uses a few mods or skills …

No need to be sorry; I’m sure it’s my unclear way of writing (more like thinking). Yes that sounds like what I had in mind, especially since apply() takes into accounts other Fighter variables already anyway.

Re: Unused fields: I figured they’d be not much of a problem for the computer, just don’t like them from an, I guess you could say aesthetic point of view? So I’m not opposed to them in general, it’s just that I avoid them when it’s reasonably easy to do so.

ags1,

I thought about this, but having a dedicated class for SkillSet, SkillLevel, I can also use do “foreach SkillSet displaySkillName()” etc, my plan is to use this class to represent the actual skill it references for all intents and purposes, even though in reality it’s more like a looking glass showing the real Skill through a variable determined lense.

I had a hunch and indeed, methods don’t actually cause any overhead per class instance as I intuitively assumed and well, that makes things easier.

So I will stay with the old method of every fighter has its own FireballSkill object, but they only hold methods, int level and one reference to FireballBlueprint, where the single FireballBlueprint object holds all the would be duplicate variables like damage, damage type, animation info and so on.

I have a slight feeling, that you worry about the wrong things. A method pointer is like 4 or 8 bytes, and even if is was per instance and not per class, this still is very little memory.

In case of this thread, skills for an RPG, I would sauggest to care about two issues first

  • Make the system easy to understand. Just in case someone else joins the project to help you, or if you take a break and forget most of it, and need to re-learn it from the code

  • Make the system easy to expand. Usually when you start a game, you don’t have all the ideas ready yet, and often you face the problem to add new ideas later.

If you load a texture with 1000x1000 pixels, you have 4 million bytes allocated, just for this one texture. You can fit really many skill objects into 4 million bytes. So don’t worry about a few bytes for an int type field or a pointer/reference to another class. Compared to graphics and sound data, these are really minor.

Furthermore, unlike graphics which tend to be copied each frame, skills will be evaluated relatively seldom, so they are unlikely to be a bottleneck. Attacks are the most frequent skills, but compared to the millions of bytes of graphics that are copied each frame, there will probably be less than a dozen attacks be evaluted each frame, in a typical RPG. So they are neither memory critical, nor runtime critical. And in this case, the things to care for are clean design and readability of the code.

All coding tricks that you do, have a big chance to bite your backside once you were away from the project a short while.

Thanks and yeah I agree with you in general. I’m already working on this for two months and have come pretty far but at this point, I need to overhaul the entire skill system anyway, so I want something I’ll be happy with for at least a couple of months.

The setup I settled for yesterday in the end is pretty easy and fits your criteria I think, there is a skill class that everyone has multiple instances of and every skill is linked to one blueprint, of which only one exists each.

Using this I reduced the database which holds players and their heroes by 35%, I get that it probably won’t matter but to me it’s cool and I definitely learned a bunch.