flatland-presentation 0.2.22

Gfx sprite mode resolution — maps game states to sprite sheet mode ids
Documentation
//! Canonical player presentation keys for gfx `sprite_modes` (designer-facing).

/// Standard presentation keys shown in content-admin and used on the wire.
pub const PLAYER_PRESENTATION_STATES: &[(&str, &str)] = &[
    ("combat", "Combat — in melee range or casting"),
    ("pursue", "Pursue — has target, out of attack range"),
    ("sprinting", "Sprinting — fast movement"),
    ("walking", "Walking — normal movement"),
    ("harvesting", "Harvesting — gathering a resource node"),
    ("crafting", "Crafting — timed blueprint craft"),
    ("talking", "Talking — open NPC conversation"),
    ("chatting", "Chatting — recent nearby / whisper-stone chat"),
    ("idle", "Idle — stationary"),
];

/// Inputs for player presentation (keeps this crate free of sim types).
#[derive(Debug, Clone, Copy)]
pub struct PlayerPresentationInput {
    pub harvesting: bool,
    pub crafting: bool,
    pub talking: bool,
    pub chatting: bool,
    pub in_combat: bool,
    pub pursue: bool,
    pub in_attack_range: bool,
    pub is_moving: bool,
    pub sprinting: bool,
}

pub fn resolve_player_presentation_key(input: PlayerPresentationInput) -> &'static str {
    if input.harvesting {
        return "harvesting";
    }
    if input.crafting {
        return "crafting";
    }
    if input.talking {
        return "talking";
    }
    if input.chatting {
        return "chatting";
    }
    if input.in_combat && input.in_attack_range {
        return "combat";
    }
    if input.pursue || (input.in_combat && !input.in_attack_range) {
        return "pursue";
    }
    if input.in_combat {
        return "combat";
    }
    if input.is_moving && input.sprinting {
        return "sprinting";
    }
    if input.is_moving {
        return "walking";
    }
    "idle"
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn player_harvesting_wins() {
        let key = resolve_player_presentation_key(PlayerPresentationInput {
            harvesting: true,
            crafting: false,
            talking: false,
            chatting: false,
            in_combat: true,
            pursue: false,
            in_attack_range: true,
            is_moving: true,
            sprinting: true,
        });
        assert_eq!(key, "harvesting");
    }

    #[test]
    fn player_talking_over_walking() {
        let key = resolve_player_presentation_key(PlayerPresentationInput {
            harvesting: false,
            crafting: false,
            talking: true,
            chatting: false,
            in_combat: false,
            pursue: false,
            in_attack_range: false,
            is_moving: true,
            sprinting: false,
        });
        assert_eq!(key, "talking");
    }

    #[test]
    fn player_pursue_out_of_range() {
        let key = resolve_player_presentation_key(PlayerPresentationInput {
            harvesting: false,
            crafting: false,
            talking: false,
            chatting: false,
            in_combat: true,
            pursue: false,
            in_attack_range: false,
            is_moving: true,
            sprinting: true,
        });
        assert_eq!(key, "pursue");
    }
}