Add a mini-game around sharing knowledge
It still needs to apply buffs at the end and a few other details!
This commit is contained in:
parent
706825be20
commit
0c280711e8
@ -281,6 +281,14 @@ pub fn join_words(words: &[&str]) -> String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn join_words_or(words: &[&str]) -> String {
|
||||||
|
match words.split_last() {
|
||||||
|
None => "".to_string(),
|
||||||
|
Some((last, [])) => last.to_string(),
|
||||||
|
Some((last, rest)) => rest.join(", ") + " or " + last,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn weight(grams: u64) -> String {
|
pub fn weight(grams: u64) -> String {
|
||||||
if grams > 999 {
|
if grams > 999 {
|
||||||
format!(
|
format!(
|
||||||
@ -380,6 +388,19 @@ mod test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn join_words_or_works() {
|
||||||
|
for (inp, outp) in vec![
|
||||||
|
(vec![], ""),
|
||||||
|
(vec!["cat"], "cat"),
|
||||||
|
(vec!["cat", "dog"], "cat or dog"),
|
||||||
|
(vec!["cat", "dog", "fish"], "cat, dog or fish"),
|
||||||
|
(vec!["wolf", "cat", "dog", "fish"], "wolf, cat, dog or fish"),
|
||||||
|
] {
|
||||||
|
assert_eq!(super::join_words_or(&inp[..]), outp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn weight_works() {
|
fn weight_works() {
|
||||||
assert_eq!(super::weight(100), "100 g");
|
assert_eq!(super::weight(100), "100 g");
|
||||||
|
@ -68,6 +68,7 @@ mod reset_spawns;
|
|||||||
pub mod say;
|
pub mod say;
|
||||||
pub mod scavenge;
|
pub mod scavenge;
|
||||||
mod score;
|
mod score;
|
||||||
|
mod share;
|
||||||
mod sign;
|
mod sign;
|
||||||
pub mod sit;
|
pub mod sit;
|
||||||
mod staff_show;
|
mod staff_show;
|
||||||
@ -241,6 +242,22 @@ static REGISTERED_COMMANDS: UserVerbRegistry = phf_map! {
|
|||||||
"sc" => score::VERB,
|
"sc" => score::VERB,
|
||||||
"score" => score::VERB,
|
"score" => score::VERB,
|
||||||
|
|
||||||
|
"share" => share::VERB,
|
||||||
|
"serious" => share::VERB,
|
||||||
|
"amicable" => share::VERB,
|
||||||
|
"joking" => share::VERB,
|
||||||
|
"parody" => share::VERB,
|
||||||
|
"play" => share::VERB,
|
||||||
|
"thoughts" => share::VERB,
|
||||||
|
"exploring" => share::VERB,
|
||||||
|
"roaming" => share::VERB,
|
||||||
|
"fishing" => share::VERB,
|
||||||
|
"good" => share::VERB,
|
||||||
|
"surviving" => share::VERB,
|
||||||
|
"slow" => share::VERB,
|
||||||
|
"normal" => share::VERB,
|
||||||
|
"intense" => share::VERB,
|
||||||
|
|
||||||
"sign" => sign::VERB,
|
"sign" => sign::VERB,
|
||||||
"sit" => sit::VERB,
|
"sit" => sit::VERB,
|
||||||
|
|
||||||
|
@ -373,8 +373,8 @@ mod tests {
|
|||||||
"Bar",
|
"Bar",
|
||||||
"her",
|
"her",
|
||||||
"from bar",
|
"from bar",
|
||||||
&ConsentType::Sex,
|
&ConsentType::Share,
|
||||||
&ConsentDetails::default_for(&ConsentType::Sex),
|
&ConsentDetails::default_for(&ConsentType::Share),
|
||||||
&Some(Consent::default()),
|
&Some(Consent::default()),
|
||||||
&None,
|
&None,
|
||||||
false,
|
false,
|
||||||
@ -527,8 +527,8 @@ mod tests {
|
|||||||
"Bar",
|
"Bar",
|
||||||
"her",
|
"her",
|
||||||
"from bar",
|
"from bar",
|
||||||
&ConsentType::Sex,
|
&ConsentType::Share,
|
||||||
&ConsentDetails::default_for(&ConsentType::Sex),
|
&ConsentDetails::default_for(&ConsentType::Share),
|
||||||
&None,
|
&None,
|
||||||
&None,
|
&None,
|
||||||
true,
|
true,
|
||||||
@ -820,12 +820,10 @@ async fn handle_user_consent(
|
|||||||
.await?
|
.await?
|
||||||
{
|
{
|
||||||
None => {}
|
None => {}
|
||||||
Some((session, session_dat)) => {
|
Some((session, _session_dat)) => {
|
||||||
if cmd.consent_type != ConsentType::Sex || !session_dat.less_explicit_mode {
|
ctx.trans
|
||||||
ctx.trans
|
.queue_for_session(&session, Some(&(msg + "\n")))
|
||||||
.queue_for_session(&session, Some(&(msg + "\n")))
|
.await?;
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1030,8 +1028,7 @@ impl UserVerb for Verb {
|
|||||||
if remaining_trim == "" {
|
if remaining_trim == "" {
|
||||||
handle_list_allows(ctx, &player_item).await?;
|
handle_list_allows(ctx, &player_item).await?;
|
||||||
} else {
|
} else {
|
||||||
let mut cmd = match parsing::parse_allow(remaining, !ctx.session_dat.less_explicit_mode)
|
let mut cmd = match parsing::parse_allow(remaining) {
|
||||||
{
|
|
||||||
Err(msg) => user_error(msg)?,
|
Err(msg) => user_error(msg)?,
|
||||||
Ok(cmd) => cmd,
|
Ok(cmd) => cmd,
|
||||||
};
|
};
|
||||||
|
@ -32,12 +32,6 @@ fn unregistered_help_pages() -> &'static BTreeMap<String, String> {
|
|||||||
CELL.get_or_init(|| load_help_yaml(include_str!("help/unregistered.yaml")))
|
CELL.get_or_init(|| load_help_yaml(include_str!("help/unregistered.yaml")))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn explicit_help_pages() -> &'static BTreeMap<String, String> {
|
|
||||||
static CELL: OnceCell<BTreeMap<String, String>> = OnceCell::new();
|
|
||||||
|
|
||||||
CELL.get_or_init(|| load_help_yaml(include_str!("help/explicit.yaml")))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Verb;
|
pub struct Verb;
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl UserVerb for Verb {
|
impl UserVerb for Verb {
|
||||||
@ -57,9 +51,6 @@ impl UserVerb for Verb {
|
|||||||
help = help.or_else(|| unregistered_help_pages().get(remaining));
|
help = help.or_else(|| unregistered_help_pages().get(remaining));
|
||||||
} else {
|
} else {
|
||||||
help = help.or_else(|| registered_help_pages().get(remaining));
|
help = help.or_else(|| registered_help_pages().get(remaining));
|
||||||
if !ctx.session_dat.less_explicit_mode {
|
|
||||||
help = explicit_help_pages().get(remaining).or(help);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
help = help.or_else(|| always_help_pages().get(remaining).map(|v| v));
|
help = help.or_else(|| always_help_pages().get(remaining).map(|v| v));
|
||||||
let help_final = help.ok_or(UserError("No help available on that".to_string()))?;
|
let help_final = help.ok_or(UserError("No help available on that".to_string()))?;
|
||||||
@ -90,9 +81,4 @@ mod tests {
|
|||||||
fn always_help_ok() {
|
fn always_help_ok() {
|
||||||
always_help_pages();
|
always_help_pages();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn explicit_help_ok() {
|
|
||||||
explicit_help_pages();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
fuck: "Type <bold>fuck <lt>name><reset> to fuck someone. It only works if they have consented."
|
|
||||||
allow: |-
|
|
||||||
<bold>allow<reset> is the corner-stone of Blastmud's consent system. Consents in Blastmud let you choose how you want to play with other players (it only affects players, not NPCs). There are 5 types of consent: <bold>fight<reset> (for hostile actions like attack or pick), <bold>medicine<reset> (for medical actions, including those that might crit fail and do harm), <bold>gifts<reset> (lets them give you things), <bold>visit<reset> (lets them on to a tile owned by you legally), and <bold>fuck<reset> (lets them do fun but dirty things to you).
|
|
||||||
|
|
||||||
To allow, as an individual, use the syntax <bold>allow <reset>type <bold>from <reset>player options
|
|
||||||
As a corp, use the syntax <bold>allow <reset>type <bold>against <reset>corpname <bold>by<reset> corpname options
|
|
||||||
Options can be blank to use defaults, or can be one or more of the following, separated by spaces:
|
|
||||||
<bold>until <reset> n <bold>minutes<reset> - replace n with a number. You can use hours, days, or weeks instead of minutes. This makes the consent expire. Fight expires after a week if you don't give a shorter period, and all other consent types have no expiry unless you specify one.
|
|
||||||
<bold>until death<reset> - makes the consent valid only until you next die.
|
|
||||||
<bold>allow private<reset> - makes the consent valid even in privately owned places. This is the default for anything except fight.
|
|
||||||
<bold>disallow private<reset> - the opposite of allow private.
|
|
||||||
<bold>in<reset> place - limits where fighting can happen to selected public places. You can use <bold>here<reset>, or if you know the code, a place name. You can use this option more than once to allow any place, and if you don't use the option, it means anywhere (subject to allow private).
|
|
||||||
<bold>allow pick<reset> - fight only - include picking in your consent.
|
|
||||||
<bold>allow revoke<reset> - fight only - allows the player to revoke any time with disallow.
|
|
||||||
|
|
||||||
Consents for anything except fight take effect immediately to let the other player do the action.
|
|
||||||
Consents for fight take effect when the other player executes a reciprocal allow command.
|
|
||||||
Consents for anything except than fight can be revoked instantly with:
|
|
||||||
<bold>disallow<reset> action <bold>from<reset> player
|
|
||||||
Consent for fight can be revoked similarly if the consent used the <bold>allow revoke<reset> option. Otherwise, attempting to revoke informs the other player, and it is revoked when they also issue a disallow command.
|
|
@ -93,7 +93,7 @@ list: *possessions
|
|||||||
wield: *possessions
|
wield: *possessions
|
||||||
gear: *possessions
|
gear: *possessions
|
||||||
allow: |-
|
allow: |-
|
||||||
<bold>allow<reset> is the corner-stone of Blastmud's consent system. Consents in Blastmud let you choose how you want to play with other players (it only affects players, not NPCs). There are 4 types of consent: <bold>fight<reset> (for hostile actions like attack or pick), <bold>medicine<reset> (for medical actions, including those that might crit fail and do harm), <bold>gifts<reset> (lets them give you things), and <bold>visit<reset> (lets them on to a tile owned by you legally).
|
<bold>allow<reset> is the corner-stone of Blastmud's consent system. Consents in Blastmud let you choose how you want to play with other players (it only affects players, not NPCs). There are 5 types of consent: <bold>fight<reset> (for hostile actions like attack or pick), <bold>medicine<reset> (for medical actions, including those that might crit fail and do harm), <bold>gifts<reset> (lets them give you things), <bold>visit<reset> (lets them on to a tile owned by you legally), and <bold>share<reset> (lets them local share knowledge with you, making both parties stronger).
|
||||||
|
|
||||||
To allow, as an individual, use the syntax <bold>allow <reset>type <bold>from <reset>player options
|
To allow, as an individual, use the syntax <bold>allow <reset>type <bold>from <reset>player options
|
||||||
As a corp, use the syntax <bold>allow <reset>type <bold>against <reset>corpname <bold>by<reset> corpname options
|
As a corp, use the syntax <bold>allow <reset>type <bold>against <reset>corpname <bold>by<reset> corpname options
|
||||||
|
@ -24,6 +24,7 @@ use crate::{
|
|||||||
check_consent, check_one_consent,
|
check_consent, check_one_consent,
|
||||||
combat::{change_health, handle_resurrect, stop_attacking_mut},
|
combat::{change_health, handle_resurrect, stop_attacking_mut},
|
||||||
comms::broadcast_to_room,
|
comms::broadcast_to_room,
|
||||||
|
sharing::stop_conversation_mut,
|
||||||
skills::skill_check_and_grind,
|
skills::skill_check_and_grind,
|
||||||
urges::{recalculate_urge_growth, thirst_changed},
|
urges::{recalculate_urge_growth, thirst_changed},
|
||||||
},
|
},
|
||||||
@ -892,6 +893,14 @@ impl UserVerb for Verb {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
if player_item.active_conversation.is_some() {
|
||||||
|
stop_conversation_mut(
|
||||||
|
&ctx.trans,
|
||||||
|
&mut player_item,
|
||||||
|
"walks away from sharing knowledge with",
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
ctx.trans.save_item_model(&player_item).await?;
|
ctx.trans.save_item_model(&player_item).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -118,7 +118,7 @@ pub fn parse_duration_mins<'l>(input: &'l str) -> Result<(u64, &'l str), String>
|
|||||||
}, input))
|
}, input))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_allow<'l>(input: &'l str, is_explicit: bool) -> Result<AllowCommand, String> {
|
pub fn parse_allow<'l>(input: &'l str) -> Result<AllowCommand, String> {
|
||||||
let usage: &'static str =
|
let usage: &'static str =
|
||||||
ansi!("Usage: allow <lt>action> from <lt>user> <lt>options> | allow <lt>action> against <lt>corp> by <lt>corp> <lt>options>. Try <bold>help allow<reset> for more.");
|
ansi!("Usage: allow <lt>action> from <lt>user> <lt>options> | allow <lt>action> against <lt>corp> by <lt>corp> <lt>options>. Try <bold>help allow<reset> for more.");
|
||||||
let (consent_type_s, input) = match input.trim_start().split_once(" ") {
|
let (consent_type_s, input) = match input.trim_start().split_once(" ") {
|
||||||
@ -126,11 +126,7 @@ pub fn parse_allow<'l>(input: &'l str, is_explicit: bool) -> Result<AllowCommand
|
|||||||
Some(v) => Ok(v),
|
Some(v) => Ok(v),
|
||||||
}?;
|
}?;
|
||||||
let consent_type = match ConsentType::from_str(&consent_type_s.trim().to_lowercase()) {
|
let consent_type = match ConsentType::from_str(&consent_type_s.trim().to_lowercase()) {
|
||||||
None => Err(if is_explicit {
|
None => Err("Invalid consent type - options are fight, medicine, gifts, visit and share"),
|
||||||
"Invalid consent type - options are fight, medicine, gifts, visit and sex"
|
|
||||||
} else {
|
|
||||||
"Invalid consent type - options are fight, medicine, gifts and visit"
|
|
||||||
}),
|
|
||||||
Some(ct) => Ok(ct),
|
Some(ct) => Ok(ct),
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
@ -434,7 +430,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn parse_consent_works_default_options_user() {
|
fn parse_consent_works_default_options_user() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
super::parse_allow("medicine From Athorina", false),
|
super::parse_allow("medicine From Athorina"),
|
||||||
Ok(AllowCommand {
|
Ok(AllowCommand {
|
||||||
consent_type: ConsentType::Medicine,
|
consent_type: ConsentType::Medicine,
|
||||||
consent_target: ConsentTarget::UserTarget {
|
consent_target: ConsentTarget::UserTarget {
|
||||||
@ -448,7 +444,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn parse_consent_works_default_options_corp() {
|
fn parse_consent_works_default_options_corp() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
super::parse_allow("Fight Against megacorp By supercorp", false),
|
super::parse_allow("Fight Against megacorp By supercorp"),
|
||||||
Ok(AllowCommand {
|
Ok(AllowCommand {
|
||||||
consent_type: ConsentType::Fight,
|
consent_type: ConsentType::Fight,
|
||||||
consent_target: ConsentTarget::CorpTarget {
|
consent_target: ConsentTarget::CorpTarget {
|
||||||
@ -462,7 +458,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_consent_handles_options() {
|
fn parse_consent_handles_options() {
|
||||||
assert_eq!(super::parse_allow("fighT fRom athorina For 2 hOurs unTil deAth allOw priVate Disallow pIck alLow revoKe iN here in pit", false),
|
assert_eq!(super::parse_allow("fighT fRom athorina For 2 hOurs unTil deAth allOw priVate Disallow pIck alLow revoKe iN here in pit"),
|
||||||
Ok(AllowCommand {
|
Ok(AllowCommand {
|
||||||
consent_type: ConsentType::Fight,
|
consent_type: ConsentType::Fight,
|
||||||
consent_target: ConsentTarget::UserTarget { to_user: "athorina" },
|
consent_target: ConsentTarget::UserTarget { to_user: "athorina" },
|
||||||
|
112
blastmud_game/src/message_handler/user_commands/share.rs
Normal file
112
blastmud_game/src/message_handler/user_commands/share.rs
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
use crate::{
|
||||||
|
db::ItemSearchParams,
|
||||||
|
models::item::{ConversationIntensity, ConversationalStyle},
|
||||||
|
services::sharing::{
|
||||||
|
change_conversation_intensity, change_conversation_topic, change_conversational_style,
|
||||||
|
display_conversation_status, parse_conversation_topic, start_conversation,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
get_player_item_or_fail, search_item_for_user, user_error, UResult, UserError, UserVerb,
|
||||||
|
UserVerbRef, VerbContext,
|
||||||
|
};
|
||||||
|
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 mut player_item = (*(get_player_item_or_fail(ctx).await?)).clone();
|
||||||
|
if player_item.death_data.is_some() {
|
||||||
|
user_error("You can't do that, you're dead!".to_string())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let remaining = remaining.trim();
|
||||||
|
if let Some(ac) = player_item.active_conversation.as_ref() {
|
||||||
|
match ConversationalStyle::from_name(verb) {
|
||||||
|
None => {}
|
||||||
|
Some(style) => {
|
||||||
|
change_conversational_style(ctx, &mut player_item, style).await?;
|
||||||
|
ctx.trans.save_item_model(&player_item).await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
match parse_conversation_topic(&format!("{} {}", verb, remaining))
|
||||||
|
.map_err(|e| UserError(e.to_owned()))?
|
||||||
|
{
|
||||||
|
None => {}
|
||||||
|
Some(topic) => {
|
||||||
|
change_conversation_topic(ctx, &mut player_item, topic).await?;
|
||||||
|
ctx.trans.save_item_model(&player_item).await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if verb == "share" {
|
||||||
|
match ConversationIntensity::from_adverb(remaining) {
|
||||||
|
None => {}
|
||||||
|
Some(intensity) => {
|
||||||
|
change_conversation_intensity(ctx, &mut player_item, intensity).await?;
|
||||||
|
ctx.trans.save_item_model(&player_item).await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if remaining == "status" {
|
||||||
|
let (partner_type, partner_code) = ac
|
||||||
|
.partner_ref
|
||||||
|
.split_once("/")
|
||||||
|
.ok_or_else(|| UserError("Bad share partner".to_owned()))?;
|
||||||
|
if let Some(partner) = ctx
|
||||||
|
.trans
|
||||||
|
.find_item_by_type_code(partner_type, partner_code)
|
||||||
|
.await?
|
||||||
|
{
|
||||||
|
display_conversation_status(&ctx.trans, &player_item, &partner).await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
user_error("You're already sharing knowledge!".to_owned())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let (word2, remaining) = remaining.split_once(" ").ok_or_else(|| {
|
||||||
|
UserError(
|
||||||
|
ansi!("Start your encounter with the <bold>share knowledge with<reset> command first.")
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
let (word3, remaining) = remaining.trim().split_once(" ").ok_or_else(|| {
|
||||||
|
UserError(ansi!("<bold>share knowledge with<reset> command first.").to_owned())
|
||||||
|
})?;
|
||||||
|
if verb != "share" || word2.trim() != "knowledge" || word3.trim() != "with" {
|
||||||
|
user_error(
|
||||||
|
ansi!("Start your encounter with the <bold>share knowledge with<reset> command first.")
|
||||||
|
.to_owned(),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let with_whom = search_item_for_user(
|
||||||
|
ctx,
|
||||||
|
&ItemSearchParams {
|
||||||
|
include_loc_contents: true,
|
||||||
|
limit: 1,
|
||||||
|
..ItemSearchParams::base(&player_item, remaining)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
start_conversation(&ctx.trans, &player_item, &with_whom).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static VERB_INT: Verb = Verb;
|
||||||
|
pub static VERB: UserVerbRef = &VERB_INT as UserVerbRef;
|
@ -1,22 +1,11 @@
|
|||||||
use super::{get_player_item_or_fail, user_error, UResult, UserVerb, UserVerbRef, VerbContext};
|
use super::{get_player_item_or_fail, user_error, UResult, UserVerb, UserVerbRef, VerbContext};
|
||||||
use crate::{models::item::Urges, services::combat::max_health};
|
use crate::{
|
||||||
|
models::item::Urges,
|
||||||
|
services::{combat::max_health, display::bar_n_of_m},
|
||||||
|
};
|
||||||
use ansi::ansi;
|
use ansi::ansi;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
|
||||||
fn bar_n_of_m(mut actual: u64, max: u64) -> String {
|
|
||||||
if actual > max {
|
|
||||||
actual = max;
|
|
||||||
}
|
|
||||||
let mut r = String::new();
|
|
||||||
for _i in 0..actual {
|
|
||||||
r += "|";
|
|
||||||
}
|
|
||||||
for _i in actual..max {
|
|
||||||
r += " ";
|
|
||||||
}
|
|
||||||
r
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Verb;
|
pub struct Verb;
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl UserVerb for Verb {
|
impl UserVerb for Verb {
|
||||||
|
@ -2,6 +2,7 @@ use super::{
|
|||||||
get_player_item_or_fail, movement::reverse_climb, user_error, UResult, UserVerb, UserVerbRef,
|
get_player_item_or_fail, movement::reverse_climb, user_error, UResult, UserVerb, UserVerbRef,
|
||||||
VerbContext,
|
VerbContext,
|
||||||
};
|
};
|
||||||
|
use crate::services::sharing::stop_conversation_mut;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
|
||||||
pub struct Verb;
|
pub struct Verb;
|
||||||
@ -21,6 +22,20 @@ impl UserVerb for Verb {
|
|||||||
let mut player_item_mut = (*player_item).clone();
|
let mut player_item_mut = (*player_item).clone();
|
||||||
let mut queue_head = player_item_mut.queue.pop_front();
|
let mut queue_head = player_item_mut.queue.pop_front();
|
||||||
|
|
||||||
|
if player_item_mut.active_conversation.is_some() {
|
||||||
|
stop_conversation_mut(
|
||||||
|
&ctx.trans,
|
||||||
|
&mut player_item_mut,
|
||||||
|
&format!(
|
||||||
|
"holds up {} hand to stop the conversation with",
|
||||||
|
&player_item.pronouns.possessive
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
ctx.trans.save_item_model(&player_item_mut).await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
if player_item.active_combat.is_some() {
|
if player_item.active_combat.is_some() {
|
||||||
// Otherwise, we assume they wanted to stop escaping etc...
|
// Otherwise, we assume they wanted to stop escaping etc...
|
||||||
if queue_head.is_none() {
|
if queue_head.is_none() {
|
||||||
|
@ -8,7 +8,7 @@ pub enum ConsentType {
|
|||||||
Medicine,
|
Medicine,
|
||||||
Gifts,
|
Gifts,
|
||||||
Visit,
|
Visit,
|
||||||
Sex,
|
Share,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConsentType {
|
impl ConsentType {
|
||||||
@ -19,7 +19,7 @@ impl ConsentType {
|
|||||||
"medicine" => Some(Medicine),
|
"medicine" => Some(Medicine),
|
||||||
"gifts" => Some(Gifts),
|
"gifts" => Some(Gifts),
|
||||||
"visit" => Some(Visit),
|
"visit" => Some(Visit),
|
||||||
"sex" => Some(Sex),
|
"share" => Some(Share),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -31,7 +31,7 @@ impl ConsentType {
|
|||||||
Medicine => "medicine",
|
Medicine => "medicine",
|
||||||
Gifts => "gifts",
|
Gifts => "gifts",
|
||||||
Visit => "visit",
|
Visit => "visit",
|
||||||
Sex => "sex",
|
Share => "share",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,6 @@ pub enum SkillType {
|
|||||||
Fists,
|
Fists,
|
||||||
Flails,
|
Flails,
|
||||||
Focus,
|
Focus,
|
||||||
Fuck,
|
|
||||||
Hack,
|
Hack,
|
||||||
Locksmith,
|
Locksmith,
|
||||||
Medic,
|
Medic,
|
||||||
@ -66,6 +65,7 @@ pub enum SkillType {
|
|||||||
Rifles,
|
Rifles,
|
||||||
Scavenge,
|
Scavenge,
|
||||||
Science,
|
Science,
|
||||||
|
Share,
|
||||||
Sneak,
|
Sneak,
|
||||||
Spears,
|
Spears,
|
||||||
Swim,
|
Swim,
|
||||||
@ -81,8 +81,9 @@ impl SkillType {
|
|||||||
use SkillType::*;
|
use SkillType::*;
|
||||||
vec![
|
vec![
|
||||||
Appraise, Blades, Bombs, Chemistry, Climb, Clubs, Craft, Dodge, Fish, Fists, Flails,
|
Appraise, Blades, Bombs, Chemistry, Climb, Clubs, Craft, Dodge, Fish, Fists, Flails,
|
||||||
Focus, Fuck, Hack, Locksmith, Medic, Persuade, Pilot, Pistols, Quickdraw, Repair, Ride,
|
Focus, Hack, Locksmith, Medic, Persuade, Pilot, Pistols, Quickdraw, Repair, Ride,
|
||||||
Rifles, Scavenge, Science, Sneak, Spears, Swim, Teach, Throw, Track, Wrestle, Whips,
|
Rifles, Scavenge, Science, Share, Sneak, Spears, Swim, Teach, Throw, Track, Wrestle,
|
||||||
|
Whips,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
pub fn display(&self) -> &'static str {
|
pub fn display(&self) -> &'static str {
|
||||||
@ -100,7 +101,6 @@ impl SkillType {
|
|||||||
Fists => "fists",
|
Fists => "fists",
|
||||||
Flails => "flails",
|
Flails => "flails",
|
||||||
Focus => "focus",
|
Focus => "focus",
|
||||||
Fuck => "fuck",
|
|
||||||
Hack => "hack",
|
Hack => "hack",
|
||||||
Locksmith => "locksmith",
|
Locksmith => "locksmith",
|
||||||
Medic => "medic",
|
Medic => "medic",
|
||||||
@ -113,6 +113,7 @@ impl SkillType {
|
|||||||
Rifles => "rifles",
|
Rifles => "rifles",
|
||||||
Scavenge => "scavenge",
|
Scavenge => "scavenge",
|
||||||
Science => "science",
|
Science => "science",
|
||||||
|
Share => "share",
|
||||||
Sneak => "sneak",
|
Sneak => "sneak",
|
||||||
Spears => "spears",
|
Spears => "spears",
|
||||||
Swim => "swim",
|
Swim => "swim",
|
||||||
@ -317,6 +318,7 @@ pub enum ItemFlag {
|
|||||||
HasUrges,
|
HasUrges,
|
||||||
NoUrgesHere,
|
NoUrgesHere,
|
||||||
DontListInLook,
|
DontListInLook,
|
||||||
|
AllowShare,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
@ -362,6 +364,175 @@ impl Default for ActiveClimb {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
|
pub enum ConversationalInterestType {
|
||||||
|
Philosophy,
|
||||||
|
LocalGeography,
|
||||||
|
Threats,
|
||||||
|
Tactics,
|
||||||
|
Weather,
|
||||||
|
Politics,
|
||||||
|
Frivolity,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConversationalInterestType {
|
||||||
|
pub fn display(&self) -> &'static str {
|
||||||
|
use ConversationalInterestType::*;
|
||||||
|
match self {
|
||||||
|
Philosophy => "philosophy",
|
||||||
|
LocalGeography => "local geography",
|
||||||
|
Threats => "threats",
|
||||||
|
Tactics => "tactics",
|
||||||
|
Weather => "weather",
|
||||||
|
Politics => "politics",
|
||||||
|
Frivolity => "frivolity",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
|
pub enum ConversationalStyle {
|
||||||
|
Joking,
|
||||||
|
Serious,
|
||||||
|
Amicable,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConversationalStyle {
|
||||||
|
pub fn display(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
ConversationalStyle::Amicable => "amicable",
|
||||||
|
ConversationalStyle::Serious => "serious",
|
||||||
|
ConversationalStyle::Joking => "joking",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn transitions(&self) -> Vec<ConversationalStyle> {
|
||||||
|
use ConversationalStyle::*;
|
||||||
|
vec![Amicable, Serious, Joking]
|
||||||
|
.into_iter()
|
||||||
|
.filter(|v| v != self)
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_name(n: &str) -> Option<ConversationalStyle> {
|
||||||
|
use ConversationalStyle::*;
|
||||||
|
match n {
|
||||||
|
"amicable" => Some(Amicable),
|
||||||
|
"serious" => Some(Serious),
|
||||||
|
"joking" => Some(Joking),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
|
pub enum ConversationTopic {
|
||||||
|
ParodyKingsOffice,
|
||||||
|
PlayFight,
|
||||||
|
ThoughtsOnSunTzu,
|
||||||
|
ThoughtsOnMachiavelli,
|
||||||
|
ExploringRuins,
|
||||||
|
RoamingEnemies,
|
||||||
|
FishingSpots,
|
||||||
|
GoodAmbushSpots,
|
||||||
|
SurvivingWeather,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConversationTopic {
|
||||||
|
pub fn display_command(&self) -> &'static str {
|
||||||
|
use ConversationTopic::*;
|
||||||
|
match self {
|
||||||
|
ParodyKingsOffice => "parody kings office",
|
||||||
|
PlayFight => "play fight",
|
||||||
|
ThoughtsOnSunTzu => "thoughts on sun tzu",
|
||||||
|
ThoughtsOnMachiavelli => "thoughts on machiavelli",
|
||||||
|
ExploringRuins => "exploring ruins",
|
||||||
|
RoamingEnemies => "roaming enemies",
|
||||||
|
FishingSpots => "fishing spots",
|
||||||
|
GoodAmbushSpots => "good ambush spots",
|
||||||
|
SurvivingWeather => "surviving weather",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn display_readable(&self) -> &'static str {
|
||||||
|
use ConversationTopic::*;
|
||||||
|
match self {
|
||||||
|
ParodyKingsOffice => "parodying the kings office",
|
||||||
|
PlayFight => "proposing a play fight",
|
||||||
|
ThoughtsOnSunTzu => "sharing thoughts on Sun Tzu",
|
||||||
|
ThoughtsOnMachiavelli => "sharing thoughts on Machiavelli",
|
||||||
|
ExploringRuins => "comparing notes on exploring ruins",
|
||||||
|
RoamingEnemies => "complaining about roaming enemies",
|
||||||
|
FishingSpots => "sharing the best fishing spots",
|
||||||
|
GoodAmbushSpots => "discussing good ambush spots",
|
||||||
|
SurvivingWeather => "describing how to survive weather",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
|
pub enum ConversationIntensity {
|
||||||
|
Slow,
|
||||||
|
Normal,
|
||||||
|
Fast,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConversationIntensity {
|
||||||
|
pub fn to_command(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Self::Slow => "share slowly",
|
||||||
|
Self::Normal => "share normally",
|
||||||
|
Self::Fast => "share quickly",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn display_readable(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Self::Slow => "slowly",
|
||||||
|
Self::Normal => "normally",
|
||||||
|
Self::Fast => "quickly",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_adverb(input: &str) -> Option<ConversationIntensity> {
|
||||||
|
let input = input.to_lowercase();
|
||||||
|
if input == "slowly" {
|
||||||
|
Some(ConversationIntensity::Slow)
|
||||||
|
} else if input == "normally" {
|
||||||
|
Some(ConversationIntensity::Normal)
|
||||||
|
} else if input == "quickly" {
|
||||||
|
Some(ConversationIntensity::Fast)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
|
#[serde(default)]
|
||||||
|
pub struct ActiveConversation {
|
||||||
|
pub interest_levels: BTreeMap<ConversationalInterestType, u64>,
|
||||||
|
pub partner_ref: String,
|
||||||
|
pub style: ConversationalStyle,
|
||||||
|
pub current_topic: ConversationTopic,
|
||||||
|
pub current_intensity: ConversationIntensity,
|
||||||
|
pub peak_total_interest: u64,
|
||||||
|
pub last_change: DateTime<Utc>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ActiveConversation {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
interest_levels: BTreeMap::new(),
|
||||||
|
partner_ref: "unset".to_owned(),
|
||||||
|
style: ConversationalStyle::Serious,
|
||||||
|
current_topic: ConversationTopic::RoamingEnemies,
|
||||||
|
current_intensity: ConversationIntensity::Normal,
|
||||||
|
peak_total_interest: 0,
|
||||||
|
last_change: DateTime::UNIX_EPOCH,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct Urge {
|
pub struct Urge {
|
||||||
@ -495,6 +666,7 @@ pub struct Item {
|
|||||||
pub active_climb: Option<ActiveClimb>,
|
pub active_climb: Option<ActiveClimb>,
|
||||||
pub active_combat: Option<ActiveCombat>,
|
pub active_combat: Option<ActiveCombat>,
|
||||||
pub active_effects: Vec<(EffectType, i64)>,
|
pub active_effects: Vec<(EffectType, i64)>,
|
||||||
|
pub active_conversation: Option<ActiveConversation>,
|
||||||
pub aliases: Vec<String>,
|
pub aliases: Vec<String>,
|
||||||
pub charges: u8,
|
pub charges: u8,
|
||||||
pub death_data: Option<DeathData>,
|
pub death_data: Option<DeathData>,
|
||||||
@ -620,6 +792,7 @@ impl Default for Item {
|
|||||||
active_climb: None,
|
active_climb: None,
|
||||||
active_combat: Some(Default::default()),
|
active_combat: Some(Default::default()),
|
||||||
active_effects: vec![],
|
active_effects: vec![],
|
||||||
|
active_conversation: None,
|
||||||
aliases: vec![],
|
aliases: vec![],
|
||||||
charges: 0,
|
charges: 0,
|
||||||
death_data: None,
|
death_data: None,
|
||||||
|
@ -27,6 +27,7 @@ pub enum TaskDetails {
|
|||||||
npc_code: String,
|
npc_code: String,
|
||||||
},
|
},
|
||||||
AttackTick,
|
AttackTick,
|
||||||
|
ShareTick,
|
||||||
RecloneNPC {
|
RecloneNPC {
|
||||||
npc_code: String,
|
npc_code: String,
|
||||||
},
|
},
|
||||||
@ -78,6 +79,7 @@ impl TaskDetails {
|
|||||||
NPCWander { .. } => "NPCWander",
|
NPCWander { .. } => "NPCWander",
|
||||||
NPCAggro { .. } => "NPCAggro",
|
NPCAggro { .. } => "NPCAggro",
|
||||||
AttackTick => "AttackTick",
|
AttackTick => "AttackTick",
|
||||||
|
ShareTick => "ShareTick",
|
||||||
RecloneNPC { .. } => "RecloneNPC",
|
RecloneNPC { .. } => "RecloneNPC",
|
||||||
RotCorpse { .. } => "RotCorpse",
|
RotCorpse { .. } => "RotCorpse",
|
||||||
DelayedHealth { .. } => "DelayedHealth",
|
DelayedHealth { .. } => "DelayedHealth",
|
||||||
|
@ -9,7 +9,7 @@ use crate::{
|
|||||||
listener::{ListenerMap, ListenerSend},
|
listener::{ListenerMap, ListenerSend},
|
||||||
message_handler::user_commands::{delete, drop, hire, open, rent},
|
message_handler::user_commands::{delete, drop, hire, open, rent},
|
||||||
models::task::Task,
|
models::task::Task,
|
||||||
services::{combat, effect, spawn, urges},
|
services::{combat, effect, sharing, spawn, urges},
|
||||||
static_content::{
|
static_content::{
|
||||||
npc::{self, computer_museum_npcs},
|
npc::{self, computer_museum_npcs},
|
||||||
room::general_hospital,
|
room::general_hospital,
|
||||||
@ -52,6 +52,7 @@ fn task_handler_registry(
|
|||||||
("NPCWander", npc::WANDER_HANDLER),
|
("NPCWander", npc::WANDER_HANDLER),
|
||||||
("NPCAggro", npc::AGGRO_HANDLER),
|
("NPCAggro", npc::AGGRO_HANDLER),
|
||||||
("AttackTick", combat::TASK_HANDLER),
|
("AttackTick", combat::TASK_HANDLER),
|
||||||
|
("ShareTick", sharing::TASK_HANDLER),
|
||||||
("RecloneNPC", npc::RECLONE_HANDLER),
|
("RecloneNPC", npc::RECLONE_HANDLER),
|
||||||
("RotCorpse", combat::ROT_CORPSE_HANDLER),
|
("RotCorpse", combat::ROT_CORPSE_HANDLER),
|
||||||
("DelayedHealth", effect::DELAYED_HEALTH_HANDLER),
|
("DelayedHealth", effect::DELAYED_HEALTH_HANDLER),
|
||||||
|
@ -19,7 +19,9 @@ use mockall_double::double;
|
|||||||
pub mod capacity;
|
pub mod capacity;
|
||||||
pub mod combat;
|
pub mod combat;
|
||||||
pub mod comms;
|
pub mod comms;
|
||||||
|
pub mod display;
|
||||||
pub mod effect;
|
pub mod effect;
|
||||||
|
pub mod sharing;
|
||||||
pub mod skills;
|
pub mod skills;
|
||||||
pub mod spawn;
|
pub mod spawn;
|
||||||
pub mod urges;
|
pub mod urges;
|
||||||
|
@ -1361,7 +1361,7 @@ impl TaskHandler for RotCorpseTaskHandler {
|
|||||||
pub static ROT_CORPSE_HANDLER: &'static (dyn TaskHandler + Sync + Send) = &RotCorpseTaskHandler;
|
pub static ROT_CORPSE_HANDLER: &'static (dyn TaskHandler + Sync + Send) = &RotCorpseTaskHandler;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod Tests {
|
mod tests {
|
||||||
use crate::{models::effect::EffectType, services::effect::default_effects_for_type};
|
use crate::{models::effect::EffectType, services::effect::default_effects_for_type};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
13
blastmud_game/src/services/display.rs
Normal file
13
blastmud_game/src/services/display.rs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
pub fn bar_n_of_m(mut actual: u64, max: u64) -> String {
|
||||||
|
if actual > max {
|
||||||
|
actual = max;
|
||||||
|
}
|
||||||
|
let mut r = String::new();
|
||||||
|
for _i in 0..actual {
|
||||||
|
r += "|";
|
||||||
|
}
|
||||||
|
for _i in actual..max {
|
||||||
|
r += " ";
|
||||||
|
}
|
||||||
|
r
|
||||||
|
}
|
1260
blastmud_game/src/services/sharing.rs
Normal file
1260
blastmud_game/src/services/sharing.rs
Normal file
File diff suppressed because it is too large
Load Diff
@ -183,12 +183,12 @@ pub fn calculate_total_stats_skills_for_user(target_item: &mut Item, user: &User
|
|||||||
.or_insert(end * 0.5);
|
.or_insert(end * 0.5);
|
||||||
target_item
|
target_item
|
||||||
.total_skills
|
.total_skills
|
||||||
.entry(SkillType::Fuck)
|
.entry(SkillType::Share)
|
||||||
.and_modify(|sk| *sk += sen * 0.5)
|
.and_modify(|sk| *sk += sen * 0.5)
|
||||||
.or_insert(sen * 0.5);
|
.or_insert(sen * 0.5);
|
||||||
target_item
|
target_item
|
||||||
.total_skills
|
.total_skills
|
||||||
.entry(SkillType::Fuck)
|
.entry(SkillType::Share)
|
||||||
.and_modify(|sk| *sk += end * 0.5)
|
.and_modify(|sk| *sk += end * 0.5)
|
||||||
.or_insert(end * 0.5);
|
.or_insert(end * 0.5);
|
||||||
target_item
|
target_item
|
||||||
|
@ -56,7 +56,7 @@ pub fn npc_list() -> Vec<NPC> {
|
|||||||
message_handler: None,
|
message_handler: None,
|
||||||
wander_zones: vec!("melbs".to_owned()),
|
wander_zones: vec!("melbs".to_owned()),
|
||||||
says: vec!(melbs_citizen_stdsay.clone()),
|
says: vec!(melbs_citizen_stdsay.clone()),
|
||||||
player_consents: vec!(ConsentType::Medicine, ConsentType::Sex),
|
player_consents: vec!(ConsentType::Medicine, ConsentType::Share),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
).collect()
|
).collect()
|
||||||
|
@ -104,7 +104,7 @@ fn points_left(user: &User) -> f64 {
|
|||||||
(62 - (brn + sen + brw + refl + end + col) as i16).max(0) as f64
|
(62 - (brn + sen + brw + refl + end + col) as i16).max(0) as f64
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_action_text(session: &Session, user: &User, item: &Item) -> String {
|
fn next_action_text(_session: &Session, user: &User, item: &Item) -> String {
|
||||||
let brn = user
|
let brn = user
|
||||||
.raw_stats
|
.raw_stats
|
||||||
.get(&StatType::Brains)
|
.get(&StatType::Brains)
|
||||||
@ -156,13 +156,12 @@ fn next_action_text(session: &Session, user: &User, item: &Item) -> String {
|
|||||||
are: ").to_owned() + &summary,
|
are: ").to_owned() + &summary,
|
||||||
StatbotState::Senses => format!(ansi!(
|
StatbotState::Senses => format!(ansi!(
|
||||||
"Your next job is to choose how good your senses will be. Senses help your \
|
"Your next job is to choose how good your senses will be. Senses help your \
|
||||||
appraise, dodge, focus,{} scavenge, sneak, throw, track and whips skills.\n\
|
appraise, dodge, focus, scavenge, share knowledge, sneak, throw, track and \
|
||||||
|
whips skills.\n\
|
||||||
\tType <green><bold>-statbot senses 8<reset><blue> (or any other number) to \
|
\tType <green><bold>-statbot senses 8<reset><blue> (or any other number) to \
|
||||||
set your senses to that number. You will be able to adjust your stats by \
|
set your senses to that number. You will be able to adjust your stats by \
|
||||||
sending me the new value, up until you leave here. Your stats now are: {}"),
|
sending me the new value, up until you leave here. Your stats now are: {}"),
|
||||||
if session.less_explicit_mode {
|
&summary),
|
||||||
""
|
|
||||||
} else { " fuck,"}, &summary),
|
|
||||||
StatbotState::Brawn => ansi!(
|
StatbotState::Brawn => ansi!(
|
||||||
"Your next job is to choose how strong you will be. Brawn helps your \
|
"Your next job is to choose how strong you will be. Brawn helps your \
|
||||||
clubs, fists, and throw skills.\n\
|
clubs, fists, and throw skills.\n\
|
||||||
@ -180,11 +179,11 @@ fn next_action_text(session: &Session, user: &User, item: &Item) -> String {
|
|||||||
).to_owned() + &summary,
|
).to_owned() + &summary,
|
||||||
StatbotState::Endurance => format!(ansi!(
|
StatbotState::Endurance => format!(ansi!(
|
||||||
"Your next job is to choose how much stamina you will have. Endurance helps \
|
"Your next job is to choose how much stamina you will have. Endurance helps \
|
||||||
your climb, fish, fists, focus,{} scavenge, spears and swim skills.\n\
|
your climb, fish, fists, focus, scavenge, share knowledge, spears and swim skills.\n\
|
||||||
\tType <green><bold>-statbot endurance 8<reset><blue> (or any other number) to \
|
\tType <green><bold>-statbot endurance 8<reset><blue> (or any other number) to \
|
||||||
set your endurance to that number. You will be able to adjust your stats by \
|
set your endurance to that number. You will be able to adjust your stats by \
|
||||||
sending me the new value, up until you leave here. Your stats now are: {}"
|
sending me the new value, up until you leave here. Your stats now are: {}"
|
||||||
), if session.less_explicit_mode { "" } else { " fuck,"}, &summary),
|
), &summary),
|
||||||
StatbotState::Cool => ansi!(
|
StatbotState::Cool => ansi!(
|
||||||
"Your next job is to choose how much you keep your cool under pressure. \
|
"Your next job is to choose how much you keep your cool under pressure. \
|
||||||
Cool helps your blades, bombs, fish, pistols, quickdraw, rifles, sneak \
|
Cool helps your blades, bombs, fish, pistols, quickdraw, rifles, sneak \
|
||||||
|
Loading…
Reference in New Issue
Block a user