Search in sources :

Example 26 with PCLevelInfo

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

the class PlayerCharacter method getSkillPoints.

/**
	 * Get skill points.
	 *
	 * @return skill points
	 */
public int getSkillPoints() {
    int returnValue = 0;
    // to display this as -x on the "Total Skill Points" field
    for (PCLevelInfo li : getLevelInfo()) {
        returnValue += li.getSkillPointsGained(this);
    }
    for (Skill aSkill : getSkillSet()) {
        for (PCClass pcc : getSkillRankClasses(aSkill)) {
            if (pcc != null) {
                Double curRank = getSkillRankForClass(aSkill, pcc);
                if (curRank == null) {
                    Logging.errorPrint("Got null on ranks for " + aSkill + " in class " + pcc);
                    curRank = 0.0d;
                }
                // Only add the cost for skills associated with a class.
                // Skill ranks from feats etc are free.
                final int cost = getSkillCostForClass(aSkill, pcc).getCost();
                returnValue -= (int) (cost * curRank);
            }
        }
    }
    if (Globals.getGameModeHasPointPool()) {
        // DO NOT CALL
        returnValue += (int) getRemainingFeatPoints(false);
    // getFeats() here! It
    // will set up a
    // recursive loop and
    // result in a stack
    // overflow!
    }
    return returnValue;
}
Also used : PCLevelInfo(pcgen.core.pclevelinfo.PCLevelInfo)

Example 27 with PCLevelInfo

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

the class PCClass method addLevel.

/**
	 * Adds a level of this class to the character.
	 *
	 * TODO: Split the PlayerCharacter code out of PCClass (i.e. the level
	 * property). Then have a joining class assigned to PlayerCharacter that
	 * maps PCClass and number of levels in the class.
	 *
	 *
	 * @param argLevelMax
	 *            True if we should only allow extra levels if there are still
	 *            levels in this class to take. (i.e. a lot of prestige classes
	 *            stop at level 10, so if this is true it would not allow an
	 *            11th level of the class to be added
	 * @param bSilent
	 *            True if we are not to show any dialog boxes about errors or
	 *            questions.
	 * @param aPC
	 *            The character we are adding the level to.
	 * @param ignorePrereqs
	 *            True if prereqs for the level should be ignored. Used in
	 *            situations such as when the character is being loaded.
	 * @return true or false
	 */
/*
	 * REFACTOR Clearly this is part of the PCClass factory method that produces
	 * PCClassLevels combined with some other work that will need to be done to
	 * extract some of the complicated gunk out of here that goes out and puts
	 * information into PCLevelInfo and PlayerCharacter.
	 */
public boolean addLevel(final boolean argLevelMax, final boolean bSilent, final PlayerCharacter aPC, final boolean ignorePrereqs) {
    // Check to see if we can add a level of this class to the
    // current character
    final int newLevel = aPC.getLevel(this) + 1;
    boolean levelMax = argLevelMax;
    aPC.setAllowInteraction(false);
    aPC.setLevelWithoutConsequence(this, newLevel);
    if (!ignorePrereqs) {
        // When loading a character, classes are added before feats, so
        // this test would always fail on loading if feats are required
        boolean doReturn = false;
        if (!qualifies(aPC, this)) {
            doReturn = true;
            if (!bSilent) {
                ShowMessageDelegate.showMessageDialog("This character does not qualify for level " + newLevel, Constants.APPLICATION_NAME, MessageType.ERROR);
            }
        }
        aPC.setLevelWithoutConsequence(this, newLevel - 1);
        if (doReturn) {
            return false;
        }
    }
    aPC.setAllowInteraction(true);
    if (isMonster()) {
        levelMax = false;
    }
    if (hasMaxLevel() && (newLevel > getSafe(IntegerKey.LEVEL_LIMIT)) && levelMax) {
        if (!bSilent) {
            ShowMessageDelegate.showMessageDialog("This class cannot be raised above level " + Integer.toString(getSafe(IntegerKey.LEVEL_LIMIT)), Constants.APPLICATION_NAME, MessageType.ERROR);
        }
        return false;
    }
    // Add the level to the current character
    int total = aPC.getTotalLevels();
    // No longer need this since the race now sets a bonus itself and Templates
    // are not able to reassign their feats.  There was nothing else returned in
    // this number
    //		if (total == 0) {
    //			aPC.setFeats(aPC.getInitialFeats());
    //		}
    setLevel(newLevel, aPC);
    // the level has now been added to the character,
    // so now assign the attributes of this class level to the
    // character...
    PCClassLevel classLevel = aPC.getActiveClassLevel(this, newLevel);
    // Make sure that if this Class adds a new domain that
    // we record where that domain came from
    final int dnum = aPC.getMaxCharacterDomains(this, aPC) - aPC.getDomainCount();
    if (dnum > 0 && !aPC.hasDefaultDomainSource()) {
        aPC.setDefaultDomainSource(new ClassSource(this, newLevel));
    }
    // out
    if (Globals.getUseGUI()) {
        final int levels = SettingsHandler.isHPMaxAtFirstClassLevel() ? aPC.totalNonMonsterLevels() : aPC.getTotalLevels();
        final boolean isFirst = levels == 1;
        aPC.rollHP(this, aPC.getLevel(this), isFirst);
    }
    if (!aPC.isImporting()) {
        DomainApplication.addDomainsUpToLevel(this, newLevel, aPC);
    }
    int levelUpStats = 0;
    // i.e. a bonus feat every 3 levels
    if (aPC.getTotalLevels() > total) {
        boolean processBonusStats = true;
        total = aPC.getTotalLevels();
        if (isMonster()) {
            // If we have less levels that the races monster levels
            // then we can not give a stat bonus (i.e. an Ogre has
            // 4 levels of Giant, so it does not get a stat increase at
            // 4th level because that is already taken into account in
            // its racial stat modifiers, but it will get one at 8th
            LevelCommandFactory lcf = aPC.getRace().get(ObjectKey.MONSTER_CLASS);
            int monLevels = 0;
            if (lcf != null) {
                monLevels = lcf.getLevelCount().resolve(aPC, "").intValue();
            }
            if (total <= monLevels) {
                processBonusStats = false;
            }
        }
        if (!aPC.isImporting()) {
            if (processBonusStats) {
                final int bonusStats = Globals.getBonusStatsForLevel(total, aPC);
                if (bonusStats > 0) {
                    aPC.setPoolAmount(aPC.getPoolAmount() + bonusStats);
                    if (!bSilent && SettingsHandler.getShowStatDialogAtLevelUp()) {
                        levelUpStats = StatApplication.askForStatIncrease(aPC, bonusStats, true);
                    }
                }
            }
        }
    }
    int spMod = getSkillPointsForLevel(aPC, classLevel, total);
    PCLevelInfo pcl;
    if (aPC.getLevelInfoSize() > 0) {
        pcl = aPC.getLevelInfo(aPC.getLevelInfoSize() - 1);
        if (pcl != null) {
            pcl.setClassLevel(aPC.getLevel(this));
            pcl.setSkillPointsGained(aPC, spMod);
            pcl.setSkillPointsRemaining(pcl.getSkillPointsGained(aPC));
        }
    }
    Integer currentPool = aPC.getSkillPool(this);
    int newSkillPool = spMod + (currentPool == null ? 0 : currentPool);
    aPC.setSkillPool(this, newSkillPool);
    if (!aPC.isImporting()) {
        //
        if (levelUpStats > 0) {
            StatApplication.askForStatIncrease(aPC, levelUpStats, false);
        }
        if (newLevel == 1) {
            AddObjectActions.doBaseChecks(this, aPC);
            CDOMObjectUtilities.addAdds(this, aPC);
            CDOMObjectUtilities.checkRemovals(this, aPC);
        }
        for (TransitionChoice<Kit> kit : classLevel.getSafeListFor(ListKey.KIT_CHOICE)) {
            kit.act(kit.driveChoice(aPC), classLevel, aPC);
        }
        TransitionChoice<Region> region = classLevel.get(ObjectKey.REGION_CHOICE);
        if (region != null) {
            region.act(region.driveChoice(aPC), classLevel, aPC);
        }
    }
    // this is a monster class, so don't worry about experience
    if (isMonster()) {
        return true;
    }
    if (!aPC.isImporting()) {
        CDOMObjectUtilities.checkRemovals(this, aPC);
        final int minxp = aPC.minXPForECL();
        if (aPC.getXP() < minxp) {
            aPC.setXP(minxp);
        } else if (aPC.getXP() >= aPC.minXPForNextECL()) {
            if (!bSilent) {
                ShowMessageDelegate.showMessageDialog(SettingsHandler.getGame().getLevelUpMessage(), Constants.APPLICATION_NAME, MessageType.INFORMATION);
            }
        }
    }
    //
    if (containsKey(ObjectKey.EXCHANGE_LEVEL) && (aPC.getLevel(this) == 1) && !aPC.isImporting()) {
        ExchangeLevelApplication.exchangeLevels(aPC, this);
    }
    return true;
}
Also used : LevelCommandFactory(pcgen.cdom.content.LevelCommandFactory) Region(pcgen.cdom.enumeration.Region) PCLevelInfo(pcgen.core.pclevelinfo.PCLevelInfo) ClassSource(pcgen.cdom.helper.ClassSource) PCClassLevel(pcgen.cdom.inst.PCClassLevel)

Example 28 with PCLevelInfo

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

the class CharacterLevelsFacadeImpl method investSkillPoints.

/**
	 * @see pcgen.core.facade.CharacterLevelsFacade#investSkillPoints(int, pcgen.core.facade.SkillFacade, int)
	 */
@Override
public boolean investSkillPoints(CharacterLevelFacade level, SkillFacade skill, int points) {
    if (points == 0 || level == null || !(level instanceof CharacterLevelFacadeImpl)) {
        Logging.errorPrint("Invalid request to investSkillPoints in " + skill + ". Points: " + points + " level: " + level);
        return false;
    }
    PCLevelInfo classLevel = getLevelInfo(level);
    int skillPool;
    if (Globals.getGameModeHasPointPool()) {
        skillPool = theCharacter.getSkillPoints();
    } else {
        skillPool = classLevel.getSkillPointsRemaining();
        if ((points < 0) && (((skillPool - points) > classLevel.getSkillPointsGained(theCharacter)) || !classHasRanksIn(skill, ((CharacterLevelFacadeImpl) level).getSelectedClass()))) {
            level = findLevelWithSpentSkillPoints(points, skill);
            if (level == null) {
                delegate.showInfoMessage(Constants.APPLICATION_NAME, LanguageBundle.getFormattedString("in_iskErr_message_05", skill));
                return false;
            }
            classLevel = getLevelInfo(level);
            skillPool = classLevel.getSkillPointsRemaining();
        }
    }
    if ((points > 0) && (points > skillPool)) {
        delegate.showInfoMessage(Constants.APPLICATION_NAME, LanguageBundle.getFormattedString("in_iskErr_message_04a", String.valueOf(skillPool)));
        return false;
    }
    SkillCost sc = getSkillCost(level, skill);
    if (sc == null) {
        Logging.errorPrint("Failed to get skillcost for skill " + skill + ". Could not process request to invest " + points + " in the skill");
        return false;
    }
    if (sc.equals(SkillCost.EXCLUSIVE)) {
        delegate.showInfoMessage(Constants.APPLICATION_NAME, LanguageBundle.getString("in_iskErr_message_06"));
        return false;
    }
    final double cost = sc.getCost();
    double rank = points / cost;
    Skill aSkill = (Skill) skill;
    boolean hasSkill = charDisplay.hasSkill(aSkill);
    if (!hasSkill) {
        SkillDisplay.updateSkillsOutputOrder(theCharacter, aSkill);
    }
    final String classKeyName = charDisplay.getLevelInfoClassKeyName(getLevelIndex(level));
    PCClass aClass = theCharacter.getClassKeyed(classKeyName);
    String errMessage = SkillRankControl.modRanks(rank, aClass, false, theCharacter, aSkill);
    if (//$NON-NLS-1$
    "".equals(errMessage)) {
        classLevel.setSkillPointsRemaining(skillPool - points);
    }
    if (ChooseActivation.hasNewChooseToken(aSkill) && characterFacadeImpl != null) {
        characterFacadeImpl.postLevellingUpdates();
    }
    if (!errMessage.isEmpty()) {
        delegate.showInfoMessage(Constants.APPLICATION_NAME, errMessage);
        return false;
    }
    updateSkillsTodo();
    fireSkillPointEvent(this, getLevelIndex(level), false);
    fireSkillBonusEvent(this, getLevelIndex(level), false);
    return true;
}
Also used : Skill(pcgen.core.Skill) SkillCost(pcgen.cdom.enumeration.SkillCost) PCLevelInfo(pcgen.core.pclevelinfo.PCLevelInfo) PCClass(pcgen.core.PCClass)

Example 29 with PCLevelInfo

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

the class CharacterLevelsFacadeImpl method findLevelWithSpentSkillPoints.

/**
	 * Find a level which has a certain number of points spent.
	 * @param points The negative number of points spent required.
	 * @param skill 
	 * @return The level with spent points, or null if none match
	 */
private CharacterLevelFacade findLevelWithSpentSkillPoints(int points, SkillFacade skill) {
    for (int i = charLevels.size() - 1; i >= 0; i--) {
        CharacterLevelFacadeImpl levelFacade = (CharacterLevelFacadeImpl) charLevels.get(i);
        PCLevelInfo levelInfo = getLevelInfo(levelFacade);
        if (levelInfo.getSkillPointsRemaining() - points <= levelInfo.getSkillPointsGained(theCharacter)) {
            if (classHasRanksIn(skill, levelFacade.getSelectedClass())) {
                return levelFacade;
            }
        }
    }
    return null;
}
Also used : PCLevelInfo(pcgen.core.pclevelinfo.PCLevelInfo)

Example 30 with PCLevelInfo

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

the class CharacterLevelsFacadeImpl method setGainedSkillPoints.

/**
	 * @see pcgen.core.facade.CharacterLevelsFacade#setGainedSkillPoints(int, int)
	 */
@Override
public void setGainedSkillPoints(CharacterLevelFacade level, int points) {
    int spentSkillPoints = getSpentSkillPoints(level);
    PCLevelInfo classLevel = getLevelInfo(level);
    classLevel.setSkillPointsGained(theCharacter, points);
    classLevel.setSkillPointsRemaining(points - spentSkillPoints);
    fireSkillPointEvent(this, getLevelIndex(level), false);
}
Also used : PCLevelInfo(pcgen.core.pclevelinfo.PCLevelInfo)

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