Jump to content
  • Advertisement
Sign in to follow this  
Nemox

Unity Generic RPG stats.

This topic is 1826 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

So I've got an idea of how I want to handle stats in my RPG, but I'm not sure if I can implement it this way.  I'm using C# in Unity.

 

All entities in my game have some physical properties which can be modified.  This is stuff like mass, density and the like.  Just as any other statistic, I want to be able to modify this with various (de/buffs).  For example, an object that suddenly gets heavier will have its mass buffed.

 

So every entity needs the ability to be de/buffed without having its base stat values messed with, and every stat needs a minimum and maximum value that the buffs can't exceed.

 

 

Specific types of entities such as characters have special stats like Agility or Willpower and junk.  These are straightforward enough.

 

But when it comes to things like vitals (health/energy), there's some issues.  Some characters can have vitals other characters can't.  (Like Death Knights in WoW having Runic Power, Warlocks having Demonic Fury, Mages Warlocks and Priests having Mana, etc.)

 

 

So when I'm buffing an entity, I have to check whether the entity has any of these stats to buff in the first place.  And another thing to keep in mind is other types of stats that may need altering without messing with the base value; Vector3s like center of mass and buoyancy, bools like whether or not a character can breathe or fly, etc.

 

How can I handle all these different stats in a generic manner?  Is it a lost cause?

Edited by Nemox

Share this post


Link to post
Share on other sites
Advertisement

For the buffing it sounds like you need to have at least two stats.  For example, intrinsic_mass and effective_mass.  The effective_mass is a final computed mass.  You'll need some mapping, probably an equation, to use a variety of inputs to compute the effective mass.  One of these inputs will be intrinisic_mass.  Thus, all of your intrinsic properties are retained.  Whenever you encounter an event that modifies the effective mass, simply re-run your effective_mass equation.

Edited by Cosmic314

Share this post


Link to post
Share on other sites

For the buffing it sounds like you need to have at least two stats.  For example, intrinsic_mass and effective_mass.  The effective_mass is a final computed mass.  You'll need some mapping, probably an equation, to use a variety of inputs to compute the effective mass.  One of these inputs will be intrinisic_mass.  Thus, all of your intrinsic properties are retained.  Whenever you encounter an event that modifies the effective mass, simply re-run your effective_mass equation.

 

Yeah, that's the easy part.  The hard part is when it comes to other types of variables like Vectors or Bools and searching for the proper stats to modify.

Share this post


Link to post
Share on other sites

It seems like it would be pretty straightforward to just save base values for each of the stats and keep the buffs/debuffs and the final values as separate variables. That way, you can for instance recalculate the actual max health (another variable) by adding up the base health and all health related buffs/debuffs in the base class any time the value needs to change. (same thing for vectors and bools; just add together base and extra vectors, then and/or together all the related bools to get the final value) If a unit doesn’t have a certain stat at all, just include a Boolean in the base class for say, hasMana to exclude it from any mana related calculations.

Share this post


Link to post
Share on other sites

I suppose if you truly want something dynamic, create a property list.  Whenever you want a creature to have a new ability/buff, register a property along with a callback function.  Use some sort of transaction object to load appropriate values from the creature object and then pass it to the registered function.  The function does its calculation, returns a value which you store on your effective list.  I just get a vague notion that such a system might become too expensive to execute.

 

If you know all possible stats in the game simply create a base class with default computations.  Override as necessary in derived classes.  Keep a list of bools to indicate which stats are present.  You could even skip the bools and override with a stub that does nothing.

Edited by Cosmic314

Share this post


Link to post
Share on other sites

Hmm...  Maybe what I need at this point is a way to reference stats as a list, but to override the property in subsequent classes.

 

For example:
Entities have Mass and Density stats.

Characters have those and Agility and Wisdom stats.

 

The AddBuff() function of an Entity would list { Mass, Density }.

But when called on a character (even when referring to its base Entity class), it should return { Mass, Density, Agility, Wisdom }.

 

Is there some way to do that instead?  Is that what override functions are for?

Share this post


Link to post
Share on other sites

Use a data driven approach:

 

Define a base Stat as a class with a field storing a semantic and a field storing the value type. Derive concrete Stat classes that add a value field of respective type. Define a base StatEffect as a class with a semantic field, a type field, and a duration field. Derive concrete StatEffect classes that add a value field of respective type. 

 

A StatEffect has an influence on the Stat where Stat.semantic == StatEffect.semantic and Stat.type == StatEffect.type; if no such Stat is attached then the StatEffect is to be ignored.

 

The stats of an object of interest then is a list / vector / array of Stat instances. The currently active buffs / debuffs are a list of StatEffect instances attached to the object of interest.

Share this post


Link to post
Share on other sites

Use a data driven approach:

 

Define a base Stat as a class with a field storing a semantic and a field storing the value type. Derive concrete Stat classes that add a value field of respective type. Define a base StatEffect as a class with a semantic field, a type field, and a duration field. Derive concrete StatEffect classes that add a value field of respective type. 

 

A StatEffect has an influence on the Stat where Stat.semantic == StatEffect.semantic and Stat.type == StatEffect.type; if no such Stat is attached then the StatEffect is to be ignored.

 

The stats of an object of interest then is a list / vector / array of Stat instances. The currently active buffs / debuffs are a list of StatEffect instances attached to the object of interest.

 

Ahhh, this makes a lot of sense!  I'll still have to do some reading and swish it around in my tiny brain for a bit, but this may very well be the solution I'm looking for.

Share this post


Link to post
Share on other sites

A very flexible system would be for the object or character to have a stat field that indicates the minimum, maximum, and current values of a particular stat. From there, de/buffs are something applied -- they would never change the current value, but the effective value of the state would be calculated from the stat and the sum of all de/buffs. The effective value can be cached for performance if necessary, but its likely not a real issue.

 

More generally, de/buffs fall under the category of status effects -- they're a modifier that applies to something based on the presence of something else. Status effects might include things like a character being poisoned, mute, unconscious, or berserk, in addition to simple stat de/buffs. For maximum flexibility, you don't want to limit your thinking to things like one status effect affects only one stat, or status effects don't interact... For example, maybe there's something called the "Ring of Power" in your game that gives you +1 STR, maybe there are "Gauntlets of Power" that give you +2 STR, maybe there's an entire suit worth of "X of Power" armor that each give you +Y STR individually -- what if you want to give the player an additional +20 STR when they have collected and equipped the entire suit "of Power"?

 

This sort of thing builds interesting choices into your game -- is it better to buy the last piece in your suit "of Power", or is it better to get that Diamond Chestplate that has better base-stats than the Chestplate of Power, but won't give you the bonus buff? Or, what if you loot a mysterious ring from a warlocks home, equip it, and find out that it's cursed! You can't take it off, and the Warlock won't remove it for you unless you pay him 5,000 silver pieces. The penalties are interesting because not only can you not equip other useful rings, the cursed thing might prevent you from ever attaining the kind of bonus buff I described above, because you'd never be able to equip a complete suit "of Power".

 

Being flexible allows you to be more creative as a designer, and to offer the player more interesting choices that have real consequences. Notice that in the above scenario, choosing to steal the ring from the Warlock was something of a moral choice, it wasn't about simply upgrading equipment. That's interesting for the player, and the experience of being bitten by their greed will have an effect on the way they play the rest of the game. Particularly in an RPG where the game is really about choices and their effects, and with a strong emphasis on stats, equipment, and customizing the character to suit the player's playstyle, it makes a lot of sense to spend time building a very flexible system into those core game mechanics.

Share this post


Link to post
Share on other sites

I've just learned of Interfaces, and I think I'm trying to do something similar.  I'm not exactly sure what the deal is with semantic types, but I know a few basic things.

 

I've got (let's say 3) types of stats:  Floats, Vectors, and Bools.  I'll need to make a Property within the stat that gets/sets the stat's value based on type.  How does one go about implementing this?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!