From b06f045d10fcfee5a85620063a4ea896b3192124 Mon Sep 17 00:00:00 2001 From: Condorra Date: Wed, 11 Oct 2023 22:51:00 +1100 Subject: [PATCH] Move help to separate YAML file. --- .../src/message_handler/user_commands/help.rs | 350 ++++-------------- .../user_commands/help/always.yaml | 3 + .../user_commands/help/explicit.yaml | 20 + .../user_commands/help/registered.yaml | 202 ++++++++++ .../user_commands/help/unregistered.yaml | 12 + blastmud_game/src/static_content.rs | 4 +- blastmud_game/src/static_content/npc.rs | 14 +- .../npc/computer_museum_npcs.yaml | 12 +- 8 files changed, 316 insertions(+), 301 deletions(-) create mode 100644 blastmud_game/src/message_handler/user_commands/help/always.yaml create mode 100644 blastmud_game/src/message_handler/user_commands/help/explicit.yaml create mode 100644 blastmud_game/src/message_handler/user_commands/help/registered.yaml create mode 100644 blastmud_game/src/message_handler/user_commands/help/unregistered.yaml diff --git a/blastmud_game/src/message_handler/user_commands/help.rs b/blastmud_game/src/message_handler/user_commands/help.rs index 7fcac94e..6cda1e79 100644 --- a/blastmud_game/src/message_handler/user_commands/help.rs +++ b/blastmud_game/src/message_handler/user_commands/help.rs @@ -1,293 +1,42 @@ +use std::collections::BTreeMap; + use super::{CommandHandlingError::UserError, UResult, UserVerb, UserVerbRef, VerbContext}; -use ansi::ansi; +use ansi_markup::parse_ansi_markup; use async_trait::async_trait; -use phf::phf_map; +use once_cell::sync::OnceCell; +use serde_yaml::from_str as from_yaml_str; -static ALWAYS_HELP_PAGES: phf::Map<&'static str, &'static str> = phf_map! { - "" => - ansi!("You are supposed to replace topicname> with the topic you want \ - to learn about. Example:\n\ - \thelp register will tell you about the register command.") -}; +fn load_help_yaml(input: &str) -> BTreeMap { + let mut map: BTreeMap = from_yaml_str(input).unwrap(); + for val in map.values_mut() { + *val = parse_ansi_markup(val).unwrap(); + } + map +} -static UNREGISTERED_HELP_PAGES: phf::Map<&'static str, &'static str> = phf_map! { - "" => - ansi!("Type help topicname> to learn about a topic. Most \ - commands can be used as a topicname.\n\ - Topics of interest to unregistered users:\n\ - \tregister\tLearn about the register command.\n\ - \tlogin\tLearn how to log in as an existing user.\n"), - "register" => - ansi!("Registers a new user. You are allowed at most 5 at once.\n\ - \tregister username> password> email>\n\ - Email will be used to check you don't have too many accounts and \ - in case you need to reset your password."), - "login" => - ansi!("Logs in as an existing user.\n\ - \tlogin username> password") -}; +fn always_help_pages() -> &'static BTreeMap { + static CELL: OnceCell> = OnceCell::new(); -static REGISTERED_HELP_PAGES: phf::Map<&'static str, &'static str> = phf_map! { - "" => - ansi!("Type help topicname> to learn about a topic. Most \ - commands can be used as a topicname.\n\ - Topics of interest:\n\ - \tnewbie\tLearn the absolute basics.\n\ - \tmovement\tCommands for moving around.\n\ - \tpossessions\tCommands for dealing with possessions / weapons.\n\ - \ttalk\tFind out how to talk in the game.\n\ - \tcombat\tLearn how to fight.\n\ - \tinformation\tLearn how to find out about the world and your character."), - "newbie" => - ansi!("So you've just landed in BlastMud, and want to know how to get started?\n\ - You control your character, and can tell your character to move around the\n\ - world, and see things through their eyes.\n\ - The world (yes, even outside!) is divided up into rooms, and each room has\n\ - exits that you are allowed to take, normally called north, south, east, west,\n\ - northeast, northwest, southeast, southwest, up and down (sometimes you can also go in).\n\ - \n\ - Try look (or l) to look at the current room. It will\n\ - also show you all the exits you can take, and a little ASCII-art map showing \n\ - the local layout. lmap shows you a more detailed map showing the\n\ - directions you can move in. You can also look at objects or players with \n\ - l followed by the name of the object (shortening is okay).\n\ - Once you know what direction to move, you can type the direction, using either\n\ - the full name of the direction (e.g. northeast or south,\n\ - or a short form (n, e, s, w, ne, nw, se, sw, up, down).\n\n\ - Also try the map commands - lmap for a local map including exits, and gmap for a giant \ - map to let you see the broader context."), - "movement" => - ansi!("Once you know what direction to move, you can type the direction, using either\n\ - the full name of the direction (e.g. northeast or south,\n\ - or a short form (n, e, s, w, ne, nw, se, sw, up, down)."), - "look" => - ansi!("Try look or l to look at the current room. Follow it with the \ - name of an exit to look at an adjacent room. Or name an object or player in the room to look \ - at that."), - "combat" => - ansi!("Type kill character or k character to attack a character. \ - If their health points hits zero, they die. If your health points hit zero, you die. \ - Note that characters can reclone so death isn't fully permanent (see help death). \ - Combat depends on your ability to dodge the enemy's attacks (based on your dodge skill), \ - your armour's ability to soak their attacks, and the skill in the weapon you are wielding \ - - and of course the same factors for your opponents. \ - You can only attack one character at a time, but more than one can gang up on you! \ - When you fight, you might notice you improve at your skills (see help skills), \ - and also gain more experience. You gain more skills using a weapon matched to your current \ - experience level, and more experience fighting harder opponents - but if you take on someone \ - too tough, you might die and lose experience recloning! \ - Remember, you can always (at least while you are not dead) try to run away from combat by just \ - by using movement commands (see help movement - but if your dodge skill isn't high \ - enough, it might fail."), - "death" => - ansi!("In Blastmud, you can die if your health points reach zero. While you are dead, you can't \ - move or talk! Unless someone quickly comes and uses a defibrilator on you, your current \ - body is gone. Luckily, thanks to residual Gazos-Murlison technology that survived the \ - fall of the empire, you can still re-clone into a new body. However, this has some \ - downsides: you lose a bit of your experience in the process, and anything you had on your \ - person stays with the corpse of your old body! So it is certainly worth trying not to die!"), - "skills" => - ansi!( - "Blastmud has lots of different skills that you can learn. There are two different \ - measures of a skill. Total skill is how good you are in absolute terms - you get some skill from your stats, \ - and some from your raws. Raw skill is how much you have improved by learning the skill as you \ - play the game. Your raw skill caps out at 15 per skill, and adds on to the contribution from \ - your stats, and any temporary buffs or debuffs caused by your character's state."), - "information" => - ansi!( - "Commands to examine the world:\n\ - \tlook (or l) to look around - follow it with an exit or\n\ - \t\ta character / item name for detail on that.\n\ - \tlmap - get a map showing exits and places."), - "talk" => TALK_HELP, - "say" => TALK_HELP, - "whisper" => TALK_HELP, - "page" => TALK_HELP, - "reply" => TALK_HELP, - "possessions" => - ansi!("Use:\n\ - \tget item to pick something up from the ground.\n\ - \tdrop item to drop something from your inventory.\n\ - \tinv to see what you are holding.\n\ - \tbuy item to buy something from the shop you are in.\n\ - \tlist to see the price list for the stop.\n\ - \twield to hold a weapon in your inventory for use when you attack.\n\ - \tgear to see what you are wearing, and how much protection it offers.\n\ - Hint: get and drop support an item name, but you can also prefix it \ - with a number - e.g. get 2 whip. Instead of a number, you can \ - use all. You can also omit the item name to match any \ - possession, e.g. drop all will drop everything you have."), - "allow" => - ansi!("allow 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: fight (for hostile actions like \ - attack or pick), medicine (for medical actions, including those that might \ - crit fail and do harm), gifts (lets them give you things), and \ - visit (lets them on to a tile owned by you legally).\n\ - \n\ - To allow, as an individual, use the syntax allow type from player options\n\ - As a corp, use the syntax allow type against corpname by corpname options\n\ - Options can be blank to use defaults, or can be one or more of the following, separated by spaces:\n\ - \tfor n minutes - 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.\n\ - \tuntil death - makes the consent valid only until you next die.\n\ - \tallow private - makes the consent valid even in privately owned places. This is the default for anything except fight.\n\ - \tdisallow private - the opposite of allow private.\n\ - \tin place - limits where fighting can happen to selected public places. You can use \ - here, 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).\n\ - \tallow pick - fight only - include picking in your consent.\n\ - \tallow revoke - fight only - allows the player to revoke any time with disallow.\n\ - \n\ - Consents for anything except fight take effect immediately to let the other player do the action.\n\ - Consents for fight take effect when the other player executes a reciprocal allow command.\n\ - Consents for anything except than fight can be revoked instantly with:\n\ - \tdisallow action from player\n\ - Consent for fight can be revoked similarly if the consent used the allow revoke option. \ - Otherwise, attempting to revoke informs the other player, and it is revoked when they also issue a \ - disallow command."), - "corp" => - ansi!("corp is the entry point to commands related to corps. It supports the following subcommands:\n\ - \tcorp hire username into corpname\n\t\tHires a player into your corp.\n\ - \tcorp join corpname\n\t\tAccepts an offer to hire you.\n\ - \tcorp list\n\t\tList the corps you belong to.\n\ - \tcorp leave corpname\n\t\tResign from a corp.\n\ - \tcorp fire username from corpname\n\t\tFires a player from your corp.\n\ - \tcorp promote username in corpname to title privileges privileges\n\ - \t\tPromotes/demotes a player within your corp.\n\ - \tcorp info corpname\n\t\tGet information about a corp.\n\ - \tcorp allow combat\n\t\tAllow the corp to consent to combat on your behalf.\n\ - \tcorp disallow combat\n\t\tDon't allow the corp to consent to combat on your behalf.\n\ - \tcorp config corpname setting\n\t\tConfigure corp settings.\n\ - \tcorp sub type from corpname\n\ - \t\t\tSubscribe to corp broadcasts.\n\ - \tcorp unsub type from corpname\n\ - \t\tUnsubscribe from corp broadcasts.\n\ - \tcorp order corpname as number\n\ - \t\tSet the position of the corp in your list.\n\ - Help is available for many individual corp commands, e.g. try help corp hire"), - "corp hire" => - ansi!("corp hire username into corpname\tHires a player into your corp."), - "corp join" => - ansi!("corp join corpname\tAccepts an offer to hire you."), - "corp list" => - ansi!("corp list\tList the corps you belong to."), - "corp leave" => - ansi!("corp leave corpname\tResign from a corp."), - "corp fire" => - ansi!("corp fire username from corpname\tFires a player from your corp."), - "corp promote" => - ansi!("corp promote username in corpname to title privileges privileges\n\ - Promotes or demotes a player to a specific title within a corp, and modifies their privileges.\n\ - username - the player you want to promote.\n\ - corpname - the name of the corporation you want to promote the player within.\n\ - title - the title you want to assign to the player.\n\ - privileges - the privileges you want to grant or remove from the player, prefixed with + or - \ - respectively, separated by spaces.\n\ - The following privileges exist:\n\ - \tholder - The owner of the corp (implies all other privileges).\n\ - \thire - Can hire new people into the corp.\n\ - \tfire - Can fire people from the corp.\n\ - \tpromote - Can promote/demote people.\n\ - \twar - Can declare war against other corps on behalf of the corp.\n\ - \tconfigure - Can change the settings of the corp.\n\ - \tfinance - Can access (or embezzle!) the corp’s funds."), - "corp info" => - ansi!("corp info corpname\tGet information about a corp."), - "corp allow combat" => - ansi!("corp allow combat\tAllow the corp to consent to combat on your behalf."), - "corp disallow combat" => - ansi!("corp disallow combat\tDon't allow the corp to consent to combat on your behalf."), - "corp config" => - ansi!("corp config corpname setting\n\ - \tConfigure various settings for your corp, such as member privileges and combat consent requirements.\n\ - \tcorpname - the name of your corp.\n\ - \tsetting - one of the following options:\n\ - \t\tallow combat required - Requires that all new members have the allow combat setting.\n\ - \t\tallow combat not required - Stops requiring that new members have allow combat on.\n\ - \t\tbase privileges privilege_name privilege_name - Sets the privileges that new members \ - receive when they join the corporation. See help corp promote for privileges."), - "corp sub" => - ansi!("corp sub type from corpname\n\ - Subscribes to corp broadcasts. Type is one of:\n\ - \tchat - Messages from users.\n\ - \tnotice - Important corp notices.\n\ - \tconnect - Connecting players.\n\ - \treward - Rewards paid to the corp.\n\ - \tdeath - Deaths of players in the corp.\n\ - \tconsent - Changes to corp consents (war declarations)."), - "corp unsub" => - ansi!("corp unsub type from corpname\n\ - Unsubscribe from corp broadcasts. Type is one of:\n\ - \tchat - Messages from users.\n\ - \tnotice - Important corp notices.\n\ - \tconnect - Connecting players.\n\ - \treward - Rewards paid to the corp.\n\ - \tdeath - Deaths of players in the corp.\n\ - \tconsent - Changes to corp consents (war declarations)."), - "corp order" => - ansi!("corp order corpname as number\tSet the position of the corp in your list."), - "install" => - ansi!("install item on door to direction\tInstalls hardware such as a lock on a door."), - "uninstall" => - ansi!("uninstall item from door to direction\tRemoves installed hardware such as a lock on a door."), - "gear" => ansi!("gear\tSee equipment you have on, and what protection it offers you."), - "delete" => ansi!("Delete is the most destructive command in the game - used to reset your character, or even give it up \ - forever. All commands below echo out a command including a single-use command you can use to confirm the \ - command - they don't take effect without the code. This prevents accidentally pasting in dangerous commands.\n\ - delete character forever\tDestroy your character permanently. The command starts a one week \ - countdown at the end of which your account and character (and anything in their possession) are permanently \ - destroyed (as in we irreversibly wipe your data from the server), and any places you are renting get evicted. \ - The command disconnects you immediately. If you reconnect and log in again within the week, \ - the countdown is stopped and the deletion aborted. After the one week, anyone can register again with the \ - same username. At the end of the week, when your character is destroyed, it no longer counts towards the limit \ - of 5 usernames per person.\n\ - delete stats\tKills your character instantly (leaving anything you are carrying on your corpse) \ - and sends you back to the choice room to pick new stats. Any XP gained, apart from XP from journals, is reset \ - back to 0.") -}; + CELL.get_or_init(|| load_help_yaml(include_str!("help/always.yaml"))) +} -static EXPLICIT_HELP_PAGES: phf::Map<&'static str, &'static str> = phf_map! { - "fuck" => - ansi!("Type fuck name> to fuck someone. It only works if \ - they have consented."), - "allow" => - ansi!("allow 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: fight (for hostile actions like \ - attack or pick), medicine (for medical actions, including those that might \ - crit fail and do harm), gifts (lets them give you things), \ - visit (lets them on to a tile owned by you legally), and fuck \ - (lets them do fun but dirty things to you).\n\ - \n\ - To allow, as an individual, use the syntax allow type from player options\n\ - As a corp, use the syntax allow type against corpname by corpname options\n\ - Options can be blank to use defaults, or can be one or more of the following, separated by spaces:\n\ - \tuntil n minutes - 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.\n\ - \tuntil death - makes the consent valid only until you next die.\n\ - \tallow private - makes the consent valid even in privately owned places. This is the default for anything except fight.\n\ - \tdisallow private - the opposite of allow private.\n\ - \tin place - limits where fighting can happen to selected public places. You can use \ - here, 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).\n\ - \tallow pick - fight only - include picking in your consent.\n\ - \tallow revoke - fight only - allows the player to revoke any time with disallow.\n\ - \n\ - Consents for anything except fight take effect immediately to let the other player do the action.\n\ - Consents for fight take effect when the other player executes a reciprocal allow command.\n\ - Consents for anything except than fight can be revoked instantly with:\n\ - \tdisallow action from player\n\ - Consent for fight can be revoked similarly if the consent used the allow revoke option. \ - Otherwise, attempting to revoke informs the other player, and it is revoked when they also issue a \ - disallow command."), -}; +fn registered_help_pages() -> &'static BTreeMap { + static CELL: OnceCell> = OnceCell::new(); -static TALK_HELP: &'static str = ansi!( - "Use:\n\ - \t'message to send message to the room.\n\ - \t-user message to whisper to someone.\n\ - \tp user message to page someone on your wristpad.\n\ - \treply message to page back the last person to page you." -); + CELL.get_or_init(|| load_help_yaml(include_str!("help/registered.yaml"))) +} + +fn unregistered_help_pages() -> &'static BTreeMap { + static CELL: OnceCell> = OnceCell::new(); + + CELL.get_or_init(|| load_help_yaml(include_str!("help/unregistered.yaml"))) +} + +fn explicit_help_pages() -> &'static BTreeMap { + static CELL: OnceCell> = OnceCell::new(); + + CELL.get_or_init(|| load_help_yaml(include_str!("help/explicit.yaml"))) +} pub struct Verb; #[async_trait] @@ -305,20 +54,45 @@ impl UserVerb for Verb { }; let remaining = remaining.trim(); if is_unregistered { - help = help.or_else(|| UNREGISTERED_HELP_PAGES.get(remaining)); + help = help.or_else(|| unregistered_help_pages().get(remaining)); } 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 = explicit_help_pages().get(remaining).or(help); } } - help = help.or_else(|| ALWAYS_HELP_PAGES.get(remaining)); + 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()))?; ctx.trans - .queue_for_session(ctx.session, Some(&(help_final.to_string() + "\n"))) + .queue_for_session(ctx.session, Some(&(help_final.clone() + "\n"))) .await?; Ok(()) } } static VERB_INT: Verb = Verb; pub static VERB: UserVerbRef = &VERB_INT as UserVerbRef; + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn registered_help_ok() { + registered_help_pages(); + } + + #[test] + fn unregistered_help_ok() { + unregistered_help_pages(); + } + + #[test] + fn always_help_ok() { + always_help_pages(); + } + + #[test] + fn explicit_help_ok() { + explicit_help_pages(); + } +} diff --git a/blastmud_game/src/message_handler/user_commands/help/always.yaml b/blastmud_game/src/message_handler/user_commands/help/always.yaml new file mode 100644 index 00000000..0c1a8658 --- /dev/null +++ b/blastmud_game/src/message_handler/user_commands/help/always.yaml @@ -0,0 +1,3 @@ +"": |- + You are supposed to replace topicname> with the topic you want to learn about. Example: + help register will tell you about the register command. diff --git a/blastmud_game/src/message_handler/user_commands/help/explicit.yaml b/blastmud_game/src/message_handler/user_commands/help/explicit.yaml new file mode 100644 index 00000000..6fc9882a --- /dev/null +++ b/blastmud_game/src/message_handler/user_commands/help/explicit.yaml @@ -0,0 +1,20 @@ +fuck: "Type fuck name> to fuck someone. It only works if they have consented." +allow: |- + allow 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: fight (for hostile actions like attack or pick), medicine (for medical actions, including those that might crit fail and do harm), gifts (lets them give you things), visit (lets them on to a tile owned by you legally), and fuck (lets them do fun but dirty things to you). + + To allow, as an individual, use the syntax allow type from player options + As a corp, use the syntax allow type against corpname by corpname options + Options can be blank to use defaults, or can be one or more of the following, separated by spaces: + until n minutes - 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. + until death - makes the consent valid only until you next die. + allow private - makes the consent valid even in privately owned places. This is the default for anything except fight. + disallow private - the opposite of allow private. + in place - limits where fighting can happen to selected public places. You can use here, 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). + allow pick - fight only - include picking in your consent. + allow revoke - 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: + disallow action from player + Consent for fight can be revoked similarly if the consent used the allow revoke option. Otherwise, attempting to revoke informs the other player, and it is revoked when they also issue a disallow command. diff --git a/blastmud_game/src/message_handler/user_commands/help/registered.yaml b/blastmud_game/src/message_handler/user_commands/help/registered.yaml new file mode 100644 index 00000000..0efe3fbb --- /dev/null +++ b/blastmud_game/src/message_handler/user_commands/help/registered.yaml @@ -0,0 +1,202 @@ +"": |- + Type help topicname> to learn about a topic. Most commands can be used as a topicname. + Topics of interest: + newbie Learn the absolute basics. + movement Commands for moving around. + possessions Commands for dealing with possessions / weapons. + talk Find out how to talk in the game. + combat Learn how to fight. + information Learn how to find out about the world and your character. +newbie: |- + So you've just landed in Blastmud, and want to know how to get started? + You control your character, and can tell your character to move around the + world, and see things through their eyes. + The world (yes, even outside!) is divided up into rooms, and each room has + exits that you are allowed to take, normally called north, south, east, west, + northeast, northwest, southeast, southwest, up and down (sometimes you can also go in). + + Try look (or l) to look at the current room. It will + also show you all the exits you can take, and a little ASCII-art map showing + the local layout. lmap shows you a more detailed map showing the + directions you can move in. You can also look at objects or players with + l followed by the name of the object (shortening is okay). + Once you know what direction to move, you can type the direction, using either + the full name of the direction (e.g. northeast or south, + or a short form (n, e, s, w, ne, nw, se, sw, up, down). + + Also try the map commands - lmap for a local map including exits, and gmap for a giant + map to let you see the broader context. +movement: |- + Once you know what direction to move, you can type the direction, using either + the full name of the direction (e.g. northeast or south, + or a short form (n, e, s, w, ne, nw, se, sw, up, down). +look: Try look or l to look at the current room. Follow it with the name of an exit to look at an adjacent room. Or name an object or player in the room to look at that. +combat: >- + Type kill character or k character to attack a character. + If their health points hits zero, they die. If your health points hit zero, you die. + Note that characters can reclone so death isn't fully permanent (see help death). + Combat depends on your ability to dodge the enemy's attacks (based on your dodge skill), + your armour's ability to soak their attacks, and the skill in the weapon you are wielding + - and of course the same factors for your opponents. + You can only attack one character at a time, but more than one can gang up on you! + When you fight, you might notice you improve at your skills (see help skills), + and also gain more experience. You gain more skills using a weapon matched to your current + experience level, and more experience fighting harder opponents - but if you take on someone + too tough, you might die and lose experience recloning! + Remember, you can always (at least while you are not dead) try to run away from combat by just + by using movement commands (see help movement - but if your dodge skill isn't high + enough, it might fail. +death: >- + In Blastmud, you can die if your health points reach zero. While you are dead, you can't + move or talk! Unless someone quickly comes and uses a defibrilator on you, your current + body is gone. Luckily, thanks to residual Gazos-Murlison technology that survived the + fall of the empire, you can still re-clone into a new body. However, this has some + downsides: you lose a bit of your experience in the process, and anything you had on your + person stays with the corpse of your old body! So it is certainly worth trying not to die! +skills: >- + Blastmud has lots of different skills that you can learn. There are two different + measures of a skill. Total skill is how good you are in absolute terms - you get some skill from your stats, + and some from your raws. Raw skill is how much you have improved by learning the skill as you + play the game. Your raw skill caps out at 15 per skill, and adds on to the contribution from + your stats, and any temporary buffs or debuffs caused by your character's state. +information: |- + Commands to examine the world: + look (or l) to look around - follow it with an exit or + a character / item name for detail on that. + lmap - get a map showing exits and places. +talk: &talk |- + Use: + 'message to send message to the room. + -user message to whisper to someone. + p user message to page someone on your wristpad. + reply message to page back the last person to page you. +say: *talk +whisper: *talk +page: *talk +reply: *talk +possessions: &possessions |- + Use: + get item to pick something up from the ground. + drop item to drop something from your inventory. + inv to see what you are holding. + buy item to buy something from the shop you are in. + list to see the price list for the stop. + wield to hold a weapon in your inventory for use when you attack. + gear to see what you are wearing, and how much protection it offers. + Hint: get and drop support an item name, but you can also prefix it with a number - e.g. get 2 whip. Instead of a number, you can use all. You can also omit the item name to match any possession, e.g. drop all will drop everything you have. +get: *possessions +drop: *possessions +inv: *possessions +inventory: *possessions +buy: *possessions +list: *possessions +wield: *possessions +gear: *possessions +allow: |- + allow 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: fight (for hostile actions like attack or pick), medicine (for medical actions, including those that might crit fail and do harm), gifts (lets them give you things), and visit (lets them on to a tile owned by you legally). + + To allow, as an individual, use the syntax allow type from player options + As a corp, use the syntax allow type against corpname by corpname options + Options can be blank to use defaults, or can be one or more of the following, separated by spaces: + for n minutes - 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. + until death - makes the consent valid only until you next die. + allow private - makes the consent valid even in privately owned places. This is the default for anything except fight. + disallow private - the opposite of allow private. + in place - limits where fighting can happen to selected public places. You can use + here, 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). + allow pick - fight only - include picking in your consent. + allow revoke - 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: + disallow action from player + Consent for fight can be revoked similarly if the consent used the allow revoke option. + Otherwise, attempting to revoke informs the other player, and it is revoked when they also issue a disallow command. +corp: |- + corp is the entry point to commands related to corps. It supports the following subcommands: + corp hire username into corpname + Hires a player into your corp. + corp join corpname + Accepts an offer to hire you. + corp list + List the corps you belong to. + corp leave corpname + Resign from a corp. + corp fire username from corpname + Fires a player from your corp. + corp promote username in corpname to title privileges privileges + Promotes/demotes a player within your corp. + corp info corpname + Get information about a corp. + corp allow combat + Allow the corp to consent to combat on your behalf. + corp disallow combat + Don't allow the corp to consent to combat on your behalf. + corp config corpname setting + Configure corp settings. + corp sub type from corpname + Subscribe to corp broadcasts. + corp unsub type from corpname + Unsubscribe from corp broadcasts. + corp order corpname as number + Set the position of the corp in your list. + Help is available for many individual corp commands, e.g. try help corp hire +"corp hire": "corp hire username into corpname Hires a player into your corp." +"corp join": "corp join corpname Accepts an offer to hire you." +"corp list": "corp list List the corps you belong to." +"corp leave": &corp-leave "corp leave corpname Resign from a corp." +"corp resign": *corp-leave +"corp fire": "corp fire username from corpname Fires a player from your corp." +"corp promote": |- + corp promote username in corpname to title privileges privileges + Promotes or demotes a player to a specific title within a corp, and modifies their privileges. + username - the player you want to promote. + corpname - the name of the corporation you want to promote the player within. + title - the title you want to assign to the player. + privileges - the privileges you want to grant or remove from the player, prefixed with + or - respectively, separated by spaces. + The following privileges exist: + holder - The owner of the corp (implies all other privileges). + hire - Can hire new people into the corp. + fire - Can fire people from the corp. + promote - Can promote/demote people. + war - Can declare war against other corps on behalf of the corp. + configure - Can change the settings of the corp. + finance - Can access (or embezzle!) the corp’s funds. +"corp info": "corp info corpname Get information about a corp." +"corp allow combat": "corp allow combat Allow the corp to consent to combat on your behalf." +"corp disallow combat": "corp disallow combat Don't allow the corp to consent to combat on your behalf." +"corp config": |- + corp config corpname setting + Configure various settings for your corp, such as member privileges and combat consent requirements. + corpname - the name of your corp. + setting - one of the following options: + allow combat required - Requires that all new members have the allow combat setting. + allow combat not required - Stops requiring that new members have allow combat on. + base privileges privilege_name privilege_name - Sets the privileges that new members receive when they join the corporation. See help corp promote for privileges. +"corp sub": |- + corp sub type from corpname + Subscribes to corp broadcasts. Type is one of: + chat - Messages from users. + notice - Important corp notices. + connect - Connecting players. + reward - Rewards paid to the corp. + death - Deaths of players in the corp. + consent - Changes to corp consents (war declarations). +"corp unsub": |- + corp unsub type from corpname + Unsubscribe from corp broadcasts. Type is one of: + chat - Messages from users. + notice - Important corp notices. + connect - Connecting players. + reward - Rewards paid to the corp. + death - Deaths of players in the corp. + consent - Changes to corp consents (war declarations). +"corp order": "corp order corpname as number Set the position of the corp in your list." +"install": "install item on door to direction Installs hardware such as a lock on a door." +"uninstall": "uninstall item from door to direction Removes installed hardware such as a lock on a door." +"gear": "gear See equipment you have on, and what protection it offers you." +"delete": |- + Delete is the most destructive command in the game - used to reset your character, or even give it up forever. All commands below echo out a command including a single-use command you can use to confirm the command - they don't take effect without the code. This prevents accidentally pasting in dangerous commands. + delete character forever Destroy your character permanently. The command starts a one week countdown at the end of which your account and character (and anything in their possession) are permanently destroyed (as in we irreversibly wipe your data from the server), and any places you are renting get evicted. The command disconnects you immediately. If you reconnect and log in again within the week, the countdown is stopped and the deletion aborted. After the one week, anyone can register again with the same username. At the end of the week, when your character is destroyed, it no longer counts towards the limit of 5 usernames per person. + delete stats Kills your character instantly (leaving anything you are carrying on your corpse) and sends you back to the choice room to pick new stats. Any XP gained, apart from XP from journals, is reset back to 0. diff --git a/blastmud_game/src/message_handler/user_commands/help/unregistered.yaml b/blastmud_game/src/message_handler/user_commands/help/unregistered.yaml new file mode 100644 index 00000000..155b8695 --- /dev/null +++ b/blastmud_game/src/message_handler/user_commands/help/unregistered.yaml @@ -0,0 +1,12 @@ +"": |- + Type help topicname> to learn about a topic. Most commands can be used as a topicname. + Topics of interest to unregistered users: + register\tLearn about the register command. + login\tLearn how to log in as an existing user. +register: |- + Registers a new user. You are allowed at most 5 at once. + register username> password> email> + Email will be used to check you don't have too many accounts and in case you need to reset your password. +login: |- + Logs in as an existing user. + login username> password diff --git a/blastmud_game/src/static_content.rs b/blastmud_game/src/static_content.rs index fb4d54ee..2a9951a8 100644 --- a/blastmud_game/src/static_content.rs +++ b/blastmud_game/src/static_content.rs @@ -212,8 +212,8 @@ mod test { for type_group in registry.iter() { let iterator: Box> = (type_group.things)(); - let duplicates: Vec<&'static str> = iterator - .group_by(|x| x.item_code) + let duplicates: Vec = iterator + .group_by(|x| x.item_code.clone()) .into_iter() .filter_map(|(k, v)| if v.count() <= 1 { None } else { Some(k) }) .collect(); diff --git a/blastmud_game/src/static_content/npc.rs b/blastmud_game/src/static_content/npc.rs index 2dda7930..26afab56 100644 --- a/blastmud_game/src/static_content/npc.rs +++ b/blastmud_game/src/static_content/npc.rs @@ -182,7 +182,8 @@ pub fn npc_list() -> &'static Vec { code: "repro_xv_chargen_statbot".to_owned(), name: "Statbot".to_owned(), description: - "A silvery shiny metal mechanical being. It lets out a whirring sound as it moves.".to_owned(), + "A silvery shiny metal mechanical being. It lets out a whirring sound as it moves." + .to_owned(), spawn_location: "room/repro_xv_chargen".to_owned(), message_handler: Some(&statbot::StatbotMessageHandler), says: vec![], @@ -198,7 +199,12 @@ pub fn npc_list() -> &'static Vec { pub fn npc_by_code() -> &'static BTreeMap<&'static str, &'static NPC> { static NPC_CODE_MAP: OnceCell> = OnceCell::new(); - NPC_CODE_MAP.get_or_init(|| npc_list().iter().map(|npc| (npc.code.as_str(), npc)).collect()) + NPC_CODE_MAP.get_or_init(|| { + npc_list() + .iter() + .map(|npc| (npc.code.as_str(), npc)) + .collect() + }) } pub fn npc_say_info_by_npc_code_say_code( @@ -481,9 +487,7 @@ impl TaskHandler for NPCWanderTaskHandler { } let ex_iter = room.exits.iter().filter(|ex| { resolve_exit(room, ex) - .map(|new_room| { - npc.wander_zones.contains(&new_room.zone) && !new_room.repel_npc - }) + .map(|new_room| npc.wander_zones.contains(&new_room.zone) && !new_room.repel_npc) .unwrap_or(false) }); let dir_opt = ex_iter diff --git a/blastmud_game/src/static_content/npc/computer_museum_npcs.yaml b/blastmud_game/src/static_content/npc/computer_museum_npcs.yaml index 4ac54113..91d1f062 100644 --- a/blastmud_game/src/static_content/npc/computer_museum_npcs.yaml +++ b/blastmud_game/src/static_content/npc/computer_museum_npcs.yaml @@ -1,26 +1,26 @@ -- Geek: +- !Geek code: "1" adjectives: excited spawn_loc: lobby pronouns: Male -- Geek: +- !Geek code: "2" adjectives: mesmerised spawn_loc: lobby pronouns: Female -- Killbot: +- !Killbot code: "3" adjectives: abhorrent spawn_loc: hw_1 -- Killbot: +- !Killbot code: "4" adjectives: berserk spawn_loc: hw_2 -- Killbot: +- !Killbot code: "5" adjectives: vicious spawn_loc: hw_3 -- Killbot: +- !Killbot code: "6" adjectives: murderous spawn_loc: club_door