use of pcgen.core.pclevelinfo.PCLevelInfo in project pcgen by PCGen.
the class SkillRankControl method removeSkillsForTopLevel.
/**
* Adjust the character's skills to reflect the loss of a level. This is
* done by:
* <ol>
* <li>Removing ranks from any skills with max ranks or more</li>
* <li>Taking any skill points still needing to be refunded off the remainder
* for the next highest level of the class</li>
* <li>or taking them off the remainder for the highest class level.</li>
* </ol>
*
* @param pc The character being updated.
* @param classBeingLevelledDown The class we are removing a level of.
* @param currentLevel The character;s level before the removal.
* @param pointsToRemove The number of points that need to be refunded.
*/
public static void removeSkillsForTopLevel(PlayerCharacter pc, PCClass classBeingLevelledDown, int currentLevel, int pointsToRemove) {
double remaining = pointsToRemove;
if (remaining <= 0.0) {
return;
}
// Remove a rank from each skill with max ranks at the old level (now above max ranks)
for (Skill skill : pc.getSkillSet()) {
if (!skill.getSafe(ObjectKey.VISIBILITY).isVisibleTo(View.VISIBLE_DISPLAY)) {
continue;
}
PCClass aClass = pc.getClassList().isEmpty() ? null : pc.getClassList().get(0);
double maxRanks = pc.getMaxRank(skill, aClass).doubleValue();
double rankMod = maxRanks - getTotalRank(pc, skill);
if (rankMod < 0) {
if (Logging.isLoggable(Logging.INFO)) {
Logging.log(Logging.INFO, "Removing " + (rankMod * -1) + " ranks from " + skill);
}
String err = modRanks(rankMod, classBeingLevelledDown, true, pc, skill);
if (StringUtils.isBlank(err)) {
remaining += rankMod;
if (remaining <= 0) {
break;
}
}
}
}
// Deal with any remaining skill points to be refunded
if (remaining != 0.0) {
// If there are other levels left of the class being removed,
// subtract the remainder from the remaining value of the next
// highest level of the class removed.
PCLevelInfo targetLevel = null;
int level = currentLevel - 1;
while (level > 0) {
PCLevelInfo pcLI = pc.getLevelInfo(level - 1);
if (pcLI.getClassKeyName().equals(classBeingLevelledDown.getKeyName())) {
targetLevel = pcLI;
break;
}
level--;
}
if (targetLevel == null && currentLevel > 0) {
// Otherwise subtract the remainder from the remaining value of
// the character's highest remaining level.
targetLevel = pc.getLevelInfo(currentLevel - 2);
}
if (targetLevel != null) {
targetLevel.setSkillPointsRemaining(targetLevel.getSkillPointsRemaining() - (int) remaining);
}
}
}
use of pcgen.core.pclevelinfo.PCLevelInfo in project pcgen by PCGen.
the class PCGVer2Parser method parseClassAbilitiesLevelLine.
private void parseClassAbilitiesLevelLine(final String line, final List<PCLevelInfo> pcLevelInfoList) {
final PCGTokenizer tokens;
try {
tokens = new PCGTokenizer(line);
} catch (PCGParseException pcgpex) {
final String message = LanguageBundle.getFormattedString(//$NON-NLS-1$
"Warnings.PCGenParser.IllegalClassAbility", line, pcgpex.getMessage());
warnings.add(message);
return;
}
int level = -1;
PCClass aPCClass = null;
PCGElement element;
PCLevelInfo pcl = null;
final Iterator<PCGElement> it = tokens.getElements().iterator();
// eg: Cleric=4
if (it.hasNext()) {
element = it.next();
final int index = element.getText().indexOf('=');
if (index < 0) {
final String message = LanguageBundle.getFormattedString(//$NON-NLS-1$
"Warnings.PCGenParser.InvalidClassLevel", element.getText());
warnings.add(message);
return;
}
final String classKeyName = EntityEncoder.decode(element.getText().substring(0, index));
aPCClass = thePC.getClassKeyed(classKeyName);
if (aPCClass == null) {
final String message = LanguageBundle.getFormattedString(//$NON-NLS-1$
"Warnings.PCGenParser.ClassNotFound", classKeyName);
warnings.add(message);
return;
}
try {
level = Integer.parseInt(element.getText().substring(index + 1));
} catch (NumberFormatException nfe) {
final String message = LanguageBundle.getFormattedString(//$NON-NLS-1$
"Warnings.PCGenParser.InvalidClassLevel", element.getText());
warnings.add(message);
return;
}
if (level < 1) {
final String message = LanguageBundle.getFormattedString(//$NON-NLS-1$
"Warnings.PCGenParser.InvalidClassLevel", element.getText());
warnings.add(message);
return;
}
for (PCLevelInfo info : pcLevelInfoList) {
if (classKeyName.equalsIgnoreCase(info.getClassKeyName()) && level == info.getClassLevel()) {
pcl = info;
break;
}
}
if (pcl == null) {
pcl = thePC.addLevelInfo(classKeyName);
pcl.setClassLevel(level);
} else {
thePC.addLevelInfo(pcl);
}
pcl.setSkillPointsRemaining(0);
}
while (it.hasNext()) {
element = it.next();
String tag = element.getName();
if (IOConstants.TAG_SUBSTITUTIONLEVEL.equals(tag)) {
final String substitutionClassKeyName = EntityEncoder.decode(element.getText());
SubstitutionClass aSubstitutionClass = aPCClass.getSubstitutionClassKeyed(substitutionClassKeyName);
if (aSubstitutionClass == null) {
final String message = LanguageBundle.getFormattedString(//$NON-NLS-1$
"Warnings.PCGenParser.ClassNotFound", substitutionClassKeyName);
warnings.add(message);
return;
}
SubstitutionLevelSupport.applyLevelArrayModsToLevel(aSubstitutionClass, aPCClass, level, thePC);
thePC.setSubstitutionClassName(thePC.getActiveClassLevel(aPCClass, level), substitutionClassKeyName);
} else if (IOConstants.TAG_HITPOINTS.equals(tag)) {
try {
PCClassLevel classLevel = thePC.getActiveClassLevel(aPCClass, level - 1);
thePC.setHP(classLevel, Integer.valueOf(element.getText()));
} catch (NumberFormatException nfe) {
final String message = LanguageBundle.getFormattedString(//$NON-NLS-1$
"Warnings.PCGenParser.InvalidHP", tag, element.getText());
warnings.add(message);
}
} else if (IOConstants.TAG_SAVES.equals(tag)) {
for (final PCGElement child : element.getChildren()) {
final String dString = EntityEncoder.decode(child.getText());
if (dString.startsWith(IOConstants.TAG_BONUS + IOConstants.TAG_SEPARATOR)) {
String bonusString = dString.substring(6);
int pipeLoc = bonusString.indexOf('|');
if (pipeLoc != -1) {
CDOMObject target = aPCClass;
String potentialInt = bonusString.substring(0, pipeLoc);
try {
int bonusLevel = Integer.parseInt(potentialInt);
if (bonusLevel > 0) {
target = thePC.getActiveClassLevel(aPCClass, bonusLevel);
}
bonusString = bonusString.substring(pipeLoc + 1);
} catch (NumberFormatException e) {
//OK (no level embedded in file)
if (level > 0) {
target = thePC.getActiveClassLevel(aPCClass, level);
}
}
BonusAddition.applyBonus(bonusString, "", thePC, target);
}
}
}
} else if (IOConstants.TAG_SPECIALTIES.equals(tag)) {
for (final PCGElement child : element.getChildren()) {
thePC.setAssoc(aPCClass, AssociationKey.SPECIALTY, EntityEncoder.decode(child.getText()));
}
} else if (IOConstants.TAG_SPECIALABILITIES.equals(tag)) {
for (PCGElement child : element.getChildren()) {
String specialAbilityName = EntityEncoder.decode(child.getText());
if (pcgenVersion[0] <= 5 && pcgenVersion[1] <= 5 && pcgenVersion[2] < 6) {
if (//$NON-NLS-1$
specialAbilityName.equals("Turn Undead")) {
//$NON-NLS-1$
parseFeatLine("FEAT:Turn Undead|TYPE:SPECIAL.TURNUNDEAD|DESC:");
continue;
} else if (//$NON-NLS-1$
specialAbilityName.equals("Rebuke Undead")) {
//$NON-NLS-1$
parseFeatLine("FEAT:Rebuke Undead|TYPE:SPECIAL.TURNUNDEAD|DESC:");
continue;
}
}
SpecialAbility specialAbility = new SpecialAbility(specialAbilityName);
CDOMObject target = aPCClass;
if (level > 0) {
target = thePC.getActiveClassLevel(aPCClass, level);
}
if (!thePC.hasSpecialAbility(specialAbilityName)) {
thePC.addUserSpecialAbility(specialAbility, target);
}
}
} else if (tag.equals(IOConstants.TAG_LEVELABILITY)) {
parseLevelAbilityInfo(element, aPCClass, level);
} else if (tag.equals(IOConstants.TAG_ADDTOKEN)) {
parseAddTokenInfo(element, thePC.getActiveClassLevel(aPCClass, level));
} else //
if (tag.equals(IOConstants.TAG_PRESTAT) || tag.equals(IOConstants.TAG_POSTSTAT)) {
boolean isPre = false;
if (tag.equals(IOConstants.TAG_PRESTAT)) {
isPre = true;
}
final int idx = element.getText().indexOf('=');
if (idx > 0) {
String statAbb = element.getText().substring(0, idx);
final PCStat pcstat = Globals.getContext().getReferenceContext().silentlyGetConstructedCDOMObject(PCStat.class, statAbb);
if (pcstat != null) {
try {
thePC.saveStatIncrease(pcstat, Integer.parseInt(element.getText().substring(idx + 1)), isPre);
} catch (NumberFormatException nfe) {
final String msg = LanguageBundle.getFormattedString(//$NON-NLS-1$
"Warnings.PCGenParser.InvalidStatMod", tag, element.getText());
warnings.add(msg);
}
} else {
final String msg = LanguageBundle.getFormattedString(//$NON-NLS-1$
"Warnings.PCGenParser.UnknownStat", tag, element.getText());
warnings.add(msg);
}
} else {
final String msg = LanguageBundle.getFormattedString(//$NON-NLS-1$
"Warnings.PCGenParser.MissingEquals", tag, element.getText());
warnings.add(msg);
}
} else if ((pcl != null) && IOConstants.TAG_SKILLPOINTSGAINED.equals(tag)) {
pcl.setFixedSkillPointsGained(Integer.parseInt(element.getText()));
} else if ((pcl != null) && IOConstants.TAG_SKILLPOINTSREMAINING.equals(tag)) {
pcl.setSkillPointsRemaining(Integer.parseInt(element.getText()));
} else if (IOConstants.TAG_DATA.equals(tag)) {
// TODO
// for now it's ok to ignore it!
} else {
final String msg = LanguageBundle.getFormattedString(//$NON-NLS-1$
"Warnings.PCGenParser.UnknownTag", tag, element.getText());
warnings.add(msg);
}
}
// TODO:
// process data
//
// need to add some consistency checks here to avoid
// - duplicate entries for one and the same class/level pair
// - missing entries for a given class/level pair
}
use of pcgen.core.pclevelinfo.PCLevelInfo in project pcgen by PCGen.
the class KitStat method recalculateSkillPoints.
private void recalculateSkillPoints(PlayerCharacter aPC) {
final Collection<PCClass> classes = aPC.getClassSet();
aPC.calcActiveBonuses();
if (classes != null && !classes.isEmpty()) {
for (PCClass pcClass : classes) {
aPC.setSkillPool(pcClass, 0);
// We don't limit this to MOD_TO_SKILLS classes as they may manually include the INT bonus in the skills.
for (int j = 0; j < aPC.getLevelInfoSize(); j++) {
final PCLevelInfo pcl = aPC.getLevelInfo(j);
if (pcl.getClassKeyName().equals(pcClass.getKeyName())) {
final int spMod = aPC.recalcSkillPointMod(pcClass, j + 1);
int alreadySpent = pcl.getSkillPointsGained(aPC) - pcl.getSkillPointsRemaining();
pcl.setSkillPointsGained(aPC, spMod);
pcl.setSkillPointsRemaining(pcl.getSkillPointsGained(aPC) - alreadySpent);
Integer currentPool = aPC.getSkillPool(pcClass);
int newSkillPool = (currentPool == null ? 0 : currentPool) + spMod;
aPC.setSkillPool(pcClass, newSkillPool);
}
}
}
}
}
Aggregations