Search in sources :

Example 6 with BonusPair

use of pcgen.core.bonus.BonusPair in project pcgen by PCGen.

the class BonusManager method processBonus.

/**
	 * - Get's a list of dependencies from aBonus - Finds all active bonuses
	 * that add to those dependencies and have not been processed and
	 * recursively calls itself - Once recursed in, it adds the computed bonus
	 * to activeBonusMap
	 * 
	 * @param aBonus
	 *            The bonus to be processed.
	 * @param prevProcessed
	 *            The list of bonuses which have already been processed in this
	 *            stack of calls to processBonus.
	 * @param processedBonuses
	 *            The list of bonuses which have already been processed overall.
	 * @param nonStackMap
	 *            The map of non-stacking (i.e. highest wins) bonuses being built up.
	 * @param stackMap
	 *            The map of stacking (i.e. total all) bonuses being built up.
	 */
private void processBonus(final BonusObj aBonus, final Set<BonusObj> prevProcessed, Set<BonusObj> processedBonuses, Map<String, String> nonStackMap, Map<String, String> stackMap) {
    // coding or best guess dependancy mapping
    if (prevProcessed.contains(aBonus)) {
        if (Logging.isDebugMode()) {
            Logging.log(Logging.DEBUG, //$NON-NLS-1$
            "Ignoring bonus loop for " + aBonus + //$NON-NLS-1$
            " as it was already processed. Bonuses already processed: " + prevProcessed);
            Logging.log(Logging.DEBUG, //$NON-NLS-1$
            " Depend map is " + aBonus.listDependsMap());
        }
        return;
    }
    prevProcessed.add(aBonus);
    final List<BonusObj> aList = new ArrayList<>();
    // aBonus's dependencies and have not already been processed
    for (BonusObj newBonus : getActiveBonusList()) {
        if (processedBonuses.contains(newBonus)) {
            continue;
        }
        if (aBonus.getDependsOn(newBonus.getUnparsedBonusInfoList()) || aBonus.getDependsOnBonusName(newBonus.getBonusName())) {
            aList.add(newBonus);
        }
    }
    // and process them first
    for (BonusObj newBonus : aList) {
        // Recursively call itself
        processBonus(newBonus, prevProcessed, processedBonuses, nonStackMap, stackMap);
    }
    // Double check that it hasn't been processed yet
    if (processedBonuses.contains(aBonus)) {
        return;
    }
    // Add to processed list
    //Logging.log(Logging.INFO, "Processing bonus " + aBonus + " depends on " + aBonus.listDependsMap());
    processedBonuses.add(aBonus);
    final CDOMObject anObj = (CDOMObject) getSourceObject(aBonus);
    if (anObj == null) {
        prevProcessed.remove(aBonus);
        return;
    }
    // calculate bonus and add to activeBonusMap
    for (BonusPair bp : getStringListFromBonus(aBonus)) {
        final double iBonus = bp.resolve(pc).doubleValue();
        setActiveBonusStack(iBonus, bp.fullyQualifiedBonusType, nonStackMap, stackMap);
        totalBonusesForType(nonStackMap, stackMap, bp.fullyQualifiedBonusType, activeBonusMap);
    //			Logging.debugPrint("vBONUS: " + anObj.getDisplayName() + " : "
    //					+ iBonus + " : " + bp.fullyQualifiedBonusType);
    }
    prevProcessed.remove(aBonus);
}
Also used : BonusObj(pcgen.core.bonus.BonusObj) CDOMObject(pcgen.cdom.base.CDOMObject) ArrayList(java.util.ArrayList) BonusPair(pcgen.core.bonus.BonusPair)

Example 7 with BonusPair

use of pcgen.core.bonus.BonusPair in project pcgen by PCGen.

the class SkillCostDisplay method getModifierExplanation.

/**
	 * Builds up a string describing what makes up the misc modifier for a skill
	 * for a character. This can either be in long form '+2[skill TUMBLE gteq
	 * 5|TYPE=SYNERGY.STACK]' or in short form '+2[TUMBLE]'. Any modifiers that
	 * cannot be determined will be displayed as a single entry of 'OTHER'.
	 * 
	 * @param aPC
	 *            The character associated with this skill.
	 * @param shortForm
	 *            True if the abbreviated form should be used.
	 * @return The explanation of the misc modifier's make-up.
	 */
public static String getModifierExplanation(Skill sk, PlayerCharacter aPC, boolean shortForm) {
    double bonusObjTotal = 0.0;
    List<String> explanation = new ArrayList<>();
    String keyName = sk.getKeyName();
    String bonusKey = ("SKILL." + keyName).toUpperCase();
    for (BonusObj bonus : aPC.getActiveBonusList()) {
        // calculate bonus and add to activeBonusMap
        if (aPC.isApplied(bonus) && "SKILL".equals(bonus.getBonusName())) {
            boolean include = bonusForThisSkill(bonus, keyName);
            if (!include) {
                for (BonusPair bp : aPC.getStringListFromBonus(bonus)) {
                    String bpKey = bp.fullyQualifiedBonusType.toUpperCase();
                    if (bpKey.equals(bonusKey)) {
                        include = true;
                        break;
                    }
                }
            }
            if (include) {
                double iBonus = 0;
                for (BonusPair bp : aPC.getStringListFromBonus(bonus)) {
                    String bpKey = bp.fullyQualifiedBonusType.toUpperCase();
                    if (bpKey.startsWith(bonusKey)) {
                        iBonus += bp.resolve(aPC).doubleValue();
                    }
                }
                if (!CoreUtility.doublesEqual(iBonus, 0.0)) {
                    explanation.add(Delta.toString((int) iBonus) + aPC.getBonusContext(bonus, shortForm));
                    bonusObjTotal += iBonus;
                }
            }
        }
    }
    StringBuilder bonusDetails = new StringBuilder();
    bonusDetails.append(StringUtil.joinToStringBuilder(explanation, " "));
    // TODO: Need to add other bonuses which are not encoded as bonus
    // objects
    // - familiars, racial, feats - and add them to bonusObjTotal
    double bonus;
    CDOMSingleRef<PCStat> statref = sk.get(ObjectKey.KEY_STAT);
    if (statref != null) {
        PCStat stat = statref.get();
        bonus = aPC.getStatModFor(stat);
        bonus += aPC.getTotalBonusTo("SKILL", "STAT." + stat.getKeyName());
        SkillCostDisplay.appendBonusDesc(bonusDetails, bonus, "STAT");
    }
    // The catch-all for non-bonusObj modifiers.
    bonus = aPC.getTotalBonusTo("SKILL", keyName) - bonusObjTotal;
    SkillCostDisplay.appendBonusDesc(bonusDetails, bonus, "OTHER");
    // loop through all current skill types checking for boni
    for (Type singleType : sk.getTrueTypeList(false)) {
        bonus = aPC.getTotalBonusTo("SKILL", "TYPE." + singleType);
        SkillCostDisplay.appendBonusDesc(bonusDetails, bonus, "TYPE." + singleType);
    }
    // now check for any lists of skills, etc
    bonus = aPC.getTotalBonusTo("SKILL", "LIST");
    SkillCostDisplay.appendBonusDesc(bonusDetails, bonus, "LIST");
    // now check for ALL
    bonus = aPC.getTotalBonusTo("SKILL", "ALL");
    SkillCostDisplay.appendBonusDesc(bonusDetails, bonus, "ALL");
    // function
    if (aPC.isClassSkill(sk)) {
        bonus = aPC.getTotalBonusTo("CSKILL", keyName);
        SkillCostDisplay.appendBonusDesc(bonusDetails, bonus, "CSKILL");
        // loop through all current skill types checking for boni
        for (Type singleType : sk.getTrueTypeList(false)) {
            bonus = aPC.getTotalBonusTo("CSKILL", "TYPE." + singleType);
            SkillCostDisplay.appendBonusDesc(bonusDetails, bonus, "CSKILL");
        }
        bonus = aPC.getTotalBonusTo("CSKILL", "LIST");
        SkillCostDisplay.appendBonusDesc(bonusDetails, bonus, "CSKILL");
    }
    if (!aPC.isClassSkill(sk) && !sk.getSafe(ObjectKey.EXCLUSIVE)) {
        bonus = aPC.getTotalBonusTo("CCSKILL", keyName);
        SkillCostDisplay.appendBonusDesc(bonusDetails, bonus, "CCSKILL");
        // loop through all current skill types checking for boni
        for (Type singleType : sk.getTrueTypeList(false)) {
            bonus = aPC.getTotalBonusTo("CCSKILL", "TYPE." + singleType);
            SkillCostDisplay.appendBonusDesc(bonusDetails, bonus, "CCSKILL");
        }
        bonus = aPC.getTotalBonusTo("CCSKILL", "LIST");
        SkillCostDisplay.appendBonusDesc(bonusDetails, bonus, "CCSKILL");
    }
    // Encumbrance
    int aCheckMod = sk.getSafe(ObjectKey.ARMOR_CHECK).calculateBonus(aPC);
    SkillCostDisplay.appendBonusDesc(bonusDetails, aCheckMod, "ARMOR");
    String aString = SettingsHandler.getGame().getRankModFormula();
    if (!aString.isEmpty()) {
        aString = aString.replaceAll(Pattern.quote("$$RANK$$"), SkillRankControl.getTotalRank(aPC, sk).toString());
        bonus = aPC.getVariableValue(aString, "").intValue();
        SkillCostDisplay.appendBonusDesc(bonusDetails, bonus, "RANKS");
    }
    return bonusDetails.toString();
}
Also used : Type(pcgen.cdom.enumeration.Type) BonusObj(pcgen.core.bonus.BonusObj) ArrayList(java.util.ArrayList) BonusPair(pcgen.core.bonus.BonusPair) PCStat(pcgen.core.PCStat)

Aggregations

ArrayList (java.util.ArrayList)7 BonusPair (pcgen.core.bonus.BonusPair)7 BonusObj (pcgen.core.bonus.BonusObj)6 CDOMObject (pcgen.cdom.base.CDOMObject)4 MissingObject (pcgen.core.bonus.util.MissingObject)3 IdentityHashMap (java.util.IdentityHashMap)2 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)2 HashMap (java.util.HashMap)1 List (java.util.List)1 Formula (pcgen.base.formula.Formula)1 WrappedMapSet (pcgen.base.util.WrappedMapSet)1 Type (pcgen.cdom.enumeration.Type)1 PCStat (pcgen.core.PCStat)1 PlayerCharacter (pcgen.core.PlayerCharacter)1