/*
* Copyright 2012 (C) Tom Parker <thpr@users.sourceforge.net>
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package pcgen.core.display;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import pcgen.base.formula.Formula;
import pcgen.base.util.NamedValue;
import pcgen.cdom.base.CDOMList;
import pcgen.cdom.base.CDOMObject;
import pcgen.cdom.base.CDOMObjectUtilities;
import pcgen.cdom.base.Constants;
import pcgen.cdom.content.HitDie;
import pcgen.cdom.content.LevelCommandFactory;
import pcgen.cdom.enumeration.BiographyField;
import pcgen.cdom.enumeration.CharID;
import pcgen.cdom.enumeration.Gender;
import pcgen.cdom.enumeration.Handed;
import pcgen.cdom.enumeration.IntegerKey;
import pcgen.cdom.enumeration.ListKey;
import pcgen.cdom.enumeration.ObjectKey;
import pcgen.cdom.enumeration.PCStringKey;
import pcgen.cdom.enumeration.RaceSubType;
import pcgen.cdom.enumeration.RaceType;
import pcgen.cdom.enumeration.SkillFilter;
import pcgen.cdom.facet.ActiveSpellsFacet;
import pcgen.cdom.facet.AutoLanguageGrantedFacet;
import pcgen.cdom.facet.AutoLanguageUnconditionalFacet;
import pcgen.cdom.facet.DamageReductionFacet;
import pcgen.cdom.facet.EquipSetFacet;
import pcgen.cdom.facet.EquipmentFacet;
import pcgen.cdom.facet.EquippedEquipmentFacet;
import pcgen.cdom.facet.FacetLibrary;
import pcgen.cdom.facet.FormulaResolvingFacet;
import pcgen.cdom.facet.HitPointFacet;
import pcgen.cdom.facet.KitFacet;
import pcgen.cdom.facet.LevelInfoFacet;
import pcgen.cdom.facet.MasterFacet;
import pcgen.cdom.facet.NoteItemFacet;
import pcgen.cdom.facet.PrimaryWeaponFacet;
import pcgen.cdom.facet.SecondaryWeaponFacet;
import pcgen.cdom.facet.SkillRankFacet;
import pcgen.cdom.facet.SpellBookFacet;
import pcgen.cdom.facet.SpellListFacet;
import pcgen.cdom.facet.StartingLanguageFacet;
import pcgen.cdom.facet.StatBonusFacet;
import pcgen.cdom.facet.StatCalcFacet;
import pcgen.cdom.facet.StatValueFacet;
import pcgen.cdom.facet.SubClassFacet;
import pcgen.cdom.facet.SubstitutionClassFacet;
import pcgen.cdom.facet.XPTableFacet;
import pcgen.cdom.facet.analysis.AgeSetFacet;
import pcgen.cdom.facet.analysis.ArmorClassFacet;
import pcgen.cdom.facet.analysis.BaseMovementFacet;
import pcgen.cdom.facet.analysis.ChallengeRatingFacet;
import pcgen.cdom.facet.analysis.ChangeProfFacet;
import pcgen.cdom.facet.analysis.FavoredClassFacet;
import pcgen.cdom.facet.analysis.FollowerOptionFacet;
import pcgen.cdom.facet.analysis.HasAnyFavoredClassFacet;
import pcgen.cdom.facet.analysis.InitiativeFacet;
import pcgen.cdom.facet.analysis.LegsFacet;
import pcgen.cdom.facet.analysis.LevelFacet;
import pcgen.cdom.facet.analysis.LevelTableFacet;
import pcgen.cdom.facet.analysis.LoadFacet;
import pcgen.cdom.facet.analysis.MovementResultFacet;
import pcgen.cdom.facet.analysis.MultiClassFacet;
import pcgen.cdom.facet.analysis.NonAbilityFacet;
import pcgen.cdom.facet.analysis.NonProficiencyPenaltyFacet;
import pcgen.cdom.facet.analysis.RaceTypeFacet;
import pcgen.cdom.facet.analysis.RacialSubTypesFacet;
import pcgen.cdom.facet.analysis.SpecialAbilityFacet;
import pcgen.cdom.facet.analysis.SubRaceFacet;
import pcgen.cdom.facet.analysis.TotalWeightFacet;
import pcgen.cdom.facet.analysis.UnarmedDamageFacet;
import pcgen.cdom.facet.analysis.VisionFacet;
import pcgen.cdom.facet.fact.AgeFacet;
import pcgen.cdom.facet.fact.CharacterTypeFacet;
import pcgen.cdom.facet.fact.ChronicleEntryFacet;
import pcgen.cdom.facet.fact.FactFacet;
import pcgen.cdom.facet.fact.FollowerFacet;
import pcgen.cdom.facet.fact.GenderFacet;
import pcgen.cdom.facet.fact.HandedFacet;
import pcgen.cdom.facet.fact.HeightFacet;
import pcgen.cdom.facet.fact.PortraitThumbnailRectFacet;
import pcgen.cdom.facet.fact.PreviewSheetFacet;
import pcgen.cdom.facet.fact.RegionFacet;
import pcgen.cdom.facet.fact.SkillFilterFacet;
import pcgen.cdom.facet.fact.SuppressBioFieldFacet;
import pcgen.cdom.facet.fact.WeightFacet;
import pcgen.cdom.facet.fact.XPFacet;
import pcgen.cdom.facet.input.ProhibitedSchoolFacet;
import pcgen.cdom.facet.input.UserSpecialAbilityFacet;
import pcgen.cdom.facet.model.AlignmentFacet;
import pcgen.cdom.facet.model.ArmorProfProviderFacet;
import pcgen.cdom.facet.model.BioSetFacet;
import pcgen.cdom.facet.model.ClassFacet;
import pcgen.cdom.facet.model.DeityFacet;
import pcgen.cdom.facet.model.DomainFacet;
import pcgen.cdom.facet.model.LanguageFacet;
import pcgen.cdom.facet.model.RaceFacet;
import pcgen.cdom.facet.model.ShieldProfProviderFacet;
import pcgen.cdom.facet.model.SizeFacet;
import pcgen.cdom.facet.model.SkillFacet;
import pcgen.cdom.facet.model.StatFacet;
import pcgen.cdom.facet.model.TemplateFacet;
import pcgen.cdom.facet.model.WeaponProfModelFacet;
import pcgen.cdom.helper.ProfProvider;
import pcgen.cdom.inst.PCClassLevel;
import pcgen.cdom.reference.CDOMGroupRef;
import pcgen.core.AgeSet;
import pcgen.core.ArmorProf;
import pcgen.core.BioSet;
import pcgen.core.ChronicleEntry;
import pcgen.core.Deity;
import pcgen.core.Domain;
import pcgen.core.Equipment;
import pcgen.core.FollowerOption;
import pcgen.core.Kit;
import pcgen.core.Language;
import pcgen.core.NoteItem;
import pcgen.core.PCAlignment;
import pcgen.core.PCClass;
import pcgen.core.PCStat;
import pcgen.core.PCTemplate;
import pcgen.core.Race;
import pcgen.core.SettingsHandler;
import pcgen.core.ShieldProf;
import pcgen.core.SizeAdjustment;
import pcgen.core.Skill;
import pcgen.core.SpecialAbility;
import pcgen.core.SpellProhibitor;
import pcgen.core.SubClass;
import pcgen.core.Vision;
import pcgen.core.WeaponProf;
import pcgen.core.character.CharacterSpell;
import pcgen.core.character.EquipSet;
import pcgen.core.character.Follower;
import pcgen.core.character.SpellBook;
import pcgen.core.pclevelinfo.PCLevelInfo;
import pcgen.core.spell.Spell;
import pcgen.util.enumeration.Load;
import pcgen.util.enumeration.View;
import pcgen.util.enumeration.VisionType;
public class CharacterDisplay
{
private final CharID id;
private FactFacet factFacet = FacetLibrary.getFacet(FactFacet.class);
private LevelFacet levelFacet = FacetLibrary.getFacet(LevelFacet.class);
private RaceTypeFacet raceTypeFacet = FacetLibrary.getFacet(RaceTypeFacet.class);
private RegionFacet regionFacet = FacetLibrary.getFacet(RegionFacet.class);
private SpellBookFacet spellBookFacet = FacetLibrary.getFacet(SpellBookFacet.class);
private ChronicleEntryFacet chronicleEntryFacet = FacetLibrary.getFacet(ChronicleEntryFacet.class);
private AgeSetFacet ageSetFacet = FacetLibrary.getFacet(AgeSetFacet.class);
private ActiveSpellsFacet activeSpellsFacet = FacetLibrary.getFacet(ActiveSpellsFacet.class);
private SuppressBioFieldFacet suppressBioFieldFacet = FacetLibrary.getFacet(SuppressBioFieldFacet.class);
private TemplateFacet templateFacet = FacetLibrary.getFacet(TemplateFacet.class);
private VisionFacet visionFacet = FacetLibrary.getFacet(VisionFacet.class);
private FormulaResolvingFacet formulaResolvingFacet = FacetLibrary.getFacet(FormulaResolvingFacet.class);
private ArmorClassFacet armorClassFacet = FacetLibrary.getFacet(ArmorClassFacet.class);
private AgeFacet ageFacet = FacetLibrary.getFacet(AgeFacet.class);
private MovementResultFacet moveResultFacet = FacetLibrary.getFacet(MovementResultFacet.class);
private RaceFacet raceFacet = FacetLibrary.getFacet(RaceFacet.class);
private CharacterTypeFacet characterTypeFacet = FacetLibrary.getFacet(CharacterTypeFacet.class);
private ClassFacet classFacet = FacetLibrary.getFacet(ClassFacet.class);
private SubClassFacet subClassFacet = FacetLibrary.getFacet(SubClassFacet.class);
private FavoredClassFacet favClassFacet = FacetLibrary.getFacet(FavoredClassFacet.class);
private HasAnyFavoredClassFacet hasAnyFavoredFacet = FacetLibrary.getFacet(HasAnyFavoredClassFacet.class);
private StartingLanguageFacet startingLangFacet = FacetLibrary.getFacet(StartingLanguageFacet.class);
private ChangeProfFacet changeProfFacet = FacetLibrary.getFacet(ChangeProfFacet.class);
private BioSetFacet bioSetFacet = FacetLibrary.getFacet(BioSetFacet.class);
private BaseMovementFacet baseMovementFacet = FacetLibrary.getFacet(BaseMovementFacet.class);
private LegsFacet legsFacet = FacetLibrary.getFacet(LegsFacet.class);
private StatValueFacet statValueFacet = FacetLibrary.getFacet(StatValueFacet.class);
private SubstitutionClassFacet substitutionClassFacet = FacetLibrary.getFacet(SubstitutionClassFacet.class);
private EquippedEquipmentFacet equippedFacet = FacetLibrary.getFacet(EquippedEquipmentFacet.class);
private ArmorProfProviderFacet armorProfFacet = FacetLibrary.getFacet(ArmorProfProviderFacet.class);
private SpellListFacet spellListFacet = FacetLibrary.getFacet(SpellListFacet.class);
private HitPointFacet hitPointFacet = FacetLibrary.getFacet(HitPointFacet.class);
private FollowerFacet followerFacet = FacetLibrary.getFacet(FollowerFacet.class);
private GenderFacet genderFacet = FacetLibrary.getFacet(GenderFacet.class);
private LoadFacet loadFacet = FacetLibrary.getFacet(LoadFacet.class);
private StatFacet statFacet = FacetLibrary.getFacet(StatFacet.class);
private TotalWeightFacet totalWeightFacet = FacetLibrary.getFacet(TotalWeightFacet.class);
private MultiClassFacet multiClassFacet = FacetLibrary.getFacet(MultiClassFacet.class);
private LevelTableFacet levelTableFacet = FacetLibrary.getFacet(LevelTableFacet.class);
private DamageReductionFacet drFacet = FacetLibrary.getFacet(DamageReductionFacet.class);
private UnarmedDamageFacet unarmedDamageFacet = FacetLibrary.getFacet(UnarmedDamageFacet.class);
private StatBonusFacet statBonusFacet = FacetLibrary.getFacet(StatBonusFacet.class);
private NonAbilityFacet nonAbilityFacet = FacetLibrary.getFacet(NonAbilityFacet.class);
private LevelInfoFacet levelInfoFacet = FacetLibrary.getFacet(LevelInfoFacet.class);
private KitFacet kitFacet = FacetLibrary.getFacet(KitFacet.class);
private AutoLanguageGrantedFacet autoLangGrantedFacet = FacetLibrary.getFacet(AutoLanguageGrantedFacet.class);
private AutoLanguageUnconditionalFacet autoLangUnconditionalFacet = FacetLibrary.getFacet(AutoLanguageUnconditionalFacet.class);
private XPTableFacet xpTableFacet = FacetLibrary.getFacet(XPTableFacet.class);
private XPFacet xpFacet = FacetLibrary.getFacet(XPFacet.class);
private WeightFacet weightFacet = FacetLibrary.getFacet(WeightFacet.class);
private NoteItemFacet noteItemFacet = FacetLibrary.getFacet(NoteItemFacet.class);
private SubRaceFacet subRaceFacet = FacetLibrary.getFacet(SubRaceFacet.class);
private UserSpecialAbilityFacet userSpecialAbilityFacet = FacetLibrary.getFacet(UserSpecialAbilityFacet.class);
private SkillRankFacet skillRankFacet = FacetLibrary.getFacet(SkillRankFacet.class);
private ShieldProfProviderFacet shieldProfFacet = FacetLibrary.getFacet(ShieldProfProviderFacet.class);
private SpecialAbilityFacet specialAbilityFacet = FacetLibrary.getFacet(SpecialAbilityFacet.class);
private SecondaryWeaponFacet secondaryWeaponFacet = FacetLibrary.getFacet(SecondaryWeaponFacet.class);
private PrimaryWeaponFacet primaryWeaponFacet = FacetLibrary.getFacet(PrimaryWeaponFacet.class);
private NonProficiencyPenaltyFacet nonppFacet = FacetLibrary.getFacet(NonProficiencyPenaltyFacet.class);
private MasterFacet masterFacet = FacetLibrary.getFacet(MasterFacet.class);
private FollowerOptionFacet foFacet = FacetLibrary.getFacet(FollowerOptionFacet.class);
private HeightFacet heightFacet = FacetLibrary.getFacet(HeightFacet.class);
private StatCalcFacet statCalcFacet = FacetLibrary.getFacet(StatCalcFacet.class);
private EquipmentFacet equipmentFacet = FacetLibrary.getFacet(EquipmentFacet.class);
private EquipSetFacet equipSetFacet = FacetLibrary.getFacet(EquipSetFacet.class);
private AlignmentFacet alignmentFacet = FacetLibrary.getFacet(AlignmentFacet.class);
private SkillFacet skillFacet = FacetLibrary.getFacet(SkillFacet.class);
private DomainFacet domainFacet = FacetLibrary.getFacet(DomainFacet.class);
private ChallengeRatingFacet crFacet = FacetLibrary.getFacet(ChallengeRatingFacet.class);
private ProhibitedSchoolFacet prohibitedSchoolFacet = FacetLibrary.getFacet(ProhibitedSchoolFacet.class);
private RacialSubTypesFacet subTypesFacet = FacetLibrary.getFacet(RacialSubTypesFacet.class);
private SizeFacet sizeFacet = FacetLibrary.getFacet(SizeFacet.class);
private WeaponProfModelFacet weaponProfFacet = FacetLibrary.getFacet(WeaponProfModelFacet.class);
private LanguageFacet languageFacet = FacetLibrary.getFacet(LanguageFacet.class);
private InitiativeFacet initiativeFacet = FacetLibrary.getFacet(InitiativeFacet.class);
private HandedFacet handedFacet = FacetLibrary.getFacet(HandedFacet.class);
private DeityFacet deityFacet = FacetLibrary.getFacet(DeityFacet.class);
private PortraitThumbnailRectFacet portraitThumbnailRectFacet = FacetLibrary
.getFacet(PortraitThumbnailRectFacet.class);
private PreviewSheetFacet previewSheetFacet = FacetLibrary.getFacet(PreviewSheetFacet.class);
private SkillFilterFacet skillFilterFacet = FacetLibrary.getFacet(SkillFilterFacet.class);
public CharacterDisplay(CharID id)
{
this.id = id;
}
/**
* Gets a 'safe' String representation
*
* @param key
* @return a 'safe' String
*/
public String getSafeStringFor(PCStringKey key)
{
String s = factFacet.get(id, key);
if (s == null)
{
s = Constants.EMPTY_STRING;
}
return s;
}
/**
* Get the BIO.
*
* @return the BIO
*/
public String getBio()
{
return getSafeStringFor(PCStringKey.BIO);
}
/**
* Get the catchphrase.
*
* @return catchphrase
*/
public String getCatchPhrase()
{
return getSafeStringFor(PCStringKey.CATCHPHRASE);
}
/**
* Returns the character's handedness string.
*
* @return A String for handedness.
*/
public String getHanded()
{
return getSafeStringFor(PCStringKey.HANDED);
}
/**
* Gets a string of interests for the character.
*
* @return A String of interests or an empty string.
*/
public String getInterests()
{
return getSafeStringFor(PCStringKey.INTERESTS);
}
/**
* Gets the character's location.
*
* @return The character's location.
*/
public String getLocation()
{
return getSafeStringFor(PCStringKey.LOCATION);
}
/**
* Get speech tendency.
*
* @return speech tendency
*/
public String getSpeechTendency()
{
return getSafeStringFor(PCStringKey.SPEECHTENDENCY);
}
/**
* Get tab name.
*
* @return name on tab
*/
public String getTabName()
{
return getSafeStringFor(PCStringKey.TABNAME);
}
/**
* Get trait 1.
*
* @return trait 1
*/
public String getTrait1()
{
return getSafeStringFor(PCStringKey.PERSONALITY1);
}
/**
* Get trait 2.
*
* @return trait 2
*/
public String getTrait2()
{
return getSafeStringFor(PCStringKey.PERSONALITY2);
}
/**
* Check whether the field should be hidden from output.
* @param field The BiographyField to check export suppression rules for.
* @return true if the field should not be output, false if it may be.
*/
public boolean getSuppressBioField(BiographyField field)
{
return suppressBioFieldFacet.getSuppressField(id, field);
}
public Collection<Vision> getVisionList()
{
return visionFacet.getActiveVision(id);
}
/**
* Returns a String with the characters Race Type (e.g. Humanoid).
*
* @return The character's race type or "None"
*/
public String getRaceType()
{
RaceType rt = raceTypeFacet.getRaceType(id);
return rt == null ? Constants.NONE : rt.toString();
}
public int getTotalLevels()
{
return levelFacet.getTotalLevels(id);
}
/**
* Get the Spell Resistance granted by the given template to a character at a
* given level (Class and Hit Dice). This will include the absolute
* adjustment made with {@literal SR:, LEVEL:<num>:SR and HD:<num>:SR tags}
*
* Note: unlike DR and CR, the value returned here includes the PCs own
* Spell Resistance.
*
* @param pct
* The PCTemplate for which the Spell Resistance will be returned.
* @param level
* The level to calculate the SR for
* @param hitdice
* The Hit dice to calculate the SR for
*
* @return the Spell Resistance granted by the given Template at the given level
* and HD
*/
public int getTemplateSR(PCTemplate pct, int level, int hitdice)
{
String qualifiedKey = pct.getQualifiedKey();
Formula reduction = pct.getSafe(ObjectKey.SR).getReduction();
int aSR =
formulaResolvingFacet.resolve(id, reduction, qualifiedKey)
.intValue();
for (PCTemplate rlt : pct.getSafeListFor(ListKey.REPEATLEVEL_TEMPLATES))
{
for (PCTemplate lt : rlt.getSafeListFor(ListKey.LEVEL_TEMPLATES))
{
if (lt.get(IntegerKey.LEVEL) <= level)
{
Formula ltReduction =
lt.getSafe(ObjectKey.SR).getReduction();
int ltSR =
formulaResolvingFacet.resolve(id, ltReduction,
qualifiedKey).intValue();
aSR = Math.max(aSR, ltSR);
}
}
}
for (PCTemplate lt : pct.getSafeListFor(ListKey.LEVEL_TEMPLATES))
{
if (lt.get(IntegerKey.LEVEL) <= level)
{
Formula ltReduction = lt.getSafe(ObjectKey.SR).getReduction();
int ltSR =
formulaResolvingFacet.resolve(id, ltReduction,
qualifiedKey).intValue();
aSR = Math.max(aSR, ltSR);
}
}
for (PCTemplate lt : pct.getSafeListFor(ListKey.HD_TEMPLATES))
{
if (lt.get(IntegerKey.HD_MAX) <= hitdice
&& lt.get(IntegerKey.HD_MIN) >= hitdice)
{
Formula ltReduction = lt.getSafe(ObjectKey.SR).getReduction();
int ltSR =
formulaResolvingFacet.resolve(id, ltReduction,
qualifiedKey).intValue();
aSR = Math.max(aSR, ltSR);
}
}
return aSR;
}
/**
* Retrieve a list of the templates applied to this PC that should be
* visible on output.
*
* @return The list of templates visible on output sheets.
*/
@Deprecated
public List<PCTemplate> getOutputVisibleTemplateList()
{
return getVisibleToTemplateList(View.VISIBLE_EXPORT);
}
/**
* Retrieve a list of the templates applied to this PC that should be
* visible on display.
*
* @return The list of templates visible in the UI.
*/
public List<PCTemplate> getDisplayVisibleTemplateList()
{
return getVisibleToTemplateList(View.VISIBLE_DISPLAY);
}
private List<PCTemplate> getVisibleToTemplateList(View v)
{
List<PCTemplate> tl = new ArrayList<>();
TreeSet<PCTemplate> treeSet = new TreeSet<>(CDOMObjectUtilities.CDOM_SORTER);
for (PCTemplate template : templateFacet.getSet(id))
{
if (template.getSafe(ObjectKey.VISIBILITY).isVisibleTo(v))
{
treeSet.add(template);
}
}
tl.addAll(treeSet);
return tl;
}
/**
* Get the Character's Region
*
* @return character region
*/
public String getRegionString()
{
return regionFacet.getRegion(id);
}
/**
* Get the Character's SubRegion
*
* @return character sub region
*/
public String getSubRegion()
{
return regionFacet.getSubRegion(id);
}
public int getSpellBookCount()
{
return spellBookFacet.getCount(id);
}
/**
* Get spell books.
*
* @return spellBooks
*/
public List<String> getSpellBookNames()
{
return new ArrayList<>(spellBookFacet.getBookNames(id));
}
/**
* Retrieve a spell book object given the name of the spell book.
*
* @param name
* The name of the spell book to be retrieved.
* @return The spellbook (or null if not present).
*/
public SpellBook getSpellBookByName(final String name)
{
return spellBookFacet.getBookNamed(id, name);
}
@Deprecated
public int calcACOfType(String type)
{
return armorClassFacet.calcACOfType(id, type);
}
public int getAge()
{
return ageFacet.getAge(id);
}
public int getBaseMovement(String moveType, Load load)
{
return moveResultFacet.getBaseMovement(id, moveType, load);
}
public boolean hasMovement(String moveType)
{
return moveResultFacet.hasMovement(id, moveType);
}
public List<NamedValue> getMovementValues()
{
return moveResultFacet.getMovementValues(id);
}
public int getNumberOfMovements()
{
return moveResultFacet.countMovementTypes(id);
}
public Race getRace()
{
return raceFacet.get(id);
}
public String getCharacterType()
{
return characterTypeFacet.get(id);
}
public String getPreviewSheet()
{
return previewSheetFacet.get(id);
}
public SkillFilter getSkillFilter()
{
return skillFilterFacet.get(id);
}
/**
* Gets the Set of PCClass objects for this Character.
* @return a set of PCClass objects
*/
public Set<PCClass> getClassSet()
{
return classFacet.getSet(id);
}
public String getSubClassName(PCClass cl)
{
return subClassFacet.get(id, cl);
}
public final int getLevel(PCClass pcc)
{
return classFacet.getLevel(id, pcc);
}
@Deprecated
public SortedSet<PCClass> getFavoredClasses()
{
SortedSet<PCClass> favored = new TreeSet<>(CDOMObjectUtilities.CDOM_SORTER);
favored.addAll(favClassFacet.getSet(id));
return favored;
}
@Deprecated
public boolean hasAnyFavoredClass()
{
return hasAnyFavoredFacet.contains(id, Boolean.TRUE);
}
public Collection<Follower> getFollowerList()
{
return followerFacet.getSet(id);
}
public Gender getGenderObject()
{
return genderFacet.getGender(id);
}
/**
* Get a sorted list of the languages that this character knows.
* @return a sorted list of language objects
*/
@Deprecated
public Set<Language> getSortedLanguageSet()
{
return new TreeSet<>(languageFacet.getSet(id));
}
@Deprecated
public int processOldInitiativeMod()
{
return initiativeFacet.getInitiative(id);
}
public Handed getHandedObject()
{
return handedFacet.getHanded(id);
}
public SortedSet<WeaponProf> getSortedWeaponProfs()
{
return Collections.unmodifiableSortedSet(new TreeSet<>(weaponProfFacet.getSet(id)));
}
public String getSize()
{
return sizeFacet.getSizeAbb(id);
}
public Collection<RaceSubType> getRacialSubTypes()
{
return subTypesFacet.getRacialSubTypes(id);
}
public Collection<? extends SpellProhibitor> getProhibitedSchools(Object source)
{
return prohibitedSchoolFacet.getSet(id, source);
}
public String getPortraitPath()
{
return getSafeStringFor(PCStringKey.PORTRAIT_PATH);
}
public Rectangle getPortraitThumbnailRect()
{
Rectangle rect = portraitThumbnailRectFacet.get(id);
return rect == null ? null : (Rectangle) rect.clone();
}
public String getName()
{
return getSafeStringFor(PCStringKey.NAME);
}
public String getFileName()
{
return getSafeStringFor(PCStringKey.FILE_NAME);
}
public String getPlayersName()
{
return getSafeStringFor(PCStringKey.PLAYERSNAME);
}
public Integer calcCR()
{
return crFacet.getCR(id);
}
public Integer calcBaseCR()
{
return crFacet.calcRaceCR(id);
}
public float getBaseHD()
{
return crFacet.getBaseHD(id);
}
public int getXPAward()
{
return crFacet.getXPAward(id);
}
public int getRacialHDSize()
{
int hdSize = 0;
LevelCommandFactory lcf = getRace().get(ObjectKey.MONSTER_CLASS);
if (lcf != null)
{
hdSize = getLevelHitDie(lcf.getPCClass(), 1).getDie();
}
return hdSize;
}
public Set<Domain> getSortedDomainSet()
{
SortedSet<Domain> domains = new TreeSet<>(CDOMObjectUtilities.CDOM_SORTER);
domains.addAll(domainFacet.getSet(id));
return domains;
}
/**
* Retrieve those skills in the character's skill list that match the
* supplied visibility level.
*
* @param v What level of visibility skills are desired.
*
* @return A list of the character's skills matching the visibility
* criteria.
*/
public List<Skill> getPartialSkillList(View v)
{
// Now select the required set of skills, based on their visibility.
ArrayList<Skill> aList = new ArrayList<>();
for (Skill po : skillFacet.getSet(id))
{
if (po.getSafe(ObjectKey.VISIBILITY).isVisibleTo(v))
{
aList.add(po);
}
}
return aList;
}
/**
* Alignment of this PC.
*
* @return alignment
*/
public PCAlignment getPCAlignment()
{
return alignmentFacet.get(id);
}
/**
* Get the class list.
*
* @return classList
*/
public ArrayList<PCClass> getClassList()
{
/*
* TODO This is a discussion we have to have about where items are sorted
*/
return new ArrayList<>(getClassSet());
}
/**
* Get the current equipment set name.
*
* @return equipment set name
*/
public String getCurrentEquipSetName()
{
return getSafeStringFor(PCStringKey.CURRENT_EQUIP_SET_NAME);
}
/**
* Get the deity.
*
* @return deity
*/
public Deity getDeity()
{
return deityFacet.get(id);
}
/**
* Get the list of equipment sets.
*
* @return List
*/
public Collection<EquipSet> getEquipSet()
{
return equipSetFacet.getSet(id);
}
/**
* Get the equipment set indexed by path.
*
* @param path the "path" of the equipSet to return
* @return EquipSet
*/
public EquipSet getEquipSetByIdPath(final String path)
{
return equipSetFacet.getEquipSetByIdPath(id, path);
}
/**
* Get equipment set.
*
* @return equipment set
*/
public Set<Equipment> getEquipmentSet()
{
return equipmentFacet.getSet(id);
}
/**
* Gets the character's height in inches.
*
* @return The character's height in inches.
*/
public int getHeight()
{
return heightFacet.getHeight(id);
}
/**
* Gets the character's list of languages.
*
* @return An unmodifiable language set.
*/
public Set<Language> getLanguageSet()
{
return languageFacet.getSet(id);
}
/**
* Gets the list of potential followers of a given type.
*
* @param aType
* Type of follower to retrieve list for e.g. Familiar
* @param comp
* the comparator that will be used to order the returned map.
* @return A MAP of FollowerOption objects representing the possible list
* of follower choices.
*/
public Map<FollowerOption, CDOMObject> getAvailableFollowers(final String aType, Comparator<FollowerOption> comp)
{
return foFacet.getAvailableFollowers(id, aType, comp);
}
/**
* Get the Follower object that is the "master" for this object.
*
* @return follower master
*/
public Follower getMaster()
{
return masterFacet.get(id);
}
/**
* @return nonProficiencyPenalty. Searches templates first.
*/
public int getNonProficiencyPenalty()
{
return nonppFacet.getPenalty(id);
}
/**
* Selector gets the character's primary weapons.
*
* @return primary weapons
*/
public Collection<Equipment> getPrimaryWeapons()
{
return primaryWeaponFacet.getSet(id);
}
public boolean hasPrimaryWeapons()
{
return !primaryWeaponFacet.isEmpty(id);
}
public boolean hasSecondaryWeapons()
{
return !secondaryWeaponFacet.isEmpty(id);
}
/**
* Get the character's secondary weapons.
*
* @return secondary weapons
*/
public Collection<Equipment> getSecondaryWeapons()
{
return secondaryWeaponFacet.getSet(id);
}
/**
* Get skill list.
*
* @return list of skills
*/
public Collection<Skill> getSkillSet()
{
return skillFacet.getSet(id);
}
@Deprecated
public List<SpecialAbility> getResolvedSpecialAbilities(CDOMObject cdo)
{
return specialAbilityFacet.getResolved(id, cdo);
}
@Deprecated
public List<SpecialAbility> getResolvedUserSpecialAbilities(CDOMObject cdo)
{
return userSpecialAbilityFacet.getResolved(id, cdo);
}
/**
* Get the name of the spellbook to auto add new known spells to.
*
* @return spellbook name
*/
public String getSpellBookNameToAutoAddKnown()
{
return getSafeStringFor(PCStringKey.SPELLBOOK_AUTO_ADD_KNOWN);
}
/**
* Get spell books.
*
* @return spellBooks
*/
public Collection<SpellBook> getSpellBooks()
{
return spellBookFacet.getBooks(id);
}
/**
* Accessor, Gets the sub-race of the character.
* @return character subrace.
*/
@Deprecated
public String getSubRace()
{
return subRaceFacet.getSubRace(id);
}
/**
* Get a set of the templates applies to this pc.
* @return the set of Templates.
*/
public Collection<PCTemplate> getTemplateSet()
{
return templateFacet.getSet(id);
}
/**
* Gets the character's weight in pounds.
*
* @return The character's weight.
*/
public int getWeight()
{
return weightFacet.getWeight(id);
}
public int getXP()
{
return xpFacet.getXP(id);
}
public String getXPTableName()
{
return xpTableFacet.get(id).getName();
}
/**
* Check whether this PC has this WeaponProf.
* @param wp The WeaponProf to check.
* @return True if the PC has the WeaponProf
*/
public boolean hasWeaponProf(final WeaponProf wp)
{
return weaponProfFacet.containsProf(id, wp);
}
/**
*
* @return the racial size
*/
public int racialSizeInt()
{
return sizeFacet.racialSizeInt(id);
}
public Set<Language> getAutoLanguages()
{
Set<Language> languages = new HashSet<>();
languages.addAll(autoLangGrantedFacet.getSet(id));
languages.addAll(autoLangUnconditionalFacet.getSet(id));
return languages;
}
/**
* Returns the character's Effective Character Level.
*
* <p>
* The level is calculated by adding total non-monster levels, total
* hitdice, and level adjustment.
*
* @return The ECL of the character.
*/
public int getECL()
{
return levelFacet.getECL(id);
}
public Collection<Kit> getKitInfo()
{
return kitFacet.getSet(id);
}
public Collection<PCLevelInfo> getLevelInfo()
{
return levelInfoFacet.getSet(id);
}
public PCLevelInfo getLevelInfo(int index)
{
return levelInfoFacet.get(id, index);
}
public int getLevelInfoSize()
{
return levelInfoFacet.getCount(id);
}
public String getLevelInfoClassKeyName(final int idx)
{
if ((idx >= 0) && (idx < getLevelInfoSize()))
{
return levelInfoFacet.get(id, idx).getClassKeyName();
}
return Constants.EMPTY_STRING;
}
public int getLevelInfoClassLevel(final int idx)
{
if ((idx >= 0) && (idx < getLevelInfoSize()))
{
return levelInfoFacet.get(id, idx).getClassLevel();
}
return 0;
}
/**
* Checks if the stat is a non ability.
*
* @return true, if is non ability
*/
public boolean isNonAbility(PCStat stat)
{
return nonAbilityFacet.isNonAbility(id, stat);
}
/*
* returns true if Equipment is in the secondary weapon list
*/
public boolean isSecondaryWeapon(final Equipment eq)
{
if (eq == null)
{
return false;
}
for (Equipment eqI : secondaryWeaponFacet.getSet(id))
{
if (eqI.getName().equalsIgnoreCase(eq.getName()) && (eqI.getLocation() == eq.getLocation()))
{
return true;
}
}
return false;
}
/**
* Calculates total bonus from all stats
*
* @param aType
* @param aName
* @return stat bonus to
*/
public double getStatBonusTo(String aType, String aName)
{
return statBonusFacet.getStatBonusTo(id, aType, aName);
}
public String getUDamForRace()
{
return unarmedDamageFacet.getUDamForRace(id);
}
public Set<List<String>> getUnarmedDamage()
{
return unarmedDamageFacet.getSet(id);
}
/**
* Get all possible sources of Damage Resistance and calculate
*
* @return DR
*/
public String calcDR()
{
return drFacet.getDRString(id);
}
/*
* returns true if Equipment is in the primary weapon list
*/
public boolean isPrimaryWeapon(final Equipment eq)
{
if (eq == null)
{
return false;
}
for (Equipment eqI : primaryWeaponFacet.getSet(id))
{
if (eqI.getName().equalsIgnoreCase(eq.getName()) && (eqI.getLocation() == eq.getLocation()))
{
return true;
}
}
return false;
}
public int minXPForNextECL()
{
return levelTableFacet.minXPForLevel(levelFacet.getECL(id) + 1, id);
}
public double multiclassXPMultiplier()
{
return multiClassFacet.getMultiClassXPMultiplier(id);
}
public int sizeInt()
{
return sizeFacet.sizeInt(id);
}
public int totalHitDice()
{
return levelFacet.getMonsterLevelCount(id);
}
public int totalNonMonsterLevels()
{
return levelFacet.getNonMonsterLevelCount(id);
}
public Float totalWeight()
{
return totalWeightFacet.getTotalWeight(id);
}
public SizeAdjustment getSizeAdjustment()
{
return sizeFacet.get(id);
}
public boolean hasKit(Kit kit)
{
return kitFacet.contains(id, kit);
}
public boolean hasSkill(Skill skill)
{
return skillFacet.contains(id, skill);
}
public boolean hasTemplate(PCTemplate template)
{
return templateFacet.contains(id, template);
}
public Collection<PCStat> getStatSet()
{
return statFacet.getSet(id);
}
public boolean hasDomain(Domain domain)
{
return domainFacet.contains(id, domain);
}
public boolean hasDomains()
{
return !domainFacet.isEmpty(id);
}
public int getDomainCount()
{
return domainFacet.getCount(id);
}
public Set<Domain> getDomainSet()
{
return domainFacet.getSet(id);
}
public int getStatCount()
{
return statFacet.getCount(id);
}
public PCClassLevel getActiveClassLevel(PCClass pcc, int lvl)
{
return classFacet.getClassLevel(id, pcc, lvl);
}
public int getClassCount()
{
return classFacet.getCount(id);
}
/*
* Size is taken into account for the currentPC via getLoadMultForSize
*/
public Float getMaxLoad()
{
return loadFacet.getMaxLoad(id);
}
public Float getMaxLoad(double mult)
{
return loadFacet.getMaxLoad(id, mult);
}
public Load getLoadType()
{
return loadFacet.getLoadType(id);
}
public double getMovementOfType(String moveType)
{
return moveResultFacet.getMovementOfType(id, moveType);
}
public boolean hasEquipSet()
{
return !equipSetFacet.isEmpty(id);
}
public boolean hasCharacterSpells(CDOMObject cdo)
{
return activeSpellsFacet.containsFrom(id, cdo);
}
public Collection<? extends CharacterSpell> getCharacterSpells(CDOMObject cdo)
{
return activeSpellsFacet.getSet(id, cdo);
}
public AgeSet getAgeSet()
{
return ageSetFacet.get(id);
}
/**
* Retrieve the set of the character's chronicle entries.
* @return The character's chronicle entries.
*/
public Collection<ChronicleEntry> getChronicleEntries()
{
return chronicleEntryFacet.getSet(id);
}
public HitDie getLevelHitDie(PCClass pcClass, final int classLevel)
{
return hitPointFacet.getLevelHitDie(id, pcClass, classLevel);
}
public List<? extends CDOMList<Spell>> getSpellLists(CDOMObject cdo)
{
return spellListFacet.getSet(id, cdo);
}
/**
* @return display name
*/
public String getDisplayName()
{
final String custom = getSafeStringFor(PCStringKey.TABNAME);
if (!Constants.EMPTY_STRING.equals(custom))
{
return custom;
}
final StringBuilder displayName = new StringBuilder(100).append(getName());
// TODO - i18n
switch (SettingsHandler.getNameDisplayStyle())
{
case Constants.DISPLAY_STYLE_NAME:
break;
case Constants.DISPLAY_STYLE_NAME_CLASS:
displayName.append(" the ").append(getDisplayClassName());
break;
case Constants.DISPLAY_STYLE_NAME_RACE:
displayName.append(" the ").append(getDisplayRaceName());
break;
case Constants.DISPLAY_STYLE_NAME_RACE_CLASS:
displayName.append(" the ").append(getDisplayRaceName()).append(' ').append(getDisplayClassName());
break;
case Constants.DISPLAY_STYLE_NAME_FULL:
return getFullDisplayName();
default:
break; // custom broken
}
return displayName.toString();
}
/**
* Returns a very descriptive name for the character.
*
* The format is [name] the [level]th level [race name] [classes]
*
* @return A descriptive string name for the character.
*/
public String getFullDisplayName()
{
final int levels = getTotalLevels();
final String displayClass;
// If you aren't multi-classed, don't display redundant class level
// information in addition to the total PC level
displayClass = classFacet.getCount(id) > 1 ? getFullDisplayClassName() : getDisplayClassName();
return new StringBuilder(100).append(getName()).append(" the ").append(levels).append(getOrdinal(levels))
.append(" level ").append(getDisplayRaceName()).append(' ').append(displayClass).toString();
}
private String getOrdinal(final int cardinal)
{
switch (cardinal)
{
case 1:
return "st";
case 2:
return "nd";
case 3:
return "rd";
default:
return "th";
}
}
private String getDisplayClassName()
{
ArrayList<PCClass> classList = getClassList();
return (classFacet.isEmpty(id) ? "Nobody" : getDisplayClassName(classList.get(classList.size() - 1)));
}
private String getDisplayRaceName()
{
final String raceName = getRace().toString();
return (raceName.equals(Constants.NONESELECTED) ? "Nothing" : raceName);
}
private String getFullDisplayClassName()
{
if (classFacet.isEmpty(id))
{
return "Nobody";
}
final StringBuilder buf = new StringBuilder(50);
boolean first = true;
for (PCClass c : getClassSet())
{
if (!first)
{
buf.append('/');
first = false;
}
buf.append(getFullDisplayClassName(c));
}
return buf.toString();
}
public String getFullDisplayClassName(PCClass pcClass)
{
final StringBuilder buf = new StringBuilder(40);
buf.append(getDisplayClassName(pcClass));
return buf.append(" ").append(getLevel(pcClass)).toString();
}
public String getDisplayClassName(PCClass pcClass)
{
if (pcClass != null)
{
String subClassKey = getSubClassName(pcClass);
if (subClassKey != null && (!subClassKey.isEmpty())
&& !subClassKey.equals(Constants.NONE))
{
SubClass sc = pcClass.getSubClassKeyed(subClassKey);
if (sc != null)
{
return sc.getDisplayName();
}
}
}
return pcClass.getDisplayName();
}
/**
* Get the value of the weight token in format WEIGHT.X
* @param type Encumbrance type
* @return The value of the weight token.
*/
public double getLoadToken(String type)
{
Float mult = SettingsHandler.getGame().getLoadInfo().getLoadMultiplier(
type.toUpperCase());
if (mult != null)
{
return getMaxLoad(mult).intValue();
}
return 0.0;
}
/**
* Get the armor proficiency list.
*
* @return armor proficiency list
*/
public Collection<ProfProvider<ArmorProf>> getArmorProfList()
{
return armorProfFacet.getQualifiedSet(id);
}
/**
* Get the character's "equipped" equipment.
* @return a set of the "equipped" equipment
*/
public Set<Equipment> getEquippedEquipmentSet()
{
return equippedFacet.getSet(id);
}
/**
* Returns a region (including subregion) string for the character.
*
* <p> Build on-the-fly so removing templates won't mess up region
*
* @return character region
*/
public String getFullRegion()
{
return regionFacet.getFullRegion(id);
}
public Vision getVision(VisionType type)
{
return visionFacet.getActiveVision(id, type);
}
public String getSubstitutionClassName(PCClassLevel lvl)
{
return substitutionClassFacet.get(id, lvl);
}
public int getStat(PCStat stat)
{
return statValueFacet.get(id, stat).intValue();
}
public boolean containsRacialSubType(RaceSubType st)
{
return subTypesFacet.contains(id, st);
}
/**
* Determine the number of legs the character has.
*
* @return The number of legs.
*/
public int getPreFormulaLegs()
{
return legsFacet.getLegs(id);
}
public Integer getDR(String key)
{
return drFacet.getDR(id, key);
}
public boolean hasMovement()
{
return !baseMovementFacet.isEmpty(id);
}
public Collection<WeaponProf> getWeaponProfSet()
{
return weaponProfFacet.getSet(id);
}
public List<? extends SpecialAbility> getUserSpecialAbilityList(CDOMObject source)
{
return userSpecialAbilityFacet.getSet(id, source);
}
public Integer getHP(PCClassLevel pcl)
{
return hitPointFacet.get(id, pcl);
}
public BioSet getBioSet()
{
return bioSetFacet.get(id);
}
public int getAgeSetIndex()
{
return ageSetFacet.getAgeSetIndex(id);
}
public boolean hasFollowers()
{
return !followerFacet.isEmpty(id);
}
public boolean hasEquipment()
{
return !equipmentFacet.isEmpty(id);
}
public boolean hasLanguage(Language lang)
{
return languageFacet.contains(id, lang);
}
public int getLanguageCount()
{
return languageFacet.getCount(id);
}
public boolean hasTemplates()
{
return !templateFacet.isEmpty(id);
}
/**
* Get list of shield proficiencies.
*
* @return shield prof list
*/
public Collection<ProfProvider<ShieldProf>> getShieldProfList()
{
return shieldProfFacet.getQualifiedSet(id);
}
public int getTotalStatFor(PCStat stat)
{
return statCalcFacet.getTotalStatFor(id, stat);
}
public int getStatModFor(PCStat stat)
{
return statCalcFacet.getStatModFor(id, stat);
}
public int getBaseStatFor(PCStat stat)
{
return statCalcFacet.getBaseStatFor(id, stat);
}
public int getTemplateCount()
{
return templateFacet.getCount(id);
}
public int getFollowerCount()
{
return followerFacet.getCount(id);
}
public int getRacialSubTypeCount()
{
return subTypesFacet.getCount(id);
}
public int getVisionCount()
{
return visionFacet.getVisionCount(id);
}
public Double getBaseMovement()
{
return baseMovementFacet.getSet(id).iterator().next().getDoubleMovement();
}
public double movementOfType(final String moveType)
{
return moveResultFacet.movementOfType(id, moveType);
}
public boolean containsNote(NoteItem note)
{
return noteItemFacet.contains(id, note);
}
public int getNotesCount()
{
return noteItemFacet.getCount(id);
}
/**
* Gets a list of notes associated with the character.
*
* @return A list of <tt>NoteItem</tt> objects.
*/
public Collection<NoteItem> getNotesList()
{
return noteItemFacet.getSet(id);
}
/**
* Check if the character has the given Deity.
*
* @param deity
* Deity to check for.
* @return {@code true} if the character has the Deity,
* {@code false} otherwise.
*/
public boolean hasDeity(final Deity deity)
{
return deityFacet.matches(id, deity);
}
/**
* Calculates the level of the character's favored class
*
* @return level
*/
public int getFavoredClassLevel()
{
return favClassFacet.getFavoredClassLevel(id);
}
/**
* returns ranks taken specifically in skill
*
* @return ranks taken in skill
*/
public Float getRank(Skill sk)
{
return skillRankFacet.getRank(id, sk);
}
public List<WeaponProf> getWeaponProfsInTarget(CDOMGroupRef<WeaponProf> master)
{
return changeProfFacet.getWeaponProfsInTarget(id, master);
}
/**
* Return a list of bonus languages which the character may select from.
* This function is not efficient, but is sufficient for it's current use of
* only being called when the user requests the bonus language selection
* list. Note: A check will be made for the ALL language and it will be
* replaced with the current list of languages in globals. These should be
* further restricted by the prerequisites of the languages to ensure that
* 'secret' languages are not offered.
*
* @return List of bonus languages for the character.
*/
public Set<Language> getLanguageBonusSelectionList()
{
return startingLangFacet.getSet(id);
}
public boolean isProficientWithArmor(final Equipment eq)
{
return armorProfFacet.isProficientWithArmor(id, eq);
}
/**
* WARNING: Use this method SPARINGLY... and only for transition to the
* facet model. It is NOT an excuse to throw around a CharacterDisplay
* object when unnecessary
*
* @return The id of the character as used by the facets.
*/
public CharID getCharID()
{
return id;
}
}