use super::{get_player_item_or_fail, UResult, UserError, UserVerb, UserVerbRef, VerbContext}; use crate::{ models::item::LocationActionType, static_content::{ possession_type::{possession_data, DamageType}, species::species_info_map, }, }; use ansi::ansi; use async_trait::async_trait; use std::collections::BTreeMap; pub struct Verb; #[async_trait] impl UserVerb for Verb { async fn handle( self: &Self, ctx: &mut VerbContext, _verb: &str, _remaining: &str, ) -> UResult<()> { let player_item = get_player_item_or_fail(ctx).await?; let all_gear = ctx .trans .find_by_action_and_location(&player_item.refstr(), &LocationActionType::Worn) .await?; let mut msg = String::new(); msg.push_str(&format!( ansi!( "| {:6} | {:25} | {:5} | {:5} | {:5} | {:5} | {:5} |\n" ), "Part", "Clothing", "Beat", "Slash", "Prce", "Shock", "Bullt" )); for body_part in &species_info_map() .get(&player_item.species) .ok_or_else(|| UserError("Species not found".to_owned()))? .body_parts { let mut damage_ranges: BTreeMap = BTreeMap::new(); for damtyp in [ DamageType::Beat, DamageType::Slash, DamageType::Pierce, DamageType::Shock, DamageType::Bullet, ] { damage_ranges.insert(damtyp, (0.0, 0.0)); } let mut worn: String = String::new(); for item in &all_gear { if let Some(wear_data) = item .possession_type .as_ref() .and_then(|pt| possession_data().get(pt)) .and_then(|pd| pd.wear_data.as_ref()) { if wear_data.covers_parts.contains(&body_part) { if !worn.is_empty() { worn.push_str(", "); } worn.push_str(if ctx.session_dat.less_explicit_mode { item.display_less_explicit .as_ref() .map(|s| s.as_str()) .unwrap_or(&item.display) } else { &item.display }); for entry in damage_ranges.iter_mut() { if let Some(soak_data) = wear_data.soaks.get(entry.0) { let (old_min, old_max) = entry.1; *entry.1 = (*old_min + soak_data.min_soak, *old_max + soak_data.max_soak); } } } } } worn.truncate(25); msg.push_str(&format!( ansi!("| {:6} | {:25} | {:2}-{:2} | {:2}-{:2} | {:2}-{:2} | {:2}-{:2} | {:2}-{:2} |\n"), body_part.display(player_item.sex.clone()), &worn, damage_ranges.get(&DamageType::Beat).map(|dt| dt.0).unwrap_or(0.0), damage_ranges.get(&DamageType::Beat).map(|dt| dt.1).unwrap_or(0.0), damage_ranges.get(&DamageType::Slash).map(|dt| dt.0).unwrap_or(0.0), damage_ranges.get(&DamageType::Slash).map(|dt| dt.1).unwrap_or(0.0), damage_ranges.get(&DamageType::Pierce).map(|dt| dt.0).unwrap_or(0.0), damage_ranges.get(&DamageType::Pierce).map(|dt| dt.1).unwrap_or(0.0), damage_ranges.get(&DamageType::Shock).map(|dt| dt.0).unwrap_or(0.0), damage_ranges.get(&DamageType::Shock).map(|dt| dt.1).unwrap_or(0.0), damage_ranges.get(&DamageType::Bullet).map(|dt| dt.0).unwrap_or(0.0), damage_ranges.get(&DamageType::Bullet).map(|dt| dt.1).unwrap_or(0.0), )); } let mut total_dodge: f64 = 0.0; for item in &all_gear { if let Some(wear_data) = item .possession_type .as_ref() .and_then(|pt| possession_data().get(pt)) .and_then(|pd| pd.wear_data.as_ref()) { total_dodge += wear_data.dodge_penalty; } } msg.push_str(&format!( "Total dodge penalty from armour: {}\n", total_dodge )); ctx.trans.queue_for_session(ctx.session, Some(&msg)).await?; Ok(()) } } static VERB_INT: Verb = Verb; pub static VERB: UserVerbRef = &VERB_INT as UserVerbRef;