1
\$\begingroup\$

I'm trying to create a good designed "skill system" for my game, but curious if anybody knows a good design?

Skills can Heal,Damage ofc, they can be single target,multiple(chain), AOE. Instant dmg/heal or overtime. some skills can do damage and heal together and so on.

Maybe a little bit to complex for me to start, but can anybody help me?

Update:

lets say i have a Character class, and each character ofc has hitpoints and also a method TakeDamage(float amountOfDmg,Character damage_causer);

should this TakeDamage(..) method be used inside each Skill class e.g.?:

class AnySkill
{
 public:
 void Execute()
 {
   *(somehow get the character who takes damage)*->TakeDamage(damage, *(somehow get the causer)*)
 }

 private:
 float damage;
}

Would this be a good design?

class Character
{
 public:
 void SetTarget(Character* target)
  {
    target_ = target;
  }
 void TakeDamage(float damage, Character* causer)
 {  
   hit_points_ -= damage;
 }
  void UseSkill1()
  {
    skill1->Execute(this,target);
  }

private:
 Character* target_;
 AnySkill* skill1;
 float hit_points_
}

class AnySkill
{
 public:
 void Execute(Character* causer,Character* taker)
{
  taker->TakeDamage(damage_value,causer); 
}

 private:
 float damage_value_;
 Character* target_;
}

And somewhere:

player->SetTarget(enemy);

if(skill1_key_pressed)
{
  player->UseSkill1();
}
\$\endgroup\$
3
\$\begingroup\$

I think you are looking in what's called the "Strategy pattern" in OOP. Your skill has something like the following signature(in pseudocode)

interface TargetBehaviour{
 list<targets> getTargets();
}
class TargetAOA implements TargetBehaviour{
  list<targets> getTargets(){...{
}
class TargetSingle implements TargetBehaviour{
  list<targets> getTargets(){...}
}
interface SkillEffectBehaviour...

class skill{
    TargetBehaviour targetBehaviour;
    SkillEffectBehaviour effect;
    void use(){
        list<targets> targets = targetBehaviour.getTargets();
        foreach(target in targets){
             effect.use(target);
        }
    }
}

that way you can create new skills by swapping out effects targets and whatever else you want to swap (class,graphical effect ext.) by just swapping out which class you assign to the variables.

\$\endgroup\$
  • \$\begingroup\$ heard about the pattern, but never used it. so for single target you keep the list with only one target? looks like a good way to do that \$\endgroup\$ – jeromintus May 28 '15 at 10:00
  • \$\begingroup\$ Exactly. It becomes exponentially more useful as you add more effects as well and could also be used to create new abilities at run time. \$\endgroup\$ – Thijser May 28 '15 at 10:06
  • \$\begingroup\$ But whats the difference between class TargetSingle and TargetAOE? beside the amount of items in the list? update my initial post \$\endgroup\$ – jeromintus May 29 '15 at 10:28
  • \$\begingroup\$ AOE is exactly that an area of effect. During the creation of the skill you can give it a value that determines in what area you want the effect to take place. \$\endgroup\$ – Thijser May 29 '15 at 11:02
  • \$\begingroup\$ u think its a good idea to tick these skills? for example if skills should do something overtime \$\endgroup\$ – jeromintus Jun 2 '15 at 19:30
1
\$\begingroup\$

OOP is your friend here! Many skills will have similar traits and you can categorize them so you don't have to recode every aspect of every skill.

For example, skills will all be attachable to a character. An abstract class can be used for this. This class can also include several features that all skills have, like a call to simulate the skill or the tier of the skill.

Next, are passive and active skills. That's 2 more abstract classes to derive from. Active skills will accept input and be cast while passive skills aren't cast.

Under active skills, can be damaging skills, yet another abstract class to derive from which derives from the active skills class. Damaging skills can also include an abstract variable called "DamageType" that describes the skill as lightning/fire/pineapple/whatever.

For example, Lighting Blast is a class deriving from DamageSkill which has a damage and damage type variable. Its damage is 50 and its type is Lightning. DamageSkill derives from ActiveSkill, which has an input variable. Its input to cast is "Input.One". ActiveSkill derives from Skill, which has a tier and an abstract Simulate () method. Its tier is 3 and its Simulate () method consists of checking if the ability is cooled down. If it is, check for input and if the corresponding input registers, shoot lightning that does 50 damage of Lightning type. AOE and whatnot gets simulated here just as healing would, and Simulate () is called every simulation frame on the abilities. You can also throw in a Visualize () for the skills to show cool effects independent of simulation.

Come to think of it, DamageSkill should be an interface but this is the gist of an ability system where you have the root of a tree that branches out to accommodate a vast number of leaves where your leaves are the abilities and the branches are the abstract classes/interfaces that define the shared properties of the abilities. It might actually be easier and faster (debug-wise) to copy-paste a bunch but having an OOP setup allows you to do cool things like storing all your abilities in a convenient array and in the long run, OOP can support many more abilities than hardcoding everything.

By the way, if required, you can even screw the branches and grow a leaf at the root of the tree. Sorry for the bad metaphor but this was honestly the way best I could think of to visualize OOP.

\$\endgroup\$
  • \$\begingroup\$ You may want to add UML class diagrams to better illustrate your answer! And I would use caution in using OOP with too much inheritance as it can become very hard do maintain and modify. \$\endgroup\$ – Vaillancourt May 26 '15 at 20:07
  • \$\begingroup\$ Unfortunately, I'm not the best at drawing. There are a bunch of tuts on the internet though. Here's one relevant to game dev: gamedevelopment.tutsplus.com/tutorials/…. \$\endgroup\$ – JPtheK9 May 26 '15 at 22:57
  • \$\begingroup\$ yeah I know i need OOP, but i'm still not sure how to design my skills, how the damage should be applied to a character etc. (updated my post above). \$\endgroup\$ – jeromintus May 28 '15 at 8:39
  • \$\begingroup\$ Taking damage can just be a matter of 'TakeDamage (float damage)' and the skill would call that on the character. \$\endgroup\$ – JPtheK9 May 28 '15 at 16:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.