1
Fork 0
mirror of https://github.com/redstrate/Kawari.git synced 2025-07-01 04:07:45 +00:00
kawari/src/common/gamedata.rs

110 lines
3.6 KiB
Rust
Raw Normal View History

use physis::common::{Language, Platform};
use physis::exd::{EXD, ExcelRowKind};
use physis::exh::EXH;
use physis_sheets::ClassJob::ClassJobSheet;
use physis_sheets::World::WorldSheet;
use physis_sheets::{Tribe::TribeSheet, Warp::WarpSheet};
use crate::{common::Attributes, config::get_config};
/// Convenient methods built on top of Physis to access data relevant to the server
pub struct GameData {
pub game_data: physis::gamedata::GameData,
pub item_exh: EXH,
pub item_pages: Vec<EXD>,
}
impl Default for GameData {
fn default() -> Self {
Self::new()
}
}
impl GameData {
pub fn new() -> Self {
let config = get_config();
let mut game_data =
physis::gamedata::GameData::from_existing(Platform::Win32, &config.game_location);
let mut item_pages = Vec::new();
let item_exh = game_data.read_excel_sheet_header("Item").unwrap();
for (i, _) in item_exh.pages.iter().enumerate() {
item_pages.push(
game_data
.read_excel_sheet("Item", &item_exh, Language::English, i)
.unwrap(),
);
}
Self {
game_data,
item_exh,
item_pages,
}
}
/// Gets the world name from an id into the World Excel sheet.
pub fn get_world_name(&mut self, world_id: u16) -> Option<String> {
let sheet = WorldSheet::read_from(&mut self.game_data, Language::None)?;
let row = sheet.get_row(world_id as u32)?;
row.Name().into_string().map(|x| x.clone())
}
/// Gets the starting city-state from a given class/job id.
pub fn get_citystate(&mut self, classjob_id: u16) -> Option<u8> {
let sheet = ClassJobSheet::read_from(&mut self.game_data, Language::English)?;
let row = sheet.get_row(classjob_id as u32)?;
row.StartingTown().into_u8().map(|x| *x)
}
pub fn get_racial_base_attributes(&mut self, tribe_id: u8) -> Option<Attributes> {
// The Tribe Excel sheet only has deltas (e.g. 2 or -2) which are applied to a base 20 number... from somewhere
let base_stat = 20;
let sheet = TribeSheet::read_from(&mut self.game_data, Language::English)?;
let row = sheet.get_row(tribe_id as u32)?;
Some(Attributes {
strength: (base_stat + row.STR().into_i8()?) as u32,
dexterity: (base_stat + row.DEX().into_i8()?) as u32,
vitality: (base_stat + row.VIT().into_i8()?) as u32,
intelligence: (base_stat + row.INT().into_i8()?) as u32,
mind: (base_stat + row.MND().into_i8()?) as u32,
})
}
/// Gets the primary model ID for a given item ID
pub fn get_primary_model_id(&mut self, item_id: u32) -> Option<u64> {
for page in &self.item_pages {
if let Some(row) = page.get_row(item_id) {
let ExcelRowKind::SingleRow(item_row) = row else {
panic!("Expected a single row!")
};
let physis::exd::ColumnData::UInt64(id) = &item_row.columns[47] else {
panic!("Unexpected type!");
};
return Some(*id);
}
}
None
}
/// Returns the pop range object id that's associated with the warp id
pub fn get_warp(&mut self, warp_id: u32) -> Option<(u32, u16)> {
let sheet = WarpSheet::read_from(&mut self.game_data, Language::English)?;
let row = sheet.get_row(warp_id)?;
let pop_range_id = row.PopRange().into_u32()?;
let zone_id = row.TerritoryType().into_u16()?;
Some((*pop_range_id, *zone_id))
}
}