Compare commits

..

No commits in common. "cf8ceb1351c0b5ef9b36828b11fdabbba0b44565" and "f7816334ccb7334100609743541948636f40fa6d" have entirely different histories.

23 changed files with 2037 additions and 7340 deletions

1
Cargo.lock generated
View File

@ -126,7 +126,6 @@ dependencies = [
"once_cell",
"ouroboros",
"phf",
"rand",
"ring",
"serde",
"serde_json",

View File

@ -34,4 +34,3 @@ bcrypt = "0.13.0"
validator = "0.16.0"
itertools = "0.10.5"
once_cell = "1.16.0"
rand = "0.8.5"

View File

@ -151,17 +151,6 @@ impl DBPool {
.collect()))
}
pub async fn find_static_task_types(self: &Self) -> DResult<Box<BTreeSet<String>>> {
Ok(Box::new(
self
.get_conn().await?
.query("SELECT DISTINCT details->>'task_type' AS task_type \
FROM tasks WHERE details->>'is_static' = 'true'", &[]).await?
.iter()
.map(|r| r.get("task_type"))
.collect()))
}
pub async fn delete_static_items_by_type(self: &Self, item_type: &str) -> DResult<()> {
self.get_conn().await?.query(
"DELETE FROM items WHERE details->>'is_static' = 'true' AND details->>'item_type' = {}",
@ -169,13 +158,6 @@ impl DBPool {
Ok(())
}
pub async fn delete_static_tasks_by_type(self: &Self, task_type: &str) -> DResult<()> {
self.get_conn().await?.query(
"DELETE FROM tasks WHERE details->>'is_static' = 'true' AND details->>'task_type' = {}",
&[&task_type]).await?;
Ok(())
}
pub async fn get_conn(self: &DBPool) ->
DResult<Object> {
let conn = self.pool.get().await?;
@ -285,7 +267,7 @@ impl DBTrans {
// Only copy more permanent fields, others are supposed to change over time and shouldn't
// be reset on restart.
for to_copy in ["display", "display_less_explicit", "details", "details_less_explicit",
"total_xp", "total_stats", "total_skills", "pronouns", "flags"] {
"total_xp", "total_stats", "total_skills", "pronouns"] {
det_ex = format!("jsonb_set({}, '{{{}}}', ${})", det_ex, to_copy, var_id);
params.push(obj_map.get(to_copy).unwrap_or(&Value::Null));
var_id += 1;
@ -297,29 +279,6 @@ impl DBTrans {
Ok(())
}
pub async fn limited_update_static_task(self: &Self, task: &Task) -> DResult<()> {
let value = serde_json::to_value(task)?;
let obj_map = value.as_object()
.expect("Static task to be object in JSON");
let task_name: &(dyn ToSql + Sync) = &task.details.name();
let mut params: Vec<&(dyn ToSql + Sync)> = vec!(task_name, &task.meta.task_code);
let mut det_ex: String = "details".to_owned();
let mut var_id = 3;
// Only copy more permanent fields, others are supposed to change over time and shouldn't
// be reset on restart. We do reset failure count since the problem may be fixed.
for to_copy in ["recurrence", "consecutive_failure_count", "task_details"] {
det_ex = format!("jsonb_set({}, '{{{}}}', ${})", det_ex, to_copy, var_id);
params.push(obj_map.get(to_copy).unwrap_or(&Value::Null));
var_id += 1;
}
self.pg_trans()?.execute(
&("UPDATE tasks SET details = ".to_owned() + &det_ex +
" WHERE details->>'task_type' = $1 AND details->>'task_code' = $2"),
&params).await?;
Ok(())
}
pub async fn create_user(self: &Self, session: &ListenerSession, user_dat: &User) -> DResult<()> {
self.pg_trans()?.execute("INSERT INTO users (\
username, current_session, current_listener, details\
@ -373,19 +332,6 @@ impl DBTrans {
.collect()))
}
pub async fn find_static_tasks_by_type(self: &Self, task_type: &str) ->
DResult<Box<BTreeSet<String>>> {
Ok(Box::new(
self.pg_trans()?
.query("SELECT DISTINCT details->>'task_code' AS task_code FROM tasks WHERE \
details->>'is_static' = 'true' AND \
details->>'task_type' = $1", &[&task_type])
.await?
.into_iter()
.map(|v| v.get("task_code"))
.collect()))
}
pub async fn delete_static_items_by_code(self: &Self, item_type: &str,
item_code: &str) -> DResult<()> {
self.pg_trans()?.query(
@ -396,16 +342,6 @@ impl DBTrans {
Ok(())
}
pub async fn delete_static_tasks_by_code(self: &Self, task_type: &str,
task_code: &str) -> DResult<()> {
self.pg_trans()?.query(
"DELETE FROM task WHERE details->>'is_static' = 'true' AND \
details->>'task_type' = $1 AND \
details->>'task_code' = $2",
&[&task_type, &task_code]).await?;
Ok(())
}
pub async fn find_item_by_type_code(self: &Self, item_type: &str, item_code: &str) ->
DResult<Option<Arc<Item>>> {
if let Some(item) = self.pg_trans()?.query_opt(
@ -528,7 +464,7 @@ impl DBTrans {
match self.pg_trans()?.query_opt(
"SELECT details FROM tasks WHERE \
CAST(details->>'next_scheduled' AS TIMESTAMPTZ) <= now() \
ORDER BY details->>'next_scheduled' ASC LIMIT 1", &[]
ORDER BY details->>'next_scheduled'", &[]
).await? {
None => Ok(None),
Some(row) => Ok(serde_json::from_value(row.get("details"))?)

View File

@ -15,7 +15,6 @@ mod regular_tasks;
mod models;
mod static_content;
mod language;
mod services;
pub type DResult<T> = Result<T, Box<dyn Error + Send + Sync>>;

View File

@ -21,7 +21,6 @@ pub mod movement;
pub mod parsing;
mod quit;
mod register;
pub mod say;
mod whisper;
pub struct VerbContext<'l> {
@ -101,11 +100,8 @@ static REGISTERED_COMMANDS: UserVerbRegistry = phf_map! {
"look" => look::VERB,
"read" => look::VERB,
"lmap" => map::VERB,
"\'" => say::VERB,
"say" => say::VERB,
"-" => whisper::VERB,
"whisper" => whisper::VERB,
"tell" => whisper::VERB,
};
fn resolve_handler(ctx: &VerbContext, cmd: &str) -> Option<&'static UserVerbRef> {

View File

@ -3,7 +3,7 @@ use super::{VerbContext, UserVerb, UserVerbRef, UResult, UserError, user_error,
use async_trait::async_trait;
use ansi::{ansi, flow_around, word_wrap};
use crate::db::ItemSearchParams;
use crate::models::{item::{Item, LocationActionType, Subattack, ItemFlag}};
use crate::models::{item::{Item, LocationActionType, Subattack}};
use crate::static_content::room::{self, Direction};
use itertools::Itertools;
use std::sync::Arc;
@ -75,9 +75,6 @@ pub async fn describe_room(ctx: &VerbContext<'_>, item: &Item,
}
async fn list_item_contents<'l>(ctx: &'l VerbContext<'_>, item: &'l Item) -> UResult<String> {
if item.flags.contains(&ItemFlag::NoSeeContents) {
return Ok(" It is too foggy to see who or what else is here.".to_owned());
}
let mut buf = String::new();
let mut items = ctx.trans.find_items_by_location(&format!("{}/{}",
item.item_type, item.item_code)).await?;

View File

@ -5,44 +5,15 @@ use super::{
};
use async_trait::async_trait;
use crate::{
DResult,
regular_tasks::queued_command::{
QueueCommandHandler,
QueueCommand,
queue_command
},
static_content::room::{self, Direction, ExitType},
db::DBTrans,
models::item::Item,
services::broadcast_to_room,
static_content::room::{self, Direction, ExitType}
};
use std::time;
pub async fn announce_move(trans: &DBTrans, character: &Item, leaving: &Item, arriving: &Item) -> DResult<()> {
let msg_leaving_exp = format!("{} departs towards {}\n", &character.display, &leaving.display);
let msg_leaving_nonexp = format!("{} departs towards {}\n",
character.display_less_explicit
.as_ref()
.unwrap_or(&character.display),
arriving.display_less_explicit
.as_ref()
.unwrap_or(&arriving.display));
broadcast_to_room(trans, &format!("{}/{}", &leaving.item_type, &leaving.item_code),
None, &msg_leaving_exp, Some(&msg_leaving_nonexp)).await?;
let msg_arriving_exp = format!("{} arrives from {}\n", &character.display, &leaving.display);
let msg_arriving_nonexp = format!("{} arrives from {}\n",
character.display_less_explicit
.as_ref()
.unwrap_or(&character.display),
leaving.display_less_explicit
.as_ref()
.unwrap_or(&leaving.display));
broadcast_to_room(trans, &format!("{}/{}", &arriving.item_type, &arriving.item_code),
None, &msg_arriving_exp, Some(&msg_arriving_nonexp)).await?;
Ok(())
}
pub struct QueueHandler;
#[async_trait]
impl QueueCommandHandler for QueueHandler {
@ -69,6 +40,7 @@ impl QueueCommandHandler for QueueHandler {
let exit = room.exits.iter().find(|ex| ex.direction == *direction)
.ok_or_else(|| UserError("There is nothing in that direction".to_owned()))?;
// Ideally we would queue if we were already moving rather than insta-move.
match exit.exit_type {
ExitType::Free => {}
ExitType::Blocked(blocker) => {
@ -83,16 +55,7 @@ impl QueueCommandHandler for QueueHandler {
let mut new_player_item = (*player_item).clone();
new_player_item.location = format!("{}/{}", "room", new_room.code);
ctx.trans.save_item_model(&new_player_item).await?;
look::VERB.handle(ctx, "look", "").await?;
if let Some(old_room_item) = ctx.trans.find_item_by_type_code("room", room.code).await? {
if let Some(new_room_item) = ctx.trans.find_item_by_type_code("room", new_room.code).await? {
announce_move(&ctx.trans, &new_player_item, &old_room_item, &new_room_item).await?;
}
}
Ok(())
}
}

View File

@ -1,62 +0,0 @@
use super::{VerbContext, UserVerb, UserVerbRef, UResult, UserError,
user_error,
get_player_item_or_fail, is_likely_explicit};
use crate::{
models::item::{Item, ItemFlag},
services::broadcast_to_room,
db::DBTrans
};
use async_trait::async_trait;
use ansi::{ignore_special_characters, ansi};
pub async fn say_to_room<'l>(
trans: &DBTrans,
from_item: &Item,
location: &str,
say_what: &str,
is_explicit: bool
) -> UResult<()> {
let (loc_type, loc_code) = location.split_once("/")
.ok_or_else(|| UserError("Invalid location".to_owned()))?;
let room_item = trans.find_item_by_type_code(loc_type, loc_code).await?
.ok_or_else(|| UserError("Room missing".to_owned()))?;
if room_item.flags.contains(&ItemFlag::NoSay) {
user_error("Your wristpad vibrates and flashes up an error - apparently it has \
been programmed to block your voice from working here.".to_owned())?
}
let msg_exp = format!(
ansi!("<yellow>{} says: <reset><bold>\"{}\"<reset>\n"),
from_item.display,
say_what
);
let msg_lessexp = format!(
ansi!("<yellow>{} says: <reset><bold>\"{}\"<reset>\n"),
from_item.display_less_explicit.as_ref().unwrap_or(&from_item.display),
say_what
);
broadcast_to_room(
trans,
location,
Some(from_item),
&msg_exp,
if is_explicit { None } else { Some(&msg_lessexp) }
).await?;
Ok(())
}
pub struct Verb;
#[async_trait]
impl UserVerb for Verb {
async fn handle(self: &Self, ctx: &mut VerbContext, _verb: &str, remaining: &str) -> UResult<()> {
let say_what = ignore_special_characters(remaining);
if say_what == "" {
user_error("You need to provide a message to send.".to_owned())?;
}
let player_item = get_player_item_or_fail(ctx).await?;
say_to_room(ctx.trans, &player_item, &player_item.location,
&say_what, is_likely_explicit(&say_what)).await
}
}
static VERB_INT: Verb = Verb;
pub static VERB: UserVerbRef = &VERB_INT as UserVerbRef;

View File

@ -107,13 +107,6 @@ pub enum Sex {
}
#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub enum ItemFlag {
NoSay,
NoSeeContents
}
#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
#[serde(default)]
pub struct Item {
pub item_code: String,
pub item_type: String,
@ -131,7 +124,6 @@ pub struct Item {
pub total_skills: BTreeMap<SkillType, u16>,
pub temporary_buffs: Vec<Buff>,
pub pronouns: Pronouns,
pub flags: Vec<ItemFlag>,
pub sex: Option<Sex>,
}
@ -170,7 +162,6 @@ impl Default for Item {
total_skills: BTreeMap::new(),
temporary_buffs: Vec::new(),
pronouns: Pronouns::default_inanimate(),
flags: vec!(),
sex: None
}
}

View File

@ -2,6 +2,7 @@ use serde::{Serialize, Deserialize};
use serde_json::Value;
use chrono::{DateTime, Utc};
#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub enum TaskRecurrence {
FixedDuration { seconds: u32 }
@ -10,18 +11,13 @@ pub enum TaskRecurrence {
#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
#[serde(tag="task_type", content="task_details")]
pub enum TaskDetails {
RunQueuedCommand,
NPCSay {
npc_code: String,
say_code: String
}
RunQueuedCommand
}
impl TaskDetails {
pub fn name(self: &Self) -> &'static str {
use TaskDetails::*;
match self {
RunQueuedCommand => "RunQueuedCommand",
NPCSay { .. } => "NPCSay",
RunQueuedCommand => "RunQueuedCommand"
}
}
}

View File

@ -8,7 +8,6 @@ use once_cell::sync::OnceCell;
use std::ops::AddAssign;
use std::collections::BTreeMap;
use chrono::Utc;
use crate::static_content::npc;
pub mod queued_command;
@ -27,8 +26,7 @@ fn task_handler_registry() -> &'static BTreeMap<&'static str, &'static (dyn Task
OnceCell::new();
TASK_HANDLER_REGISTRY.get_or_init(
|| vec!(
("RunQueuedCommand", queued_command::HANDLER.clone()),
("NPCSay", npc::SAY_HANDLER.clone()),
("RunQueuedCommand", queued_command::HANDLER.clone())
).into_iter().collect()
)
}

View File

@ -1,24 +0,0 @@
use crate::{
models::item::Item,
db::DBTrans,
DResult
};
pub async fn broadcast_to_room(trans: &DBTrans, location: &str, from_item: Option<&Item>,
message_explicit_ok: &str, message_nonexplicit: Option<&str>) -> DResult<()> {
for item in trans.find_items_by_location(location).await? {
if item.item_type != "player" {
continue;
}
if let Some((session, session_dat)) = trans.find_session_for_player(&item.item_code).await? {
if session_dat.less_explicit_mode && Some(&item.item_code) != from_item.map(|i| &i.item_code) {
if let Some(msg) = message_nonexplicit {
trans.queue_for_session(&session, Some(msg)).await?;
}
return Ok(());
}
trans.queue_for_session(&session, Some(message_explicit_ok)).await?;
}
}
Ok(())
}

View File

@ -1,6 +1,6 @@
use crate::DResult;
use crate::db::DBPool;
use crate::models::{item::Item, task::Task};
use crate::models::item::Item;
use std::collections::{BTreeSet, BTreeMap};
use log::info;
@ -13,64 +13,50 @@ pub struct StaticItem {
pub initial_item: Box<dyn Fn() -> Item>
}
pub struct StaticTask {
pub task_code: String,
pub initial_task: Box<dyn Fn() -> Task>
struct StaticItemTypeGroup {
item_type: &'static str,
items: fn () -> Box<dyn Iterator<Item = StaticItem>>
}
struct StaticThingTypeGroup<Thing> {
thing_type: &'static str,
things: fn () -> Box<dyn Iterator<Item = Thing>>
}
fn static_item_registry() -> Vec<StaticThingTypeGroup<StaticItem>> {
fn static_item_registry() -> Vec<StaticItemTypeGroup> {
vec!(
// Must have no duplicates.
StaticThingTypeGroup::<StaticItem> {
thing_type: "npc",
things: || npc::npc_static_items()
StaticItemTypeGroup {
item_type: "npc",
items: || npc::npc_static_items()
},
StaticThingTypeGroup::<StaticItem> {
thing_type: "room",
things: || room::room_static_items()
StaticItemTypeGroup {
item_type: "room",
items: || room::room_static_items()
},
StaticThingTypeGroup::<StaticItem> {
thing_type: "fixed_item",
things: || fixed_item::static_items()
},
)
}
fn static_task_registry() -> Vec<StaticThingTypeGroup<StaticTask>> {
vec!(
// Must have no duplicates.
StaticThingTypeGroup::<StaticTask> {
thing_type: "NPCSay",
things: || npc::npc_say_tasks()
StaticItemTypeGroup {
item_type: "fixed_item",
items: || fixed_item::static_items()
},
)
}
async fn refresh_static_items(pool: &DBPool) -> DResult<()> {
let registry = static_item_registry();
let expected_type: BTreeSet<String> =
registry.iter().map(|x| x.thing_type.to_owned()).collect();
registry.iter().map(|x| x.item_type.to_owned()).collect();
let cur_types: Box<BTreeSet<String>> = pool.find_static_item_types().await?;
for item_type in cur_types.difference(&expected_type) {
pool.delete_static_items_by_type(item_type).await?;
}
for type_group in registry.iter() {
info!("Checking static_content of item_type {}", type_group.thing_type);
info!("Checking static_content of item_type {}", type_group.item_type);
let tx = pool.start_transaction().await?;
let existing_items = tx.find_static_items_by_type(type_group.thing_type).await?;
let existing_items = tx.find_static_items_by_type(type_group.item_type).await?;
let expected_items: BTreeMap<String, StaticItem> =
(type_group.things)().map(|x| (x.item_code.to_owned(), x)).collect();
(type_group.items)().map(|x| (x.item_code.to_owned(), x)).collect();
let expected_set: BTreeSet<String> = expected_items.keys().map(|x|x.to_owned()).collect();
for unwanted_item in existing_items.difference(&expected_set) {
info!("Deleting item {:?}", unwanted_item);
tx.delete_static_items_by_code(type_group.thing_type, unwanted_item).await?;
tx.delete_static_items_by_code(type_group.item_type, unwanted_item).await?;
}
for new_item_code in expected_set.difference(&existing_items) {
info!("Creating item {:?}", new_item_code);
@ -83,51 +69,13 @@ async fn refresh_static_items(pool: &DBPool) -> DResult<()> {
.unwrap().initial_item)()).await?;
}
tx.commit().await?;
info!("Committed any changes for static_content of item_type {}", type_group.thing_type);
}
Ok(())
}
async fn refresh_static_tasks(pool: &DBPool) -> DResult<()> {
let registry = static_task_registry();
let expected_type: BTreeSet<String> =
registry.iter().map(|x| x.thing_type.to_owned()).collect();
let cur_types: Box<BTreeSet<String>> = pool.find_static_task_types().await?;
for task_type in cur_types.difference(&expected_type) {
pool.delete_static_tasks_by_type(task_type).await?;
}
for type_group in registry.iter() {
info!("Checking static_content of task_type {}", type_group.thing_type);
let tx = pool.start_transaction().await?;
let existing_tasks = tx.find_static_tasks_by_type(type_group.thing_type).await?;
let expected_tasks: BTreeMap<String, StaticTask> =
(type_group.things)().map(|x| (x.task_code.to_owned(), x)).collect();
let expected_set: BTreeSet<String> = expected_tasks.keys().map(|x|x.to_owned()).collect();
for unwanted_task in existing_tasks.difference(&expected_set) {
info!("Deleting task {:?}", unwanted_task);
tx.delete_static_tasks_by_code(type_group.thing_type, unwanted_task).await?;
}
for new_task_code in expected_set.difference(&existing_tasks) {
info!("Creating task {:?}", new_task_code);
tx.upsert_task(&(expected_tasks.get(new_task_code)
.unwrap().initial_task)()).await?;
}
for existing_task_code in expected_set.intersection(&existing_tasks) {
tx.limited_update_static_task(
&(expected_tasks.get(existing_task_code)
.unwrap().initial_task)()).await?;
}
tx.commit().await?;
info!("Committed any changes for static_content of task_type {}", type_group.thing_type);
info!("Committed any changes for static_content of item_type {}", type_group.item_type);
}
Ok(())
}
pub async fn refresh_static_content(pool: &DBPool) -> DResult<()> {
refresh_static_items(pool).await?;
refresh_static_tasks(pool).await?;
Ok(())
}
@ -137,13 +85,13 @@ mod test {
use super::*;
#[test]
fn no_duplicate_static_items() {
let mut registry = static_item_registry();
registry.sort_unstable_by(|x, y| x.thing_type.cmp(y.thing_type));
fn no_duplicate_static_content() {
let mut registry = static_item_registry();
registry.sort_unstable_by(|x, y| x.item_type.cmp(y.item_type));
let duplicates: Vec<&'static str> =
registry.iter()
.group_by(|x| x.thing_type).into_iter()
.group_by(|x| x.item_type).into_iter()
.filter_map(|(k, v)| if v.count() <= 1 { None } else { Some(k) })
.collect();
if duplicates.len() > 0 {
@ -151,7 +99,7 @@ mod test {
}
for type_group in registry.iter() {
let iterator : Box<dyn Iterator<Item = StaticItem>> = (type_group.things)();
let iterator : Box<dyn Iterator<Item = StaticItem>> = (type_group.items)();
let duplicates: Vec<&'static str> = iterator
.group_by(|x| x.item_code)
.into_iter()
@ -159,36 +107,7 @@ mod test {
.collect();
if duplicates.len() > 0 {
panic!("static_item_registry has duplicate item_codes for {}: {:}",
type_group.thing_type,
duplicates.join(", "));
}
}
}
#[test]
fn no_duplicate_static_tasks() {
let mut registry = static_task_registry();
registry.sort_unstable_by(|x, y| x.thing_type.cmp(y.thing_type));
let duplicates: Vec<&'static str> =
registry.iter()
.group_by(|x| x.thing_type).into_iter()
.filter_map(|(k, v)| if v.count() <= 1 { None } else { Some(k) })
.collect();
if duplicates.len() > 0 {
panic!("static_task_registry has duplicate task_types: {:}", duplicates.join(", "));
}
for type_group in registry.iter() {
let iterator : Box<dyn Iterator<Item = StaticTask>> = (type_group.things)();
let duplicates: Vec<String> = iterator
.group_by(|x| x.task_code.clone())
.into_iter()
.filter_map(|(k, v)| if v.count() <= 1 { None } else { Some(k) })
.collect();
if duplicates.len() > 0 {
panic!("static_task_registry has duplicate task_codes for {}: {:}",
type_group.thing_type,
type_group.item_type,
duplicates.join(", "));
}
}

View File

@ -1,25 +1,11 @@
use super::{StaticItem, StaticTask};
use crate::models::{
item::{Item, Pronouns},
task::{Task, TaskMeta, TaskRecurrence, TaskDetails}
};
use super::StaticItem;
use crate::models::item::Item;
use once_cell::sync::OnceCell;
use std::collections::BTreeMap;
use crate::message_handler::user_commands::{
VerbContext, UResult, CommandHandlingError,
say::say_to_room
};
use crate::DResult;
use crate::message_handler::user_commands::{VerbContext, UResult};
use async_trait::async_trait;
use chrono::Utc;
use rand::{thread_rng, Rng, prelude::*};
use crate::regular_tasks::{TaskHandler, TaskRunContext};
use log::info;
use std::time;
pub mod statbot;
mod melbs_citizen;
mod melbs_dog;
#[async_trait]
pub trait NPCMessageHandler {
@ -32,62 +18,26 @@ pub trait NPCMessageHandler {
) -> UResult<()>;
}
#[derive(Clone, Debug)]
pub enum NPCSayType {
// Bool is true if it should be filtered for less-explicit.
FromFixedList(Vec<(bool, &'static str)>)
}
#[derive(Clone, Debug)]
pub struct NPCSayInfo {
pub say_code: &'static str,
pub frequency_secs: u64,
pub talk_type: NPCSayType
}
pub struct NPC {
pub code: &'static str,
pub name: &'static str,
pub pronouns: Pronouns,
pub description: &'static str,
pub spawn_location: &'static str,
pub message_handler: Option<&'static (dyn NPCMessageHandler + Sync + Send)>,
pub says: Vec<NPCSayInfo>
}
impl Default for NPC {
fn default() -> Self {
Self {
code: "DEFAULT",
name: "default",
pronouns: Pronouns::default_animate(),
description: "default",
spawn_location: "default",
message_handler: None,
says: vec!()
}
}
pub message_handler: Option<&'static (dyn NPCMessageHandler + Sync + Send)>
}
pub fn npc_list() -> &'static Vec<NPC> {
static NPC_LIST: OnceCell<Vec<NPC>> = OnceCell::new();
NPC_LIST.get_or_init(
|| {
let mut npcs = vec!(
NPC {
code: "repro_xv_chargen_statbot",
name: "Statbot",
description: "A silvery shiny metal mechanical being. It lets out a whirring sound as it moves.",
spawn_location: "room/repro_xv_chargen",
message_handler: Some(&statbot::StatbotMessageHandler),
says: vec!(),
..Default::default()
},
);
npcs.append(&mut melbs_citizen::npc_list());
npcs.append(&mut melbs_dog::npc_list());
npcs
})
NPC_LIST.get_or_init(|| vec!(
NPC {
code: "repro_xv_chargen_statbot",
name: "Statbot",
description: "A silvery shiny metal mechanical being. It lets out a whirring sound as it moves.",
spawn_location: "room/repro_xv_chargen",
message_handler: Some(&statbot::StatbotMessageHandler)
}
))
}
pub fn npc_by_code() -> &'static BTreeMap<&'static str, &'static NPC> {
@ -98,18 +48,6 @@ pub fn npc_by_code() -> &'static BTreeMap<&'static str, &'static NPC> {
.collect())
}
pub fn npc_say_info_by_npc_code_say_code() -> &'static BTreeMap<(&'static str, &'static str),
&'static NPCSayInfo> {
static NPC_SAYINFO_MAP: OnceCell<BTreeMap<(&'static str, &'static str),
&'static NPCSayInfo>> = OnceCell::new();
NPC_SAYINFO_MAP.get_or_init(
|| npc_list().iter().flat_map(
|npc| npc.says.iter().map(
|says| ((npc.code, says.say_code), says)
)
).collect())
}
pub fn npc_static_items() -> Box<dyn Iterator<Item = StaticItem>> {
Box::new(npc_list().iter().map(|c| StaticItem {
item_code: c.code,
@ -120,83 +58,7 @@ pub fn npc_static_items() -> Box<dyn Iterator<Item = StaticItem>> {
details: Some(c.description.to_owned()),
location: c.spawn_location.to_owned(),
is_static: true,
pronouns: c.pronouns.clone(),
..Item::default()
})
}))
}
pub fn npc_say_tasks() -> Box<dyn Iterator<Item = StaticTask>> {
Box::new(npc_list().iter().flat_map(|c| c.says.iter().map(|say| StaticTask {
task_code: c.code.to_owned() + "_" + say.say_code,
initial_task: Box::new(
|| {
let mut rng = thread_rng();
Task {
meta: TaskMeta {
task_code: c.code.to_owned() + "_" + say.say_code,
is_static: true,
recurrence: Some(TaskRecurrence::FixedDuration { seconds: say.frequency_secs as u32 }),
next_scheduled: Utc::now() + chrono::Duration::seconds(rng.gen_range(0..say.frequency_secs) as i64),
..TaskMeta::default()
},
details: TaskDetails::NPCSay {
npc_code: c.code.to_owned(),
say_code: say.say_code.to_owned()
},
}
})
})))
}
pub struct NPCSayTaskHandler;
#[async_trait]
impl TaskHandler for NPCSayTaskHandler {
async fn do_task(&self, ctx: &mut TaskRunContext) -> DResult<Option<time::Duration>> {
let (npc_code, say_code) = match &ctx.task.details {
TaskDetails::NPCSay { npc_code, say_code } => (npc_code.clone(), say_code.clone()),
_ => Err("Expected NPC say task to be NPCSay type")?
};
let say_info = match npc_say_info_by_npc_code_say_code().get(&(&npc_code, &say_code)) {
None => {
info!("NPCSayTaskHandler can't find NPCSayInfo for npc {} say_code {}",
npc_code, say_code);
return Ok(None);
}
Some(r) => r
};
let npc_item = match ctx.trans.find_item_by_type_code("npc", &npc_code).await? {
None => {
info!("NPCSayTaskHandler can't find NPC {}", npc_code);
return Ok(None);
}
Some(r) => r
};
let (is_explicit, say_what) = match &say_info.talk_type {
NPCSayType::FromFixedList(l) => {
let mut rng = thread_rng();
match l[..].choose(&mut rng) {
None => {
info!("NPCSayTaskHandler NPCSayInfo for npc {} say_code {} has no choices",
npc_code, say_code);
return Ok(None);
}
Some(r) => r.clone()
}
}
};
match say_to_room(ctx.trans, &npc_item, &npc_item.location, say_what, is_explicit).await {
Ok(()) => {}
Err(CommandHandlingError::UserError(e)) => {
info!("NPCSayHandler couldn't send for npc {} say_code {}: {}",
npc_code, say_code, e);
}
Err(CommandHandlingError::SystemError(e)) => Err(e)?
}
Ok(None)
}
}
pub static SAY_HANDLER: &'static (dyn TaskHandler + Sync + Send) = &NPCSayTaskHandler;

View File

@ -1,563 +0,0 @@
use super::{NPC, NPCSayInfo, NPCSayType};
pub fn npc_list() -> Vec<NPC> {
use NPCSayType::FromFixedList;
let melbs_citizen_stdsay = NPCSayInfo {
say_code: "babble",
frequency_secs: 60,
talk_type: FromFixedList(vec!(
(false, "I'm so sick of being cloned."),
(false, "I hope I don't die again today."),
(false, "I wish the so-called king would do something about the damned zombies everywhere."),
(true, "I earn so many credits making babies for the body factory - it literally pays my bills."),
(false, "I know people hated the empire, but I kind of wish it was still intact - it was a lot better than what we have now."),
(false, "I wish there wasn't so much radiation outside of Melbs CBD."),
(false, "I heard about a guy who went to a special place somewhere around here, and there was a machine that enhanced his wristpad and gave him basically superpowers."),
(false, "The damn vampire movement... they are all so sneaky, and I never know when they are going to come for my blood."),
))
};
vec!(
NPC {
code: "melbs_citizen_1",
name: "Matthew Thomas",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_kingst_latrobest",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_2",
name: "Matthew Perez",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_kingst_20",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_3",
name: "Kimberly Jackson",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_kingst_40",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_4",
name: "Michael Sanchez",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_kingst_50",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_5",
name: "Jessica Davis",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_kingst_bourkest",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_6",
name: "Robert Davis",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_kingst_70",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_7",
name: "Paul Lewis",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_kingst_90",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_8",
name: "Andrew Moore",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_kingst_collinsst",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_9",
name: "Betty Thomas",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_kingst_100",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_10",
name: "Mary Robinson",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_kingst_110",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_11",
name: "Lisa Lopez",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_kingst_flinderst",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_12",
name: "Kimberly Martinez",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_flindersst_200",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_13",
name: "Anthony Nguyen",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_flindersst_190",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_14",
name: "Joshua Green",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_flindersst_180",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_15",
name: "Emily Wright",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_flindersst_170",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_16",
name: "Ashley Thomas",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_lonsdalest_130",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_17",
name: "Jessica Miller",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_kingst_80",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_18",
name: "Anthony Lopez",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_lonsdalest_140",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_19",
name: "John Lopez",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_elizabethst_lonsdalest",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_20",
name: "Thomas Garcia",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_williamsst_120",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_21",
name: "Donna Thompson",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_elizabethst_60",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_22",
name: "Matthew Davis",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_williamsst_100",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_23",
name: "Steven Jones",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_swanstonst_120",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_24",
name: "Linda Smith",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_swanstonst_lonsdalest",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_25",
name: "Karen Rodriguez",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_bourkest_180",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_26",
name: "Paul Scott",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_swanstonst_70",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_27",
name: "Ashley Thomas",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_lonsdalest_130",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_28",
name: "Sandra Scott",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_elizabethst_30",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_29",
name: "Michael Rodriguez",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_swanstonst_70",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_30",
name: "Donald Miller",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_elizabethst_30",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_31",
name: "Charles Moore",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_lonsdalest_160",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_32",
name: "Ashley Sanchez",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_kingst_100",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_33",
name: "Margaret Lewis",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_flindersst_180",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_34",
name: "Sandra Thompson",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_swanstonst_80",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_35",
name: "Sandra King",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_lonsdalest_150",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_36",
name: "Lisa Anderson",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_lonsdalest_210",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_37",
name: "Kimberly Martin",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_kingst_80",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_38",
name: "Susan Smith",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_latrobest_190",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_39",
name: "Susan Martin",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_collinsst_150",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_40",
name: "Linda Scott",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_williamsst_30",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_41",
name: "Donald Miller",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_elizabethst_80",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_42",
name: "Mark Hill",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_collinsst_120",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_43",
name: "William Perez",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_queenst_90",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_44",
name: "Donald Perez",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_queenst_lonsdalest",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_45",
name: "Lisa Rodriguez",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_collinsst_100",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_46",
name: "James Adams",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_latrobest_150",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_47",
name: "James Moore",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_latrobest_130",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_48",
name: "Joseph Martin",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_bourkest_150",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_49",
name: "Matthew Jones",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_kingst_60",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_50",
name: "Michael Sanchez",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_queenst_100",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_51",
name: "Donna Torres",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_flindersst_150",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_52",
name: "Barbara Garcia",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_swanstonst_50",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_53",
name: "Daniel Miller",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_bourkest_110",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_54",
name: "Robert Young",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_kingst_collinsst",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_55",
name: "Donald Flores",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_swanstonst_40",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_56",
name: "Charles Thomas",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_flindersst_110",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_57",
name: "William Torres",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_swanstonst_60",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_58",
name: "Barbara Gonzalez",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_collinsst_190",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_59",
name: "Mary Smith",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_bourkest_180",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
},
NPC {
code: "melbs_citizen_60",
name: "Michael Jackson",
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
spawn_location: "room/melbs_williamsst_110",
message_handler: None,
says: vec!(melbs_citizen_stdsay.clone()),
..Default::default()
}
)
}

View File

@ -1,487 +0,0 @@
use super::NPC;
use crate::models::item::Pronouns;
pub fn npc_list() -> Vec<NPC> {
vec!(
NPC {
code: "melbs_dog_1",
name: "feral black dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_elizabethst_collinsst",
..Default::default()
},
NPC {
code: "melbs_dog_2",
name: "howling black dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_collinsst_100",
..Default::default()
},
NPC {
code: "melbs_dog_3",
name: "ferocious white dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_elizabethst_lonsdalest",
..Default::default()
},
NPC {
code: "melbs_dog_4",
name: "mangy grey dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_collinsst_160",
..Default::default()
},
NPC {
code: "melbs_dog_5",
name: "howling grey dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_lonsdalest_100",
..Default::default()
},
NPC {
code: "melbs_dog_6",
name: "reeking black dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_lonsdalest_120",
..Default::default()
},
NPC {
code: "melbs_dog_7",
name: "growling grey dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_williamsst_20",
..Default::default()
},
NPC {
code: "melbs_dog_8",
name: "mangy black dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_bourkest_120",
..Default::default()
},
NPC {
code: "melbs_dog_9",
name: "howling black dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_collinsst_100",
..Default::default()
},
NPC {
code: "melbs_dog_10",
name: "howling brown dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_flindersst_130",
..Default::default()
},
NPC {
code: "melbs_dog_11",
name: "ferocious black dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_flindersst_100",
..Default::default()
},
NPC {
code: "melbs_dog_12",
name: "mangy grey dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_elizabethst_90",
..Default::default()
},
NPC {
code: "melbs_dog_13",
name: "reeking light brown dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_lonsdalest_140",
..Default::default()
},
NPC {
code: "melbs_dog_14",
name: "smelly black dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_queenst_20",
..Default::default()
},
NPC {
code: "melbs_dog_15",
name: "growling light brown dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_elizabethst_10",
..Default::default()
},
NPC {
code: "melbs_dog_16",
name: "howling brown dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_swanstonst_flindersst",
..Default::default()
},
NPC {
code: "melbs_dog_17",
name: "feral brown dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_kingst_latrobest",
..Default::default()
},
NPC {
code: "melbs_dog_18",
name: "smelly grey dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_kingst_40",
..Default::default()
},
NPC {
code: "melbs_dog_19",
name: "feral black dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_elizabethst_60",
..Default::default()
},
NPC {
code: "melbs_dog_20",
name: "smelly white dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_swanstonst_120",
..Default::default()
},
NPC {
code: "melbs_dog_21",
name: "growling white dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_elizabethst_90",
..Default::default()
},
NPC {
code: "melbs_dog_22",
name: "feral light brown dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_lonsdalest_150",
..Default::default()
},
NPC {
code: "melbs_dog_23",
name: "mangy grey dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_lonsdalest_150",
..Default::default()
},
NPC {
code: "melbs_dog_24",
name: "reeking grey dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_elizabethst_100",
..Default::default()
},
NPC {
code: "melbs_dog_25",
name: "smelly grey dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_bourkest_180",
..Default::default()
},
NPC {
code: "melbs_dog_26",
name: "growling light brown dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_queenst_100",
..Default::default()
},
NPC {
code: "melbs_dog_27",
name: "feral light brown dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_queenst_10",
..Default::default()
},
NPC {
code: "melbs_dog_28",
name: "feral grey dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_lonsdalest_160",
..Default::default()
},
NPC {
code: "melbs_dog_29",
name: "reeking brown dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_bourkest_110",
..Default::default()
},
NPC {
code: "melbs_dog_30",
name: "howling grey dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_queenst_80",
..Default::default()
},
NPC {
code: "melbs_dog_31",
name: "howling brown dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_bourkest_160",
..Default::default()
},
NPC {
code: "melbs_dog_32",
name: "feral black dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_swanstonst_collinsst",
..Default::default()
},
NPC {
code: "melbs_dog_33",
name: "reeking brown dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_kingst_flinderst",
..Default::default()
},
NPC {
code: "melbs_dog_34",
name: "reeking white dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_elizabethst_100",
..Default::default()
},
NPC {
code: "melbs_dog_35",
name: "growling light brown dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_queenst_110",
..Default::default()
},
NPC {
code: "melbs_dog_36",
name: "reeking black dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_williamsst_90",
..Default::default()
},
NPC {
code: "melbs_dog_37",
name: "growling black dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_latrobesst_200",
..Default::default()
},
NPC {
code: "melbs_dog_38",
name: "feral black dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_queenst_90",
..Default::default()
},
NPC {
code: "melbs_dog_39",
name: "mangy black dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_queenst_40",
..Default::default()
},
NPC {
code: "melbs_dog_40",
name: "growling white dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_williamsst_40",
..Default::default()
},
NPC {
code: "melbs_dog_41",
name: "reeking grey dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_queenst_latrobest",
..Default::default()
},
NPC {
code: "melbs_dog_42",
name: "mangy grey dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_flindersst_210",
..Default::default()
},
NPC {
code: "melbs_dog_43",
name: "ferocious brown dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_kingst_latrobest",
..Default::default()
},
NPC {
code: "melbs_dog_44",
name: "ferocious light brown dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_collinsst_120",
..Default::default()
},
NPC {
code: "melbs_dog_45",
name: "ferocious light brown dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_swanstonst_lonsdalest",
..Default::default()
},
NPC {
code: "melbs_dog_46",
name: "smelly grey dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_williamsst_30",
..Default::default()
},
NPC {
code: "melbs_dog_47",
name: "growling grey dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_lonsdalest_100",
..Default::default()
},
NPC {
code: "melbs_dog_48",
name: "ferocious brown dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_latrobest_210",
..Default::default()
},
NPC {
code: "melbs_dog_49",
name: "reeking brown dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_latrobest_140",
..Default::default()
},
NPC {
code: "melbs_dog_50",
name: "howling grey dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_swanstonst_110",
..Default::default()
},
NPC {
code: "melbs_dog_51",
name: "howling black dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_elizabethst_flindersst",
..Default::default()
},
NPC {
code: "melbs_dog_52",
name: "growling light brown dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_flindersst_120",
..Default::default()
},
NPC {
code: "melbs_dog_53",
name: "ferocious black dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_queenst_110",
..Default::default()
},
NPC {
code: "melbs_dog_54",
name: "growling grey dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_flindersst_210",
..Default::default()
},
NPC {
code: "melbs_dog_55",
name: "reeking brown dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_williamsst_60",
..Default::default()
},
NPC {
code: "melbs_dog_56",
name: "ferocious white dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_queenst_lonsdalest",
..Default::default()
},
NPC {
code: "melbs_dog_57",
name: "smelly brown dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_swanstonst_lonsdalest",
..Default::default()
},
NPC {
code: "melbs_dog_58",
name: "mangy white dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_williamsst_bourkest",
..Default::default()
},
NPC {
code: "melbs_dog_59",
name: "mangy brown dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_latrobest_170",
..Default::default()
},
NPC {
code: "melbs_dog_60",
name: "growling brown dog",
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
spawn_location: "room/melbs_williamsst_110",
..Default::default()
},
)
}

File diff suppressed because it is too large Load Diff

View File

@ -1,153 +0,0 @@
use super::{
Room, GridCoords, Exit, Direction, ExitTarget, ExitType,
SecondaryZoneRecord
};
use ansi::ansi;
pub fn room_list() -> Vec<Room> {
vec!(
// Residential
Room {
zone: "cok_murl",
secondary_zones: vec!(
SecondaryZoneRecord {
zone: "melbs",
short: ansi!("<bgyellow><black>CK<reset>"),
grid_coords: GridCoords { x: 2, y: 5, z: 0 },
caption: Some("Condos on King")
}
),
code: "cok_lobby",
name: "Residential Lobby",
short: ansi!("<bgyellow><black>RE<reset>"),
description: "A sizeable lobby that looks like it is serves the dual purpose as the entrance to the residential condos and as a grand entrance to the linked Murlison Suites commercial building. It is tiled with sparkling clean bluestone tiles. Light green tinted tempered glass panels line the walls. You notice a set of sleek lifts to the south, stairs to the north, and a passage to the attached Murlison commercial building to the east",
description_less_explicit: None,
grid_coords: GridCoords { x: 0, y: 0, z: 0 },
exits: vec!(
Exit {
direction: Direction::WEST,
target: ExitTarget::Custom("room/melbs_kingst_80"),
exit_type: ExitType::Free
},
Exit {
direction: Direction::NORTH,
target: ExitTarget::UseGPS,
exit_type: ExitType::Free
},
Exit {
direction: Direction::SOUTH,
target: ExitTarget::UseGPS,
exit_type: ExitType::Free
},
Exit {
direction: Direction::EAST,
target: ExitTarget::UseGPS,
exit_type: ExitType::Free
},
),
should_caption: true,
..Default::default()
},
Room {
zone: "cok_murl",
code: "cok_gf_lift",
name: "Residential Lifts",
short: ansi!("<bgyellow><black>LI<reset>"),
description: "A set of lifts leading up to various floors",
description_less_explicit: None,
grid_coords: GridCoords { x: 0, y: -1, z: 0 },
exits: vec!(
Exit {
direction: Direction::SOUTH,
target: ExitTarget::UseGPS,
exit_type: ExitType::Free
},
),
should_caption: true,
..Default::default()
},
Room {
zone: "cok_murl",
code: "cok_gf_stairs",
name: "Residential Stairs",
short: ansi!("<bgyellow><black>LI<reset>"),
description: ansi!("A set of lifts leading up to various floors. It looks like it is also possible to go down to the basement by stepping down through a trapdoor covered with tape that says <bgwhite><red>EXTREME DANGER - DO NOT ENTER<reset>"),
description_less_explicit: None,
grid_coords: GridCoords { x: 0, y: 1, z: 0 },
exits: vec!(
Exit {
direction: Direction::NORTH,
target: ExitTarget::UseGPS,
exit_type: ExitType::Free
},
),
should_caption: true,
..Default::default()
},
// Commercial
Room {
zone: "cok_murl",
code: "murl_lobby",
name: "Murlison Suites Commercial Lobby",
short: ansi!("<bgyellow><black>ML<reset>"),
description: "A sleek reception that could have been the bridge of a 2000s era sci-fi spaceship. Linished metal plates are lit up by ambient blue LEDs, while stone tiles cover the floor",
description_less_explicit: None,
grid_coords: GridCoords { x: 1, y: 0, z: 0 },
exits: vec!(
Exit {
direction: Direction::WEST,
target: ExitTarget::UseGPS,
exit_type: ExitType::Free
},
Exit {
direction: Direction::NORTH,
target: ExitTarget::UseGPS,
exit_type: ExitType::Free
},
Exit {
direction: Direction::SOUTH,
target: ExitTarget::UseGPS,
exit_type: ExitType::Free
}
),
should_caption: true,
..Default::default()
},
Room {
zone: "cok_murl",
code: "murl_gf_lift",
name: "Commercial Lifts",
short: ansi!("<bgyellow><black>LI<reset>"),
description: "A set of lifts leading up to various floors",
description_less_explicit: None,
grid_coords: GridCoords { x: 1, y: -1, z: 0 },
exits: vec!(
Exit {
direction: Direction::SOUTH,
target: ExitTarget::UseGPS,
exit_type: ExitType::Free
},
),
should_caption: true,
..Default::default()
},
Room {
zone: "cok_murl",
code: "murl_gf_stair",
name: "Commercial Stairs",
short: ansi!("<bgyellow><black>>><reset>"),
description: "A set of stairs leading up to various floors",
description_less_explicit: None,
grid_coords: GridCoords { x: 1, y: 1, z: 0 },
exits: vec!(
Exit {
direction: Direction::NORTH,
target: ExitTarget::UseGPS,
exit_type: ExitType::Free
},
),
should_caption: true,
..Default::default()
},
)
}

File diff suppressed because it is too large Load Diff

View File

@ -1,107 +0,0 @@
use super::{
Room, GridCoords, Exit, Direction, ExitTarget, ExitType,
SecondaryZoneRecord
};
use crate::static_content::npc;
use ansi::ansi;
pub fn room_list() -> Vec<Room> {
vec!(
Room {
zone: "repro_xv",
code: "repro_xv_chargen",
name: ansi!("Choice Room"),
short: ansi!("<bgwhite><green>CR<reset>"),
description: ansi!(
"A room brightly lit in unnaturally white light, covered in sparkling \
white tiles from floor to ceiling. A loudspeaker plays a message on \
loop:\n\
\t<blue>\"Citizen, you are here because your memory has been wiped and \
you are ready to start a fresh life. As a being enhanced by \
Gazos-Murlison Co technology, the emperor has granted you the power \
to choose 14 points of upgrades to yourself. Choose wisely, as it \
will impact who you end up being, and you would need to completely \
wipe your brain again to change them. Talk to Statbot to spend your \
14 points and create your body.\"<reset>\n\
[Try <bold>-statbot hi<reset>, to send hi to statbot - the - means \
to whisper to a particular person in the room]"),
grid_coords: GridCoords { x: 0, y: 0, z: -1 },
exits: vec!(Exit {
direction: Direction::EAST,
target: ExitTarget::UseGPS,
exit_type: ExitType::Blocked(&npc::statbot::ChoiceRoomBlocker),
}),
should_caption: true,
..Default::default()
},
Room {
zone: "repro_xv",
code: "repro_xv_updates",
name: ansi!("Update Centre"),
short: ansi!("<bgwhite><green>UC<reset>"),
description: ansi!(
"A room covered in posters, evidently meant to help newly wiped individuals \
get up to speed on what has happened in the world since their memory implant was \
created. A one-way opens to the east - you have a feeling that once you go through, \
there will be no coming back in here. <bold>[Hint: Try reading the posters here.]<reset>"),
grid_coords: GridCoords { x: 1, y: 0, z: -1 },
exits: vec!(Exit {
direction: Direction::EAST,
target: ExitTarget::UseGPS,
exit_type: ExitType::Free,
}),
should_caption: true,
..Default::default()
},
Room {
zone: "repro_xv",
secondary_zones: vec!(),
code: "repro_xv_respawn",
name: ansi!("Body Factory"),
short: ansi!("<bgmagenta><white>BF<reset>"),
description: ansi!(
"A room filled with glass vats full of clear fluids, with bodies of \
various stages of development floating in them. It smells like bleach. \
Being here makes you realise you aren't exactly alive right now... you \
have no body. But you sense you could go <bold>up<reset> and attach \
your memories to a body matching your current stats"),
grid_coords: GridCoords { x: 2, y: 0, z: -1 },
exits: vec!(Exit {
direction: Direction::UP,
target: ExitTarget::UseGPS,
exit_type: ExitType::Free
}),
should_caption: true,
..Default::default()
},
Room {
zone: "repro_xv",
secondary_zones: vec!(SecondaryZoneRecord {
zone: "melbs",
short: ansi!("<bgmagenta><white>RL<reset>"),
grid_coords: GridCoords { x: 2, y: 1, z: 0 },
caption: Some("ReproLabs")
}),
code: "repro_xv_lobby",
name: "Lobby",
short: "<=",
description: ansi!(
"An entrance for an establishment called ReproLabs XV. \
It looks like they make bodies and attach peoples memories to \
them, and allow people to reclone when they die. It has an \
unattended reception desk, with chrome-plated letters reading \
ReproLabs XV stuck to the wall behind it. A pipe down to into the ground \
opens up here, but the airflow is so strong, it looks like it is out \
only - it seems to be how newly re-cloned bodies get back into the world"),
grid_coords: GridCoords { x: 2, y: 0, z: 0 },
exits: vec!(
Exit {
direction: Direction::WEST,
target: ExitTarget::Custom("room/melbs_kingst_50"),
exit_type: ExitType::Free
}),
should_caption: true,
..Default::default()
}
)
}

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 62 KiB

View File

@ -1,99 +0,0 @@
module Main where
import Data.List
import System.Random
import Control.Monad
first :: [String]
first = [
"James",
"Mary",
"Robert",
"Patricia",
"John",
"Jennifer",
"Michael",
"Linda",
"David",
"Elizabeth",
"William",
"Barbara",
"Richard",
"Susan",
"Joseph",
"Jessica",
"Thomas",
"Sarah",
"Charles",
"Karen",
"Christopher",
"Lisa",
"Daniel",
"Nancy",
"Matthew",
"Betty",
"Anthony",
"Margaret",
"Mark",
"Sandra",
"Donald",
"Ashley",
"Steven",
"Kimberly",
"Paul",
"Emily",
"Andrew",
"Donna",
"Joshua"
]
surn :: [String]
surn = [
"Smith",
"Johnson",
"Williams",
"Brown",
"Jones",
"Garcia",
"Miller",
"Davis",
"Rodriguez",
"Martinez",
"Hernandez",
"Lopez",
"Gonzalez",
"Wilson",
"Anderson",
"Thomas",
"Taylor",
"Moore",
"Jackson",
"Martin",
"Lee",
"Perez",
"Thompson",
"Harris",
"Sanchez",
"Clark",
"Ramirez",
"Lewis",
"Robinson",
"Walker",
"Young",
"Allen",
"King",
"Wright",
"Scott",
"Torres",
"Nguyen",
"Hill",
"Flores",
"Green",
"Adams"
]
main :: IO ()
main = do
forM_ [1..60] $ \i -> do
first_name <- (first!!) <$> randomRIO (0, length first - 1)
last_name <- (surn!!) <$> randomRIO (0, length surn - 1)
putStrLn $ " NPC {\n code: \"melbs_citizen_" <> (show i) <> "\",\n name: \"" <> first_name <> " " <> last_name <> "\n description: \"A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life\",\n spawn_location: \"room/melbs_\"\n message_handler: None,\n says: vec!()\n },\n"

View File

@ -1,182 +0,0 @@
{-# LANGUAGE OverloadedStrings #-}
import qualified Data.Text as T
import qualified Data.Text.IO as T
import Control.Monad
import System.Random
rooms :: [T.Text]
rooms = [
"melbs_kingst_latrobest",
"melbs_kingst_10",
"melbs_kingst_20",
"melbs_kingst_30",
"melbs_kingst_lonsdalest",
"melbs_kingst_40",
"melbs_homelessshelter",
"melbs_kingst_50",
"melbs_kingst_60",
"melbs_kingst_bourkest",
"melbs_kingst_70",
"melbs_kingst_80",
"melbs_kingst_90",
"melbs_kingst_collinsst",
"melbs_kingst_100",
"melbs_kingst_110",
"melbs_kingst_120",
"melbs_kingst_flinderst",
"melbs_flindersst_210",
"melbs_flindersst_200",
"melbs_flindersst_190",
"melbs_williamsst_flindersst",
"melbs_flindersst_180",
"melbs_flindersst_170",
"melbs_flindersst_160",
"melbs_queenst_flindersst",
"melbs_flindersst_150",
"melbs_flindersst_140",
"melbs_flindersst_130",
"melbs_elizabethst_flindersst",
"melbs_flindersst_120",
"melbs_flindersst_110",
"melbs_flindersst_100",
"melbs_swanstonst_flindersst",
"melbs_swanstonst_latrobest",
"melbs_swansonst_10",
"melbs_swanstonst_20",
"melbs_swanstonst_30",
"melbs_swanstonst_lonsdalest",
"melbs_swanstonst_40",
"melbs_swanstonst_50",
"melbs_swanstonst_60",
"melbs_swanstonst_bourkest",
"melbs_swanstonst_70",
"melbs_swanstonst_80",
"melbs_swanstonst_90",
"melbs_swanstonst_collinsst",
"melbs_swanstonst_100",
"melbs_swanstonst_110",
"melbs_swanstonst_120",
"melbs_latrobest_210",
"melbs_latrobesst_200",
"melbs_latrobest_190",
"melbs_williamstlatrobest",
"melbs_latrobest_180",
"melbs_latrobest_170",
"melbs_latrobest_160",
"melbs_queenst_latrobest",
"melbs_latrobest_150",
"melbs_latrobest_140",
"melbs_latrobest_130",
"melbs_elizabethst_latrobest",
"melbs_latrobest_120",
"melbs_latrobest_110",
"melbs_latrobest_100",
"melbs_lonsdalest_210",
"melbs_lonsdalest_200",
"melbs_lonsdalest_190",
"melbs_williamstlonsdalest",
"melbs_lonsdalest_180",
"melbs_lonsdalest_170",
"melbs_lonsdalest_160",
"melbs_queenst_lonsdalest",
"melbs_lonsdalest_150",
"melbs_lonsdalest_140",
"melbs_lonsdalest_130",
"melbs_elizabethst_lonsdalest",
"melbs_lonsdalest_120",
"melbs_lonsdalest_110",
"melbs_lonsdalest_100",
"melbs_williamsst_10",
"melbs_williamsst_20",
"melbs_williamsst_30",
"melbs_williamsst_40",
"melbs_williamsst_50",
"melbs_williamsst_60",
"melbs_williamsst_bourkest",
"melbs_williamsst_70",
"melbs_williamsst_80",
"melbs_williamsst_90",
"melbs_williamsst_collinsst",
"melbs_williamsst_100",
"melbs_williamsst_110",
"melbs_williamsst_120",
"melbs_bourkest_210",
"melbs_bourkest_200",
"melbs_bourkest_190",
"melbs_bourkest_180",
"melbs_bourkest_170",
"melbs_bourkest_160",
"melbs_queenst_bourkest",
"melbs_bourkest_150",
"melbs_bourkest_140",
"melbs_bourkest_130",
"melbs_elizabethst_bourkest",
"melbs_bourkest_120",
"melbs_bourkest_110",
"melbs_bourkest_100",
"melbs_queenst_10",
"melbs_queenst_20",
"melbs_queenst_30",
"melbs_queenst_40",
"melbs_queenst_50",
"melbs_queenst_60",
"melbs_queenst_70",
"melbs_queenst_80",
"melbs_queenst_90",
"melbs_queenst_collinsst",
"melbs_queenst_100",
"melbs_queenst_110",
"melbs_queenst_120",
"melbs_collinsst_210",
"melbs_collinsst_200",
"melbs_collinsst_190",
"melbs_collinsst_180",
"melbs_collinsst_170",
"melbs_collinsst_160",
"melbs_collinsst_150",
"melbs_collinsst_140",
"melbs_collinsst_130",
"melbs_elizabethst_collinsst",
"melbs_collinsst_120",
"melbs_collinsst_110",
"melbs_collinsst_100",
"melbs_elizabethst_10",
"melbs_elizabethst_20",
"melbs_elizabethst_30",
"melbs_elizabethst_40",
"melbs_elizabethst_50",
"melbs_elizabethst_60",
"melbs_elizabethst_70",
"melbs_elizabethst_80",
"melbs_elizabethst_90",
"melbs_elizabethst_100",
"melbs_elizabethst_110",
"melbs_elizabethst_120"
]
character :: Int -> T.Text -> T.Text -> T.Text
character id adjective room =
" NPC {\n\
\ code: \"melbs_dog_" <> (T.pack $ show id) <> "\",\n\
\ name: \"" <> adjective <> " dog\",\n\
\ proper_noun: false,\n\
\ description: \"A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.\",\n\
\ spawn_location: \"room/" <> room <> "\",\n\
\ ..Default::default()\n\
\ },\n"
chooseFromList :: [a] -> IO a
chooseFromList l = (l!!) <$> randomRIO (0, length l - 1)
firstAdjectives :: [T.Text]
firstAdjectives = ["mangy", "smelly", "feral", "ferocious", "howling", "growling", "reeking"]
secondAdjectives :: [T.Text]
secondAdjectives = ["brown", "black", "white", "grey", "light brown"]
main :: IO ()
main = forM_ [1..60] $ \id -> do
adjective1 <- chooseFromList firstAdjectives
adjective2 <- chooseFromList secondAdjectives
room <- chooseFromList rooms
T.putStr $ character id (adjective1 <> " " <> adjective2) room