Search in sources :

Example 6 with Nature

use of pcgen.cdom.enumeration.Nature in project pcgen by PCGen.

the class AbilityLst method unparse.

@Override
public String[] unparse(LoadContext context, CDOMObject obj) {
    Collection<CDOMReference<? extends CDOMList<?>>> changedLists = context.getListContext().getChangedLists(obj, AbilityList.class);
    Changes<ListKey<ChooseSelectionActor<?>>> actors = context.getObjectContext().getListChanges(obj, ListKey.GA_CAKEYS);
    Set<String> returnSet = new TreeSet<>();
    TripleKeyMapToList<Nature, CDOMSingleRef<AbilityCategory>, List<Prerequisite>, CDOMReference<Ability>> m = new TripleKeyMapToList<>();
    TripleKeyMapToList<Nature, CDOMSingleRef<AbilityCategory>, List<Prerequisite>, CDOMReference<Ability>> clear = new TripleKeyMapToList<>();
    Changes<ChooseSelectionActor<?>> listChanges = context.getObjectContext().getListChanges(obj, ListKey.NEW_CHOOSE_ACTOR);
    Collection<ChooseSelectionActor<?>> listAdded = listChanges.getAdded();
    if (listAdded != null && !listAdded.isEmpty()) {
        for (ChooseSelectionActor<?> csa : listAdded) {
            if (csa.getSource().equals(getTokenName())) {
                try {
                    AbilitySelector as = (AbilitySelector) csa;
                    StringBuilder sb = new StringBuilder();
                    sb.append(as.getAbilityCategory().getLSTformat(false)).append(Constants.PIPE);
                    sb.append(as.getNature()).append(Constants.PIPE);
                    sb.append(as.getLstFormat());
                    returnSet.add(sb.toString());
                } catch (PersistenceLayerException e) {
                    context.addWriteMessage(getTokenName() + " encountered error: " + e.getMessage());
                    return null;
                }
            }
        }
    }
    for (CDOMReference ref : changedLists) {
        AssociatedChanges<CDOMReference<Ability>> changes = context.getListContext().getChangesInList(getTokenName(), obj, ref);
        if (changes.includesGlobalClear()) {
            CDOMDirectSingleRef<AbilityList> dr = (CDOMDirectSingleRef<AbilityList>) ref;
            AbilityList al = dr.get();
            StringBuilder sb = new StringBuilder();
            sb.append(al.getCategory().getLSTformat(false)).append(Constants.PIPE);
            sb.append(al.getNature()).append(Constants.PIPE);
            sb.append(Constants.LST_DOT_CLEAR);
            returnSet.add(sb.toString());
        }
        MapToList<CDOMReference<Ability>, AssociatedPrereqObject> mtl = changes.getAddedAssociations();
        if (mtl != null) {
            for (CDOMReference<Ability> ab : mtl.getKeySet()) {
                for (AssociatedPrereqObject assoc : mtl.getListFor(ab)) {
                    Nature nature = assoc.getAssociation(AssociationKey.NATURE);
                    CDOMSingleRef<AbilityCategory> cat = assoc.getAssociation(AssociationKey.CATEGORY);
                    m.addToListFor(nature, cat, assoc.getPrerequisiteList(), ab);
                }
            }
        }
        mtl = changes.getRemovedAssociations();
        if (mtl != null) {
            for (CDOMReference<Ability> ab : mtl.getKeySet()) {
                for (AssociatedPrereqObject assoc : mtl.getListFor(ab)) {
                    Nature nature = assoc.getAssociation(AssociationKey.NATURE);
                    CDOMSingleRef<AbilityCategory> cat = assoc.getAssociation(AssociationKey.CATEGORY);
                    clear.addToListFor(nature, cat, assoc.getPrerequisiteList(), ab);
                }
            }
        }
    }
    for (Nature nature : m.getKeySet()) {
        for (CDOMSingleRef<AbilityCategory> category : m.getSecondaryKeySet(nature)) {
            for (List<Prerequisite> prereqs : m.getTertiaryKeySet(nature, category)) {
                StringBuilder sb = new StringBuilder();
                sb.append(category.getLSTformat(false)).append(Constants.PIPE);
                sb.append(nature);
                List<CDOMReference<Ability>> clearList = clear.removeListFor(nature, category, prereqs);
                if (clearList != null && !clearList.isEmpty()) {
                    sb.append(Constants.PIPE);
                    sb.append(Constants.LST_DOT_CLEAR_DOT);
                    sb.append(ReferenceUtilities.joinLstFormat(clearList, Constants.PIPE + Constants.LST_DOT_CLEAR_DOT));
                }
                sb.append(Constants.PIPE);
                sb.append(ReferenceUtilities.joinLstFormat(m.getListFor(nature, category, prereqs), Constants.PIPE));
                if (prereqs != null && !prereqs.isEmpty()) {
                    sb.append(Constants.PIPE);
                    sb.append(getPrerequisiteString(context, prereqs));
                }
                returnSet.add(sb.toString());
            }
        }
    }
    for (Nature nature : clear.getKeySet()) {
        for (CDOMSingleRef<AbilityCategory> category : clear.getSecondaryKeySet(nature)) {
            for (List<Prerequisite> prereqs : clear.getTertiaryKeySet(nature, category)) {
                StringBuilder sb = new StringBuilder();
                sb.append(category.getLSTformat(false)).append(Constants.PIPE);
                sb.append(nature).append(Constants.PIPE).append(Constants.LST_DOT_CLEAR_DOT);
                sb.append(ReferenceUtilities.joinLstFormat(clear.getListFor(nature, category, prereqs), Constants.PIPE + Constants.LST_DOT_CLEAR_DOT));
                if (prereqs != null && !prereqs.isEmpty()) {
                    sb.append(Constants.PIPE);
                    sb.append(getPrerequisiteString(context, prereqs));
                }
                returnSet.add(sb.toString());
            }
        }
    }
    Collection<ListKey<ChooseSelectionActor<?>>> addedActors = actors.getAdded();
    if (addedActors != null) {
        for (ListKey<ChooseSelectionActor<?>> lk : addedActors) {
            Changes<ChooseSelectionActor<?>> cras = context.getObjectContext().getListChanges(obj, lk);
            for (ChooseSelectionActor<?> cra : cras.getAdded()) {
                if (getTokenName().equals(cra.getSource())) {
                    try {
                        AbilityTargetSelector ats = (AbilityTargetSelector) cra;
                        StringBuilder sb = new StringBuilder();
                        sb.append(ats.getAbilityCategory().getLSTformat(false)).append(Constants.PIPE);
                        sb.append(ats.getNature()).append(Constants.PIPE).append(cra.getLstFormat());
                        List<Prerequisite> prereqs = ats.getPrerequisiteList();
                        if (prereqs != null && !prereqs.isEmpty()) {
                            sb.append(Constants.PIPE);
                            sb.append(getPrerequisiteString(context, prereqs));
                        }
                        returnSet.add(sb.toString());
                    } catch (PersistenceLayerException e) {
                        context.addWriteMessage(getTokenName() + " encountered error: " + e.getMessage());
                        return null;
                    }
                }
            }
        }
    }
    if (returnSet.isEmpty()) {
        return null;
    }
    return returnSet.toArray(new String[returnSet.size()]);
}
Also used : ChooseSelectionActor(pcgen.cdom.base.ChooseSelectionActor) AbilitySelector(pcgen.cdom.helper.AbilitySelector) ListKey(pcgen.cdom.enumeration.ListKey) TreeSet(java.util.TreeSet) ArrayList(java.util.ArrayList) TripleKeyMapToList(pcgen.base.util.TripleKeyMapToList) CDOMList(pcgen.cdom.base.CDOMList) List(java.util.List) MapToList(pcgen.base.util.MapToList) AbilityList(pcgen.cdom.list.AbilityList) AssociatedPrereqObject(pcgen.cdom.base.AssociatedPrereqObject) Nature(pcgen.cdom.enumeration.Nature) Ability(pcgen.core.Ability) AbilityTargetSelector(pcgen.cdom.helper.AbilityTargetSelector) CDOMDirectSingleRef(pcgen.cdom.reference.CDOMDirectSingleRef) AbilityList(pcgen.cdom.list.AbilityList) CDOMSingleRef(pcgen.cdom.reference.CDOMSingleRef) PersistenceLayerException(pcgen.persistence.PersistenceLayerException) TripleKeyMapToList(pcgen.base.util.TripleKeyMapToList) CDOMList(pcgen.cdom.base.CDOMList) CDOMReference(pcgen.cdom.base.CDOMReference) AbilityCategory(pcgen.core.AbilityCategory) Prerequisite(pcgen.core.prereq.Prerequisite)

Example 7 with Nature

use of pcgen.cdom.enumeration.Nature in project pcgen by PCGen.

the class AbilityLst method parseTokenWithSeparator.

@Override
protected ParseResult parseTokenWithSeparator(LoadContext context, CDOMObject obj, String value) {
    if (obj instanceof Ungranted) {
        return new ParseResult.Fail("Cannot use " + getTokenName() + " on an Ungranted object type: " + obj.getClass().getSimpleName(), context);
    }
    StringTokenizer tok = new StringTokenizer(value, Constants.PIPE);
    String cat = tok.nextToken();
    CDOMSingleRef<AbilityCategory> acRef = context.getReferenceContext().getCDOMReference(ABILITY_CATEGORY_CLASS, cat);
    if (!tok.hasMoreTokens()) {
        return new ParseResult.Fail(getTokenName() + " must have a Nature, " + "Format is: CATEGORY|NATURE|AbilityName: " + value, context);
    }
    final String natureKey = tok.nextToken();
    Nature nature;
    try {
        nature = Nature.valueOf(natureKey);
    } catch (IllegalArgumentException iae) {
        return new ParseResult.Fail(getTokenName() + " refers to invalid Ability Nature: " + natureKey, context);
    }
    if (Nature.ANY.equals(nature)) {
        return new ParseResult.Fail(getTokenName() + " refers to ANY Ability Nature, cannot be used in " + getTokenName() + ": " + value, context);
    }
    if (!tok.hasMoreTokens()) {
        return new ParseResult.Fail(getTokenName() + " must have abilities, Format is: " + "CATEGORY|NATURE|AbilityName: " + value, context);
    }
    String token = tok.nextToken();
    if (looksLikeAPrerequisite(token)) {
        return new ParseResult.Fail("Cannot have only PRExxx subtoken in " + getTokenName() + ": " + value, context);
    }
    String lkString = "GA_CA_" + cat + '_' + natureKey;
    ListKey glk = ListKey.getKeyFor(ChooseSelectionActor.class, lkString);
    ListKey<ChooseSelectionActor<?>> lk = glk;
    ArrayList<PrereqObject> edgeList = new ArrayList<>();
    CDOMReference<AbilityList> abilList = AbilityList.getAbilityListReference(acRef, nature);
    boolean first = true;
    boolean removed = false;
    ReferenceManufacturer<Ability> rm = context.getReferenceContext().getManufacturer(ABILITY_CLASS, ABILITY_CATEGORY_CLASS, cat);
    if (rm == null) {
        return new ParseResult.Fail("Could not get Reference Manufacturer for Category: " + cat, context);
    }
    boolean prereqsAllowed = true;
    while (true) {
        if (Constants.LST_DOT_CLEAR.equals(token)) {
            if (!first) {
                return new ParseResult.Fail("  Non-sensical " + getTokenName() + ": .CLEAR was not the first list item: " + value, context);
            }
            context.getListContext().removeAllFromList(getTokenName(), obj, abilList);
            context.getObjectContext().removeFromList(obj, ListKey.GA_CAKEYS, lk);
            context.getObjectContext().removeList(obj, lk);
            removed = true;
        } else if (token.startsWith(Constants.LST_DOT_CLEAR_DOT)) {
            String clearText = token.substring(7);
            CDOMReference<Ability> ref = TokenUtilities.getTypeOrPrimitive(rm, clearText);
            if (ref == null) {
                return ParseResult.INTERNAL_ERROR;
            }
            AssociatedPrereqObject assoc = context.getListContext().removeFromList(getTokenName(), obj, abilList, ref);
            assoc.setAssociation(AssociationKey.NATURE, nature);
            assoc.setAssociation(AssociationKey.CATEGORY, acRef);
            removed = true;
        } else if (Constants.LST_PERCENT_LIST.equals(token)) {
            prereqsAllowed = false;
            AbilitySelector as = new AbilitySelector(getTokenName(), acRef, nature);
            context.getObjectContext().addToList(obj, ListKey.NEW_CHOOSE_ACTOR, as);
        } else {
            CDOMReference<Ability> ability = TokenUtilities.getTypeOrPrimitive(rm, token);
            if (ability == null) {
                return ParseResult.INTERNAL_ERROR;
            }
            ability.setRequiresTarget(true);
            boolean loadList = true;
            List<String> choices = null;
            if (token.indexOf('(') != -1) {
                choices = new ArrayList<>();
                AbilityUtilities.getUndecoratedName(token, choices);
                if (choices.size() == 1) {
                    if (Constants.LST_PERCENT_LIST.equals(choices.get(0)) && (ability instanceof CDOMSingleRef)) {
                        CDOMSingleRef<Ability> ref = (CDOMSingleRef<Ability>) ability;
                        AbilityTargetSelector ats = new AbilityTargetSelector(getTokenName(), acRef, ref, nature);
                        context.getObjectContext().addToList(obj, ListKey.GA_CAKEYS, lk);
                        context.getObjectContext().addToList(obj, lk, ats);
                        edgeList.add(ats);
                        loadList = false;
                    }
                }
            }
            if (loadList) {
                AssociatedPrereqObject assoc = context.getListContext().addToList(getTokenName(), obj, abilList, ability);
                assoc.setAssociation(AssociationKey.NATURE, nature);
                assoc.setAssociation(AssociationKey.CATEGORY, acRef);
                if (choices != null) {
                    assoc.setAssociation(AssociationKey.ASSOC_CHOICES, choices);
                }
                edgeList.add(assoc);
            }
        }
        if (!tok.hasMoreTokens()) {
            // No prereqs, so we're done
            return ParseResult.SUCCESS;
        }
        first = false;
        token = tok.nextToken();
        if (looksLikeAPrerequisite(token)) {
            break;
        }
    }
    if (removed || !prereqsAllowed) {
        return new ParseResult.Fail("Cannot use PREREQs when using .CLEAR, .CLEAR., or %LIST in " + getTokenName(), context);
    }
    while (true) {
        Prerequisite prereq = getPrerequisite(token);
        if (prereq == null) {
            return new ParseResult.Fail("   (Did you put feats after the " + "PRExxx tags in " + getTokenName() + ":?)", context);
        }
        for (PrereqObject edge : edgeList) {
            edge.addPrerequisite(prereq);
        }
        if (!tok.hasMoreTokens()) {
            break;
        }
        token = tok.nextToken();
    }
    return ParseResult.SUCCESS;
}
Also used : ChooseSelectionActor(pcgen.cdom.base.ChooseSelectionActor) ArrayList(java.util.ArrayList) Ungranted(pcgen.cdom.base.Ungranted) AbilitySelector(pcgen.cdom.helper.AbilitySelector) ListKey(pcgen.cdom.enumeration.ListKey) AssociatedPrereqObject(pcgen.cdom.base.AssociatedPrereqObject) Nature(pcgen.cdom.enumeration.Nature) Ability(pcgen.core.Ability) AbilityTargetSelector(pcgen.cdom.helper.AbilityTargetSelector) ParseResult(pcgen.rules.persistence.token.ParseResult) AbilityList(pcgen.cdom.list.AbilityList) CDOMSingleRef(pcgen.cdom.reference.CDOMSingleRef) PrereqObject(pcgen.cdom.base.PrereqObject) AssociatedPrereqObject(pcgen.cdom.base.AssociatedPrereqObject) StringTokenizer(java.util.StringTokenizer) AbilityCategory(pcgen.core.AbilityCategory) CDOMReference(pcgen.cdom.base.CDOMReference) Prerequisite(pcgen.core.prereq.Prerequisite)

Example 8 with Nature

use of pcgen.cdom.enumeration.Nature in project pcgen by PCGen.

the class AbilityToken method parseNonEmptyToken.

@Override
protected ParseResult parseNonEmptyToken(LoadContext context, CDOMObject obj, String value) {
    if (isEmpty(value)) {
        return new ParseResult.Fail("Value in " + getFullName() + " may not be empty", context);
    }
    ParsingSeparator sep = new ParsingSeparator(value, '|');
    sep.addGroupingPair('[', ']');
    sep.addGroupingPair('(', ')');
    String first = sep.next();
    if (!sep.hasNext()) {
        return new ParseResult.Fail("Syntax of ADD:" + getTokenName() + " requires 3 to 4 |: " + value, context);
    }
    String second = sep.next();
    if (!sep.hasNext()) {
        return new ParseResult.Fail("Syntax of ADD:" + getTokenName() + " requires a minimum of three | : " + value, context);
    }
    String third = sep.next();
    Formula count;
    if (sep.hasNext()) {
        count = FormulaFactory.getFormulaFor(first);
        if (!count.isValid()) {
            return new ParseResult.Fail("Count in " + getTokenName() + " was not valid: " + count.toString(), context);
        }
        if (count.isStatic() && count.resolveStatic().doubleValue() <= 0) {
            return new ParseResult.Fail("Count in " + getFullName() + " must be > 0", context);
        }
        first = second;
        second = third;
        third = sep.next();
    } else {
        count = FormulaFactory.ONE;
    }
    if (sep.hasNext()) {
        return new ParseResult.Fail("Syntax of ADD:" + getTokenName() + " has max of four | when a count is not present: " + value, context);
    }
    CDOMSingleRef<AbilityCategory> acRef = context.getReferenceContext().getCDOMReference(ABILITY_CATEGORY_CLASS, first);
    Nature nature = Nature.valueOf(second);
    if (nature == null) {
        return new ParseResult.Fail(getFullName() + ": Invalid ability nature: " + second, context);
    }
    if (Nature.ANY.equals(nature)) {
        return new ParseResult.Fail(getTokenName() + " refers to ANY Ability Nature, cannot be used in " + getTokenName() + ": " + value);
    }
    if (Nature.AUTOMATIC.equals(nature)) {
        return new ParseResult.Fail(getTokenName() + " refers to AUTOMATIC Ability Nature, cannot be used in " + getTokenName() + ": " + value, context);
    }
    ParseResult pr = checkSeparatorsAndNonEmpty(',', third);
    if (!pr.passed()) {
        return pr;
    }
    List<CDOMReference<Ability>> refs = new ArrayList<>();
    ParsingSeparator tok = new ParsingSeparator(third, ',');
    tok.addGroupingPair('[', ']');
    tok.addGroupingPair('(', ')');
    boolean allowStack = false;
    int dupChoices = 0;
    ReferenceManufacturer<Ability> rm = context.getReferenceContext().getManufacturer(ABILITY_CLASS, ABILITY_CATEGORY_CLASS, first);
    if (rm == null) {
        return new ParseResult.Fail("Could not get Reference Manufacturer for Category: " + first, context);
    }
    while (tok.hasNext()) {
        CDOMReference<Ability> ab;
        String token = tok.next();
        if ("STACKS".equals(token)) {
            if (allowStack) {
                return new ParseResult.Fail(getFullName() + " found second stacking specification in value: " + value, context);
            }
            allowStack = true;
            continue;
        } else if (token.startsWith("STACKS=")) {
            if (allowStack) {
                return new ParseResult.Fail(getFullName() + " found second stacking specification in value: " + value, context);
            }
            allowStack = true;
            try {
                dupChoices = Integer.parseInt(token.substring(7));
            } catch (NumberFormatException nfe) {
                return new ParseResult.Fail("Invalid Stack number in " + getFullName() + ": " + value, context);
            }
            if (dupChoices <= 0) {
                return new ParseResult.Fail("Invalid (less than 1) Stack number in " + getFullName() + ": " + value, context);
            }
            continue;
        } else {
            if (Constants.LST_ALL.equals(token)) {
                ab = rm.getAllReference();
            } else {
                ab = TokenUtilities.getTypeOrPrimitive(rm, token);
            }
        }
        if (ab == null) {
            return new ParseResult.Fail("  Error was encountered while parsing " + getTokenName() + ": " + value + " had an invalid reference: " + token, context);
        }
        refs.add(ab);
    }
    if (refs.isEmpty()) {
        return new ParseResult.Fail("Non-sensical " + getFullName() + ": Contains no ability reference: " + value, context);
    }
    AbilityRefChoiceSet rcs = new AbilityRefChoiceSet(acRef, refs, nature);
    if (!rcs.getGroupingState().isValid()) {
        return new ParseResult.Fail("Non-sensical " + getFullName() + ": Contains ANY and a specific reference: " + value, context);
    }
    AbilityChoiceSet cs = new AbilityChoiceSet(getTokenName(), rcs);
    StringBuilder title = new StringBuilder(50);
    if (!Nature.NORMAL.equals(nature)) {
        title.append(nature.toString());
        title.append(' ');
    }
    title.append(first);
    title.append(" Choice");
    cs.setTitle(title.toString());
    PersistentTransitionChoice<CNAbilitySelection> tc = new ConcretePersistentTransitionChoice<>(cs, count);
    context.getObjectContext().addToList(obj, ListKey.ADD, tc);
    tc.allowStack(allowStack);
    if (dupChoices != 0) {
        tc.setStackLimit(dupChoices);
    }
    tc.setChoiceActor(this);
    return ParseResult.SUCCESS;
}
Also used : Nature(pcgen.cdom.enumeration.Nature) Ability(pcgen.core.Ability) CNAbility(pcgen.cdom.content.CNAbility) ParseResult(pcgen.rules.persistence.token.ParseResult) ArrayList(java.util.ArrayList) ConcretePersistentTransitionChoice(pcgen.cdom.base.ConcretePersistentTransitionChoice) Formula(pcgen.base.formula.Formula) ParsingSeparator(pcgen.base.text.ParsingSeparator) AbilityChoiceSet(pcgen.cdom.base.ChoiceSet.AbilityChoiceSet) CNAbilitySelection(pcgen.cdom.helper.CNAbilitySelection) AbilityCategory(pcgen.core.AbilityCategory) CDOMReference(pcgen.cdom.base.CDOMReference) AbilityRefChoiceSet(pcgen.cdom.choiceset.AbilityRefChoiceSet)

Example 9 with Nature

use of pcgen.cdom.enumeration.Nature in project pcgen by PCGen.

the class CategorizedAbilityFacet method copyContents.

/**
	 * Copies the contents of the CategorizedAbilityFacet from one Player
	 * Character to another Player Character, based on the given CharIDs
	 * representing those Player Characters.
	 * 
	 * This is a method in CategorizedAbilityFacet in order to avoid exposing
	 * the mutable Map object to other classes. This should not be inlined, as
	 * the Map is internal information to CategorizedAbilityFacet and should not
	 * be exposed to other classes.
	 * 
	 * Note also the copy is a one-time event and no references are maintained
	 * between the Player Characters represented by the given CharIDs (meaning
	 * once this copy takes place, any change to the CategorizedAbilityFacet of
	 * one Player Character will only impact the Player Character where the
	 * CategorizedAbilityFacet was changed).
	 * 
	 * @param source
	 *            The CharID representing the Player Character from which the
	 *            information should be copied
	 * @param copy
	 *            The CharID representing the Player Character to which the
	 *            information should be copied
	 */
@Override
public void copyContents(CharID source, CharID copy) {
    Map<Category<Ability>, Map<Nature, Set<Ability>>> map = getCachedMap(source);
    if (map != null) {
        for (Entry<Category<Ability>, Map<Nature, Set<Ability>>> me : map.entrySet()) {
            Category<Ability> cat = me.getKey();
            for (Entry<Nature, Set<Ability>> nme : me.getValue().entrySet()) {
                Nature nat = nme.getKey();
                ensureCachedSet(copy, cat, nat);
                getCachedSet(copy, cat, nat).addAll(nme.getValue());
            }
        }
    }
}
Also used : Ability(pcgen.core.Ability) Nature(pcgen.cdom.enumeration.Nature) Category(pcgen.cdom.base.Category) Set(java.util.Set) WrappedMapSet(pcgen.base.util.WrappedMapSet) IdentityHashMap(java.util.IdentityHashMap) HashMap(java.util.HashMap) Map(java.util.Map)

Example 10 with Nature

use of pcgen.cdom.enumeration.Nature in project pcgen by PCGen.

the class PCGVer2Parser method parseAbilityLine.

/*
	 * ###############################################################
	 * Character Ability methods
	 * ###############################################################
	 */
private void parseAbilityLine(final String line) {
    final PCGTokenizer tokens;
    try {
        tokens = new PCGTokenizer(line);
    } catch (PCGParseException pcgpex) {
        final String msg = LanguageBundle.getFormattedString(//$NON-NLS-1$
        "Warnings.PCGenParser.IllegalAbility", line, pcgpex.getMessage());
        warnings.add(msg);
        return;
    }
    AbilityCategory category = null;
    Nature nature = Nature.NORMAL;
    String abilityCat = null;
    Ability ability = null;
    String missingCat = null;
    final Iterator<PCGElement> it = tokens.getElements().iterator();
    // the first element defines the AbilityCategory key name
    if (it.hasNext()) {
        final PCGElement element = it.next();
        final String categoryKey = EntityEncoder.decode(element.getText());
        category = SettingsHandler.getGame().getAbilityCategory(categoryKey);
        if (category == null) {
            missingCat = categoryKey;
        }
    }
    // The next element will be the nature
    if (it.hasNext()) {
        final PCGElement element = it.next();
        final String natureKey = EntityEncoder.decode(element.getText());
        nature = Nature.valueOf(natureKey);
    }
    // The next element will be the ability's innate category
    if (it.hasNext()) {
        final PCGElement element = it.next();
        abilityCat = EntityEncoder.decode(element.getText());
    }
    // The next element will be the ability key
    if (it.hasNext()) {
        final PCGElement element = it.next();
        String abilityKey = EntityEncoder.decode(element.getText());
        // Check for an ability that has been updated.
        CategorisedKey categorisedKey = AbilityMigration.getNewAbilityKey(abilityCat, abilityKey, pcgenVersion, SettingsHandler.getGame().getName());
        abilityCat = categorisedKey.getCategory();
        abilityKey = categorisedKey.getKey();
        AbilityCategory innateCategory = SettingsHandler.getGame().getAbilityCategory(abilityCat);
        if (innateCategory == null) {
            missingCat = abilityCat;
        }
        if (innateCategory == null || category == null) {
            final String msg = LanguageBundle.getFormattedString(//$NON-NLS-1$
            "Warnings.PCGenParser.AbilityCategoryNotFound", abilityKey, missingCat);
            warnings.add(msg);
            return;
        }
        ability = Globals.getContext().getReferenceContext().silentlyGetConstructedCDOMObject(Ability.class, innateCategory, abilityKey);
        if (ability == null) {
            warnings.add("Unable to Find Ability: " + abilityKey);
            return;
        }
    }
    List<String> associations = new ArrayList<>();
    List<BonusObj> bonuses = new ArrayList<>();
    while (it.hasNext()) {
        final PCGElement element = it.next();
        final String tag = element.getName();
        if (tag.equals(IOConstants.TAG_APPLIEDTO)) {
            associations.add(EntityEncoder.decode(element.getText()));
        } else if (IOConstants.TAG_SAVE.equals(tag)) {
            final String saveKey = EntityEncoder.decode(element.getText());
            // TODO - This never gets written to the file
            if (saveKey.startsWith(IOConstants.TAG_BONUS) && (saveKey.length() > 6)) {
                final BonusObj aBonus = Bonus.newBonus(Globals.getContext(), saveKey.substring(6));
                if (aBonus != null) {
                    bonuses.add(aBonus);
                }
            } else {
                if (Logging.isDebugMode()) {
                    Logging.debugPrint("Ignoring SAVE:" + saveKey);
                }
            }
        }
    }
    if (ability != null && category != null && nature != null) {
        CNAbility cna = null;
        boolean needError = true;
        if (nature == Nature.NORMAL) {
            // lines, save the feat now.
            if (!featsPresent || category != AbilityCategory.FEAT) {
                try {
                    cna = CNAbilityFactory.getCNAbility(category, nature, ability);
                } catch (IllegalArgumentException e) {
                    Logging.log(Logging.INFO, "Unabe to parse ability line: " + e.getMessage());
                }
            } else {
                needError = false;
            }
        } else if (nature == Nature.VIRTUAL) {
            cna = CNAbilityFactory.getCNAbility(category, nature, ability);
        }
        if (cna == null) {
            if (needError) {
                warnings.add("Unable to build Ability: " + ability);
            }
        } else {
            if (ability.getSafe(ObjectKey.MULTIPLE_ALLOWED)) {
                for (String appliedToKey : associations) {
                    String[] assoc = appliedToKey.split(Constants.COMMA, -1);
                    for (String string : assoc) {
                        CNAbilitySelection cnas = new CNAbilitySelection(cna, string);
                        try {
                            if (nature == Nature.VIRTUAL) {
                                thePC.addSavedAbility(cnas, UserSelection.getInstance(), UserSelection.getInstance());
                            } else {
                                thePC.addAbility(cnas, UserSelection.getInstance(), UserSelection.getInstance());
                            }
                        } catch (IllegalArgumentException e) {
                            Logging.errorPrint("PCGVer2Parser.parseAbilityLine failed", e);
                            warnings.add(cna + " with selection: " + string + " is no longer valid.");
                        }
                    }
                }
            } else {
                if (associations != null && !associations.isEmpty()) {
                    warnings.add(cna + " found with selections: " + associations + " but is MULT:NO in the data");
                }
                CNAbilitySelection cnas = new CNAbilitySelection(cna);
                if (nature == Nature.VIRTUAL) {
                    thePC.addSavedAbility(cnas, UserSelection.getInstance(), UserSelection.getInstance());
                } else {
                    thePC.addAbility(cnas, UserSelection.getInstance(), UserSelection.getInstance());
                }
            }
            for (BonusObj b : bonuses) {
                thePC.addSaveableBonus(b, cna.getAbility());
            }
        }
    }
}
Also used : Nature(pcgen.cdom.enumeration.Nature) CNAbility(pcgen.cdom.content.CNAbility) Ability(pcgen.core.Ability) SpecialAbility(pcgen.core.SpecialAbility) BonusObj(pcgen.core.bonus.BonusObj) ArrayList(java.util.ArrayList) CategorisedKey(pcgen.io.migration.AbilityMigration.CategorisedKey) CNAbility(pcgen.cdom.content.CNAbility) CNAbilitySelection(pcgen.cdom.helper.CNAbilitySelection) AbilityCategory(pcgen.core.AbilityCategory)

Aggregations

Nature (pcgen.cdom.enumeration.Nature)11 Ability (pcgen.core.Ability)10 CNAbility (pcgen.cdom.content.CNAbility)8 ArrayList (java.util.ArrayList)6 AbilityCategory (pcgen.core.AbilityCategory)6 CDOMReference (pcgen.cdom.base.CDOMReference)5 CNAbilitySelection (pcgen.cdom.helper.CNAbilitySelection)5 AssociatedPrereqObject (pcgen.cdom.base.AssociatedPrereqObject)3 CDOMSingleRef (pcgen.cdom.reference.CDOMSingleRef)3 ParseResult (pcgen.rules.persistence.token.ParseResult)3 StringTokenizer (java.util.StringTokenizer)2 Formula (pcgen.base.formula.Formula)2 ParsingSeparator (pcgen.base.text.ParsingSeparator)2 ChooseSelectionActor (pcgen.cdom.base.ChooseSelectionActor)2 ConcretePersistentTransitionChoice (pcgen.cdom.base.ConcretePersistentTransitionChoice)2 AbilityRefChoiceSet (pcgen.cdom.choiceset.AbilityRefChoiceSet)2 ListKey (pcgen.cdom.enumeration.ListKey)2 AbilitySelector (pcgen.cdom.helper.AbilitySelector)2 AbilityTargetSelector (pcgen.cdom.helper.AbilityTargetSelector)2 AbilityList (pcgen.cdom.list.AbilityList)2