mirror of
https://github.com/Threnklyn/dungeon-sheets.git
synced 2026-06-13 16:13:32 +02:00
Features added and tested for all classes/subclasses in bens campaign
This commit is contained in:
@@ -47,11 +47,13 @@ class CharClass():
|
||||
self.features_by_level[i] = fs
|
||||
for k, v in params.items():
|
||||
setattr(self, k, v)
|
||||
self.spells_known = [S() for S in cls.spells_known]
|
||||
self.spells_prepared = [S() for S in cls.spells_prepared]
|
||||
|
||||
# Apply subclass
|
||||
self.subclass = self.select_subclass(subclass)
|
||||
if isinstance(self.subclass, SubClass):
|
||||
self.apply_subclass()
|
||||
self.apply_subclass(feature_choices=feature_choices)
|
||||
|
||||
def select_subclass(self, subclass_str):
|
||||
"""
|
||||
@@ -67,23 +69,31 @@ class CharClass():
|
||||
return sc(owner=self.owner)
|
||||
return None
|
||||
|
||||
def apply_subclass(self):
|
||||
if self.subclass is None:
|
||||
def apply_subclass(self, feature_choices=[]):
|
||||
if not isinstance(self.subclass, SubClass):
|
||||
return
|
||||
subcls = self.subclass
|
||||
for i in range(1, 21):
|
||||
self.features_by_level[i] += ([f(owner=self.owner) for f in
|
||||
self.subclass.features_by_level[i]])
|
||||
for attr in ('weapon_proficiencies', '_proficiencies_text',
|
||||
'spells_known', 'spells_prepared'):
|
||||
new_list = getattr(self, attr, ()) + getattr(self.subclass, attr, ())
|
||||
fs = []
|
||||
for f in subcls.features_by_level[i]:
|
||||
if issubclass(f, FeatureSelector):
|
||||
fs.append(f(owner=self.owner,
|
||||
feature_choices=feature_choices))
|
||||
elif issubclass(f, Feature):
|
||||
fs.append(f(owner=self.owner))
|
||||
self.features_by_level[i].extend(fs)
|
||||
for attr in ('weapon_proficiencies', '_proficiencies_text'):
|
||||
new_list = tuple(getattr(self, attr, ())) + tuple(getattr(self.subclass, attr, ()))
|
||||
setattr(self, attr, new_list)
|
||||
# All subclass proficiencies transfer, regardless of if this is primary class
|
||||
self.multiclass_weapon_proficiencies += (self.subclass.weapon_proficiencies)
|
||||
self._multiclass_proficiencies_text += (self._proficiencies_text)
|
||||
self.multiclass_weapon_proficiencies += tuple(subcls.weapon_proficiencies)
|
||||
self._multiclass_proficiencies_text += tuple(subcls._proficiencies_text)
|
||||
self.spellcasting_ability = (self.spellcasting_ability or
|
||||
self.subclass.spellcasting_ability)
|
||||
subcls.spellcasting_ability)
|
||||
self.spell_slots_by_level = (self.spell_slots_by_level or
|
||||
self.subclass.spell_slots_by_level)
|
||||
subcls.spell_slots_by_level)
|
||||
self.spells_known.extend([S() for S in subcls.spells_known])
|
||||
self.spells_prepared.extend([S() for S in subcls.spells_prepared])
|
||||
|
||||
@property
|
||||
def features(self):
|
||||
@@ -104,6 +114,15 @@ class CharClass():
|
||||
else:
|
||||
return self.spell_slots_by_level[self.level][spell_level]
|
||||
|
||||
def __str__(self):
|
||||
s = 'Level {:d} {:s}'.format(self.level, self.name)
|
||||
if isinstance(self.subclass, SubClass):
|
||||
s += ' ({:s})'.format(str(self.subclass))
|
||||
return s
|
||||
|
||||
def __repr__(self):
|
||||
return '\"{:s}\"'.format(str(self))
|
||||
|
||||
|
||||
class SubClass():
|
||||
"""
|
||||
|
||||
@@ -1,9 +1,31 @@
|
||||
from .. import (weapons, features)
|
||||
from .. import (weapons, features, spells)
|
||||
from .classes import CharClass, SubClass
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
class KnowledgeDomain(SubClass):
|
||||
class ClericDomain(SubClass):
|
||||
name = "Generic Cleric Domain"
|
||||
_domain_spells = {1: [], 3: [], 5: [], 7: [], 9: []}
|
||||
|
||||
@property
|
||||
def level(self):
|
||||
return self.owner.Cleric.level
|
||||
|
||||
@property
|
||||
def spells_known(self):
|
||||
spells = []
|
||||
for lvl, sps in self._domain_spells.items():
|
||||
if self.level >= lvl:
|
||||
spells.extend(sps)
|
||||
return spells
|
||||
|
||||
# All Domain spells are both known and prepared
|
||||
@property
|
||||
def spells_prepared(self):
|
||||
return self.spells_known
|
||||
|
||||
|
||||
class KnowledgeDomain(ClericDomain):
|
||||
"""The gods of knowledge—including Oghma, Boccob, Gilean, Aureon, and
|
||||
Thoth—value learning and understanding above all. Some teach that knowledge
|
||||
is to be gathered and shared in libraries and universities, or promote the
|
||||
@@ -18,10 +40,11 @@ class KnowledgeDomain(SubClass):
|
||||
|
||||
"""
|
||||
name = "Knowledge Domain"
|
||||
_domain_spells = {1: [], 3: [], 5: [], 7: [], 9: []}
|
||||
features_by_level = defaultdict(list)
|
||||
|
||||
|
||||
class LifeDomain(SubClass):
|
||||
class LifeDomain(ClericDomain):
|
||||
"""The Life domain focuses on the vibrant positive energy—one of the
|
||||
fundamental forces of the universe— that sustains all life. The gods of
|
||||
life promote vitality and health through healing the sick and wounded,
|
||||
@@ -34,10 +57,11 @@ class LifeDomain(SubClass):
|
||||
|
||||
"""
|
||||
name = "Life Domain"
|
||||
_domain_spells = {1: [], 3: [], 5: [], 7: [], 9: []}
|
||||
features_by_level = defaultdict(list)
|
||||
|
||||
|
||||
class LightDomain(SubClass):
|
||||
class LightDomain(ClericDomain):
|
||||
"""Gods of light—including Helm, Lathander, Pholtus, Branchala, the Silver
|
||||
Flame, Belenus, Apollo, and Re-Horakhty—promote the ideals of rebirth and
|
||||
renewal, truth, vigilance, and beauty, often using the symbol of the
|
||||
@@ -51,10 +75,11 @@ class LightDomain(SubClass):
|
||||
|
||||
"""
|
||||
name = "Light Domain"
|
||||
_domain_spells = {1: [], 3: [], 5: [], 7: [], 9: []}
|
||||
features_by_level = defaultdict(list)
|
||||
|
||||
|
||||
class NatureDomain(SubClass):
|
||||
class NatureDomain(ClericDomain):
|
||||
"""Gods of nature are as varied as the natural world itself, from inscrutable
|
||||
gods of the deep forests (such as Silvanus, Obad-Hai, Chislev, Balinor, and
|
||||
Pan) to friendly deities associated with particular springs and groves
|
||||
@@ -68,10 +93,11 @@ class NatureDomain(SubClass):
|
||||
|
||||
"""
|
||||
name = "Nature Domain"
|
||||
_domain_spells = {1: [], 3: [], 5: [], 7: [], 9: []}
|
||||
features_by_level = defaultdict(list)
|
||||
|
||||
|
||||
class TempestDomain(SubClass):
|
||||
class TempestDomain(ClericDomain):
|
||||
"""Gods whose portfolios include the Tempest domain - including Talos,
|
||||
Umberlee, Kord, Zeboim, the Devourer, Zeus, and Thor — govern storms, sea,
|
||||
and sky. They include gods of lightning and thunder, gods of earthquakes,
|
||||
@@ -86,10 +112,22 @@ class TempestDomain(SubClass):
|
||||
|
||||
"""
|
||||
name = "Tempest Domain"
|
||||
_domain_spells = {1: [spells.FogCloud, spells.Thunderwave],
|
||||
3: [spells.GustOfWind, spells.Shatter],
|
||||
5: [spells.CallLightning, spells.SleetStorm],
|
||||
7: [spells.ControlWater, spells.IceStorm],
|
||||
9: [spells.DestructiveWave, spells.InsectPlague]}
|
||||
weapon_proficiencies = (weapons.MartialWeapon,)
|
||||
_proficiencies_text = ('martial weapons', 'heavy armor')
|
||||
features_by_level = defaultdict(list)
|
||||
features_by_level[1] = (features.WrathOfTheStorm,)
|
||||
features_by_level[2] = (features.DestructiveWrath,)
|
||||
features_by_level[6] = (features.ThunderboltStrike,)
|
||||
features_by_level[8] = (features.DivineStrikeTempest,)
|
||||
features_by_level[17] = (features.Stormborn,)
|
||||
|
||||
|
||||
class TrickeryDomain(SubClass):
|
||||
class TrickeryDomain(ClericDomain):
|
||||
"""Gods of trickery—such as Tymora, Beshaba, Olidammara, the Traveler, Garl
|
||||
Glittergold, and Loki—are mischief-makers and instigators who stand as a
|
||||
constant challenge to the accepted order among both gods and
|
||||
@@ -101,10 +139,11 @@ class TrickeryDomain(SubClass):
|
||||
|
||||
"""
|
||||
name = "Trickery Domain"
|
||||
_domain_spells = {1: [], 3: [], 5: [], 7: [], 9: []}
|
||||
features_by_level = defaultdict(list)
|
||||
|
||||
|
||||
class WarDomain(SubClass):
|
||||
class WarDomain(ClericDomain):
|
||||
"""War has many manifestations. It can make heroes of ordinary people. It can
|
||||
be desperate and horrific, with acts of cruelty and cowardice eclipsing
|
||||
instances of excellence and courage. In either case, the gods of war watch
|
||||
@@ -120,11 +159,12 @@ class WarDomain(SubClass):
|
||||
|
||||
"""
|
||||
name = "War Domain"
|
||||
_domain_spells = {1: [], 3: [], 5: [], 7: [], 9: []}
|
||||
features_by_level = defaultdict(list)
|
||||
|
||||
|
||||
# SCAG
|
||||
class ArcanaDomain(SubClass):
|
||||
class ArcanaDomain(ClericDomain):
|
||||
"""Magic is an energy that suffuses the multiverse and that fuels both
|
||||
destruction and creation. Gods of the Arcana domain know the secrets and
|
||||
potential of magic intimately. For some of these gods, magical knowledge
|
||||
@@ -141,11 +181,12 @@ class ArcanaDomain(SubClass):
|
||||
|
||||
"""
|
||||
name = "Arcana Domain"
|
||||
_domain_spells = {1: [], 3: [], 5: [], 7: [], 9: []}
|
||||
features_by_level = defaultdict(list)
|
||||
|
||||
|
||||
# XGTE
|
||||
class ForgeDomain(SubClass):
|
||||
class ForgeDomain(ClericDomain):
|
||||
"""The gods of the forge are patrons of artisans who work with metal, from a
|
||||
humble blacksmith who keeps a village in horseshoes and plow blades to the
|
||||
mighty elf artisan whose diamond-tipped arrows of mithral have felled demon
|
||||
@@ -163,7 +204,7 @@ class ForgeDomain(SubClass):
|
||||
features_by_level = defaultdict(list)
|
||||
|
||||
|
||||
class GraveDomain(SubClass):
|
||||
class GraveDomain(ClericDomain):
|
||||
"""Gods of the grave watch over the line between life and death. To these
|
||||
deities, death and the afterlife are a foundational part of the
|
||||
multiverse. To desecrate the peace of the dead is an abomination. Deities
|
||||
@@ -177,6 +218,7 @@ class GraveDomain(SubClass):
|
||||
|
||||
"""
|
||||
name = "Grave Domain"
|
||||
_domain_spells = {1: [], 3: [], 5: [], 7: [], 9: []}
|
||||
features_by_level = defaultdict(list)
|
||||
|
||||
|
||||
@@ -194,6 +236,9 @@ class Cleric(CharClass):
|
||||
class_skill_choices = ('History', 'Insight', 'Medicine',
|
||||
'Persuasion', 'Religion')
|
||||
features_by_level = defaultdict(list)
|
||||
features_by_level[2] = (features.ChannelDivinity, features.TurnUndead,)
|
||||
features_by_level[5] = (features.DestroyUndead, )
|
||||
features_by_level[10] = (features.DivineIntervention,)
|
||||
subclasses_available = (KnowledgeDomain, LifeDomain, LightDomain,
|
||||
NatureDomain, TempestDomain, TrickeryDomain,
|
||||
WarDomain, ArcanaDomain, ForgeDomain,
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
from .. import (weapons, features, spells)
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
# Custom Classes
|
||||
@@ -13,6 +13,11 @@ class Champion(SubClass):
|
||||
"""
|
||||
name = "Champion"
|
||||
features_by_level = defaultdict(list)
|
||||
features_by_level[3] = [features.ImprovedCritical]
|
||||
features_by_level[7] = [features.RemarkableAthelete]
|
||||
features_by_level[10] = [features.AdditionalFightingStyle]
|
||||
features_by_level[15] = [features.SuperiorCritical]
|
||||
features_by_level[18] = [features.Survivor]
|
||||
|
||||
|
||||
class BattleMaster(SubClass):
|
||||
@@ -26,6 +31,9 @@ class BattleMaster(SubClass):
|
||||
"""
|
||||
name = "Battle Master"
|
||||
features_by_level = defaultdict(list)
|
||||
features_by_level[3] = [features.CombatSuperiority, features.StudentOfWar]
|
||||
features_by_level[7] = [features.KnowYourEnemy]
|
||||
features_by_level[15] = [features.Relentless]
|
||||
|
||||
|
||||
class EldritchKnight(SubClass):
|
||||
@@ -41,6 +49,12 @@ class EldritchKnight(SubClass):
|
||||
"""
|
||||
name = "Eldritch Knight"
|
||||
features_by_level = defaultdict(list)
|
||||
features_by_level[3] = [features.EldritchKnightSpellcasting,
|
||||
features.WeaponBond]
|
||||
features_by_level[7] = [features.WarMagic]
|
||||
features_by_level[10] = [features.EldritchStrike]
|
||||
features_by_level[15] = [features.ArcaneCharge]
|
||||
features_by_level[18] = [features.ImprovedWarMagic]
|
||||
spellcasting_ability = 'intelligence'
|
||||
multiclass_spellslots_by_level = {
|
||||
# char_lvl: (cantrips, 1st, 2nd, 3rd, ...)
|
||||
@@ -157,9 +171,15 @@ class Gunslinger(SubClass):
|
||||
|
||||
"""
|
||||
name = "Gunslinger"
|
||||
features_by_level = defaultdict(list)
|
||||
weapon_proficiencies = (weapons.firearms)
|
||||
_proficiencies_text = ('firearms')
|
||||
_proficiencies_text = ('firearms', "tinker's tools")
|
||||
features_by_level = defaultdict(list)
|
||||
features_by_level[3] = [features.Gunsmith, features.AdeptMarksman]
|
||||
features_by_level[7] = [features.QuickDraw]
|
||||
features_by_level[10] = [features.RapidRepair]
|
||||
features_by_level[15] = [features.LightningReload]
|
||||
features_by_level[18] = [features.ViciousIntent,
|
||||
features.HemorrhagingCritical]
|
||||
|
||||
|
||||
class Fighter(CharClass):
|
||||
@@ -179,6 +199,10 @@ class Fighter(CharClass):
|
||||
'Athletics', 'History', 'Insight', 'Intimidation',
|
||||
'Perception', 'Survival')
|
||||
features_by_level = defaultdict(list)
|
||||
features_by_level[1] = [features.FighterFightingStyle, features.SecondWind]
|
||||
features_by_level[2] = [features.ActionSurge]
|
||||
features_by_level[5] = [features.ExtraAttackFighter]
|
||||
features_by_level[9] = [features.Indomitable]
|
||||
subclasses_available = (Champion, BattleMaster, EldritchKnight,
|
||||
PurpleDragonKnight, ArcaneArcher, Cavalier,
|
||||
Samurai, Gunslinger)
|
||||
|
||||
@@ -1,9 +1,31 @@
|
||||
from .. import (weapons, features)
|
||||
from .. import (weapons, features, spells)
|
||||
from .classes import CharClass, SubClass
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
class OathOfDevotion(SubClass):
|
||||
class PaladinOath(SubClass):
|
||||
name = "Generic Paladin Oath"
|
||||
_oath_spells = {3: [], 5: [], 9: [], 13: [], 17: []}
|
||||
|
||||
@property
|
||||
def level(self):
|
||||
return self.owner.Paladin.level
|
||||
|
||||
@property
|
||||
def spells_known(self):
|
||||
spells = []
|
||||
for lvl, sps in self._oath_spells.items():
|
||||
if self.level >= lvl:
|
||||
spells.extend(sps)
|
||||
return spells
|
||||
|
||||
# All Oath spells are both known and prepared
|
||||
@property
|
||||
def spells_prepared(self):
|
||||
return self.spells_known
|
||||
|
||||
|
||||
class OathOfDevotion(PaladinOath):
|
||||
"""The Oath of Devotion binds a paladin to the loftiest ideals of justice,
|
||||
virtue, and order. Sometim es called cavaliers, white knights, or holy
|
||||
warriors, these paladins meet the ideal of the knight in shining armor,
|
||||
@@ -35,10 +57,20 @@ class OathOfDevotion(SubClass):
|
||||
|
||||
"""
|
||||
name = "Oath of Devotion"
|
||||
_oath_spells = {3: [spells.ProtectionFromEvilAndGood,
|
||||
spells.Sanctuary],
|
||||
5: [spells.LesserRestoration, spells.ZoneOfTruth],
|
||||
9: [spells.BeaconOfHope, spells.DispelMagic],
|
||||
13: [spells.FreedomOfMovement, spells.GuardianOfFaith],
|
||||
17: [spells.Commune, spells.FlameStrike]}
|
||||
features_by_level = defaultdict(list)
|
||||
features_by_level[3] = [features.SacredWeapon, features.TurnTheUnholy]
|
||||
features_by_level[7] = [features.AuraOfDevotion]
|
||||
features_by_level[15] = [features.PurityOfSpirit]
|
||||
features_by_level[20] = [features.HolyNimbus]
|
||||
|
||||
|
||||
|
||||
class OathOfAncients(SubClass):
|
||||
class OathOfAncients(PaladinOath):
|
||||
"""The Oath of the Ancients is as old as the race of elves and the rituals of
|
||||
the druids. Sometimes called fey knights, green knights, or horned knights,
|
||||
paladins who swear this oath cast their lot with the side of the light in
|
||||
@@ -69,10 +101,15 @@ class OathOfAncients(SubClass):
|
||||
|
||||
"""
|
||||
name = "Oath of The Ancients"
|
||||
_oath_spells = {3: [spells.EnsnaringStrike, spells.SpeakWithAnimals],
|
||||
5: [spells.Moonbeam, spells.MistyStep],
|
||||
9: [spells.PlantGrowth, spells.ProtectionFromEnergy],
|
||||
13: [spells.IceStorm, spells.Stoneskin],
|
||||
17: [spells.CommuneWithNature, spells.TreeStride]}
|
||||
features_by_level = defaultdict(list)
|
||||
|
||||
|
||||
class OathOfVengance(SubClass):
|
||||
class OathOfVengance(PaladinOath):
|
||||
"""The Oath of Vengeance is a solemn commitment to punish those who have
|
||||
committed a grievous sin. When evil forces slaughter helpless villagers,
|
||||
when an entire people turns against the will of the gods, when a thieves’
|
||||
@@ -103,10 +140,15 @@ class OathOfVengance(SubClass):
|
||||
|
||||
"""
|
||||
name = "Oath of Vengance"
|
||||
_oath_spells = {3: [spells.Bane, spells.HuntersMark],
|
||||
5: [spells.HoldPerson, spells.MistyStep],
|
||||
9: [spells.Haste, spells.ProtectionFromEnergy],
|
||||
13: [spells.Banishment, spells.DimensionDoor],
|
||||
17: [spells.HoldMonster, spells.Scrying]}
|
||||
features_by_level = defaultdict(list)
|
||||
|
||||
|
||||
class OathOfCrown(SubClass):
|
||||
class OathOfCrown(PaladinOath):
|
||||
"""The Oath of the Crown is sworn to the ideals of civilization, be it the
|
||||
spirit of a nation, fealty to a sovereign, or service to a deity of law and
|
||||
rulership. The paladins who swear this oath dedicate themselves to serving
|
||||
@@ -137,10 +179,15 @@ class OathOfCrown(SubClass):
|
||||
|
||||
"""
|
||||
name = "Oath of The Crown"
|
||||
_oath_spells = {3: [spells.Command, spells.CompelledDuel],
|
||||
5: [spells.WardingBond, spells.ZoneOfTruth],
|
||||
9: [spells.AuraOfVitality, spells.SpiritGuardians],
|
||||
13: [spells.Banishment, spells.GuardianOfFaith],
|
||||
17: [spells.CircleOfPower, spells.Geas]}
|
||||
features_by_level = defaultdict(list)
|
||||
|
||||
|
||||
class OathOfConquest(SubClass):
|
||||
class OathOfConquest(PaladinOath):
|
||||
"""The Oath of Conquest calls to paladins who seek glory in battle and the
|
||||
subjugation of their enemies. It isn’t enough for these paladins to
|
||||
establish order. They must crush the forces of chaos. Sometimes called
|
||||
@@ -173,10 +220,15 @@ class OathOfConquest(SubClass):
|
||||
|
||||
"""
|
||||
name = "Oath of Conquest"
|
||||
_oath_spells = {3: [spells.ArmorOfAgathys, spells.Command],
|
||||
5: [spells.HoldPerson, spells.SpiritualWeapon],
|
||||
9: [spells.BestowCurse, spells.Fear],
|
||||
13: [spells.DominateBeast, spells.Stoneskin],
|
||||
17: [spells.Cloudkill, spells.DominatePerson]}
|
||||
features_by_level = defaultdict(list)
|
||||
|
||||
|
||||
class OathOfRedemption(SubClass):
|
||||
class OathOfRedemption(PaladinOath):
|
||||
"""The Oath of Redemption sets a paladin on a difficult path, one that requires
|
||||
a holy warrior to use violence only as a last resort. Paladins who dedicate
|
||||
themselves to this oath believe that any person can be redeemed and that
|
||||
@@ -216,7 +268,56 @@ class OathOfRedemption(SubClass):
|
||||
|
||||
"""
|
||||
name = "Oath of Redemption"
|
||||
_oath_spells = {3: [spells.Sanctuary, spells.Sleep],
|
||||
5: [spells.CalmEmotions, spells.HoldPerson],
|
||||
9: [spells.Counterspell, spells.HypnoticPattern],
|
||||
13: [spells.OtilukesResilientSphere, spells.Stoneskin],
|
||||
17: [spells.HoldMonster, spells.WallOfForce]}
|
||||
features_by_level = defaultdict(list)
|
||||
features_by_level[3] = [features.EmissaryOfPeace,
|
||||
features.RebukeTheViolent]
|
||||
features_by_level[7] = [features.AuraOfTheGuardian]
|
||||
features_by_level[15] = [features.ProtectiveSpirit]
|
||||
features_by_level[20] = [features.EmissaryOfRedemption]
|
||||
|
||||
|
||||
# Custom
|
||||
class OathOfZor(PaladinOath):
|
||||
"""The Oath of Zor
|
||||
|
||||
**Tenets of Zor**:
|
||||
|
||||
--Courage. Never fear to act, though caution is wise.
|
||||
|
||||
--Honesty. Don’t lie or cheat. Let your word be your promise.
|
||||
|
||||
--Innocence. All people begin life in an innocent state, and it is their
|
||||
environment or the influence of dark forces that drives them to evil. By
|
||||
setting the proper example, and working to heal the wounds of a deeply
|
||||
flawed world, you can set anyone on a righteous path.
|
||||
|
||||
--Restitution. If my foes wreak ruin on the world, it is because I failed
|
||||
to stop them. I must help those harmed by their misdeeds.
|
||||
|
||||
--Patience. Change takes time. Those who have walked the path of the wicked
|
||||
must be given reminders to keep them honest and true. Once you have planted
|
||||
the seed of righteousness in a creature, you must work day after day to
|
||||
allow that seed to survive and flourish.
|
||||
|
||||
|
||||
"""
|
||||
name = "Oath of Zor"
|
||||
_oath_spells = {3: [spells.Sanctuary, spells.Sleep],
|
||||
5: [spells.CalmEmotions, spells.HoldPerson],
|
||||
9: [spells.Counterspell, spells.HypnoticPattern],
|
||||
13: [spells.OtilukesResilientSphere, spells.Stoneskin],
|
||||
17: [spells.HoldMonster, spells.WallOfForce]}
|
||||
features_by_level = defaultdict(list)
|
||||
features_by_level[3] = [features.EmissaryOfPeace,
|
||||
features.RebukeTheViolent]
|
||||
features_by_level[7] = [features.AuraOfTheGuardian]
|
||||
features_by_level[15] = [features.ProtectiveSpirit]
|
||||
features_by_level[20] = [features.EmissaryOfRedemption]
|
||||
|
||||
|
||||
class Paladin(CharClass):
|
||||
@@ -234,8 +335,19 @@ class Paladin(CharClass):
|
||||
class_skill_choices = ("Athletics", 'Insight', 'Intimidation',
|
||||
'Medicine', 'Persuasion', 'Religion')
|
||||
features_by_level = defaultdict(list)
|
||||
features_by_level[1] = [features.DivineSense, features.LayOnHands]
|
||||
features_by_level[2] = [features.PaladinFightingStyle,
|
||||
features.DivineSmite]
|
||||
features_by_level[3] = [features.DivineHealth,
|
||||
features.ChannelDivinityPaladin]
|
||||
features_by_level[5] = [features.ExtraAttackPaladin]
|
||||
features_by_level[6] = [features.AuraOfProtection]
|
||||
features_by_level[10] = [features.AuraOfCourage]
|
||||
features_by_level[11] = [features.ImprovedDivineSmite]
|
||||
features_by_level[14] = [features.CleansingTouch]
|
||||
subclasses_available = (OathOfDevotion, OathOfAncients, OathOfVengance,
|
||||
OathOfCrown, OathOfConquest, OathOfRedemption)
|
||||
OathOfCrown, OathOfConquest, OathOfRedemption,
|
||||
OathOfZor)
|
||||
spellcasting_ability = 'charisma'
|
||||
spell_slots_by_level = {
|
||||
# char_lvl: (cantrips, 1st, 2nd, 3rd, ...)
|
||||
|
||||
@@ -115,12 +115,6 @@ class Ranger(CharClass):
|
||||
20: (0, 4, 3, 3, 3, 2, 0, 0, 0, 0),
|
||||
}
|
||||
|
||||
def __init__(self, level, subclass=None, **params):
|
||||
super().__init__(level, subclass=subclass, **params)
|
||||
fighting_style = features.select_ranger_fighting_style(
|
||||
feature_choices=params.get('feature_choices', []))
|
||||
self.features_by_level[2].append(fighting_style)
|
||||
|
||||
|
||||
# Revised Ranger
|
||||
class BeastConclave(SubClass):
|
||||
@@ -132,6 +126,11 @@ class BeastConclave(SubClass):
|
||||
"""
|
||||
name = "Beast Conclave"
|
||||
features_by_level = defaultdict(list)
|
||||
features_by_level[3] = [features.AnimalCompanion, features.CompanionsBond]
|
||||
features_by_level[5] = [features.CoordinatedAttack]
|
||||
features_by_level[7] = [features.BeastsDefense]
|
||||
features_by_level[11] = [features.StormOfClawsAndFangs]
|
||||
features_by_level[15] = [features.SuperiorBeastsDefense]
|
||||
|
||||
|
||||
class HunterConclave(SubClass):
|
||||
@@ -160,5 +159,15 @@ class DeepStalkerConclave(SubClass):
|
||||
class RevisedRanger(Ranger):
|
||||
name = 'Revised Ranger'
|
||||
features_by_level = defaultdict(list)
|
||||
features_by_level[1] = [features.FavoredEnemyRevised,
|
||||
features.NaturalExplorerRevised]
|
||||
features_by_level[2] = [features.RangerFightingStyle]
|
||||
features_by_level[3] = [features.PrimevalAwarenessRevised]
|
||||
features_by_level[6] = [features.GreaterFavoredEnemy]
|
||||
features_by_level[8] = [features.FleetOfFoot]
|
||||
features_by_level[10] = [features.HideInPlainSight]
|
||||
features_by_level[14] = [features.Vanish]
|
||||
features_by_level[18] = [features.FeralSenses]
|
||||
features_by_level[20] = [features.FoeSlayer]
|
||||
subclasses_available = (BeastConclave, HunterConclave, DeepStalkerConclave)
|
||||
|
||||
|
||||
@@ -134,6 +134,23 @@ class Rogue(CharClass):
|
||||
'Insight', 'Intimidation', 'Investigation',
|
||||
'Perception', 'Performance', 'Persuasion',
|
||||
'Sleight of Hand', 'Stealth')
|
||||
num_skill_choices = 4
|
||||
features_by_level = defaultdict(list)
|
||||
features_by_level[1] = [features.Expertise, features.SneakAttack]
|
||||
features_by_level[2] = [features.CunningAction]
|
||||
features_by_level[5] = [features.UncannyDodge]
|
||||
features_by_level[7] = [features.Evasion]
|
||||
features_by_level[11] = [features.ReliableTalent]
|
||||
features_by_level[14] = [features.BlindSense]
|
||||
features_by_level[15] = [features.SlipperyMind]
|
||||
features_by_level[18] = [features.Elusive]
|
||||
features_by_level[20] = [features.StrokeOfLuck]
|
||||
subclasses_available = (Thief, Assassin, ArcaneTrickster,
|
||||
Inquisitive, Mastermind, Scout, Swashbuckler)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
# slippery mind feature
|
||||
if self.owner.Rogue.level >= 15:
|
||||
self.saving_throw_proficiencies = ('dexterity', 'intelligence',
|
||||
'wisdom')
|
||||
|
||||
@@ -30,6 +30,10 @@ class WildMagic(SubClass):
|
||||
"""
|
||||
name = "Wild Magic"
|
||||
features_by_level = defaultdict(list)
|
||||
features_by_level[1] = [features.WildMagicSurge, features.TidesOfChaos]
|
||||
features_by_level[6] = [features.BendLuck]
|
||||
features_by_level[14] = [features.ControlledChaos]
|
||||
features_by_level[18] = [features.SpellBombardment]
|
||||
|
||||
|
||||
# XGTE
|
||||
@@ -107,6 +111,9 @@ class Sorceror(CharClass):
|
||||
class_skill_choices = ('Arcana', 'Deception', 'Insight',
|
||||
'Intimidation', 'Persuasion', 'Religion')
|
||||
features_by_level = defaultdict(list)
|
||||
features_by_level[2] = [features.FontOfMagic]
|
||||
features_by_level[3] = [features.Metamagic]
|
||||
features_by_level[20] = [features.SorcerousRestoration]
|
||||
subclasses_available = (DraconicBloodline, WildMagic, DivineSoul,
|
||||
ShadowMagic, StormSorcery)
|
||||
spellcasting_ability = 'charisma'
|
||||
|
||||
@@ -31,6 +31,10 @@ class Fiend(SubClass):
|
||||
"""
|
||||
name = "The Fiend Patron"
|
||||
features_by_level = defaultdict(list)
|
||||
features_by_level[1] = [features.DarkOnesBlessing]
|
||||
features_by_level[6] = [features.DarkOnesOwnLuck]
|
||||
features_by_level[10] = [features.FiendishResilience]
|
||||
features_by_level[14] = [features.HurlThroughHell]
|
||||
|
||||
|
||||
class GreatOldOne(SubClass):
|
||||
@@ -109,7 +113,13 @@ class Hexblade(SubClass):
|
||||
|
||||
"""
|
||||
name = "Hexblade Patron"
|
||||
weapon_proficiencies = (weapons.MartialWeapon,)
|
||||
_proficiencies_text = ['martial weapons', 'medium armor', 'shields']
|
||||
features_by_level = defaultdict(list)
|
||||
features_by_level[1] = [features.HexbladesCurse, features.HexWarrior]
|
||||
features_by_level[6] = [features.AccursedSpecter]
|
||||
features_by_level[10] = [features.ArmorOfHexes]
|
||||
features_by_level[14] = [features.MasterOfHexes]
|
||||
|
||||
|
||||
class Warlock(CharClass):
|
||||
@@ -126,6 +136,10 @@ class Warlock(CharClass):
|
||||
multiclass_weapon_proficiencies = weapon_proficiencies
|
||||
_multiclass_proficiencies_text = ('light armor', 'simple weapons')
|
||||
features_by_level = defaultdict(list)
|
||||
features_by_level[2] = [features.EldritchInvocation]
|
||||
features_by_level[3] = [features.PactBoon]
|
||||
features_by_level[11] = [features.MysticArcanum]
|
||||
features_by_level[20] = [features.EldritchMaster]
|
||||
subclasses_available = (Archfey, Fiend, GreatOldOne, Undying, Celestial,
|
||||
Hexblade)
|
||||
spellcasting_ability = 'charisma'
|
||||
|
||||
Reference in New Issue
Block a user