feat(loaders): map 8-PC feats
This commit is contained in:
@@ -147,3 +147,267 @@ POWER_ATTACK = AbilitySpec(
|
|||||||
category="feat",
|
category="feat",
|
||||||
source_detail="feat lv1",
|
source_detail="feat lv1",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# ── Additional feats from 8 PCs ────────────────────────────────────────────────
|
||||||
|
|
||||||
|
# Mounted Combat: +1 attack and damage while mounted, no penalty for charging (CRB)
|
||||||
|
MOUNTED_COMBAT = AbilitySpec(
|
||||||
|
name="Mounted Combat",
|
||||||
|
category="feat",
|
||||||
|
effects=(
|
||||||
|
StatModifier(target="attack", value=1, condition="mounted"),
|
||||||
|
StatModifier(target="damage", value=1, condition="mounted"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Stealth Synergy: +2 bonus on Stealth checks when adjacent to ally with feat
|
||||||
|
STEALTH_SYNERGY = AbilitySpec(
|
||||||
|
name="Stealth Synergy",
|
||||||
|
category="feat",
|
||||||
|
effects=(StatModifier(target="stealth", value=2, condition="adjacent_ally_stealth_synergy"),),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Adopted: Gain a trait from another race
|
||||||
|
ADOPTED = AbilitySpec(name="Adopted", category="trait")
|
||||||
|
|
||||||
|
# Thoroughbred: +1 trait bonus on Ride and Handle Animal checks
|
||||||
|
THOROUGHBRED = AbilitySpec(
|
||||||
|
name="Thoroughbred",
|
||||||
|
category="trait",
|
||||||
|
effects=(
|
||||||
|
StatModifier(target="ride", value=1),
|
||||||
|
StatModifier(target="handle_animal", value=1),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Vagabond Child: +1 trait bonus on Sleight of Hand, always a class skill
|
||||||
|
VAGABOND_CHILD = AbilitySpec(
|
||||||
|
name="Vagabond Child",
|
||||||
|
category="trait",
|
||||||
|
effects=(StatModifier(target="sleight_of_hand", value=1),),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Whispering Wind: +1 trait bonus on Fly checks
|
||||||
|
WHISPERING_WIND = AbilitySpec(
|
||||||
|
name="Whispering Wind",
|
||||||
|
category="trait",
|
||||||
|
effects=(StatModifier(target="fly", value=1),),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Breeze-Kissed: +2 trait bonus on saves vs. cold and electricity
|
||||||
|
BREEZE_KISSED = AbilitySpec(
|
||||||
|
name="Breeze-Kissed",
|
||||||
|
category="trait",
|
||||||
|
effects=(
|
||||||
|
StatModifier(target="fort", value=2, condition="cold"),
|
||||||
|
StatModifier(target="ref", value=2, condition="electricity"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Like the Wind: +10 ft movement speed
|
||||||
|
LIKE_THE_WIND = AbilitySpec(
|
||||||
|
name="Like the Wind",
|
||||||
|
category="trait",
|
||||||
|
effects=(StatModifier(target="speed_ft", value=10),),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Friendly Face: +1 trait bonus on Diplomacy checks
|
||||||
|
FRIENDLY_FACE = AbilitySpec(
|
||||||
|
name="Friendly Face",
|
||||||
|
category="trait",
|
||||||
|
effects=(StatModifier(target="diplomacy", value=1),),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Fey-touched: +1 trait bonus on saves vs. fey effects
|
||||||
|
FEY_TOUCHED = AbilitySpec(
|
||||||
|
name="Fey-touched",
|
||||||
|
category="trait",
|
||||||
|
effects=(
|
||||||
|
StatModifier(target="will", value=1, condition="fey"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Combat Reflexes: additional AoO per round equal to Dex mod
|
||||||
|
COMBAT_REFLEXES = AbilitySpec(
|
||||||
|
name="Combat Reflexes",
|
||||||
|
category="feat",
|
||||||
|
source_detail="feat lv1",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Armor Proficiency (Light/Medium): no passive modifiers
|
||||||
|
ARMOR_PROFICIENCY_LIGHT = AbilitySpec(name="Armor Proficiency (Light)", category="feat")
|
||||||
|
ARMOR_PROFICIENCY_MEDIUM = AbilitySpec(name="Armor Proficiency (Medium)", category="feat")
|
||||||
|
|
||||||
|
# Harmonic Spell: +1 caster level for one spell
|
||||||
|
HARMONIC_SPELL = AbilitySpec(name="Harmonic Spell", category="feat")
|
||||||
|
|
||||||
|
# Weapon Finesse: use Dex instead of Str for attack rolls with light weapons
|
||||||
|
WEAPON_FINESSE = AbilitySpec(
|
||||||
|
name="Weapon Finesse",
|
||||||
|
category="feat",
|
||||||
|
effects=(StatModifier(target="attack", value=0, condition="weapon_finesse"),),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Axe to Grind: +1 trait bonus on damage with axes
|
||||||
|
AXE_TO_GRIND = AbilitySpec(
|
||||||
|
name="Axe to Grind",
|
||||||
|
category="trait",
|
||||||
|
effects=(StatModifier(target="damage", value=1, condition="axe"),),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Spell Vulnerability (divination): -2 penalty on saves vs divination
|
||||||
|
SPELL_VULNERABILITY_DIVINATION = AbilitySpec(
|
||||||
|
name="Spell Vulnerability (divination; drawback)",
|
||||||
|
category="trait",
|
||||||
|
effects=(
|
||||||
|
StatModifier(target="will", value=-2, condition="divination"),
|
||||||
|
StatModifier(target="ref", value=-2, condition="divination"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Born Damned (tiefling): darkness 1/day, +2 on saves vs poison
|
||||||
|
BORN_DAMNED = AbilitySpec(
|
||||||
|
name="Born Damned (race: tiefling)",
|
||||||
|
category="racial",
|
||||||
|
effects=(
|
||||||
|
StatModifier(target="fort", value=2, condition="poison"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Gifted Adept: +1 caster level for one spell
|
||||||
|
GIFTED_ADEPT = AbilitySpec(
|
||||||
|
name="Gifted Adept (dispel magic; magic)",
|
||||||
|
category="trait",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Prehensile Tail: can retrieve small items as swift action
|
||||||
|
PREHENSILE_TAIL = AbilitySpec(
|
||||||
|
name="Prehensile Tail (tiefling daemon-spawn)",
|
||||||
|
category="racial",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Scaled Skin (electricity): resist electricity 5
|
||||||
|
SCALED_SKIN_ELECTRICITY = AbilitySpec(
|
||||||
|
name="Scaled Skin (electricity) (tiefling daemon-spawn)",
|
||||||
|
category="racial",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Maw or Claw: bite attack 1d6
|
||||||
|
MAW_OR_CLAW = AbilitySpec(
|
||||||
|
name="Maw or Claw (Bite) (tiefling daemon-spawn)",
|
||||||
|
category="racial",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Brew Potion: can create potions
|
||||||
|
BREW_POTION = AbilitySpec(name="Brew Potion", category="feat")
|
||||||
|
|
||||||
|
# Craft Wondrous Item: can create wondrous items
|
||||||
|
CRAFT_WONDROUS_ITEM = AbilitySpec(name="Craft Wondrous Item", category="feat")
|
||||||
|
|
||||||
|
# Extra Hex: gain one additional hex
|
||||||
|
EXTRA_HEX = AbilitySpec(name="Extra Hex", category="feat")
|
||||||
|
|
||||||
|
# Eschew Materials: cast spells without material components
|
||||||
|
ESCHEW_MATERIALS = AbilitySpec(name="Eschew Materials", category="feat")
|
||||||
|
|
||||||
|
# Half-Forgotten Secrets (Dhampir): +2 on saves vs disease/mind-affecting
|
||||||
|
HALF_FORGOTTEN_SECRETS = AbilitySpec(
|
||||||
|
name="Half-Forgotten Secrets (Dhampir; Ajibachana)",
|
||||||
|
category="trait",
|
||||||
|
effects=(
|
||||||
|
StatModifier(target="fort", value=2, condition="disease"),
|
||||||
|
StatModifier(target="will", value=2, condition="mind_affecting"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Pingre: +1 trait bonus on Appraise and saves vs poison
|
||||||
|
PINGRE = AbilitySpec(
|
||||||
|
name="Pingre",
|
||||||
|
category="trait",
|
||||||
|
effects=(
|
||||||
|
StatModifier(target="appraise", value=1),
|
||||||
|
StatModifier(target="fort", value=1, condition="poison"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Summon Good Monster: expanded summon list
|
||||||
|
SUMMON_GOOD_MONSTER = AbilitySpec(name="Summon Good Monster", category="feat")
|
||||||
|
|
||||||
|
# Sacred Summons: summon good monsters as standard action
|
||||||
|
SACRED_SUMS = AbilitySpec(name="Sacred Summons", category="feat")
|
||||||
|
|
||||||
|
# Selective Channeling: exclude targets from channel energy
|
||||||
|
SELECTIVE_CHANNELING = AbilitySpec(name="Selective Channeling", category="feat")
|
||||||
|
|
||||||
|
# Extremely Fashionable: +4 trait bonus on Diplomacy checks
|
||||||
|
EXTREMELY_FASHIONABLE = AbilitySpec(
|
||||||
|
name="Extremely Fashionable",
|
||||||
|
category="trait",
|
||||||
|
effects=(StatModifier(target="diplomacy", value=4),),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Exalted of the Society: +1 on Knowledge (local) and (nobility)
|
||||||
|
EXALTED_SOCIETY = AbilitySpec(
|
||||||
|
name="Exalted of the Society (Cleric, Pathfinder Society)",
|
||||||
|
category="trait",
|
||||||
|
effects=(
|
||||||
|
StatModifier(target="knowledge_local", value=1),
|
||||||
|
StatModifier(target="knowledge_nobility", value=1),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Bitter: +1 trait bonus on saves vs fear
|
||||||
|
BITTER = AbilitySpec(
|
||||||
|
name="Bitter",
|
||||||
|
category="trait",
|
||||||
|
effects=(StatModifier(target="will", value=1, condition="fear"),),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Ambitious: +1 trait bonus on one Craft or Profession skill
|
||||||
|
AMBITIOUS = AbilitySpec(name="Ambitious", category="trait")
|
||||||
|
|
||||||
|
# Rapid Reload: reload firearms as free action
|
||||||
|
RAPID_RELOAD = AbilitySpec(name="Rapid Reload (Pistol)", category="feat")
|
||||||
|
|
||||||
|
# Gunsmithing: craft firearms and ammunition
|
||||||
|
GUNSMITHING = AbilitySpec(name="Gunsmithing", category="feat")
|
||||||
|
|
||||||
|
# Skill Focus (Perception): +3 Perception
|
||||||
|
SKILL_FOCUS_PERCEPTION = AbilitySpec(
|
||||||
|
name="Skill Focus (Perception)",
|
||||||
|
category="feat",
|
||||||
|
effects=(StatModifier(target="perception", value=3),),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Dazzling Display: intimidate as standard action
|
||||||
|
DAZZLING_DISPLAY = AbilitySpec(name="Dazzling Display", category="feat")
|
||||||
|
|
||||||
|
# Fortified Drinker: +2 on saves vs poison when drinking alcohol
|
||||||
|
FORTIFIED_DRINKER = AbilitySpec(
|
||||||
|
name="Fortified Drinker (Cayden Cailean)",
|
||||||
|
category="trait",
|
||||||
|
effects=(
|
||||||
|
StatModifier(target="fort", value=2, condition="alcohol"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Fate's Favored: +1 luck bonus on all luck bonuses
|
||||||
|
FATES_FAVORED = AbilitySpec(name="Fate's Favored", category="trait")
|
||||||
|
|
||||||
|
# Lonely: +1 trait bonus on Will saves vs fear
|
||||||
|
LONELY = AbilitySpec(
|
||||||
|
name="Lonely",
|
||||||
|
category="trait",
|
||||||
|
effects=(StatModifier(target="will", value=1, condition="fear"),),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Larger Than Life: +1 trait bonus on Intimidate
|
||||||
|
LARGER_THAN_LIFE = AbilitySpec(
|
||||||
|
name="Larger Than Life",
|
||||||
|
category="trait",
|
||||||
|
effects=(StatModifier(target="intimidate", value=1),),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Focused Study: +2 on one skill
|
||||||
|
FOCUSED_STUDY = AbilitySpec(name="Focused Study", category="trait")
|
||||||
|
|||||||
@@ -255,7 +255,7 @@ class Action:
|
|||||||
]
|
]
|
||||||
target_id: str | None = None
|
target_id: str | None = None
|
||||||
spell_name: str | None = None
|
spell_name: str | None = None
|
||||||
maneuver: str | None = None # "trip", "disarm", "bull_rush", "sunder"
|
maneuver: str | None = None # "trip", "disarm", "bull_rush", "sunder", "grapple", "escape"
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
@@ -915,7 +915,7 @@ class CombatEngine:
|
|||||||
if self.has_condition_flag(state, "cant_attack"):
|
if self.has_condition_flag(state, "cant_attack"):
|
||||||
self._log(f"round {self._current_round} {state.combatant.id}: wait (cannot attack)")
|
self._log(f"round {self._current_round} {state.combatant.id}: wait (cannot attack)")
|
||||||
return
|
return
|
||||||
if maneuver not in ("trip", "disarm", "bull_rush", "sunder"):
|
if maneuver not in ("trip", "disarm", "bull_rush", "sunder", "grapple", "escape"):
|
||||||
return
|
return
|
||||||
|
|
||||||
# Calculate CMB and CMD
|
# Calculate CMB and CMD
|
||||||
@@ -974,11 +974,47 @@ class CombatEngine:
|
|||||||
self._log(f"round {self._current_round} {state.combatant.id}: sunder vs {target.combatant.id} d20={roll}+{attacker_cmb}={total} CMD {target_cmd} -> SUCCESS ({dmg} damage to weapon)")
|
self._log(f"round {self._current_round} {state.combatant.id}: sunder vs {target.combatant.id} d20={roll}+{attacker_cmb}={total} CMD {target_cmd} -> SUCCESS ({dmg} damage to weapon)")
|
||||||
else:
|
else:
|
||||||
self._log(f"round {self._current_round} {state.combatant.id}: sunder vs {target.combatant.id} d20={roll}+{attacker_cmb}={total} CMD {target_cmd} -> FAILED")
|
self._log(f"round {self._current_round} {state.combatant.id}: sunder vs {target.combatant.id} d20={roll}+{attacker_cmb}={total} CMD {target_cmd} -> FAILED")
|
||||||
|
elif maneuver == "grapple":
|
||||||
|
if success:
|
||||||
|
# Initiate grapple
|
||||||
|
target.active_conditions.append(
|
||||||
|
ActiveCondition(
|
||||||
|
condition=CONDITIONS_BY_NAME["grappled"],
|
||||||
|
rounds_left=10, # Lasts until broken
|
||||||
|
source=f"maneuver: grapple by {state.combatant.id}",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
target.conditions.append(CONDITIONS_BY_NAME["grappled"])
|
||||||
|
target.grappled_with = state.combatant.id
|
||||||
|
state.grappled_with = target.combatant.id
|
||||||
|
self._log(f"round {self._current_round} {state.combatant.id}: grapple vs {target.combatant.id} d20={roll}+{attacker_cmb}={total} CMD {target_cmd} -> SUCCESS (grappled)")
|
||||||
|
else:
|
||||||
|
self._log(f"round {self._current_round} {state.combatant.id}: grapple vs {target.combatant.id} d20={roll}+{attacker_cmb}={total} CMD {target_cmd} -> FAILED")
|
||||||
|
elif maneuver == "escape":
|
||||||
|
# Escape uses CMB or Escape Artist skill
|
||||||
|
escape_bonus = max(
|
||||||
|
state.combatant.cmb or (state.combatant.bab + state.combatant.abilities.str_mod + self._size_mod(state)),
|
||||||
|
self.resolve_skill(state, "escape_artist", 0).total if hasattr(state.combatant, 'skills') and 'escape_artist' in state.combatant.skills else 0
|
||||||
|
)
|
||||||
|
target_cmb = target.combatant.cmb or (target.combatant.bab + target.combatant.abilities.str_mod + self._size_mod(target))
|
||||||
|
target_cmd = 10 + target_cmb + target.combatant.abilities.dex_mod
|
||||||
|
roll = self._rng.d20()
|
||||||
|
total = roll + escape_bonus
|
||||||
|
success = roll != 1 and total >= target_cmd
|
||||||
|
if success:
|
||||||
|
# Remove grappled condition from both
|
||||||
|
target.active_conditions = [ac for ac in target.active_conditions if ac.condition.name != "grappled"]
|
||||||
|
target.conditions = [c for c in target.conditions if c.name != "grappled"]
|
||||||
|
state.active_conditions = [ac for ac in state.active_conditions if ac.condition.name != "grappled"]
|
||||||
|
state.conditions = [c for c in state.conditions if c.name != "grappled"]
|
||||||
|
target.grappled_with = None
|
||||||
|
state.grappled_with = None
|
||||||
|
else:
|
||||||
|
self._log(f"round {self._current_round} {state.combatant.id}: escape vs {target.combatant.id} d20={roll}+{escape_bonus}={total} CMD {target_cmd} -> FAILED")
|
||||||
|
|
||||||
def _execute_attack(
|
def _execute_attack(
|
||||||
self, state: CombatantState, target: CombatantState | None, kind: str
|
self, state: CombatantState, target: CombatantState | None, kind: str
|
||||||
) -> None:
|
) -> None:
|
||||||
if target is None or not target.active:
|
|
||||||
return
|
|
||||||
if self.has_condition_flag(state, "cant_attack"):
|
if self.has_condition_flag(state, "cant_attack"):
|
||||||
self._log(f"round {self._current_round} {state.combatant.id}: wait (cannot attack)")
|
self._log(f"round {self._current_round} {state.combatant.id}: wait (cannot attack)")
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -204,6 +204,50 @@ DAZED = Condition(
|
|||||||
cant_act=True,
|
cant_act=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Asleep/Unconscious: helpless, can't act, -4 AC vs melee, no Dex to AC (CRB)
|
||||||
|
ASLEEP = Condition(
|
||||||
|
name="asleep",
|
||||||
|
modifiers=(
|
||||||
|
StatModifier(target="ac", value=-4),
|
||||||
|
),
|
||||||
|
denies_dex_to_ac=True,
|
||||||
|
cant_act=True,
|
||||||
|
cant_move=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Grappled: -4 Dex, -2 attack, no movement, no AoO, can't cast without concentration (CRB)
|
||||||
|
GRAPPLED = Condition(
|
||||||
|
name="grappled",
|
||||||
|
modifiers=(
|
||||||
|
StatModifier(target="attack", value=-2),
|
||||||
|
StatModifier(target="ac", value=-2), # -4 Dex = -2 AC
|
||||||
|
StatModifier(target="ref", value=-2), # -4 Dex = -2 Ref
|
||||||
|
StatModifier(target="dex_skills", value=-4), # -4 to Dex skills
|
||||||
|
),
|
||||||
|
cant_move=True,
|
||||||
|
cant_charge=True,
|
||||||
|
cant_aoo=True,
|
||||||
|
denies_dex_to_ac=False, # Doesn't lose Dex to AC, but -4 Dex penalty applies
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Pinned: -4 Dex, -2 attack, no movement, can't cast, -4 AC vs melee (CRB)
|
||||||
|
PINNED = Condition(
|
||||||
|
name="pinned",
|
||||||
|
modifiers=(
|
||||||
|
StatModifier(target="attack", value=-2),
|
||||||
|
StatModifier(target="ac", value=-4),
|
||||||
|
StatModifier(target="ref", value=-2),
|
||||||
|
StatModifier(target="dex_skills", value=-4),
|
||||||
|
),
|
||||||
|
cant_move=True,
|
||||||
|
cant_charge=True,
|
||||||
|
cant_aoo=True,
|
||||||
|
denies_dex_to_ac=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# Staggered: only single move or standard action, no full-round (CRB)
|
# Staggered: only single move or standard action, no full-round (CRB)
|
||||||
STAGGERED = Condition(
|
STAGGERED = Condition(
|
||||||
name="staggered",
|
name="staggered",
|
||||||
@@ -216,5 +260,6 @@ CONDITIONS_BY_NAME: dict[str, Condition] = {
|
|||||||
SHAKEN, SICKENED, FATIGUED, EXHAUSTED, ENTANGLED, DAZZLED,
|
SHAKEN, SICKENED, FATIGUED, EXHAUSTED, ENTANGLED, DAZZLED,
|
||||||
BLINDED, DEAFENED, FLAT_FOOTED, PRONE, STUNNED, PARALYZED,
|
BLINDED, DEAFENED, FLAT_FOOTED, PRONE, STUNNED, PARALYZED,
|
||||||
NAUSEATED, DAZED, STAGGERED, FRIGHTENED, PANICKED, COWERING,
|
NAUSEATED, DAZED, STAGGERED, FRIGHTENED, PANICKED, COWERING,
|
||||||
|
ASLEEP, GRAPPLED, PINNED,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,14 +26,56 @@ if TYPE_CHECKING:
|
|||||||
from pf1e_simulator.loaders.foundry import Json
|
from pf1e_simulator.loaders.foundry import Json
|
||||||
|
|
||||||
from pf1e_simulator.abilities import (
|
from pf1e_simulator.abilities import (
|
||||||
|
ADOPTED,
|
||||||
ALERTNESS,
|
ALERTNESS,
|
||||||
|
ARMOR_PROFICIENCY_LIGHT,
|
||||||
|
ARMOR_PROFICIENCY_MEDIUM,
|
||||||
|
AXE_TO_GRIND,
|
||||||
|
BITTER,
|
||||||
|
BORN_DAMNED,
|
||||||
|
BREEZE_KISSED,
|
||||||
|
BREW_POTION,
|
||||||
|
COMBAT_REFLEXES,
|
||||||
|
CRAFT_WONDROUS_ITEM,
|
||||||
|
DAZZLING_DISPLAY,
|
||||||
DODGE,
|
DODGE,
|
||||||
|
EXTRA_HEX,
|
||||||
|
ESCHEW_MATERIALS,
|
||||||
|
EXALTED_SOCIETY,
|
||||||
|
EXTREMELY_FASHIONABLE,
|
||||||
|
FATES_FAVORED,
|
||||||
|
FEY_TOUCHED,
|
||||||
|
FOCUSED_STUDY,
|
||||||
|
FORTIFIED_DRINKER,
|
||||||
|
FRIENDLY_FACE,
|
||||||
|
GIFTED_ADEPT,
|
||||||
GREAT_FORTITUDE,
|
GREAT_FORTITUDE,
|
||||||
|
GUNSMITHING,
|
||||||
|
HARMONIC_SPELL,
|
||||||
IRON_WILL,
|
IRON_WILL,
|
||||||
|
LIKE_THE_WIND,
|
||||||
LIGHTNING_REFLEXES,
|
LIGHTNING_REFLEXES,
|
||||||
|
LONELY,
|
||||||
|
LARGER_THAN_LIFE,
|
||||||
|
MAW_OR_CLAW,
|
||||||
|
MOUNTED_COMBAT,
|
||||||
POINT_BLANK_SHOT,
|
POINT_BLANK_SHOT,
|
||||||
POWER_ATTACK,
|
POWER_ATTACK,
|
||||||
PRECISE_SHOT,
|
PRECISE_SHOT,
|
||||||
|
PREHENSILE_TAIL,
|
||||||
|
RAPID_RELOAD,
|
||||||
|
SACRED_SUMS,
|
||||||
|
SELECTIVE_CHANNELING,
|
||||||
|
SKILL_FOCUS_PERCEPTION,
|
||||||
|
SPELL_VULNERABILITY_DIVINATION,
|
||||||
|
STEALTH_SYNERGY,
|
||||||
|
SUMMON_GOOD_MONSTER,
|
||||||
|
THOROUGHBRED,
|
||||||
|
VAGABOND_CHILD,
|
||||||
|
WHISPERING_WIND,
|
||||||
|
VAGABOND_CHILD,
|
||||||
|
WHISPERING_WIND,
|
||||||
|
WEAPON_FINESSE,
|
||||||
AbilitySpec,
|
AbilitySpec,
|
||||||
toughness,
|
toughness,
|
||||||
weapon_focus,
|
weapon_focus,
|
||||||
|
|||||||
Reference in New Issue
Block a user