summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cli.rs8
-rw-r--r--src/main.rs31
-rw-r--r--src/rules/npcs.rs13
3 files changed, 42 insertions, 10 deletions
diff --git a/src/cli.rs b/src/cli.rs
index bc6c3a8..0c58461 100644
--- a/src/cli.rs
+++ b/src/cli.rs
@@ -33,6 +33,14 @@ pub fn cli() -> Command {
.short('c')
.long("class")
.help("The class of the NPC, e.g. fighter"),
+ )
+ .arg(
+ Arg::new("level")
+ .short('l')
+ .long("level")
+ .help("The level of the NPC, e.g 18")
+ .default_value("1")
+ .value_parser(clap::value_parser!(i32)),
),
),
)
diff --git a/src/main.rs b/src/main.rs
index 44c162c..85c90fe 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -27,10 +27,19 @@ fn main() {
std::process::exit(1);
});
+ let level = npc_matches
+ .get_one::<i32>("level")
+ .unwrap_or_else(|| {
+ eprintln!("Error: Couldn't parse level.");
+ std::process::exit(1);
+ })
+ .clone();
+
let mut npc = Npc::new(
Some(RANDOM_TABLES.roll_table("npc_alignment")),
None,
Some(class_ref),
+ level,
None,
None,
Vec::new(),
@@ -39,9 +48,14 @@ fn main() {
npc.add_random_magic_items();
println!(
- "{} {}. {}",
- npc.alignment.unwrap(),
+ "{} {} {}. {}",
+ npc.alignment
+ .unwrap()
+ .split_whitespace()
+ .map(|word| word.chars().next().unwrap())
+ .collect::<String>(),
npc.class.unwrap().name,
+ npc.level,
npc.magic_items
.iter()
.map(|item| item.name.clone())
@@ -70,6 +84,7 @@ fn main() {
Some(RANDOM_TABLES.roll_table("npc_alignment")),
Some(race_ref),
Some(class_ref),
+ 1,
None,
None,
Vec::new(),
@@ -86,7 +101,7 @@ fn main() {
// string literal at compile time.
if output_csv {
println!(
- "{},{},{},{},{},{},{},{},{},\"{}\"",
+ "{},{},{},{},{},{},{},{},{},{},\"{}\"",
npc.alignment
.unwrap()
.split_whitespace()
@@ -94,6 +109,7 @@ fn main() {
.collect::<String>(),
npc.race.unwrap().name,
npc.class.unwrap().name,
+ npc.level,
ability_scores.get_score(AbilityScore::Strength).unwrap(),
ability_scores
.get_score(AbilityScore::Intelligence)
@@ -108,10 +124,15 @@ fn main() {
);
} else {
println!(
- "{} {} {}. STR {}, INT {}, WIS {}, CON {}, DEX {}, CHA {}. {}",
- npc.alignment.unwrap(),
+ "{} {} {} {}. STR {}, INT {}, WIS {}, CON {}, DEX {}, CHA {}. {}",
+ npc.alignment
+ .unwrap()
+ .split_whitespace()
+ .map(|word| word.chars().next().unwrap())
+ .collect::<String>(),
npc.race.unwrap().name,
npc.class.unwrap().name,
+ npc.level,
ability_scores.get_score(AbilityScore::Strength).unwrap(),
ability_scores
.get_score(AbilityScore::Intelligence)
diff --git a/src/rules/npcs.rs b/src/rules/npcs.rs
index fe87e76..5477306 100644
--- a/src/rules/npcs.rs
+++ b/src/rules/npcs.rs
@@ -13,6 +13,7 @@ pub struct Npc {
pub alignment: Option<String>,
pub race: Option<&'static Race>,
pub class: Option<&'static Class>,
+ pub level: i32,
pub ability_scores: Option<AbilityScoreCollection>,
pub persona: Option<String>,
pub magic_items: Vec<&'static MagicItem>,
@@ -23,6 +24,7 @@ impl Npc {
alignment: Option<String>,
race: Option<&'static Race>,
class: Option<&'static Class>,
+ level: i32, // TODO: Multiclass and dualclass.
ability_scores: Option<AbilityScoreCollection>,
persona: Option<String>,
magic_items: Vec<&'static MagicItem>,
@@ -31,6 +33,7 @@ impl Npc {
alignment,
race,
class,
+ level,
ability_scores,
persona,
magic_items,
@@ -120,7 +123,6 @@ impl Npc {
// This uses the Appendix C method provided in the city/town section.
// I prefer it to the Monster Manual method and the NPC party method
// because it provides more variance.
- // TODO: Support other levels than 1st.
pub fn add_random_magic_items(&mut self) {
let mut rng = rand::thread_rng();
let class_ref = self.class.unwrap();
@@ -139,13 +141,13 @@ impl Npc {
];
for &kind_string in kind_strings_for_chances.iter() {
- if class_ref
+ let chance_per_level = class_ref
.chances_for_magic
.get(kind_string)
.copied()
- .unwrap_or(0)
- >= rng.gen_range(1..=100)
- {
+ .unwrap_or(0);
+ let chance = chance_per_level * self.level;
+ if chance >= rng.gen_range(1..=100) {
// For now, just get a dummy item named after the item type.
// Later, we'll add the actual magic items.
self.magic_items.push(
@@ -202,6 +204,7 @@ mod tests {
alignment: Some(String::from("Lawful Good")),
race: Some(race_ref),
class: Some(class_ref),
+ level: 1,
ability_scores: None,
persona: None,
magic_items: Vec::new(),