fix(models): require a positive range_increment_ft (reject 0 and negatives)
This commit is contained in:
@@ -285,7 +285,8 @@ passe par les conditions (`miss_chance`), pas par la carte.
|
||||
```
|
||||
|
||||
Champ `range_increment_ft` (optionnel, uniquement pour `kind: ranged` ou
|
||||
`kind: touch`) : incrément de portée en pieds. La pénalité de portée vaut −2
|
||||
`kind: touch`) : incrément de portée en pieds, entier **strictement positif**
|
||||
(zéro ou négatif = erreur de données, rejetée au chargement). La pénalité de portée vaut −2
|
||||
par incrément complet au-delà du premier ; une arme `ranged` reste utilisable
|
||||
jusqu'à 10 incréments, une arme `touch` jusqu'à 5 (jet/firearm), au-delà elle
|
||||
n'est pas sélectionnable. `damage_bonus` et `dr` sont optionnels.
|
||||
|
||||
@@ -278,7 +278,11 @@ class AttackSpec(_FrozenModel):
|
||||
crit_mult: int = Field(default=2, ge=2, le=4)
|
||||
reach_ft: int = 5
|
||||
reach_weapon: bool = False
|
||||
range_increment_ft: int | None = None
|
||||
# Positive or None (None = no range increments: melee, or touch at natural
|
||||
# reach). A zero increment would crash the engine's range_penalty with a
|
||||
# ZeroDivisionError (dist_ft // 0); a negative one silently makes the
|
||||
# weapon unusable -- both are data errors, rejected at the schema.
|
||||
range_increment_ft: int | None = Field(default=None, ge=1)
|
||||
count: int = Field(default=1, ge=1)
|
||||
firearm: bool = False
|
||||
two_handed: bool = False
|
||||
|
||||
@@ -116,6 +116,21 @@ class TestAttackSpec:
|
||||
with pytest.raises(ValidationError):
|
||||
AttackSpec.model_validate(_attack_dict(damage=[]))
|
||||
|
||||
@pytest.mark.parametrize("increment", [0, -30])
|
||||
def test_rejects_non_positive_range_increment(self, increment: int) -> None:
|
||||
# Given a range_increment_ft of 0 (ZeroDivisionError in range_penalty)
|
||||
# or negative (silently unusable weapon)
|
||||
# When/Then validation rejects it
|
||||
with pytest.raises(ValidationError):
|
||||
AttackSpec.model_validate(_attack_dict(kind="ranged", range_increment_ft=increment))
|
||||
|
||||
def test_accepts_positive_range_increment(self) -> None:
|
||||
# Given a legal range increment
|
||||
# When validated
|
||||
attack = AttackSpec.model_validate(_attack_dict(kind="ranged", range_increment_ft=30))
|
||||
# Then it is kept
|
||||
assert attack.range_increment_ft == 30
|
||||
|
||||
def test_rejects_crit_mult_below_2(self) -> None:
|
||||
# Given crit_mult=1 (a weapon that never multiplies is not PF1e)
|
||||
# When/Then validation rejects it
|
||||
|
||||
Reference in New Issue
Block a user