fix(rules): Esha sylph traits and invented names to documented traced no-ops (Whispering Wind/Like the Wind/Breeze-Kissed are real sylph racial traits whose SRD effects the engine cannot resolve - the coded bonuses were fabricated; Fey-touched and Pingre are not PF1e features and move to _NOOP_FEATS; descriptor gating stays covered via local probe specs)

This commit is contained in:
2026-09-19 12:37:32 +02:00
parent 2dd3fefa1d
commit 7262568959
3 changed files with 59 additions and 49 deletions
+19 -31
View File
@@ -198,28 +198,35 @@ VAGABOND_CHILD = AbilitySpec(
effects=(StatModifier(target="sleight_of_hand", value=1),),
)
# Whispering Wind: +1 trait bonus on Fly checks
# Whispering Wind (Sylph alternate racial trait, ARG): "+4 racial bonus on
# Stealth checks" (replaces the sylph spell-like ability). Esha's sheet
# declares race Sylph, so the pick is legal; the engine resolves no Stealth
# checks -> documented traced no-op.
WHISPERING_WIND = AbilitySpec(
name="Whispering Wind",
category="trait",
effects=(StatModifier(target="fly", value=1),),
category="racial",
source_detail="racial sylph (not modeled: +4 racial Stealth, no stealth checks)",
)
# Breeze-Kissed: +2 trait bonus on saves vs. cold and electricity
# Breeze-Kissed (Sylph alternate racial trait, ARG): "+2 racial bonus to AC
# against nonmagical ranged attacks" plus a 1/day gust bull rush or trip
# (replaces air affinity). No magical/nonmagical AC filter exists (AC is a
# final sheet value) and the 1/day maneuver is not selectable -> documented
# traced no-op.
BREEZE_KISSED = AbilitySpec(
name="Breeze-Kissed",
category="trait",
effects=(
StatModifier(target="fort", value=2, condition="cold"),
StatModifier(target="ref", value=2, condition="electricity"),
),
category="racial",
source_detail="racial sylph (not modeled: +2 AC vs nonmagical ranged, 1/day gust)",
)
# Like the Wind: +10 ft movement speed
# Like the Wind (Sylph alternate racial trait, ARG): "+5 foot bonus to base
# speed" (replaces energy resistance). The engine never resolves "speed_ft"
# stat modifiers (movement reads the final JSON speed), and Esha's sheet
# carries the final land speed 25 -> documented traced no-op.
LIKE_THE_WIND = AbilitySpec(
name="Like the Wind",
category="trait",
effects=(StatModifier(target="speed_ft", value=10),),
category="racial",
source_detail="racial sylph (not modeled: +5 ft base speed, speed modifiers unresolved)",
)
# Friendly Face (feat, Animal Archive): "Other animals of roughly the same
@@ -232,15 +239,6 @@ FRIENDLY_FACE = AbilitySpec(
source_detail="feat (not modeled: animal initial attitude +2 steps)",
)
# 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",
@@ -343,16 +341,6 @@ HALF_FORGOTTEN_SECRETS = AbilitySpec(
),
)
# 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")
+7 -6
View File
@@ -46,7 +46,6 @@ from pf1e_simulator.abilities import (
EXTRA_HEX,
EXTREMELY_FASHIONABLE,
FATES_FAVORED,
FEY_TOUCHED,
FOCUSED_STUDY,
FORTIFIED_DRINKER,
FRIENDLY_FACE,
@@ -62,7 +61,6 @@ from pf1e_simulator.abilities import (
LONELY,
MAW_OR_CLAW,
MOUNTED_COMBAT,
PINGRE,
POINT_BLANK_SHOT,
POWER_ATTACK,
PRECISE_SHOT,
@@ -110,7 +108,6 @@ _KNOWN_FEATS: dict[str, AbilitySpec] = {
"breeze-kissed": BREEZE_KISSED,
"like the wind": LIKE_THE_WIND,
"friendly face": FRIENDLY_FACE,
"fey-touched": FEY_TOUCHED,
"combat reflexes": COMBAT_REFLEXES,
"armor proficiency (light)": ARMOR_PROFICIENCY_LIGHT,
"armor proficiency (medium)": ARMOR_PROFICIENCY_MEDIUM,
@@ -128,7 +125,6 @@ _KNOWN_FEATS: dict[str, AbilitySpec] = {
"extra hex": EXTRA_HEX,
"eschew materials": ESCHEW_MATERIALS,
"half-forgotten secrets (dhampir; ajibachana)": HALF_FORGOTTEN_SECRETS,
"pingre": PINGRE,
"summon good monster": SUMMON_GOOD_MONSTER,
"sacred summons": SACRED_SUMS,
"selective channeling": SELECTIVE_CHANNELING,
@@ -147,13 +143,18 @@ _KNOWN_FEATS: dict[str, AbilitySpec] = {
"focused study (trait racial humain \u2014 remplace le bonus feat)": FOCUSED_STUDY,
}
# Feat names with no combat-mechanical definition (flavor / race descriptors / jokes).
# These are resolved to traced no-ops so the loader never silently drops a name.
# Feat names with no combat-mechanical definition (flavor / race descriptors /
# jokes). These are resolved to traced no-ops so the loader never silently
# drops a name. "Fey-touched" (Harvie's sheet) and "Pingre" (Nairda's sheet,
# French for "miser") are not PF1e features; the SRD has no entry under those
# names, so no effect can be attributed to them.
_NOOP_FEATS: frozenset[str] = frozenset({
"6. vert - yes mistress",
"animal (race)",
"drake (race)",
"fey-touched",
"orange - lazy ass",
"pingre",
"plot armor",
})