Search in sources :

Example 26 with ClassSource

use of pcgen.cdom.helper.ClassSource in project pcgen by PCGen.

the class AbstractAddListTokenTest method testFromDomain.

@Test
public void testFromDomain() throws PersistenceLayerException {
    Domain source = create(Domain.class, "Source");
    PCClass pcc = create(PCClass.class, "Class");
    T granted = createGrantedObject();
    processToken(source);
    assertEquals(0, getCount());
    ClassSource classSource = new ClassSource(pcc);
    domainFacet.add(id, source, classSource);
    assertTrue(containsExpected(granted));
    assertEquals(1, getCount());
    domainFacet.remove(id, source, classSource);
    assertEquals(0, getCount());
    assertTrue(cleanedSideEffects());
}
Also used : Domain(pcgen.core.Domain) PCClass(pcgen.core.PCClass) ClassSource(pcgen.cdom.helper.ClassSource) Test(org.junit.Test)

Example 27 with ClassSource

use of pcgen.cdom.helper.ClassSource in project pcgen by PCGen.

the class PlayerCharacter method getDC.

public int getDC(final Spell sp, PCClass aClass, int spellLevel, int metaDC, CDOMObject ow) {
    String bonDomain = "";
    if (ow instanceof Domain) {
        bonDomain = "DOMAIN." + ow.getKeyName();
        ClassSource source = getDomainSource((Domain) ow);
        if (source != null) {
            aClass = getClassKeyed(source.getPcclass().getKeyName());
        }
    }
    boolean useStatFromSpell = false;
    String bonClass = "";
    String spellType = "";
    String classKey = "";
    if ((aClass != null) || (ow instanceof PCClass)) {
        if ((aClass == null) || (ow instanceof PCClass)) {
            aClass = (PCClass) ow;
        }
        bonClass = "CLASS." + aClass.getKeyName();
        classKey = "CLASS:" + aClass.getKeyName();
        spellType = aClass.getSpellType();
        useStatFromSpell = aClass.getSafe(ObjectKey.USE_SPELL_SPELL_STAT);
    }
    if (!(ow instanceof PCClass) && !(ow instanceof Domain)) {
        // get BASESPELLSTAT from spell itself
        useStatFromSpell = true;
    }
    // set the spell Level used in aPC.getVariableValue()
    // Explicitly should *not* set the dirty flag to true.
    spellLevelTemp = spellLevel;
    // must be done after spellLevel is set above
    int dc = getVariableValue(SettingsHandler.getGame().getSpellBaseDC(), classKey).intValue() + metaDC;
    dc += (int) getTotalBonusTo("DC", "ALLSPELLS");
    if (useStatFromSpell) {
        // get the BASESPELLSTAT from the spell itself
        CDOMSingleRef<PCStat> stat = sp.get(ObjectKey.SPELL_STAT);
        if (stat != null) {
            dc += this.getStatModFor(stat.get());
        }
    }
    if (!sp.getKeyName().isEmpty()) {
        dc += (int) getTotalBonusTo("DC", "SPELL." + sp.getKeyName());
    }
    // DOMAIN.name
    if (!bonDomain.isEmpty()) {
        dc += (int) getTotalBonusTo("DC", bonDomain);
    }
    // CLASS.name
    if (!bonClass.isEmpty()) {
        dc += (int) getTotalBonusTo("DC", bonClass);
    }
    dc += (int) getTotalBonusTo("DC", "TYPE." + spellType);
    if (spellType.equals("ALL")) {
        for (Type aType : sp.getTrueTypeList(false)) {
            dc += (int) getTotalBonusTo("DC", "TYPE." + aType);
        }
    }
    for (SpellSchool aType : sp.getSafeListFor(ListKey.SPELL_SCHOOL)) {
        dc += (int) getTotalBonusTo("DC", "SCHOOL." + aType.toString());
    }
    for (String aType : sp.getSafeListFor(ListKey.SPELL_SUBSCHOOL)) {
        dc += (int) getTotalBonusTo("DC", "SUBSCHOOL." + aType);
    }
    for (String aType : sp.getSafeListFor(ListKey.SPELL_DESCRIPTOR)) {
        dc += (int) getTotalBonusTo("DC", "DESCRIPTOR." + aType);
    }
    // Explicitly should *not* set the dirty flag to true.
    spellLevelTemp = 0;
    return dc;
}
Also used : SpellSchool(pcgen.cdom.identifier.SpellSchool) MessageType(pcgen.core.utils.MessageType) AttackType(pcgen.util.enumeration.AttackType) Type(pcgen.cdom.enumeration.Type) ClassSource(pcgen.cdom.helper.ClassSource)

Example 28 with ClassSource

use of pcgen.cdom.helper.ClassSource in project pcgen by PCGen.

the class PCClass method addLevel.

/**
	 * Adds a level of this class to the character.
	 *
	 * TODO: Split the PlayerCharacter code out of PCClass (i.e. the level
	 * property). Then have a joining class assigned to PlayerCharacter that
	 * maps PCClass and number of levels in the class.
	 *
	 *
	 * @param argLevelMax
	 *            True if we should only allow extra levels if there are still
	 *            levels in this class to take. (i.e. a lot of prestige classes
	 *            stop at level 10, so if this is true it would not allow an
	 *            11th level of the class to be added
	 * @param bSilent
	 *            True if we are not to show any dialog boxes about errors or
	 *            questions.
	 * @param aPC
	 *            The character we are adding the level to.
	 * @param ignorePrereqs
	 *            True if prereqs for the level should be ignored. Used in
	 *            situations such as when the character is being loaded.
	 * @return true or false
	 */
/*
	 * REFACTOR Clearly this is part of the PCClass factory method that produces
	 * PCClassLevels combined with some other work that will need to be done to
	 * extract some of the complicated gunk out of here that goes out and puts
	 * information into PCLevelInfo and PlayerCharacter.
	 */
public boolean addLevel(final boolean argLevelMax, final boolean bSilent, final PlayerCharacter aPC, final boolean ignorePrereqs) {
    // Check to see if we can add a level of this class to the
    // current character
    final int newLevel = aPC.getLevel(this) + 1;
    boolean levelMax = argLevelMax;
    aPC.setAllowInteraction(false);
    aPC.setLevelWithoutConsequence(this, newLevel);
    if (!ignorePrereqs) {
        // When loading a character, classes are added before feats, so
        // this test would always fail on loading if feats are required
        boolean doReturn = false;
        if (!qualifies(aPC, this)) {
            doReturn = true;
            if (!bSilent) {
                ShowMessageDelegate.showMessageDialog("This character does not qualify for level " + newLevel, Constants.APPLICATION_NAME, MessageType.ERROR);
            }
        }
        aPC.setLevelWithoutConsequence(this, newLevel - 1);
        if (doReturn) {
            return false;
        }
    }
    aPC.setAllowInteraction(true);
    if (isMonster()) {
        levelMax = false;
    }
    if (hasMaxLevel() && (newLevel > getSafe(IntegerKey.LEVEL_LIMIT)) && levelMax) {
        if (!bSilent) {
            ShowMessageDelegate.showMessageDialog("This class cannot be raised above level " + Integer.toString(getSafe(IntegerKey.LEVEL_LIMIT)), Constants.APPLICATION_NAME, MessageType.ERROR);
        }
        return false;
    }
    // Add the level to the current character
    int total = aPC.getTotalLevels();
    // No longer need this since the race now sets a bonus itself and Templates
    // are not able to reassign their feats.  There was nothing else returned in
    // this number
    //		if (total == 0) {
    //			aPC.setFeats(aPC.getInitialFeats());
    //		}
    setLevel(newLevel, aPC);
    // the level has now been added to the character,
    // so now assign the attributes of this class level to the
    // character...
    PCClassLevel classLevel = aPC.getActiveClassLevel(this, newLevel);
    // Make sure that if this Class adds a new domain that
    // we record where that domain came from
    final int dnum = aPC.getMaxCharacterDomains(this, aPC) - aPC.getDomainCount();
    if (dnum > 0 && !aPC.hasDefaultDomainSource()) {
        aPC.setDefaultDomainSource(new ClassSource(this, newLevel));
    }
    // out
    if (Globals.getUseGUI()) {
        final int levels = SettingsHandler.isHPMaxAtFirstClassLevel() ? aPC.totalNonMonsterLevels() : aPC.getTotalLevels();
        final boolean isFirst = levels == 1;
        aPC.rollHP(this, aPC.getLevel(this), isFirst);
    }
    if (!aPC.isImporting()) {
        DomainApplication.addDomainsUpToLevel(this, newLevel, aPC);
    }
    int levelUpStats = 0;
    // i.e. a bonus feat every 3 levels
    if (aPC.getTotalLevels() > total) {
        boolean processBonusStats = true;
        total = aPC.getTotalLevels();
        if (isMonster()) {
            // If we have less levels that the races monster levels
            // then we can not give a stat bonus (i.e. an Ogre has
            // 4 levels of Giant, so it does not get a stat increase at
            // 4th level because that is already taken into account in
            // its racial stat modifiers, but it will get one at 8th
            LevelCommandFactory lcf = aPC.getRace().get(ObjectKey.MONSTER_CLASS);
            int monLevels = 0;
            if (lcf != null) {
                monLevels = lcf.getLevelCount().resolve(aPC, "").intValue();
            }
            if (total <= monLevels) {
                processBonusStats = false;
            }
        }
        if (!aPC.isImporting()) {
            if (processBonusStats) {
                final int bonusStats = Globals.getBonusStatsForLevel(total, aPC);
                if (bonusStats > 0) {
                    aPC.setPoolAmount(aPC.getPoolAmount() + bonusStats);
                    if (!bSilent && SettingsHandler.getShowStatDialogAtLevelUp()) {
                        levelUpStats = StatApplication.askForStatIncrease(aPC, bonusStats, true);
                    }
                }
            }
        }
    }
    int spMod = getSkillPointsForLevel(aPC, classLevel, total);
    PCLevelInfo pcl;
    if (aPC.getLevelInfoSize() > 0) {
        pcl = aPC.getLevelInfo(aPC.getLevelInfoSize() - 1);
        if (pcl != null) {
            pcl.setClassLevel(aPC.getLevel(this));
            pcl.setSkillPointsGained(aPC, spMod);
            pcl.setSkillPointsRemaining(pcl.getSkillPointsGained(aPC));
        }
    }
    Integer currentPool = aPC.getSkillPool(this);
    int newSkillPool = spMod + (currentPool == null ? 0 : currentPool);
    aPC.setSkillPool(this, newSkillPool);
    if (!aPC.isImporting()) {
        //
        if (levelUpStats > 0) {
            StatApplication.askForStatIncrease(aPC, levelUpStats, false);
        }
        if (newLevel == 1) {
            AddObjectActions.doBaseChecks(this, aPC);
            CDOMObjectUtilities.addAdds(this, aPC);
            CDOMObjectUtilities.checkRemovals(this, aPC);
        }
        for (TransitionChoice<Kit> kit : classLevel.getSafeListFor(ListKey.KIT_CHOICE)) {
            kit.act(kit.driveChoice(aPC), classLevel, aPC);
        }
        TransitionChoice<Region> region = classLevel.get(ObjectKey.REGION_CHOICE);
        if (region != null) {
            region.act(region.driveChoice(aPC), classLevel, aPC);
        }
    }
    // this is a monster class, so don't worry about experience
    if (isMonster()) {
        return true;
    }
    if (!aPC.isImporting()) {
        CDOMObjectUtilities.checkRemovals(this, aPC);
        final int minxp = aPC.minXPForECL();
        if (aPC.getXP() < minxp) {
            aPC.setXP(minxp);
        } else if (aPC.getXP() >= aPC.minXPForNextECL()) {
            if (!bSilent) {
                ShowMessageDelegate.showMessageDialog(SettingsHandler.getGame().getLevelUpMessage(), Constants.APPLICATION_NAME, MessageType.INFORMATION);
            }
        }
    }
    //
    if (containsKey(ObjectKey.EXCHANGE_LEVEL) && (aPC.getLevel(this) == 1) && !aPC.isImporting()) {
        ExchangeLevelApplication.exchangeLevels(aPC, this);
    }
    return true;
}
Also used : LevelCommandFactory(pcgen.cdom.content.LevelCommandFactory) Region(pcgen.cdom.enumeration.Region) PCLevelInfo(pcgen.core.pclevelinfo.PCLevelInfo) ClassSource(pcgen.cdom.helper.ClassSource) PCClassLevel(pcgen.cdom.inst.PCClassLevel)

Example 29 with ClassSource

use of pcgen.cdom.helper.ClassSource in project pcgen by PCGen.

the class DomainApplication method addDomain.

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);
    }
}
Also used : ClassSource(pcgen.cdom.helper.ClassSource)

Example 30 with ClassSource

use of pcgen.cdom.helper.ClassSource in project pcgen by PCGen.

the class DomainApplication method applyDomain.

/**
	 * Sets the locked flag on a PC
	 * 
	 * @param pc
	 */
public static void applyDomain(PlayerCharacter pc, Domain d) {
    ClassSource source = pc.getDomainSource(d);
    PCClass aClass = pc.getClassKeyed(source.getPcclass().getKeyName());
    if (aClass != null) {
        int maxLevel;
        for (maxLevel = 0; maxLevel < 10; maxLevel++) {
            if (pc.getSpellSupport(aClass).getCastForLevel(maxLevel, pc) == 0) {
                break;
            }
        }
        if (maxLevel > 0) {
            addSpellsToClassForLevels(pc, d, aClass, 0, maxLevel - 1);
        }
        if ((maxLevel > 1) && (aClass.getSafe(IntegerKey.KNOWN_SPELLS_FROM_SPECIALTY) == 0)) {
            DomainSpellList domainSpellList = d.get(ObjectKey.DOMAIN_SPELLLIST);
            final List<Spell> aList = pc.getAllSpellsInLists(Collections.singletonList(domainSpellList));
            for (Spell gcs : aList) {
                if (SpellLevel.getFirstLvlForKey(gcs, domainSpellList, pc) < maxLevel) {
                    pc.setDomainSpellCount(aClass, 1);
                    break;
                }
            }
        }
    }
    Collection<CDOMReference<Spell>> mods = d.getSafeListMods(Spell.SPELLS);
    for (CDOMReference<Spell> ref : mods) {
        Collection<Spell> spells = ref.getContainedObjects();
        Collection<AssociatedPrereqObject> assoc = d.getListAssociations(Spell.SPELLS, ref);
        for (AssociatedPrereqObject apo : assoc) {
            if (!PrereqHandler.passesAll(apo.getPrerequisiteList(), pc, d)) {
                continue;
            }
            for (Spell s : spells) {
                String book = apo.getAssociation(AssociationKey.SPELLBOOK);
                List<CharacterSpell> aList = pc.getCharacterSpells(aClass, s, book, -1);
                if (aList.isEmpty()) {
                    Formula times = apo.getAssociation(AssociationKey.TIMES_PER_UNIT);
                    CharacterSpell cs = new CharacterSpell(d, s);
                    int resolvedTimes = times.resolve(pc, d.getQualifiedKey()).intValue();
                    cs.addInfo(1, resolvedTimes, book);
                    pc.addCharacterSpell(aClass, cs);
                }
            }
        }
    }
}
Also used : PCClass(pcgen.core.PCClass) Spell(pcgen.core.spell.Spell) CharacterSpell(pcgen.core.character.CharacterSpell) DomainSpellList(pcgen.cdom.list.DomainSpellList) Formula(pcgen.base.formula.Formula) CharacterSpell(pcgen.core.character.CharacterSpell) ClassSource(pcgen.cdom.helper.ClassSource) CDOMReference(pcgen.cdom.base.CDOMReference) AssociatedPrereqObject(pcgen.cdom.base.AssociatedPrereqObject)

Aggregations

ClassSource (pcgen.cdom.helper.ClassSource)31 PCClass (pcgen.core.PCClass)19 Domain (pcgen.core.Domain)18 Test (org.junit.Test)9 AbstractTokenModelTest (tokenmodel.testsupport.AbstractTokenModelTest)6 ParseResult (pcgen.rules.persistence.token.ParseResult)5 PlayerCharacter (pcgen.core.PlayerCharacter)4 CNAbility (pcgen.cdom.content.CNAbility)3 Ability (pcgen.core.Ability)3 CharacterSpell (pcgen.core.character.CharacterSpell)3 Spell (pcgen.core.spell.Spell)3 PreParserFactory (pcgen.persistence.lst.prereq.PreParserFactory)3 AssociatedPrereqObject (pcgen.cdom.base.AssociatedPrereqObject)2 CDOMReference (pcgen.cdom.base.CDOMReference)2 Type (pcgen.cdom.enumeration.Type)2 SpellSchool (pcgen.cdom.identifier.SpellSchool)2 DomainSpellList (pcgen.cdom.list.DomainSpellList)2 PCLevelInfo (pcgen.core.pclevelinfo.PCLevelInfo)2 MessageType (pcgen.core.utils.MessageType)2 AttackType (pcgen.util.enumeration.AttackType)2