Support player recloning + NPCs can wander and aggro.
This commit is contained in:
parent
2d9fcf9850
commit
a3ea381438
@ -15,6 +15,11 @@ pub struct Verb;
|
|||||||
impl UserVerb for Verb {
|
impl UserVerb for Verb {
|
||||||
async fn handle(self: &Self, ctx: &mut VerbContext, _verb: &str, remaining: &str) -> UResult<()> {
|
async fn handle(self: &Self, ctx: &mut VerbContext, _verb: &str, remaining: &str) -> UResult<()> {
|
||||||
let player_item = get_player_item_or_fail(ctx).await?;
|
let player_item = get_player_item_or_fail(ctx).await?;
|
||||||
|
|
||||||
|
if player_item.is_dead {
|
||||||
|
user_error("It doesn't really seem fair, but you realise you won't be able to attack anyone while you're dead!".to_string())?;
|
||||||
|
}
|
||||||
|
|
||||||
let attack_whom = search_item_for_user(ctx, &ItemSearchParams {
|
let attack_whom = search_item_for_user(ctx, &ItemSearchParams {
|
||||||
include_loc_contents: true,
|
include_loc_contents: true,
|
||||||
..ItemSearchParams::base(&player_item, remaining)
|
..ItemSearchParams::base(&player_item, remaining)
|
||||||
|
@ -143,7 +143,10 @@ impl UserVerb for Verb {
|
|||||||
let player_item = get_player_item_or_fail(ctx).await?;
|
let player_item = get_player_item_or_fail(ctx).await?;
|
||||||
|
|
||||||
let rem_trim = remaining.trim().to_lowercase();
|
let rem_trim = remaining.trim().to_lowercase();
|
||||||
let (heretype, herecode) = player_item.location.split_once("/").unwrap_or(("room", "repro_xv_chargen"));
|
let use_location = if player_item.is_dead { "room/repro_xv_respawn" } else {
|
||||||
|
&player_item.location
|
||||||
|
};
|
||||||
|
let (heretype, herecode) = use_location.split_once("/").unwrap_or(("room", "repro_xv_chargen"));
|
||||||
let item: Arc<Item> = if rem_trim == "" {
|
let item: Arc<Item> = if rem_trim == "" {
|
||||||
ctx.trans.find_item_by_type_code(heretype, herecode).await?
|
ctx.trans.find_item_by_type_code(heretype, herecode).await?
|
||||||
.ok_or_else(|| UserError("Sorry, that no longer exists".to_owned()))?
|
.ok_or_else(|| UserError("Sorry, that no longer exists".to_owned()))?
|
||||||
|
@ -23,27 +23,27 @@ use crate::{
|
|||||||
broadcast_to_room,
|
broadcast_to_room,
|
||||||
skills::skill_check_and_grind,
|
skills::skill_check_and_grind,
|
||||||
combat::stop_attacking,
|
combat::stop_attacking,
|
||||||
|
combat::handle_resurrect,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
use std::time;
|
use std::time;
|
||||||
|
|
||||||
pub async fn announce_move(trans: &DBTrans, character: &Item, leaving: &Item, arriving: &Item) -> DResult<()> {
|
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_exp = format!("{} departs towards {}\n",
|
||||||
|
&character.display_for_sentence(true, 1, true),
|
||||||
|
&arriving.display);
|
||||||
let msg_leaving_nonexp = format!("{} departs towards {}\n",
|
let msg_leaving_nonexp = format!("{} departs towards {}\n",
|
||||||
character.display_less_explicit
|
character.display_for_sentence(true, 1, false),
|
||||||
.as_ref()
|
|
||||||
.unwrap_or(&character.display),
|
|
||||||
arriving.display_less_explicit
|
arriving.display_less_explicit
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap_or(&arriving.display));
|
.unwrap_or(&arriving.display));
|
||||||
broadcast_to_room(trans, &format!("{}/{}", &leaving.item_type, &leaving.item_code),
|
broadcast_to_room(trans, &format!("{}/{}", &leaving.item_type, &leaving.item_code),
|
||||||
None, &msg_leaving_exp, Some(&msg_leaving_nonexp)).await?;
|
None, &msg_leaving_exp, Some(&msg_leaving_nonexp)).await?;
|
||||||
|
|
||||||
let msg_arriving_exp = format!("{} arrives from {}\n", &character.display, &leaving.display);
|
let msg_arriving_exp = format!("{} arrives from {}\n", &character.display_for_sentence(true, 1, true),
|
||||||
|
&leaving.display);
|
||||||
let msg_arriving_nonexp = format!("{} arrives from {}\n",
|
let msg_arriving_nonexp = format!("{} arrives from {}\n",
|
||||||
character.display_less_explicit
|
character.display_for_sentence(true, 1, false),
|
||||||
.as_ref()
|
|
||||||
.unwrap_or(&character.display),
|
|
||||||
leaving.display_less_explicit
|
leaving.display_less_explicit
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap_or(&leaving.display));
|
.unwrap_or(&leaving.display));
|
||||||
@ -58,7 +58,15 @@ pub async fn attempt_move_immediate(
|
|||||||
direction: &Direction,
|
direction: &Direction,
|
||||||
mut player_ctx: Option<&mut VerbContext<'_>>
|
mut player_ctx: Option<&mut VerbContext<'_>>
|
||||||
) -> UResult<()> {
|
) -> UResult<()> {
|
||||||
let (heretype, herecode) = orig_mover.location.split_once("/").unwrap_or(("room", "repro_xv_chargen"));
|
let use_location = if orig_mover.is_dead {
|
||||||
|
if orig_mover.item_type != "player" {
|
||||||
|
user_error("Dead players don't move".to_owned())?;
|
||||||
|
}
|
||||||
|
"room/repro_xv_respawn"
|
||||||
|
} else {
|
||||||
|
&orig_mover.location
|
||||||
|
};
|
||||||
|
let (heretype, herecode) = use_location.split_once("/").unwrap_or(("room", "repro_xv_chargen"));
|
||||||
if heretype != "room" {
|
if heretype != "room" {
|
||||||
// Fix this when we have planes / boats / roomkits.
|
// Fix this when we have planes / boats / roomkits.
|
||||||
user_error("Navigating outside rooms not yet supported.".to_owned())?
|
user_error("Navigating outside rooms not yet supported.".to_owned())?
|
||||||
@ -115,9 +123,9 @@ pub async fn attempt_move_immediate(
|
|||||||
trans.queue_for_session(ctx.session,
|
trans.queue_for_session(ctx.session,
|
||||||
Some(&format!("You successfully get away from {}\n",
|
Some(&format!("You successfully get away from {}\n",
|
||||||
&attacker_names_str))).await?;
|
&attacker_names_str))).await?;
|
||||||
for item in &attacker_items[..] {
|
}
|
||||||
stop_attacking(trans, &item, &mover).await?;
|
for item in &attacker_items[..] {
|
||||||
}
|
stop_attacking(trans, &item, &mover).await?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if let Some(ctx) = player_ctx.as_ref() {
|
if let Some(ctx) = player_ctx.as_ref() {
|
||||||
@ -131,9 +139,16 @@ pub async fn attempt_move_immediate(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if mover.is_dead {
|
||||||
|
if !handle_resurrect(trans, &mut mover).await? {
|
||||||
|
user_error("You couldn't be resurrected.".to_string())?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mover.location = format!("{}/{}", "room", new_room.code);
|
mover.location = format!("{}/{}", "room", new_room.code);
|
||||||
mover.action_type = LocationActionType::Normal;
|
mover.action_type = LocationActionType::Normal;
|
||||||
mover.active_combat = None;
|
mover.active_combat = None;
|
||||||
|
|
||||||
trans.save_item_model(&mover).await?;
|
trans.save_item_model(&mover).await?;
|
||||||
|
|
||||||
if let Some(ctx) = player_ctx {
|
if let Some(ctx) = player_ctx {
|
||||||
|
@ -54,6 +54,9 @@ impl UserVerb for Verb {
|
|||||||
user_error("You need to provide a message to send.".to_owned())?;
|
user_error("You need to provide a message to send.".to_owned())?;
|
||||||
}
|
}
|
||||||
let player_item = get_player_item_or_fail(ctx).await?;
|
let player_item = get_player_item_or_fail(ctx).await?;
|
||||||
|
if player_item.is_dead {
|
||||||
|
user_error("Shush, the dead can't talk!".to_string())?;
|
||||||
|
}
|
||||||
say_to_room(ctx.trans, &player_item, &player_item.location,
|
say_to_room(ctx.trans, &player_item, &player_item.location,
|
||||||
&say_what, is_likely_explicit(&say_what)).await
|
&say_what, is_likely_explicit(&say_what)).await
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,9 @@ impl UserVerb for Verb {
|
|||||||
user_error("You need to provide a message to send.".to_owned())?;
|
user_error("You need to provide a message to send.".to_owned())?;
|
||||||
}
|
}
|
||||||
let player_item = get_player_item_or_fail(ctx).await?;
|
let player_item = get_player_item_or_fail(ctx).await?;
|
||||||
|
if player_item.is_dead {
|
||||||
|
user_error("Shush, the dead can't talk!".to_string())?;
|
||||||
|
}
|
||||||
let to_whom = search_item_for_user(ctx, &ItemSearchParams {
|
let to_whom = search_item_for_user(ctx, &ItemSearchParams {
|
||||||
include_loc_contents: true,
|
include_loc_contents: true,
|
||||||
..ItemSearchParams::base(&player_item, &to_whom_name)
|
..ItemSearchParams::base(&player_item, &to_whom_name)
|
||||||
|
@ -15,6 +15,12 @@ pub enum TaskDetails {
|
|||||||
npc_code: String,
|
npc_code: String,
|
||||||
say_code: String
|
say_code: String
|
||||||
},
|
},
|
||||||
|
NPCWander {
|
||||||
|
npc_code: String,
|
||||||
|
},
|
||||||
|
NPCAggro {
|
||||||
|
npc_code: String,
|
||||||
|
},
|
||||||
AttackTick,
|
AttackTick,
|
||||||
RecloneNPC {
|
RecloneNPC {
|
||||||
npc_code: String
|
npc_code: String
|
||||||
@ -29,6 +35,8 @@ impl TaskDetails {
|
|||||||
match self {
|
match self {
|
||||||
RunQueuedCommand => "RunQueuedCommand",
|
RunQueuedCommand => "RunQueuedCommand",
|
||||||
NPCSay { .. } => "NPCSay",
|
NPCSay { .. } => "NPCSay",
|
||||||
|
NPCWander { .. } => "NPCWander",
|
||||||
|
NPCAggro { .. } => "NPCAggro",
|
||||||
AttackTick => "AttackTick",
|
AttackTick => "AttackTick",
|
||||||
RecloneNPC { .. } => "RecloneNPC",
|
RecloneNPC { .. } => "RecloneNPC",
|
||||||
RotCorpse { .. } => "RotCorpse",
|
RotCorpse { .. } => "RotCorpse",
|
||||||
|
@ -34,6 +34,8 @@ fn task_handler_registry() -> &'static BTreeMap<&'static str, &'static (dyn Task
|
|||||||
|| vec!(
|
|| vec!(
|
||||||
("RunQueuedCommand", queued_command::HANDLER.clone()),
|
("RunQueuedCommand", queued_command::HANDLER.clone()),
|
||||||
("NPCSay", npc::SAY_HANDLER.clone()),
|
("NPCSay", npc::SAY_HANDLER.clone()),
|
||||||
|
("NPCWander", npc::WANDER_HANDLER.clone()),
|
||||||
|
("NPCAggro", npc::AGGRO_HANDLER.clone()),
|
||||||
("AttackTick", combat::TASK_HANDLER.clone()),
|
("AttackTick", combat::TASK_HANDLER.clone()),
|
||||||
("RecloneNPC", npc::RECLONE_HANDLER.clone()),
|
("RecloneNPC", npc::RECLONE_HANDLER.clone()),
|
||||||
("RotCorpse", combat::ROT_CORPSE_HANDLER.clone()),
|
("RotCorpse", combat::ROT_CORPSE_HANDLER.clone()),
|
||||||
|
@ -10,7 +10,7 @@ pub mod combat;
|
|||||||
pub async fn broadcast_to_room(trans: &DBTrans, location: &str, from_item: Option<&Item>,
|
pub async fn broadcast_to_room(trans: &DBTrans, location: &str, from_item: Option<&Item>,
|
||||||
message_explicit_ok: &str, message_nonexplicit: Option<&str>) -> DResult<()> {
|
message_explicit_ok: &str, message_nonexplicit: Option<&str>) -> DResult<()> {
|
||||||
for item in trans.find_items_by_location(location).await? {
|
for item in trans.find_items_by_location(location).await? {
|
||||||
if item.item_type != "player" {
|
if item.item_type != "player" || item.is_dead {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if let Some((session, session_dat)) = trans.find_session_for_player(&item.item_code).await? {
|
if let Some((session, session_dat)) = trans.find_session_for_player(&item.item_code).await? {
|
||||||
|
@ -22,6 +22,7 @@ use chrono::Utc;
|
|||||||
use async_recursion::async_recursion;
|
use async_recursion::async_recursion;
|
||||||
use std::time;
|
use std::time;
|
||||||
use ansi::ansi;
|
use ansi::ansi;
|
||||||
|
use rand::prelude::IteratorRandom;
|
||||||
use rand_distr::{Normal, Distribution};
|
use rand_distr::{Normal, Distribution};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -129,8 +130,41 @@ impl TaskHandler for AttackTaskHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn consider_xp_gain_for(trans: &DBTrans, by_item: &mut Item, for_item: &Item) -> DResult<()> {
|
||||||
|
if by_item.item_type != "player" {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
let (session, _) = match trans.find_session_for_player(&by_item.item_code).await? {
|
||||||
|
None => return Ok(()),
|
||||||
|
Some(r) => r
|
||||||
|
};
|
||||||
|
if by_item.total_xp >= for_item.total_xp {
|
||||||
|
trans.queue_for_session(&session, Some("[You didn't gain any experience for that]\n")).await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
let xp_gain =
|
||||||
|
(((for_item.total_xp - by_item.total_xp) as f64 * 10.0 / (by_item.total_xp + 1) as f64) as u64)
|
||||||
|
.min(100);
|
||||||
|
|
||||||
|
if xp_gain == 0 {
|
||||||
|
trans.queue_for_session(&session, Some("[You didn't gain any experience for that]\n")).await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
by_item.total_xp += xp_gain;
|
||||||
|
let mut user = match trans.find_by_username(&by_item.item_code).await? {
|
||||||
|
None => return Ok(()),
|
||||||
|
Some(r) => r
|
||||||
|
};
|
||||||
|
user.experience.xp_change_for_this_reroll += xp_gain as i64;
|
||||||
|
trans.save_user_model(&user).await?;
|
||||||
|
trans.queue_for_session(&session, Some(&format!("You gained {} experience points!\n", xp_gain))).await?;
|
||||||
|
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn handle_death(trans: &DBTrans, whom: &mut Item) -> DResult<()> {
|
pub async fn handle_death(trans: &DBTrans, whom: &mut Item) -> DResult<()> {
|
||||||
whom.is_dead = true;
|
|
||||||
let msg_exp = format!(
|
let msg_exp = format!(
|
||||||
ansi!("<red>{} stiffens and collapses dead.<reset>\n"),
|
ansi!("<red>{} stiffens and collapses dead.<reset>\n"),
|
||||||
&whom.display_for_sentence(true, 1, true)
|
&whom.display_for_sentence(true, 1, true)
|
||||||
@ -139,14 +173,17 @@ pub async fn handle_death(trans: &DBTrans, whom: &mut Item) -> DResult<()> {
|
|||||||
ansi!("<red>{} stiffens and collapses dead.<reset>\n"),
|
ansi!("<red>{} stiffens and collapses dead.<reset>\n"),
|
||||||
&whom.display_for_sentence(false, 1, true)
|
&whom.display_for_sentence(false, 1, true)
|
||||||
);
|
);
|
||||||
|
broadcast_to_room(trans, &whom.location, None, &msg_exp, Some(&msg_nonexp)).await?;
|
||||||
|
|
||||||
|
whom.is_dead = true;
|
||||||
if let Some(ac) = &whom.active_combat {
|
if let Some(ac) = &whom.active_combat {
|
||||||
let at_str = ac.attacking.clone();
|
let at_str = ac.attacking.clone();
|
||||||
for attacker in ac.attacked_by.clone().iter() {
|
for attacker in ac.attacked_by.clone().iter() {
|
||||||
if let Some((atype, acode)) = attacker.split_once("/") {
|
if let Some((atype, acode)) = attacker.split_once("/") {
|
||||||
if let Some(aitem) = trans.find_item_by_type_code(atype, acode).await? {
|
if let Some(aitem) = trans.find_item_by_type_code(atype, acode).await? {
|
||||||
let mut new_aitem = (*aitem).clone();
|
let mut new_aitem = (*aitem).clone();
|
||||||
stop_attacking_mut(trans, &mut new_aitem, whom).await?;
|
consider_xp_gain_for(trans, &mut new_aitem, &whom).await?;
|
||||||
|
stop_attacking_mut(trans, &mut new_aitem, whom, true).await?;
|
||||||
trans.save_item_model(&new_aitem).await?;
|
trans.save_item_model(&new_aitem).await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -154,7 +191,7 @@ pub async fn handle_death(trans: &DBTrans, whom: &mut Item) -> DResult<()> {
|
|||||||
if let Some((vtype, vcode)) = at_str.as_ref().and_then(|a| a.split_once("/")) {
|
if let Some((vtype, vcode)) = at_str.as_ref().and_then(|a| a.split_once("/")) {
|
||||||
if let Some(vitem) = trans.find_item_by_type_code(vtype, vcode).await? {
|
if let Some(vitem) = trans.find_item_by_type_code(vtype, vcode).await? {
|
||||||
let mut new_vitem = (*vitem).clone();
|
let mut new_vitem = (*vitem).clone();
|
||||||
stop_attacking_mut(trans, whom, &mut new_vitem).await?;
|
stop_attacking_mut(trans, whom, &mut new_vitem, false).await?;
|
||||||
trans.save_item_model(&new_vitem).await?;
|
trans.save_item_model(&new_vitem).await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -171,8 +208,29 @@ pub async fn handle_death(trans: &DBTrans, whom: &mut Item) -> DResult<()> {
|
|||||||
}
|
}
|
||||||
}).await?;
|
}).await?;
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn handle_resurrect(trans: &DBTrans, player: &mut Item) -> DResult<bool> {
|
||||||
|
corpsify_item(trans, &player).await?;
|
||||||
|
player.is_dead = false;
|
||||||
|
let lost_xp = (player.total_xp / 200).max(10).min(player.total_xp);
|
||||||
|
let (session, _) = match trans.find_session_for_player(&player.item_code).await? {
|
||||||
|
None => return Ok(false),
|
||||||
|
Some(r) => r
|
||||||
|
};
|
||||||
|
let mut user = match trans.find_by_username(&player.item_code).await? {
|
||||||
|
None => return Ok(false),
|
||||||
|
Some(r) => r
|
||||||
|
};
|
||||||
|
trans.queue_for_session(&session,
|
||||||
|
Some(&format!("You lost {} experience points by dying.\n", lost_xp))).await?;
|
||||||
|
player.total_xp -= lost_xp;
|
||||||
|
user.experience.xp_change_for_this_reroll -= lost_xp as i64;
|
||||||
|
player.health = max_health(&player);
|
||||||
|
|
||||||
broadcast_to_room(trans, &whom.location, None, &msg_exp, Some(&msg_nonexp)).await
|
trans.save_user_model(&user).await?;
|
||||||
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn max_health(_whom: &Item) -> u64 {
|
pub fn max_health(_whom: &Item) -> u64 {
|
||||||
@ -181,7 +239,8 @@ pub fn max_health(_whom: &Item) -> u64 {
|
|||||||
|
|
||||||
pub static TASK_HANDLER: &(dyn TaskHandler + Sync + Send) = &AttackTaskHandler;
|
pub static TASK_HANDLER: &(dyn TaskHandler + Sync + Send) = &AttackTaskHandler;
|
||||||
|
|
||||||
pub async fn stop_attacking_mut(trans: &DBTrans, new_by_whom: &mut Item, new_to_whom: &mut Item) ->
|
pub async fn stop_attacking_mut(trans: &DBTrans, new_by_whom: &mut Item, new_to_whom: &mut Item,
|
||||||
|
auto_refocus: bool) ->
|
||||||
DResult<()>
|
DResult<()>
|
||||||
{
|
{
|
||||||
trans.delete_task("AttackTick",
|
trans.delete_task("AttackTick",
|
||||||
@ -194,6 +253,19 @@ pub async fn stop_attacking_mut(trans: &DBTrans, new_by_whom: &mut Item, new_to_
|
|||||||
}
|
}
|
||||||
if let Some(ac) = new_by_whom.active_combat.as_mut() {
|
if let Some(ac) = new_by_whom.active_combat.as_mut() {
|
||||||
ac.attacking = None;
|
ac.attacking = None;
|
||||||
|
if auto_refocus {
|
||||||
|
let old_vic = format!("{}/{}", new_to_whom.item_type, new_to_whom.item_code);
|
||||||
|
let new_vic_opt = ac.attacked_by.iter().filter(|i| **i != old_vic).choose(&mut rand::thread_rng());
|
||||||
|
if let Some(new_vic) = new_vic_opt {
|
||||||
|
if let Some((vtype, vcode)) = new_vic.split_once("/") {
|
||||||
|
if let Some(vic_item) = trans.find_item_by_type_code(vtype, vcode).await? {
|
||||||
|
let mut new_vic_item = (*vic_item).clone();
|
||||||
|
start_attack_mut(trans, new_by_whom, &mut new_vic_item);
|
||||||
|
trans.save_item_model(&new_vic_item).await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
new_by_whom.action_type = LocationActionType::Normal;
|
new_by_whom.action_type = LocationActionType::Normal;
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -203,7 +275,7 @@ pub async fn stop_attacking_mut(trans: &DBTrans, new_by_whom: &mut Item, new_to_
|
|||||||
pub async fn stop_attacking(trans: &DBTrans, by_whom: &Item, to_whom: &Item) -> DResult<()> {
|
pub async fn stop_attacking(trans: &DBTrans, by_whom: &Item, to_whom: &Item) -> DResult<()> {
|
||||||
let mut new_by_whom = (*by_whom).clone();
|
let mut new_by_whom = (*by_whom).clone();
|
||||||
let mut new_to_whom = (*to_whom).clone();
|
let mut new_to_whom = (*to_whom).clone();
|
||||||
stop_attacking_mut(trans, &mut new_by_whom, &mut new_to_whom).await?;
|
stop_attacking_mut(trans, &mut new_by_whom, &mut new_to_whom, false).await?;
|
||||||
trans.save_item_model(&new_by_whom).await?;
|
trans.save_item_model(&new_by_whom).await?;
|
||||||
trans.save_item_model(&new_to_whom).await?;
|
trans.save_item_model(&new_to_whom).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -228,6 +300,16 @@ fn attack_speed(_who: &Item) -> time::Duration {
|
|||||||
|
|
||||||
#[async_recursion]
|
#[async_recursion]
|
||||||
pub async fn start_attack(trans: &DBTrans, by_whom: &Item, to_whom: &Item) -> UResult<()> {
|
pub async fn start_attack(trans: &DBTrans, by_whom: &Item, to_whom: &Item) -> UResult<()> {
|
||||||
|
let mut by_whom_for_update = by_whom.clone();
|
||||||
|
let mut to_whom_for_update = to_whom.clone();
|
||||||
|
start_attack_mut(trans, &mut by_whom_for_update, &mut to_whom_for_update).await?;
|
||||||
|
trans.save_item_model(&by_whom_for_update).await?;
|
||||||
|
trans.save_item_model(&to_whom_for_update).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_recursion]
|
||||||
|
pub async fn start_attack_mut(trans: &DBTrans, by_whom: &mut Item, to_whom: &mut Item) -> UResult<()> {
|
||||||
let mut msg_exp = String::new();
|
let mut msg_exp = String::new();
|
||||||
let mut msg_nonexp = String::new();
|
let mut msg_nonexp = String::new();
|
||||||
let mut verb: String = "attacks".to_string();
|
let mut verb: String = "attacks".to_string();
|
||||||
@ -272,13 +354,11 @@ pub async fn start_attack(trans: &DBTrans, by_whom: &Item, to_whom: &Item) -> UR
|
|||||||
|
|
||||||
broadcast_to_room(trans, &by_whom.location, None::<&Item>, &msg_exp, Some(msg_nonexp.as_str())).await?;
|
broadcast_to_room(trans, &by_whom.location, None::<&Item>, &msg_exp, Some(msg_nonexp.as_str())).await?;
|
||||||
|
|
||||||
let mut by_whom_for_update = by_whom.clone();
|
by_whom.active_combat.get_or_insert_with(|| Default::default()).attacking =
|
||||||
by_whom_for_update.active_combat.get_or_insert_with(|| Default::default()).attacking =
|
|
||||||
Some(format!("{}/{}",
|
Some(format!("{}/{}",
|
||||||
&to_whom.item_type, &to_whom.item_code));
|
&to_whom.item_type, &to_whom.item_code));
|
||||||
by_whom_for_update.action_type = LocationActionType::Attacking(Subattack::Normal);
|
by_whom.action_type = LocationActionType::Attacking(Subattack::Normal);
|
||||||
let mut to_whom_for_update = to_whom.clone();
|
to_whom.active_combat.get_or_insert_with(|| Default::default()).attacked_by.push(
|
||||||
to_whom_for_update.active_combat.get_or_insert_with(|| Default::default()).attacked_by.push(
|
|
||||||
format!("{}/{}",
|
format!("{}/{}",
|
||||||
&by_whom.item_type, &by_whom.item_code)
|
&by_whom.item_type, &by_whom.item_code)
|
||||||
);
|
);
|
||||||
@ -292,11 +372,9 @@ pub async fn start_attack(trans: &DBTrans, by_whom: &Item, to_whom: &Item) -> UR
|
|||||||
},
|
},
|
||||||
details: TaskDetails::AttackTick
|
details: TaskDetails::AttackTick
|
||||||
}).await?;
|
}).await?;
|
||||||
trans.save_item_model(&by_whom_for_update).await?;
|
|
||||||
trans.save_item_model(&to_whom_for_update).await?;
|
|
||||||
// Auto-counterattack if victim isn't busy.
|
// Auto-counterattack if victim isn't busy.
|
||||||
if to_whom_for_update.active_combat.as_ref().and_then(|ac| ac.attacking.as_ref()) == None {
|
if to_whom.active_combat.as_ref().and_then(|ac| ac.attacking.as_ref()) == None {
|
||||||
start_attack(trans, &to_whom_for_update, &by_whom_for_update).await?;
|
start_attack(trans, &to_whom, &by_whom).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -50,6 +50,14 @@ fn static_task_registry() -> Vec<StaticThingTypeGroup<StaticTask>> {
|
|||||||
thing_type: "NPCSay",
|
thing_type: "NPCSay",
|
||||||
things: || npc::npc_say_tasks()
|
things: || npc::npc_say_tasks()
|
||||||
},
|
},
|
||||||
|
StaticThingTypeGroup::<StaticTask> {
|
||||||
|
thing_type: "NPCWander",
|
||||||
|
things: || npc::npc_wander_tasks()
|
||||||
|
},
|
||||||
|
StaticThingTypeGroup::<StaticTask> {
|
||||||
|
thing_type: "NPCAggro",
|
||||||
|
things: || npc::npc_aggro_tasks()
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,11 @@ use super::{
|
|||||||
StaticItem,
|
StaticItem,
|
||||||
StaticTask,
|
StaticTask,
|
||||||
possession_type::PossessionType,
|
possession_type::PossessionType,
|
||||||
species::SpeciesType
|
species::SpeciesType,
|
||||||
|
room::{
|
||||||
|
room_map_by_code,
|
||||||
|
resolve_exit
|
||||||
|
}
|
||||||
};
|
};
|
||||||
use crate::models::{
|
use crate::models::{
|
||||||
item::{Item, Pronouns, SkillType},
|
item::{Item, Pronouns, SkillType},
|
||||||
@ -12,13 +16,15 @@ use crate::services::{
|
|||||||
combat::{
|
combat::{
|
||||||
max_health,
|
max_health,
|
||||||
corpsify_item,
|
corpsify_item,
|
||||||
|
start_attack,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use crate::message_handler::user_commands::{
|
use crate::message_handler::user_commands::{
|
||||||
VerbContext, UResult, CommandHandlingError,
|
VerbContext, UResult, CommandHandlingError,
|
||||||
say::say_to_room
|
say::say_to_room,
|
||||||
|
movement::attempt_move_immediate,
|
||||||
};
|
};
|
||||||
use crate::DResult;
|
use crate::DResult;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
@ -66,9 +72,12 @@ pub struct NPC {
|
|||||||
pub aliases: Vec<&'static str>,
|
pub aliases: Vec<&'static str>,
|
||||||
pub says: Vec<NPCSayInfo>,
|
pub says: Vec<NPCSayInfo>,
|
||||||
pub attackable: bool,
|
pub attackable: bool,
|
||||||
|
pub aggression: u64,
|
||||||
pub intrinsic_weapon: Option<PossessionType>,
|
pub intrinsic_weapon: Option<PossessionType>,
|
||||||
|
pub total_xp: u64,
|
||||||
pub total_skills: BTreeMap<SkillType, f64>,
|
pub total_skills: BTreeMap<SkillType, f64>,
|
||||||
pub species: SpeciesType,
|
pub species: SpeciesType,
|
||||||
|
pub wander_zones: Vec<&'static str>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for NPC {
|
impl Default for NPC {
|
||||||
@ -82,10 +91,13 @@ impl Default for NPC {
|
|||||||
message_handler: None,
|
message_handler: None,
|
||||||
aliases: vec!(),
|
aliases: vec!(),
|
||||||
says: vec!(),
|
says: vec!(),
|
||||||
|
total_xp: 1000,
|
||||||
total_skills: SkillType::values().into_iter().map(|sk| (sk, 10.0)).collect(),
|
total_skills: SkillType::values().into_iter().map(|sk| (sk, 10.0)).collect(),
|
||||||
attackable: false,
|
attackable: false,
|
||||||
|
aggression: 0,
|
||||||
intrinsic_weapon: None,
|
intrinsic_weapon: None,
|
||||||
species: SpeciesType::Human,
|
species: SpeciesType::Human,
|
||||||
|
wander_zones: vec!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -174,6 +186,54 @@ pub fn npc_say_tasks() -> Box<dyn Iterator<Item = StaticTask>> {
|
|||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn npc_wander_tasks() -> Box<dyn Iterator<Item = StaticTask>> {
|
||||||
|
Box::new(npc_list().iter().filter(|c| !c.wander_zones.is_empty())
|
||||||
|
.map(|c| StaticTask {
|
||||||
|
task_code: c.code.to_owned(),
|
||||||
|
initial_task: Box::new(
|
||||||
|
|| {
|
||||||
|
let mut rng = thread_rng();
|
||||||
|
Task {
|
||||||
|
meta: TaskMeta {
|
||||||
|
task_code: c.code.to_owned(),
|
||||||
|
is_static: true,
|
||||||
|
recurrence: Some(TaskRecurrence::FixedDuration { seconds: rng.gen_range(100..150) as u32 }),
|
||||||
|
next_scheduled: Utc::now() + chrono::Duration::seconds(rng.gen_range(0..30) as i64),
|
||||||
|
..TaskMeta::default()
|
||||||
|
},
|
||||||
|
details: TaskDetails::NPCWander {
|
||||||
|
npc_code: c.code.to_owned(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn npc_aggro_tasks() -> Box<dyn Iterator<Item = StaticTask>> {
|
||||||
|
Box::new(npc_list().iter().filter(|c| c.aggression != 0)
|
||||||
|
.map(|c| StaticTask {
|
||||||
|
task_code: c.code.to_owned(),
|
||||||
|
initial_task: Box::new(
|
||||||
|
|| {
|
||||||
|
let mut rng = thread_rng();
|
||||||
|
let aggro_time = (rng.gen_range(100..150) as u64) / c.aggression;
|
||||||
|
Task {
|
||||||
|
meta: TaskMeta {
|
||||||
|
task_code: c.code.to_owned(),
|
||||||
|
is_static: true,
|
||||||
|
recurrence: Some(TaskRecurrence::FixedDuration { seconds: aggro_time as u32 }),
|
||||||
|
next_scheduled: Utc::now() + chrono::Duration::seconds(rng.gen_range(0..aggro_time) as i64),
|
||||||
|
..TaskMeta::default()
|
||||||
|
},
|
||||||
|
details: TaskDetails::NPCAggro {
|
||||||
|
npc_code: c.code.to_owned(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pub struct NPCSayTaskHandler;
|
pub struct NPCSayTaskHandler;
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl TaskHandler for NPCSayTaskHandler {
|
impl TaskHandler for NPCSayTaskHandler {
|
||||||
@ -226,6 +286,105 @@ impl TaskHandler for NPCSayTaskHandler {
|
|||||||
}
|
}
|
||||||
pub static SAY_HANDLER: &'static (dyn TaskHandler + Sync + Send) = &NPCSayTaskHandler;
|
pub static SAY_HANDLER: &'static (dyn TaskHandler + Sync + Send) = &NPCSayTaskHandler;
|
||||||
|
|
||||||
|
pub struct NPCWanderTaskHandler;
|
||||||
|
#[async_trait]
|
||||||
|
impl TaskHandler for NPCWanderTaskHandler {
|
||||||
|
async fn do_task(&self, ctx: &mut TaskRunContext) -> DResult<Option<time::Duration>> {
|
||||||
|
let npc_code = match &ctx.task.details {
|
||||||
|
TaskDetails::NPCWander { npc_code } => npc_code.clone(),
|
||||||
|
_ => Err("Expected NPCWander type")?
|
||||||
|
};
|
||||||
|
let npc = match npc_by_code().get(npc_code.as_str()) {
|
||||||
|
None => {
|
||||||
|
info!("NPC {} is gone / not yet in static items, ignoring in wander handler", &npc_code);
|
||||||
|
return Ok(None)
|
||||||
|
},
|
||||||
|
Some(r) => r
|
||||||
|
};
|
||||||
|
let item = match ctx.trans.find_item_by_type_code("npc", &npc_code).await? {
|
||||||
|
None => {
|
||||||
|
info!("NPC {} is gone / not yet in DB, ignoring in wander handler", &npc_code);
|
||||||
|
return Ok(None)
|
||||||
|
},
|
||||||
|
Some(r) => r
|
||||||
|
};
|
||||||
|
if item.is_dead {
|
||||||
|
return Ok(None)
|
||||||
|
}
|
||||||
|
let (ltype, lcode) = match item.location.split_once("/") {
|
||||||
|
None => return Ok(None),
|
||||||
|
Some(r) => r
|
||||||
|
};
|
||||||
|
if ltype != "room" {
|
||||||
|
let mut new_item = (*item).clone();
|
||||||
|
new_item.location = npc.spawn_location.to_owned();
|
||||||
|
ctx.trans.save_item_model(&new_item).await?;
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
let room = match room_map_by_code().get(lcode) {
|
||||||
|
None => {
|
||||||
|
let mut new_item = (*item).clone();
|
||||||
|
new_item.location = npc.spawn_location.to_owned();
|
||||||
|
ctx.trans.save_item_model(&new_item).await?;
|
||||||
|
return Ok(None);
|
||||||
|
},
|
||||||
|
Some(r) => r
|
||||||
|
};
|
||||||
|
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).unwrap_or(false)
|
||||||
|
);
|
||||||
|
let dir_opt = ex_iter.choose(&mut thread_rng()).map(|ex| ex.direction.clone()).clone();
|
||||||
|
if let Some(dir) = dir_opt {
|
||||||
|
match attempt_move_immediate(ctx.trans, &item, &dir, None).await {
|
||||||
|
Ok(()) | Err(CommandHandlingError::UserError(_)) => {},
|
||||||
|
Err(CommandHandlingError::SystemError(e)) => Err(e)?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub static WANDER_HANDLER: &'static (dyn TaskHandler + Sync + Send) = &NPCWanderTaskHandler;
|
||||||
|
|
||||||
|
pub struct NPCAggroTaskHandler;
|
||||||
|
#[async_trait]
|
||||||
|
impl TaskHandler for NPCAggroTaskHandler {
|
||||||
|
async fn do_task(&self, ctx: &mut TaskRunContext) -> DResult<Option<time::Duration>> {
|
||||||
|
let npc_code = match &ctx.task.details {
|
||||||
|
TaskDetails::NPCAggro { npc_code } => npc_code.clone(),
|
||||||
|
_ => Err("Expected NPCAggro type")?
|
||||||
|
};
|
||||||
|
let item = match ctx.trans.find_item_by_type_code("npc", &npc_code).await? {
|
||||||
|
None => {
|
||||||
|
info!("NPC {} is gone / not yet in DB, ignoring in aggro handler", &npc_code);
|
||||||
|
return Ok(None)
|
||||||
|
},
|
||||||
|
Some(r) => r
|
||||||
|
};
|
||||||
|
if item.is_dead || item.active_combat.as_ref().map(|ac| ac.attacking.is_some()).unwrap_or(false) {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
let items_loc = ctx.trans.find_items_by_location(&item.location).await?;
|
||||||
|
let vic_opt = items_loc
|
||||||
|
.iter()
|
||||||
|
.filter(|it| (it.item_type == "player" || it.item_type == "npc") &&
|
||||||
|
!it.is_dead && (it.item_type != item.item_type || it.item_code != item.item_code))
|
||||||
|
.choose(&mut thread_rng());
|
||||||
|
if let Some(victim) = vic_opt {
|
||||||
|
match start_attack(ctx.trans, &item, victim).await {
|
||||||
|
Ok(()) | Err(CommandHandlingError::UserError(_)) => {}
|
||||||
|
Err(CommandHandlingError::SystemError(e)) => Err(e)?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub static AGGRO_HANDLER: &'static (dyn TaskHandler + Sync + Send) = &NPCAggroTaskHandler;
|
||||||
|
|
||||||
pub struct NPCRecloneTaskHandler;
|
pub struct NPCRecloneTaskHandler;
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl TaskHandler for NPCRecloneTaskHandler {
|
impl TaskHandler for NPCRecloneTaskHandler {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use super::{NPC, NPCSayInfo, NPCSayType};
|
use super::{NPC, NPCSayInfo, NPCSayType};
|
||||||
|
use crate::models::item::Pronouns;
|
||||||
|
|
||||||
pub fn npc_list() -> Vec<NPC> {
|
pub fn npc_list() -> Vec<NPC> {
|
||||||
use NPCSayType::FromFixedList;
|
use NPCSayType::FromFixedList;
|
||||||
@ -17,547 +18,82 @@ pub fn npc_list() -> Vec<NPC> {
|
|||||||
))
|
))
|
||||||
};
|
};
|
||||||
|
|
||||||
vec!(
|
macro_rules! citizen {
|
||||||
NPC {
|
($code: expr, $name: expr, $spawn: expr, $pronouns: expr) => {
|
||||||
code: "melbs_citizen_1",
|
NPC {
|
||||||
name: "Matthew Thomas",
|
code: concat!("melbs_citizen_", $code),
|
||||||
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
|
name: $name,
|
||||||
spawn_location: "room/melbs_kingst_latrobest",
|
pronouns: $pronouns,
|
||||||
message_handler: None,
|
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
|
||||||
says: vec!(melbs_citizen_stdsay.clone()),
|
spawn_location: concat!("room/melbs_", $spawn),
|
||||||
..Default::default()
|
message_handler: None,
|
||||||
},
|
wander_zones: vec!("melbs"),
|
||||||
NPC {
|
says: vec!(melbs_citizen_stdsay.clone()),
|
||||||
code: "melbs_citizen_2",
|
..Default::default()
|
||||||
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 {
|
vec!(
|
||||||
code: "melbs_citizen_3",
|
citizen!("1", "Matthew Thomas", "kingst_latrobest", Pronouns::default_male()),
|
||||||
name: "Kimberly Jackson",
|
citizen!("2", "Matthew Perez", "kingst_20", Pronouns::default_male()),
|
||||||
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
|
citizen!("3", "Kimberly Jackson", "kingst_40", Pronouns::default_female()),
|
||||||
spawn_location: "room/melbs_kingst_40",
|
citizen!("4", "Michael Sanchez", "kingst_50", Pronouns::default_male()),
|
||||||
message_handler: None,
|
citizen!("5", "Jessica Davis", "kingst_bourkest", Pronouns::default_female()),
|
||||||
says: vec!(melbs_citizen_stdsay.clone()),
|
citizen!("6", "Robert Davis", "kingst_70", Pronouns::default_male()),
|
||||||
..Default::default()
|
citizen!("7", "Paul Lewis", "kingst_90", Pronouns::default_male()),
|
||||||
},
|
citizen!("8", "Andrew Moore", "kingst_collinsst", Pronouns::default_male()),
|
||||||
NPC {
|
citizen!("9", "Betty Thomas", "kingst_100", Pronouns::default_female()),
|
||||||
code: "melbs_citizen_4",
|
citizen!("10", "Mary Robinson", "kingst_110", Pronouns::default_female()),
|
||||||
name: "Michael Sanchez",
|
citizen!("11", "Lisa Lopez", "kingst_flinderst", Pronouns::default_female()),
|
||||||
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
|
citizen!("12", "Kimberly Martinez", "flindersst_200", Pronouns::default_female()),
|
||||||
spawn_location: "room/melbs_kingst_50",
|
citizen!("13", "Anthony Nguyen", "flindersst_190", Pronouns::default_male()),
|
||||||
message_handler: None,
|
citizen!("14", "Joshua Green", "flindersst_180", Pronouns::default_male()),
|
||||||
says: vec!(melbs_citizen_stdsay.clone()),
|
citizen!("15", "Emily Wright", "flindersst_170", Pronouns::default_female()),
|
||||||
..Default::default()
|
citizen!("16", "Ashley Thomas", "lonsdalest_130", Pronouns::default_male()),
|
||||||
},
|
citizen!("17", "Jessica Miller", "kingst_80", Pronouns::default_female()),
|
||||||
NPC {
|
citizen!("18", "Anthony Lopez", "lonsdalest_140", Pronouns::default_male()),
|
||||||
code: "melbs_citizen_5",
|
citizen!("19", "John Lopez", "elizabethst_lonsdalest", Pronouns::default_male()),
|
||||||
name: "Jessica Davis",
|
citizen!("20", "Thomas Garcia", "williamsst_120", Pronouns::default_male()),
|
||||||
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
|
citizen!("21", "Donna Thompson", "elizabethst_60", Pronouns::default_female()),
|
||||||
spawn_location: "room/melbs_kingst_bourkest",
|
citizen!("22", "Matthew Davis", "williamsst_100", Pronouns::default_male()),
|
||||||
message_handler: None,
|
citizen!("23", "Steven Jones", "swanstonst_120", Pronouns::default_male()),
|
||||||
says: vec!(melbs_citizen_stdsay.clone()),
|
citizen!("24", "Linda Smith", "swanstonst_lonsdalest", Pronouns::default_male()),
|
||||||
..Default::default()
|
citizen!("25", "Karen Rodriguez", "bourkest_180", Pronouns::default_female()),
|
||||||
},
|
citizen!("26", "Paul Scott", "swanstonst_70", Pronouns::default_male()),
|
||||||
NPC {
|
citizen!("27", "Ashley Thomas", "lonsdalest_130", Pronouns::default_male()),
|
||||||
code: "melbs_citizen_6",
|
citizen!("28", "Sandra Scott", "elizabethst_30", Pronouns::default_female()),
|
||||||
name: "Robert Davis",
|
citizen!("29", "Michael Rodriguez", "swanstonst_70", Pronouns::default_male()),
|
||||||
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
|
citizen!("30", "Donald Miller", "elizabethst_30", Pronouns::default_male()),
|
||||||
spawn_location: "room/melbs_kingst_70",
|
citizen!("31", "Charles Moore", "lonsdalest_160", Pronouns::default_male()),
|
||||||
message_handler: None,
|
citizen!("32", "Ashley Sanchez", "kingst_100", Pronouns::default_male()),
|
||||||
says: vec!(melbs_citizen_stdsay.clone()),
|
citizen!("33", "Margaret Lewis", "flindersst_180", Pronouns::default_female()),
|
||||||
..Default::default()
|
citizen!("34", "Sandra Thompson", "swanstonst_80", Pronouns::default_female()),
|
||||||
},
|
citizen!("35", "Sandra King", "lonsdalest_150", Pronouns::default_female()),
|
||||||
NPC {
|
citizen!("36", "Lisa Anderson", "lonsdalest_210", Pronouns::default_female()),
|
||||||
code: "melbs_citizen_7",
|
citizen!("37", "Kimberly Martin", "kingst_80", Pronouns::default_female()),
|
||||||
name: "Paul Lewis",
|
citizen!("38", "Susan Smith", "latrobest_190", Pronouns::default_female()),
|
||||||
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
|
citizen!("39", "Susan Martin", "collinsst_150", Pronouns::default_female()),
|
||||||
spawn_location: "room/melbs_kingst_90",
|
citizen!("40", "Linda Scott", "williamsst_30", Pronouns::default_female()),
|
||||||
message_handler: None,
|
citizen!("41", "Donald Miller", "elizabethst_80", Pronouns::default_male()),
|
||||||
says: vec!(melbs_citizen_stdsay.clone()),
|
citizen!("42", "Mark Hill", "collinsst_120", Pronouns::default_male()),
|
||||||
..Default::default()
|
citizen!("43", "William Perez", "queenst_90", Pronouns::default_male()),
|
||||||
},
|
citizen!("44", "Donald Perez", "queenst_lonsdalest", Pronouns::default_male()),
|
||||||
NPC {
|
citizen!("45", "Lisa Rodriguez", "collinsst_100", Pronouns::default_female()),
|
||||||
code: "melbs_citizen_8",
|
citizen!("46", "James Adams", "latrobest_150", Pronouns::default_male()),
|
||||||
name: "Andrew Moore",
|
citizen!("47", "James Moore", "latrobest_130", Pronouns::default_male()),
|
||||||
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
|
citizen!("48", "Joseph Martin", "bourkest_150", Pronouns::default_male()),
|
||||||
spawn_location: "room/melbs_kingst_collinsst",
|
citizen!("49", "Matthew Jones", "kingst_60", Pronouns::default_male()),
|
||||||
message_handler: None,
|
citizen!("50", "Michael Sanchez", "queenst_100", Pronouns::default_male()),
|
||||||
says: vec!(melbs_citizen_stdsay.clone()),
|
citizen!("51", "Donna Torres", "flindersst_150", Pronouns::default_female()),
|
||||||
..Default::default()
|
citizen!("52", "Barbara Garcia", "swanstonst_50", Pronouns::default_female()),
|
||||||
},
|
citizen!("53", "Daniel Miller", "bourkest_110", Pronouns::default_male()),
|
||||||
NPC {
|
citizen!("54", "Robert Young", "kingst_collinsst", Pronouns::default_male()),
|
||||||
code: "melbs_citizen_9",
|
citizen!("55", "Donald Flores", "swanstonst_40", Pronouns::default_male()),
|
||||||
name: "Betty Thomas",
|
citizen!("56", "Charles Thomas", "flindersst_110", Pronouns::default_male()),
|
||||||
description: "A fairly ordinary looking citizen of Melbs, clearly weary from the harst reality of post-apocalyptic life",
|
citizen!("57", "William Torres", "swanstonst_60", Pronouns::default_male()),
|
||||||
spawn_location: "room/melbs_kingst_100",
|
citizen!("58", "Barbara Gonzalez", "collinsst_190", Pronouns::default_female()),
|
||||||
message_handler: None,
|
citizen!("59", "Mary Smith", "bourkest_180", Pronouns::default_female()),
|
||||||
says: vec!(melbs_citizen_stdsay.clone()),
|
citizen!("60", "Michael John", "williamsst_110", Pronouns::default_male()),
|
||||||
..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()
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,8 @@ macro_rules! dog {
|
|||||||
name: concat!($adj, " dog"),
|
name: concat!($adj, " dog"),
|
||||||
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
|
pronouns: Pronouns { is_proper: false, ..Pronouns::default_inanimate() },
|
||||||
attackable: true,
|
attackable: true,
|
||||||
|
aggression: 12,
|
||||||
|
wander_zones: vec!("melbs"),
|
||||||
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
|
description: "A malnourished looking dog. Its skeleton is visible through its thin and patchy fur. It smells terrible, and certainly doesn't look tame.",
|
||||||
aliases: vec!("dog"),
|
aliases: vec!("dog"),
|
||||||
spawn_location: concat!("room/", $spawn),
|
spawn_location: concat!("room/", $spawn),
|
||||||
|
@ -157,6 +157,7 @@ pub struct Room {
|
|||||||
pub description_less_explicit: Option<&'static str>,
|
pub description_less_explicit: Option<&'static str>,
|
||||||
pub exits: Vec<Exit>,
|
pub exits: Vec<Exit>,
|
||||||
pub should_caption: bool,
|
pub should_caption: bool,
|
||||||
|
pub repel_npc: bool,
|
||||||
pub item_flags: Vec<ItemFlag>
|
pub item_flags: Vec<ItemFlag>
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,6 +174,7 @@ impl Default for Room {
|
|||||||
description_less_explicit: None,
|
description_less_explicit: None,
|
||||||
exits: vec!(),
|
exits: vec!(),
|
||||||
should_caption: true,
|
should_caption: true,
|
||||||
|
repel_npc: false,
|
||||||
item_flags: vec!(),
|
item_flags: vec!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -181,6 +181,7 @@ pub fn room_list() -> Vec<Room> {
|
|||||||
),
|
),
|
||||||
should_caption: true,
|
should_caption: true,
|
||||||
item_flags: vec!(ItemFlag::NoSay, ItemFlag::NoSeeContents),
|
item_flags: vec!(ItemFlag::NoSay, ItemFlag::NoSeeContents),
|
||||||
|
repel_npc: true,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
Room {
|
Room {
|
||||||
|
Loading…
Reference in New Issue
Block a user