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), } } }