HeroEngine Forums
Welcome, Guest. Please login or Register for HeroCloud Account.

Author Topic: Theory of a Spec system Skill heavy food for thought  (Read 1722 times)

keeperofstars

  • General Accounts
  • *
  • Posts: 998
    • View Profile
    • StarKeeper Online
Theory of a Spec system Skill heavy food for thought
« on: May 03, 15, 12:26:15 PM »

I wanted to put together a bit of a theory of a spec system tutorial I often run into numerous people that over think yet under design the spec system. To point they end up missing it's full power and potential so I wanted to create a bit of a how to design your spec system food for thought post. This is just what i've done and what i've helped other teams realize, and what i've learned over 15 years of large scale application design, and almost 3 years + of HE experience.

Note I'll probably edit and refine it a bit after I review with a few co-horts wanted to get base guide written up as a starting point. I might break it up into smaller chunks to help edit it's flow and talking points.


We all get the immutable versus mutable data aspects. But quick level again.
http://hewiki.heroengine.com/wiki/Immutable
High level from that page.
Quote
Immutable objects

An object that is immutable shares its data with other similar objects, and cannot have its individual data changed. Examples of common immutable data in an MMO would include: Name, description, DPs. Immutable data is represented once regardless of how many objects share that representation. The result is that game objects have small memory footprints and require less bandwidth with an associated lack of flexibility in game mechanics.

    Minimal Memory Footprint
    Changes to a template apply to all objects referencing that template
    Unable to represent per object data that changes at runtime. e.g. inflexible at runtime
    Game objects are limited from a design point of view

Mutable objects

An object that is mutable can have its individual data changed. For example: Durability, enhancements, number of charges in a magic wand, etc. Mutable data is represented uniquely for each object providing the maximum amount of flexibility for game mechanics, but can lead to data bloat. Data bloat affects memory usage, database load, bandwidth between server and client and more.

    Able to represent dynamic data. e.g. flexible at runtime
    Game objects are virtually unlimited from a design point of view
    Data is unique without a common reference, global updates to all objects of some type requires a lot more code
    Large memory footprint (per object store)


So what makes for good Immutable Objects / pieces of data.
Here are a few examples that are usually common.

skill name
skill base damage
skill Effect(particle/FX,etc)
skill range
skill base resource amount (note amount not cost, will explain in a bit)
skill base resource type
skill cooldown
skill duration: used for damage over time effects
skill damage type
skill icon
skill description



etc by no means a full listing.

Now the key aspect is to think of the spec system as a building block tool with the glom factoring aspect. So almost all skills have the same mechanics, in fact if you break down your skills into their individual steps and group them up you find they all have the same set of mechanics.


1.) Effect towards player casting, ( so this is anything that does a buff, creates an effect at the players location, alters the player's status, etc)

2.) Effect around the player(Point Blank AOE stuff) so group buffs, heals etc, short range aoe damage)

3.) Effect of skill travel (if the skill is to travel what and how does it act.)

4.)Effect of skill on impact (what happens when the skill hits it target)

5.) Skill failure / end of life (if a skill fails / ends without performing it's intended goal what happens)

Each of those above components tend to have a small sub set of aspects that happen. So you build the template for those, then you just mix and match to build billions of skills without writing a bit of code.

So for example:

Lets say you have three skills that freeze/stun players. One is a melee shield bash, one is a frozen arrow, the other is an iceball projectile,

Lets quickly build the thoughts around it according to the outline.

Melee shield bash

1.) Effect towards player casting: (mana reduced, animation played, Single player hit detected)
2.) Effect around player:(none as this is single target)
3.) Effect of travel: (No Range)
4.) Effect on skill impact: (Single player stunned)
5.) Effect if failure: (Failure Animation Plays)

Frozen Arrow
1.) Effect towards player casting: (mana reduced, animation played, Single player hit detected)
2.) Effect around player:(none as this is single target)
3.) Effect of travel: (Single Target flight, Animation/Particle Effect of projectile, Distance?)
4.) Effect on skill impact: (Single player stunned)
5.) Effect if failure: (Failure Animation Plays)

IceBall
1.) Effect towards player casting: (mana reduced, animation played, Single player hit detected)
2.) Effect around player:(none as this is single target)
3.) Effect of travel: (Single Target flight, Animation/Particle Effect of projectile, Distance?)
4.) Effect on skill impact: (Single player stunned)
5.) Effect if failure: (Failure Animation Plays)

So as you see they share a ton of similarities. So you just code out for those similarities.

So we see they all need mana reduction.
So we code
mana reduction as it's own class takes in CharacterNode, and amount to reduce. returns boolean to see if it passes or fails right aka if you couldn't take the mana then report fail so your other systems know you don't have enough mana.

Now I would probably refactor this some. Meaning if you had stamina, mana, reagents, make it
resource reduction, and i would actually get even more bang and add in player health here and change it to be bi-directional

So it becomes resource modification (characternode, resourceToReduce, Amount) returns boolean


Could also use this for ammo, reagents, potions, consumables, etc If you have a skill that heals, the amount is positive you pass in if it needs to drain the resource you use a negative. Now any skill that needs to alter anything resource wise for your player is self contained into one class and can be glommed onto any skill needing to do so.

You might say well why not just make it part of the base spec? Well cause you will always have some skills that don't consume anything. A base melee, an infinite low damage auto attack, a skill that is purely flair, a skill that might just be "sense" area that doesn't consume resources. The key is flexibility and you never want to lock into having to have a component.

So now we have or resource modification class ready to be glommed when we need to do such.

Also note as a key aspect you aren't creating new fields or values to store the "Amount value" as it's stored already in the base spec under Skill Resource Amount so that keeps the data amounts down, and keeps your input in editor simple.

First question to arise is what about resource reduction gear or stats. So armor that reduces the amount of mana needed to deal with performing the action. That reduction code will be part of the resource modification class.

This would look to a player held field(s) for the modifications. Instead of calculating them all the time. What I mean is if you know you have armor that has mana cost reduction the player should probably have a field that stores that amount "manaCostReduction".

That field gets updated when armor is moved / removed. That way every action doesn't have to pool the armor, add the values up, then apply the difference, instead actions just read that value and goes from there. Cause unless the gear changes that value doesn't and in most games a players gear rarely changes in the grand scheme of things. A player might go weeks or months (with end game gear) and never need to recalc those figures.

Also those fields play a part of GUI aspects so when the player hits stats they see the percent reduction. So those fields are useful in multitude of systems and reasons.

Now next up is animation played. Well lets make a class for that

PlayAnimation (takes in node, animation name/path, etc)

this one will be a bit up to you to think about as it's really dependent on how you plan to or are doing animations. which varies a ton. Point is though you will be doing the same thing wanting the player to preform an animation, and it will always be the same setup for any call to play an animation. Just need to tell the code what one you want to play.


Next up single player hit detected value/field

Well this is branch point, could to keep number of glommed classes down become Hit Detection. Or could keep it seperate depending on what you want to do and how detailed your hit detection needs to be.
For this though we will go with Hit Detection.

Hit Detection:

 Takes type of hit detection, single player, mutliple, PointBlankAOE, Ranged AOE) others as needed this field Probably best as an enum so it shows as a drop down in spec editor. setups the scripts to know what branch / method / function to start at. No need to go down the AOE branch for single target detection.

Needs number of hits to detect. This is so you can scope AOEs to only hit lets say a max of 7 players, so they don't become too powerful. A zero here would mean Infinite and to skip hit limits / detection totals.

Range of Detection: this is so you can have a means to determine how big of an area to impact.

Now note all 3 of these fields once again are set at the base skill spec system at it's root. Now could i add these as fields to the hit class yes, and in some cases as we will see it will be good to do so, but since it's highly likely in a 95% case scenario we need all of our skills to have these fields I find it's best to put them in at the base level. Why? Cause it helps remind people and provides a way for you as the coder to remind people they need to glom on more classes. So if the skill builder which won't always be a coder, is in the editor and is setting hit detection to anything but none, then I'll have a nice editor description saying if other than none, please glom (hit Detection)

So it helps developer proof your spec system some.


As I wrote this and as part of the Effect on player there is a design point where you might and probably should add a player modification Class, this would allow you to say change color, add persistent particle effect etc. This is the first time when you will want to add the aspect of a fields to the glommed class versus the base spec. Why well there going to be a lot of times when these fields will never be needed for a skill. Meaning a simple melee skill won't need a player modification so it doesn't need the player modification class glommed onto it, thus no need to store empty data or ask the skill editing staff to deal with it.
This is sort of a step 1.1 aspect of the skill setup, you can decide if you want to make it part of the main



1.) Effect towards player casting: (mana reduced, animation played, Single player hit detected) class adding fields for it.

Or break it out separate. I break mine out because if we look down the road of steps some.

4.)Effect of skill on impact (what happens when the skill hits it target)

ends up being almost the exact same as 1.) Effect towards player Casting, just with a different target provided, and that is exactly what we will be doing. Reusing the same class but with a different target / node.

I want to also remind us about the classes of ApplyStatusEffectOwner, and ApplyStatusEffectTarget which is Has fields for duration, and two status effects.

skill status effect1: Stun, paralayze, blind, slow, knockback, knockdown, haste,
skill status effect2: stun, blind, etc.

Sometimes you will want skills to have multiple effects, like paralayze and blind, so the player can't move, or just blind but the player can move around.

I tend to put the status effects here and in an enum to prevent typo errors also gives nice drop down selection in editor. I don't tend to find need for more than 2 status effect combinations, as it's rare you would status effect someone in 3 different manners, but if so just add another field.


So now we have covered a bit of how to setup some of the base aspects lets recap with a quick progression / call stack setup. To hopefully tie all the above together.

Player skill: Shield Bash

skill name: Shield Bash
skill base damage: 25
skill Effect (FX Shield Bash)
skill range: 0
skill base resource amount: 15
skill resource type: stamina
skill cooldown: 10
skill duration: 0
skill damage type: physical
skill icon: ShieldBash
skill description: Player performs a back hand swing with shield stunning opponent.
ApplyEffectTarget: Status duration 10
ApplyEffectTarget: status effect1: Stun
ApplyEffectTarget: status effect2: <none>

We glom on the following classes to the skill
ResourceModification
PlayAnimamation
Hit Detection
ApplyStatusEffect(Enemy)

So my on Combat performed

1.) receives action ShieldBash
2.) Calls for the spec for ShieldBash which should be all cached pretty much.
3.) Calls ResourceModification's:  Method Modify Resource. We provide the targetNode IF result is True move to step 4, if false. Report back as not enough "resource"
4.) Calls PlayAnimation - once again we have all the items setup in the spec.
5.) Calls ApplyStatusEffectOwner - which fails as it's not glommed so we capture failure of call move on.
 
Quick note here: You could add check boxes / booleans in the skill base spec to say affectsTarget, and affectsOwner, if you don't want to capture the failed call, in retro spec I would probably add those into the base spec. But good point to note your spec will be needing to get refactored a few times as you build it.

5.) Calls HitDetection - will return the target(s) based on spec setup
6.) Calls ApplyStatusEffectTarget - Note this would apply to all targets if an AOE.



Now all of this is semi based around some core base skill concepts. There is lots of modifications that can and should happen to better fit your game.

For example I have for my ResourceModificationOwner and ResourceModificationTarget, Cause I want to be able to do transfers / drains, so I can drain my targets health and replenish mine. So it's a two way street to say.

I also expanded my playAnimationOwner and PlayAnimationTarget to allow me to alter the target's animation setup so when stunned i make them wobble to say.

There are a billion ways to build your system together. The key piece though is to break down the small components and then call them as needed or not.

So creating a skill you start to think what does it do.
Lets say I want to do a skill that saps speed from my opponent and gives it to me.

Well it needs to drain mana from player casting, so you glom ResourceModificationOwner(mana, - 10)
It needs to apply status effect to caster, So you glom ApplyStatusEffectOwner(haste)
it needs to target other players so you glom HitDetection (single target)
It needs to apply status effect to target, so you glom ApplyStatusEffectTarget(slow)
I don't have an animation to play cause it's an insta cast and my animator is lazy. :) lol

That's it.

I want a skill that does Point blank AOE, damage and freeze(aka paralyze)

Well
It needs to drain mana from caster, so you glom ResourceModificationOwner(mana, -20)
It needs to target other players so you glom HitDetection(AOE)
It needs to apply status effect to target(s), so you glom ApplyStatusEffectTarget(paralyze)
It needs to play animation so glom PlayAnimation(FrostRing)


You want a skill that heals the player only

it will need to heal HealthPoints from caster, so you glom ResourceModificationOwner(Health, 50)
it needs to play self Heal animation so glom PlayAnimation(SelfHeal)


Now I appologize if this is confusing in structure, was one where I needed to mainly just walk through it all and did a 99% of the whole system design roughly off what i've done but tried to keep it in-between too simple to illustrate the point and so complex people wrote it off.

Is it the best way to do things, yes and no. lol Yes in aspect of always break your design down to the root aspects cause in the end the game is a set of small blocks of code ran over and over and over. Break it down to the root blocks and only gather the bare minimal data needed in each block to perform it's duty.

No in the aspect as you saw here each user's system will need to be built a tad differently based on style of game. There are always ways to refactor a system to be much more efficient as you saw me doing some. Based on a design you might have to further break down the system into even smaller chunks than whats demonstrated.

What I hope you get out of it is the aspects of how strong the spec system is once you get the base small duty driven single task code blocks setup, you can mix and match them on the fly to make any type of skill / ability / setup you need to perform complex designs of skills. Noting that once it's done you the coder doesn't need to sit around building anything for skills anymore. You build about 10 - 20 classes and that is all the code you need to do for an unlimited amount of skills / abilities. And anyone off the street can make a skill in your game at that point. This can free you up to work on other systems while your team or those with less code knowledge if you have the luxury can build skills all day long. Add a skill fill in some common fields, add any special functions it needs, via glom, fill in a few detail fields on the glommed class and hit save. Bam new skill in 15 seconds.














 



Logged
[img]http://screencast.com/t/x7btcSSyp3h0[\img]

arrestedgames

  • General Accounts
  • *
  • Posts: 14
    • View Profile
Re: Theory of a Spec system Skill heavy food for thought
« Reply #1 on: May 25, 15, 05:32:57 PM »

bang on - this is great.  thank you!
Logged

nocake

  • General Accounts
  • *
  • Posts: 404
    • View Profile
    • BlightMMO
Re: Theory of a Spec system Skill heavy food for thought
« Reply #2 on: Aug 28, 15, 09:28:56 AM »

This is how the ability system in the hjref essentially works. Except they have a spec oracle system for combat effects and maneuvers.

This is a nice high level overview but I highly suggest looking into hjrefs maneuver and combat effects spec oracles to grasp handling complex dynamically created abilities.

Also look into their activators and how they set up the custom glom window to handle such a form.