Search in sources :

Example 31 with PCLevelInfo

use of pcgen.core.pclevelinfo.PCLevelInfo in project pcgen by PCGen.

the class SkillRankControl method removeSkillsForTopLevel.

/**
	 * Adjust the character's skills to reflect the loss of a level. This is 
	 * done by:
	 * <ol>
	 * <li>Removing ranks from any skills with max ranks or more</li>
	 * <li>Taking any skill points still needing to be refunded off the remainder 
	 * for the next highest level of the class</li>
	 * <li>or taking them off the remainder for the highest class level.</li>
	 * </ol>
	 * 
	 * @param pc The character being updated.
	 * @param classBeingLevelledDown The class we are removing a level of.
	 * @param currentLevel The character;s level before the removal.
	 * @param pointsToRemove The number of points that need to be refunded.
	 */
public static void removeSkillsForTopLevel(PlayerCharacter pc, PCClass classBeingLevelledDown, int currentLevel, int pointsToRemove) {
    double remaining = pointsToRemove;
    if (remaining <= 0.0) {
        return;
    }
    // Remove a rank from each skill with max ranks at the old level (now above max ranks)
    for (Skill skill : pc.getSkillSet()) {
        if (!skill.getSafe(ObjectKey.VISIBILITY).isVisibleTo(View.VISIBLE_DISPLAY)) {
            continue;
        }
        PCClass aClass = pc.getClassList().isEmpty() ? null : pc.getClassList().get(0);
        double maxRanks = pc.getMaxRank(skill, aClass).doubleValue();
        double rankMod = maxRanks - getTotalRank(pc, skill);
        if (rankMod < 0) {
            if (Logging.isLoggable(Logging.INFO)) {
                Logging.log(Logging.INFO, "Removing " + (rankMod * -1) + " ranks from " + skill);
            }
            String err = modRanks(rankMod, classBeingLevelledDown, true, pc, skill);
            if (StringUtils.isBlank(err)) {
                remaining += rankMod;
                if (remaining <= 0) {
                    break;
                }
            }
        }
    }
    // Deal with any remaining skill points to be refunded
    if (remaining != 0.0) {
        //  If there are other levels left of the class being removed, 
        // subtract the remainder from the remaining value of the next 
        // highest level of the class removed.
        PCLevelInfo targetLevel = null;
        int level = currentLevel - 1;
        while (level > 0) {
            PCLevelInfo pcLI = pc.getLevelInfo(level - 1);
            if (pcLI.getClassKeyName().equals(classBeingLevelledDown.getKeyName())) {
                targetLevel = pcLI;
                break;
            }
            level--;
        }
        if (targetLevel == null && currentLevel > 0) {
            //  Otherwise subtract the remainder from the remaining value of 
            // the character's highest remaining level.
            targetLevel = pc.getLevelInfo(currentLevel - 2);
        }
        if (targetLevel != null) {
            targetLevel.setSkillPointsRemaining(targetLevel.getSkillPointsRemaining() - (int) remaining);
        }
    }
}
Also used : Skill(pcgen.core.Skill) PCLevelInfo(pcgen.core.pclevelinfo.PCLevelInfo) PCClass(pcgen.core.PCClass)

Example 32 with PCLevelInfo

use of pcgen.core.pclevelinfo.PCLevelInfo 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 33 with PCLevelInfo

use of pcgen.core.pclevelinfo.PCLevelInfo in project pcgen by PCGen.

the class KitStat method recalculateSkillPoints.

private void recalculateSkillPoints(PlayerCharacter aPC) {
    final Collection<PCClass> classes = aPC.getClassSet();
    aPC.calcActiveBonuses();
    if (classes != null && !classes.isEmpty()) {
        for (PCClass pcClass : classes) {
            aPC.setSkillPool(pcClass, 0);
            // We don't limit this to MOD_TO_SKILLS classes as they may manually include the INT bonus in the skills.
            for (int j = 0; j < aPC.getLevelInfoSize(); j++) {
                final PCLevelInfo pcl = aPC.getLevelInfo(j);
                if (pcl.getClassKeyName().equals(pcClass.getKeyName())) {
                    final int spMod = aPC.recalcSkillPointMod(pcClass, j + 1);
                    int alreadySpent = pcl.getSkillPointsGained(aPC) - pcl.getSkillPointsRemaining();
                    pcl.setSkillPointsGained(aPC, spMod);
                    pcl.setSkillPointsRemaining(pcl.getSkillPointsGained(aPC) - alreadySpent);
                    Integer currentPool = aPC.getSkillPool(pcClass);
                    int newSkillPool = (currentPool == null ? 0 : currentPool) + spMod;
                    aPC.setSkillPool(pcClass, newSkillPool);
                }
            }
        }
    }
}
Also used : PCLevelInfo(pcgen.core.pclevelinfo.PCLevelInfo) PCClass(pcgen.core.PCClass)

Aggregations

PCLevelInfo (pcgen.core.pclevelinfo.PCLevelInfo)33 PCClass (pcgen.core.PCClass)11 PCClassLevel (pcgen.cdom.inst.PCClassLevel)9 ArrayList (java.util.ArrayList)5 HashMap (java.util.HashMap)3 Skill (pcgen.core.Skill)3 StringTokenizer (java.util.StringTokenizer)2 CDOMObject (pcgen.cdom.base.CDOMObject)2 LevelCommandFactory (pcgen.cdom.content.LevelCommandFactory)2 ClassSource (pcgen.cdom.helper.ClassSource)2 Language (pcgen.core.Language)2 PlayerCharacter (pcgen.core.PlayerCharacter)2 SpecialAbility (pcgen.core.SpecialAbility)2 SpellProhibitor (pcgen.core.SpellProhibitor)2 BonusObj (pcgen.core.bonus.BonusObj)2 PCLevelInfoStat (pcgen.core.pclevelinfo.PCLevelInfoStat)2 BigDecimal (java.math.BigDecimal)1 TreeSet (java.util.TreeSet)1 Test (org.junit.Test)1 HitDie (pcgen.cdom.content.HitDie)1