I've been developing my own idle game and I'm admittedly in way over my head. One of the growing problems I'm wrestling with is tracking unlocks for classes, skills, features, etc. The below snippet of code is updating the current hero class's tier if it's higher than reached on a previous prestige. I call this when a hero gains access to the next set of skills.
playerData just contains some ints/bools that are saved/loaded between sessions, and preserved between prestiges.
I'm looking for a better solution, that does not require more else/if statements for every hero class implemented. Is it possible to reduce this to a single if statement that works for all current and future hero classes? I keep thinking there should be something in the Warrior class that tells it to update the warriorTier in playerData, but I'm not sure how that would work. Please feel free to point me in a completely different direction if I'm just looking at this all wrong.
public void UpdateTier()
{
if (ClassName == "Warrior" & SkillTier > gameEngine.playerData.warriorTier)
{
gameEngine.playerData.warriorTier = SkillTier;
}
else if (ClassName == "Mage" & SkillTier > gameEngine.playerData.mageTier)
{
gameEngine.playerData.mageTier = SkillTier;
}
else if (ClassName == "Archer" & SkillTier > gameEngine.playerData.archerTier)
{
gameEngine.playerData.archerTier = SkillTier;
}
else if (ClassName == "Cleric" & SkillTier > gameEngine.playerData.clericTier)
{
gameEngine.playerData.clericTier = SkillTier;
}
}
CodePudding user response:
You're falling for the yanderedev code style. Please don't.
First, consider switch statemets and expressions instead of chaining infinite if elses
Second, to directly adress your problem:
have a tier interface (something like IPlayerDataTierUpdater) exposing a method taking whatever gameEngine.playerData is and update it, then implement it for each class (mage, archer, whatever).
UpdateTier() will then work with any implementation of said interface and adding new classes won't be a problem (as long as you correcly manage your inheritance)!
As a general tip, I suggest you research more about structural and behavioral design patterns; and invest some time on refactoring your codebase for similiar problems.
CodePudding user response:
There are many solutions to this, but given the simple question, I will try to keep my answer simple. By simple I mean changing as little of your current code as possible, while still keeping the code clean and easy to read.
You also didn't specify whether or not a player can have stats for multiple different player classes at once, so I will be assuming that this is the case.
First, I would look into using an enum instead of a string for the class names. It should look something like
internal enum PlayerClass
{
Warrior,
Mage,
Archer,
Cleric
...
}
Second, create a new object with all of the properties you will need to access in a class (such as the current tier). Something like
internal class PlayerClassStats
{
internal int Tier { get; set; }
internal long Exp { get; set; }
...
}
Finally, create some sort of manager that keeps track of and manages the relationship between a value of PlayerClass and an instance of PlayerClassStats. It should look something like
internal static class PlayerStatManager
{
private static Dictionary<PlayerClass, PlayerClassStats> _playerStats = new Dictionary<PlayerClass, PlayerClassStats>();
internal static PlayerClassStats GetStats(PlayerClass playerClass)
{
if(!_playerStats.ContainsKey(playerClass))
_playerStats.Add(playerClass, new PlayerClassStats());
return _playerStats[playerClass];
}
}
You could create more methods for handing the actual math that goes into updating the player's information, which in most cases would be a better practice, but for the sake of brevity, I'm not going to showcase that.
The example above can be used like so:
public class Game
{
private int _skillTier = 0;
private PlayerClass _currentClass = PlayerClass.Archer;
...
public void UpdateTier()
{
var stats = PlayerStatManager.GetStats(_currentClass);
if(_skillTier > stats.Tier)
stats.Tier = _skillTier;
}
}
Please be aware that none of this was tested. If I made a mistake, I will be happy to update it. The code is also not complete so you will have to fill in the blanks.
