Start work on shops.
This commit is contained in:
parent
2053c9cbb3
commit
722757468f
@ -15,6 +15,7 @@ mod describe;
|
||||
mod help;
|
||||
mod ignore;
|
||||
mod less_explicit_mode;
|
||||
mod list;
|
||||
mod login;
|
||||
mod look;
|
||||
mod map;
|
||||
@ -106,6 +107,8 @@ static REGISTERED_COMMANDS: UserVerbRegistry = phf_map! {
|
||||
"l" => look::VERB,
|
||||
"look" => look::VERB,
|
||||
"read" => look::VERB,
|
||||
|
||||
"list" => list::VERB,
|
||||
|
||||
"lmap" => map::VERB,
|
||||
|
||||
|
47
blastmud_game/src/message_handler/user_commands/list.rs
Normal file
47
blastmud_game/src/message_handler/user_commands/list.rs
Normal file
@ -0,0 +1,47 @@
|
||||
use super::{VerbContext, UserVerb, UserVerbRef, UResult, user_error,
|
||||
get_player_item_or_fail};
|
||||
use crate::{
|
||||
static_content::room,
|
||||
static_content::possession_type::possession_data,
|
||||
};
|
||||
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 offer you any prices... 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 list stock 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 list stock because you're not in a shop.".to_owned())?
|
||||
}
|
||||
|
||||
let mut msg = String::new();
|
||||
msg.push_str(&format!(ansi!("<bold><bgblue><white>| {:20} | {:15} |<reset>\n"),
|
||||
ansi!("Item"),
|
||||
ansi!("Price")));
|
||||
|
||||
for stock in &room.stock_list {
|
||||
if let Some(possession_type) = possession_data().get(&stock.possession_type) {
|
||||
msg.push_str(&format!("| {:20} | {:15.2} |\n", &possession_type.name, &stock.list_price))
|
||||
}
|
||||
}
|
||||
msg.push('\n');
|
||||
ctx.trans.queue_for_session(&ctx.session, Some(&msg)).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
static VERB_INT: Verb = Verb;
|
||||
pub static VERB: UserVerbRef = &VERB_INT as UserVerbRef;
|
@ -92,7 +92,8 @@ impl Default for NPC {
|
||||
aliases: vec!(),
|
||||
says: vec!(),
|
||||
total_xp: 1000,
|
||||
total_skills: SkillType::values().into_iter().map(|sk| (sk, 10.0)).collect(),
|
||||
total_skills: SkillType::values().into_iter()
|
||||
.map(|sk| (sk.clone(), if &sk == &SkillType::Dodge { 8.0 } else { 10.0 })).collect(),
|
||||
attackable: false,
|
||||
aggression: 0,
|
||||
intrinsic_weapon: None,
|
||||
@ -155,6 +156,7 @@ pub fn npc_static_items() -> Box<dyn Iterator<Item = StaticItem>> {
|
||||
is_static: true,
|
||||
pronouns: c.pronouns.clone(),
|
||||
is_challenge_attack_only: !c.attackable,
|
||||
total_xp: c.total_xp.clone(),
|
||||
total_skills: c.total_skills.clone(),
|
||||
species: c.species.clone(),
|
||||
aliases: c.aliases.iter().map(|a| (*a).to_owned()).collect::<Vec<String>>(),
|
||||
|
@ -54,13 +54,23 @@ impl Default for WeaponData {
|
||||
}
|
||||
|
||||
pub struct PossessionData {
|
||||
pub weapon_data: Option<WeaponData>
|
||||
pub weapon_data: Option<WeaponData>,
|
||||
pub name: &'static str,
|
||||
pub name_nonexp: Option<&'static str>,
|
||||
#[allow(unused)]
|
||||
pub display: &'static str,
|
||||
#[allow(unused)]
|
||||
pub display_nonexp: Option<&'static str>,
|
||||
}
|
||||
|
||||
impl Default for PossessionData {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
weapon_data: None
|
||||
weapon_data: None,
|
||||
name: "Thingy",
|
||||
name_nonexp: None,
|
||||
display: "A generic looking thing",
|
||||
display_nonexp: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -93,6 +103,7 @@ pub enum PossessionType {
|
||||
// Special values that substitute for possessions.
|
||||
Fangs, // Default weapon for certain animals
|
||||
// Real possessions from here on:
|
||||
AntennaWhip,
|
||||
}
|
||||
|
||||
pub fn fist() -> &'static WeaponData {
|
||||
@ -156,6 +167,38 @@ pub fn possession_data() -> &'static BTreeMap<PossessionType, PossessionData> {
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
}),
|
||||
(AntennaWhip, PossessionData {
|
||||
name: "Antenna whip",
|
||||
display: "A crudely fashioned whip made from a broken metal antenna. It looks a bit flimsy, but it \
|
||||
might do you until you get a better weapon!",
|
||||
weapon_data: Some(WeaponData {
|
||||
uses_skill: SkillType::Whips,
|
||||
raw_min_to_learn: 0.0,
|
||||
raw_max_to_learn: 2.0,
|
||||
normal_attack_start_messages: vec!(
|
||||
Box::new(|attacker, victim, exp|
|
||||
format!("{} lines up {} antenna whip for a strike on {}",
|
||||
&attacker.display_for_sentence(exp, 1, true),
|
||||
&attacker.pronouns.possessive,
|
||||
&victim.display_for_sentence(exp, 1, false),
|
||||
)
|
||||
)
|
||||
),
|
||||
normal_attack_success_messages: vec!(
|
||||
Box::new(|attacker, victim, part, exp|
|
||||
format!("{}'s antenna whip scores a painful red line across {}'s {}",
|
||||
&attacker.display_for_sentence(exp, 1, true),
|
||||
&victim.display_for_sentence(exp, 1, false),
|
||||
&part.display(victim.sex.clone())
|
||||
)
|
||||
)
|
||||
),
|
||||
normal_attack_mean_damage: 3.0,
|
||||
normal_attack_stdev_damage: 3.0,
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
})
|
||||
).into_iter().collect()
|
||||
})
|
||||
|
@ -1,4 +1,7 @@
|
||||
use super::StaticItem;
|
||||
use super::{
|
||||
StaticItem,
|
||||
possession_type::PossessionType,
|
||||
};
|
||||
use once_cell::sync::OnceCell;
|
||||
use std::collections::BTreeMap;
|
||||
use async_trait::async_trait;
|
||||
@ -6,7 +9,9 @@ use serde::{Serialize, Deserialize};
|
||||
use crate::message_handler::user_commands::{
|
||||
UResult, VerbContext
|
||||
};
|
||||
use crate::models::item::{Item, ItemFlag};
|
||||
use crate::{
|
||||
models::item::{Item, ItemFlag}
|
||||
};
|
||||
|
||||
mod repro_xv;
|
||||
mod melbs;
|
||||
@ -145,6 +150,20 @@ pub struct SecondaryZoneRecord {
|
||||
pub caption: Option<&'static str>
|
||||
}
|
||||
|
||||
pub struct RoomStock {
|
||||
pub possession_type: PossessionType,
|
||||
pub list_price: f64
|
||||
}
|
||||
|
||||
impl Default for RoomStock {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
possession_type: PossessionType::AntennaWhip,
|
||||
list_price: 1000000000.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Room {
|
||||
pub zone: &'static str,
|
||||
// Other zones where it can be seen on the map and accessed.
|
||||
@ -158,7 +177,9 @@ pub struct Room {
|
||||
pub exits: Vec<Exit>,
|
||||
pub should_caption: bool,
|
||||
pub repel_npc: bool,
|
||||
pub item_flags: Vec<ItemFlag>
|
||||
pub item_flags: Vec<ItemFlag>,
|
||||
// Empty means not a shop.
|
||||
pub stock_list: Vec<RoomStock>,
|
||||
}
|
||||
|
||||
impl Default for Room {
|
||||
@ -176,6 +197,7 @@ impl Default for Room {
|
||||
should_caption: true,
|
||||
repel_npc: false,
|
||||
item_flags: vec!(),
|
||||
stock_list: vec!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,11 @@
|
||||
use super::{
|
||||
Room, GridCoords, Exit, Direction, ExitTarget, ExitType,
|
||||
Room, RoomStock, GridCoords, Exit, Direction, ExitTarget, ExitType,
|
||||
SecondaryZoneRecord
|
||||
};
|
||||
use crate::models::item::ItemFlag;
|
||||
use crate::{
|
||||
models::item::ItemFlag,
|
||||
static_content::possession_type::PossessionType
|
||||
};
|
||||
use ansi::ansi;
|
||||
|
||||
pub fn room_list() -> Vec<Room> {
|
||||
@ -1707,10 +1710,41 @@ pub fn room_list() -> Vec<Room> {
|
||||
target: ExitTarget::UseGPS,
|
||||
exit_type: ExitType::Free
|
||||
},
|
||||
Exit {
|
||||
direction: Direction::SOUTH,
|
||||
target: ExitTarget::UseGPS,
|
||||
exit_type: ExitType::Free
|
||||
},
|
||||
),
|
||||
should_caption: false,
|
||||
..Default::default()
|
||||
},
|
||||
Room {
|
||||
zone: "melbs",
|
||||
secondary_zones: vec!(),
|
||||
code: "melbs_mckillocks_self_defence",
|
||||
name: "McKillock's Self Defence",
|
||||
short: ansi!("<red>MS<reset>"),
|
||||
description: ansi!("A neatly painted shop with bars covering the window, and a mean looking shop-keeper sitting behind a desk. [Use <bold>list<reset> to see stock for sale here]"),
|
||||
description_less_explicit: None,
|
||||
grid_coords: GridCoords { x: 3, y: 0, z: 0 },
|
||||
exits: vec!(
|
||||
Exit {
|
||||
direction: Direction::NORTH,
|
||||
target: ExitTarget::UseGPS,
|
||||
exit_type: ExitType::Free
|
||||
},
|
||||
),
|
||||
should_caption: true,
|
||||
stock_list: vec!(
|
||||
RoomStock {
|
||||
possession_type: PossessionType::AntennaWhip,
|
||||
list_price: 100.0,
|
||||
..Default::default()
|
||||
}
|
||||
),
|
||||
..Default::default()
|
||||
},
|
||||
Room {
|
||||
zone: "melbs",
|
||||
secondary_zones: vec!(),
|
||||
|
Loading…
Reference in New Issue
Block a user