Hi everyone, as we had lately reworked the barbarians it was also time to rework our lovely guards a bit.
Besides the obvious issues as wandering too far off, not switching tasks accordingly or having issues with the armor requesting there are also some strong code style issues.
First of all, I set up that the job of the guard is assigned by random again.
If the guard is an archer or knight.
By setting the default to null and if null assigning a random one.
Then, I created a new abstract class which is AbstractEntityAIFight.
This class mainly got the preparing stages of fighting AI.
Being more specific, it contains armor requesting, constants, attack delay, speed, distance and putting on armor.
This allowed me to reduce the size of the AbstractEntityAIGuard class by a lot and makes it easier to browse and find issues.
That's why I did this as a first step because it will make the following refactoring easier.
One of the important parts of refactoring this code for me is to reduce the size of the methods and make access handier.
Therefore, I extracted the very big decide method to have it only decide actions and not do any specialized code.
This decreased the size significantly.
Checking for target went to the checkForTarget method:
Patrolling to patrolling:
Guarding to guarding:
and following to following:
After checking for a target, still in the decide method we would check if a target is too far away from our job to be attacked.
This is important because else our guards would wander of infinitely even though they should be guarding or following or even patrolling.
For that reason I created a bunch of methods which do this specific check:
Next up, I created a regeneration task for the guard. The guards until now regenerated their health only over the minimum threshold and would then go back to fight. Now they will retreat under the minimum and wait until at least half of it is regenerated.
Therefore, if the worker runs into this state it will walk to the building and stay there as long as the health is low and as long as he should retrieve on low health.
After that, I moved code from the specialized classes archer and knight to the general class since it was the same code in both classes.
I moved it into a method called, preAttackChecks.
Where we would check if the worker has the weapon, enough health, no better target (a target which is attacking him) or even if it has a target at all.
I also reworked the way we select the target to prioritize the right entities.
First of all, it will check if it has a last attacked entity and if that entity is within attack distance. Then if the entity can be seen or if it has been seen recently.
Afterward, it would check if there is a barbarian horde in the colony or if the colony is under attack by another player.
Then it would prioritize on entities attacking the citizens.
If none of these are true it would search the area for mobs and then order them.
Lastly, it will search the closest entity it can see.
Another issue I fixed was that workers had some funny behavior running away since they might run in the direction from which they are running away.
For that reason, I included the direction it should avoid into the calc to make sure it would not run there.
Finally, the last piece of the puzzle in terms of armor requesting.
Previously we were using weapon code to define the armor level.
This doesn't work because armor is a bit more versatile.
That's why I separated the armor grade calc.
Besides that, I took into account the armor max level when requesting.
And I fixed waypoint placement which was being overruled since it was detected equal to the world block.
https://github.com/ldtteam/minecolonies
https://github.com/ldtteam/minecolonies/pull/2860
https://github.com/ldtteam/minecolonies/pull/2858