diff --git a/README.md b/README.md index 855ccbe..41a30c0 100644 --- a/README.md +++ b/README.md @@ -414,17 +414,20 @@ Règles modélisées : `one_round` → **round complet par clamp** — approximation documentée : le moteur ne tient pas d'incantation en cours entre les tours, le sort d'1 round se résout au bout du tour courant au lieu du suivant ; - `long` (≥ 1 minute) → **jeté avant le filtre de budget**, rapporté comme + `long` (> 1 round : 3 rounds, 10 minutes, 1 heure — cast multi-round non + planifiable dans un tour) → **jeté avant le filtre de budget**, rapporté comme `ActionResult(kind="cast_spell", ok=False, reason="downgraded:cast_time")` (seule `default_policy` s'en préserve : `_choose_spell_action` ne sélectionne jamais un sort à temps long). Le moteur résout le code via sa registry (`_cast_time_of`, repli `standard` pour un nom inconnu) et le passe aux - filtres purs sous forme de résolveur `CastTimeResolver`. Seuls - `Summon Monster I/II` déclarent `"1 round"` dans `data/spells/` ; les autres - sorts exotiques (Bladed Dash, Silence…) restent au défaut `standard` — hors - du périmètre de ce paquet. Hors du périmètre (hook futur, commenté dans + filtres purs sous forme de résolveur `CastTimeResolver`. Les 107 sorts + importés de `data/spells/` déclarent tous leur `cast_time` (codes normalisés, + backfillés depuis le SRD) : 95 `standard`, 6 `one_round` (Enhance Water, + Silence, Sleep, Summon Instrument, Summon Monster I/II), 2 `immediate` + (Grasp, Saving Finale) et 4 `long` (Make Whole, Masterwork Transformation, + Mending, Restoration Lesser). Hors du périmètre (hook futur, commenté dans `_cast_time_of`) : la métamagie d'incanteur spontané qui allonge le temps - d'incantation à un round complet sans don Quickened — le signature + d'incantation à un round complet sans don Quickened — la signature `Callable[[Action], CastTime]` du résolveur l'accommodera sans changement. - Retard (`Action(kind="delay")`, action standard) : le combattant renonce à agir maintenant et agit plus tard dans le **même round** — en fin d'ordre si diff --git a/data/spells/abundant_ammunition.json b/data/spells/abundant_ammunition.json index f07bebb..f263e7f 100644 --- a/data/spells/abundant_ammunition.json +++ b/data/spells/abundant_ammunition.json @@ -5,6 +5,7 @@ "range": "close", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "A cantrip that conjures duplicate ammunition: attacks with the affected ammunition do not expend it. No combat-mechanical effect in the engine (ammunition is not tracked)." } diff --git a/data/spells/acid_arrow.json b/data/spells/acid_arrow.json index 8888fae..236daa0 100644 --- a/data/spells/acid_arrow.json +++ b/data/spells/acid_arrow.json @@ -5,6 +5,7 @@ "range": "medium", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "damage", diff --git a/data/spells/acid_splash.json b/data/spells/acid_splash.json index d3dd8f2..12b1f67 100644 --- a/data/spells/acid_splash.json +++ b/data/spells/acid_splash.json @@ -5,6 +5,7 @@ "range": "close", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "damage", diff --git a/data/spells/aid.json b/data/spells/aid.json index e03fc1a..6fe4e93 100644 --- a/data/spells/aid.json +++ b/data/spells/aid.json @@ -5,6 +5,7 @@ "range": "long", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "buff", diff --git a/data/spells/air_bubble.json b/data/spells/air_bubble.json index cd67e91..6717770 100644 --- a/data/spells/air_bubble.json +++ b/data/spells/air_bubble.json @@ -5,6 +5,7 @@ "range": "personal", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "You create a sphere of air around your head (or a touched creature's) that lasts 10 min/level, allowing breathing underwater. No combat-mechanical effect in the engine." } diff --git a/data/spells/alarm.json b/data/spells/alarm.json index 704eb8d..682dcc7 100644 --- a/data/spells/alarm.json +++ b/data/spells/alarm.json @@ -5,6 +5,7 @@ "range": "medium", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "Wards a area (20-ft radius, 20 ft high) against intrusion for 2 hours/level, alerting you mentally. No combat-mechanical effect in the engine." } diff --git a/data/spells/arcane_mark.json b/data/spells/arcane_mark.json index a76eb77..903e725 100644 --- a/data/spells/arcane_mark.json +++ b/data/spells/arcane_mark.json @@ -5,6 +5,7 @@ "range": "touch", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "Creates a permanent visible inscribed mark of your choosing on an object or surface, optionally invisible and keyed to you. Utility cantrip, no combat effect." } diff --git a/data/spells/bane.json b/data/spells/bane.json index 39f15e7..613f3a1 100644 --- a/data/spells/bane.json +++ b/data/spells/bane.json @@ -5,6 +5,7 @@ "range": "medium", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "condition", diff --git a/data/spells/bears_endurance.json b/data/spells/bears_endurance.json index 64e4f90..c5c8c12 100644 --- a/data/spells/bears_endurance.json +++ b/data/spells/bears_endurance.json @@ -5,6 +5,7 @@ "range": "touch", "save": "fort", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "buff", diff --git a/data/spells/bladed_dash.json b/data/spells/bladed_dash.json index d69cdf9..dc639dd 100644 --- a/data/spells/bladed_dash.json +++ b/data/spells/bladed_dash.json @@ -5,6 +5,7 @@ "range": "close", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "buff", diff --git a/data/spells/bleed.json b/data/spells/bleed.json index 4e17a1f..ec8c4a0 100644 --- a/data/spells/bleed.json +++ b/data/spells/bleed.json @@ -5,6 +5,7 @@ "range": "close", "save": "fort", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "condition", diff --git a/data/spells/bless.json b/data/spells/bless.json index 33e54e6..f43b0a7 100644 --- a/data/spells/bless.json +++ b/data/spells/bless.json @@ -5,6 +5,7 @@ "range": "medium", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "area", diff --git a/data/spells/blindness_deafness.json b/data/spells/blindness_deafness.json index fcdfcba..a92a272 100644 --- a/data/spells/blindness_deafness.json +++ b/data/spells/blindness_deafness.json @@ -5,6 +5,7 @@ "range": "medium", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "condition", diff --git a/data/spells/bulls_strength.json b/data/spells/bulls_strength.json index d315734..0367b77 100644 --- a/data/spells/bulls_strength.json +++ b/data/spells/bulls_strength.json @@ -5,6 +5,7 @@ "range": "touch", "save": "fort", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "buff", diff --git a/data/spells/burning_hands.json b/data/spells/burning_hands.json index 3ee9f37..29c4ad8 100644 --- a/data/spells/burning_hands.json +++ b/data/spells/burning_hands.json @@ -5,6 +5,7 @@ "range": "touch", "save": "ref", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "damage", diff --git a/data/spells/charm_person.json b/data/spells/charm_person.json index 19e3e48..6d3a060 100644 --- a/data/spells/charm_person.json +++ b/data/spells/charm_person.json @@ -5,6 +5,7 @@ "range": "medium", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "condition", diff --git a/data/spells/color_spray.json b/data/spells/color_spray.json index 16cd31d..83452d6 100644 --- a/data/spells/color_spray.json +++ b/data/spells/color_spray.json @@ -5,6 +5,7 @@ "range": "close", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "area", diff --git a/data/spells/comprehend_languages.json b/data/spells/comprehend_languages.json index f07d716..9ee2751 100644 --- a/data/spells/comprehend_languages.json +++ b/data/spells/comprehend_languages.json @@ -5,6 +5,7 @@ "range": "personal", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "A cantrip that lets you understand the meaning of any spoken or written language you encounter for 1 min/level. Utility spell, no combat effect." } diff --git a/data/spells/create_alcool.json b/data/spells/create_alcool.json index 54e0b1f..dc32990 100644 --- a/data/spells/create_alcool.json +++ b/data/spells/create_alcool.json @@ -5,6 +5,7 @@ "range": "close", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "A cantrip (Create Alcohol, spelled as on the PC sheet) that transforms one liquid per level into an alcoholic drink of equal volume. Utility spell, no combat effect." } diff --git a/data/spells/create_water.json b/data/spells/create_water.json index 03aa9d8..fde84b0 100644 --- a/data/spells/create_water.json +++ b/data/spells/create_water.json @@ -5,6 +5,7 @@ "range": "medium", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "Conjures 4 gallons of clean water per level in an open space or container. Utility spell, no combat effect." } diff --git a/data/spells/cure_light_wounds.json b/data/spells/cure_light_wounds.json index 6279d1b..8fcef8a 100644 --- a/data/spells/cure_light_wounds.json +++ b/data/spells/cure_light_wounds.json @@ -5,6 +5,7 @@ "range": "touch", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "heal", diff --git a/data/spells/cure_moderate_wounds.json b/data/spells/cure_moderate_wounds.json index 902f5a7..e23049e 100644 --- a/data/spells/cure_moderate_wounds.json +++ b/data/spells/cure_moderate_wounds.json @@ -5,6 +5,7 @@ "range": "touch", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "heal", diff --git a/data/spells/dancing_lights.json b/data/spells/dancing_lights.json index 7521913..b10db9f 100644 --- a/data/spells/dancing_lights.json +++ b/data/spells/dancing_lights.json @@ -5,6 +5,7 @@ "range": "close", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "A cantrip that creates up to four flickering torch-like lights you move as desired (concentration, 1 min/level). Utility spell, no combat effect." } diff --git a/data/spells/darkness.json b/data/spells/darkness.json index bf21c1a..c723a09 100644 --- a/data/spells/darkness.json +++ b/data/spells/darkness.json @@ -5,6 +5,7 @@ "range": "touch", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "area", diff --git a/data/spells/daze.json b/data/spells/daze.json index 52c4ddb..f137b99 100644 --- a/data/spells/daze.json +++ b/data/spells/daze.json @@ -5,6 +5,7 @@ "range": "close", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "condition", diff --git a/data/spells/deja_vu.json b/data/spells/deja_vu.json index 97e4936..dff79b2 100644 --- a/data/spells/deja_vu.json +++ b/data/spells/deja_vu.json @@ -5,6 +5,7 @@ "range": "personal", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "A cantrip that lets you reroll one attack roll, saving throw, or skill check made in the past round (once per casting). Not modeled by the engine's action flow, so it carries no mechanical effect." } diff --git a/data/spells/delay_disease.json b/data/spells/delay_disease.json index 6d9ae75..fa3d44a 100644 --- a/data/spells/delay_disease.json +++ b/data/spells/delay_disease.json @@ -5,6 +5,7 @@ "range": "touch", "save": "fort", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "You suppress the progression of one disease the subject carries for 1 hour/level, keeping it dormant. Utility spell, no combat-mechanical effect in the engine. Fortitude negates (harmless)." } diff --git a/data/spells/delay_poison.json b/data/spells/delay_poison.json index bb1f45f..8312021 100644 --- a/data/spells/delay_poison.json +++ b/data/spells/delay_poison.json @@ -5,6 +5,7 @@ "range": "touch", "save": "fort", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "You temporarily stave off incoming poison or eliminate one already in the subject's system for 1 hour/level. Utility spell, no combat-mechanical effect in the engine. Fortitude negates (harmless)." } diff --git a/data/spells/detect_fiendish_presence.json b/data/spells/detect_fiendish_presence.json index 0b09c44..0d185bd 100644 --- a/data/spells/detect_fiendish_presence.json +++ b/data/spells/detect_fiendish_presence.json @@ -5,6 +5,7 @@ "range": "close", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "A cantrip that reveals whether a creature of the outsider (evil) subtype has been in the area within 10 minutes/HD, and hints at its nature. Utility spell, no combat effect." } diff --git a/data/spells/detect_magic.json b/data/spells/detect_magic.json index 6c471ba..156aa20 100644 --- a/data/spells/detect_magic.json +++ b/data/spells/detect_magic.json @@ -5,6 +5,7 @@ "range": "close", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "A cantrip that detects magical auras in a 60-ft cone (2 rounds to identify strength and school). Utility spell, no combat effect." } diff --git a/data/spells/detect_poison.json b/data/spells/detect_poison.json index ff5767f..ee09ed3 100644 --- a/data/spells/detect_poison.json +++ b/data/spells/detect_poison.json @@ -5,6 +5,7 @@ "range": "close", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "A cantrip that determines whether a creature, object, or area is poisoned, venomous, or afflicted by acid. Utility spell, no combat effect." } diff --git a/data/spells/disrupt_undead.json b/data/spells/disrupt_undead.json index 1720b46..93e93b8 100644 --- a/data/spells/disrupt_undead.json +++ b/data/spells/disrupt_undead.json @@ -5,6 +5,7 @@ "range": "close", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "damage", diff --git a/data/spells/divine_favor.json b/data/spells/divine_favor.json index dd99461..ee6f363 100644 --- a/data/spells/divine_favor.json +++ b/data/spells/divine_favor.json @@ -5,6 +5,7 @@ "range": "personal", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "You draw upon divine power for 1 round/level: a +1 luck bonus on attack rolls and weapon damage per 4 caster levels. Simplified: the engine has no luck-bonus self-buff that preserves the pinned default-policy casting order, so no mechanical effect is applied." } diff --git a/data/spells/doom.json b/data/spells/doom.json index 9f3227f..5dc6950 100644 --- a/data/spells/doom.json +++ b/data/spells/doom.json @@ -5,6 +5,7 @@ "range": "close", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "condition", diff --git a/data/spells/drunkards_breath.json b/data/spells/drunkards_breath.json index bdef68e..44e5127 100644 --- a/data/spells/drunkards_breath.json +++ b/data/spells/drunkards_breath.json @@ -5,6 +5,7 @@ "range": "personal", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "For 1 hour/level you gain DR 5/- against alcohol effects and cannot become drunk. The engine has no DR buff target, so no mechanical effect is applied." } diff --git a/data/spells/endure_elements.json b/data/spells/endure_elements.json index 03aaff1..358e26c 100644 --- a/data/spells/endure_elements.json +++ b/data/spells/endure_elements.json @@ -5,6 +5,7 @@ "range": "personal", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "For 24 hours you tolerate comfortable extremes of heat and cold (from -50 to 140 degrees F) without ill effect. Environmental protection, no combat-mechanical effect in the engine." } diff --git a/data/spells/enhance_water.json b/data/spells/enhance_water.json index 6d53fe9..18bfea0 100644 --- a/data/spells/enhance_water.json +++ b/data/spells/enhance_water.json @@ -5,6 +5,7 @@ "range": "personal", "save": "none", "base_dc": 10, + "cast_time": "one_round", "effects": [], "description": "You purify and bless 1 gallon/level of water (or one vial of holy/unholy water). Utility spell, no combat-mechanical effect in the engine." } diff --git a/data/spells/enhanced_diplomacy.json b/data/spells/enhanced_diplomacy.json index c7c7ca4..49bca72 100644 --- a/data/spells/enhanced_diplomacy.json +++ b/data/spells/enhanced_diplomacy.json @@ -5,6 +5,7 @@ "range": "touch", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "A cantrip: the subject gains a +2 competence bonus on a single Diplomacy or Intimidate check, declared before the roll (duration 1 minute or until discharged). Will negates (harmless). Social skill effect only: the engine does not model skill-check modifiers, so the spell has no mechanical effects here." } diff --git a/data/spells/face_of_the_devourer.json b/data/spells/face_of_the_devourer.json index 6044aaf..b7b23a1 100644 --- a/data/spells/face_of_the_devourer.json +++ b/data/spells/face_of_the_devourer.json @@ -5,6 +5,7 @@ "range": "touch", "save": "fort", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "The target's face becomes hideous: it gains a +4 circumstance bonus on Intimidate checks and, if it lacks one, a bite attack (1d6 for Medium) for 1 min/level. Fortitude negates (harmless). The skill bonus and the granted natural attack are not modeled by the engine, so the spell has no mechanical effects here." } diff --git a/data/spells/fear.json b/data/spells/fear.json index 57a82f8..6406544 100644 --- a/data/spells/fear.json +++ b/data/spells/fear.json @@ -5,6 +5,7 @@ "range": "medium", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "condition", diff --git a/data/spells/fireball.json b/data/spells/fireball.json index 86debf0..3f368e0 100644 --- a/data/spells/fireball.json +++ b/data/spells/fireball.json @@ -5,6 +5,7 @@ "range": "long", "save": "ref", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "area", diff --git a/data/spells/flurry_of_snowballs.json b/data/spells/flurry_of_snowballs.json index 89b8621..d6f633b 100644 --- a/data/spells/flurry_of_snowballs.json +++ b/data/spells/flurry_of_snowballs.json @@ -5,6 +5,7 @@ "range": "close", "save": "ref", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "area", diff --git a/data/spells/forbid_action.json b/data/spells/forbid_action.json index 903c135..2b4008f 100644 --- a/data/spells/forbid_action.json +++ b/data/spells/forbid_action.json @@ -5,6 +5,7 @@ "range": "close", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "condition", diff --git a/data/spells/grasp.json b/data/spells/grasp.json index 75b2079..2fadea2 100644 --- a/data/spells/grasp.json +++ b/data/spells/grasp.json @@ -5,6 +5,7 @@ "range": "personal", "save": "none", "base_dc": 10, + "cast_time": "immediate", "effects": [], "description": "A cantrip cast as an immediate action when you fail a Climb check and would fall: you immediately retry the Climb check at a -2 penalty (increasing by 2 per successive use in the same situation); on success you don't fall. Climbing is not modeled by the engine, so the spell has no mechanical effects here." } diff --git a/data/spells/guidance.json b/data/spells/guidance.json index 230aad1..a5a1014 100644 --- a/data/spells/guidance.json +++ b/data/spells/guidance.json @@ -5,6 +5,7 @@ "range": "touch", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "A cantrip: the subject gains a +1 competence bonus on a single attack roll, saving throw, or skill check, declared before the roll (duration 1 minute or until discharged). Will negates (harmless). Single-roll discharge is not modeled by the engine, so the spell has no mechanical effects here." } diff --git a/data/spells/heroism.json b/data/spells/heroism.json index a1693d8..9eff129 100644 --- a/data/spells/heroism.json +++ b/data/spells/heroism.json @@ -5,6 +5,7 @@ "range": "touch", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "buff", diff --git a/data/spells/hex_vulnerability.json b/data/spells/hex_vulnerability.json index 2826e17..d05191f 100644 --- a/data/spells/hex_vulnerability.json +++ b/data/spells/hex_vulnerability.json @@ -5,6 +5,7 @@ "range": "close", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "The target becomes susceptible to a repeat use of your harmful hexes for 1 round/level, bypassing the once-per-day targeting limit. Will negates. No combat effect: the hex-reuse permission is outside the engine's model, so the spell has no mechanical effects here." } diff --git a/data/spells/hidden_diplomacy.json b/data/spells/hidden_diplomacy.json index e74d507..f5ba25a 100644 --- a/data/spells/hidden_diplomacy.json +++ b/data/spells/hidden_diplomacy.json @@ -5,6 +5,7 @@ "range": "close", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "As part of casting, you attempt a single Intimidate check to make the target act friendly; its memory of the threats is clouded, so its attitude does not worsen afterward. Will negates. Social effect only: no combat mechanics are modeled." } diff --git a/data/spells/hide_from_undead.json b/data/spells/hide_from_undead.json index cfea54d..943edd6 100644 --- a/data/spells/hide_from_undead.json +++ b/data/spells/hide_from_undead.json @@ -5,6 +5,7 @@ "range": "touch", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "Undead cannot perceive warded creatures (nonintelligent undead ignore them automatically; intelligent undead get a single Will save) until the subject attacks, channels energy, or touches undead. Duration 10 min/level. Saving throw entries here cover the harmless-target save; the undead-perception effect is not modeled by the engine." } diff --git a/data/spells/hold_person.json b/data/spells/hold_person.json index 343a8f9..95d1242 100644 --- a/data/spells/hold_person.json +++ b/data/spells/hold_person.json @@ -5,6 +5,7 @@ "range": "medium", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "condition", diff --git a/data/spells/ice_slick.json b/data/spells/ice_slick.json index 3b004bd..f38fc84 100644 --- a/data/spells/ice_slick.json +++ b/data/spells/ice_slick.json @@ -5,6 +5,7 @@ "range": "close", "save": "ref", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "area", diff --git a/data/spells/ill_omen.json b/data/spells/ill_omen.json index 208a3ac..c24018b 100644 --- a/data/spells/ill_omen.json +++ b/data/spells/ill_omen.json @@ -5,6 +5,7 @@ "range": "close", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "The target is afflicted with bad luck: on its next d20 roll (one per 5 caster levels, up to five) it must roll twice and take the less favorable result; duration 1 round/level. No saving throw; spell resistance applies. The forced worst-of-two reroll mechanic is not modeled by the engine, so the spell has no mechanical effects here." } diff --git a/data/spells/inflict_light_wounds.json b/data/spells/inflict_light_wounds.json index 463ca91..8535ba6 100644 --- a/data/spells/inflict_light_wounds.json +++ b/data/spells/inflict_light_wounds.json @@ -5,6 +5,7 @@ "range": "touch", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "damage", diff --git a/data/spells/ironskin.json b/data/spells/ironskin.json index 86d1128..ab0ace2 100644 --- a/data/spells/ironskin.json +++ b/data/spells/ironskin.json @@ -5,6 +5,7 @@ "range": "personal", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "buff", diff --git a/data/spells/light.json b/data/spells/light.json index 353a09c..cc73bb0 100644 --- a/data/spells/light.json +++ b/data/spells/light.json @@ -5,6 +5,7 @@ "range": "touch", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "A cantrip: a touched object glows like a torch, shedding normal light in a 20-foot radius (plus dim light for 20 more feet) for 10 min/level. No combat effect; illumination is not modeled by the engine." } diff --git a/data/spells/lightning_bolt.json b/data/spells/lightning_bolt.json index 186fc0d..be7853c 100644 --- a/data/spells/lightning_bolt.json +++ b/data/spells/lightning_bolt.json @@ -5,6 +5,7 @@ "range": "medium", "save": "ref", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "damage", diff --git a/data/spells/mage_hand.json b/data/spells/mage_hand.json index c1723ea..f2d2bdc 100644 --- a/data/spells/mage_hand.json +++ b/data/spells/mage_hand.json @@ -5,6 +5,7 @@ "range": "close", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "A cantrip: a spectral hand lifts and moves one unattended nonmagical object weighing up to 5 lb. from up to 25 ft. away, as far as 15 feet per move action while you concentrate. No combat effect; object manipulation is not modeled by the engine." } diff --git a/data/spells/magic_missile.json b/data/spells/magic_missile.json index 21aa47d..841faca 100644 --- a/data/spells/magic_missile.json +++ b/data/spells/magic_missile.json @@ -5,6 +5,7 @@ "range": "medium", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "damage", diff --git a/data/spells/make_whole.json b/data/spells/make_whole.json index 6893eb9..d53b070 100644 --- a/data/spells/make_whole.json +++ b/data/spells/make_whole.json @@ -5,6 +5,7 @@ "range": "close", "save": "will", "base_dc": 10, + "cast_time": "long", "effects": [], "description": "Repairs 1d6 points of damage per caster level (maximum 5d6) to one object or construct creature (10-minute casting). Will negates (harmless, object). Object/construct repair is outside the engine's combat model, so the spell has no mechanical effects here." } diff --git a/data/spells/masterwork_transformation.json b/data/spells/masterwork_transformation.json index b221356..ca26b3e 100644 --- a/data/spells/masterwork_transformation.json +++ b/data/spells/masterwork_transformation.json @@ -5,6 +5,7 @@ "range": "touch", "save": "none", "base_dc": 10, + "cast_time": "long", "effects": [], "description": "After 1 hour of casting (plus masterwork-priced reagents), a non-masterwork weapon, armor, shield, tool, or skill kit becomes its masterwork equivalent. Item crafting is outside the engine's combat model, so the spell has no mechanical effects here." } diff --git a/data/spells/mending.json b/data/spells/mending.json index c286e6b..75ceab6 100644 --- a/data/spells/mending.json +++ b/data/spells/mending.json @@ -5,6 +5,7 @@ "range": "close", "save": "will", "base_dc": 10, + "cast_time": "long", "effects": [], "description": "A cantrip: after 10 minutes, the spell repairs 1d4 hit points of damage to one object (up to 1 lb./level), removing the broken condition if restored to at least half HP. Will negates (harmless, object). Object repair is outside the engine's combat model, so the spell has no mechanical effects here." } diff --git a/data/spells/message.json b/data/spells/message.json index 127f9a4..9f72d43 100644 --- a/data/spells/message.json +++ b/data/spells/message.json @@ -5,6 +5,7 @@ "range": "medium", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "A cantrip: you whisper messages and receive replies with targeted creatures within range for 10 min/level; bystanders hear nothing without a DC 25 Perception check. Communication is not modeled by the engine, so the spell has no mechanical effects here." } diff --git a/data/spells/mirror_image.json b/data/spells/mirror_image.json index 1602825..162e14e 100644 --- a/data/spells/mirror_image.json +++ b/data/spells/mirror_image.json @@ -5,6 +5,7 @@ "range": "personal", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "condition", diff --git a/data/spells/oath_of_anonymity.json b/data/spells/oath_of_anonymity.json index 7f54321..23ed626 100644 --- a/data/spells/oath_of_anonymity.json +++ b/data/spells/oath_of_anonymity.json @@ -5,6 +5,7 @@ "range": "personal", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "A cantrip: you swear an oath of secrecy - your voice, body language and gear are magically distorted, granting a +10 bonus on Disguise checks to conceal your identity (not to impersonate a specific person) for 10 min/level. Social skill effect only: the engine does not model skill-check modifiers, so the spell has no mechanical effects here." } diff --git a/data/spells/obscuring_mist.json b/data/spells/obscuring_mist.json index 9965645..e24aa04 100644 --- a/data/spells/obscuring_mist.json +++ b/data/spells/obscuring_mist.json @@ -5,6 +5,7 @@ "range": "close", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "area", diff --git a/data/spells/open_close.json b/data/spells/open_close.json index ae7d4f3..fa14dd3 100644 --- a/data/spells/open_close.json +++ b/data/spells/open_close.json @@ -5,6 +5,7 @@ "range": "close", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "A cantrip: you open or close one unsecured object or portal weighing up to 30 lb. at up to 25 ft. away (fails if a bar or lock resists). Will negates (object). Object manipulation is not modeled by the engine, so the spell has no mechanical effects here." } diff --git a/data/spells/owls_wisdom.json b/data/spells/owls_wisdom.json index 3223684..f752ccb 100644 --- a/data/spells/owls_wisdom.json +++ b/data/spells/owls_wisdom.json @@ -5,6 +5,7 @@ "range": "touch", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "The subject gains a +4 enhancement bonus to Wisdom for 1 min/level, adding the usual benefit to Wisdom-based skills, Will saves and spell DCs. Will negates (harmless). Ability-score increases are not modeled by the engine, so the spell has no mechanical effects here." } diff --git a/data/spells/prestidigitation.json b/data/spells/prestidigitation.json index 6baca5f..e7ac790 100644 --- a/data/spells/prestidigitation.json +++ b/data/spells/prestidigitation.json @@ -5,6 +5,7 @@ "range": "close", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "A cantrip: minor magical tricks for 1 hour - lift 1 lb. of material, color/clean/soil items in a 1-ft cube, chill/warm/flavor 1 lb. of nonliving material, or create crude trinkets. It can deal no damage and duplicates no other spell. No combat effect; the trivial manipulations are not modeled by the engine." } diff --git a/data/spells/protection_from_evil.json b/data/spells/protection_from_evil.json index 5f26b89..232cf41 100644 --- a/data/spells/protection_from_evil.json +++ b/data/spells/protection_from_evil.json @@ -5,6 +5,7 @@ "range": "touch", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "A barrier wards the subject from evil for 1 min/level: +2 deflection bonus to AC and +2 resistance bonus on saves against attacks and effects created by evil creatures, renewed saves and suppression of mental control, and lawful summoned evil creatures cannot touch it. Will negates (harmless). The engine has no alignment system, so alignment-restricted bonuses cannot be modeled and the spell has no mechanical effects here." } diff --git a/data/spells/protection_from_evil_communal.json b/data/spells/protection_from_evil_communal.json index 0182edc..ae57cc0 100644 --- a/data/spells/protection_from_evil_communal.json +++ b/data/spells/protection_from_evil_communal.json @@ -5,6 +5,7 @@ "range": "touch", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "Functions like protection from evil (+2 deflection to AC and +2 resistance on saves vs evil creatures, protection from mental control), except the 1 min/level duration is divided in 1-minute intervals among the touched creatures. Will negates (harmless). Alignment-restricted bonuses and duration-sharing are not modeled, so the spell has no mechanical effects here." } diff --git a/data/spells/protection_from_law.json b/data/spells/protection_from_law.json index fecb172..1970d29 100644 --- a/data/spells/protection_from_law.json +++ b/data/spells/protection_from_law.json @@ -5,6 +5,7 @@ "range": "touch", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "A barrier wards the subject from lawful creatures for 1 min/level: +2 deflection bonus to AC and +2 resistance bonus on saves against attacks and effects created by lawful creatures, plus renewed saves against mental control by lawful creatures. Will negates (harmless). The engine has no alignment system, so alignment-restricted bonuses cannot be modeled and the spell has no mechanical effects here." } diff --git a/data/spells/protection_from_law_communal.json b/data/spells/protection_from_law_communal.json index dd06bda..8e857e4 100644 --- a/data/spells/protection_from_law_communal.json +++ b/data/spells/protection_from_law_communal.json @@ -5,6 +5,7 @@ "range": "touch", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "Functions like protection from law (+2 deflection to AC and +2 resistance on saves vs lawful creatures, protection from mental control), except the 1 min/level duration is divided in 1-minute intervals among the touched creatures. Will negates (harmless). Alignment-restricted bonuses and duration-sharing are not modeled, so the spell has no mechanical effects here." } diff --git a/data/spells/purify_food_and_drink.json b/data/spells/purify_food_and_drink.json index c97bdbb..c8ba06c 100644 --- a/data/spells/purify_food_and_drink.json +++ b/data/spells/purify_food_and_drink.json @@ -5,6 +5,7 @@ "range": "close", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "A cantrip: cleanses 1 cu. ft./level of spoiled, rotten, diseased or poisoned food and water, making it pure and drinkable (no effect on creatures or magic potions). Will negates (object). Non-combat utility: the engine does not model objects, so the spell has no mechanical effects here." } diff --git a/data/spells/putrefy_food_and_drink.json b/data/spells/putrefy_food_and_drink.json index 95a4407..6f09041 100644 --- a/data/spells/putrefy_food_and_drink.json +++ b/data/spells/putrefy_food_and_drink.json @@ -5,6 +5,7 @@ "range": "close", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "A cantrip: instantly rots 1 cu. ft./level of edible food and makes water and liquids brackish and undrinkable (can also spoil a single potion; no effect on creatures or unholy water). Will negates (object). Non-combat utility: the engine does not model objects, so the spell has no mechanical effects here." } diff --git a/data/spells/ray_of_enfeeblement.json b/data/spells/ray_of_enfeeblement.json index 350277e..a7fca83 100644 --- a/data/spells/ray_of_enfeeblement.json +++ b/data/spells/ray_of_enfeeblement.json @@ -5,6 +5,7 @@ "range": "close", "save": "fort", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "condition", diff --git a/data/spells/ray_of_frost.json b/data/spells/ray_of_frost.json index 707a772..ef6c565 100644 --- a/data/spells/ray_of_frost.json +++ b/data/spells/ray_of_frost.json @@ -5,6 +5,7 @@ "range": "close", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "damage", diff --git a/data/spells/read_magic.json b/data/spells/read_magic.json index ef76d81..8cd64c1 100644 --- a/data/spells/read_magic.json +++ b/data/spells/read_magic.json @@ -5,6 +5,7 @@ "range": "personal", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "A cantrip: you can decipher magical inscriptions on objects that would otherwise be unintelligible, at one page per minute, and you can thereafter read that particular writing without the spell. Duration 10 min./level. No combat effect; reading magical writing is not modeled by the engine." } diff --git a/data/spells/resistance.json b/data/spells/resistance.json index 5cb7652..8cda58c 100644 --- a/data/spells/resistance.json +++ b/data/spells/resistance.json @@ -5,6 +5,7 @@ "range": "touch", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "A cantrip: the subject gains a +1 resistance bonus on saving throws for 1 minute. Will negates (harmless). Simplified: the engine has no resistance bonus type and no self-buff encoding that preserves the pinned default-policy casting order, so no mechanical effect is applied." } diff --git a/data/spells/restoration_lesser.json b/data/spells/restoration_lesser.json index a01aec4..d94a561 100644 --- a/data/spells/restoration_lesser.json +++ b/data/spells/restoration_lesser.json @@ -5,6 +5,7 @@ "range": "touch", "save": "will", "base_dc": 10, + "cast_time": "long", "effects": [], "description": "Casting time 3 rounds. Dispels any magical effects reducing one of the subject's ability scores or cures 1d4 points of temporary ability damage to one ability score, and eliminates any fatigue (improving exhausted to fatigued). Will negates (harmless). No combat effect encoded: the engine has no ability damage, fatigue-from-spell, or magical-effect-reduction state to restore." } diff --git a/data/spells/sanctuary.json b/data/spells/sanctuary.json index ca7095a..9490519 100644 --- a/data/spells/sanctuary.json +++ b/data/spells/sanctuary.json @@ -5,6 +5,7 @@ "range": "touch", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "You ward a creature against attacks for 1 round/level: any opponent attempting to directly attack the warded creature must succeed on a Will save or be unable to follow through with that attack and cannot directly attack the subject for the duration. The subject cannot attack without ending the spell. Will negates. No combat effect encoded: the engine has no attack-refusal-by-save mechanic, so the protection cannot be represented." } diff --git a/data/spells/saving_finale.json b/data/spells/saving_finale.json index 487d4f7..9443e2e 100644 --- a/data/spells/saving_finale.json +++ b/data/spells/saving_finale.json @@ -5,6 +5,7 @@ "range": "close", "save": "will", "base_dc": 10, + "cast_time": "immediate", "effects": [], "description": "Immediate action, requires an active bardic performance: when a creature affected by your performance fails a saving throw, end the performance to let it immediately reroll the failed save and take the new result. Will negates (harmless). No combat effect encoded: conditional save rerolls tied to bardic performance are not modeled by the engine." } diff --git a/data/spells/scorching_ray.json b/data/spells/scorching_ray.json index 8716a5f..4a16846 100644 --- a/data/spells/scorching_ray.json +++ b/data/spells/scorching_ray.json @@ -5,6 +5,7 @@ "range": "close", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "damage", diff --git a/data/spells/shard_of_chaos.json b/data/spells/shard_of_chaos.json index 0130ff8..f9d73c0 100644 --- a/data/spells/shard_of_chaos.json +++ b/data/spells/shard_of_chaos.json @@ -5,6 +5,7 @@ "range": "close", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "A dart-shaped projectile of chaotic energy (ranged touch attack): lawful creatures take 1d8 per two caster levels (max 5d8); lawful outsiders take 1d6 per caster level (max 10d6) and are slowed 1 round. A successful Will save halves the damage and negates the slow. Half damage to neutral creatures, no effect on chaotic ones. No combat effect encoded: the engine has no alignment, so the alignment-gated damage cannot be represented." } diff --git a/data/spells/shield.json b/data/spells/shield.json index 9870e1b..fe8e1cd 100644 --- a/data/spells/shield.json +++ b/data/spells/shield.json @@ -5,6 +5,7 @@ "range": "personal", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "buff", diff --git a/data/spells/shield_of_faith.json b/data/spells/shield_of_faith.json index 45dae8b..c41440c 100644 --- a/data/spells/shield_of_faith.json +++ b/data/spells/shield_of_faith.json @@ -5,6 +5,7 @@ "range": "touch", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "A shimmering magical field grants the target a +2 deflection bonus to AC (+1 per six caster levels, max +5) for 1 min./level. Will negates (harmless). Simplified: the engine has no self-buff encoding that preserves the pinned default-policy casting order, so no mechanical effect is applied." } diff --git a/data/spells/shocking_grasp.json b/data/spells/shocking_grasp.json index 23f6839..799440c 100644 --- a/data/spells/shocking_grasp.json +++ b/data/spells/shocking_grasp.json @@ -5,6 +5,7 @@ "range": "touch", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "damage", diff --git a/data/spells/silence.json b/data/spells/silence.json index d5c2b1d..95eb77d 100644 --- a/data/spells/silence.json +++ b/data/spells/silence.json @@ -5,6 +5,7 @@ "range": "long", "save": "will", "base_dc": 10, + "cast_time": "one_round", "effects": [], "description": "Casting time 1 round. A 20-ft.-radius emanation centered on a creature, object, or point in space: all sound is stopped in the area, spells with verbal components cannot be cast, and creatures inside are immune to sonic and language-dependent effects. Duration 1 round/level. Will negates (object). No combat effect encoded: the engine has no verbal component or sound propagation model." } diff --git a/data/spells/sleep.json b/data/spells/sleep.json index ab53ae2..bee6972 100644 --- a/data/spells/sleep.json +++ b/data/spells/sleep.json @@ -5,6 +5,7 @@ "range": "medium", "save": "will", "base_dc": 10, + "cast_time": "one_round", "effects": [ { "type": "area", diff --git a/data/spells/sound_burst.json b/data/spells/sound_burst.json index 5ab47df..9e1ef76 100644 --- a/data/spells/sound_burst.json +++ b/data/spells/sound_burst.json @@ -5,6 +5,7 @@ "range": "close", "save": "fort", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "area", diff --git a/data/spells/spark.json b/data/spells/spark.json index bb7861d..b3da32b 100644 --- a/data/spells/spark.json +++ b/data/spells/spark.json @@ -5,6 +5,7 @@ "range": "close", "save": "fort", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "A cantrip: you create a tiny spark that ignites one unattended Fine flammable object within close range, in any weather (works as flint and steel but much faster). Fortitude negates (object). No combat effect: the spell targets objects, not creatures." } diff --git a/data/spells/spear_of_purity.json b/data/spells/spear_of_purity.json index 232482a..166f755 100644 --- a/data/spells/spear_of_purity.json +++ b/data/spells/spear_of_purity.json @@ -5,6 +5,7 @@ "range": "close", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "A spear of good energy (ranged touch attack): evil creatures take 1d8 per two caster levels (max 5d8); evil outsiders take 1d6 per caster level (max 10d6) and are blinded 1 round. A successful Will save halves the damage and negates the blind. Half damage to neutral creatures, no effect on good ones. No combat effect encoded: the engine has no alignment, so the alignment-gated damage cannot be represented." } diff --git a/data/spells/spiritual_weapon.json b/data/spells/spiritual_weapon.json index 58bdebe..346393b 100644 --- a/data/spells/spiritual_weapon.json +++ b/data/spells/spiritual_weapon.json @@ -5,6 +5,7 @@ "range": "medium", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "A force weapon appears and attacks foes at a distance as you direct it (1d8 force damage +1 per three caster levels), using your base attack bonus plus Wisdom modifier, once per round on your turn for 1 round/level. No combat effect encoded: the engine has no autonomous floating-attack creature to summon, and the weapon's per-round attacks are not modeled." } diff --git a/data/spells/stabilize.json b/data/spells/stabilize.json index e20eabb..179e904 100644 --- a/data/spells/stabilize.json +++ b/data/spells/stabilize.json @@ -5,6 +5,7 @@ "range": "close", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "A cantrip: you touch a living creature with -1 or fewer hit points (up to close range) and stabilize it automatically, so it stops losing hit points until it takes more damage. Will negates (harmless). No combat effect encoded: the engine's dying/stabilization track is not exposed to the spell-effect system." } diff --git a/data/spells/status.json b/data/spells/status.json index 6a77032..625de1b 100644 --- a/data/spells/status.json +++ b/data/spells/status.json @@ -5,6 +5,7 @@ "range": "touch", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "You mentally monitor the relative position and general condition (unharmed, wounded, staggered, unconscious, dying, poisoned, and so on) of up to one creature per three caster levels for 1 hour/level. Will negates (harmless). No combat effect: out-of-combat scrying is not modeled by the engine." } diff --git a/data/spells/stave_off_corruption.json b/data/spells/stave_off_corruption.json index df464c7..3de0f0e 100644 --- a/data/spells/stave_off_corruption.json +++ b/data/spells/stave_off_corruption.json @@ -5,6 +5,7 @@ "range": "touch", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "You ward the target to slow the advancement of its corruption, granting a +2 circumstance bonus on saving throws against the advancement of that corruption for 1 day per 2 caster levels. Will negates (harmless). Simplified: the engine has no corruption track and no self-buff encoding that preserves the pinned default-policy casting order, so no mechanical effect is applied." } diff --git a/data/spells/summon_instrument.json b/data/spells/summon_instrument.json index c41261b..2d3401b 100644 --- a/data/spells/summon_instrument.json +++ b/data/spells/summon_instrument.json @@ -5,6 +5,7 @@ "range": "personal", "save": "none", "base_dc": 10, + "cast_time": "one_round", "effects": [], "description": "A cantrip (casting time 1 round): you summon one handheld musical instrument of your choice into your hands or at your feet; it plays only for you and disappears when the spell ends (1 min./level). No combat effect: summoned objects are not modeled by the engine." } diff --git a/data/spells/summon_monster_i.json b/data/spells/summon_monster_i.json index 0369403..0bb761f 100644 --- a/data/spells/summon_monster_i.json +++ b/data/spells/summon_monster_i.json @@ -5,7 +5,7 @@ "range": "close", "save": "none", "base_dc": 10, - "cast_time": "1 round", + "cast_time": "one_round", "effects": [ { "type": "summon", diff --git a/data/spells/summon_monster_ii.json b/data/spells/summon_monster_ii.json index 1828b81..ff56e8c 100644 --- a/data/spells/summon_monster_ii.json +++ b/data/spells/summon_monster_ii.json @@ -5,7 +5,7 @@ "range": "close", "save": "none", "base_dc": 10, - "cast_time": "1 round", + "cast_time": "one_round", "effects": [ { "type": "summon", diff --git a/data/spells/suppress_charms_and_compulsions.json b/data/spells/suppress_charms_and_compulsions.json index 845b711..ee9528d 100644 --- a/data/spells/suppress_charms_and_compulsions.json +++ b/data/spells/suppress_charms_and_compulsions.json @@ -5,6 +5,7 @@ "range": "close", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "You bolster the target's willpower: either a +4 morale bonus on saving throws against charm and compulsion effects for 10 minutes, or (as concentration, max 1 round/level) suppression of all charm and compulsion effects on the targets. Will negates (harmless). Simplified: the engine has no conditional save bonus and no self-buff encoding that preserves the pinned default-policy casting order, so no mechanical effect is applied." } diff --git a/data/spells/surmount_affliction.json b/data/spells/surmount_affliction.json index dc2533b..55e7ad1 100644 --- a/data/spells/surmount_affliction.json +++ b/data/spells/surmount_affliction.json @@ -5,6 +5,7 @@ "range": "personal", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "You temporarily overcome one harmful condition on yourself (blinded, confused, dazed, dazzled, deafened, fatigued, frightened, paralyzed, shaken, or sickened) for 1 round/level — the condition's effect is suspended, not ended. No combat effect encoded: the engine has no condition-suspension mechanic." } diff --git a/data/spells/tears_to_wine.json b/data/spells/tears_to_wine.json index ab26ecb..3bd7816 100644 --- a/data/spells/tears_to_wine.json +++ b/data/spells/tears_to_wine.json @@ -5,6 +5,7 @@ "range": "close", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "You transmute up to 1 cubic foot of nonmagical liquid per two caster levels (including spoiled, poisoned, or contaminated drink, tears, seawater) into mead or wine of average quality for 10 min./level (RAW range 10 ft., approximated as close). Will negates (object). No combat effect: liquid transmutation is not modeled by the engine." } diff --git a/data/spells/touch_of_fatigue.json b/data/spells/touch_of_fatigue.json index fde2650..e27fd5b 100644 --- a/data/spells/touch_of_fatigue.json +++ b/data/spells/touch_of_fatigue.json @@ -5,6 +5,7 @@ "range": "touch", "save": "fort", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "condition", diff --git a/data/spells/unseen_servant.json b/data/spells/unseen_servant.json index b706b54..076571b 100644 --- a/data/spells/unseen_servant.json +++ b/data/spells/unseen_servant.json @@ -5,6 +5,7 @@ "range": "close", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "An invisible, mindless, shapeless force performs simple tasks at your command for 1 hour/level: fetching, opening unstuck doors, holding chairs, cleaning or mending (effective Strength 2, speed 15 ft., no attacks, DC 10 skill limit). No combat effect: object manipulation by invisible servants is not modeled by the engine." } diff --git a/data/spells/vanish.json b/data/spells/vanish.json index 6ce37ad..9c89869 100644 --- a/data/spells/vanish.json +++ b/data/spells/vanish.json @@ -5,6 +5,7 @@ "range": "touch", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "condition", diff --git a/data/spells/virtue.json b/data/spells/virtue.json index 6884604..95bcb38 100644 --- a/data/spells/virtue.json +++ b/data/spells/virtue.json @@ -5,6 +5,7 @@ "range": "touch", "save": "none", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "A cantrip: with a touch you infuse a creature with a tiny surge of life, granting it 1 temporary hit point for 1 minute. Spell resistance yes (harmless). Simplified: the engine has no temporary hit points and no self-buff encoding that preserves the pinned default-policy casting order, so no mechanical effect is applied." } diff --git a/data/spells/weapon_of_awe.json b/data/spells/weapon_of_awe.json index 6696065..d870e09 100644 --- a/data/spells/weapon_of_awe.json +++ b/data/spells/weapon_of_awe.json @@ -5,6 +5,7 @@ "range": "touch", "save": "will", "base_dc": 10, + "cast_time": "standard", "effects": [], "description": "The touched weapon becomes an awe-inspiring instrument for 1 min./level: it gains a +2 sacred bonus on damage rolls, and a creature struck by a critical hit from it becomes shaken for 1 round (a mind-affecting fear effect). Will negates (harmless, object). Simplified: the engine has no weapon-targeted buff track and no self-buff encoding that preserves the pinned default-policy casting order, so no mechanical effect is applied." } diff --git a/data/spells/web.json b/data/spells/web.json index 3d80f16..54059b2 100644 --- a/data/spells/web.json +++ b/data/spells/web.json @@ -5,6 +5,7 @@ "range": "medium", "save": "ref", "base_dc": 10, + "cast_time": "standard", "effects": [ { "type": "area", diff --git a/src/pf1e_simulator/combat.py b/src/pf1e_simulator/combat.py index 68a42cd..f65cb92 100644 --- a/src/pf1e_simulator/combat.py +++ b/src/pf1e_simulator/combat.py @@ -789,7 +789,7 @@ class Action: # drops from the policy sequence (second standard, second move when no # standard is left to convert, second swift, full-round conflicting with # standard+move). The cast-time package adds downgraded:cast_time for -# cast_spell actions whose spell has a long casting time (1+ minutes): the +# cast_spell actions whose spell has a long casting time (more than 1 round): the # engine cannot schedule them within a turn, so they are dropped before the # budget filter runs. ACTION_RESULT_REASONS: frozenset[str] = frozenset({ @@ -1468,7 +1468,7 @@ class CombatEngine: """Downgrade the policy's action sequence to the legal action economy. Composition order: a cast-time pre-pass first drops every cast_spell - whose spell has a long casting time (1+ minutes — the engine cannot + whose spell has a long casting time (more than 1 round — the engine cannot schedule it within a turn; reported as downgraded:cast_time). Then the general per-turn budget (CRB, "Actions in Combat": one standard + one move, or one full-round, plus one swift; a move action may be @@ -5795,7 +5795,7 @@ def _has_slot(engine: CombatEngine, caster: CombatantState, spell_name: str) -> def _is_castable_this_turn(engine: CombatEngine, spell_name: str) -> bool: - """False only for long casting times (1+ minutes): the budget filter + """False only for long casting times (more than 1 round): the budget filter would drop the cast, so the policy must never propose it.""" spell = engine.spell_registry.get(spell_name) return spell is None or spell.cast_time != "long" @@ -5874,7 +5874,8 @@ def _cast_time_slot(cast_time: CastTime) -> _ActionEconomySlot: free-action cast is free. one_round is CLAMPED to the full-round slot: the engine resolves it within the current turn instead of tracking a pending cast across turns (documented approximation). A long casting - time (1+ minutes) cannot be scheduled by the turn budget at all — the + time (more than 1 round: 3 rounds, 10 minutes, 1 hour, ...) cannot be + scheduled by the turn budget at all — the engine drops such casts before the filter runs, so reaching this function with "long" is a programming error. """ diff --git a/src/pf1e_simulator/spells.py b/src/pf1e_simulator/spells.py index 493cac0..89375f1 100644 --- a/src/pf1e_simulator/spells.py +++ b/src/pf1e_simulator/spells.py @@ -198,6 +198,7 @@ _CAST_TIME_ALIASES: dict[str, CastTime] = { "full-round action": "full_round", "full-round": "full_round", "1 minute": "long", + "3 rounds": "long", "10 minutes": "long", "1 hour": "long", "standard action": "standard", diff --git a/tests/test_spells.py b/tests/test_spells.py index 457a0c4..33cfc1f 100644 --- a/tests/test_spells.py +++ b/tests/test_spells.py @@ -212,6 +212,7 @@ class TestSpellCastTime: cases = { "1 round": "one_round", "1 minute": "long", + "3 rounds": "long", "full-round": "full_round", "swift action": "swift", } @@ -227,6 +228,30 @@ class TestSpellCastTime: with pytest.raises(ValueError, match="unknown cast time"): self._load(tmp_path, "2 hours") + def test_imported_spells_declare_their_cast_time(self) -> None: + """Given: the imported spell data + When: the registry is loaded + Then: exactly the KB-verified spells carry a non-standard cast_time.""" + expected = { + "Enhance Water": "one_round", + "Silence": "one_round", + "Sleep": "one_round", + "Summon Instrument": "one_round", + "Summon Monster I": "one_round", + "Summon Monster II": "one_round", + "Grasp": "immediate", + "Saving Finale": "immediate", + "Make Whole": "long", + "Masterwork Transformation": "long", + "Mending": "long", + "Restoration, Lesser": "long", + } + registry = load_spell_registry(_SPELLS_DIR) + non_standard = {n for n, s in registry.items() if s.cast_time != "standard"} + assert non_standard == set(expected) + for name, code in expected.items(): + assert registry[name].cast_time == code, name + class TestSpellRangeFt: """Given: a spell with a range category