engine/rpg_components/src/items/rarities.rs
2024-08-27 14:06:06 +02:00

134 lines
3.4 KiB
Rust

use anyhow::Result;
use engine::prelude::*;
use image::RgbaImage;
use std::{fmt, slice::Iter};
use crate::config::items::{ItemSettings, RarityColorSettings};
use super::{ability_book::Ability, ItemSystem};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Rarities {
Common,
Uncommon,
Magical,
Rare,
Epic,
Legendary,
}
impl Rarities {
const COUNT: u32 = 6;
pub fn iter() -> Iter<'static, Rarities> {
use Rarities::*;
static RARITIES: [Rarities; Rarities::COUNT as usize] =
[Common, Uncommon, Magical, Rare, Epic, Legendary];
RARITIES.iter()
}
pub fn random(item_settings: &ItemSettings, level: u32) -> Self {
let p = Coin::raw();
let multiplier = level as f32 / item_settings.general.drop_chance_reference_level as f32;
// legendary
let mut lower = 0.0;
let mut upper = item_settings.rarity_drop_rates.legendary * multiplier;
if Self::is_between(p, lower, upper) {
return Self::Legendary;
}
// epic
lower = upper;
upper = upper + item_settings.rarity_drop_rates.epic * multiplier;
if Self::is_between(p, lower, upper) {
return Self::Epic;
}
// rare
lower = upper;
upper = upper + item_settings.rarity_drop_rates.rare * multiplier;
if Self::is_between(p, lower, upper) {
return Self::Rare;
}
// magical
lower = upper;
upper = upper + item_settings.rarity_drop_rates.magical * multiplier;
if Self::is_between(p, lower, upper) {
return Self::Magical;
}
// uncommon
lower = upper;
upper = upper + item_settings.rarity_drop_rates.uncommon * multiplier;
if Self::is_between(p, lower, upper) {
return Self::Uncommon;
}
// common
Self::Common
}
#[inline]
fn is_between(p: f32, l: f32, h: f32) -> bool {
p >= l && p <= h
}
pub(crate) fn apply_color<A: Ability>(
&self,
base_image: &RgbaImage,
rarity_color_settings: &RarityColorSettings,
) -> RgbaImage {
ItemSystem::<A>::apply_color(base_image, rarity_color_settings.from_rarity(*self))
}
}
impl Default for Rarities {
fn default() -> Self {
Self::Common
}
}
impl std::str::FromStr for Rarities {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self> {
match s {
"Common" => Ok(Self::Common),
"Uncommon" => Ok(Self::Uncommon),
"Magical" => Ok(Self::Magical),
"Rare" => Ok(Self::Rare),
"Epic" => Ok(Self::Epic),
"Legendary" => Ok(Self::Legendary),
_ => {
return Err(anyhow::Error::msg(format!(
"Failed parsing Rarities from {}",
s
)))
}
}
}
}
impl fmt::Display for Rarities {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
Self::Common => write!(f, "Common"),
Self::Uncommon => write!(f, "Uncommon"),
Self::Magical => write!(f, "Magical"),
Self::Rare => write!(f, "Rare"),
Self::Epic => write!(f, "Epic"),
Self::Legendary => write!(f, "Legendary"),
}
}
}