special abilities

Started by
10 comments, last by frob 6 years, 11 months ago
When I was conceptualizing the answer for this question I had similar thinking of "building blocks" to create an ability but the question really maybe I should be asking *how* to execute it...
I think (not there yet) I need to be able to write it in both C# (the client in unity) and cloudcode (the server - which i believe makes me use javascript...ive been treating it as such anyway) just a point of reference if some of the things you guys mentioned wont work in C# and javascript.

"Can you provide more context on the tactics aspect?"

Such as what exactly...?Maybe below would cover what you were asking not sure though.

I haven't looked up the command or the valve or the nodecanvas things yet, been dealing with the networking basics atm - but wanted to reply for the time being.
So far I was/am thinking something like this:
Every special ability will have a damage, type, delay, range, and a special effect - possibly as a list of strings. - this will probably cover quite a number of abilities I want.
they will all need a target because thats how it works in my head right now - not a design choice.
If its a pure buff/debuff i can just change the damage to 0, it will go through evasion checks regardless - which i thought was kind of cool even if it just makes my life easier.
Every special effect I need I add on to the list, for example I need to leave a debuff. I would iterate over the list and call a function via switch case (if not the delegate thing) to apply the debuff on the target.
The problem with this so far for me comes when for example the special effect needs to break the system like skip the evasion check, then I need to code in the evasion check to check the special effects for this specific effect

Anyway am I going the right way at all with this?

The other way I was thinking but no idea how to execute was something like:
the ability would iterate a bunch of "things to do" so i have a list of "things to do" functions that can grow that combines to unique abilities.
for example:
"hit stun"
-select a target
-apply a stun effect
-add self delay x

or
"aura buffs"
-apply all allies a buff
-apply self a debuff
-add self delay x

or
"sure strike"
-select a target
-hit target for x damage skipping evasion check
-add self delay x

or
"morph"
-change the type of my basic attack.
-add self delay x

etc etc

I think this is what you guys meant by "composition" but no clue how to do.
Advertisement

I think this is what you guys meant by "composition" but no clue how to do.

There are many different ways to do it.

One implementation may be to have a main object with a container for an abstract class. Then have a bunch of implementations of that abstract class that provide the functionality. So you might have a Weapon class that has the container of weapon abilities. That container may contain WeaponAbility objects, where WeaponAbility is an abstract base class. Next you would implement your various abilities underneath it: WeaponAbilityExplode, WeaponAbilityFire, WeaponAbilityPoison, WeaponAbilityIce. When someone uses the main object, perhaps Weapon.Attack(character,target), you would have a function that you would iterate through the container, for every ability in WeaponAbility call ability.Attack(character,target). A benefit is that new abilities are easily created and extended in code, but a drawback is that small changes may need to be made in several places.

Another implementation may be to have the main object with a container for bundles of data. You'll then have data bundles as described above for all the things you care about: aoe, ice bonus, fire bonus, poison bonus, life drain, stun on hit, interrupt on hit, etc. That can be implemented with a simple structure with an enumeration value plus data fields inside it. When someone uses the weapon, again perhaps with Weapon.Attack(character,target), you can have a utility function that tallies up the net effect of all the effects in the container. The utility function might have a giant switch statement based on the data's enumeration. If it is enum type WeaponAbility::Fire the code can check the character for a fire modifier; maybe a modifier of 0 is completely immune to fire, 0.5 is partial immunity, 1.0 is regular strength, and 2.0 might be for a wood-based monster. The data packet may have other details like a knockback that happens 5% of the time, or 80% stun chance. Do what you need for each ability in that utility function. It gets run for each item in the weapons container, so once for fire, once for poision, once for knockback, once for stun. A benefit is that the logic remains in a single location, with the drawback that it is difficult to extend without modifying the central code, although in a small game by an individual that usually isn't a problem.

Another implementation may be a look up table as part of your data, where there may be many rows on the table that apply to the object. The weapon's abilities are then composed of the various rows of data. You process each row similar to the method above, applying each row in turn.

There are many more ways to implement it. You might have sub-containers allowing you to create abilities that attach to sub-items, perhaps a ruby that gives fire resistance in armor and fire damage in weapons, or emeralds affecting poison, or maybe magic tokens that enable other abilities. No matter what story you tell the players, the code behind it means walking through a tree of data and processing all the elements as you go through them.

One "gotcha" is that you want to keep information about the effects and the processing of the effects as separate steps. If someone wants to look at the sword to see all the stats they should be able to see them as numbers or qualities. To that end it can be useful to have a function that calculates the total effect of all the items, and pass that over to the damage processing function. However, some game designs might not work with that, perhaps if your weapons have embedded elements you might want each to trigger separately, one embedded element may only apply to undead, another embedded element may only apply to dragons, or only apply to living creatures, or only apply to animals. That's partly why the details of how you traverse the tree and what data you store at each level will be unique to each game.

This topic is closed to new replies.

Advertisement