mourning-ember / src / main / java / dev / llan / model / pieces / BaseEntity.java
BaseEntity.java
Raw
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);
  }
}