use super::{ VerbContext, UserVerb, UserVerbRef, UResult, user_error, get_player_item_or_fail, parsing::parse_offset, }; use crate::{ static_content::room, static_content::possession_type::possession_data, models::item::Item, }; use async_trait::async_trait; use ansi::ansi; 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.is_dead { user_error("Nobody seems to listen when you try to buy... possibly because you're dead.".to_owned())? } let (heretype, herecode) = player_item.location.split_once("/").unwrap_or(("room", "repro_xv_chargen")); if heretype != "room" { user_error("Can't buy anything because you're not in a shop.".to_owned())?; } let room = match room::room_map_by_code().get(herecode) { None => user_error("Can't find that shop.".to_owned())?, Some(r) => r }; if room.stock_list.is_empty() { user_error("Can't buy anything because you're not in a shop.".to_owned())? } let (offset_m, remaining) = parse_offset(remaining); let mut offset_remaining = offset_m.unwrap_or(1); let match_item = remaining.trim().to_lowercase(); if match_item == "" { user_error("You need to specify what to buy.".to_owned())? } for stock in &room.stock_list { if let Some(possession_type) = possession_data().get(&stock.possession_type) { if possession_type.display.to_lowercase().starts_with(&match_item) || possession_type.display_less_explicit.map(|d| d.to_lowercase().starts_with(&match_item)).unwrap_or(false) || possession_type.aliases.iter().any(|al| al.starts_with(&match_item)) { if offset_remaining <= 1 { if let Some(mut user) = ctx.user_dat.as_mut() { if user.credits < stock.list_price { user_error("You don't have enough credits to buy that!".to_owned())?; } user.credits -= stock.list_price; let item_code = ctx.trans.alloc_item_code().await?; let new_item = Item { item_type: "possession".to_owned(), item_code: format!("{}", item_code), possession_type: Some(stock.possession_type.clone()), display: possession_type.display.to_owned(), display_less_explicit: possession_type.display_less_explicit.map(|d| d.to_owned()), details: Some(possession_type.details.to_owned()), details_less_explicit: possession_type.details_less_explicit.map(|d| d.to_owned()), aliases: possession_type.aliases.iter().map(|al| (*al).to_owned()).collect(), location: format!("player/{}", &player_item.item_code), health: possession_type.max_health, ..Default::default() }; ctx.trans.create_item(&new_item).await?; ctx.trans.queue_for_session( &ctx.session, Some(&format!("Your wristpad beeps for a deduction of {} credits.\n", stock.list_price)) ).await?; } return Ok(()); } else { offset_remaining -= 1; } } } } user_error(ansi!("That doesn't seem to be for sale. Try list").to_owned()) } } static VERB_INT: Verb = Verb; pub static VERB: UserVerbRef = &VERB_INT as UserVerbRef;