Depending on the design of the game, the player may or may not have knowledge on how the level progression might look like. Regardless, the inner workings of the progression system in my view should be kept internal and all access should go through the BaseStats
(or a similar script).
Therefore, in my Progression
I added some accessors to the ProgressionCharacterClass
data that I put as internal
and only to be read from.
[Serializable]
class ProgressionCharacterClass
{
[SerializeField] private CharacterClass characterClass = CharacterClass.Grunt;
[SerializeField] private float[] health;
[SerializeField] private float[] damage;
internal CharacterClass CharacterClass { get => characterClass; }
internal float[] Damage { get => damage; }
internal float[] Health { get => health; }
}
Also, Progression.GetHealth()
is defined to be internal
, so BaseStats
(being in the same namespace) can call it, but Health
(for example) cannot.
As for the implementation of GetHealth()
, I did add some code to catch when a character class’s health
is not defined, as well as adding some mechanism to deal with levels beyond what’s defined (just returning the highest defined level’s health value).
internal float GetHealth(CharacterClass characterClass, int level)
{
foreach (ProgressionCharacterClass progressionCharacterClass in characterClasses)
{
if (progressionCharacterClass.CharacterClass == characterClass)
{
// if we ran out of progression levels then return the highest level's health...
int levelIndex = (progressionCharacterClass.Health.Length < level) ? progressionCharacterClass.Health.Length : level;
// This class has no progression values defined
if (0 == progressionCharacterClass.Health.Length) return 0;
// level counts 1..99 while the array-index starts at 0. Similar for the array's length and last index...
levelIndex--;
if (levelIndex < 0) levelIndex = 0;
return progressionCharacterClass.Health[levelIndex];
}
}
return 0; // fallback to make the compiler happy.
}