Created a simple example PassiveTree and PassiveNode classes for you to look at. It doesn’t involve the timing part you will need CoRoutines for that most likely, but I hope this can help you get started. When you get more efficient you can replace some of the Lists and read from files instead, but this will get you started in understanding how it’s working.
PassiveNode.cs
//*************************
// Passive Node
//
// An individual node on the passive tree containing a description and various bonuses
//*************************
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PassiveNode
{
public enum BonusType
{
percentPhysDmg,percentMagic,percentHealth,
flatPhysDmg,flatMagic,flatHealth
};
//The name and description of this individual passive node
public string bonusName;
public string bonusDescript;
public int bonusLevel = 1;
//Each passive node may have multiple bonuses
public List<BonusType> bonusTypes = new List<BonusType>();
public List<float> bonusValues = new List<float>();
public List<float> bonusValuePerLevel = new List<float>();
//Add a new bonus to this individual passive node
public void addBonus( BonusType type, float value, float valuePerLevel )
{
bonusTypes.Add(type);
bonusValues.Add(value);
bonusValuePerLevel.Add(valuePerLevel);
}
//Simulate one level up of the passive node
public void levelUp()
{
//Level up each one of the bonuses in the passive node
for(int i=0; i< bonusValues.Count; i++)
bonusValues[i] += bonusValuePerLevel[i];
//Add one to level count
bonusLevel++;
}
}
PassiveTree.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PassiveTree
{
//List containing all passive bonuses
List<PassiveNode> PassiveNodes = new List<PassiveNode>();
//Total bonuses precalculated for battle in the calcBonuses function
float calcPhysDmg, calcMagic, calcHealth;
float calcPhysDmgPerc, calcMagicPerc, calcHealthPerc;
//Use when adding a passive node for the first time (level 1)
public void addPassiveNode( string passiveName )
{
switch( passiveName)
{
case "Brute":
{
PassiveNode statNew = new PassiveNode();
//Describe the Brute passive bonus
statNew.bonusName = "Brute";
statNew.bonusDescript = "Add 5 physical damage and +10% on top of all damage. Each level up adds 2 physical damage and 3% physical damage";
statNew.bonusLevel = 1;
//Add both the bonuses to brute
statNew.addBonus(PassiveNode.BonusType.flatPhysDmg, 5.0f, 2.0f);
statNew.addBonus(PassiveNode.BonusType.percentPhysDmg, 0.10f, .03f);
//Add the newly created stat to the current passive tree
PassiveNodes.Add(statNew);
break;
}
case "Wizard":
{
PassiveNode statNew = new PassiveNode();
//Describe the Wizard passive bonus
statNew.bonusName = "Wizard";
statNew.bonusDescript = "Add 4 magic and +8% on top of all magic. Each level up adds 2 magic and 2% magic";
statNew.bonusLevel = 1;
//Add both the bonuses to Wizard
statNew.addBonus(PassiveNode.BonusType.flatMagic, 4.0f, 2.0f);
statNew.addBonus(PassiveNode.BonusType.percentPhysDmg, 0.08f, .02f);
//Add the newly created stat to the current passive tree
PassiveNodes.Add(statNew);
break;
}
case "Constitution":
{
PassiveNode statNew = new PassiveNode();
//Describe the Wizard passive bonus
statNew.bonusName = "Constitution";
statNew.bonusDescript = "Add 8 health and +10% on top of all health. Each level up adds 3 health and 2% health";
statNew.bonusLevel = 1;
//Add both the bonuses to Wizard
statNew.addBonus(PassiveNode.BonusType.flatHealth, 8.0f, 3.0f);
statNew.addBonus(PassiveNode.BonusType.percentHealth, 0.10f, .02f);
//Add the newly created stat to the current passive tree
PassiveNodes.Add(statNew);
break;
}
}
//Recalculate the overall passive tree bonuses each time a new passive stat is added
calculateBonuses();
}
//Each time a passive stat is changed, all bonuses are recalculated and stored in this class
//for easy retrieval from the combat class when using Active Skills
public void calculateBonuses()
{
//Set all bonuses to zero for recalculation
calcHealth = calcHealthPerc = calcMagic = calcMagicPerc = calcPhysDmg = calcPhysDmgPerc = 0f;
//Look through each passive stat in the passive tree
for(int i=0; i< PassiveNodes.Count; i++)
{
//Look for each bonus in the passive stats
for(int j=0; j<PassiveNodes[i].bonusValues.Count; j++)
{
float newBonus = PassiveNodes[i].bonusValues[j];
//Find out which type of bonus it is to determine which stat is being added
switch (PassiveNodes[i].bonusTypes[j])
{
case PassiveNode.BonusType.flatHealth:
{
calcHealth += newBonus;
break;
}
case PassiveNode.BonusType.percentHealth:
{
calcHealthPerc += newBonus;
break;
}
case PassiveNode.BonusType.flatMagic:
{
calcMagic += newBonus;
break;
}
case PassiveNode.BonusType.percentMagic:
{
calcMagicPerc += newBonus;
break;
}
case PassiveNode.BonusType.flatPhysDmg:
{
calcPhysDmg += newBonus;
break;
}
case PassiveNode.BonusType.percentPhysDmg:
{
calcPhysDmgPerc += newBonus;
break;
}
}
}
}
}
//Call on to level up a passive node, probably will be replaced later as leveling up will take place from a GUI
public void levelupNode(PassiveNode node)
{
node.levelUp();
calculateBonuses();
}
}
As for adding more tiers or classifications that’s really easiest to do using enumerations, look at my example of enumerations in the passiveNode class, basically allows to create any sort of abstract classifications of objects, events, or ideas and treat them as a variable/number.