refactor: getter-traits durch pub-felder ersetzen, print_box wiederverwenden
This commit is contained in:
42
src/items.rs
42
src/items.rs
@@ -8,7 +8,7 @@ pub use armor::ItemArmor;
|
|||||||
pub use weapon::ItemWeapon;
|
pub use weapon::ItemWeapon;
|
||||||
|
|
||||||
// === ENUMS ===
|
// === ENUMS ===
|
||||||
#[derive(Clone, Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub enum ItemType {
|
pub enum ItemType {
|
||||||
Weapon,
|
Weapon,
|
||||||
OffHand,
|
OffHand,
|
||||||
@@ -23,10 +23,10 @@ pub enum ItemType {
|
|||||||
// === STRUCTS ===
|
// === STRUCTS ===
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct Item {
|
pub struct Item {
|
||||||
id: String,
|
pub id: String,
|
||||||
name: String,
|
pub name: String,
|
||||||
value: u32,
|
pub value: u32,
|
||||||
item_type: ItemType,
|
pub item_type: ItemType,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Rohform einer Item-Datei. Jede TOML nutzt `[[items]]` als Wurzel,
|
/// Rohform einer Item-Datei. Jede TOML nutzt `[[items]]` als Wurzel,
|
||||||
@@ -43,33 +43,6 @@ pub struct ItemCatalog {
|
|||||||
pub armors: Vec<ItemArmor>,
|
pub armors: Vec<ItemArmor>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// === TRAITS ===
|
|
||||||
pub trait ItemTrait {
|
|
||||||
fn get_id(&self) -> String;
|
|
||||||
fn get_name(&self) -> String;
|
|
||||||
fn get_value(&self) -> u32;
|
|
||||||
fn get_type(&self) -> ItemType;
|
|
||||||
}
|
|
||||||
|
|
||||||
// === IMPLEMENTS ===
|
|
||||||
impl ItemTrait for Item {
|
|
||||||
fn get_id(&self) -> String {
|
|
||||||
self.id.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_name(&self) -> String {
|
|
||||||
self.name.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_value(&self) -> u32 {
|
|
||||||
self.value
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_type(&self) -> ItemType {
|
|
||||||
self.item_type.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// === FUNCTIONS ===
|
// === FUNCTIONS ===
|
||||||
pub fn load_items() -> ItemCatalog {
|
pub fn load_items() -> ItemCatalog {
|
||||||
ItemCatalog {
|
ItemCatalog {
|
||||||
@@ -87,12 +60,13 @@ fn parse<T: DeserializeOwned>(raw: &str, file: &str) -> Vec<T> {
|
|||||||
/// Rahmen um beliebig viele Zeilen. Wird von jedem `print_values` genutzt.
|
/// Rahmen um beliebig viele Zeilen. Wird von jedem `print_values` genutzt.
|
||||||
pub(crate) fn print_box(lines: &[String]) {
|
pub(crate) fn print_box(lines: &[String]) {
|
||||||
let longest: usize = lines.iter().map(|l| l.chars().count()).max().unwrap_or(0);
|
let longest: usize = lines.iter().map(|l| l.chars().count()).max().unwrap_or(0);
|
||||||
|
let border: String = format!("+-{}-+", "-".repeat(longest));
|
||||||
|
|
||||||
println!("+-{}-+", "-".repeat(longest));
|
println!("{}", border);
|
||||||
for line in lines {
|
for line in lines {
|
||||||
println!("| {}{} |", line, " ".repeat(longest - line.chars().count()));
|
println!("| {}{} |", line, " ".repeat(longest - line.chars().count()));
|
||||||
}
|
}
|
||||||
println!("+-{}-+", "-".repeat(longest));
|
println!("{}", border);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -1,46 +1,22 @@
|
|||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
use super::{Item, ItemTrait, ItemType, print_box};
|
use super::{Item, print_box};
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct ItemArmor {
|
pub struct ItemArmor {
|
||||||
armor: u32,
|
pub armor: u32,
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
item: Item,
|
pub item: Item,
|
||||||
}
|
|
||||||
|
|
||||||
impl ItemTrait for ItemArmor {
|
|
||||||
fn get_id(&self) -> String {
|
|
||||||
self.item.get_id()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_name(&self) -> String {
|
|
||||||
self.item.get_name()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_value(&self) -> u32 {
|
|
||||||
self.item.get_value()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_type(&self) -> ItemType {
|
|
||||||
self.item.get_type()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ItemArmor {
|
impl ItemArmor {
|
||||||
pub fn get_armor(&self) -> u32 {
|
|
||||||
self.armor
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn print_values(&self) {
|
pub fn print_values(&self) {
|
||||||
let lines: Vec<String> = vec![
|
print_box(&[
|
||||||
format!("Stats for {} ", self.get_name()),
|
format!("Stats for {} ", self.item.name),
|
||||||
format!("ID: {}", self.get_id()),
|
format!("ID: {}", self.item.id),
|
||||||
format!("Slot: {:?}", self.get_type()),
|
format!("Slot: {:?}", self.item.item_type),
|
||||||
format!("Armor: {}", self.get_armor()),
|
format!("Armor: {}", self.armor),
|
||||||
format!("Value: {}", self.get_value()),
|
format!("Value: {}", self.item.value),
|
||||||
];
|
]);
|
||||||
|
|
||||||
print_box(&lines);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,62 +1,26 @@
|
|||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
use super::{Item, ItemTrait, ItemType, print_box};
|
use super::{Item, print_box};
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct ItemWeapon {
|
pub struct ItemWeapon {
|
||||||
base_damage: u32,
|
pub base_damage: u32,
|
||||||
critical_factor: f32,
|
pub critical_factor: f32,
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
item: Item,
|
pub item: Item,
|
||||||
}
|
|
||||||
|
|
||||||
impl ItemTrait for ItemWeapon {
|
|
||||||
fn get_id(&self) -> String {
|
|
||||||
self.item.get_id()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_name(&self) -> String {
|
|
||||||
self.item.get_name()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_value(&self) -> u32 {
|
|
||||||
self.item.get_value()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_type(&self) -> ItemType {
|
|
||||||
self.item.get_type()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ItemWeapon {
|
impl ItemWeapon {
|
||||||
pub fn get_base_damage(&self) -> u32 {
|
|
||||||
self.base_damage
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_critical_factor(&self) -> f32 {
|
|
||||||
self.critical_factor
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_critical_factor_readable(&self) -> String {
|
|
||||||
let factor: i32 = ((self.get_critical_factor() - 1.0) * 100.0).round() as i32;
|
|
||||||
format!("{}%", factor)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn print_values(&self) {
|
pub fn print_values(&self) {
|
||||||
let crit_dmg: u32 =
|
let crit_damage: u32 = (self.base_damage as f32 * self.critical_factor).ceil() as u32;
|
||||||
(self.get_base_damage() as f32 * self.get_critical_factor()).ceil() as u32;
|
let crit_percent: i32 = ((self.critical_factor - 1.0) * 100.0).round() as i32;
|
||||||
|
|
||||||
let lines: Vec<String> = vec![
|
print_box(&[
|
||||||
format!("Stats for {} ", self.get_name()),
|
format!("Stats for {} ", self.item.name),
|
||||||
format!("ID: {}", self.get_id()),
|
format!("ID: {}", self.item.id),
|
||||||
format!("Base Damage: {} ({})", self.get_base_damage(), crit_dmg),
|
format!("Base Damage: {} ({})", self.base_damage, crit_damage),
|
||||||
format!(
|
format!("Critical Factor: {}%", crit_percent),
|
||||||
"Critical Factor: {}",
|
format!("Value: {}", self.item.value),
|
||||||
self.get_critical_factor_readable()
|
]);
|
||||||
),
|
|
||||||
format!("Value: {}", self.get_value()),
|
|
||||||
];
|
|
||||||
|
|
||||||
print_box(&lines);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
145
src/player.rs
145
src/player.rs
@@ -1,20 +1,11 @@
|
|||||||
use std::fmt::format;
|
use crate::items::print_box;
|
||||||
|
use crate::stats::Stats;
|
||||||
use crate::stats::{Stats, StatsTrait};
|
|
||||||
|
|
||||||
pub struct Player {
|
pub struct Player {
|
||||||
name: String,
|
pub name: String,
|
||||||
stats: Stats,
|
pub stats: Stats,
|
||||||
next_level_exp: usize,
|
pub next_level_exp: usize,
|
||||||
current_exp: usize,
|
pub current_exp: usize,
|
||||||
}
|
|
||||||
|
|
||||||
pub trait PlayerTrait {
|
|
||||||
fn get_name(&self) -> String;
|
|
||||||
fn set_name(&mut self, name: String);
|
|
||||||
fn get_current_exp(&self) -> usize;
|
|
||||||
fn get_next_level_exp(&self) -> usize;
|
|
||||||
fn show_stats(&self);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Player {
|
impl Player {
|
||||||
@@ -26,119 +17,21 @@ impl Player {
|
|||||||
current_exp: 0,
|
current_exp: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl PlayerTrait for Player {
|
pub fn show_stats(&self) {
|
||||||
fn get_name(&self) -> String {
|
let stats: &Stats = &self.stats;
|
||||||
self.name.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_name(&mut self, name: String) {
|
print_box(&[
|
||||||
self.name = name;
|
format!("Name: {}", self.name),
|
||||||
}
|
format!(
|
||||||
|
|
||||||
fn show_stats(&self) {
|
|
||||||
let name: String = format!("Name: {}", self.get_name());
|
|
||||||
let level: String = format!(
|
|
||||||
"Level: {} ({}/{})",
|
"Level: {} ({}/{})",
|
||||||
self.get_level(),
|
stats.level, self.current_exp, self.next_level_exp
|
||||||
self.get_current_exp(),
|
),
|
||||||
self.get_next_level_exp()
|
format!("Strength: {}", stats.strength),
|
||||||
);
|
format!("Dexterity: {}", stats.dexterity),
|
||||||
let strength: String = format!("Strength: {}", self.get_strengh());
|
format!("Constitution: {}", stats.constitution),
|
||||||
let dexterity: String = format!("Dexterity: {}", self.get_dexterity());
|
format!("Charisma: {}", stats.charisma),
|
||||||
let constitution: String = format!("Constitution: {}", self.get_constitution());
|
format!("Luck: {}", stats.luck),
|
||||||
let charisma: String = format!("Charisma: {}", self.get_charisma());
|
]);
|
||||||
let luck: String = format!("Luck: {}", self.get_luck());
|
|
||||||
|
|
||||||
let stats_data: [&String; 7] = [
|
|
||||||
&name,
|
|
||||||
&level,
|
|
||||||
&strength,
|
|
||||||
&dexterity,
|
|
||||||
&constitution,
|
|
||||||
&charisma,
|
|
||||||
&luck,
|
|
||||||
];
|
|
||||||
let mut longest: usize = 0;
|
|
||||||
for data in stats_data {
|
|
||||||
let length: usize = data.chars().count();
|
|
||||||
longest = length.max(longest);
|
|
||||||
}
|
|
||||||
|
|
||||||
let spacer: String = format!("+-{}-+", "-".repeat(longest));
|
|
||||||
|
|
||||||
println!("{}", spacer);
|
|
||||||
for data in stats_data {
|
|
||||||
let length: usize = data.chars().count();
|
|
||||||
println!("| {}{} |", data, " ".repeat(longest - length));
|
|
||||||
}
|
|
||||||
println!("{}", spacer);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_current_exp(&self) -> usize {
|
|
||||||
self.current_exp
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_next_level_exp(&self) -> usize {
|
|
||||||
self.next_level_exp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl StatsTrait for Player {
|
|
||||||
fn get_max_health(&self) -> f32 {
|
|
||||||
self.stats.get_max_health()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_current_health(&self) -> f32 {
|
|
||||||
self.stats.get_current_health()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_current_health(&mut self, value: f32) {
|
|
||||||
self.stats.set_current_health(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_dead(&self) -> bool {
|
|
||||||
self.stats.is_dead()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_max_stamina(&self) -> f32 {
|
|
||||||
self.stats.get_max_stamina()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_current_stamina(&self) -> f32 {
|
|
||||||
self.stats.get_current_stamina()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_current_stamina(&mut self, value: f32) {
|
|
||||||
self.stats.set_current_stamina(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_strengh(&self) -> usize {
|
|
||||||
self.stats.get_strengh()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_dexterity(&self) -> usize {
|
|
||||||
self.stats.get_dexterity()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_constitution(&self) -> usize {
|
|
||||||
self.stats.get_constitution()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_charisma(&self) -> usize {
|
|
||||||
self.stats.get_charisma()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_luck(&self) -> usize {
|
|
||||||
self.stats.get_luck()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_level(&self) -> usize {
|
|
||||||
self.stats.get_level()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn level_up(&mut self) {
|
|
||||||
self.stats.level_up();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
116
src/stats.rs
116
src/stats.rs
@@ -1,31 +1,14 @@
|
|||||||
pub struct Stats {
|
pub struct Stats {
|
||||||
max_health: f32,
|
pub max_health: f32,
|
||||||
current_health: f32,
|
pub current_health: f32,
|
||||||
max_stamina: f32,
|
pub max_stamina: f32,
|
||||||
current_stamina: f32,
|
pub current_stamina: f32,
|
||||||
strength: usize, // Determines base_damage modifier
|
pub strength: usize, // Determines base_damage modifier
|
||||||
dexterity: usize, // Determines Critical Factor Modifier
|
pub dexterity: usize, // Determines Critical Factor Modifier
|
||||||
constitution: usize, // Determines Max Health Bonuses
|
pub constitution: usize, // Determines Max Health Bonuses
|
||||||
charisma: usize, // Determines Shop Prices
|
pub charisma: usize, // Determines Shop Prices
|
||||||
luck: usize, // Determines Loot Drop & Critical Chance
|
pub luck: usize, // Determines Loot Drop & Critical Chance
|
||||||
level: usize,
|
pub level: usize,
|
||||||
}
|
|
||||||
|
|
||||||
pub trait StatsTrait {
|
|
||||||
fn get_max_health(&self) -> f32;
|
|
||||||
fn get_current_health(&self) -> f32;
|
|
||||||
fn set_current_health(&mut self, value: f32);
|
|
||||||
fn is_dead(&self) -> bool;
|
|
||||||
fn get_max_stamina(&self) -> f32;
|
|
||||||
fn get_current_stamina(&self) -> f32;
|
|
||||||
fn set_current_stamina(&mut self, value: f32);
|
|
||||||
fn get_strengh(&self) -> usize;
|
|
||||||
fn get_dexterity(&self) -> usize;
|
|
||||||
fn get_constitution(&self) -> usize;
|
|
||||||
fn get_charisma(&self) -> usize;
|
|
||||||
fn get_luck(&self) -> usize;
|
|
||||||
fn get_level(&self) -> usize;
|
|
||||||
fn level_up(&mut self);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Stats {
|
impl Stats {
|
||||||
@@ -45,64 +28,41 @@ impl Stats {
|
|||||||
level: 1,
|
level: 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Delta auf die aktuelle Health: positiv heilt, negativ verletzt.
|
||||||
|
pub fn change_health(&mut self, delta: f32) {
|
||||||
|
self.current_health = (self.current_health + delta).clamp(0.0, self.max_health);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StatsTrait for Stats {
|
/// Delta auf die aktuelle Stamina: positiv regeneriert, negativ verbraucht.
|
||||||
fn get_max_health(&self) -> f32 {
|
// TODO: noch ungenutzt — wird vom Kampfsystem aufgerufen, sobald es existiert.
|
||||||
self.max_health
|
pub fn change_stamina(&mut self, delta: f32) {
|
||||||
|
self.current_stamina = (self.current_stamina + delta).clamp(0.0, self.max_stamina);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_current_health(&self) -> f32 {
|
pub fn is_dead(&self) -> bool {
|
||||||
self.current_health
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_current_health(&mut self, value: f32) {
|
|
||||||
let new_val: f32 = self.current_health + value;
|
|
||||||
self.current_health = new_val.clamp(0.0, self.max_health);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_dead(&self) -> bool {
|
|
||||||
self.current_health <= 0.0
|
self.current_health <= 0.0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_max_stamina(&self) -> f32 {
|
// TODO: noch ungenutzt — wird vom Exp-/Level-System aufgerufen, sobald es existiert.
|
||||||
self.max_stamina
|
pub fn level_up(&mut self) {
|
||||||
}
|
|
||||||
|
|
||||||
fn get_current_stamina(&self) -> f32 {
|
|
||||||
self.current_stamina
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_current_stamina(&mut self, value: f32) {
|
|
||||||
let new_val: f32 = self.current_stamina + value;
|
|
||||||
self.current_stamina = new_val.clamp(0.0, self.max_stamina);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_strengh(&self) -> usize {
|
|
||||||
self.strength
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_dexterity(&self) -> usize {
|
|
||||||
self.dexterity
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_constitution(&self) -> usize {
|
|
||||||
self.constitution
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_charisma(&self) -> usize {
|
|
||||||
self.charisma
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_luck(&self) -> usize {
|
|
||||||
self.luck
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_level(&self) -> usize {
|
|
||||||
self.level
|
|
||||||
}
|
|
||||||
|
|
||||||
fn level_up(&mut self) {
|
|
||||||
self.level = (self.level + 1).clamp(1, 50);
|
self.level = (self.level + 1).clamp(1, 50);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn health_clamps_at_both_ends() {
|
||||||
|
let mut stats: Stats = Stats::new();
|
||||||
|
|
||||||
|
stats.change_health(50.0);
|
||||||
|
assert_eq!(stats.current_health, stats.max_health);
|
||||||
|
|
||||||
|
stats.change_health(-500.0);
|
||||||
|
assert_eq!(stats.current_health, 0.0);
|
||||||
|
assert!(stats.is_dead());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user