broken-battle/src/unit.rs
2023-08-14 15:50:27 -05:00

214 lines
6.3 KiB
Rust

use crate::equipment::EquipmentBlock;
use crate::statistics::StatBlock;
use crate::status::Status;
use rand::seq::SliceRandom;
use rand::Rng;
const MASC_NAMES: &'static [&'static str] = &["Antonio", "Brandon", "Charles", "Denzel", "Edgar"];
const FEMME_NAMES: &'static [&'static str] = &["Alice", "Bethany", "Cynthia", "Dawn", "Elizabeth"];
const NEUTR_NAMES: &'static [&'static str] = &["Aspen", "Blake", "Charlie", "Dekota", "Emery"];
#[derive(Debug, Copy, Clone)]
pub enum Gender {
Man,
Woman,
Nonbinary,
DemiGirl,
DemiBoy,
NoGender,
}
#[derive(Debug, Clone)]
pub struct Unit {
name: String,
level: u8,
exp: u32,
status: Option<(Option<Status>,Option<Status>)>,
gender: Gender,
base_stats: StatBlock,
hp: u16,
jel: u8,
jel_total: u8,
is_monster: bool,
equipment: Option<EquipmentBlock>,
}
impl Unit {
pub fn new() -> Unit {
let mut rng = rand::thread_rng();
let j = rng.gen_range(10..26);
Unit {
name: String::from("Basic Unit"),
level: 1,
exp: 0,
status: None,
gender: Gender::NoGender,
base_stats: StatBlock::new(),
hp: 18,
jel: j,
jel_total: j,
is_monster: true,
equipment: None,
}
}
pub fn name(self) -> String {
self.name
}
pub fn level(self) -> u8 {
self.level
}
pub fn gender(self) -> Gender {
self.gender
}
pub fn stats(self) -> StatBlock {
self.base_stats + self.stat_bonus()
}
pub fn base_stats(self) -> StatBlock {
self.base_stats
}
pub fn stat_bonus(self) -> StatBlock {
match self.equipment() {
Some(e) => e.bonuses(),
None => StatBlock::new_zero(),
}
}
pub fn hp(self) -> u16 {
self.hp
}
pub fn hp_max(self) -> u16 {
u16::from(
18u16
+ (u16::from(self.level)
* u16::from(0u8.wrapping_add_signed(self.stats().vitality()))),
)
}
pub fn jel(self) -> u8 {
self.jel
}
pub fn jel_total(self) -> u8 {
self.jel_total
}
pub fn is_monster(self) -> bool {
self.is_monster
}
pub fn equipment(self) -> Option<EquipmentBlock> {
if self.is_monster {
return None;
}
self.equipment
}
pub fn generate_gender() -> Gender {
let gender_variants = [
Gender::Man,
Gender::Woman,
Gender::Nonbinary,
Gender::DemiGirl,
Gender::DemiBoy,
];
match gender_variants.choose(&mut rand::thread_rng()) {
Some(g) => g.to_owned(),
None => Gender::NoGender,
}
}
pub fn generate_name(g: &Gender) -> String {
let names = match g {
Gender::Man => MASC_NAMES.to_vec(),
Gender::Woman => FEMME_NAMES.to_vec(),
Gender::Nonbinary => NEUTR_NAMES.to_vec(),
Gender::DemiGirl => [FEMME_NAMES, NEUTR_NAMES].concat(),
Gender::DemiBoy => [MASC_NAMES, NEUTR_NAMES].concat(),
Gender::NoGender => [MASC_NAMES, FEMME_NAMES, NEUTR_NAMES].concat(),
_ => return String::from("MISSINGNO"),
};
match names.choose(&mut rand::thread_rng()) {
Some(n) => String::from(n.clone()),
None => String::from("MISSINGNO"),
}
}
pub fn human_battle_maniac(lv: u8) -> Unit {
let mut rng = rand::thread_rng();
let mut j = rng.gen_range(10..26);
if lv > 20 {
j += rng.gen_range(10..26);
}
let g = Unit::generate_gender();
let n = format!("Battle Maniac {}", Unit::generate_name(&g)); // Excuse me, but may I
// borrow your gender for a
// moment?
let mut sb = StatBlock::new();
for _i in 0..lv {
match rng.gen_range(0..4) {
0 => sb.add_strength(1),
1 => sb.add_defense(1),
2 => sb.add_vitality(1),
3 => sb.add_intellect(1),
_ => {
eprintln!("ERROR! human_battle_maniac() stat assign out of bounds!");
sb.add_vitality(1);
},
};
}
let mut equip = EquipmentBlock::new();
//TODO: create equipment and equipment allocation algorithm
Unit {
name: n,
level: lv,
exp: 0, //TODO!! Fix this
status: None,
gender: g,
base_stats: sb.clone(),
hp: u16::from(
18u16 + (u16::from(lv) * u16::from(0u8.wrapping_add_signed(sb.vitality()))),
),
jel: j,
jel_total: j,
is_monster: false,
equipment: Some(equip),
}
}
pub fn human_street_samurai(lv: u8) -> Unit {
let mut rng = rand::thread_rng();
let mut j = rng.gen_range(10..26);
if rng.gen_range(0..100) < 25 && lv > 20 {
j += rng.gen_range(10..26);
}
let g = Unit::generate_gender();
let n = format!("Street Samurai {}", Unit::generate_name(&g));
let mut sb = StatBlock::new();
for _i in 0..lv {
match rng.gen_range(0..4) {
0 => sb.add_strength(1),
1 => sb.add_defense(1),
2 => sb.add_vitality(1),
3 => sb.add_agility(1),
_ => {
eprintln!("ERROR! human_street_samurai() stat assign out of bounds!");
sb.add_vitality(1);
},
};
}
let mut equip = EquipmentBlock::new();
//TODO: create equipment and equipment allocation algorithm
Unit {
name: n,
level: lv,
exp: 0, //TODO!! fix this
status: None,
gender: g,
base_stats: sb.clone(),
hp: u16::from(
18u16 + (u16::from(lv) * u16::from(0u8.wrapping_add_signed(sb.vitality()))),
),
jel: j,
jel_total: j,
is_monster: false,
equipment: Some(equip),
}
}
}