package dev.llan.model.pieces; import dev.llan.model.board.Grid; import dev.llan.model.board.Point; import dev.llan.model.board.pathfinding.GridHeuristic; import dev.llan.model.board.pathfinding.Path; import dev.llan.model.board.pathfinding.PathFinder; import dev.llan.model.cards.CardCollection; import dev.llan.model.pieces.attributes.effects.*; import dev.llan.model.pieces.attributes.modifiers.BaseModifier; import dev.llan.model.pieces.attributes.modifiers.ModifierCover; import dev.llan.model.pieces.attributes.modifiers.ModifierDecoratorCover; import dev.llan.model.pieces.attributes.stats.BaseStatsBuilder; import dev.llan.model.pieces.attributes.stats.Stats; import dev.llan.model.state.combat.TurnInfo; import java.util.ArrayList; import java.util.List; import java.util.Optional; public abstract class BaseEntity extends APiece implements Entity { protected PathFinder pathFinder; protected Optional activePath; protected Grid grid; protected Stats stats; protected CardCollection collection; protected ModifierCover modifiers; protected EffectCover effects; protected List clonedEffects; protected boolean hasAttacked; public BaseEntity( String name, String resourcePath, Point startingPos, Grid grid, BaseStatsBuilder builder) { super(name, resourcePath); this.grid = grid; this.stats = builder.build(); this.setPosition(startingPos); pathFinder = new GridHeuristic(grid); this.activePath = Optional.empty(); collection = new CardCollection(); BaseModifier baseModifier = new BaseModifier(this); modifiers = new ModifierDecoratorCover(baseModifier, this); BaseEffect baseEffect = new BaseEffect(this); effects = new EffectDecoratorCover(baseEffect, this); hasAttacked = false; } public BaseEntity( String name, String resourcePath, Point startingPos, Grid grid, Stats clonedStats) { super(name, resourcePath); this.grid = grid; this.stats = clonedStats; this.setPosition(startingPos); pathFinder = new GridHeuristic(grid); this.activePath = Optional.empty(); collection = new CardCollection(); BaseModifier baseModifier = new BaseModifier(this); modifiers = new ModifierDecoratorCover(baseModifier, this); BaseEffect baseEffect = new BaseEffect(this); effects = new EffectDecoratorCover(baseEffect, this); hasAttacked = false; } @Override public Stats getStats() { return effects.applyEffects(modifiers.applyStatsModifier(stats)); } @Override public CardCollection getCollection() { return collection; } @Override public ModifierCover getModifiers() { return modifiers; } @Override public EffectCover getEffects() { return effects; } protected void setStats(Stats newStats) { stats = newStats; } @Override public void addHealth(double delta) { double maxHealth = this.getStats().getMaxHealth(); double change = Math.max(0, delta); double ratioDelta = change / maxHealth; stats.changeHealthRatio(ratioDelta); } @Override public void reduceHealth(double delta) { double maxHealth = this.getStats().getMaxHealth(); double change = Math.max(0, delta); double ratioDelta = change / maxHealth; stats.changeHealthRatio(-ratioDelta); } @Override public void reduceMana(double delta) { double maxMana = this.getStats().getMaxMana(); double change = Math.max(0, delta); double ratioDelta = change / maxMana; stats.changeManaRatio(-ratioDelta); } @Override public boolean canMove(double movementCost) { return this.getStats().getMovement() >= movementCost; } @Override public void reduceMovement(double movement) { double maxMovement = this.getStats().getSpeed(); double change = Math.max(0, movement); double ratioDelta = change / maxMovement; this.getStats().changeMovementRatio(-ratioDelta); } @Override public Optional getActivePath() { return activePath; } @Override public List getClonedEffects() { return clonedEffects; } @Override public void setHasAttacked(boolean hasAttacked) { this.hasAttacked = hasAttacked; } @Override public void onNextCombatRound() { Stats stats = this.getStats(); stats.setMovementRatio(1.0); double manaRatioDelta = stats.getManaRegen() / stats.getMaxMana(); stats.changeManaRatio(manaRatioDelta); double healthRatioDelta = stats.getHealthRegen() / stats.getMaxHealth(); stats.changeHealthRatio(healthRatioDelta); collection.updatePlayableCards(stats.getMana()); effects.onTurnEnd(); effects.decrementAllActiveDurations(); effects.removeStaleEffects(); hasAttacked = false; } @Override public TurnInfo getTurnInfo() { return new TurnInfo(this.getImage(), this.getStats().getHealth(), this.getPosition().clone()); } protected List cloneEffects() { List cloned = new ArrayList<>(); List active = effects.getAll(); for (Effect effect : active) { cloned.add(new EffectRecord(effect.getType(), effect.getDurationLeft(), effect.getTickDamage())); } return cloned; } protected Optional cloneActivePath() { if (activePath.isEmpty()) { return Optional.empty(); } Path path = activePath.get(); Path clone = path.clone(); return Optional.of(clone); } }