/* * Copyright (c) Thomas Parker, 2012. * * This program 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 program 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., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ package pcgen.cdom.facet; import java.util.ArrayList; import java.util.List; import pcgen.cdom.base.CDOMObject; import pcgen.cdom.content.LevelCommandFactory; import pcgen.cdom.enumeration.CharID; import pcgen.cdom.enumeration.ObjectKey; import pcgen.cdom.facet.analysis.LevelFacet; import pcgen.cdom.facet.event.DataFacetChangeEvent; import pcgen.cdom.facet.event.DataFacetChangeListener; import pcgen.cdom.facet.model.ClassFacet; import pcgen.cdom.facet.model.ClassFacet.ClassInfo; import pcgen.cdom.facet.model.RaceFacet; import pcgen.core.Globals; import pcgen.core.PCClass; import pcgen.core.PlayerCharacter; import pcgen.core.pclevelinfo.PCLevelInfo; /** * {@code MonsterClassFacet} is a Facet that tracks the {@literal Classes & Levels} that a Player * Character was granted through MONSTERCLASS * * @author Thomas Parker (thpr [at] yahoo.com) */ public class MonsterClassFacet implements DataFacetChangeListener<CharID, CDOMObject> { private LevelFacet levelFacet; private ClassFacet classFacet; private FormulaResolvingFacet formulaResolvingFacet; private LevelInfoFacet levelInfoFacet; private RaceFacet raceFacet; private final PlayerCharacterTrackingFacet trackingFacet = FacetLibrary .getFacet(PlayerCharacterTrackingFacet.class); /** * Adds monster classes to the Player Character when a CDOMObject which * grants monster classes is added to the Player Character. * * Triggered when one of the Facets to which MonsterClassFacet listens fires * a DataFacetChangeEvent to indicate a CDOMObject was added to a Player * Character. * * @param dfce * The DataFacetChangeEvent containing the information about the * change * * @see pcgen.cdom.facet.event.DataFacetChangeListener#dataAdded(pcgen.cdom.facet.event.DataFacetChangeEvent) */ @Override public void dataAdded(DataFacetChangeEvent<CharID, CDOMObject> dfce) { CharID id = dfce.getCharID(); CDOMObject cdo = dfce.getCDOMObject(); // Get existing classes ClassInfo ci = classFacet.removeAllClasses(id); // // Remove all saved monster level information // for (int i = levelInfoFacet.getCount(id) - 1; i >= 0; --i) { PCLevelInfo pli = levelInfoFacet.get(id, i); final String classKeyName = pli.getClassKeyName(); final PCClass aClass = Globals.getContext().getReferenceContext() .silentlyGetConstructedCDOMObject(PCClass.class, classKeyName); if (aClass.isMonster()) { levelInfoFacet.remove(id, pli); } } PlayerCharacter pc = trackingFacet.getPC(id); final List<PCLevelInfo> existingLevelInfo = new ArrayList<>(levelInfoFacet.getSet(id)); levelInfoFacet.removeAll(id); // Make sure monster classes are added first if (!pc.isImporting()) { LevelCommandFactory lcf = cdo.get(ObjectKey.MONSTER_CLASS); if (lcf != null) { int levelCount = formulaResolvingFacet.resolve(id, lcf.getLevelCount(), "").intValue(); pc.incrementClassLevel(levelCount, lcf.getPCClass(), true); } } levelInfoFacet.addAll(id, existingLevelInfo); // // If user has chosen a class before choosing a race, // we need to tweak the number of skill points and feats // if (!pc.isImporting() && ci != null && !ci.isEmpty()) { int totalLevels = levelFacet.getTotalLevels(id); for (PCClass pcClass : ci.getClassSet()) { // // Don't add monster classes back in. This will possibly // mess up feats earned by level // ?Possibly convert to monster class if not null? // if (!pcClass.isMonster()) { classFacet.addClass(id, pcClass); int cLevels = ci.getLevel(pcClass); classFacet.setLevel(id, pcClass, cLevels); pc.setSkillPool(pcClass, 0); int cMod = 0; for (int j = 0; j < cLevels; ++j) { cMod += pc.recalcSkillPointMod(pcClass, ++totalLevels); } pc.setSkillPool(pcClass, cMod); } } } } /** * Removes monster classes from the Player Character when the CDOMObject * which granted the monster classes is removed from the Player Character. * * Triggered when one of the Facets to which MonsterClassFacet listens fires * a DataFacetChangeEvent to indicate a CDOMObject was removed from a Player * Character. * * @param dfce * The DataFacetChangeEvent containing the information about the * change * * @see pcgen.cdom.facet.event.DataFacetChangeListener#dataRemoved(pcgen.cdom.facet.event.DataFacetChangeEvent) */ @Override public void dataRemoved(DataFacetChangeEvent<CharID, CDOMObject> dfce) { CDOMObject cdo = dfce.getCDOMObject(); LevelCommandFactory lcf = cdo.get(ObjectKey.MONSTER_CLASS); if (lcf != null) { CharID id = dfce.getCharID(); int levelCount = formulaResolvingFacet.resolve(id, lcf.getLevelCount(), "") .intValue(); PlayerCharacter pc = trackingFacet.getPC(id); pc.incrementClassLevel(-levelCount, lcf.getPCClass(), true); } } public void setLevelFacet(LevelFacet levelFacet) { this.levelFacet = levelFacet; } public void setClassFacet(ClassFacet classFacet) { this.classFacet = classFacet; } public void setFormulaResolvingFacet(FormulaResolvingFacet formulaResolvingFacet) { this.formulaResolvingFacet = formulaResolvingFacet; } public void setLevelInfoFacet(LevelInfoFacet levelInfoFacet) { this.levelInfoFacet = levelInfoFacet; } public void setRaceFacet(RaceFacet raceFacet) { this.raceFacet = raceFacet; } /** * Initializes the connections for MonsterClassFacet to other facets. * * This method is automatically called by the Spring framework during * initialization of the MonsterClassFacet. */ public void init() { raceFacet.addDataFacetChangeListener(this); } }