339 lines
9.1 KiB
Rust
339 lines
9.1 KiB
Rust
use std::{collections::HashMap, fmt::Display, path};
|
|
|
|
use serde::Deserialize;
|
|
|
|
use crate::ASSETS_FOLDER_PATH;
|
|
|
|
use super::{
|
|
Game,
|
|
enemy::{Enemy, EnemyDrop},
|
|
};
|
|
|
|
pub const GENERIC_MATERIAL_ICON: &str = "generic";
|
|
|
|
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
|
pub struct MaterialDetails {
|
|
pub category: MaterialCategory,
|
|
pub kind: MaterialKind,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
#[serde(rename_all = "lowercase")]
|
|
pub enum MaterialCategory {
|
|
// Common
|
|
Adamantite,
|
|
#[serde(alias = "blaze")]
|
|
Blazing,
|
|
#[serde(alias = "soothing")]
|
|
Bright,
|
|
#[serde(alias = "betwixt")]
|
|
Dense,
|
|
#[serde(alias = "writhing")]
|
|
Dark,
|
|
#[serde(alias = "wellspring")]
|
|
Energy,
|
|
Frost,
|
|
#[serde(alias = "thunder")]
|
|
Lightning,
|
|
Lucid,
|
|
Mythril,
|
|
Orichalcum,
|
|
#[serde(alias = "pulsing")]
|
|
Power,
|
|
#[serde(alias = "shiny")]
|
|
Shimmering,
|
|
#[serde(alias = "mystery", alias = "hungry")]
|
|
Serenity,
|
|
Twilight,
|
|
|
|
// KH1 Only
|
|
Spirit,
|
|
Stormy,
|
|
|
|
// KH2 Only
|
|
Remembrance,
|
|
Tranquility,
|
|
Illusion,
|
|
|
|
// KH3 Only
|
|
Sinister,
|
|
Evanescent,
|
|
Illusory,
|
|
Fluorite,
|
|
Damascus,
|
|
Electrum,
|
|
|
|
// Days Only
|
|
Gust,
|
|
Shining,
|
|
GearComponent,
|
|
ComboTech,
|
|
ShieldTech,
|
|
RuneTech,
|
|
PowerTech,
|
|
AerialTech,
|
|
RangeTech,
|
|
LuckTech,
|
|
Ankharite,
|
|
Iron,
|
|
Bronze,
|
|
DarkIngot,
|
|
Silver,
|
|
Gold,
|
|
Moonstone,
|
|
Diamond,
|
|
PremiumOrb,
|
|
|
|
// DDD Only
|
|
Fleeting,
|
|
Lofty,
|
|
Rampant,
|
|
Dulcet,
|
|
Intrepid,
|
|
Noble,
|
|
Grim,
|
|
Vibrant,
|
|
Troubling,
|
|
Wondrous,
|
|
Malleable,
|
|
Prickly,
|
|
Wild,
|
|
Epic,
|
|
Charming,
|
|
Brilliant,
|
|
Savage,
|
|
}
|
|
|
|
impl MaterialCategory {
|
|
pub fn get_texture_group(&self) -> String {
|
|
match self {
|
|
MaterialCategory::Adamantite => "adamantite".to_string(),
|
|
MaterialCategory::Blazing => "blazing".to_string(),
|
|
MaterialCategory::Bright => "bright".to_string(),
|
|
MaterialCategory::Dense => "dense".to_string(),
|
|
MaterialCategory::Dark => "dark".to_string(),
|
|
MaterialCategory::Energy => "energy".to_string(),
|
|
MaterialCategory::Frost => "frost".to_string(),
|
|
MaterialCategory::Lightning => "lightning".to_string(),
|
|
MaterialCategory::Lucid => "lucid".to_string(),
|
|
MaterialCategory::Mythril => "mythril".to_string(),
|
|
MaterialCategory::Orichalcum => "orichalcum".to_string(),
|
|
MaterialCategory::Power => "power".to_string(),
|
|
MaterialCategory::Shimmering => "shimmering".to_string(),
|
|
MaterialCategory::Serenity => "serenity".to_string(),
|
|
MaterialCategory::Twilight => "twilight".to_string(),
|
|
|
|
MaterialCategory::Spirit => "spirit".to_string(),
|
|
MaterialCategory::Stormy => "stormy".to_string(),
|
|
|
|
MaterialCategory::Remembrance => "remembrance".to_string(),
|
|
MaterialCategory::Tranquility => "tranquility".to_string(),
|
|
MaterialCategory::Illusion => "illusion".to_string(),
|
|
|
|
MaterialCategory::Sinister => "sinister".to_string(),
|
|
MaterialCategory::Evanescent => "evanescent".to_string(),
|
|
MaterialCategory::Illusory => "illusory".to_string(),
|
|
MaterialCategory::Fluorite => "fluorite".to_string(),
|
|
MaterialCategory::Damascus => "damascus".to_string(),
|
|
MaterialCategory::Electrum => "electrum".to_string(),
|
|
|
|
MaterialCategory::Gust => "gust".to_string(),
|
|
MaterialCategory::Shining => "shining".to_string(),
|
|
MaterialCategory::GearComponent => "gear_component".to_string(),
|
|
MaterialCategory::ComboTech => "combo_tech".to_string(),
|
|
MaterialCategory::ShieldTech => "shield_tech".to_string(),
|
|
MaterialCategory::RuneTech => "rune_tech".to_string(),
|
|
MaterialCategory::PowerTech => "power_tech".to_string(),
|
|
MaterialCategory::AerialTech => "aerial_tech".to_string(),
|
|
MaterialCategory::RangeTech => "range_tech".to_string(),
|
|
MaterialCategory::LuckTech => "luck_tech".to_string(),
|
|
MaterialCategory::Ankharite => "ankharite".to_string(),
|
|
MaterialCategory::Iron => "iron".to_string(),
|
|
MaterialCategory::Bronze => "bronze".to_string(),
|
|
MaterialCategory::DarkIngot => "dark_ingot".to_string(),
|
|
MaterialCategory::Silver => "silver".to_string(),
|
|
MaterialCategory::Gold => "gold".to_string(),
|
|
MaterialCategory::Moonstone => "moonstone".to_string(),
|
|
MaterialCategory::Diamond => "diamond".to_string(),
|
|
MaterialCategory::PremiumOrb => "premium_orb".to_string(),
|
|
|
|
MaterialCategory::Fleeting => "fleeting".to_string(),
|
|
MaterialCategory::Lofty => "lofty".to_string(),
|
|
MaterialCategory::Rampant => "rampant".to_string(),
|
|
MaterialCategory::Dulcet => "dulcet".to_string(),
|
|
MaterialCategory::Intrepid => "intrepid".to_string(),
|
|
MaterialCategory::Noble => "noble".to_string(),
|
|
MaterialCategory::Grim => "grim".to_string(),
|
|
MaterialCategory::Vibrant => "vibrant".to_string(),
|
|
MaterialCategory::Troubling => "troubling".to_string(),
|
|
MaterialCategory::Wondrous => "wondrous".to_string(),
|
|
MaterialCategory::Malleable => "malleable".to_string(),
|
|
MaterialCategory::Prickly => "prickly".to_string(),
|
|
MaterialCategory::Wild => "wild".to_string(),
|
|
MaterialCategory::Epic => "epic".to_string(),
|
|
MaterialCategory::Charming => "charming".to_string(),
|
|
MaterialCategory::Brilliant => "brilliant".to_string(),
|
|
MaterialCategory::Savage => "savage".to_string(),
|
|
}
|
|
}
|
|
|
|
pub fn get_category(&self, game: &Game) -> String {
|
|
match self {
|
|
MaterialCategory::Blazing => match game {
|
|
Game::Kh1 => "blaze".to_string(),
|
|
_ => "blazing".to_string(),
|
|
},
|
|
MaterialCategory::Bright => match game {
|
|
Game::Kh1 | Game::Kh2 => "bright".to_string(),
|
|
_ => "soothing".to_string(),
|
|
},
|
|
MaterialCategory::Dense => match game {
|
|
Game::Kh2 => "dense".to_string(),
|
|
_ => "betwixt".to_string(),
|
|
},
|
|
MaterialCategory::Dark => match game {
|
|
Game::Kh2 => "dark".to_string(),
|
|
_ => "writhing".to_string(),
|
|
},
|
|
MaterialCategory::Energy => match game {
|
|
Game::Kh1 | Game::Kh2 => "energy".to_string(),
|
|
_ => "wellspring".to_string(),
|
|
},
|
|
MaterialCategory::Lightning => match game {
|
|
Game::Kh1 => "thunder".to_string(),
|
|
_ => "lightning".to_string(),
|
|
},
|
|
MaterialCategory::Power => match game {
|
|
Game::Kh1 | Game::Kh2 => "power".to_string(),
|
|
_ => "pulsing".to_string(),
|
|
},
|
|
MaterialCategory::Shimmering => match game {
|
|
Game::Kh1 => "shiny".to_string(),
|
|
_ => "shimmering".to_string(),
|
|
},
|
|
MaterialCategory::Serenity => match game {
|
|
Game::Kh1 => "mystery".to_string(),
|
|
Game::Kh2 => "serenity".to_string(),
|
|
_ => "hungry".to_string(),
|
|
},
|
|
_ => self.get_texture_group(),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
#[serde(rename_all = "lowercase")]
|
|
pub enum MaterialKind {
|
|
Shard,
|
|
Stone,
|
|
Gem,
|
|
Crystal,
|
|
|
|
Figment,
|
|
Fancy,
|
|
Fantasy,
|
|
}
|
|
|
|
impl Display for MaterialKind {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
MaterialKind::Shard => f.write_str("shard"),
|
|
MaterialKind::Stone => f.write_str("stone"),
|
|
MaterialKind::Gem => f.write_str("gem"),
|
|
MaterialKind::Crystal => f.write_str("crystal"),
|
|
|
|
MaterialKind::Figment => f.write_str("figment"),
|
|
MaterialKind::Fancy => f.write_str("fancy"),
|
|
MaterialKind::Fantasy => f.write_str("fantasy"),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, PartialEq, Eq)]
|
|
pub struct MaterialDrops {
|
|
pub name: String,
|
|
pub icon: String,
|
|
pub category: MaterialCategory,
|
|
pub kind: MaterialKind,
|
|
pub drops: Vec<EnemyDrop>,
|
|
}
|
|
|
|
impl PartialOrd for MaterialDrops {
|
|
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
|
if self.category.cmp(&other.category) == std::cmp::Ordering::Equal {
|
|
return Some(self.kind.cmp(&other.kind));
|
|
}
|
|
|
|
Some(self.category.cmp(&other.category))
|
|
}
|
|
}
|
|
|
|
impl MaterialDrops {
|
|
pub fn new(enemies: Vec<Enemy>) -> Vec<MaterialDrops> {
|
|
let mut mat_map = HashMap::<(MaterialCategory, MaterialKind), MaterialDrops>::new();
|
|
|
|
for enemy in enemies {
|
|
for drop in &enemy.drops {
|
|
let Some(material) = &drop.material else {
|
|
continue;
|
|
};
|
|
|
|
let key = (material.category.clone(), material.kind.clone());
|
|
|
|
mat_map
|
|
.entry(key)
|
|
.and_modify(|d| d.drops.push(drop.clone()))
|
|
.or_insert(MaterialDrops {
|
|
name: drop.name.to_string(),
|
|
icon: "".to_string(),
|
|
category: material.category.clone(),
|
|
kind: material.kind.clone(),
|
|
drops: vec![drop.clone()],
|
|
});
|
|
}
|
|
}
|
|
|
|
let mut values: Vec<MaterialDrops> = mat_map.into_values().collect();
|
|
|
|
values.sort_by(|a, b| a.partial_cmp(b).unwrap());
|
|
|
|
values
|
|
}
|
|
|
|
pub fn drops(&self, kind: &str) -> Vec<&EnemyDrop> {
|
|
match kind {
|
|
"shard" => self.get_drop_kind(MaterialKind::Shard),
|
|
"stone" => self.get_drop_kind(MaterialKind::Stone),
|
|
"gem" => self.get_drop_kind(MaterialKind::Gem),
|
|
"crystal" => self.get_drop_kind(MaterialKind::Crystal),
|
|
_ => vec![],
|
|
}
|
|
}
|
|
|
|
fn get_drop_kind(&self, kind: MaterialKind) -> Vec<&EnemyDrop> {
|
|
self.drops
|
|
.iter()
|
|
.filter(|d| d.material.as_ref().map(|m| m.kind == kind).unwrap_or(false))
|
|
.collect::<Vec<&EnemyDrop>>()
|
|
}
|
|
|
|
pub fn texture(&self, game: &Game) -> String {
|
|
if *game == Game::Kh1 {
|
|
return GENERIC_MATERIAL_ICON.to_string();
|
|
}
|
|
|
|
let category = self.category.get_category(game);
|
|
let kind = self.kind.to_string();
|
|
let path = format!(
|
|
"{}/materials/{}/{}.webp",
|
|
ASSETS_FOLDER_PATH, category, kind
|
|
);
|
|
let path = path::Path::new(&path);
|
|
if path.exists() {
|
|
format!("{}/{}", self.category.get_category(game), self.kind)
|
|
} else {
|
|
GENERIC_MATERIAL_ICON.to_string()
|
|
}
|
|
}
|
|
}
|