diff --git a/blastmud_game/src/message_handler/user_commands.rs b/blastmud_game/src/message_handler/user_commands.rs index 94fffcd2..74a3dcbc 100644 --- a/blastmud_game/src/message_handler/user_commands.rs +++ b/blastmud_game/src/message_handler/user_commands.rs @@ -14,6 +14,7 @@ use std::sync::Arc; mod agree; mod allow; pub mod attack; +mod butcher; mod buy; mod c; pub mod close; @@ -127,6 +128,7 @@ static REGISTERED_COMMANDS: UserVerbRegistry = phf_map! { "disallow" => allow::VERB, "attack" => attack::VERB, + "butcher" => butcher::VERB, "buy" => buy::VERB, "c" => c::VERB, "close" => close::VERB, diff --git a/blastmud_game/src/message_handler/user_commands/butcher.rs b/blastmud_game/src/message_handler/user_commands/butcher.rs new file mode 100644 index 00000000..6c685fb4 --- /dev/null +++ b/blastmud_game/src/message_handler/user_commands/butcher.rs @@ -0,0 +1,70 @@ +use super::{ + VerbContext, UserVerb, UserVerbRef, UResult, UserError, + get_player_item_or_fail, user_error, search_item_for_user, + cut::ensure_has_butcher_tool, +}; +use async_trait::async_trait; +use crate::{ + models::item::DeathData, + db::ItemSearchParams, + static_content::possession_type::{possession_data}, + services::{ + combat::corpsify_item, + }, + regular_tasks::queued_command::{ + QueueCommand, + queue_command + }, +}; +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 player_item = get_player_item_or_fail(ctx).await?; + + if player_item.death_data.is_some() { + user_error("You butcher things while they are dead, not while YOU are dead!".to_owned())? + } + + let possible_corpse = search_item_for_user(ctx, &ItemSearchParams { + include_loc_contents: true, + dead_first: true, + ..ItemSearchParams::base(&player_item, remaining.trim()) + }).await?; + + let possession_types = match possible_corpse.death_data.as_ref() { + None => user_error(format!("You can't do that while {} is still alive!", possible_corpse.pronouns.subject))?, + Some(DeathData { parts_remaining, ..}) => + parts_remaining + }.clone(); + + let corpse = if possible_corpse.item_type == "corpse" { + possible_corpse + } else if possible_corpse.item_type == "npc" || possible_corpse.item_type == "player" { + let mut possible_corpse_mut = (*possible_corpse).clone(); + possible_corpse_mut.location = if possible_corpse.item_type == "npc" { + "room/valhalla" + } else { + "room/repro_xv_respawn" + }.to_owned(); + Arc::new(corpsify_item(&ctx.trans, &possible_corpse).await?) + } else { + user_error("You can't butcher that!".to_owned())? + }; + + ensure_has_butcher_tool(&ctx.trans, &player_item).await?; + + for possession_type in possession_types { + let possession_data = possession_data().get(&possession_type) + .ok_or_else(|| UserError("That part doesn't exist anymore".to_owned()))?; + + queue_command(ctx, &QueueCommand::Cut { from_corpse: corpse.item_code.clone(), + what_part: possession_data.display.to_owned() }).await?; + } + Ok(()) + } +} +static VERB_INT: Verb = Verb; +pub static VERB: UserVerbRef = &VERB_INT as UserVerbRef; diff --git a/blastmud_game/src/static_content/possession_type/blade.rs b/blastmud_game/src/static_content/possession_type/blade.rs index 06f211f7..9238cf0c 100644 --- a/blastmud_game/src/static_content/possession_type/blade.rs +++ b/blastmud_game/src/static_content/possession_type/blade.rs @@ -35,5 +35,5 @@ pub fn butcher_data() -> PossessionData { ..Default::default() }), ..Default::default() - } + } }