public static String getSituationModifierExplanation( Skill sk, String situation, PlayerCharacter aPC, boolean shortForm) { List<String> explanation = new ArrayList<>(); String keyName = sk.getKeyName(); String bonusKey = ("SITUATION." + keyName + "=" + situation).toUpperCase(); for (BonusObj bonus : aPC.getActiveBonusList()) { // calculate bonus and add to activeBonusMap if (aPC.isApplied(bonus) && "SITUATION".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)); } } } } return StringUtil.join(explanation, " "); }
/** * 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"); // these next two if-blocks try to get BONUS:[C]CSKILL|TYPE=xxx|y to // 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(); }