I started my own implementation right from the point when Sam had introduced the Dictionary
data structures and the skeleton of BuildLookup()
and my implementation survived pretty much unscathed through the lecture, with only some minor tweaks…
private void BuildLookup()
{
// Only ever actually do it once per run...
if (null != lookupTable) return;
lookupTable = new Dictionary<CharacterClass, Dictionary<Stats, float[]>>();
foreach (ProgressionCharacterClass progressionCharacterClass in characterClasses)
{
Dictionary<Stats, float[]> statLookupTable = new Dictionary<Stats, float[]>();
foreach (ProgressionStat progressionStat in progressionCharacterClass.stats)
{
statLookupTable.Add(progressionStat.stat, progressionStat.levels);
}
lookupTable.Add(progressionCharacterClass.characterClass, statLookupTable);
}
// DebugLookup();
}
private void DebugLookup()
{
Debug.Log($"{lookupTable}\nlookupTable has {lookupTable.Count} entries");
foreach (KeyValuePair<CharacterClass, Dictionary<Stats, float[]>> item in lookupTable)
{
// Debug.Log($"item '{item}' -- T '{item.GetType()}'");
foreach (KeyValuePair<Stats, float[]> inneritem in item.Value)
{
// Debug.Log($"'{inneritem}' -- T: '{inneritem.GetType()}'");
foreach (float level in inneritem.Value)
{
Debug.Log($"{item.Key}<{inneritem.Key}>[{level}]");
}
}
}
}
So, instead of assigning the entries with an array syntax I used Add()
instead (more like a list).
Also, I wrote myself some debugging output in order to check the result from populating the lookupTable
(and eventually pushed it out into a separate method DebugLookup()
…)
One of the primary issues I hit doing so was deriving the correct type for the items in the foreach()
loops. (Not going lazy there and just calling them var
).
And for the final challenge from the lecture, implementing GetStat()
using the lookupTable
:
internal float GetStat(Stats stat, CharacterClass characterClass, int level)
{
BuildLookup();
if (lookupTable.TryGetValue(characterClass, out Dictionary<Stats, float[]> progressionCharacter))
{
if (progressionCharacter.TryGetValue(stat, out float[] statLevels))
{
if (0 == statLevels.Length) return 0; // the stat might be defined but the levels not filled...
// if we ran out of progression levels then return the highest level's stat value...
// int levelIndex = (statLevels.Length < level) ? statLevels.Length : level;
// See https://community.gamedev.tv/t/linq-performance/228783/2 for using Math.Min()
level = Mathf.Min(statLevels.Length, level);
// level counts 1..99 while the array-index starts at 0. Similar for the array's length and last index...
if (level > 0) return statLevels[level - 1];
}
}
return 0; // fallback to make the compiler happy.
}