- difficulty mechanics
- attack mechanics
The difficulty of the level was being determined by the number of enemies, but the enemy stats were being generated randomly. This meant that some games level 2 could be much more harder than other games. To balance this I came up with a budgeting system. Each level has a budget that is a function of the level number. The more advanced the level, the higher the budget. At the start of each level, this budget is consumed according to the stats of the randomly generated enemy. So if say the level 2 budget is 10, you could have 3 monsters with 3 stats, or 2 with 5 each. This keeps the game dynamic while keeping the levels balanced. For the in-level enemy spawns, the budget is increased each turn according to the current level. Further on the game the intra level budget increase is much high therefore more/stronger enemies spawn.
I also changed the end of level loots to a random number between one and two. Sometimes you’ll be lucky and get two, but this should not affact the game progression that much.
I also increased enemy melee damage with level and building armor too. This provides a way to decide on which buildings to protect from which enemy. Also it’s now a good idea to check an enemies damage before deciding to go in for a melee or ranged attack.
I tried playing around with the committed attack directions. This means that once the enemy is committed to an attack, they will keep the relative direction of the attack, and do the attack on that square even if it means damaging a friendly. I though this would lead to more tactical game play, by pushing enemies into tiles that will be attacked for sure the next turn, but that doesn’t happen as much I as thought it would, so I reverted the code.
An peculiar thing with Godot is that freed objects are not set to null. This lead to a subtle bug: If the player dies, and you click on an enemy to see some info about the guy that killed you the game would crash. This was happening because the player object had been freed and there was a reference in the info label to the player object. There was a null check if place, but that didn’t cover it. The current solution is the wrap that object with a weak reference, but that means changing every access of the target variable with a weak refence. Meh. What I came up with is checking the the target object is in the scene tree during the label update. The label update is done every frame, so this is potentially a performance bottleneck, but since it is only run when the enemy is selected it is an acceptable trade-off for a clean approach.