package org.mafagafogigante.dungeon.entity.creatures;
import org.mafagafogigante.dungeon.entity.items.Item;
import org.mafagafogigante.dungeon.game.Random;
import org.mafagafogigante.dungeon.stats.CauseOfDeath;
import org.mafagafogigante.dungeon.stats.TypeOfCauseOfDeath;
import org.mafagafogigante.dungeon.util.Percentage;
import org.jetbrains.annotations.NotNull;
/**
* A simple implementation of the AttackAlgorithm interface.
*
* <p>This class has two non-final protected methods getHitRate and getCriticalChance that may be overridden in order to
* get simple and foolproof behavior modification. Reasonable defaults are provided if these methods are not
* overridden.
*/
class SimpleAttackAlgorithm implements AttackAlgorithm {
private static final Percentage DEFAULT_UNARMED_HIT_RATE = new Percentage(0.9);
private static final Percentage DEFAULT_CRITICAL_CHANCE = new Percentage(0.1);
private static boolean isEquippingWorkingWeapon(@NotNull Creature attacker) {
return attacker.hasWeapon() && !attacker.getWeapon().isBroken();
}
/**
* Retrieves the hit rate of a creature. The implementation provided by SimpleAttackAlgorithm uses a default hit rate
* if the creature is not equipping an unbroken weapon. Otherwise the hit rate of the weapon is used.
*/
Percentage getHitRate(@NotNull Creature creature) {
if (isEquippingWorkingWeapon(creature)) {
return creature.getWeapon().getWeaponComponent().getHitRate();
} else {
return DEFAULT_UNARMED_HIT_RATE;
}
}
/**
* Retrieves the critical chance of a creature. The implementation provided by SimpleAttackAlgorithm just uses a 10%
* default critical chance.
*/
Percentage getCriticalChance(@NotNull Creature creature) {
return DEFAULT_CRITICAL_CHANCE;
}
public void renderAttack(@NotNull Creature attacker, @NotNull Creature defender) {
if (Random.roll(getHitRate(attacker))) {
int damage = attacker.getAttack();
boolean attackerIsEquippingWorkingWeapon = isEquippingWorkingWeapon(attacker);
if (attackerIsEquippingWorkingWeapon) {
damage += attacker.getWeapon().getWeaponComponent().getDamage();
}
boolean isCriticalHit = Random.roll(getCriticalChance(attacker));
if (isCriticalHit) {
damage *= 2;
}
// Decrement the health of the defender.
defender.getHealth().decrementBy(damage);
AttackAlgorithmWriter.writeInflictedDamage(attacker, damage, defender, isCriticalHit);
// Respect the contract: If the defender is dead, set its cause of death.
if (defender.getHealth().isDead()) {
if (attackerIsEquippingWorkingWeapon) {
defender.setCauseOfDeath(new CauseOfDeath(TypeOfCauseOfDeath.WEAPON, attacker.getWeapon().getId()));
} else {
defender.setCauseOfDeath(CauseOfDeath.getUnarmedCauseOfDeath());
}
}
// Decrement the integrity of the weapon.
if (attackerIsEquippingWorkingWeapon) {
Item weapon = attacker.getWeapon();
weapon.decrementIntegrityByHit();
if (weapon.isBroken()) {
AttackAlgorithmWriter.writeWeaponBreak(weapon);
}
}
} else {
AttackAlgorithmWriter.writeMiss(attacker);
}
}
}