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);
}
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();
}
Aggregations