Exemple #1
0
  @Override
  public Float resolve(PlayerCharacter pc) {

    if (source.length() == 0) {
      return 0.0f;
    }

    return (float) pc.getTotalBonusTo("PCLEVEL", source);
  }
  /**
   * 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();
  }
  /* (non-Javadoc)
   * @see pcgen.core.facade.SpellSupportFacade#getClassInfo(pcgen.core.facade.ClassFacade)
   */
  @Override
  public String getClassInfo(ClassFacade spellcaster) {
    if (!(spellcaster instanceof PCClass)) {
      return "";
    }
    PCClass aClass = (PCClass) spellcaster;
    SpellSupportForPCClass spellSupport = pc.getSpellSupport(aClass);
    int highestSpellLevel = spellSupport.getHighestLevelSpell(pc);

    final HtmlInfoBuilder b = new HtmlInfoBuilder();
    b.append("<table border=1><tr><td><font size=-2><b>"); // $NON-NLS-1$
    b.append(OutputNameFormatting.piString(aClass, false)).append(" ["); // $NON-NLS-1$
    b.append(
        String.valueOf(
            charDisplay.getLevel(aClass)
                + (int) pc.getTotalBonusTo("PCLEVEL", aClass.getKeyName()))); // $NON-NLS-1$
    b.append("]</b></font></td>"); // $NON-NLS-1$

    for (int i = 0; i <= highestSpellLevel; ++i) {
      b.append("<td><font size=-2><b><center>&nbsp;"); // $NON-NLS-1$
      b.append(String.valueOf(i));
      b.append("&nbsp;</b></center></font></td>"); // $NON-NLS-1$
    }

    b.append("</tr>"); // $NON-NLS-1$
    b.append("<tr><td><font size=-1><b>Cast</b></font></td>"); // $NON-NLS-1$

    for (int i = 0; i <= highestSpellLevel; ++i) {
      b.append("<td><font size=-1><center>"); // $NON-NLS-1$
      b.append(getNumCast(aClass, i, pc));
      b.append("</center></font></td>"); // $NON-NLS-1$
    }
    b.append("</tr>"); // $NON-NLS-1$

    // Making sure KnownList can be handled safely and produces the correct behaviour
    if (spellSupport.hasKnownList() || spellSupport.hasKnownSpells(pc)) {
      b.append("<tr><td><font size=-1><b>Known</b></font></td>"); // $NON-NLS-1$

      for (int i = 0; i <= highestSpellLevel; ++i) {
        final int a = spellSupport.getKnownForLevel(i, pc);
        final int bonus = spellSupport.getSpecialtyKnownForLevel(i, pc);

        b.append("<td><font size=-1><center>"); // $NON-NLS-1$
        b.append(String.valueOf(a));
        if (bonus > 0) {
          b.append('+').append(Integer.toString(bonus));
        }
        b.append("</center></font></td>"); // $NON-NLS-1$
      }
      b.append("</tr>"); // $NON-NLS-1$
    }

    b.append("<tr><td><font size=-1><b>DC</b></font></td>"); // $NON-NLS-1$

    for (int i = 0; i <= highestSpellLevel; ++i) {
      b.append("<td><font size=-1><center>"); // $NON-NLS-1$
      b.append(String.valueOf(getDC(aClass, i, pc)));
      b.append("</center></font></td>"); // $NON-NLS-1$
    }

    b.append("</tr></table>"); // $NON-NLS-1$

    b.appendI18nElement("InfoSpells.caster.type", aClass.getSpellType()); // $NON-NLS-1$
    b.appendLineBreak();
    b.appendI18nElement("InfoSpells.stat.bonus", aClass.getSpellBaseStat()); // $NON-NLS-1$

    if (pc.hasAssocs(aClass, AssociationKey.SPECIALTY) || charDisplay.hasDomains()) {
      boolean needComma = false;
      StringBuilder schoolInfo = new StringBuilder();
      String spec = pc.getAssoc(aClass, AssociationKey.SPECIALTY);
      if (spec != null) {
        schoolInfo.append(spec);
        needComma = true;
      }

      for (Domain d : charDisplay.getSortedDomainSet()) {
        if (needComma) {
          schoolInfo.append(',');
        }
        needComma = true;
        schoolInfo.append(d.getKeyName());
      }
      b.appendLineBreak();
      b.appendI18nElement("InfoSpells.school", schoolInfo.toString()); // $NON-NLS-1$
    }

    Set<String> set = new TreeSet<>();
    for (SpellProhibitor sp : aClass.getSafeListFor(ListKey.PROHIBITED_SPELLS)) {
      set.addAll(sp.getValueList());
    }

    Collection<? extends SpellProhibitor> prohibList = charDisplay.getProhibitedSchools(aClass);
    if (prohibList != null) {
      for (SpellProhibitor sp : prohibList) {
        set.addAll(sp.getValueList());
      }
    }
    if (!set.isEmpty()) {
      b.appendLineBreak();
      b.appendI18nElement(
          "InfoSpells.prohibited.school", //$NON-NLS-1$
          StringUtil.join(set, ",")); // $NON-NLS-1$
    }

    String bString = SourceFormat.getFormattedString(aClass, Globals.getSourceDisplay(), true);
    if (bString.length() > 0) {
      b.appendLineBreak();
      b.appendI18nElement("in_source", bString); // $NON-NLS-1$
    }

    return b.toString();
  }