use assembly_fdb::mem::Field;
use latin1str::Latin1Str;
use crate::{
columns::{ItemSetsColumn, SkillBehaviorColumn},
tables::{ItemSetsTable, MissionTasksTable, ObjectsTable, SkillBehaviorTable},
TypedTable,
};
use serde::Serialize;
#[derive(Debug, Copy, Clone, Default)]
pub struct Components {
pub render: Option<i32>,
}
#[derive(Debug, Clone)]
pub struct ItemSet {
pub item_ids: Vec<i32>,
pub kit_type: i32,
pub kit_rank: i32,
pub kit_image: Option<i32>,
}
impl<'db> ItemSetsTable<'db> {
pub fn get_data(&self, id: i32) -> Option<ItemSet> {
let hash = u32::from_ne_bytes(id.to_ne_bytes());
let bucket = self.as_raw().bucket_for_hash(hash);
let col_item_ids = self
.get_col(ItemSetsColumn::ItemIDs)
.expect("Missing column 'ItemSets::itemIDs'");
let col_kit_image = self
.get_col(ItemSetsColumn::KitImage)
.expect("Missing column 'ItemSets::kitImage'");
let col_kit_type = self
.get_col(ItemSetsColumn::KitType)
.expect("Missing column 'ItemSets::kitType'");
let col_kit_rank = self
.get_col(ItemSetsColumn::KitRank)
.expect("Missing column 'ItemSets::kitRank'");
for row in bucket.row_iter() {
let id_field = row.field_at(0).unwrap();
if id_field == Field::Integer(id) {
let kit_type = row
.field_at(col_kit_type)
.unwrap()
.into_opt_integer()
.unwrap();
let kit_rank = row
.field_at(col_kit_rank)
.unwrap()
.into_opt_integer()
.unwrap_or(0);
let kit_image = row.field_at(col_kit_image).unwrap().into_opt_integer();
let item_ids = row
.field_at(col_item_ids)
.unwrap()
.into_opt_text()
.unwrap()
.decode()
.split(',')
.map(str::trim)
.filter_map(|idstr| idstr.parse::<i32>().ok())
.collect();
return Some(ItemSet {
kit_type,
kit_rank,
kit_image,
item_ids,
});
}
}
None
}
}
#[derive(Default)]
pub struct Mission {
pub mission_icon_id: Option<i32>,
pub is_mission: bool,
}
#[derive(Default)]
pub struct MissionTask {
pub icon_id: Option<i32>,
pub uid: i32,
}
#[derive(Debug, Copy, Clone)]
pub enum MissionKind {
Achievement,
Mission,
}
#[derive(Debug, Copy, Clone, Serialize)]
pub struct ObjectRef<'a> {
pub id: i32,
pub name: &'a Latin1Str,
}
impl<'a> ObjectsTable<'a> {
pub fn ref_iter(&self) -> impl Iterator<Item = ObjectRef<'a>> + '_ {
self.row_iter().map(|row| ObjectRef {
id: row.id(),
name: row.name(),
})
}
}
#[derive(Copy, Clone)]
pub struct SkillBehavior {
pub skill_icon: Option<i32>,
}
impl<'db> SkillBehaviorTable<'db> {
pub fn get_data(&self, id: i32) -> Option<SkillBehavior> {
let hash = u32::from_ne_bytes(id.to_ne_bytes());
let bucket = self.as_raw().bucket_for_hash(hash);
let col_skill_icon = self
.get_col(SkillBehaviorColumn::SkillIcon)
.expect("Missing 'SkillBehavior::skillIcon'");
for row in bucket.row_iter() {
let id_field = row.field_at(0).unwrap();
if id_field == Field::Integer(id) {
let skill_icon = row.field_at(col_skill_icon).unwrap().into_opt_integer();
return Some(SkillBehavior { skill_icon });
}
}
None
}
}
#[derive(Serialize)]
pub struct MissionTaskIcon {
uid: i32,
#[serde(rename = "largeTaskIconID")]
large_task_icon_id: Option<i32>,
}
impl<'a> MissionTasksTable<'a> {
pub fn as_task_icon_iter(&self, key: i32) -> impl Iterator<Item = MissionTaskIcon> + '_ {
self.key_iter(key).map(|x| MissionTaskIcon {
uid: x.uid(),
large_task_icon_id: x.large_task_icon_id(),
})
}
}