Implement sit command.
This commit is contained in:
parent
57537d80bf
commit
3e4e448404
@ -61,6 +61,7 @@ mod reset_spawns;
|
|||||||
pub mod say;
|
pub mod say;
|
||||||
mod score;
|
mod score;
|
||||||
mod sign;
|
mod sign;
|
||||||
|
pub mod sit;
|
||||||
mod status;
|
mod status;
|
||||||
mod uninstall;
|
mod uninstall;
|
||||||
pub mod use_cmd;
|
pub mod use_cmd;
|
||||||
@ -219,6 +220,7 @@ static REGISTERED_COMMANDS: UserVerbRegistry = phf_map! {
|
|||||||
"score" => score::VERB,
|
"score" => score::VERB,
|
||||||
|
|
||||||
"sign" => sign::VERB,
|
"sign" => sign::VERB,
|
||||||
|
"sit" => sit::VERB,
|
||||||
|
|
||||||
"st" => status::VERB,
|
"st" => status::VERB,
|
||||||
"stat" => status::VERB,
|
"stat" => status::VERB,
|
||||||
|
@ -524,8 +524,30 @@ async fn list_room_contents<'l>(ctx: &'l VerbContext<'_>, item: &'l Item) -> URe
|
|||||||
" is "
|
" is "
|
||||||
});
|
});
|
||||||
match head.action_type {
|
match head.action_type {
|
||||||
LocationActionType::Sitting => buf.push_str("sitting "),
|
LocationActionType::Sitting(ref on) => {
|
||||||
LocationActionType::Reclining => buf.push_str("reclining "),
|
buf.push_str("sitting ");
|
||||||
|
if let Some((on_type, on_code)) =
|
||||||
|
on.as_ref().and_then(|on_ref| on_ref.split_once("/"))
|
||||||
|
{
|
||||||
|
if let Some(sit_on) = ctx.trans.find_item_by_type_code(on_type, on_code).await?
|
||||||
|
{
|
||||||
|
buf.push_str("on ");
|
||||||
|
buf.push_str(&sit_on.display_for_session(&ctx.session_dat));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LocationActionType::Reclining(ref on) => {
|
||||||
|
buf.push_str("reclining ");
|
||||||
|
if let Some((on_type, on_code)) =
|
||||||
|
on.as_ref().and_then(|on_ref| on_ref.split_once("/"))
|
||||||
|
{
|
||||||
|
if let Some(sit_on) = ctx.trans.find_item_by_type_code(on_type, on_code).await?
|
||||||
|
{
|
||||||
|
buf.push_str("on ");
|
||||||
|
buf.push_str(&sit_on.display_for_session(&ctx.session_dat));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
LocationActionType::Normal | LocationActionType::Attacking(_) if is_creature => {
|
LocationActionType::Normal | LocationActionType::Attacking(_) if is_creature => {
|
||||||
if head.death_data.is_some() {
|
if head.death_data.is_some() {
|
||||||
buf.push_str("lying ");
|
buf.push_str("lying ");
|
||||||
|
213
blastmud_game/src/message_handler/user_commands/sit.rs
Normal file
213
blastmud_game/src/message_handler/user_commands/sit.rs
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
use super::{
|
||||||
|
get_player_item_or_fail, search_item_for_user, user_error, ItemSearchParams, UResult, UserVerb,
|
||||||
|
UserVerbRef, VerbContext,
|
||||||
|
};
|
||||||
|
use crate::{
|
||||||
|
models::item::LocationActionType,
|
||||||
|
regular_tasks::queued_command::{
|
||||||
|
queue_command_and_save, QueueCommand, QueueCommandHandler, QueuedCommandContext,
|
||||||
|
},
|
||||||
|
services::comms::broadcast_to_room,
|
||||||
|
};
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use std::time;
|
||||||
|
|
||||||
|
pub struct QueueHandler;
|
||||||
|
#[async_trait]
|
||||||
|
impl QueueCommandHandler for QueueHandler {
|
||||||
|
async fn start_command(&self, ctx: &mut QueuedCommandContext<'_>) -> UResult<time::Duration> {
|
||||||
|
if ctx.item.death_data.is_some() {
|
||||||
|
user_error("You try to sit, but it turns out the dead can't even do that!".to_owned())?;
|
||||||
|
}
|
||||||
|
let item_ref = match ctx.command {
|
||||||
|
QueueCommand::Sit { item } => item,
|
||||||
|
_ => user_error("Unexpected command".to_owned())?,
|
||||||
|
};
|
||||||
|
if ctx
|
||||||
|
.item
|
||||||
|
.active_combat
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|ac| ac.attacking.as_ref())
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
|
user_error(
|
||||||
|
"Sit... while fighting? You can't figure out how to make it work".to_owned(),
|
||||||
|
)?
|
||||||
|
}
|
||||||
|
if ctx.item.active_climb.is_some() {
|
||||||
|
user_error(
|
||||||
|
"Sit... while climbing? You can't figure out how to make it work".to_owned(),
|
||||||
|
)?
|
||||||
|
}
|
||||||
|
match ctx.item.action_type {
|
||||||
|
LocationActionType::Sitting { .. } => user_error("You're already sitting.".to_owned())?,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
match item_ref {
|
||||||
|
None => {}
|
||||||
|
Some(item_ref) => {
|
||||||
|
let (item_type, item_code) = match item_ref.split_once("/") {
|
||||||
|
None => user_error("Invalid item ref in Sit command".to_owned())?,
|
||||||
|
Some(v) => v,
|
||||||
|
};
|
||||||
|
match ctx
|
||||||
|
.trans
|
||||||
|
.find_item_by_type_code(&item_type, &item_code)
|
||||||
|
.await?
|
||||||
|
{
|
||||||
|
None => user_error("Item not found".to_owned())?,
|
||||||
|
Some(item) => {
|
||||||
|
if item.location != ctx.item.location {
|
||||||
|
user_error(format!(
|
||||||
|
"You try to sit on {} but realise it's no longer here",
|
||||||
|
item.display_for_sentence(ctx.explicit().await?, 1, false)
|
||||||
|
))?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ok(time::Duration::from_secs(1))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unreachable_patterns)]
|
||||||
|
async fn finish_command(&self, ctx: &mut QueuedCommandContext<'_>) -> UResult<()> {
|
||||||
|
if ctx.item.death_data.is_some() {
|
||||||
|
user_error("You try to sit, but it turns out the dead can't even do that!".to_owned())?;
|
||||||
|
}
|
||||||
|
let item_ref = match ctx.command {
|
||||||
|
QueueCommand::Sit { item } => item,
|
||||||
|
_ => user_error("Unexpected command".to_owned())?,
|
||||||
|
};
|
||||||
|
if ctx
|
||||||
|
.item
|
||||||
|
.active_combat
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|ac| ac.attacking.as_ref())
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
|
user_error(
|
||||||
|
"Sit... while fighting? You can't figure out how to make it work".to_owned(),
|
||||||
|
)?
|
||||||
|
}
|
||||||
|
if ctx.item.active_climb.is_some() {
|
||||||
|
user_error(
|
||||||
|
"Sit... while climbing? You can't figure out how to make it work".to_owned(),
|
||||||
|
)?
|
||||||
|
}
|
||||||
|
match ctx.item.action_type {
|
||||||
|
LocationActionType::Sitting { .. } => user_error("You're already sitting.".to_owned())?,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
let (item, desc_exp, desc_nonexp) = match item_ref {
|
||||||
|
None => (None, "the floor".to_owned(), "the floor".to_owned()),
|
||||||
|
Some(item_ref) => {
|
||||||
|
let (item_type, item_code) = match item_ref.split_once("/") {
|
||||||
|
None => user_error("Invalid item ref in Sit command".to_owned())?,
|
||||||
|
Some(v) => v,
|
||||||
|
};
|
||||||
|
match ctx
|
||||||
|
.trans
|
||||||
|
.find_item_by_type_code(&item_type, &item_code)
|
||||||
|
.await?
|
||||||
|
{
|
||||||
|
None => user_error("Item not found".to_owned())?,
|
||||||
|
Some(item) => {
|
||||||
|
if item.location != ctx.item.location {
|
||||||
|
user_error(format!(
|
||||||
|
"You try to sit on {} but realise it's no longer here",
|
||||||
|
item.display_for_sentence(ctx.explicit().await?, 1, false)
|
||||||
|
))?
|
||||||
|
}
|
||||||
|
(
|
||||||
|
Some(item.clone()),
|
||||||
|
item.display_for_sentence(true, 1, false),
|
||||||
|
item.display_for_sentence(false, 1, false),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let msg_exp = format!(
|
||||||
|
"{} sits on {}.\n",
|
||||||
|
&ctx.item.display_for_sentence(true, 1, true),
|
||||||
|
&desc_exp
|
||||||
|
);
|
||||||
|
let msg_nonexp = format!(
|
||||||
|
"{} sits on {}.\n",
|
||||||
|
&ctx.item.display_for_sentence(false, 1, true),
|
||||||
|
&desc_nonexp
|
||||||
|
);
|
||||||
|
broadcast_to_room(
|
||||||
|
ctx.trans,
|
||||||
|
&ctx.item.location,
|
||||||
|
None,
|
||||||
|
&msg_exp,
|
||||||
|
Some(&msg_nonexp),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
ctx.item.action_type = LocationActionType::Sitting(item.map(|it| it.refstr()));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Verb;
|
||||||
|
#[async_trait]
|
||||||
|
impl UserVerb for Verb {
|
||||||
|
async fn handle(
|
||||||
|
self: &Self,
|
||||||
|
ctx: &mut VerbContext,
|
||||||
|
_verb: &str,
|
||||||
|
mut remaining: &str,
|
||||||
|
) -> UResult<()> {
|
||||||
|
let player_item = get_player_item_or_fail(ctx).await?;
|
||||||
|
|
||||||
|
if remaining.starts_with("on ") {
|
||||||
|
remaining = remaining[3..].trim();
|
||||||
|
}
|
||||||
|
if remaining == "" {
|
||||||
|
remaining = "floor";
|
||||||
|
}
|
||||||
|
|
||||||
|
let target = if remaining == "here" || remaining == "ground" || remaining == "floor" {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(
|
||||||
|
search_item_for_user(
|
||||||
|
ctx,
|
||||||
|
&ItemSearchParams {
|
||||||
|
include_loc_contents: true,
|
||||||
|
..ItemSearchParams::base(&player_item, &remaining)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await?,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
if player_item.death_data.is_some() {
|
||||||
|
user_error("You try to sit, but it turns out the dead can't even do that!".to_owned())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(target) = target.as_ref() {
|
||||||
|
if target
|
||||||
|
.static_data()
|
||||||
|
.and_then(|pd| pd.sit_data.as_ref())
|
||||||
|
.is_none()
|
||||||
|
{
|
||||||
|
user_error("You can't sit on that!".to_owned())?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
queue_command_and_save(
|
||||||
|
ctx,
|
||||||
|
&player_item,
|
||||||
|
&QueueCommand::Sit {
|
||||||
|
item: target.map(|t| t.refstr()),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static VERB_INT: Verb = Verb;
|
||||||
|
pub static VERB: UserVerbRef = &VERB_INT as UserVerbRef;
|
@ -264,8 +264,8 @@ pub enum Subattack {
|
|||||||
#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
pub enum LocationActionType {
|
pub enum LocationActionType {
|
||||||
Normal,
|
Normal,
|
||||||
Sitting,
|
Sitting(Option<String>),
|
||||||
Reclining,
|
Reclining(Option<String>),
|
||||||
Worn, // Clothing etc...
|
Worn, // Clothing etc...
|
||||||
Wielded,
|
Wielded,
|
||||||
Attacking(Subattack),
|
Attacking(Subattack),
|
||||||
|
@ -2,8 +2,8 @@ use super::{TaskHandler, TaskRunContext};
|
|||||||
#[double]
|
#[double]
|
||||||
use crate::db::DBTrans;
|
use crate::db::DBTrans;
|
||||||
use crate::message_handler::user_commands::{
|
use crate::message_handler::user_commands::{
|
||||||
close, cut, drink, drop, eat, fill, get, improvise, make, movement, open, put, remove, use_cmd,
|
close, cut, drink, drop, eat, fill, get, improvise, make, movement, open, put, remove, sit,
|
||||||
user_error, wear, wield, CommandHandlingError, UResult, VerbContext,
|
use_cmd, user_error, wear, wield, CommandHandlingError, UResult, VerbContext,
|
||||||
};
|
};
|
||||||
use crate::message_handler::ListenerSession;
|
use crate::message_handler::ListenerSession;
|
||||||
use crate::models::session::Session;
|
use crate::models::session::Session;
|
||||||
@ -99,6 +99,9 @@ pub enum QueueCommand {
|
|||||||
Remove {
|
Remove {
|
||||||
possession_id: String,
|
possession_id: String,
|
||||||
},
|
},
|
||||||
|
Sit {
|
||||||
|
item: Option<String>,
|
||||||
|
},
|
||||||
Use {
|
Use {
|
||||||
possession_id: String,
|
possession_id: String,
|
||||||
target_id: String,
|
target_id: String,
|
||||||
@ -135,6 +138,7 @@ impl QueueCommand {
|
|||||||
OpenDoor { .. } => "OpenDoor",
|
OpenDoor { .. } => "OpenDoor",
|
||||||
Put { .. } => "Put",
|
Put { .. } => "Put",
|
||||||
Remove { .. } => "Remove",
|
Remove { .. } => "Remove",
|
||||||
|
Sit { .. } => "Sit",
|
||||||
Use { .. } => "Use",
|
Use { .. } => "Use",
|
||||||
Wear { .. } => "Wear",
|
Wear { .. } => "Wear",
|
||||||
Wield { .. } => "Wield",
|
Wield { .. } => "Wield",
|
||||||
@ -235,6 +239,10 @@ fn queue_command_registry(
|
|||||||
"Remove",
|
"Remove",
|
||||||
&remove::QueueHandler as &(dyn QueueCommandHandler + Sync + Send),
|
&remove::QueueHandler as &(dyn QueueCommandHandler + Sync + Send),
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"Sit",
|
||||||
|
&sit::QueueHandler as &(dyn QueueCommandHandler + Sync + Send),
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"Use",
|
"Use",
|
||||||
&use_cmd::QueueHandler as &(dyn QueueCommandHandler + Sync + Send),
|
&use_cmd::QueueHandler as &(dyn QueueCommandHandler + Sync + Send),
|
||||||
|
@ -669,7 +669,7 @@ pub async fn start_attack_mut(
|
|||||||
let mut msg_nonexp = String::new();
|
let mut msg_nonexp = String::new();
|
||||||
let mut verb: String = "attacks".to_string();
|
let mut verb: String = "attacks".to_string();
|
||||||
match by_whom.action_type {
|
match by_whom.action_type {
|
||||||
LocationActionType::Sitting | LocationActionType::Reclining => {
|
LocationActionType::Sitting { .. } | LocationActionType::Reclining { .. } => {
|
||||||
msg_exp.push_str(&format!(ansi!("{} stands up.\n"), &by_whom.display));
|
msg_exp.push_str(&format!(ansi!("{} stands up.\n"), &by_whom.display));
|
||||||
msg_nonexp.push_str(&format!(
|
msg_nonexp.push_str(&format!(
|
||||||
ansi!("{} stands up.\n"),
|
ansi!("{} stands up.\n"),
|
||||||
|
@ -348,8 +348,8 @@ pub async fn set_has_urges_if_needed(trans: &DBTrans, player_item: &mut Item) ->
|
|||||||
pub async fn recalculate_urge_growth(_trans: &DBTrans, item: &mut Item) -> DResult<()> {
|
pub async fn recalculate_urge_growth(_trans: &DBTrans, item: &mut Item) -> DResult<()> {
|
||||||
let cool = item.total_stats.get(&StatType::Cool).unwrap_or(&8.0);
|
let cool = item.total_stats.get(&StatType::Cool).unwrap_or(&8.0);
|
||||||
let relax_action_factor = match item.action_type {
|
let relax_action_factor = match item.action_type {
|
||||||
LocationActionType::Sitting => 100.0,
|
LocationActionType::Sitting(_) => 100.0,
|
||||||
LocationActionType::Reclining => 150.0,
|
LocationActionType::Reclining(_) => 150.0,
|
||||||
LocationActionType::Attacking(_) => 0.5,
|
LocationActionType::Attacking(_) => 0.5,
|
||||||
_ => 1.0,
|
_ => 1.0,
|
||||||
};
|
};
|
||||||
|
@ -305,6 +305,10 @@ pub struct EatData {
|
|||||||
pub thirst_impact: i16,
|
pub thirst_impact: i16,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct SitData {
|
||||||
|
pub stress_impact: i16,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct PossessionData {
|
pub struct PossessionData {
|
||||||
pub weapon_data: Option<WeaponData>,
|
pub weapon_data: Option<WeaponData>,
|
||||||
pub display: &'static str,
|
pub display: &'static str,
|
||||||
@ -328,6 +332,7 @@ pub struct PossessionData {
|
|||||||
pub liquid_container_data: Option<LiquidContainerData>,
|
pub liquid_container_data: Option<LiquidContainerData>,
|
||||||
pub default_flags: Vec<ItemFlag>,
|
pub default_flags: Vec<ItemFlag>,
|
||||||
pub eat_data: Option<EatData>,
|
pub eat_data: Option<EatData>,
|
||||||
|
pub sit_data: Option<SitData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for PossessionData {
|
impl Default for PossessionData {
|
||||||
@ -355,6 +360,7 @@ impl Default for PossessionData {
|
|||||||
liquid_container_data: None,
|
liquid_container_data: None,
|
||||||
default_flags: vec![],
|
default_flags: vec![],
|
||||||
eat_data: None,
|
eat_data: None,
|
||||||
|
sit_data: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user