示例#1
0
 @Override
 public void ownBonuses(Object owner) throws CloneNotSupportedException {
   super.ownBonuses(owner);
   for (PCClassLevel pcl : this.getOriginalClassLevelCollection()) {
     pcl.ownBonuses(owner);
   }
 }
示例#2
0
  public static void removeDomainsForLevel(
      PCClass cl, final int removedLevel, final PlayerCharacter aPC) {

    /*
     * Note this uses ALL of the domains up to and including this level,
     * because there is the possibility (albeit strange) that the PC was
     * qualified at a previous level change, but the PlayerCharacter is now
     * not qualified for the given Domain. Even this has quirks, since it is
     * only applied at the time of level increase, but I think that quirk
     * should be resolved by a CDOM system around 6.0 - thpr 10/23/06
     */
    for (QualifiedObject<CDOMSingleRef<Domain>> qo : cl.getSafeListFor(ListKey.DOMAIN)) {
      CDOMSingleRef<Domain> ref = qo.getObject(aPC, cl);
      if (ref == null) {
        ref = qo.getRawObject();
        aPC.removeDomain(ref.resolvesTo());
      }
    }
    for (int i = 0; i <= removedLevel; i++) {
      // TODO This stinks for really high level characters - can this ever
      // get null back?
      PCClassLevel pcl = aPC.getActiveClassLevel(cl, i);
      for (QualifiedObject<CDOMSingleRef<Domain>> qo : pcl.getSafeListFor(ListKey.DOMAIN)) {
        CDOMSingleRef<Domain> ref = qo.getObject(aPC, cl);
        if ((ref == null) || (i == removedLevel)) {
          ref = qo.getRawObject();
          aPC.removeDomain(ref.resolvesTo());
        }
      }
    }
  }
示例#3
0
  public static void addDomainsUpToLevel(PCClass cl, final int aLevel, final PlayerCharacter aPC) {

    // any domains set by level would have already been saved
    // and don't need to be re-set at level up time
    if (aPC.isImporting()) {
      return;
    }

    /*
     * Note this uses ALL of the domains up to and including this level,
     * because there is the possibility (albeit strange) that the PC was not
     * qualified at a previous level change, but the PlayerCharacter is now
     * qualified for the given Domain. Even this has quirks, since it is
     * only applied at the time of level increase, but I think that quirk
     * should be resolved by a CDOM system around 6.0 - thpr 10/23/06
     */
    for (QualifiedObject<CDOMSingleRef<Domain>> qo : cl.getSafeListFor(ListKey.DOMAIN)) {
      CDOMSingleRef<Domain> ref = qo.getObject(aPC, cl);
      if (ref != null) {
        addDomain(aPC, cl, ref.resolvesTo());
      }
    }
    for (int i = 0; i <= aLevel; i++) {
      // TODO This stinks for really high level characters - can this ever
      // get null back?
      PCClassLevel pcl = aPC.getActiveClassLevel(cl, i);
      for (QualifiedObject<CDOMSingleRef<Domain>> qo : pcl.getSafeListFor(ListKey.DOMAIN)) {
        CDOMSingleRef<Domain> ref = qo.getObject(aPC, cl);
        if (ref != null) {
          addDomain(aPC, cl, ref.resolvesTo());
        }
      }
    }
  }
示例#4
0
 public PCClassLevel getOriginalClassLevel(int lvl) {
   if (!levelMap.containsKey(lvl)) {
     PCClassLevel classLevel = new PCClassLevel();
     classLevel.put(IntegerKey.LEVEL, lvl);
     classLevel.setName(getDisplayName() + "(" + lvl + ")");
     classLevel.put(StringKey.QUALIFIED_KEY, getQualifiedKey());
     classLevel.put(ObjectKey.SOURCE_CAMPAIGN, get(ObjectKey.SOURCE_CAMPAIGN));
     classLevel.put(StringKey.SOURCE_PAGE, get(StringKey.SOURCE_PAGE));
     classLevel.put(StringKey.SOURCE_LONG, get(StringKey.SOURCE_LONG));
     classLevel.put(StringKey.SOURCE_SHORT, get(StringKey.SOURCE_SHORT));
     classLevel.put(StringKey.SOURCE_WEB, get(StringKey.SOURCE_WEB));
     classLevel.put(ObjectKey.SOURCE_DATE, get(ObjectKey.SOURCE_DATE));
     classLevel.put(ObjectKey.TOKEN_PARENT, this);
     levelMap.put(lvl, classLevel);
   }
   return levelMap.get(lvl);
 }
示例#5
0
 public int getSkillPointsForLevel(
     final PlayerCharacter aPC, PCClassLevel classLevel, int characterLevel) {
   // Update Skill Points. Modified 20 Nov 2002 by sage_sam
   // for bug #629643
   // final int spMod;
   int spMod = aPC.recalcSkillPointMod(this, characterLevel);
   if (classLevel.get(ObjectKey.DONTADD_SKILLPOINTS) != null) {
     spMod = 0;
   }
   return spMod;
 }
示例#6
0
 @Override
 public ParseResult parseToken(LoadContext context, PCClassLevel obj, String value) {
   if (ONE.equals(obj.get(IntegerKey.LEVEL))) {
     PCClass parent = (PCClass) obj.get(ObjectKey.TOKEN_PARENT);
     if (parent instanceof SubClass || parent instanceof SubstitutionClass) {
       return new ParseResult.Fail(
           "Data used token: "
               + value
               + " which is a Class token, "
               + "but it was used in a class level for a "
               + parent.getClass().getSimpleName(),
           context);
     }
     return wrappedToken.parseToken(context, parent, value);
   }
   return new ParseResult.Fail(
       "Data used token: "
           + value
           + " which is a Class token, "
           + "but it was used in a class level line other than level 1",
       context);
 }
示例#7
0
  /*
   * 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));
    }

    // Don't roll the hit points if the gui is not being used.
    // This is so GMGen can add classes to a person without pcgen flipping
    // 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;

    // Add any bonus feats or stats that will be gained from this level
    // 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()) {
        // We do not want to do these
        // calculations a second time when are
        // importing a character. The feat
        // number and the stat point pool are
        // already saved in the import file.

        // if (processBonusFeats) {
        //	final double bonusFeats = aPC.getBonusFeatsForNewLevel(this);
        //	if (bonusFeats > 0) {
        //		aPC.adjustFeats(bonusFeats);
        //	}
        // }

        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()) {
      //
      // Ask for stat increase after skill points have been calculated
      //
      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);
        }
      }
    }

    //
    // Allow exchange of classes only when assign 1st level
    //
    if (containsKey(ObjectKey.EXCHANGE_LEVEL) && (aPC.getLevel(this) == 1) && !aPC.isImporting()) {
      ExchangeLevelApplication.exchangeLevels(aPC, this);
    }
    return true;
  }
示例#8
0
 public void copyLevelsFrom(PCClass cl) {
   for (Map.Entry<Integer, PCClassLevel> me : cl.levelMap.entrySet()) {
     try {
       PCClassLevel lvl = me.getValue().clone();
       lvl.put(StringKey.QUALIFIED_KEY, getQualifiedKey());
       lvl.put(ObjectKey.SOURCE_CAMPAIGN, get(ObjectKey.SOURCE_CAMPAIGN));
       lvl.put(StringKey.SOURCE_PAGE, get(StringKey.SOURCE_PAGE));
       lvl.put(StringKey.SOURCE_LONG, get(StringKey.SOURCE_LONG));
       lvl.put(StringKey.SOURCE_SHORT, get(StringKey.SOURCE_SHORT));
       lvl.put(StringKey.SOURCE_WEB, get(StringKey.SOURCE_WEB));
       lvl.put(ObjectKey.SOURCE_DATE, get(ObjectKey.SOURCE_DATE));
       lvl.put(ObjectKey.TOKEN_PARENT, this);
       lvl.setName(getDisplayName() + "(" + lvl.get(IntegerKey.LEVEL) + ")");
       lvl.ownBonuses(this);
       levelMap.put(me.getKey(), lvl);
     } catch (CloneNotSupportedException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
     }
   }
 }