td

poison.rs at [1c4f2f89eb]
Login

poison.rs at [1c4f2f89eb]

File src/weapons/poison.rs artifact a4a8c81e09 part of check-in 1c4f2f89eb


//! PoisonCoating — an on-hit weapon mod that applies a poison DoT. Doesn't deal instant
//! damage itself (that's `Impact`'s job); it just pushes a status onto `HitContext.status`
//! the same way `Impact` pushes onto `HitContext.damage` — same event, same accumulate-then-
//! finalize shape, just a different accumulator.
//!
//! Deliberately builds `PeriodDamage` directly instead of going through `StatusRegistry` at
//! hit-time: `PoisonCoating` already knows exactly what it wants, the same way
//! `TowerBaseWeapon` never calls back into `DamageRegistry` from `on_hit_enemy` either. The
//! registry is for generic/data-driven construction (UI, "apply a random status" behaviors);
//! a hardcoded weapon mod that always applies the same status doesn't need that indirection.

use crate::{
    behavior::{
        projectile::{BehaviorPriority, HitResponse, ProjectileBehavior},
        status::PeriodDamage,
    },
    context::HitContext,
    enemy::Enemy,
    registry::DamageID,
    world::Projectile,
};

#[derive(Clone)]
pub struct PoisonCoating {
    damage_type: DamageID,
    amount: f32,
    interval: f32,
    duration: f32,
}

impl PoisonCoating {
    /// The registry supplies `damage_type` (resolved once from the live `DamageRegistry`,
    /// see `WeaponRegistry::new`) — same pattern as `TowerBaseWeapon::create`.
    pub fn create(tier: u32, damage_type: DamageID) -> Box<dyn ProjectileBehavior> {
        Box::new(Self {
            damage_type,
            amount: 3.0 + (1.5 * tier as f32),
            interval: 1.0,
            duration: 5.0,
        })
    }
}

impl ProjectileBehavior for PoisonCoating {
    fn priority(&self) -> i32 {
        BehaviorPriority::DEFAULT
    }
    fn on_hit_enemy(
        &mut self,
        p: &mut Projectile,
        _e: &mut Enemy,
        c: &mut HitContext,
    ) -> HitResponse {
        c.status.push(PeriodDamage::make(
            self.damage_type,
            self.amount,
            self.interval,
            self.duration,
            p.source,
        ));
        HitResponse::PASS
    }
}