use of pcgen.core.pclevelinfo.PCLevelInfo in project pcgen by PCGen.
the class PlayerCharacterTest method testCheckSkillModChangeWithBonus.
/**
* Validate the checkSkillModChange correctly handles SKILLPOOL bonuses
*/
public void testCheckSkillModChangeWithBonus() {
readyToRun();
PlayerCharacter character = getCharacter();
character.setRace(human);
character.setStat(intel, 10);
PCTemplate template = TestHelper.makeTemplate("grantsskills");
LoadContext context = Globals.getContext();
final BonusObj skillBonusLvl1 = Bonus.newBonus(context, "SKILLPOOL|CLASS=MyClass;LEVEL=1|2");
assertNotNull("Failed to create bonus", skillBonusLvl1);
template.addToListFor(ListKey.BONUS, skillBonusLvl1);
character.addTemplate(template);
character.incrementClassLevel(2, pcClass, true);
List<PCLevelInfo> levelInfoList = new ArrayList<>(character.getLevelInfo());
assertEquals("Level number lvl 1", 1, levelInfoList.get(0).getClassLevel());
assertEquals("Level number lvl 2", 2, levelInfoList.get(1).getClassLevel());
assertEquals("Skills gained lvl 1", 3, levelInfoList.get(0).getSkillPointsGained(character));
assertEquals("Skills remaining lvl 1", 3, levelInfoList.get(0).getSkillPointsRemaining());
assertEquals("Skills gained lvl 2", 1, levelInfoList.get(1).getSkillPointsGained(character));
assertEquals("Skills remaining lvl 2", 1, levelInfoList.get(1).getSkillPointsRemaining());
character.checkSkillModChange();
character.checkSkillModChange();
assertEquals("Skills gained lvl 1", 3, levelInfoList.get(0).getSkillPointsGained(character));
assertEquals("Skills remaining lvl 1", 3, levelInfoList.get(0).getSkillPointsRemaining());
assertEquals("Skills gained lvl 2", 1, levelInfoList.get(1).getSkillPointsGained(character));
assertEquals("Skills remaining lvl 2", 1, levelInfoList.get(1).getSkillPointsRemaining());
}
use of pcgen.core.pclevelinfo.PCLevelInfo in project pcgen by PCGen.
the class CharacterLevelsFacadeImplTest method testFindNextLevelForSkillCrossClass2Points.
/**
* Test method for {@link pcgen.gui2.facade.CharacterLevelsFacadeImpl#findNextLevelForSkill(pcgen.core.facade.SkillFacade, pcgen.core.facade.CharacterLevelFacade, float)}
* to check level selection where cross-class skills cost 2 points and class
* skills cost only 1.
*/
@Test
public void testFindNextLevelForSkillCrossClass2Points() {
// Set game mode skill cost to be double for cross-class
setGameSkillRankData(true);
PlayerCharacter pc = getCharacter();
pc.incrementClassLevel(4, fighterClass);
pc.incrementClassLevel(4, wizardClass);
pc.incrementClassLevel(3, fighterClass);
pc.incrementClassLevel(3, wizardClass);
pc.incrementClassLevel(3, fighterClass);
pc.incrementClassLevel(3, wizardClass);
assertTrue("Climb should be class for fighter", pc.isClassSkill(fighterClass, climbSkill));
assertFalse("Spellcraft should not be class for fighter", pc.isClassSkill(fighterClass, spellcraftSkill));
assertTrue("UMD should be class for fighter", pc.isClassSkill(fighterClass, umdSkill));
assertFalse("Climb should not be class for wizard", pc.isClassSkill(wizardClass, climbSkill));
assertTrue("Spellcraft should be class for wizard", pc.isClassSkill(wizardClass, spellcraftSkill));
assertFalse("UMD should be class for wizard", pc.isClassSkill(wizardClass, umdSkill));
CharacterLevelsFacadeImpl charLvlsFI = new CharacterLevelsFacadeImpl(pc, delegate, todoManager, dataSetFacade, null);
// Rules for finding the next level to spend a point:
// 1. Selected level, if points available and not exceeding max ranks.
assertEquals("Level for 1 rank spellcraft", charLvlsFI.getElementAt(2), charLvlsFI.findNextLevelForSkill(spellcraftSkill, charLvlsFI.getElementAt(2), 1.0f));
assertEquals("Level for 7 ranks climb", charLvlsFI.getElementAt(3), charLvlsFI.findNextLevelForSkill(climbSkill, charLvlsFI.getElementAt(3), 7.0f));
assertEquals("Level for 7.5 ranks climb", charLvlsFI.getElementAt(4), charLvlsFI.findNextLevelForSkill(climbSkill, charLvlsFI.getElementAt(4), 7.5f));
// 2. Scan forward from selected level for first level with points spare
// where the rank is not above max rank for the level and the cost is
// equal to class cost
assertEquals("Level for 3 ranks spellcraft", charLvlsFI.getElementAt(4), charLvlsFI.findNextLevelForSkill(spellcraftSkill, charLvlsFI.getElementAt(1), 3.0f));
assertEquals("Level for 9 ranks spellcraft", charLvlsFI.getElementAt(5), charLvlsFI.findNextLevelForSkill(spellcraftSkill, charLvlsFI.getElementAt(1), 9.0f));
// not prohibited
for (int i = 0; i < 20; i++) {
PCLevelInfo pcLevelInfo = charLvlsFI.getLevelInfo(charLvlsFI.getElementAt(i));
if (pcLevelInfo.getClassKeyName().equals(wizardClass.getKeyName())) {
pcLevelInfo.setSkillPointsRemaining(0);
}
}
assertEquals("Level for 5 ranks spellcraft", charLvlsFI.getElementAt(8), charLvlsFI.findNextLevelForSkill(spellcraftSkill, charLvlsFI.getElementAt(5), 5.0f));
// 5. Scan from level 1 for first level with points spare where the rank
// is not above max rank for the level and the skill is not prohibited
assertEquals("Level for 3 ranks spellcraft", charLvlsFI.getElementAt(2), charLvlsFI.findNextLevelForSkill(spellcraftSkill, charLvlsFI.getElementAt(19), 3.0f));
// 6. Advise that the skill cannot be advanced.
charLvlsFI.getLevelInfo(charLvlsFI.getElementAt(18)).setSkillPointsRemaining(4);
charLvlsFI.getLevelInfo(charLvlsFI.getElementAt(19)).setSkillPointsRemaining(4);
assertNull("Level for rank 23.5 climb - cannot be advanced", charLvlsFI.findNextLevelForSkill(climbSkill, charLvlsFI.getElementAt(2), 23.5f));
}
use of pcgen.core.pclevelinfo.PCLevelInfo in project pcgen by PCGen.
the class PCClassTest method testMonsterSkillPoints.
/**
* Test monster classes generating the correct number of skill points.
*/
public void testMonsterSkillPoints() {
// Create a medium bugbear first level
PlayerCharacter bugbear = new PlayerCharacter();
bugbear.setRace(bugbearRace);
setPCStat(bugbear, intel, 12);
// Test skills granted for each level
bugbear.incrementClassLevel(1, humanoidClass);
PCLevelInfo levelInfo = bugbear.getLevelInfo(0);
assertEquals("First level of bugbear", 7, levelInfo.getSkillPointsGained(bugbear));
bugbear.incrementClassLevel(1, humanoidClass);
levelInfo = bugbear.getLevelInfo(1);
assertEquals("2nd level of bugbear", 1, levelInfo.getSkillPointsGained(bugbear));
bugbear.incrementClassLevel(1, humanoidClass);
levelInfo = bugbear.getLevelInfo(2);
assertEquals("3rd level of bugbear", 1, levelInfo.getSkillPointsGained(bugbear));
// Craete a huge bugbear first level
bugbear = new PlayerCharacter();
bugbear.setRace(bigBugbearRace);
assertEquals("big bugbear", "L", bugbear.getDisplay().getSize());
setPCStat(bugbear, intel, 10);
bugbear.incrementClassLevel(1, humanoidClass);
// Test skills granted for each level
levelInfo = bugbear.getLevelInfo(0);
assertEquals("First level of big bugbear", 6, levelInfo.getSkillPointsGained(bugbear));
bugbear.incrementClassLevel(1, humanoidClass);
levelInfo = bugbear.getLevelInfo(1);
assertEquals("2nd level of big bugbear", 0, levelInfo.getSkillPointsGained(bugbear));
bugbear.incrementClassLevel(1, humanoidClass);
levelInfo = bugbear.getLevelInfo(2);
assertEquals("3rd level of big bugbear", 1, levelInfo.getSkillPointsGained(bugbear));
// Create a nymph - first level
PlayerCharacter nymph = new PlayerCharacter();
nymph.setRace(nymphRace);
assertEquals("nymph", "M", nymph.getDisplay().getSize());
setPCStat(nymph, intel, 10);
nymph.incrementClassLevel(1, nymphClass);
// Test skills granted for each level
levelInfo = nymph.getLevelInfo(0);
assertEquals("First level of nymph", 24, levelInfo.getSkillPointsGained(bugbear));
nymph.incrementClassLevel(1, nymphClass);
levelInfo = nymph.getLevelInfo(1);
assertEquals("2nd level of nymph", 6, levelInfo.getSkillPointsGained(bugbear));
}
use of pcgen.core.pclevelinfo.PCLevelInfo in project pcgen by PCGen.
the class CharacterFacadeImpl method addDomain.
/**
* @see pcgen.core.facade.CharacterFacade#addDomain(pcgen.core.facade.DomainFacade)
*/
@Override
public void addDomain(DomainFacade domainFacade) {
if (!(domainFacade instanceof DomainFacadeImpl)) {
return;
}
DomainFacadeImpl domainFI = (DomainFacadeImpl) domainFacade;
Domain domain = domainFI.getRawObject();
if (charDisplay.hasDomain(domain)) {
return;
}
if (!isQualifiedFor(domainFacade)) {
delegate.showErrorMessage(Constants.APPLICATION_NAME, LanguageBundle.getFormattedString("in_qualifyMess", domain.getDisplayName()));
return;
}
// Check selected domains vs Max number allowed
if (charDisplay.getDomainCount() >= theCharacter.getMaxCharacterDomains()) {
delegate.showErrorMessage(Constants.APPLICATION_NAME, LanguageBundle.getFormattedString("in_errorNoMoreDomains"));
return;
}
if (!theCharacter.hasDefaultDomainSource()) {
// No source for the domain yet? Default to the last added class level
int level = charDisplay.getLevelInfoSize();
PCLevelInfo highestLevelInfo = charDisplay.getLevelInfo(level - 1);
PCClass cls = theCharacter.getClassKeyed(highestLevelInfo.getClassKeyName());
theCharacter.setDefaultDomainSource(new ClassSource(cls, highestLevelInfo.getClassLevel()));
}
if (theCharacter.addDomain(domain)) {
domains.addElement(domainFI);
DomainApplication.applyDomain(theCharacter, domain);
theCharacter.calcActiveBonuses();
remainingDomains.set(theCharacter.getMaxCharacterDomains() - charDisplay.getDomainCount());
updateDomainTodo();
spellSupportFacade.refreshAvailableKnownSpells();
companionSupportFacade.refreshCompanionData();
}
}
use of pcgen.core.pclevelinfo.PCLevelInfo in project pcgen by PCGen.
the class PlayerCharacter method incrementClassLevel.
/**
* Change the number of levels a character has in a particular class. Note:
* It is assumed that this method is not used as part of loading a
* previously saved character.
*
* @param numberOfLevels
* The number of levels to add or remove. If a positive number is
* passed in then that many levels will be added. If the number
* of levels passed in is negative then that many levels will be
* removed from the specified class.
* @param globalClass
* The global class from the data store. The class as stored in
* the character will be compared to this one using the
* getClassNamed() method
* @param bSilent
* If true do not display any warning messages about adding or
* removing too many levels
* @param bypassPrereqs
* Whether we should bypass the checks as to whether or not the
* PC qualifies to take this class. If true, the checks will be
* bypassed
*/
public void incrementClassLevel(final int numberOfLevels, final PCClass globalClass, final boolean bSilent, final boolean bypassPrereqs) {
// If not importing, load the spell list
if (!importing) {
getSpellList();
}
// Make sure the character qualifies for the class if adding it
if (numberOfLevels > 0) {
if (!bypassPrereqs && !globalClass.qualifies(this, globalClass)) {
return;
}
Race race = getRace();
if (globalClass.isMonster() && !SettingsHandler.isIgnoreMonsterHDCap() && !race.isAdvancementUnlimited() && ((totalHitDice() + numberOfLevels) > race.maxHitDiceAdvancement()) && !bSilent) {
ShowMessageDelegate.showMessageDialog("Cannot increase Monster Hit Dice for this character beyond " + race.maxHitDiceAdvancement() + ". This character's current number of Monster Hit Dice is " + totalHitDice(), Constants.APPLICATION_NAME, MessageType.INFORMATION);
return;
}
}
// Check if the character already has the class.
PCClass pcClassClone = getClassKeyed(globalClass.getKeyName());
// If the character did not already have the class...
if (pcClassClone == null) {
// add the class even if setting to level 0
if (numberOfLevels >= 0) {
// Get a clone of the class so we don't modify the globals!
//Still required :(
pcClassClone = globalClass.clone();
// Make sure the clone was successful
if (pcClassClone == null) {
Logging.errorPrint("PlayerCharacter::incrementClassLevel => " + "Clone of class " + globalClass.getKeyName() + " failed!");
return;
}
// If not importing, add extra feats
if (!importing && classFacet.isEmpty(id)) {
adjustAbilities(AbilityCategory.FEAT, new BigDecimal(pcClassClone.getSafe(IntegerKey.START_FEATS)));
}
// Add the class to the character classes as level 0
classFacet.addClass(id, pcClassClone);
} else {
// mod is < 0 and character does not have class. Return.
return;
}
}
// Add or remove levels as needed
if (numberOfLevels > 0) {
for (int i = 0; i < numberOfLevels; ++i) {
int currentLevel = getLevel(pcClassClone);
final PCLevelInfo playerCharacterLevelInfo = addLevelInfo(pcClassClone.getKeyName());
// if we fail to add the level, remove and return
if (!pcClassClone.addLevel(false, bSilent, this, bypassPrereqs)) {
PCClassLevel failedpcl = getActiveClassLevel(pcClassClone, currentLevel + 1);
removeLevelInfo(pcClassClone.getKeyName());
return;
}
}
} else if (numberOfLevels < 0) {
for (int i = 0; i < -numberOfLevels; ++i) {
int currentLevel = getLevel(pcClassClone);
pcClassClone.subLevel(this);
PCLevelInfo removedLI = removeLevelInfo(pcClassClone.getKeyName());
int pointsToRemove = removedLI.getSkillPointsGained(this) - removedLI.getSkillPointsRemaining();
SkillRankControl.removeSkillsForTopLevel(this, pcClassClone, currentLevel, pointsToRemove);
}
}
calcActiveBonuses();
}
Aggregations