diff --git a/server/src/storyteller/mod.rs b/server/src/storyteller/mod.rs index dd997ed5a..4b980210f 100644 --- a/server/src/storyteller/mod.rs +++ b/server/src/storyteller/mod.rs @@ -7,8 +7,8 @@ //! //! ## Contamination (#254) //! -//! After `CONTAMINATION_DELAY_TICKS` (default 1800 = 30 game-minutes at -//! 10 tps), the storyteller: +//! After `CONTAMINATION_DELAY_TICKS` (default 300 = 30 game-minutes at +//! 10 ticks/game-minute per D-031), the storyteller: //! 1. Sets `ContaminationActive` resource to true (one-shot) //! 2. Applies a tension delta to all `ActiveFork` triangles //! 3. Emits a `ContaminationEvent` for downstream systems (monologue, etc.) @@ -18,14 +18,14 @@ use bevy_ecs::prelude::*; use crate::content::template::{TriangleClassification, TriangleState}; use crate::simulation::tier::ActiveSim; -use crate::simulation::time::SimulationTime; +use crate::simulation::time::{SimulationTime, TICKS_PER_GAME_MINUTE}; // --------------------------------------------------------------------------- // Constants // --------------------------------------------------------------------------- -/// Tick at which contamination activates (30 game-minutes × 10 tps × 60s = 1800). -pub const CONTAMINATION_DELAY_TICKS: u64 = 1800; +/// Tick at which contamination activates (30 game-minutes × 10 ticks/minute = 300). +pub const CONTAMINATION_DELAY_TICKS: u64 = 30 * TICKS_PER_GAME_MINUTE; /// Tension delta applied to ActiveFork triangles when contamination fires. pub const CONTAMINATION_PRESSURE_DELTA: u8 = 10; @@ -41,7 +41,7 @@ pub const CONFRONTATION_THRESHOLD: u8 = 75; /// Whether contamination has been activated by the storyteller. /// /// Once set to `true`, it stays true for the remainder of the session. -/// Persisted via save state (future — currently session-scoped). +/// Persisted in `SaveStateV1` to prevent double-firing on save/load. #[derive(Resource, Debug, Clone, Default)] pub struct ContaminationActive(pub bool); diff --git a/server/tests/contamination.rs b/server/tests/contamination.rs index 4ff1b6649..07b82b4dc 100644 --- a/server/tests/contamination.rs +++ b/server/tests/contamination.rs @@ -42,10 +42,10 @@ fn make_triangle( } } -/// Acceptance test: run 1801 ticks, assert ContaminationActive is set and -/// all ActiveFork TriangleState entities have tension > 0. +/// Acceptance test: run past CONTAMINATION_DELAY_TICKS, assert ContaminationActive +/// is set and all ActiveFork TriangleState entities have tension > 0. #[test] -fn contamination_activates_after_1801_ticks() { +fn contamination_activates_after_delay() { let mut world = World::new(); world.init_resource::(); world.init_resource::(); @@ -102,8 +102,8 @@ fn contamination_activates_after_1801_ticks() { let mut schedule = Schedule::default(); schedule.add_systems(tick_contamination_activation); - // Simulate 1801 ticks - for tick in 0..=1800 { + // Simulate past the delay threshold (CONTAMINATION_DELAY_TICKS = 300) + for tick in 0..=CONTAMINATION_DELAY_TICKS { world.resource_mut::().tick = tick; schedule.run(&mut world); } @@ -111,7 +111,8 @@ fn contamination_activates_after_1801_ticks() { // Assert ContaminationActive is set assert!( world.resource::().0, - "ContaminationActive must be true after 1801 ticks" + "ContaminationActive must be true after CONTAMINATION_DELAY_TICKS ({}) ticks", + CONTAMINATION_DELAY_TICKS ); // Assert all ActiveFork triangles have tension > 0