Ultimate Attributes and Stats Component

Documentation

Features

  • Custom stats and attributes - create any number of desired stats or attributes that will fit your game (eg. RPG style game: strength, vitality, damage, mana, critical, evasion).
  • Attributes affect stats - all attributes can increase stats by a defined amount (eg. each Dexterity point increases character speed by 0.1%, evasion rate by 0.2% and ranged damage by 5).
  • Spendable attribute points - award players with attribute points so they have freedom in improving their characters.
  • Attributes and stats bases - create separate attributes and stats bases for each actor using the data table. Additionally, you can determine the attributes and stats increment per level.
  • Built-in leveling system - set up custom XP amount needed to level up, the amount of gained attribute points and your custom rewards.
  • Four recalculation methods - select the one that suits your game.
  • Perks system - perks provide passive bonuses to stats and attributes. These bonuses can be disproportionate (eg. level 1 adds 30 health, level 2 adds 80 health, level 3 adds 200 health).
  • Buffs system - create any number of buffs that will affect attributes and stats (positively, negatively, mixed).
  • Effects over time system - create any number of effects that will execute special actions every few seconds (eg. health regeneration or burning which damages characters).
  • Customizable buffs and effects options - power, duration(can be permanent), stacking, ticks interval etc.
  • Remove buffs or effects on demand - you can remove specific buffs and effects or do it totally random (eg. "cleanse spell" which will randomly remove negative buff or effect).
  • Automatically recalculated - whenever an attribute or stat value is affected all related values are recalculated to reflect the new state (eg. attributes increased by level, on item equipped, on buff applied or removed etc.).
  • Premade widgets - small widget blueprints which can be used to quickly populate your character info windows, premade buffs and effects bar, tooltip widget.

Go back to homepage

Ultimate Inventory and Equipment Component

Ultimate Attributes and Stats Component

Ultimate Quests and Achievements System

Simple Notification System

Options Constructor

jRPG Template

Implementation

The system is handled by a single component (AC_USC_Stats) which can be added to any actor. It is responsible for generating and storing data.

Steps to do:
Open blueprint actor that you want to add attributes or stats.
Navigate to its Components tab.
Click the green +AddComponent button and from the dropdown list choose AC_USC_Stats.
Click on newly added AC_UIC_Stats and navigate to Details tab.
Under Setup category, you will find DefaultStatsSetName. Enter the name of set you want to assign to this actor (must be equal to one of the row names in DT_USC_DefaultActorStats data table).
To create new default attributes and stats set open DT_USC_DefaultActorStats located in Datatables folder. Add a new row, name it and set up all needed values.


Each set of stats consists of several maps of values. They all have a similar structure but are responsible for different things:
  • DefaultAttributes - all attributes that actor will use. Add there even these attributes which starting value is 0. It will be also used as actor's starting attributes.
  • AttributesPerLevel - determines what attributes will be increased on level up (Eg. if Strength=1 and Endurance=2, on level up actor's Strength attribute will be increased by 1 and Endurance attribute by 2).
  • AttributesBonusesToStats - determines how much stats are influenced by specific attribute points. Each attribute can increase stats by flat or percentage amount. (eg. Endurance attribute has 2 flat bonus points to Defence stat and 1 percentage bonus point to Health stat so for each Endurance point actor's Defence will be increased by 2 and Health by 1% of base value.
  • DefaultStats - all stats that actor will use. Add there even these stats which starting value is 0. It will be also used as actor's starting stats.
  • DefaultStats(CurrentValues) - add here all stats that need to have a separate current value such as health, mana, stamina, hunger. It will let the system know what stats current values it needs to track separately.
  • StatsPerLevel - determines what stats will be increased on level up (Eg. if Health=10 and Mana=5, on level up actor's Health stat will be increased by 10 and Mana stat by 5)
  • DefaultPerks - all perks that actor will use. Add all perks that are possible to get on that actor, if you want them to be non-active by default just set their level to 0.


Initialization

To load actor stats and attributes correctly you will need to execute the initialization process correctly. Functions that need to be called in proper order:
  • InitializeAttributesAndStats - this function will read actor default values from DT_USC_DefaultActorStats data table and scale all stats and attributes to actor's current level. It means if you want to spawn actors with different levels (ie. monsters) you will need to set their current level to the desired value (can be a random integer in range) and then call this function. Thanks to this it will adjust actors stats and attributes to the given level.
  • LoadStatsData - this function will load attributes and stats data from the file or game instance and will override default actors stats and attributes. You can change this function to read data from an external server if you need to.
  • PerformFullAttributesAndStatsRecalculation - this function will calculate all final values for attributes and stats (including all bonuses).
  • (optional)SetStatCurrentValueToMax - this function is optional and you may want to skip it if actors data is loaded from file or game instance because it will set actor stats to max. Although it has to be executed if data wasn't loaded so current values of stats like health, mana or stamina won't be equal 0 (usually characters start fully healed).
  • InitialWindowsUpdate - this function will send data from component to widgets (available attribute points, level, XP amount). I will create tooltip widget as well (for default windows provided with component). In multiplayer games, it will send data from server to client. Note: this function doesn't update attributes and stats because these are updated automatically when recalculation happens.


Important: For player characters, before you execute initialization process it is recommended to set up all references and create all required widgets (like attributes and stats windows) so the system will be able to update them automatically on actor initialization.

Whole initialization process can be found in demo Player Controller and Character blueprints. It works for both single and multiplayer games.


Creating new stats or attributes

To add new stats to your project you will need to do few simple steps:
Head to Enumerations folder and open E_USC_StatType.
Add new enum and name it (the description is optional).
Once it is added, head to Blueprints folder and open FL_USC_Stats.
Find StatTypeToText function and enter the desired name for newly created stat. It will be displayed to players.


You can add new attributes to your project in a very similar way:
Head to Enumerations folder and open E_USC_AttributeType.
Add new enum and name it (the description is optional).
Once it is added, head to Blueprints folder and open FL_USC_Stats.
Find AttributeTypeToText function and enter the desired name for newly created stat. It will be displayed to players.

Accessing and modyfing stats or attributes

To read the final value of stat use the GetStatValue function. It will as well return current value for stats like Health or Mana (or any other stat that has current value tracked). Reading the final value of an attribute can be done in the very same way, just call the GetAttributeValue function.


Stats and attributes can be affected by other systems (eg. when you equip an item it will increase certain stats and decrease them when you unequip that item). To achieve this you can use premade functions - AddStatsBonuses and RemoveStatsBonuses for stats or AddAttributesBonuses and RemoveAttributeBonuses for attributes. You just need to supply nodes with item bonuses.
Important! After using one of these functions you need to call the PerformFullAttributesAndStatsRecalculation function, it will update the final values of stats and attributes and refresh their values in widgets as well.


Current stats values can be affected by three functions:
  • SetStatCurrentValueToMax - this will set desired stat current value to its max value. Max value is the final one after all recalculations (buffs, equipment etc.). Can be used to replenish characters health to max.
  • SetNewStatCurrentValue - this will set desired stat current value to given one. Can be used to set characters health after receiving damage.
  • ModifyStatCurrentValue - this will increase the desired stat current value by given amount (or decrease if it is negative). Can be used to program persistent mechanics, like health regen.

Gain, spend and reset attribute points

To grant an actor with attribute points just call the ReceiveAttributePoints function from actor's Stats Component. Set the desired amount of points you wish to add to the actor. Received points can be spent to increase attributes Base Values. Use SpentAttributePoint function and from drop down list select attribute you wish to increase. This function is also hooked up to the "Plus" buttons in AttributeSlot widget, so pressing the buttons increases attribute value. All spent attribute points can be restored by using ResetAttributesPoints function. Once attributes are reset their Base Values will be set to default ones.

If you need to know how many available attribute points actor currently has and how many already have been spent, you can do it be accessing variables in Stats Component - AvailableAttributePoints and TotalAttributePointsSpent.


Creating new perks

To add new perks to your project you will need to do few simple steps:
Head to Enumerations folder and open E_USC_PerkType.
Add new enum and name it (the description is optional).
Once it is added, head to Datatables folder and open DT_USC_Perks.
Add as many new rows as perk has levels (ie. if perk has 5 levels you will need to create 5 rows for each level separately.)
  • DisplayName - name displayed to players.
  • Description - description displayed to players.
  • Type - defines to which perk type current perk level is associated with.
  • Level - determines perk level. Used to level up perk in the proper order (perk level 1 will become perk level 2, so plan your perk carefully).
  • PerkPointsCost - how many perk points are required to get this perk.
  • Icon - image displayed to players.
  • AttributeBonuses - what attributes should be increased or decreased by perk. Supports flat and percentage bonuses.
  • StatBonuses - what stats should be increased or decreased by perk. Supports flat and percentage bonuses.


Important: When perk is level up bonuses from the previous level will be removed.
Eg. level 1 perk adds 30 health and level 2 perk adds 80 health. When a player "unlocks" perk (generally up it from level 0 to level 1) he will be granted 30 health. Then he levels the perk up so previously given 30 health bonus will be removed and he will gain new 80 health bonus.

Receiving, spending and resetting perk points.

To grant an actor with perk points call the ReceivePerkPoints function from the actor's Stats Component. Set the desired amount of points you wish to add to the actor.

Use LevelUpPerk_SERVER event to request leveling up given perk. Server will increase its level if an actor has enough perk points. Perk level will not be increased if it is maxed already or the actor doesn't have given perk in his defaults (Default perks are added to actors in DT_USC_DefaultActorStats data table).

You can revert back perk to level 0 and restore all spent points using the ResetPerk function. Additionally, you can also use ResetAllPerks function to reset them all at once.

Recalculation methods for attributes and stats

The system provides four different stats and attributes recalculation methods. You can select which method will be used in AC_USC_Stats under Setup category.
Below you will find a short presentation for all methods using the same base and bonuses values.
base value: 100
percentage bonuses: +40%, +30%, -20%
flat bonuses: +30, +25, +45

Method A. Sum up percentage bonuses first. Then add flat bonuses.
  1. Percentage bonuses are summed up. 40% + 30% - 20% = 50%
  2. Then total percentage bonus is calculated. 50% of 100 = 50.
  3. Flat bonuses are summed up. 30 +25 + 45 = 100
  4. And everything is added together: 100 + 50 + 100 = 250

Method B. Multiply percentage bonuses first. Then add flat bonuses.
  1. Percentage bonuses aren't summed up like previously. Instead we multiply each of them by base value and add it. Each time percentage bonuses is added to base value result becomes new base value.
  • 40% of 100 = 40 | 40 + 100 = 140(new base value)
  • 30% of 140 = 42 | 42 + 140 = 182(new base value)
  • -20% of 182 = - -36,4 | -36,4 + 182 =  145,6(new base value)
     2. Then flat bonuses are summed up and added to new base value. (30+25+45) + 145,6 = 245,6

Method C. Add flat bonuses first. Then sum up percentage bonuses.
  1. This method is very similar to method A. The only difference is that we firstly add flat bonuses to base value and the result becomes a new base value. (30+25+45) + 100 = 200(new base value)
  2. Then percentage bonuses are summed up: 40% + 30% - 20% = 50%
  3. Percentage bonus is calculated. 50% of 200(new base value) = 100
  4. Finally percentage bonus is added to new base value. 200 + 100 = 300.

Method D. Add flat bonuses first. Then multiply percentage bonuses.
  1. This method is similar to method B. Difference is that we firstly add flat bonuses to the base value and the result becomes new base value (like method C). (30+25+45) + 100 = 200(new base value).
  2. Then we multiply all percentage bonuses by new base value and add the result to new base value. Also the result becomes new base value instantly.
  • 40% of 200 = 80; 80+ 200 = 280(new base value)
  • 30% of 280 = 84; 84+ 280 = 364(new base value)
  • -20% of 364 = -72,8; -72,8 + 364 = 291,2(new base value)
     3. 291,2 is the final value.


Leveling and XP

You can set up how much XP is needed to level up and how many attribute points and perk points are gained on level up in DT_USC_Level. If you wish you can extend the data table by editing S_USC_Level structure (found in Structures folder). The logic for custom level up rewards can be set up in ReceiveLevelUpReward function.


You can reward players with XP using ReceiveExperience function. When enough XP is accumulated LevelUp function will be executed and XP will be set to 0 + any remaining surplus from the previous level (eg. player is level 3 and has 1400/1500 XP, player gained 220 XP for killing a monster, leveled up and now has 120/3000 XP.).
The LevelUp function is executed automatically but you can also use it on demand to award player with level. XP will be reduced to 0 after level up.


Creating new buffs and effects

To add a new buff to the project follow few simple steps:
Head to Enumerations folder and open E_USC_BuffType.
Add new enum and name it.
Once it is added, head to Datatables folder and open DT_USC_Buffs.
Add a new row and set up desired buff data. Important: Row name must be the same as BuffType Enum.
  • Type - BuffType enum that buff is referring to.
  • DisplayName - Name displayed to players.
  • Description - Description displayed to players in the tooltip.
  • InfluenceType - How buff is perceived by the system.
  • Displayable - determines if buff should be visible in status bar widget.
  • Icon - an image of the buff in status bar widget.
  • Stackable - determines if buff should be able to accumulate stacks.
  • MaxStackAmount - how many stacks buff can accumulate. Works only if "Stackable" option is set to true.
  • RemoveStackByStack - determines if buff should be removed stack by stack, instead of all stack at once.
  • Unremovable - determines if buff should be unremovable by default removal functions.


New effects are added to the project the same way:
Head to Enumerations folder and open E_USC_EffectType.
Add new enum and name it.
Once it is added, head to Datatables folder and open DT_USC_Effects.
Add a new row and set up desired effect data. Important: Row name must be the same as EffectType Enum.
  • Type - EffectType enum that effect is referring to.
  • DisplayName - Name displayed to players.
  • Description - Description displayed to players in the tooltip.
  • InfluenceType - How effect is perceived by the system.
  • Displayable - determines if effect should be visible in status bar widget.
  • Icon - an image of the effect in status bar widget.
  • AdditionalTickWhenApplied - one additional tick will be executed instantly when an effect is applied to the actor. Useful when you want to indicate some action immediately, ie. when a character steps on fire, you want to apply burning effect, but also deal damage instantly.
  • Stackable - determines if effect should be able to accumulate stacks.
  • MaxStackAmount - how many stacks effect can accumulate. Works only if "Stackable" option is set to true.
  • Unremovable - determines if effect should be unremovable by default removal functions.

Applying buffs

You can apply buffs to actors using the ApplyBuff function. It has few inputs which help you to customize its power:
  • BuffType - what buff you want to apply to an actor.
  • StacksAmount - how many stacks will be applied with buff.
  • AffectedStats - what stats should be increased or decreased by buff. Supports flat and percentage bonuses.
  • AffectedAttributes - what attributes should be increased or decreased by buff. Supports flat and percentage bonuses.
  • Permanent - if set to permanent buff will generally become passive.
  • Duration - how long buff will last. Skip if buff is permanent.

AffectedStats and AffectedAttributes variables are used to set bonus for stats and attributes. Use negative value if you want to decrease stats. Buffs can also be used to store temporarily some data (ie. Skills Charges), they won't affect stats, but all other settings will be used as for regular buff. Stats and attributes that need to be affected can be selected through MakeMap and MakeStruct nodes. If you don't need all kind of bonuses, click on desired struct node and on its Details tab you can uncheck unnecessary options.


If the buff is stackable and the same buff is applied their stacks will be summed up. However, reapplying buff isn't the only option to add stacks. There is a special function called ChangeBuffStacksByAmount. Use it if you want to increase or decrease selected buff stacks upon request. It is useful if certain skill consumes other skill stacks.

Buffs power and reapplying

Different sources will apply different buffs, but sometimes it will also happen that they apply the same type of buff. Here are a few tips you should keep in mind designing buffs for your game:
  • when two buffs of the same type are applied, only one - stronger - will be applied (or will remain)
  • if buff is stackable, then stacks from old and new buff will be summed up, but only if a new buff is stronger
  • if buff has reached maximum stacks amount, then applying new ones will only refresh its duration
  • if buffs have the same power, but a new one has a longer duration, then the new one will be applied (basically it will extend its duration)
  • buff is considered as stronger than the one currently applied when its power is higher or if its power is equal, but its duration is longer

How is buff power calculated? It is a sum of all absolute values of buff bonuses. Stacks amount doesn't matter.

Example 1
Buff A: health +20%, duration 12s (its power is equal to 20)
Buff B: health +25%, duration 3s (its power is equal to 25)
Buff B will be applied because it is stronger, even if it will only last 3s

Example 2
Buff A: mana -40, duration 12s (its power is equal to 40)
Buff B: mana -30, duration 10s (its power is equal to 30)
Buff A  will be applied because it is stronger. In this case, the buff is negative so the more stat reduction is the stronger buff is.

Example 3
Buff A: health +20%, mana -40, duration 12s (its power is equal to 60)
Buff B: health +25%, mana -30, duration 10s (its power is equal to 55)
Buff A will be applied because it is stronger. From user perspective Buff B may be better, it has higher positive bonus and lesser stat reduction. Although the combined power of Buff A is higher.

Example 4
Buff A: health + 20%, duration 12s (power 20)
After 2 seconds you again apply Buff A, so the situation will look like this:
(currently applied) Buff A: health +20%, duration 10s (2 seconds already elapsed)(newly applied) Buff A: health +20%, duration 12s
Then fresh Buff A will be applied because it has the longer duration.

Example 5
Buff A: health +20% per stack, 5 stacks already applied, duration 12s (its power is equal to 20, even if there are 5 stacks applied)
Buff B: health +25%, non-stackable, duration 3s (its power is equal to 25)
Buff B will be applied because it is stronger. When power is calculated stacks doesn't matter and all buffs are considered as if they had one stack.

Applying effects

Effects are applied through the ApplyEffect function. It also has several inputs to customize effect power:
  • EffectType - what effect you want to apply to an actor.
  • StacksAmount - how many stacks will be applied with effect.
  • EffectPower - power of the effect that will be carried in effect structure. Useful for implementing effects functionality (ie. health regeneration may vary on effect power).
  • Permanent - if set to permanent effect will become passive activated every given amount of time (ie. Hunger Effect which will deplete 1% of character satiety every 10 seconds).
  • TicksAmount - how many times the effect will be executed.
  • TickFrequency - how long is the interval between effect ticks. (in seconds)


Each time effect tick is executed it will call OnEffectTickExecuted event. It will provide info on which effect is executed, how many stacks it has and its power. Power and other detailed info can be accessed through breaking EffectStaticData structure. Use SwitchOnEffectType flow control node to assign your custom action to all effects. From each of execution pins, you can call other events or functions.

Removing buffs and effects

Buffs can be removed in two ways.
  • You can remove single specific buff using the RemoveBuffByType function.
  • You can also remove random buff with specific influence using the RemoveRandomBuff function. If influence type won't be defined then any random buff will be removed (including neutral ones).
Both methods have two additional inputs:
  • ForceRemoveAllStacks? - if it is selected, then regardless how many stacks buff has it will always remove all of them.
  • DisregardUnremovableState? - sometimes buffs have to be removed with specific action. You make them Unremovable by default, so they won't be removed "by the way" when random buff removal function is executed. Then using specific action you can remove selected buff disregarding Unremovable state.

Effects, same as buffs, can be removed in two ways.
  • You can remove specific effect using the RemoveEffectByType function.
  • And you can remove random effect with specific influence using the RemoveRandomEffect function. If influence type won't be defined then any random buff will be removed (including neutral ones).
Using these methods you can additionally remove "Unremovable" effects by checking "DisregardUnremovableState?" option. It works the same way as in case of buffs.


Above functions let you remove buffs or effects separately, but there is also a possibility to remove random buff or effect using a single function. This may be needed to create some kind of "cleanse" effect, which removes random buff or effect as they were in the same pool. To do this use RemoveRandomBuffOrEffect function.

Saving and loading

To save actor stats data use SaveStatsData function. It has two inputs:
  • SaveName - how save file will be named, remember to use different names for different actors, unless you want to overwrite the data.
  • SaveToGameInstance - determines whether the game should be saved to the game instance or to separate save file on a device.

Data saved to the game instance will be stored only during a single game session and it will be wiped after the game is closed. Use it to temporarily store data, ie. when changing levels. Data saved to file (using standard SaveGame object) will be stored on a device even when the game was closed. It can be accessed each time the game is started to load stats data. Depending on your needs you may use a single method or mix them.

To load actor stats data use LoadStatsData function. It also has two inputs:
  • SaveName - name of the save file to load stats data from or name of map value stored in the game instance.
  • LoadFromGameInstance - determines if game should be loaded from game instance or from save file stored on a device.
To ensure smooth implementation of the saving system to your game project without overriding any of your data use BPI_USC_SaveCommunication blueprint interface, which can be found in Blueprints>Interfaces folder. Open your custom game instance blueprints, navigate to ClassSettings and on details tab you will find the option to add interface and compile blueprint. Open BP_DemoUSC_GI_Custom blueprint located in DemoData Blueprints folder and copy or recreate its functions and variables.
If you don't use the custom game instance, but you still want to use save system with game instance you can use the one which is used in demo content (or a copy of it). It has the saving system already set up.

Important: Remember that this save functionality is created primarily for single player games because of multiplayer games rather store data externally.

Event dispatchers

Whenever something important happens inside StatsComponent character will be immediately notified about it through event dispatchers. All available events can be accessed through component Details tab (category Events). You can use these events to execute specific actions like:
  • play sound and particle effects OnLevelUp
  • add specific particle systems when buffs or effects are applied and remove them when buffs or effects end
  • display special messages when stats or attributes are increased
  • update widgets when specific stat or attribute value changes
and so on.

Note: in multiplayer games, these events will be mostly called on server, so remember to create proper events and send info to client(s).

Updating widgets data

Blueprint interfaces are used to update most of the data displayed to players. It means that if you have your custom widget blueprints you can feed them with desired stats, attributes, level and XP values whenever they change. To do this implement one of the provided blueprint interfaces to your widget blueprint:
  • BPI_USC_StatUpdater - use RefreshStatData event to get stat current and final values.
  • BPI_USC_AttributeUpdater - use RefreshAttributeData event to get attribute final value and RefreshAvailableAttributePoints event to get the amount of points that can be spent to improve attributes.
  • BPI_USC_LevelUpdater - use RefreshLevelValue event to get current actor level or RefreshXPValue event to get current XP and the amount needed to level up.
  • BPI_USC_PerkUpdater - use RefreshPerkData event to get perk's current level and RefreshAvailablePerkPoints event to get the amount of free Perk Points.

Gamepad controls

To move between stats and attributes slots or buffs and effects slots you can use a gamepad. You can spend points on attributes and perks. Detailed gamepad controls setup can be seen in BP_DemoUSC_PlayerController blueprint (in GamepadControls graph) and to check functionality go to Stats Component (Gamepad Controls category).

Gamepad controls are heavily dependant on the project. Controls used in demo are made to work with specific windows. When you add your own widgets you will need to reimplement gamepad functionality to work with your windows. However, you can base on existing controls.