use crate::utils::GameTimeC;
use std::any::Any;
use std::fmt;
use std::cmp::Ordering;
use std::hash::{Hash, Hasher};
#[macro_export]
macro_rules! inv_item(
($t:ty, $nm:expr, $wt:expr) => (
impl zara::inventory::items::InventoryItem for $t {
fn get_count(&self) -> usize { self.count }
fn set_count(&mut self, new_count: usize) { self.count = new_count; }
fn get_name(&self) -> String { String::from($nm) }
fn get_is_infinite(&self) -> bool { false }
fn get_total_weight(&self) -> f32 { self.count as f32 * $wt }
fn consumable(&self) -> Option<&dyn zara::inventory::items::ConsumableDescription> { None }
fn appliance(&self) -> Option<&dyn zara::inventory::items::ApplianceDescription> { None }
fn clothes(&self) -> Option<&dyn zara::inventory::items::ClothesDescription> { None }
fn as_any(&self) -> &dyn std::any::Any { self }
}
);
);
#[macro_export]
macro_rules! inv_infinite(
($t:ty, $nm:expr, $wt:expr) => (
impl zara::inventory::items::InventoryItem for $t {
fn get_count(&self) -> usize { self.count }
fn set_count(&mut self, new_count: usize) { self.count = new_count; }
fn get_name(&self) -> String { String::from($nm) }
fn get_is_infinite(&self) -> bool { true }
fn get_total_weight(&self) -> f32 { self.count as f32 * $wt }
fn consumable(&self) -> Option<&dyn zara::inventory::items::ConsumableDescription> { None }
fn appliance(&self) -> Option<&dyn zara::inventory::items::ApplianceDescription> { None }
fn clothes(&self) -> Option<&dyn zara::inventory::items::ClothesDescription> { None }
fn as_any(&self) -> &dyn std::any::Any { self }
}
);
);
#[macro_export]
macro_rules! inv_item_cons(
($t:ty, $nm:expr, $wt:expr, $cons:expr) => (
impl zara::inventory::items::InventoryItem for $t {
fn get_count(&self) -> usize { self.count }
fn set_count(&mut self, new_count: usize) { self.count = new_count; }
fn get_name(&self) -> String { String::from($nm) }
fn get_is_infinite(&self) -> bool { false }
fn get_total_weight(&self) -> f32 { self.count as f32 * $wt }
fn consumable(&self) -> Option<&dyn zara::inventory::items::ConsumableDescription> { $cons }
fn appliance(&self) -> Option<&dyn zara::inventory::items::ApplianceDescription> { None }
fn clothes(&self) -> Option<&dyn zara::inventory::items::ClothesDescription> { None }
fn as_any(&self) -> &dyn std::any::Any { self }
}
);
);
#[macro_export]
macro_rules! inv_item_appl (
($t:ty, $nm:expr, $wt:expr, $appl:expr) => (
impl zara::inventory::items::InventoryItem for $t {
fn get_count(&self) -> usize { self.count }
fn set_count(&mut self, new_count: usize) { self.count = new_count; }
fn get_name(&self) -> String { String::from($nm) }
fn get_is_infinite(&self) -> bool { false }
fn get_total_weight(&self) -> f32 { self.count as f32 * $wt }
fn consumable(&self) -> Option<&dyn zara::inventory::items::ConsumableDescription> { None }
fn appliance(&self) -> Option<&dyn zara::inventory::items::ApplianceDescription> { $appl }
fn clothes(&self) -> Option<&dyn zara::inventory::items::ClothesDescription> { None }
fn as_any(&self) -> &dyn std::any::Any { self }
}
);
);
#[macro_export]
macro_rules! inv_item_clothes (
($t:ty, $nm:expr, $wt:expr, $cl:expr) => (
impl zara::inventory::items::InventoryItem for $t {
fn get_count(&self) -> usize { self.count }
fn set_count(&mut self, new_count: usize) { self.count = new_count; }
fn get_name(&self) -> String { String::from($nm) }
fn get_is_infinite(&self) -> bool { false }
fn get_total_weight(&self) -> f32 { self.count as f32 * $wt }
fn consumable(&self) -> Option<&dyn zara::inventory::items::ConsumableDescription> { None }
fn appliance(&self) -> Option<&dyn zara::inventory::items::ApplianceDescription> { None }
fn clothes(&self) -> Option<&dyn zara::inventory::items::ClothesDescription> { $cl }
fn as_any(&self) -> &dyn std::any::Any { self }
}
);
);
#[macro_export]
macro_rules! inv_body_appliance (
($t:ty) => (
impl zara::inventory::items::ApplianceDescription for $t {
fn is_body_appliance(&self) -> bool { true }
fn is_injection(&self) -> bool { false }
}
);
);
#[macro_export]
macro_rules! inv_injection_appliance (
($t:ty) => (
impl zara::inventory::items::ApplianceDescription for $t {
fn is_body_appliance(&self) -> bool { false }
fn is_injection(&self) -> bool { true }
}
);
);
#[macro_export]
macro_rules! inv_food(
($t:ty, $wg:expr, $fg:expr, $sp:expr) => (
impl zara::inventory::items::ConsumableDescription for $t {
fn is_food(&self) -> bool { true }
fn is_water(&self) -> bool { false}
fn water_gain_per_dose(&self) -> f32 { $wg as f32}
fn food_gain_per_dose(&self) -> f32 { $fg as f32 }
fn spoiling(&self) -> Option<&dyn zara::inventory::items::SpoilingBehavior> { $sp }
}
);
);
#[macro_export]
macro_rules! inv_water(
($t:ty, $wg:expr, $fg:expr, $sp:ty) => (
impl zara::inventory::items::ConsumableDescription for $t {
fn is_food(&self) -> bool { false }
fn is_water(&self) -> bool { true }
fn water_gain_per_dose(&self) -> f32 { $wg as f32}
fn food_gain_per_dose(&self) -> f32 { $fg as f32 }
fn spoiling(&self) -> Option<&dyn zara::inventory::items::SpoilingBehavior> { $sp }
}
);
);
#[macro_export]
macro_rules! inv_spoil(
($t:ty, $c1:expr, $c2:expr, $st:expr) => (
impl zara::inventory::items::SpoilingBehavior for $t {
fn fresh_poisoning_chance(&self) -> usize { $c1 as usize }
fn spoil_poisoning_chance(&self) -> usize { $c2 as usize }
fn spoil_time(&self) -> zara::utils::GameTimeC { $st }
}
);
);
#[macro_export]
macro_rules! inv_clothes(
($t:ty, $c1:expr, $c2:expr) => (
impl zara::inventory::items::ClothesDescription for $t {
fn cold_resistance(&self) -> usize { $c1 as usize }
fn water_resistance(&self) -> usize { $c2 as usize }
}
);
);
#[derive(Clone, Debug)]
pub struct ConsumableC {
pub name: String,
pub is_food: bool,
pub is_water: bool,
pub consumed_count: usize,
pub water_gain: f32,
pub food_gain: f32,
pub fresh_poisoning_chance: usize,
pub spoiled_poisoning_chance: usize,
pub spoil_time: Option<GameTimeC>
}
impl fmt::Display for ConsumableC {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{} [{}]", self.name, self.consumed_count)
}
}
impl Ord for ConsumableC {
fn cmp(&self, other: &Self) -> Ordering {
self.consumed_count.cmp(&other.consumed_count)
}
}
impl Eq for ConsumableC { }
impl PartialOrd for ConsumableC {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl PartialEq for ConsumableC {
fn eq(&self, other: &Self) -> bool {
const EPS: f32 = 0.0001;
self.name == other.name &&
self.is_food == other.is_food &&
self.is_water == other.is_water &&
self.consumed_count == other.consumed_count &&
self.fresh_poisoning_chance == other.fresh_poisoning_chance &&
self.spoiled_poisoning_chance == other.spoiled_poisoning_chance &&
self.spoil_time == other.spoil_time &&
f32::abs(self.water_gain - other.water_gain) < EPS &&
f32::abs(self.food_gain - other.food_gain) < EPS
}
}
impl Hash for ConsumableC {
fn hash<H: Hasher>(&self, state: &mut H) {
self.name.hash(state);
self.is_food.hash(state);
self.is_water.hash(state);
self.consumed_count.hash(state);
self.fresh_poisoning_chance.hash(state);
self.spoiled_poisoning_chance.hash(state);
self.spoil_time.hash(state);
state.write_u32(self.food_gain as u32);
state.write_u32(self.water_gain as u32);
}
}
impl ConsumableC {
pub fn new() -> Self {
ConsumableC {
name: String::new(),
is_food: false,
is_water: false,
food_gain: 0.,
water_gain: 0.,
consumed_count: 0,
fresh_poisoning_chance: 0,
spoiled_poisoning_chance: 0,
spoil_time: None
}
}
}
#[derive(Clone, Debug)]
pub struct ApplianceC {
pub name: String,
pub is_body_appliance: bool,
pub is_injection: bool,
pub taken_count: usize
}
impl fmt::Display for ApplianceC {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{} [{}]", self.name, self.taken_count)
}
}
impl Ord for ApplianceC {
fn cmp(&self, other: &Self) -> Ordering {
self.taken_count.cmp(&other.taken_count)
}
}
impl Eq for ApplianceC { }
impl PartialOrd for ApplianceC {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl PartialEq for ApplianceC {
fn eq(&self, other: &Self) -> bool {
self.name == other.name &&
self.is_body_appliance == other.is_body_appliance &&
self.is_injection == other.is_injection &&
self.taken_count == other.taken_count
}
}
impl Hash for ApplianceC {
fn hash<H: Hasher>(&self, state: &mut H) {
self.name.hash(state);
self.is_body_appliance.hash(state);
self.is_injection.hash(state);
self.taken_count.hash(state);
}
}
impl ApplianceC {
pub fn new() -> Self {
ApplianceC {
name: String::new(),
is_body_appliance: false,
is_injection: false,
taken_count: 0
}
}
}
pub trait InventoryItem {
fn get_count(&self) -> usize;
fn set_count(&mut self, new_count: usize);
fn get_name(&self) -> String;
fn get_is_infinite(&self) -> bool;
fn get_total_weight(&self) -> f32;
fn consumable(&self) -> Option<&dyn ConsumableDescription>;
fn appliance(&self) -> Option<&dyn ApplianceDescription>;
fn clothes(&self) -> Option<&dyn ClothesDescription>;
fn as_any(&self) -> &dyn Any;
}
pub trait ApplianceDescription {
fn is_body_appliance(&self) -> bool;
fn is_injection(&self) -> bool;
}
pub trait ConsumableDescription {
fn is_food(&self) -> bool;
fn is_water(&self) -> bool;
fn water_gain_per_dose(&self) -> f32;
fn food_gain_per_dose(&self) -> f32;
fn spoiling(&self) -> Option<&dyn SpoilingBehavior>;
}
pub trait SpoilingBehavior {
fn fresh_poisoning_chance(&self) -> usize;
fn spoil_poisoning_chance(&self) -> usize;
fn spoil_time(&self) -> GameTimeC;
}
pub trait ClothesDescription {
fn cold_resistance(&self) -> usize;
fn water_resistance(&self) -> usize;
}