public void testMultiple() throws Exception { final PlayerCharacter character = getCharacter(); Prerequisite prereq; final PreParserFactory factory = PreParserFactory.getInstance(); prereq = factory.parse("PREDEITYDOMAIN:1,Good,Law"); assertFalse("Character has no deity selected", PrereqHandler.passes(prereq, character, null)); character.setAlignment(ng); character.setDeity(deity); assertTrue("Character's deity has Good domain", PrereqHandler.passes(prereq, character, null)); prereq = factory.parse("PREDEITYDOMAIN:2,Good,Law"); assertFalse( "Character's deity doesn't have Law domain", PrereqHandler.passes(prereq, character, null)); prereq = factory.parse("PREDEITYDOMAIN:2,Good,Animal"); assertTrue( "Character's deity has Good and animal domains", PrereqHandler.passes(prereq, character, null)); }
/* * @see TestCase#setUp() */ @Override protected void setUp() throws Exception { super.setUp(); PlayerCharacter character = getCharacter(); character.setName("The Vitamins are in my Fresh Brussels Sprouts"); character.setInterests("one potatoe. two potatoe. mORe"); }
/** Construct the list of available spells for the character. */ private void buildAvailableNodes() { availableSpellNodes.clearContents(); // Scan character classes for spell classes List<PCClass> classList = getCharactersSpellcastingClasses(); // Look at each spell on each spellcasting class for (PCClass pcClass : classList) { DoubleKeyMapToList<SpellFacade, String, SpellNode> existingSpells = buildExistingSpellMap(availableSpellNodes, pcClass); for (Spell spell : pc.getAllSpellsInLists(charDisplay.getSpellLists(pcClass))) { // Create SpellNodeImpl for each spell CharacterSpell charSpell = new CharacterSpell(pcClass, spell); SpellFacadeImplem spellImplem = new SpellFacadeImplem(pc, spell, charSpell, null); HashMapToList<CDOMList<Spell>, Integer> levelInfo = pc.getSpellLevelInfo(spell); for (CDOMList<Spell> spellList : charDisplay.getSpellLists(pcClass)) { List<Integer> levels = levelInfo.getListFor(spellList); if (levels != null) { for (Integer level : levels) { SpellNodeImpl node = new SpellNodeImpl(spellImplem, pcClass, String.valueOf(level), null); if (!existingSpells.containsInList(spellImplem, node.getSpellLevel(), node)) { // Add to list availableSpellNodes.addElement(node); } } } } } } }
public static void addSpellsToClassForLevels( PlayerCharacter pc, Domain d, PCClass aClass, int minLevel, int maxLevel) { if (aClass == null) { return; } for (int aLevel = minLevel; aLevel <= maxLevel; aLevel++) { Collection<Spell> domainSpells = pc.getSpellsIn(d.get(ObjectKey.DOMAIN_SPELLLIST), aLevel); for (Spell spell : domainSpells) { List<CharacterSpell> slist = pc.getCharacterSpells(aClass, spell, Globals.getDefaultSpellBook(), aLevel); boolean flag = true; for (CharacterSpell cs1 : slist) { flag = !(cs1.getOwner().equals(d)); if (!flag) { break; } } if (flag) { CharacterSpell cs = new CharacterSpell(d, spell); cs.addInfo(aLevel, 1, Globals.getDefaultSpellBook()); pc.addCharacterSpell(aClass, cs); } } } }
/* (non-Javadoc) * @see pcgen.core.facade.SpellSupportFacade#removeSpellList(java.lang.String) */ @Override public void removeSpellList(String spellList) { if (spellList.equalsIgnoreCase(Globals.getDefaultSpellBook())) { Logging.errorPrint( LanguageBundle.getString("InfoSpells.can.not.delete.default.spellbook")); // $NON-NLS-1$ return; } if (pc.delSpellBook(spellList)) { pc.setDirty(true); for (Iterator<SpellNode> iterator = preparedSpellLists.iterator(); iterator.hasNext(); ) { SpellNode listNode = iterator.next(); if (spellList.equals(listNode.getRootNode().getName())) { iterator.remove(); } } for (Iterator<SpellNode> iterator = preparedSpellNodes.iterator(); iterator.hasNext(); ) { SpellNode spell = iterator.next(); if (spellList.equals(spell.getRootNode().getName())) { iterator.remove(); } } } else { Logging.errorPrint("delBookButton:failed "); // $NON-NLS-1$ return; } }
/** Test the output for positive numbers with fractions. */ public void testTextFormatting() { TextToken tok = new TextToken(); ExportHandler eh = new ExportHandler(null); PlayerCharacter character = getCharacter(); assertEquals( "TEXT.LOWER.NAME", "the vitamins are in my fresh brussels sprouts", tok.getToken("TEXT.LOWER.NAME", character, eh)); assertEquals( "TEXT.UPPER.NAME", "THE VITAMINS ARE IN MY FRESH BRUSSELS SPROUTS", tok.getToken("TEXT.UPPER.NAME", character, eh)); assertEquals( "TEXT.SENTENCE.NAME", "The vitamins are in my fresh brussels sprouts", tok.getToken("TEXT.SENTENCE.NAME", character, eh)); assertEquals( "TEXT.SENTENCE.NAME", "The vitamins are in my fresh brussels sprouts", tok.getToken("TEXT.SENTENCE.NAME", character, eh)); character.setName("The Vitamins are in my Fresh Brussels Sprouts"); assertEquals( "TEXT.SENTENCE.INTERESTS", "One potatoe. Two potatoe. More", tok.getToken("TEXT.SENTENCE.INTERESTS", character, eh)); assertEquals( "TEXT.TITLE.NAME", "The Vitamins Are In My Fresh Brussels Sprouts", tok.getToken("TEXT.TITLE.NAME", getCharacter(), eh)); assertEquals( "TEXT.TITLE.NAME", "One Potatoe. Two Potatoe. More", tok.getToken("TEXT.TITLE.INTERESTS", character, eh)); }
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()); } } } }
/** * Drives the selection of the AgeSet Kit for a Player Character when relevant changes (change to * an AgeSet) are made to a Player Character. * * <p>Triggered when one of the Facets to which AgeSetKitFacet listens fires a * DataFacetChangeEvent to indicate a CDOMObject was added to a Player Character. * * @param dfce The DataFacetChangeEvent containing the information about the change * @see * pcgen.cdom.facet.event.DataFacetChangeListener#dataAdded(pcgen.cdom.facet.event.DataFacetChangeEvent) */ @Override public void dataAdded(DataFacetChangeEvent<CharID, Integer> dfce) { CharID id = dfce.getCharID(); AgeSet ageSet = ageSetFacet.get(id); PlayerCharacter pc = trackingFacet.getPC(id); // TODO Is ageSet null check necessary? if (ageSet == null || pc.isImporting()) { return; } int ageSetIndex = ageSetFacet.getAgeSetIndex(id); /* * TODO The method of storing what AgeSets have had kit selections made * should be converted to store the actual AgeSet rather than the index, * in order to reduce the number of calls to ageSetFacet.getAgeSetIndex. * This (of course) drives the move of the AgeSets for which a kit * selection has been made into a Facet. It is possible that the * CacheInfo of AgeSetKitFacet is actually a good place to store that * information (or it may be implicit with the information already * stored there??) */ if (!pc.hasMadeKitSelectionForAgeSet(ageSetIndex)) { CacheInfo cache = getConstructingClassInfo(id); List<Kit> kits = cache.get(ageSet); if (kits != null) { // Need to do selection BioSet bioSet = bioSetFacet.get(id); for (TransitionChoice<Kit> kit : ageSet.getKits()) { Collection<? extends Kit> choice = kit.driveChoice(pc); cache.put(ageSet, choice); kit.act(choice, bioSet, pc); } } pc.setHasMadeKitSelectionForAgeSet(ageSetIndex, true); } }
/** * Test to ensure that a character will fail a test if it does not have the correct number of * levels in the class. * * @throws Exception */ public void testCharWithMultipleSpellClasses() throws Exception { LoadContext context = Globals.getContext(); final PCClass pcClass = new PCClass(); pcClass.setName("MyClass"); context.unconditionallyProcess(pcClass, "SPELLSTAT", "CHA"); pcClass.put(StringKey.SPELLTYPE, "ARCANE"); context.unconditionallyProcess(pcClass.getOriginalClassLevel(1), "CAST", "5,4"); final PCClass pcClass2 = new PCClass(); pcClass2.setName("Other Class"); context.unconditionallyProcess(pcClass2, "SPELLSTAT", "INT"); pcClass2.put(StringKey.SPELLTYPE, "ARCANE"); context.unconditionallyProcess(pcClass2.getOriginalClassLevel(1), "CAST", "5,4"); final PlayerCharacter character = getCharacter(); setPCStat(character, cha, 12); setPCStat(character, intel, 12); character.incrementClassLevel(1, pcClass); character.incrementClassLevel(2, pcClass2); final PreClassParser producer = new PreClassParser(); final Prerequisite prereq = producer.parse("CLASS", "1,SPELLCASTER.Arcane,SPELLCASTER.Arcane=2", false, false); final PreMult test = new PreMult(); final int passes = test.passes(prereq, character, null); assertEquals(1, passes); }
private void updateSelections() { /* Use set intersection/join's to figure out what updates have been done */ /* First, find which temporary bonuses have been removed, and which have been added */ Set<String> newValues = pc.getTempBonusNames(); Set<String> oldValues = new TreeSet<String>(tempBonusWidgets.keySet()); oldValues.removeAll(newValues); newValues.removeAll(tempBonusWidgets.keySet()); if (!newValues.isEmpty()) { addTempBonus(newValues); } if (!oldValues.isEmpty()) { removeTempBonus(oldValues); } /* Now, same for equipment sets. */ newValues.clear(); oldValues.clear(); newValues.addAll(equipSet2Set(pc.getEquipSet())); oldValues.addAll(eqSetWidgets.keySet()); oldValues.removeAll(newValues); newValues.removeAll(eqSetWidgets.keySet()); if (!newValues.isEmpty()) { addEquipSets(newValues); } if (!oldValues.isEmpty()) { removeEquipSets(oldValues); } }
/** * Count the number of times the character has the ability. This can be limited to either hidden * or visible Abilities, and can be limited to only counting once per ability rather than once per * time taken (e.g. Weapon Specialisation in two weapons would count as 2 unless the onceOnly flag * was true). * * @param pc the Character with the abilities * @param cna The feat to be counted. * @param visible Should it be counted if it is visible? * @param hidden Should it be counted if it is hidden? * @param onceOnly Should it be counted as one if was taken multiple times? * @return The number of occurrences of the ability. */ protected Float countVisibleAbility( PlayerCharacter pc, final CNAbility cna, final boolean visible, final boolean hidden, final boolean onceOnly) { Visibility v = cna.getAbility().getSafe(ObjectKey.VISIBILITY); // TODO This is a bug, it assumes export boolean abilityInvisibile = v.isVisibleTo(View.HIDDEN_EXPORT); int count = 0; if (abilityInvisibile) { if (hidden) { count += onceOnly ? 1 : Math.max(1, pc.getSelectCorrectedAssociationCount(cna)); } } else { if (visible) { count += onceOnly ? 1 : Math.max(1, pc.getSelectCorrectedAssociationCount(cna)); } } return (float) count; }
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()); } } } }
/** * Make sure or case works * * @throws Exception */ public void testMultiOr() throws Exception { final PlayerCharacter character = getCharacter(); character.setRace(race); Prerequisite prereq; final PreParserFactory factory = PreParserFactory.getInstance(); prereq = factory.parse("PREDR:1,+1=10,+2=5"); assertFalse("Character has no DR", PrereqHandler.passes(prereq, character, null)); race.addToListFor(ListKey.DAMAGE_REDUCTION, drPlus1); // This weirdness is because we are altering the race after application (no-no at runtime) character.setRace(null); character.setRace(race); assertFalse("Character DR not 10", PrereqHandler.passes(prereq, character, null)); DamageReduction drPlus2_5 = new DamageReduction(FormulaFactory.getFormulaFor(5), "+2"); race.addToListFor(ListKey.DAMAGE_REDUCTION, drPlus2_5); // This weirdness is because we are altering the race after application (no-no at runtime) character.setRace(null); character.setRace(race); assertTrue("Character has DR 5/+2", PrereqHandler.passes(prereq, character, null)); }
@Override public boolean testApply(Kit aKit, PlayerCharacter aPC, List<String> warnings) { skillsToAdd = new ArrayList<KitSkillAdd>(); List<Skill> skillChoices = getSkillChoices(aPC); if (skillChoices == null || skillChoices.size() == 0) { // They didn't make a choice so don't add any ranks. return false; } for (Skill skill : skillChoices) { BigDecimal ranksLeftToAdd = getRank(); if (ranksLeftToAdd == null) { ranksLeftToAdd = BigDecimal.ONE; } double ranksLeft = ranksLeftToAdd.doubleValue(); List<PCClass> classList = new ArrayList<PCClass>(); if (className != null) { String classKey = className.resolvesTo().getKeyName(); // Make sure if they specified a class to add from we try that // class first. PCClass pcClass = aPC.getClassKeyed(classKey); if (pcClass != null) { classList.add(pcClass); } else { warnings.add( "SKILL: Could not find specified class " + classKey + " in PC to add ranks from."); } } for (PCClass pcClass : aPC.getClassSet()) { if (!classList.contains(pcClass)) { classList.add(pcClass); } } // Try and find a class we can add them from. boolean oldImporting = aPC.isImporting(); aPC.setImporting(true); for (PCClass pcClass : classList) { final KitSkillAdd sta = addRanks(aPC, pcClass, skill, ranksLeft, isFree(), warnings); if (sta != null) { skillsToAdd.add(sta); ranksLeft -= sta.getRanks(); if (ranksLeft <= 0.0) { break; } } } aPC.setImporting(oldImporting); if (ranksLeft > 0.0) { warnings.add( "SKILL: Could not add " + ranksLeft + " ranks to " + skill.getKeyName() + ". Not enough points."); } } return true; }
private static String getNumCast(PCClass aClass, int level, PlayerCharacter pc) { String sbook = Globals.getDefaultSpellBook(); final String cast = pc.getSpellSupport(aClass).getCastForLevel(level, sbook, true, false, pc) + pc.getSpellSupport(aClass).getBonusCastForLevelString(level, sbook, pc); return cast; }
public boolean allow(PlayerCharacter pc, Skill sk) { Collection<PCClass> classlist = pc.getClassSet(); for (PCClass cl : classlist) { if (pc.isClassSkill(cl, sk)) { return true; } } return false; }
private static void addDomain(final PlayerCharacter aPC, PCClass cl, Domain d) { if (d.qualifies(aPC, d)) { // TODO Not entirely correct, as this takes this level, not // the level where BONUS DOMAINS was present ClassSource cs = new ClassSource(cl, aPC.getLevel(cl)); aPC.addDomain(d, cs); applyDomain(aPC, d); } }
public void itemStateChanged(ItemEvent e) { if (e.getStateChange() == ItemEvent.DESELECTED) { playerCharacter.setTempBonusFilter(bonus); } if (e.getStateChange() == ItemEvent.SELECTED) { playerCharacter.unsetTempBonusFilter(bonus); } theParent.refresh(); }
@Override public int getModifier() { String initiativeVar = ControlUtilities.getControlToken(Globals.getContext(), CControl.INITIATIVE); if (initiativeVar == null) { return pc.getDisplay().processOldInitiativeMod() + incrementalBonus; } return ((Number) pc.getGlobal(initiativeVar)).intValue() + incrementalBonus; }
/** * <code>refresh</code> updates all filters and eqsets. Should typically be called whenever there * is a chance that the user has added/removed temporary bonuses or equipment sets. */ public void refresh() { if (pc == null) { return; } if (serial < pc.getSerial()) { updateSelections(); serial = pc.getSerial(); } }
@Override public void applyChoice( CDOMObject owner, CategorizedAbilitySelection choice, PlayerCharacter pc) { double cost = choice.getAbility().getSafe(ObjectKey.SELECTION_COST).doubleValue(); if (cost > 0.0001) { pc.adjustFeats(cost); } AbilityUtilities.modAbility( pc, choice.getAbility(), choice.getSelection(), AbilityCategory.FEAT); pc.addAssoc(owner, AssociationListKey.TEMPLATE_FEAT, choice); }
public PcgSystemInitiative(PlayerCharacter pc) { this.pc = pc; display = pc.getDisplay(); PCStat stat = Globals.getContext() .getReferenceContext() .silentlyGetConstructedCDOMObject(PCStat.class, "DEX"); this.attribute = new SystemAttribute("Dexterity", pc.getTotalStatFor(stat)); incrementalBonus = 0; die = new Dice(1, 20); }
@Override public void restoreChoice(PlayerCharacter pc, CDOMObject owner, T choice) { pc.addAssoc(owner, getListKey(), choice); pc.addAssociation(owner, encodeChoice(choice)); List<ChooseSelectionActor<?>> actors = owner.getListFor(ListKey.NEW_CHOOSE_ACTOR); if (actors != null) { for (ChooseSelectionActor ca : actors) { applyChoice(owner, choice, pc, ca); } } }
/** * Remove any spells granted by the domain to the class. * * @param pc The character. * @param domain The domain. * @param aClass The class which would have the spells allocated. */ public static void removeSpellsFromClassForLevels( PlayerCharacter pc, Domain domain, PCClass aClass) { if (aClass == null) { return; } Collection<? extends CharacterSpell> characterSpells = pc.getCharacterSpells(aClass); for (CharacterSpell characterSpell : characterSpells) { if (characterSpell.getOwner() == domain) { pc.removeCharacterSpell(aClass, characterSpell); } } }
@Override public boolean allow(CategorizedAbilitySelection choice, PlayerCharacter pc, boolean allowStack) { // Only allow those already selected for (Ability a : pc.getAbilityList(AbilityCategory.FEAT, Nature.NORMAL)) { if (a.getKeyName().equals(choice.getAbilityKey())) { Boolean multYes = a.getSafe(ObjectKey.MULTIPLE_ALLOWED); if (!multYes || multYes && hasAssoc(pc.getAssociationList(a), choice)) { return true; } } } return false; }
private <R> List<R> getList(PlayerCharacter pc, Ability a) { // workaround for cloning issue List<R> availableList = new ArrayList<>(); List<CNAbility> theFeats = pc.getMatchingCNAbilities(a); for (CNAbility ability : theFeats) { @SuppressWarnings("unchecked") List<? extends R> list = (List<? extends R>) pc.getDetailedAssociations(ability); if (list != null) { availableList.addAll(list); } } return availableList; }
/** * Needs documentation. * * @param pc update skills for this PC * @param aSkill Skill to update * @param aRank Number of ranks to add * @param aCost Cost of added ranks * @param langList Languages to be selected for a language skill * @param pcClass skills apply to this class * @return <code>true</code> for success TODO What about throwing on failure? */ private boolean updatePCSkills( final PlayerCharacter pc, final Skill aSkill, final int aRank, final double aCost, List<Language> langList, final PCClass pcClass) { pc.addSkill(aSkill); boolean oldImporting = pc.isImporting(); pc.setImporting(true); final String aString = SkillRankControl.modRanks(aRank, pcClass, true, pc, aSkill); pc.setImporting(oldImporting); if (aString.length() > 0) { Logging.errorPrint("SKILL: " + aString); return false; } // Add any supplied languages ChoiceManagerList<Language> controller = ChooserUtilities.getConfiguredController(aSkill, pc, null, new ArrayList<String>()); for (Language lang : langList) { if (!controller.conditionallyApply(pc, lang)) { Logging.errorPrint("Failed to apply Language into Skill: " + lang.getLSTformat()); } } // // Fix up the skill pools to reflect what we just spent. // double ptsToSpend = aCost; if (ptsToSpend >= 0.0) { for (PCLevelInfo info : pc.getLevelInfo()) { if (info.getClassKeyName().equals(pcClass.getKeyName())) { // We are spending this class' points. int remaining = info.getSkillPointsRemaining(); if (remaining == 0) { continue; } int left = remaining - (int) Math.min(remaining, ptsToSpend); info.setSkillPointsRemaining(left); ptsToSpend -= (remaining - left); if (ptsToSpend <= 0) { break; } } } } return true; }
/** Test the SPELLLISTCAST sub-tag of the SPELLLIST token. */ public void testSpellListCastToken() { PlayerCharacter character = new PlayerCharacter(); character.setRace(human); character.setStat(cha, 12); character.calcActiveBonuses(); character.incrementClassLevel(1, arcaneClass, true); SpellListCastToken token = new SpellListCastToken(); assertEquals( "testSpellListCastToken(1lv TA)", "2", token.getToken("SPELLLISTCAST.0.1", character, null)); }
/* (non-Javadoc) * @see junit.framework.TestCase#setUp() */ @Override protected void setUp() throws Exception { super.setUp(); final PlayerCharacter character = getCharacter(); myClass = new PCClass(); myClass.setName("My Class"); knowledge = new Skill(); Globals.getContext().unconditionallyProcess(knowledge, "CLASSES", "My Class"); knowledge.setName("KNOWLEDGE (ARCANA)"); TestHelper.addType(knowledge, "KNOWLEDGE.INT"); character.addSkill(knowledge); SkillRankControl.modRanks(8.0, myClass, true, character, knowledge); }
/** Test the SPELLLISTDC sub-tag of the SPELLLIST token. */ public void testSpellListDcToken() { PlayerCharacter character = new PlayerCharacter(); character.setRace(human); setPCStat(character, cha, 14); character.calcActiveBonuses(); character.incrementClassLevel(1, arcaneClass, true); character.calcActiveBonuses(); SpellListDcToken token = new SpellListDcToken(); assertEquals( "SpellListDcToken(1lv TA)", "12", token.getToken("SPELLLISTDC.0.0", character, null)); assertEquals( "SpellListDcToken(1lv TA)", "15", token.getToken("SPELLLISTDC.0.3", character, null)); }