use super::{get_player_item_or_fail, UResult, UserError, UserVerb, UserVerbRef, VerbContext}; use crate::{ models::item::{Item, ItemSpecialData}, static_content::npc::npc_by_code, }; use ansi::ansi; use async_trait::async_trait; use std::sync::Arc; pub struct Verb; #[async_trait] impl UserVerb for Verb { async fn handle( self: &Self, ctx: &mut VerbContext, _verb: &str, remaining: &str, ) -> UResult<()> { let npc_name = remaining.trim().to_lowercase(); let player_item = get_player_item_or_fail(ctx).await?; let mut match_staff: Vec> = ctx .trans .find_staff_by_hirer(&player_item.item_code) .await? .into_iter() .filter(|it| { it.display.to_lowercase().starts_with(&npc_name) || it .display_less_explicit .as_ref() .map(|v| v.to_lowercase().starts_with(&npc_name)) .unwrap_or(false) || it .aliases .iter() .any(|al| al.to_lowercase().starts_with(&npc_name)) }) .collect(); match_staff.sort_by_key(|it| (it.display.len() as i64 - npc_name.len() as i64).abs()); let npc: Arc = match_staff.first().ok_or_else(|| UserError(ansi!("You don't have any matching employees. Try hire to list your staff.").to_owned()))?.clone(); let hire_dat = npc_by_code() .get(npc.item_code.as_str()) .as_ref() .and_then(|npci| npci.hire_data.as_ref()) .ok_or_else(|| { UserError( "Sorry, I've forgotten how to fire them! Ask the game staff for help." .to_owned(), ) })?; ctx.trans .queue_for_session( &ctx.session, Some(&format!( "A hushed silence falls over the room as you fire {}.\n", npc.display_for_session(&ctx.session_dat), )), ) .await?; let mut npc_mut = (*npc).clone(); hire_dat .handler .fire_handler(&ctx.trans, &player_item, &mut npc_mut) .await?; npc_mut.special_data = Some(ItemSpecialData::HireData { hired_by: None }); ctx.trans.save_item_model(&npc_mut).await?; ctx.trans.delete_task("ChargeWages", &npc.item_code).await?; Ok(()) } } static VERB_INT: Verb = Verb; pub static VERB: UserVerbRef = &VERB_INT as UserVerbRef;