blastmud/blastmud_game/src/message_handler/user_commands/sell.rs
Condorra 19cef2d9c4 Allow selling in stores, with Josephine special behaviour
Also added a staff invincible mode to help clean out NPCs with wrong
inventory.
2024-02-26 22:35:55 +11:00

136 lines
4.2 KiB
Rust

use super::{
get_player_item_or_fail, search_item_for_user, user_error, UResult, UserVerb, UserVerbRef,
VerbContext,
};
use crate::{
db::ItemSearchParams,
language::pluralise,
models::item::Item,
services::combat::max_health,
static_content::{
possession_type::possession_data,
room::{self, Room},
},
};
use async_trait::async_trait;
async fn check_sell_trigger(
ctx: &mut VerbContext<'_>,
player_item: &Item,
room: &Room,
sell_item: &Item,
) -> UResult<()> {
let trigger = match room.sell_trigger.as_ref() {
None => return Ok(()),
Some(tr) => tr,
};
trigger.handle_sell(ctx, room, player_item, sell_item).await
}
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 sell... 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 sell 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 sell anything because you're not in a shop.".to_owned())?
}
let sell_item = search_item_for_user(
ctx,
&ItemSearchParams {
include_contents: true,
item_type_only: Some("possession"),
..ItemSearchParams::base(&player_item, remaining)
},
)
.await?;
if let Some(charge_data) = sell_item
.possession_type
.as_ref()
.and_then(|pt| possession_data().get(pt))
.and_then(|pd| pd.charge_data.as_ref())
{
if charge_data.max_charges > sell_item.charges {
user_error(format!(
"No one will want to buy a used {}!",
&sell_item.display
))?
}
}
if sell_item.health < max_health(&sell_item) {
user_error(format!(
"No one will want to buy a damaged {}!",
&sell_item.display
))?
}
for stock in &room.stock_list {
if Some(stock.possession_type.clone()) != sell_item.possession_type {
continue;
}
let stats = ctx.trans.get_location_stats(&sell_item.refstr()).await?;
if stats.total_count > 0 {
user_error("Shouldn't you empty it first?".to_owned())?;
}
let sell_discount = match stock.can_sell {
None => continue,
Some(d) => d,
};
if let Some(user) = ctx.user_dat.as_mut() {
let sell_price =
((stock.list_price as f64) * (sell_discount as f64 / 10000.0)) as u64;
user.credits += stock.list_price;
ctx.trans
.delete_item(&sell_item.item_type, &sell_item.item_code)
.await?;
ctx.trans
.queue_for_session(
&ctx.session,
Some(&format!(
"Your wristpad beeps for a credit of {} credits.\n",
sell_price
)),
)
.await?;
check_sell_trigger(ctx, &player_item, &room, &sell_item).await?;
return Ok(());
}
}
user_error(format!(
"Sorry, this store doesn't buy {}!",
pluralise(&sell_item.display)
))?
}
}
static VERB_INT: Verb = Verb;
pub static VERB: UserVerbRef = &VERB_INT as UserVerbRef;