|
From: <nu...@us...> - 2006-04-16 04:41:50
|
Revision: 822 Author: nuance Date: 2006-04-15 21:41:32 -0700 (Sat, 15 Apr 2006) ViewCVS: http://svn.sourceforge.net/pcgen/?rev=822&view=rev Log Message: ----------- commit some refactoring i did while fixing [ 1463228 ] LEVEL:x:FEAT:TYPE.type broken Modified addVirtualFeat method to return the Ability it adds, also moved the setting of the PC.setDirty out of the addVirtualAbility method. Refactored AbilityUtilities. Extracted lots of small methods. Sorted the methods into alpha order. Have changed the way Feats work, they no longer add anything to the associated list if they are not multiples. Modified tests for this new behaviour. Modified Paths: -------------- Trunk/pcgen/.project Trunk/pcgen/code/src/java/pcgen/core/AbilityUtilities.java Trunk/pcgen/code/src/java/pcgen/core/levelability/LevelAbilityAbility.java Trunk/pcgen/code/src/java/pcgen/core/levelability/LevelAbilityFeat.java Trunk/pcgen/code/src/java/pcgen/io/PCGVer2Parser.java Trunk/pcgen/code/testsuite/csheets/BarJack.xml Trunk/pcgen/code/testsuite/csheets/BrdJoe.xml Trunk/pcgen/code/testsuite/csheets/CleElf.xml Trunk/pcgen/code/testsuite/csheets/FigFae.xml Trunk/pcgen/code/testsuite/csheets/JimDop.xml Modified: Trunk/pcgen/.project =================================================================== --- Trunk/pcgen/.project 2006-04-16 04:03:20 UTC (rev 821) +++ Trunk/pcgen/.project 2006-04-16 04:41:32 UTC (rev 822) @@ -15,9 +15,15 @@ <arguments> </arguments> </buildCommand> + <buildCommand> + <name>com.teaminabox.eclipse.metrics.MetricsBuilder</name> + <arguments> + </arguments> + </buildCommand> </buildSpec> <natures> <nature>org.eclipse.jdt.core.javanature</nature> <nature>com.ibm.etools.ctc.javaprojectnature</nature> + <nature>com.teaminabox.eclipse.metrics.MetricsNature</nature> </natures> </projectDescription> Modified: Trunk/pcgen/code/src/java/pcgen/core/AbilityUtilities.java =================================================================== --- Trunk/pcgen/code/src/java/pcgen/core/AbilityUtilities.java 2006-04-16 04:03:20 UTC (rev 821) +++ Trunk/pcgen/code/src/java/pcgen/core/AbilityUtilities.java 2006-04-16 04:41:32 UTC (rev 822) @@ -46,394 +46,302 @@ */ public class AbilityUtilities { -// /** -// * Find an ability that matches a given name in a list (using this is -// * probably a really bad idea since it doesn't pay attention to category) -// * -// * @param aFeatList A list of Ability Objects -// * @param cat TODO -// * @param featName The name of the Ability being looked for -// * @param type TODO -// * @return the Ability if found, otherwise null -// */ -// public static Ability getFeatNamedInList( -// final List aFeatList, -// String cat, final String featName, int type) -// { -// AbilityInfo abInfo = new AbilityInfo("FEAT", featName); -// return getAbilityFromList(aFeatList, abInfo, -1); -// } -// -// /** -// * Find an ability that matches a given name in a list (using this is -// * probably a really bad idea since it doesn't pay attention to category). -// * Also takes an integer representing a type, -1 always matches, otherwise -// * an ability will only be returned if its type is the same as featType -// * -// * @param aFeatList -// * @param featName -// * @param featType -// * -// * @return the Ability if found, otherwise null -// */ -// public static Ability getFeatNamedInList( -// final List aFeatList, -// final String featName, -// final int featType) -// { -// if (aFeatList.isEmpty()) -// { -// return null; -// } -// -// for (Iterator e = aFeatList.iterator(); e.hasNext();) -// { -// final Ability aFeat = (Ability) e.next(); -// -// if (aFeat.getName().equalsIgnoreCase(featName)) -// { -// if ((featType == -1) || (aFeat.getFeatType() == featType)) -// { -// return aFeat; -// } -// } -// } -// -// return null; -// } -// -// /** -// * Find an ability that matches a given name in a list (If you use this it -// * defaults to category FEAT). Also takes an integer representing a type, -1 -// * always matches, otherwise an ability will only be returned if its type is -// * the same as featType -// * -// * @param anAbilityList -// * @param featName -// * @param abilityType -// * -// * @return the Ability if found, otherwise null -// */ -// public static Ability getFeatNamedInList( -// final List anAbilityList, -// final String featName, -// final int abilityType) -// { -// AbilityInfo abInfo = new AbilityInfo("FEAT", featName); -// return getAbilityFromList(anAbilityList, abInfo, abilityType); -// } + private AbilityUtilities () + { + // private constructor, do nothing + } - /** - * Get an Ability (that is the same basic ability as the argument, but may - * have had choices applied) from the list. + * Add the choices in the List to the ability if it is legal to do so. * - * @param abilityList - * @param argAbility - * - * @return the Ability if found, otherwise null + * @param ability + * @param choices */ - public static Ability getMatchingFeatInList( - final List abilityList, - final Ability argAbility) + private static void addChoicesToAbility( + final Ability ability, + final List choices) { - if (abilityList.isEmpty()) + final Iterator choiceIt = choices.iterator(); + + while (choiceIt.hasNext()) { - return null; + final String assoc = (String) choiceIt.next(); + + if (ability.canAddAssociation(assoc)) + { + ability.addAssociated(assoc); + } } + } - for (Iterator it = abilityList.iterator(); it.hasNext();) + + /** + * Clone anAbility, apply choices and add it to the addList, provided the + * Ability allows it (if not isMultiples check if it's already there before + * adding it). + * + * @param anAbility + * @param choices + * @param addList + * @return the Ability added, or null if Ability was not added to the list. + */ + private static Ability addCloneOfAbilityToListwithChoices( + final Ability anAbility, + final List choices, + final List addList) + { + Ability newAbility = null; + + if (anAbility != null && (anAbility.isMultiples() || getAbilityFromList(addList, anAbility) == null)) { - final Ability anAbility = (Ability) it.next(); + newAbility = (Ability) anAbility.clone(); - if (anAbility.isSameBaseAbility(argAbility)) + if (choices != null) { - return anAbility; + addChoicesToAbility(newAbility, choices); } + addList.add(newAbility); } - - return null; + return newAbility; } + /** - * This method attempts to get an Ability Object from the Global Store keyed - * by token. If this fails, it checks if token has info in parenthesis - * appended to it. If it does, it strips this and attempts to get an - * Ability Keyed by the stripped token. If this works, it passes back this - * Ability, if it does not work, it returns null. + * Search the List passed in for an instance of the Ability matching + * category and Ability name. If we don't find it, attempt to locate + * it in global Storage and, if it's there, clone it and add it the List. + * If we got an ability, then add any sub choices from the name to the + * associated list of the ability. * - * @param cat The category of Ability Object to retrieve - * @param token The name of the Ability Object - * - * @return The ability in category "cat" called "token" + * @param theAbilityList A list of abilities to add to + * @param category The category of Ability to add + * @param abilityName The name of the Ability to Add + * + * @return The Ability processed */ - public static Ability retrieveAbilityKeyed( - String cat, - final String token) + private static Ability addCloneOfGlobalAbilityToListWithChoices( + final List theAbilityList, + final String category, + final String abilityName) { - Ability ab = Globals.getAbilityKeyed(cat, token); + final ArrayList choices = new ArrayList(); + EquipmentUtilities.getUndecoratedName(abilityName, choices); - if (ab != null) + Ability anAbility = getAbilityFromList(theAbilityList, "FEAT", abilityName, -1); + + if (anAbility == null) { - return ab; + anAbility = cloneGlobalAbility(category, abilityName); + + if (anAbility != null) + { + theAbilityList.add(anAbility); + } } - String stripped = EquipmentUtilities.removeChoicesFromName(token); - ab = Globals.getAbilityKeyed(cat, stripped); - - if (ab != null) + if (anAbility != null) { - return ab; + addChoicesToAbility(anAbility, choices); } - return null; + return anAbility; } - /** * Add a virtual feat to the character and include it in the List. * * @param anAbility * @param choices * @param addList - * @param aPC * @param levelInfo - * - * @return the list with the new Ability added + * @return the Ability added */ - public static List addVirtualFeat( - Ability anAbility, - final List choices, - final List addList, - final PlayerCharacter aPC, - final PCLevelInfo levelInfo) + public static Ability addVirtualAbility( + final Ability anAbility, + final List choices, + final List addList, + final PCLevelInfo levelInfo) { - if (anAbility != null) + if (anAbility == null) { - Ability newAbility = (Ability) anAbility.clone(); + return null; + } + + final Ability newAbility = addCloneOfAbilityToListwithChoices(anAbility, choices, addList); + + if (newAbility != null) + { newAbility.setFeatType(Ability.ABILITY_VIRTUAL); newAbility.clearPreReq(); - - if (choices != null) + if (levelInfo != null) { - final Iterator it = choices.iterator(); - - while (it.hasNext()) - { - final String assoc = (String) it.next(); - - if (!newAbility.containsAssociated(assoc)) - { - newAbility.addAssociated(assoc); - } - } + levelInfo.addObject(newAbility); } - - if (newAbility.isMultiples()) - { - addList.add(newAbility); - - if (levelInfo != null) - { - levelInfo.addObject(newAbility); - } - } - else if (getAbilityFromList(addList, newAbility) == null) - { - addList.add(newAbility); - - if (levelInfo != null) - { - levelInfo.addObject(newAbility); - } - } } - aPC.setDirty(true); - - return addList; + return newAbility; } /** - * Add a virtual feat to the character by name and include it in the List. - * Any choices are extracted from the name and added appropriately - * + * Add a virtual Ability to abilityList by category and name. Any choices made + * (by including in parenthesis e.g. "Weapon Focus (Longsword)", are extracted + * from the name and added appropriately + * + * @param category * @param featName - * @param addList + * @param abilityList * @param levelInfo - * @param aPC - * - * @return the list with the new Ability added + * + * @return the Ability added */ - public static List addVirtualFeat( - final String featName, - final List addList, - final PCLevelInfo levelInfo, - final PlayerCharacter aPC) + public static Ability addVirtualAbility( + final String category, + final String featName, + final List abilityList, + final PCLevelInfo levelInfo) { - ArrayList choices = new ArrayList(); - String abilityName = EquipmentUtilities.getUndecoratedName(featName, choices); - Ability anAbility = Globals.getAbilityNamed("FEAT", abilityName); + final ArrayList choices = new ArrayList(); + final String abilityName = EquipmentUtilities.getUndecoratedName(featName, choices); + final Ability anAbility = Globals.getAbilityNamed(category, abilityName); - return addVirtualFeat(anAbility, choices, addList, aPC, levelInfo); + return addVirtualAbility(anAbility, choices, abilityList, levelInfo); } - + /** - * Add a Feat to a character, allowing sub-choices if necessary. Always adds - * weapon proficiencies, either a single choice if addAll is false, or all - * possible choices if addAll is true. - * @param aPC the PC to add or remove the Feat from - * @param playerCharacterLevelInfo - * @param featName the name of the Feat to add. - * @param addIt {<code>false</code>} means the character must already have the - * feat (which only makes sense if it - * allows multiples); {<code>true</code>} means - * to add the feat (the only way to add - * new feats). - * @param addAll {<code>false</code>} means allow sub-choices; {<code>true</code>} means - * no sub-choices. + * Do the Categorisable objects passed in represent the same ability? * - * @return 1 if adding the Ability but it wasn't there or 0 if the PC does - * not currently have the Ability. + * @param first + * @param second + * @return true if the same object is represented */ - public static int modFeat( - final PlayerCharacter aPC, - final PCLevelInfo playerCharacterLevelInfo, - String featName, - final boolean addIt, - boolean addAll) + static public boolean areSameAbility( + final Categorisable first, + final Categorisable second) { - if (!aPC.isImporting()) - { - aPC.getSpellList(); + if (first == null || second == null) { + return false; } - ArrayList choices = new ArrayList(); - int retVal = addIt ? 1 : 0; - boolean added = false; - final String undoctoredName = featName; - final String baseName = EquipmentUtilities.getUndecoratedName(featName, choices); - String subName = choices.size() > 0 ? (String) choices.get(0) : ""; + final boolean multFirst = getIsMultiples(first); + final boolean multSecond = getIsMultiples(second); + boolean nameCheck = false; - // See if our choice is not auto or virtual - Ability anAbility = aPC.getRealFeatNamed(undoctoredName); + if (multFirst && multSecond) { + /* + * The are both Multiply applicable, so strip the decorations (parts + * in brackets) from the name, then check the undecorated names are + * equal. + */ + final ArrayList decorationsThis = new ArrayList(); + final ArrayList decorationsThat = new ArrayList(); + final String undecoratedThis = EquipmentUtilities.getUndecoratedName(first.getKeyName(), decorationsThis); + final String undecoratedThat = EquipmentUtilities.getUndecoratedName(second.getKeyName(), decorationsThat); + nameCheck = undecoratedThis.compareToIgnoreCase(undecoratedThat) == 0; - // if a feat named featName doesn't exist, and featName - // contains a (blah) descriptor, try removing it. - if (anAbility == null) - { - anAbility = aPC.getRealFeatNamed(baseName); + } else if (multFirst || multSecond) { - if (addAll && (anAbility != null) && (subName.length() != 0)) - { - addAll = false; - } + // one is multiply applicable but the other isn't. They can't be the + // same Ability + return false; + } else { + + /* + * They're not multiply selectable, so anything in brackets isn't a + * choice, it's part of the name + */ + nameCheck = first.getKeyName().compareToIgnoreCase(second.getKeyName()) == 0; } - // (anAbility == null) means we don't have this feat, - // so we need to add it - if (addIt && (anAbility == null)) - { - // adding feat for first time - anAbility = Globals.getAbilityNamed("FEAT", baseName); + return (nameCheck && first.getCategory().compareToIgnoreCase(second.getCategory()) == 0); + } - if (anAbility == null) - { - anAbility = Globals.getAbilityNamed("FEAT", undoctoredName); - if (anAbility != null) - { - subName = ""; - } - } - - if (anAbility != null) - { - anAbility = (Ability) anAbility.clone(); - } - else - { - Logging.errorPrint("Feat not found: " + undoctoredName); - - return retVal; - } - - aPC.addFeat(anAbility, playerCharacterLevelInfo); - anAbility.getTemplates(aPC.isImporting(), aPC); + /** + * Do the Categorisable object and the string passed in represent the + * same ability? the string is assumed to be in the same Category as the + * Categorisable object. + * + * @param first + * @param second + * @return true if the same object is represented + */ + static public boolean areSameAbility( + final Categorisable first, + final String second) + { + if (first == null || second == null) { + return false; } + final Categorisable newSecond = new AbilityInfo(first.getCategory(), second); + return areSameAbility(first, newSecond); + } - /* - * could not find the Ability: addIt true means that no global Ability called - * featName exists, addIt false means that the PC does not have this ability - */ - if (anAbility == null) - { - return retVal; + /** + * Do the strings passed in represent the same Ability object in the + * Category category? + * + * @param category + * @param first + * @param second + * @return true if the same object is represented + */ + static public boolean areSameAbility( + final String category, + final String first, + final String second) + { + if (category == null || first == null || second == null) { + return false; } - - return finaliseAbility(anAbility, subName, aPC, addIt, addAll, added, retVal); + final Categorisable newFirst = new AbilityInfo(category, first); + return areSameAbility(newFirst, second); } /** - * Add an Ability to a character, allowing sub-choices if necessary. Always adds - * weapon proficiencies, either a single choice if addAll is false, or all - * possible choices if addAll is true. - * @param aPC the PC to add or remove the Feat from - * @param playerCharacterLevelInfo LevelInfo object to adjust. - * @param argAbility The ability to process - * @param choice For an isMultiples() Ability - * @param addIt {<code>false</code>} means the character must already have the - * feat (which only makes sense if it - * allows multiples); {<code>true</code>} means - * to add the feat (the only way to add - * new feats). - * @param addAll {<code>false</code>} means allow sub-choices; {<code>true</code>} means - * no sub-choices. - * @return 1 if adding the Ability or 0 if removing it. + * If an ability in Global storage matches the category and name passed + * in, then return a clone of that Ability. + * + * @param category + * @param abilityName + * + * @return a clone of a global ability */ - - public static int modAbility( - final PlayerCharacter aPC, - final PCLevelInfo playerCharacterLevelInfo, - final Ability argAbility, - final String choice, - final boolean addIt, - boolean addAll) + private static Ability cloneGlobalAbility( + final String category, + final String abilityName) { + Ability anAbility; + final ArrayList choices = new ArrayList(); + final String baseName = EquipmentUtilities.getUndecoratedName(abilityName, choices); - int retVal = addIt ? 1 : 0; - boolean added = false; + anAbility = Globals.getAbilityNamed(category, abilityName); - if (argAbility == null) + if ((anAbility == null) && (baseName.length() != 0)) { - Logging.errorPrint("Can't process null Ability"); - return retVal; + anAbility = Globals.getAbilityNamed(category, baseName); } - if (aPC.isNotImporting()) {aPC.getSpellList();} - - List realAbilities = aPC.getRealFeatsList(); - Ability pcAbility = getAbilityFromList(realAbilities, argAbility); - - if (addAll && (pcAbility != null) && (choice.length() != 0)) + if (anAbility == null) { - addAll = false; + ShowMessageDelegate.showMessageDialog( + "Adding unknown feat: " + abilityName, + Constants.s_APPNAME, + MessageType.INFORMATION); } - - // (pcAbility == null) means we don't have this feat, - // so we need to add it - if (addIt && (pcAbility == null)) + else { - // adding feat for first time - pcAbility = (Ability) argAbility.clone(); - - aPC.addFeat(pcAbility, playerCharacterLevelInfo); - pcAbility.getTemplates(aPC.isImporting(), aPC); + anAbility = (Ability) anAbility.clone(); + + if (choices.size() > 0) + { + addChoicesToAbility(anAbility, choices); + } + } - - return finaliseAbility(pcAbility, choice, aPC, addIt, addAll, added, retVal); + + return anAbility; } /** @@ -443,78 +351,61 @@ * the Ability to the character, this method ensures that all necessary * adjustments (choices to add etc.) are made. * - * @param anAbility + * @param ability * @param choice * @param aPC * @param addIt - * @param addAll - * @param added + * @param singleChoice * @param retVal - * * @return 1 if adding the Ability, or 0 if removing it. */ private static int finaliseAbility( - final Ability anAbility, - final String choice, - final PlayerCharacter aPC, - final boolean addIt, - final boolean addAll, - boolean added, - int retVal) + final Ability ability, + final String choice, + final PlayerCharacter aPC, + final boolean addIt, + final boolean singleChoice, + int retVal) { // how many sub-choices to make - double j = (anAbility.getAssociatedCount() * anAbility.getCost(aPC)) + aPC.getFeats(); + double featCount = (ability.getAssociatedCount() * ability.getCost(aPC)) + aPC.getFeats(); -// // process ADD tags from the feat definition - // Don't need this anymore since ADD tags are parsed globally -// if (!addIt) -// { -// anAbility.modAdds(addIt, aPC); -// } - boolean canSetFeats = true; - if (addIt || anAbility.isMultiples()) + if (singleChoice && (addIt || ability.isMultiples())) { - if (!addAll) + if ("".equals(choice)) { - if ("".equals(choice)) + // Allow sub-choices + canSetFeats = !ability.modChoices(aPC, addIt); + } + else if (addIt) + { + if (ability.canAddAssociation(choice)) { - // Allow sub-choices - canSetFeats = !anAbility.modChoices(aPC, addIt); + ability.addAssociated(choice); } - else - { - if ( - addIt && - (anAbility.isStacks() || !anAbility.containsAssociated(choice))) - { - anAbility.addAssociated(choice); - } - else if (!addIt && anAbility.containsAssociated(choice)) - { - anAbility.removeAssociated(choice); - } - } } + else + { + ability.removeAssociated(choice); + } } - anAbility.modifyChoice(aPC); + ability.modifyChoice(aPC); - if (anAbility.isMultiples() && !addAll) + if (ability.isMultiples() && singleChoice) { - retVal = (anAbility.getAssociatedCount() > 0) ? 1 : 0; + retVal = (ability.getAssociatedCount() > 0) ? 1 : 0; } - // process ADD tags from the feat definition - if (!added && addIt) + if (addIt) { - List l = anAbility.getSafeListFor(ListKey.KITS); - for (int i = 0; i < l.size(); i++) + final List kitList = ability.getSafeListFor(ListKey.KITS); + for (int i = 0; i < kitList.size(); i++) { - KitUtilities.makeKitSelections(0, (String)l.get(i), 1, aPC); + KitUtilities.makeKitSelections(0, (String)kitList.get(i), 1, aPC); } - // anAbility.modAdds(addIt, aPC); } // if no sub choices made (i.e. all of them removed in Chooser box), @@ -523,53 +414,52 @@ if (retVal == 0) { - removed = aPC.removeRealFeat(anAbility); - aPC.removeNaturalWeapons(anAbility); + removed = aPC.removeRealFeat(ability); + aPC.removeNaturalWeapons(ability); - for (int x = 0; x < anAbility.templatesAdded().size(); ++x) + for (int x = 0; x < ability.templatesAdded().size(); ++x) { - aPC.removeTemplate( - aPC.getTemplateNamed((String) anAbility.templatesAdded().get(x))); + aPC.removeTemplate(aPC.getTemplateNamed((String) ability.templatesAdded().get(x))); } - anAbility.subAddsForLevel(-9, aPC); + ability.subAddsForLevel(-9, aPC); } - if (!addIt && !anAbility.isMultiples() && removed) + if (singleChoice && canSetFeats) { - j += anAbility.getCost(aPC); - } - else if (addIt && !anAbility.isMultiples()) - { - j -= anAbility.getCost(aPC); - } - else - { - int associatedListSize = anAbility.getAssociatedCount(); - - for (Iterator e1 = aPC.getRealFeatsIterator(); e1.hasNext();) + if (!addIt && !ability.isMultiples() && removed) { - final Ability myFeat = (Ability) e1.next(); + featCount += ability.getCost(aPC); + } + else if (addIt && !ability.isMultiples()) + { + featCount -= ability.getCost(aPC); + } + else + { + int listSize = ability.getAssociatedCount(); - if (myFeat.getName().equalsIgnoreCase(anAbility.getName())) + for (final Iterator e1 = aPC.getRealFeatsIterator(); e1.hasNext();) { - associatedListSize = myFeat.getAssociatedCount(); + final Ability myAbility = (Ability) e1.next(); + + if (myAbility.getName().equalsIgnoreCase(ability.getName())) + { + listSize = myAbility.getAssociatedCount(); + } } - } - j -= (associatedListSize * anAbility.getCost(aPC)); + featCount -= (listSize * ability.getCost(aPC)); + } + + aPC.adjustFeats(featCount - aPC.getFeats()); } - if (!addAll && canSetFeats) - { - aPC.adjustFeats(j - aPC.getFeats()); - } - aPC.setAutomaticFeatsStable(false); if (addIt && !aPC.isImporting()) { - anAbility.globalChecks(false, aPC); - anAbility.checkRemovals(aPC); + ability.globalChecks(false, aPC); + ability.checkRemovals(aPC); } return retVal; @@ -577,106 +467,262 @@ /** - * Search the List passed in for an instance of the Ability matching - * category and Ability name. If we don't find it, attempt to locate - * it in global Storage and, if it's there, clone it and add it the List. - * If we got an ability, then add any sub choices from the name to the - * associated list of the ability. - * - * @param theAbilityList A list of abilities to add to - * @param category The category of Ability to add - * @param abilityName The name of the Ability to Add + * Find an ability in a list that matches a given Ability or AbilityInfo + * Object. + * + * @param anAbilityList + * @param abilityInfo + * + * @return the Ability if found, otherwise null */ - static void addToAbilityList( - final List theAbilityList, - final String category, - final String abilityName) + public static Ability getAbilityFromList( + final List anAbilityList, + final Categorisable abilityInfo) { - ArrayList choices = new ArrayList(); - EquipmentUtilities.getUndecoratedName(abilityName, choices); - String subName = choices.size() > 0 ? (String) choices.get(0) : ""; + return getAbilityFromList(anAbilityList, abilityInfo, -1); + } - AbilityInfo abInf = new AbilityInfo("FEAT", abilityName); - Ability anAbility = getAbilityFromList(theAbilityList, abInf); - if (anAbility == null) + /** + * Find an ability in a list that matches a given Ability or AbilityInfo + * Object. Also takes an integer representing a type, -1 always matches, + * otherwise an ability will only be returned if its type is the same as + * abilityType + * + * @param anAbilityList + * @param abilityInfo + * @param abilityType + * + * @return the Ability if found, otherwise null + */ + public static Ability getAbilityFromList( + final List anAbilityList, + final Categorisable abilityInfo, + final int abilityType) + { + if (anAbilityList.isEmpty()) { + return null; + } + + for (final Iterator abListIt = anAbilityList.iterator(); abListIt.hasNext();) { - anAbility = cloneGlobalAbility(category, abilityName); + final Ability anAbility = (Ability) abListIt.next(); - if (anAbility != null) + if (AbilityUtilities.areSameAbility(anAbility, abilityInfo) && + ((abilityType == -1) || (anAbility.getFeatType() == abilityType))) { - anAbility.setFeatType(Ability.ABILITY_AUTOMATIC); - theAbilityList.add(anAbility); + return anAbility; } } - if (anAbility == null && - subName.length() != 0 && - anAbility.canAddAssociation(subName)) + return null; + } + + /** + * Find an ability in a list that matches a given AbilityInfo Object. Also + * takes an integer representing a type, -1 always matches, otherwise an + * ability will only be returned if its type is the same as abilityType + * + * @param anAbilityList + * @param aCat + * @param aName + * @param abilityType + * + * @return the Ability if found, otherwise null + */ + public static Ability getAbilityFromList( + final List anAbilityList, + final String aCat, + final String aName, + final int abilityType) + { + final AbilityInfo abInfo = new AbilityInfo(aCat, aName); + return getAbilityFromList(anAbilityList, abInfo, abilityType); + } + + /** + * Find out if this Categorisable Object can be applied to a character + * multiple times + * + * @param aCatObj + * @return true if can be applied multiple times + */ + private static boolean getIsMultiples( + final Categorisable aCatObj) + { + if (aCatObj instanceof Ability) { - anAbility.addAssociated(subName); + return ((Ability) aCatObj).isMultiples(); } + else if (aCatObj instanceof AbilityInfo) + { + final Ability ability = ((AbilityInfo) aCatObj).getAbility(); + if (ability == null) + { + return false; + } + return ability.isMultiples(); + } + return false; + } + /** + * Add an Ability to a character, allowing sub-choices if necessary. Always adds + * weapon proficiencies, either a single choice if addAll is false, or all + * possible choices if addAll is true. + * @param aPC the PC to add or remove the Feat from + * @param levelInfo LevelInfo object to adjust. + * @param argAbility The ability to process + * @param choice For an isMultiples() Ability + * @param create false means the character must already have the Ability (which + * only makes sense if it allows multiples); true means a new + * instance of the global Ability will be cloned and added to the + * character as a real Ability (this is the only way to add real + * nonvirtual Ability objects). + * @return 1 if adding the Ability or 0 if removing it. + */ + + public static int modAbility( + final PlayerCharacter aPC, + final PCLevelInfo levelInfo, + final Ability argAbility, + final String choice, + final boolean create) + { + final int result = create ? 1 : 0; + + if (argAbility == null) + { + Logging.errorPrint("Can't process null Ability"); + return result; + } + + if (aPC.isNotImporting()) {aPC.getSpellList();} + + final List realAbilities = aPC.getRealFeatsList(); + Ability pcAbility = getAbilityFromList(realAbilities, argAbility); + + // (pcAbility == null) means we don't have this feat, + // so we need to add it + if (create && (pcAbility == null)) + { + // adding feat for first time + pcAbility = (Ability) argAbility.clone(); + + aPC.addFeat(pcAbility, levelInfo); + pcAbility.getTemplates(aPC.isImporting(), aPC); + } + + return finaliseAbility(pcAbility, choice, aPC, create, true, result); } /** - * If an ability in Global storage matches the category and name passed - * in, then return a clone of that Ability. + * Add a Feat to a character, allowing sub-choices if necessary. Always adds + * weapon proficiencies, either a single choice if addAll is false, or all + * possible choices if addAll is true. * - * @param category - * @param abilityName + * @param aPC the PC to add or remove the Feat from + * @param LevelInfo + * @param featName the name of the Feat to add. + * @param addIt false means the character must already have the + * feat (which only makes sense if it + * allows multiples); true means + * to add the feat (the only way to add + * new feats). + * @param singleChoice false means allow sub-choices; true means no sub-choices. * - * @return a clone of a global ability + * @return 1 if adding the Ability but it wasn't there or 0 if the PC does + * not currently have the Ability. */ - private static Ability cloneGlobalAbility( - final String category, - final String abilityName) + public static int modFeat( + final PlayerCharacter aPC, + final PCLevelInfo LevelInfo, + final String featName, + final boolean addIt, + final boolean singleChoice) { - ArrayList choices = new ArrayList(); - final String baseName = EquipmentUtilities.getUndecoratedName(abilityName, choices); - final String subName = choices.size() > 0 ? (String) choices.get(0) : ""; - Ability anAbility; + boolean singleChoice1 = !singleChoice; + if (!aPC.isImporting()) + { + aPC.getSpellList(); + } - anAbility = Globals.getAbilityNamed(category, abilityName); + final ArrayList choices = new ArrayList(); + final int result = addIt ? 1 : 0; + final String undoctoredName = featName; + final String baseName = EquipmentUtilities.getUndecoratedName(featName, choices); + String subName = choices.size() > 0 ? (String) choices.get(0) : ""; - if ((anAbility == null) && (baseName.length() != 0)) + // See if our choice is not auto or virtual + Ability anAbility = aPC.getRealFeatNamed(undoctoredName); + + // if a feat named featName doesn't exist, and featName + // contains a (blah) descriptor, try removing it. + if (anAbility == null) { - anAbility = Globals.getAbilityNamed(category, baseName); + anAbility = aPC.getRealFeatNamed(baseName); + + if (!singleChoice1 && (anAbility != null) && (subName.length() != 0)) + { + singleChoice1 = true; + } } - if (anAbility != null) + // (anAbility == null) means we don't have this feat, so we need to add it + if ((anAbility == null) && addIt) { - anAbility = (Ability) anAbility.clone(); - if (subName.length() > 0) + // Adding feat for first time + anAbility = Globals.getAbilityNamed("FEAT", baseName); + + if (anAbility == null) { - anAbility.addAssociated(subName); + anAbility = Globals.getAbilityNamed("FEAT", undoctoredName); + + if (anAbility != null) + { + subName = ""; + } } + + if (anAbility == null) + { + Logging.errorPrint("Feat not found: " + undoctoredName); + + return result; + } + + anAbility = (Ability) anAbility.clone(); + + aPC.addFeat(anAbility, LevelInfo); + anAbility.getTemplates(aPC.isImporting(), aPC); } - else + + /* + * Could not find the Ability: addIt true means that no global Ability called + * featName exists, addIt false means that the PC does not have this ability + */ + if (anAbility == null) { - ShowMessageDelegate.showMessageDialog( - "Adding unknown feat: " + abilityName, - Constants.s_APPNAME, - MessageType.INFORMATION); + return result; } - return anAbility; + return finaliseAbility(anAbility, subName, aPC, addIt, singleChoice1, result); } - /** * Add multiple feats from a String list separated by commas. * @param aPC - * @param playerCharacterLevelInfo + * @param LevelInfo * @param aList * @param addIt * @param all */ - static void modFeatsFromList(final PlayerCharacter aPC, - final PCLevelInfo playerCharacterLevelInfo, - final String aList, - final boolean addIt, - final boolean all) + static void modFeatsFromList( + final PlayerCharacter aPC, + final PCLevelInfo LevelInfo, + final String aList, + final boolean addIt, + final boolean all) { final StringTokenizer aTok = new StringTokenizer(aList, ","); @@ -731,7 +777,7 @@ { // add the Feat found, as a CharacterFeat anAbility = (Ability) anAbility.clone(); - aPC.addFeat(anAbility, playerCharacterLevelInfo); + aPC.addFeat(anAbility, LevelInfo); } } @@ -753,7 +799,7 @@ } anAbility = (Ability) anAbility.clone(); - aPC.addFeat(anAbility, playerCharacterLevelInfo); + aPC.addFeat(anAbility, LevelInfo); } if ((bTok != null) && bTok.hasMoreTokens()) @@ -810,14 +856,13 @@ } } - modFeat(aPC, playerCharacterLevelInfo, aString, addIt, all); + modFeat(aPC, LevelInfo, aString, addIt, all); } } aPC.setAutomaticFeatsStable(false); } - /** * Build and return a list of the Ability objects associated with the given * PlayerCharacter object @@ -826,8 +871,8 @@ * @return a List of the Abilities this Character has */ - static public List rebuildAutoAbilityList(PlayerCharacter aPc) { - + static public List rebuildAutoAbilityList(PlayerCharacter aPc) + { final List autoFeatList; autoFeatList = new ArrayList(); @@ -840,7 +885,8 @@ while (aTok.hasMoreTokens()) { - addToAbilityList(autoFeatList, "FEAT", aTok.nextToken()); + Ability added = addCloneOfGlobalAbilityToListWithChoices(autoFeatList, "FEAT", aTok.nextToken()); + added.setFeatType(Ability.ABILITY_AUTOMATIC); } } @@ -920,7 +966,8 @@ } } - addToAbilityList(autoFeatList, "FEAT", autoFeat); + Ability added = addCloneOfGlobalAbilityToListWithChoices(autoFeatList, "FEAT", autoFeat); + added.setFeatType(Ability.ABILITY_AUTOMATIC); } } @@ -941,7 +988,8 @@ while (aTok.hasMoreTokens()) { - addToAbilityList(autoFeatList, "FEAT", aTok.nextToken()); + Ability added = addCloneOfGlobalAbilityToListWithChoices(autoFeatList, "FEAT", aTok.nextToken()); + added.setFeatType(Ability.ABILITY_AUTOMATIC); } } } @@ -967,7 +1015,8 @@ if (idx > -1) { - addToAbilityList(autoFeatList, "FEAT", aString.substring(idx + 1)); + Ability added = addCloneOfGlobalAbilityToListWithChoices(autoFeatList, "FEAT", aString.substring(idx + 1)); + added.setFeatType(Ability.ABILITY_AUTOMATIC); } else { @@ -981,282 +1030,53 @@ for (; anIt.hasNext();) { final AbilityInfo abI = (AbilityInfo) anIt.next(); - addToAbilityList(autoFeatList, "FEAT", abI.getKeyName()); + Ability added = addCloneOfGlobalAbilityToListWithChoices(autoFeatList, "FEAT", abI.getKeyName()); + added.setFeatType(Ability.ABILITY_AUTOMATIC); } } } } - // // Need to save current as stable as getAutoWeaponProfs() needs it - // + aPc.setStableAutomaticFeatList(autoFeatList); aPc.getAutoWeaponProfs(autoFeatList); aPc.setStableAutomaticFeatList(autoFeatList); return autoFeatList; } - /** - * Extracts the contents of the first set of balanced parenthesis (including - * any properly nested parenthesis). "foo (bar, baz)" returns "bar, baz". + * This method attempts to get an Ability Object from the Global Store keyed + * by token. If this fails, it checks if token has info in parenthesis + * appended to it. If it does, it strips this and attempts to get an + * Ability Keyed by the stripped token. If this works, it passes back this + * Ability, if it does not work, it returns null. * - * @param aString the input string - * @return the contents of the parenthesis - */ - static public String extractContentsOfFirstBalancedParens(String aString) { - - int open = 0; - int start = aString.indexOf('('); - int end = start; - - if (end > -1) { - while (end < aString.length()) { - switch (aString.charAt(end)) { - case '(': - open += 1; - break; - - case ')': - open -= 1; - break; - - default: - } - - if (open < 1) { - break; - } - end++; - } - } - - if (open < 1) { - aString = aString.substring(start, end); - } - return aString; - } - - - /** - * Given the string "token<Prereq1|Prereq2|Prereq3>", this will clear preReqArray, - * then populate it with "Prereq1", "Prereq2", "Prereq3" and return token. + * @param cat The category of Ability Object to retrieve + * @param token The name of the Ability Object * - * @param aString "token<Prereq1|Prereq2|Prereq3>" - * @param preReqArray will contain any prereqs after the routine returns - * - * @return the token + * @return The ability in category "cat" called "token" */ - public static String extractTokenPrerequities(String aString, final List preReqArray) { + public static Ability retrieveAbilityKeyed( + final String cat, + final String token) + { + Ability ability = Globals.getAbilityKeyed(cat, token); - preReqArray.clear(); - String tokenString = aString; - String pString = ""; - - final StringTokenizer preTok = new StringTokenizer(aString, "<>|", true); - - if (preTok.hasMoreTokens()) { - tokenString = preTok.nextToken(); - } - - while (preTok.hasMoreTokens() && !(">").equals(pString)) + if (ability != null) { - pString = preTok.nextToken(); - - if ((pString.startsWith("PRE") || pString.startsWith("!PRE"))) - { - preReqArray.add(pString); - } + return ability; } - return tokenString; - } + final String stripped = EquipmentUtilities.removeChoicesFromName(token); + ability = Globals.getAbilityKeyed(cat, stripped); - /** - * Find an ability in a list that matches a given AbilityInfo Object. Also - * takes an integer representing a type, -1 always matches, otherwise an - * ability will only be returned if its type is the same as abilityType - * - * @param anAbilityList - * @param aCat - * @param aName - * @param abilityType - * - * @return the Ability if found, otherwise null - */ - public static Ability getAbilityFromList( - final List anAbilityList, - final String aCat, - final String aName, - final int abilityType) - { - AbilityInfo abInfo = new AbilityInfo(aCat, aName); - return getAbilityFromList(anAbilityList, abInfo, abilityType); - } - - /** - * Find an ability in a list that matches a given Ability or AbilityInfo - * Object. - * - * @param anAbilityList - * @param abilityInfo - * - * @return the Ability if found, otherwise null - */ - public static Ability getAbilityFromList( - final List anAbilityList, - final Categorisable abilityInfo) - { - return getAbilityFromList(anAbilityList, abilityInfo, -1); - } - - /** - * Find an ability in a list that matches a given Ability or AbilityInfo - * Object. Also takes an integer representing a type, -1 always matches, - * otherwise an ability will only be returned if its type is the same as - * abilityType - * - * @param anAbilityList - * @param abilityInfo - * @param abilityType - * - * @return the Ability if found, otherwise null - */ - public static Ability getAbilityFromList( - final List anAbilityList, - final Categorisable abilityInfo, - final int abilityType) - { - if (anAbilityList.isEmpty()) { - return null; + if (ability != null) + { + return ability; } - for (Iterator abListIt = anAbilityList.iterator(); abListIt.hasNext();) { - final Ability anAbility = (Ability) abListIt.next(); - - if (AbilityUtilities.areSameAbility(anAbility, abilityInfo)) { - if ((abilityType == -1) || (anAbility.getFeatType() == abilityType)) { - return anAbility; - } - } - } - return null; } - /** - * Do the strings passed in represent the same Ability object in the - * Category category? - * - * @param category - * @param first - * @param second - * @return true if the same object is represented - */ - static public boolean areSameAbility( - final String category, - final String first, - final String second) - { - if (category == null || first == null || second == null) { - return false; - } - Categorisable newFirst = new AbilityInfo(category, first); - return areSameAbility(newFirst, second); - } - - /** - * Do the Categorisable object and the string passed in represent the - * same ability? the string is assumed to be in the same Category as the - * Categorisable object. - * - * @param first - * @param second - * @return true if the same object is represented - */ - static public boolean areSameAbility( - final Categorisable first, - final String second) - { - if (first == null || second == null) { - return false; - } - Categorisable newSecond = new AbilityInfo(first.getCategory(), second); - return areSameAbility(first, newSecond); - } - - /** - * Do the Categorisable objects passed in represent the same ability? - * - * @param first - * @param second - * @return true if the same object is represented - */ - static public boolean areSameAbility( - final Categorisable first, - final Categorisable second) - { - if (first == null || second == null) { - return false; - } - - boolean multFirst = getIsMultiples(first); - boolean multSecond = getIsMultiples(second); - boolean nameCheck = false; - - if (multFirst && multSecond) { - /* - * The are both Multiply applicable, so strip the decorations (parts - * in brackets) from the name, then check the undecorated names are - * equal. - */ - ArrayList decorationsThis = new ArrayList(); - ArrayList decorationsThat = new ArrayList(); - String undecoratedThis = EquipmentUtilities.getUndecoratedName(first.getKeyName(), decorationsThis); - String undecoratedThat = EquipmentUtilities.getUndecoratedName(second.getKeyName(), decorationsThat); - nameCheck = undecoratedThis.compareToIgnoreCase(undecoratedThat) == 0; - - } else if (multFirst || multSecond) { - - // one is multiply applicable but the other isn't. They can't be the - // same Ability - return false; - } else { - - /* - * They're not multiply selectable, so anything in brackets isn't a - * choice, it's part of the name - */ - nameCheck = first.getKeyName().compareToIgnoreCase(second.getKeyName()) == 0; - } - - return (nameCheck && first.getCategory().compareToIgnoreCase(second.getCategory()) == 0); - } - - /** - * Find out if this Categorisable Object can be applied to a character - * multiple times - * - * @param aCatObj - * @return true if can be applied multiple times - */ - private static boolean getIsMultiples( - final Categorisable aCatObj) - { - if (aCatObj instanceof Ability) - { - return ((Ability) aCatObj).isMultiples(); - } - else if (aCatObj instanceof AbilityInfo) - { - Ability ability = ((AbilityInfo) aCatObj).getAbility(); - if (ability == null) - { - return false; - } - return ability.isMultiples(); - } - return false; - } - } Modified: Trunk/pcgen/code/src/java/pcgen/core/levelability/LevelAbilityAbility.java =================================================================== --- Trunk/pcgen/code/src/java/pcgen/core/levelability/LevelAbilityAbility.java 2006-04-16 04:03:20 UTC (rev 821) +++ Trunk/pcgen/code/src/java/pcgen/core/levelability/LevelAbilityAbility.java 2006-04-16 04:41:32 UTC (rev 822) @@ -602,15 +602,13 @@ previousChoices.add(ab); List aList = aPC.getVirtualFeatList(); - aList = AbilityUtilities.addVirtualFeat( + final Ability pcAbility = AbilityUtilities.addVirtualAbility( ab, choiceList, aList, - aPC, pcLevelInfo); - final Ability pcAbility = AbilityUtilities.getMatchingFeatInList(aList, ab); -// final Ability pcAbility = AbilityUtilities.getAbilityFromList(aList, ab); + aPC.setDirty(true); if (pcAbility != null) { @@ -668,7 +666,7 @@ aBonusList.add(bonusIt.next()); } } - AbilityUtilities.modAbility(aPC, pcLevelInfo, ab, choice, true, false); + AbilityUtilities.modAbility(aPC, pcLevelInfo, ab, choice, true); if (spellLevelProcess && (ab != null)) { Modified: Trunk/pcgen/code/src/java/pcgen/core/levelability/LevelAbilityFeat.java =================================================================== --- Trunk/pcgen/code/src/java/pcgen/core/levelability/LevelAbilityFeat.java 2006-04-16 04:03:20 UTC (rev 821) +++ Trunk/pcgen/code/src/java/pcgen/core/levelability/LevelAbilityFeat.java 2006-04-16 04:41:32 UTC (rev 822) @@ -187,11 +187,9 @@ final String featName = selectedList.get(index).toString(); previousChoices.add(featName); - List aList = aPC.getVirtualFeatList(); - aList = AbilityUtilities.addVirtualFeat(featName, aList, pcLevelInfo, aPC); + final Ability aFeat = AbilityUtilities.addVirtualAbility("FEAT", featName, aPC.getVirtualFeatList(), pcLevelInfo); + aPC.setDirty(true); - final Ability aFeat = AbilityUtilities.getAbilityFromList(aList, "FEAT", featName, -1); - if (aFeat != null) { if (aFeat.isMultiples()) Modified: Trunk/pcgen/code/src/java/pcgen/io/PCGVer2Parser.java =================================================================== --- Trunk/pcgen/code/src/java/pcgen/io/PCGVer2Parser.java 2006-04-16 04:03:20 UTC (rev 821) +++ Trunk/pcgen/code/src/java/pcgen/io/PCGVer2Parser.java 2006-04-16 04:41:32 UTC (rev 822) @@ -3399,9 +3399,9 @@ return; } - AbilityUtilities.addVirtualFeat(abilityKey, aPC.getVirtualFeatList(), null, aPC); - anAbility = AbilityUtilities.getAbilityFromList(aPC.getVirtualFeatList(), "FEAT", abilityKey, -1); + anAbility = AbilityUtilities.addVirtualAbility("FEAT", abilityKey, aPC.getVirtualFeatList(), null); anAbility.setNeedsSaving(true); + aPC.setDirty(true); } parseFeatsHandleAppliedToAndSaveTags(it, anAbility, line); Modified: Trunk/pcgen/code/testsuite/csheets/BarJack.xml =================================================================== --- Trunk/pcgen/code/testsuite/csheets/BarJack.xml 2006-04-16 04:03:20 UTC (rev 821) +++ Trunk/pcgen/code/testsuite/csheets/BarJack.xml 2006-04-16 04:41:32 UTC (rev 822) @@ -1160,8 +1160,8 @@ <name>Armor Proficiency (Light)</name> <description>When a character wears a type of armor with which the character is proficient, the armor check penalty applies only to Balance, Climb, Escape Artist, Hide, Jump, Move Silently, Pick Pocket, and Tumble checks.</description> <type>GENERAL</type> - <associated>Light</associated> - <count>1</count> + <associated></associated> + <count>0</count> <auto>T</auto> <hidden>F</hidden> <virtual>F</virtual> @@ -1170,8 +1170,8 @@ <name>Armor Proficiency (Medium)</name> <description>When a character wears a type of armor with which the character is proficient, the armor check penalty applies only to Balance, Climb, Escape Artist, Hide, Jump, Move Silently, Pick Pocket, and Tumble checks.</description> <type>GENERAL</type> - <associated>Medium</associated> - <count>1</count> + <associated></associated> + <count>0</count> <auto>T</auto> <hidden>F</hidden> <virtual>F</virtual> Modified: Trunk/pcgen/code/testsuite/csheets/BrdJoe.xml =================================================================== --- Trunk/pcgen/code/testsuite/csheets/BrdJoe.xml 2006-04-16 04:03:20 UTC (rev 821) +++ Trunk/pcgen/code/testsuite/csheets/BrdJoe.xml 2006-04-16 04:41:32 UTC (rev 822) @@ -1032,8 +1032,8 @@ <name>Armor Proficiency (Light)</name> <description>When a character wears a type of armor with which the character is proficient, the armor check penalty applies only to Balance, Climb, Escape Artist, Hide, Jump, Move Silently, Pick Pocket, and Tumble checks.</description> <type>GENERAL</type> - <associated>Light</associated> - <count>1</count> + <associated></associated> + <count>0</count> <auto>T</auto> <hidden>F</hidden> <virtual>F</virtual> @@ -1042,8 +1042,8 @@ <name>Armor Proficiency (Medium)</name> <description>When a character wears a type of armor with which the character is proficient, the armor check penalty applies only to Balance, Climb, Escape Artist, Hide, Jump, Move Silently, Pick Pocket, and Tumble checks.</description> <type>GENERAL</type> - <associated>Medium</associated> - <count>1</count> + <associated></associated> + <count>0</count> <auto>T</auto> <hidden>F</hidden> <virtual>F</virtual> Modified: Trunk/pcgen/code/testsuite/csheets/CleElf.xml =================================================================== --- Trunk/pcgen/code/testsuite/csheets/CleElf.xml 2006-04-16 04:03:20 UTC (rev 821) +++ Trunk/pcgen/code/testsuite/csheets/CleElf.xml 2006-04-16 04:41:32 UTC (rev 822) @@ -1259,8 +1259,8 @@ <name>Armor Proficiency (Heavy)</name> <description>When a character wears a type of armor with which the character is proficient, the armor check penalty applies only to Balance, Climb, Escape Artist, Hide, Jump, Move Silently, Pick Pocket, and Tumble checks.</description> <type>GENERAL</type> - <associated>Heavy</associated> - <count>1</count> + <associated></associated> + <count>0</count> <auto>T</auto> <hidden>F</hidden> <virtual>F</virtual> @@ -1269,8 +1269,8 @@ <name>Armor Proficiency (Light)</name> <description>When a character wears a type of armor with which the character is proficient, the armor check penalty applies only to Balance, Climb, Escape Artist, Hide, Jump, Move Silently, Pick Pocket, and Tumble checks.</description> <type>GENERAL</type> - <associated>Light</associated> - <count>1</count> + <associated></associated> + <count>0</count> <auto>T</auto> <hidden>F</hidden> <virtual>F</virtual> @@ -1279,8 +1279,8 @@ <name>Armor Proficiency (Medium)</name> <description>When a character wears a type of armor with which the character is proficient, the armor check penalty applies only to Balance, Climb, Escape Artist, Hide, Jump, Move Silently, Pick Pocket, and Tumble checks.</description> <type>GENERAL</type> - <associated>Medium</associated> - <count>1</count> + <associated></associated> + <count>0</count> <auto>T</auto> <hidden>F</hidden> <virtual>F</virtual> Modified: Trunk/pcgen/code/testsuite/csheets/FigFae.xml =================================================================== --- Trunk/pcgen/code/testsuite/csheets/FigFae.xml 2006-04-16 04:03:20 UTC (rev 821) +++ Trunk/pcgen/code/testsuite/csheets/FigFae.xml 2006-04-16 04:41:32 UTC (rev 822) @@ -1065,8 +1065,8 @@ <name>Armor Proficiency (Heavy)</name> <description>When a character wears a type of armor with which the character is proficient, the armor check penalty applies only to Balance, Climb, Escape Artist, Hide, Jump, Move Silently, Pick Pocket, and Tumble checks.</description> <type>GENERAL</type> - <associated>Heavy</associated> - <count>1</count> + <associated></associated> + <count>0</count> <auto>T</auto> <hidden>F</hidden> <virtual>F</virtual> @@ -1075,8 +1075,8 @@ <name>Armor Proficiency (Light)</name> <description>When a character wears a type of armor with which the character is proficient, the armor check penalty applies only to Balance, Climb, Escape Artist, Hide, Jump, Move Silently, Pick Pocket, and Tumble checks.</description> <type>GENERAL</type> - <associated>Light</associated> - <count>1</count> + <associated></associated> + <count>0</count> <auto>T</auto> <hidden>F</hidden> <virtual>F</virtual> @@ -1085,8 +1085,8 @@ <name>Armor Proficiency (Medium)</name> <description>When a character wears a type of armor with which the character is proficient, the armor check penalty applies only to Balance, Climb, Escape Artist, Hide, Jump, Move Silently, Pick Pocket, and Tumble checks.</description> <type>GENERAL</type> - <associated>Medium</associated> - <count>1</count> + <associated></associated> + <count>0</count> <auto>T</auto> <hidden>F</hidden> <virtual>F</virtual> Modified: Trunk/pcgen/code/testsuite/csheets/JimDop.xml =================================================================== --- Trunk/pcgen/code/testsuite/csheets/JimDop.xml 2006-04-16 04:03:20 UTC (rev 821) +++ Trunk/pcgen/code/testsuite/csheets/JimDop.xml 2006-04-16 04:41:32 UTC (rev 822) @@ -1209,8 +1209,8 @@ <name>Armor Proficiency (Heavy)</name> <description>When you wear a type of armor with which you are proficient, the armor check penalty for that armor applies only to Balance, Climb, Escape Artist, Hide, Jump, Move Silently, Pick Pocket, and Tumble checks.</description> <type>GENERAL</type> - <associated>Heavy</associated> - <count>1</count> + <associated></associated> + <count>0</count> <auto>T</auto> <hidden>F</hidden> <virtual>F</virtual> @@ -1219,8 +1219,8 @@ <name>Armor Proficiency (Light)</name> <description>When you wear a type of armor with which you are proficient, the armor check penalty for that armor applies only to Balance, Climb, Escape Artist, Hide, Jump, Move Silently, Pick Pocket, and Tumble checks.</description> <type>GENERAL</type> - <associated>Light</associated> - <count>1</count> + <associated></associated> + <count>0</count> <auto>T</auto> <hidden>F</hidden> <virtual>F</virtual> @@ -1229,8 +1229,8 @@ <name>Armor Proficiency (Medium)</name> <description>When you wear a type of armor with which you are proficient, the armor check penalty for that armor applies only to Balance, Climb, Escape Artist, Hide, Jump, Move Silently, Pick Pocket, and Tumble checks.</description> <type>GENERAL</type> - <associated>Medium</associated> - <count>1</count> + <associated></associated> + <count>0</count> <auto>T</auto> <hidden>F</hidden> <virtual>F</virtual> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |