Design a Skill system with ES

Hi

In my previous posts about inventory and quest task design, pspeed introduced the idea of “ObjectActions” or so-called “Methods” which are a piece of groovy scripts that can be registered for a specific object type and I can run them by their names.

For example, I can have a fireball spell that has a “Cast” method registered to that spell. When the “Cast” method runs it will do the game logic there (i.e it will initialize necessary entities,…)

or I can have a sword item in player inventory that has an “Attack” method registered to that sword type. When it is called I am going to do the attack logic there.

Here is where I am so far.

In this post, I want to know how I can add the idea of “Skills” to this approach. I see skills as the ability to use an item.

Say I have a sword item and I can do an Attack with this sword but I can do this attack in many ways, a quick sword attack, a heavy sword attack or a jump and slash, and may more. I am calling theme melee attack skills.

I want these skills to get unlocked for the player as he gains more experience with that item. Also, I want them to get applied automatically when using an item. For example, when I do an Attack action with a sword I want it automatically decide if it should do a light attack or heavy attack, or a jump-slash,…

But not sure how should I implement this skill system. Any idea?

The way I see, each skill is an entity that is buffed to the player.

And say when I call the “Attack” method on sword item, there I can check all available skills and select one, is this right? Should I do all this inside the “Attack” method?

Do you have any suggestions?

Will appreciate any help :slightly_smiling_face:

Regards

Well… You are asking simple questions which do not have simple answers :slight_smile:

I already designed a system like this for my RPG and if you are interested I can try to write it down. But you have to be patient as it will be a low prio thing and might take some time (weeks maybe).

It will also describe some other systems as they are interconnected.

Also bear in that I built my game around a custom built ECS. I must admit it was not a good idea but I wasn’t aware of @pspeed’s ECS at that time and I also wasn’t aware that I’m building an ECS :smiley: So some parts of the design may not be immediately obvious as to why it was done like this. But I think that should be very limited if non-existent.

1 Like

Yeah, interested to know more about your approach. :slightly_smiling_face: Thanks

I was very lucky that I was knowing about Zay-ES and his other open source libraries when starting my project. :grinning:

Else I could not even imagien about making a multiplayer RPG game with JME :slightly_smiling_face:

1 Like

And I’ve enjoyed seeing my posts that you’ve ‘liked’ recently as I’d forgotten about them. Almost a shame that discourse doesn’t have youtube style public ‘playlists’ for links. We could start building a “useful ES advice” playlist from various folks’ comments.

1 Like

Yeah, I think I tried most of the DON’Ts that will end up on that list… Everything became a little easier when I started thinking of it as more of a database with specific needs rather than way to abstract away stuff related to PlayerCharacter etc…

Just be aware that my game is a turn-based tactical RPG so not all may translate well to your case

1 Like

@pspeed by the way, I am interested to know how do you see the relationship between item and skill?
Do you think of a skill just like an item that has object type and a list of scripts that can be executed or as a way (from possibly many ways) of using an item that player learns as he gains more experiance using that item?

Keeping in mind that my Outside Engine works a little different from ES.

Every component that is within the game world (player component, npc component, item component, game object component, etc.) has a stats registry. A Stat is a object that manages a stat, which could be a player skill, it could be the state of the object, or even metadata that game rules or other interactions utilize. The Stat object has within it floats min, max, and value, long for xp, int for level. It also contains a subclass for calculating the level from the xp.

So in the case of the sword we would have a stat on the sword, say AttackRequirement, and the player would have an Attack stat. When the player triggers an attack action, the attack action would check if the sword AttackRequirement is less than the players Attack stat, and of so run an attack interaction between the player and what it attacked, otherwise it would cancel the action.

The takeaway here for how it was developed is that the Stat class is a way of storing xp, level, and value in a generic way. (The value is especially useful for doing power ups that give, say extra attack, without modifying level or xp.) And can be used to store things like Skills and other metadata on game objects.

Just some food for thought.

1 Like

@tlf30 thanks for your response.
In your case, how many types of melee attacks player can do with a sword? I mean like combo, slash or slide attack with sword,… how do you handle them?

To me each of these attack types looks like a skill :thinking:
what do you think?

In the Outside Engine, the actual process would be (I will use json to represent the data, but it is just pojo internally, not json)
Client sends action:

"action": {
    "type":"attack",
    "properties": {
        "attack-type":"melee",
        "id":"543210"
    }
}

In this case, the attack-type would be the type of attack for the server to process, and the id would be the object the player is attacking.

The server then checks if the player has the action attack registered to it. If not, it discards the action. If so, it notifies all action listeners that have registered to that action (an action listener can be registered to multiple actions), that playerX has performed attack by passing both the player and the action objects to the listener. A listener then initiates the attack by creating an interaction between the player and the object. The interaction handles the attack checks, first by checking if the player is within range of the object based on the attack type. Then it will check what weapon the player has equipped and based on a stat on the weapon it determines if the weapon can be used for that type of attack. Then it will check that the player has the necessary stat level to use the weapon by using the process described in my last post. Finally, if all of the checks look good, the interaction will trigger the melee attack game rule. Different attack types have their own game rule that is a subclass of the attack game rule. The game rule calculates the damage done and applies the end result to the target of the interaction.

The separation of what pieces of the engine do what is important for abstraction in how Outside was developed.

To simplify:

  1. Client Sends Action
  2. Server receives action, and triggers the action listener(s) on the player registered to the action.
  3. Action listener creates an interaction between the player and the object being attacked.
  4. The interaction performs initial checks, decieds which game rule to run, and makes sure we can run the game rule. Then runs it.
  5. The game rule calculates what the end result is and applies it to the game.

I know it sounds like a lot of steps and complicated. But because the Outside Engine handles the actual passing of data and management of the process, it becomes very simple and easy to develop and work on.

I really only have two classes: AttackInteraction, and AttackGameRule. If I want to add a new attack type, I add a check for it in the AttackInteraction, then build a subclass of AttackGameRule to actual handle the attack.

2 Likes

I ended up putting skill as a component on an item using a SkillLevel(int level) component. Not every item going to need that, mostly combat items like weapons and spells will have it.

For example in case of a sword item, if your skill level is 1 then you can only do a slash attack if it is 2 then you can also do a slide attack and if 3 then you can also do a combo attack. I want it to be selected automatically when attacking, so I am going to put the logic in “Attack” script of sword item.

Edit:

Here are the steps in brief:

1- player would equip a weapon from his inventory
2- when player clicks on an enemy I am going to create a new entity and put an Attack(EntityId attacker, EntityId target) component on it.
3- combat system will listen to attack entities and will get active weapon that attacker holds in his hand and call “Attack” script on it and will also pass the target id as a parameter to it.
4- “Attack” script will handle attack initialization logic and based on skill level will decide how to do the attack.

Looks like I was wrong :slightly_smiling_face:

Reading more about skills in

and

Seems skill is a kind of stat (just like the attributes) and is given to the player, not an item. This makes sense. So a player can change his item or buy a new one without losing the skill.

This makes it easy because I already have a stat system in place :grinning:

So in my example with a sword, I can have a “Melee Combat” or more specifically “Sword Attack” skill on the player which is just an integer number and as he practices more he will gain more skill points.