blastmud/blastmud_game/src/message_handler/user_commands/buy.rs

179 lines
8.2 KiB
Rust

use super::{
get_player_item_or_fail, parsing::parse_offset, user_error, UResult, UserVerb, UserVerbRef,
VerbContext,
};
use crate::{
models::item::Item,
services::{
capacity::{check_item_capacity, check_item_ref_capacity, CapacityLevel},
urges::change_stress_considering_cool,
},
static_content::possession_type::possession_data,
static_content::room,
};
use ansi::ansi;
use async_trait::async_trait;
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(
"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(user) = ctx.user_dat.as_mut() {
let mut paid_price = stock.list_price;
if user.credits < stock.list_price {
if stock.poverty_discount {
if let Some(urges) = player_item.urges.as_ref() {
if urges.stress.value > 500 {
user_error(ansi!("You don't have the money to pay full price, \
and are too tired to try begging for a \
discount. [Hint: Try to <bold>recline<reset> \
for a bit and try again]").to_owned())?;
}
let mut player_item_mut = (*player_item).clone();
change_stress_considering_cool(
&ctx.trans,
&mut player_item_mut,
2000,
)
.await?;
ctx.trans.save_item_model(&player_item_mut).await?;
}
paid_price = user.credits;
user.credits = 0;
} else {
user_error(
"You don't have enough credits to buy that!".to_owned(),
)?;
}
} else {
user.credits -= stock.list_price;
}
let player_item_str = player_item.refstr();
let item_code = ctx.trans.alloc_item_code().await?;
let loc = match check_item_capacity(
ctx.trans,
&player_item,
possession_type.weight,
)
.await?
{
CapacityLevel::OverBurdened | CapacityLevel::AboveItemLimit => {
match check_item_ref_capacity(
ctx.trans,
&player_item.location,
possession_type.weight,
)
.await?
{
CapacityLevel::AboveItemLimit => user_error(
"You can't carry it, and there is too much stuff \
here already"
.to_owned(),
)?,
_ => {
ctx.trans.queue_for_session(
&ctx.session,
Some(
"It's too much for you to carry so you leave it on the ground.\n")
).await?;
&player_item.location
}
}
}
_ => &player_item_str,
};
let new_item = Item {
item_code: format!("{}", item_code),
location: loc.to_owned(),
..stock.possession_type.clone().into()
};
ctx.trans.create_item(&new_item).await?;
if let Some(container_data) = possession_type.container_data.as_ref() {
for sub_possession_type in &container_data.default_contents {
let sub_item_code = ctx.trans.alloc_item_code().await?;
let new_sub_item = Item {
item_code: format!("{}", sub_item_code),
location: new_item.refstr(),
..sub_possession_type.clone().into()
};
ctx.trans.create_item(&new_sub_item).await?;
}
}
ctx.trans
.queue_for_session(
&ctx.session,
Some(&format!(
"Your wristpad beeps for a deduction of {} credits.\n",
paid_price
)),
)
.await?;
}
return Ok(());
} else {
offset_remaining -= 1;
}
}
}
}
user_error(ansi!("That doesn't seem to be for sale. Try <bold>list<reset>").to_owned())
}
}
static VERB_INT: Verb = Verb;
pub static VERB: UserVerbRef = &VERB_INT as UserVerbRef;