Search in sources :

Example 61 with PCClassLevel

use of pcgen.cdom.inst.PCClassLevel in project pcgen by PCGen.

the class DomainApplication method removeDomainsForLevel.

public static void removeDomainsForLevel(PCClass cl, final int removedLevel, final PlayerCharacter aPC) {
    /*
		 * Note this uses ALL of the domains up to and including this level,
		 * because there is the possibility (albeit strange) that the PC was
		 * qualified at a previous level change, but the PlayerCharacter is now
		 * not qualified for the given Domain. Even this has quirks, since it is
		 * only applied at the time of level increase, but I think that quirk
		 * should be resolved by a CDOM system around 6.0 - thpr 10/23/06
		 */
    for (QualifiedObject<CDOMSingleRef<Domain>> qo : cl.getSafeListFor(ListKey.DOMAIN)) {
        CDOMSingleRef<Domain> ref = qo.getObject(aPC, cl);
        if (ref == null) {
            ref = qo.getRawObject();
            aPC.removeDomain(ref.get());
        }
    }
    for (int i = 0; i <= removedLevel; i++) {
        // TODO This stinks for really high level characters - can this ever
        // get null back?
        PCClassLevel pcl = aPC.getActiveClassLevel(cl, i);
        for (QualifiedObject<CDOMSingleRef<Domain>> qo : pcl.getSafeListFor(ListKey.DOMAIN)) {
            CDOMSingleRef<Domain> ref = qo.getObject(aPC, cl);
            if ((ref == null) || (i == removedLevel)) {
                ref = qo.getRawObject();
                aPC.removeDomain(ref.get());
            }
        }
    }
}
Also used : Domain(pcgen.core.Domain) CDOMSingleRef(pcgen.cdom.reference.CDOMSingleRef) PCClassLevel(pcgen.cdom.inst.PCClassLevel)

Example 62 with PCClassLevel

use of pcgen.cdom.inst.PCClassLevel in project pcgen by PCGen.

the class SpellSupportForPCClass method updateSpellCache.

public boolean updateSpellCache(boolean force) {
    if (force || !spellCacheValid) {
        SpellProgressionCache cache = new SpellProgressionCache();
        for (PCClassLevel cl : source.getOriginalClassLevelCollection()) {
            Integer lvl = cl.get(IntegerKey.LEVEL);
            List<Formula> cast = cl.getListFor(ListKey.CAST);
            if (cast != null) {
                cache.setCast(lvl, cast);
            }
            List<Formula> known = cl.getListFor(ListKey.KNOWN);
            if (known != null) {
                cache.setKnown(lvl, known);
            }
            List<Formula> spec = cl.getListFor(ListKey.SPECIALTYKNOWN);
            if (spec != null) {
                cache.setSpecialtyKnown(lvl, spec);
            }
        }
        if (!cache.isEmpty()) {
            spellCache = cache;
        }
        spellCacheValid = true;
    }
    return spellCache != null;
}
Also used : Formula(pcgen.base.formula.Formula) PCClassLevel(pcgen.cdom.inst.PCClassLevel)

Example 63 with PCClassLevel

use of pcgen.cdom.inst.PCClassLevel in project pcgen by PCGen.

the class PCClassKeyChange method changeReferences.

public static void changeReferences(String oldClass, PCClass pcc) {
    String newClass = pcc.getKeyName();
    // Don't traverse the list if the names are the same
    if (oldClass.equals(newClass)) {
        return;
    }
    renameVariables(oldClass, pcc, newClass);
    renameBonusTarget(pcc, oldClass, newClass);
    // Repeat for Class Levels
    for (PCClassLevel pcl : pcc.getOriginalClassLevelCollection()) {
        renameVariables(oldClass, pcl, newClass);
        renameBonusTarget(pcl, oldClass, newClass);
    }
}
Also used : PCClassLevel(pcgen.cdom.inst.PCClassLevel)

Example 64 with PCClassLevel

use of pcgen.cdom.inst.PCClassLevel in project pcgen by PCGen.

the class PCGVer2Parser method parseClassAbilitiesLevelLine.

private void parseClassAbilitiesLevelLine(final String line, final List<PCLevelInfo> pcLevelInfoList) {
    final PCGTokenizer tokens;
    try {
        tokens = new PCGTokenizer(line);
    } catch (PCGParseException pcgpex) {
        final String message = LanguageBundle.getFormattedString(//$NON-NLS-1$
        "Warnings.PCGenParser.IllegalClassAbility", line, pcgpex.getMessage());
        warnings.add(message);
        return;
    }
    int level = -1;
    PCClass aPCClass = null;
    PCGElement element;
    PCLevelInfo pcl = null;
    final Iterator<PCGElement> it = tokens.getElements().iterator();
    // eg: Cleric=4
    if (it.hasNext()) {
        element = it.next();
        final int index = element.getText().indexOf('=');
        if (index < 0) {
            final String message = LanguageBundle.getFormattedString(//$NON-NLS-1$
            "Warnings.PCGenParser.InvalidClassLevel", element.getText());
            warnings.add(message);
            return;
        }
        final String classKeyName = EntityEncoder.decode(element.getText().substring(0, index));
        aPCClass = thePC.getClassKeyed(classKeyName);
        if (aPCClass == null) {
            final String message = LanguageBundle.getFormattedString(//$NON-NLS-1$
            "Warnings.PCGenParser.ClassNotFound", classKeyName);
            warnings.add(message);
            return;
        }
        try {
            level = Integer.parseInt(element.getText().substring(index + 1));
        } catch (NumberFormatException nfe) {
            final String message = LanguageBundle.getFormattedString(//$NON-NLS-1$
            "Warnings.PCGenParser.InvalidClassLevel", element.getText());
            warnings.add(message);
            return;
        }
        if (level < 1) {
            final String message = LanguageBundle.getFormattedString(//$NON-NLS-1$
            "Warnings.PCGenParser.InvalidClassLevel", element.getText());
            warnings.add(message);
            return;
        }
        for (PCLevelInfo info : pcLevelInfoList) {
            if (classKeyName.equalsIgnoreCase(info.getClassKeyName()) && level == info.getClassLevel()) {
                pcl = info;
                break;
            }
        }
        if (pcl == null) {
            pcl = thePC.addLevelInfo(classKeyName);
            pcl.setClassLevel(level);
        } else {
            thePC.addLevelInfo(pcl);
        }
        pcl.setSkillPointsRemaining(0);
    }
    while (it.hasNext()) {
        element = it.next();
        String tag = element.getName();
        if (IOConstants.TAG_SUBSTITUTIONLEVEL.equals(tag)) {
            final String substitutionClassKeyName = EntityEncoder.decode(element.getText());
            SubstitutionClass aSubstitutionClass = aPCClass.getSubstitutionClassKeyed(substitutionClassKeyName);
            if (aSubstitutionClass == null) {
                final String message = LanguageBundle.getFormattedString(//$NON-NLS-1$
                "Warnings.PCGenParser.ClassNotFound", substitutionClassKeyName);
                warnings.add(message);
                return;
            }
            SubstitutionLevelSupport.applyLevelArrayModsToLevel(aSubstitutionClass, aPCClass, level, thePC);
            thePC.setSubstitutionClassName(thePC.getActiveClassLevel(aPCClass, level), substitutionClassKeyName);
        } else if (IOConstants.TAG_HITPOINTS.equals(tag)) {
            try {
                PCClassLevel classLevel = thePC.getActiveClassLevel(aPCClass, level - 1);
                thePC.setHP(classLevel, Integer.valueOf(element.getText()));
            } catch (NumberFormatException nfe) {
                final String message = LanguageBundle.getFormattedString(//$NON-NLS-1$
                "Warnings.PCGenParser.InvalidHP", tag, element.getText());
                warnings.add(message);
            }
        } else if (IOConstants.TAG_SAVES.equals(tag)) {
            for (final PCGElement child : element.getChildren()) {
                final String dString = EntityEncoder.decode(child.getText());
                if (dString.startsWith(IOConstants.TAG_BONUS + IOConstants.TAG_SEPARATOR)) {
                    String bonusString = dString.substring(6);
                    int pipeLoc = bonusString.indexOf('|');
                    if (pipeLoc != -1) {
                        CDOMObject target = aPCClass;
                        String potentialInt = bonusString.substring(0, pipeLoc);
                        try {
                            int bonusLevel = Integer.parseInt(potentialInt);
                            if (bonusLevel > 0) {
                                target = thePC.getActiveClassLevel(aPCClass, bonusLevel);
                            }
                            bonusString = bonusString.substring(pipeLoc + 1);
                        } catch (NumberFormatException e) {
                            //OK (no level embedded in file)
                            if (level > 0) {
                                target = thePC.getActiveClassLevel(aPCClass, level);
                            }
                        }
                        BonusAddition.applyBonus(bonusString, "", thePC, target);
                    }
                }
            }
        } else if (IOConstants.TAG_SPECIALTIES.equals(tag)) {
            for (final PCGElement child : element.getChildren()) {
                thePC.setAssoc(aPCClass, AssociationKey.SPECIALTY, EntityEncoder.decode(child.getText()));
            }
        } else if (IOConstants.TAG_SPECIALABILITIES.equals(tag)) {
            for (PCGElement child : element.getChildren()) {
                String specialAbilityName = EntityEncoder.decode(child.getText());
                if (pcgenVersion[0] <= 5 && pcgenVersion[1] <= 5 && pcgenVersion[2] < 6) {
                    if (//$NON-NLS-1$
                    specialAbilityName.equals("Turn Undead")) {
                        //$NON-NLS-1$
                        parseFeatLine("FEAT:Turn Undead|TYPE:SPECIAL.TURNUNDEAD|DESC:");
                        continue;
                    } else if (//$NON-NLS-1$
                    specialAbilityName.equals("Rebuke Undead")) {
                        //$NON-NLS-1$
                        parseFeatLine("FEAT:Rebuke Undead|TYPE:SPECIAL.TURNUNDEAD|DESC:");
                        continue;
                    }
                }
                SpecialAbility specialAbility = new SpecialAbility(specialAbilityName);
                CDOMObject target = aPCClass;
                if (level > 0) {
                    target = thePC.getActiveClassLevel(aPCClass, level);
                }
                if (!thePC.hasSpecialAbility(specialAbilityName)) {
                    thePC.addUserSpecialAbility(specialAbility, target);
                }
            }
        } else if (tag.equals(IOConstants.TAG_LEVELABILITY)) {
            parseLevelAbilityInfo(element, aPCClass, level);
        } else if (tag.equals(IOConstants.TAG_ADDTOKEN)) {
            parseAddTokenInfo(element, thePC.getActiveClassLevel(aPCClass, level));
        } else //
        if (tag.equals(IOConstants.TAG_PRESTAT) || tag.equals(IOConstants.TAG_POSTSTAT)) {
            boolean isPre = false;
            if (tag.equals(IOConstants.TAG_PRESTAT)) {
                isPre = true;
            }
            final int idx = element.getText().indexOf('=');
            if (idx > 0) {
                String statAbb = element.getText().substring(0, idx);
                final PCStat pcstat = Globals.getContext().getReferenceContext().silentlyGetConstructedCDOMObject(PCStat.class, statAbb);
                if (pcstat != null) {
                    try {
                        thePC.saveStatIncrease(pcstat, Integer.parseInt(element.getText().substring(idx + 1)), isPre);
                    } catch (NumberFormatException nfe) {
                        final String msg = LanguageBundle.getFormattedString(//$NON-NLS-1$
                        "Warnings.PCGenParser.InvalidStatMod", tag, element.getText());
                        warnings.add(msg);
                    }
                } else {
                    final String msg = LanguageBundle.getFormattedString(//$NON-NLS-1$
                    "Warnings.PCGenParser.UnknownStat", tag, element.getText());
                    warnings.add(msg);
                }
            } else {
                final String msg = LanguageBundle.getFormattedString(//$NON-NLS-1$
                "Warnings.PCGenParser.MissingEquals", tag, element.getText());
                warnings.add(msg);
            }
        } else if ((pcl != null) && IOConstants.TAG_SKILLPOINTSGAINED.equals(tag)) {
            pcl.setFixedSkillPointsGained(Integer.parseInt(element.getText()));
        } else if ((pcl != null) && IOConstants.TAG_SKILLPOINTSREMAINING.equals(tag)) {
            pcl.setSkillPointsRemaining(Integer.parseInt(element.getText()));
        } else if (IOConstants.TAG_DATA.equals(tag)) {
        // TODO
        // for now it's ok to ignore it!
        } else {
            final String msg = LanguageBundle.getFormattedString(//$NON-NLS-1$
            "Warnings.PCGenParser.UnknownTag", tag, element.getText());
            warnings.add(msg);
        }
    }
// TODO:
// process data
//
// need to add some consistency checks here to avoid
// - duplicate entries for one and the same class/level pair
// - missing entries for a given class/level pair
}
Also used : SpecialAbility(pcgen.core.SpecialAbility) PCClass(pcgen.core.PCClass) SubstitutionClass(pcgen.core.SubstitutionClass) PCClassLevel(pcgen.cdom.inst.PCClassLevel) CDOMObject(pcgen.cdom.base.CDOMObject) PCLevelInfo(pcgen.core.pclevelinfo.PCLevelInfo) PCStat(pcgen.core.PCStat)

Example 65 with PCClassLevel

use of pcgen.cdom.inst.PCClassLevel in project pcgen by PCGen.

the class PCGIOHandler method sanityChecks.

/*
	 * ###############################################################
	 * private helper methods
	 * ###############################################################
	 */
private void sanityChecks(PlayerCharacter currentPC, PCGParser parser) {
    // Hit point sanity check
    boolean fixMade = false;
    resolveDuplicateEquipmentSets(currentPC);
    // First make sure the "working" equipment list
    // is in effect for all the bonuses it may add
    currentPC.setCalcEquipmentList();
    // make sure the bonuses from companions are applied
    currentPC.setCalcFollowerBonus();
    // pre-calculate all the bonuses
    currentPC.calcActiveBonuses();
    final int oldHp = currentPC.hitPoints();
    // Recalc the feat pool if required
    if (parser.isCalcFeatPoolAfterLoad()) {
        double baseFeatPool = parser.getBaseFeatPool();
        double featPoolBonus = currentPC.getRemainingFeatPoints(true);
        baseFeatPool -= featPoolBonus;
        currentPC.setUserPoolBonus(AbilityCategory.FEAT, new BigDecimal(baseFeatPool));
    }
    for (CNAbility aFeat : currentPC.getPoolAbilities(AbilityCategory.FEAT, Nature.NORMAL)) {
        if (aFeat.getAbility().getSafe(ObjectKey.MULTIPLE_ALLOWED) && !currentPC.hasAssociations(aFeat)) {
            warnings.add("Multiple selection feat found with no selections (" + aFeat.getAbility().getDisplayName() + "). Correct on Feat tab.");
        }
    }
    //PCTemplate aTemplate = null;
    if (currentPC.hasClass()) {
        for (PCClass pcClass : currentPC.getClassSet()) {
            // Ignore if no levels
            if (currentPC.getLevel(pcClass) < 1) {
                continue;
            }
            for (int i = 1; i <= currentPC.getLevel(pcClass); i++) {
                int baseSides = currentPC.getLevelHitDie(pcClass, i).getDie();
                //TODO i-1 is strange see CODE-1925
                PCClassLevel pcl = currentPC.getActiveClassLevel(pcClass, i - 1);
                Integer hp = currentPC.getHP(pcl);
                int iRoll = hp == null ? 0 : hp;
                int iSides = baseSides + (int) pcClass.getBonusTo("HD", "MAX", i, currentPC);
                if (iRoll > iSides) {
                    currentPC.setHP(pcl, iSides);
                    fixMade = true;
                }
            }
        }
    }
    if (fixMade) {
        final String message = "Fixed illegal value in hit points. " + "Current character hit points: " + currentPC.hitPoints() + " not " + oldHp;
        warnings.add(message);
    }
    //
    for (PCClass pcClass : currentPC.getClassSet()) {
        currentPC.calcActiveBonuses();
        currentPC.calculateKnownSpellsForClassLevel(pcClass);
    }
    //
    // need to calc the movement rates
    currentPC.adjustMoveRates();
    // re-calculate all the bonuses
    currentPC.calcActiveBonuses();
    // make sure we are not dirty
    currentPC.setDirty(false);
}
Also used : CNAbility(pcgen.cdom.content.CNAbility) PCClass(pcgen.core.PCClass) BigDecimal(java.math.BigDecimal) PCClassLevel(pcgen.cdom.inst.PCClassLevel)

Aggregations

PCClassLevel (pcgen.cdom.inst.PCClassLevel)69 PCClass (pcgen.core.PCClass)26 Test (org.junit.Test)25 PCLevelInfo (pcgen.core.pclevelinfo.PCLevelInfo)9 CDOMObject (pcgen.cdom.base.CDOMObject)8 ArrayList (java.util.ArrayList)5 CharID (pcgen.cdom.enumeration.CharID)5 ParseResult (pcgen.rules.persistence.token.ParseResult)5 CDOMReference (pcgen.cdom.base.CDOMReference)4 SpecialAbility (pcgen.core.SpecialAbility)4 LoadContext (pcgen.rules.context.LoadContext)4 AbstractTokenModelTest (tokenmodel.testsupport.AbstractTokenModelTest)4 StringTokenizer (java.util.StringTokenizer)3 DataFacetChangeEvent (pcgen.cdom.facet.event.DataFacetChangeEvent)3 Domain (pcgen.core.Domain)3 Skill (pcgen.core.Skill)3 TestContext (plugin.lsttokens.editcontext.testsupport.TestContext)3 BigDecimal (java.math.BigDecimal)2 URI (java.net.URI)2 URISyntaxException (java.net.URISyntaxException)2