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<Path> activePath;
protected Grid grid;
protected Stats stats;
protected CardCollection collection;
protected ModifierCover modifiers;
protected EffectCover effects;
protected List<EffectRecord> 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<Path> getActivePath() {
return activePath;
}
@Override
public List<EffectRecord> 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<EffectRecord> cloneEffects() {
List<EffectRecord> cloned = new ArrayList<>();
List<Effect> active = effects.getAll();
for (Effect effect : active) {
cloned.add(new EffectRecord(effect.getType(), effect.getDurationLeft(), effect.getTickDamage()));
}
return cloned;
}
protected Optional<Path> cloneActivePath() {
if (activePath.isEmpty()) {
return Optional.empty();
}
Path path = activePath.get();
Path clone = path.clone();
return Optional.of(clone);
}
}