package com.cardshifter.modapi.actions.attack; import com.cardshifter.modapi.actions.ActionAllowedCheckEvent; import com.cardshifter.modapi.actions.ActionPerformEvent; import com.cardshifter.modapi.actions.SpecificActionSystem; import com.cardshifter.modapi.base.ECSGame; import com.cardshifter.modapi.base.Entity; import com.cardshifter.modapi.base.PlayerComponent; import com.cardshifter.modapi.events.IEvent; import com.cardshifter.modapi.resources.ECSResource; import com.cardshifter.modapi.resources.ResourceRetriever; import java.util.function.BiPredicate; public class AttackDamageAccumulating extends SpecificActionSystem { private final ResourceRetriever attack; private final ResourceRetriever health; private final BiPredicate<Entity, Entity> allowCounterAttack; public AttackDamageAccumulating(ECSResource attack, ECSResource health, BiPredicate<Entity, Entity> allowCounterAttack) { super("Attack"); this.attack = ResourceRetriever.forResource(attack); this.health = ResourceRetriever.forResource(health); this.allowCounterAttack = allowCounterAttack; } @Override protected void isAllowed(ActionAllowedCheckEvent event) { if (attack.getFor(event.getEntity()) <= 0) { event.setAllowed(false); } } @Override protected void onPerform(ActionPerformEvent event) { Entity source = event.getEntity(); Entity target = event.getAction().getTargetSets().get(0).getChosenTargets().get(0); AttackEvent attackEvent = new AttackEvent(source, target); source.getGame().executeCancellableEvent(attackEvent, () -> { int attackDamage = attack.getFor(source); int defenseDamage = attack.getFor(target); int attackHealth = health.getFor(source); int defenseHealth = health.getFor(target); ECSGame game = source.getGame(); attackDamage = damage(attackEvent, attackDamage, target, source, game); boolean counterAttack = allowCounterAttack.test(source, target); if (counterAttack) { defenseDamage = damage(attackEvent, defenseDamage, source, target, game); } checkKill(target, attackDamage, defenseHealth); if (counterAttack) { checkKill(source, defenseDamage, attackHealth); } }); } private void checkKill(Entity target, int damage, int previousHealth) { if (damage >= previousHealth && !target.hasComponent(PlayerComponent.class)) { target.destroy(); } } private int damage(IEvent cause, int damage, Entity target, Entity damagedBy, ECSGame game) { if (damage <= 0) { return 0; } DamageEvent damageEvent = new DamageEvent(cause, target, damagedBy, damage); game.getEvents().executeEvent(damageEvent, e -> health.resFor(target).change(-e.getDamage())); return damageEvent.getDamage(); } }