package org.leumasjaffe.charsheet.model; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; import org.leumasjaffe.charsheet.model.features.DDProperty; import org.leumasjaffe.charsheet.model.magic.DDSpellbook; import org.leumasjaffe.charsheet.model.observable.IntValue; import org.leumasjaffe.observer.Observable; import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.experimental.Delegate; import lombok.experimental.FieldDefaults; @Data @AllArgsConstructor @EqualsAndHashCode(callSuper=false) @FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true) public class DDCharacterClass extends Observable.Instance implements Comparable { private static final class Reference { DDClass base; public boolean equals(Object o) { return this == o || base.equals(o); } public String getName() { return base.getName(); } public int hashCode() { return base.hashCode(); } public String toString() { return base.toString(); } public Reference(final String name) { this.base = DDClass.getFromResource(name); } } IntValue level; // @NonNull List healthRolls; @Delegate @Getter(AccessLevel.NONE) Reference name; Optional spellBook; public DDCharacterClass(String name) { this.level = new IntValue(0); this.name = new Reference(name); this.spellBook = getProto().createNewSpellBook(); } public String toString() { return getName() + " " + getLevel(); } @JsonIgnore public int getSkillPoints() { return name.base.getSkillPoints(); } @JsonIgnore public int getBab() { return name.base.getBab().getBonus(level.value()); } @JsonIgnore public int getFort() { return name.base.getFort().getBonus(level.value()); } @JsonIgnore public int getRef() { return name.base.getRef().getBonus(level.value()); } @JsonIgnore public int getWill() { return name.base.getWill().getBonus(level.value()); } public boolean isClassSkill(final String skill) { return name.base.isClassSkill(skill); } @JsonIgnore public DDClass getProto() { return name.base; } @JsonIgnore public int getHighestSpellLevel() { return getHighestSpellLevel(getLevel().value()); } public int getHighestSpellLevel(int level) { // TODO: Bonus levels to spellsKnown/spellsPerDay? // TODO: Bonus spellsPerDay for high ability scores if (level == 0) { return -1; } final List list = getProto().getSpells().get().getPerDay().get(level-1); level = list.size() - 1; return list.get(level) == 0 ? level : level + 1; } @Override public int compareTo(DDCharacterClass o) { return getName().compareTo(o.getName()); } public List getFeatureBonuses(Object appliesScope) { return IntStream.rangeClosed(1, level.value()) .mapToObj(level -> name.base.getFeatures(level).stream()) .reduce(Stream.empty(), (l, r) -> Stream.concat(l, r)) .filter(p -> p.appliesTo(appliesScope)).collect(Collectors.toList()); } }