diff --git a/src/fot/attributes.rs b/src/fot/attributes.rs index d17705c..530881a 100644 --- a/src/fot/attributes.rs +++ b/src/fot/attributes.rs @@ -1,3 +1,5 @@ +use crate::fot::decoder::Decoder; + use super::esh::{ESHValue, ESH}; use super::stream::{ReadStream, WriteStream}; use super::tag::Tag; @@ -256,6 +258,10 @@ const ADDICTIONS: [&str; 10] = [ #[derive(Debug)] pub struct Attributes { esh: ESH, + size1: u32, + size2: u32, + tag: Tag, + enc_size: usize, pub stats: IndexMap<&'static str, u32>, pub traits: IndexMap<&'static str, u32>, pub derived: IndexMap<&'static str, u32>, @@ -270,7 +276,7 @@ impl Attributes { pub fn from_binary(bin: &[u8]) -> Result { let mut rd = ReadStream::new(bin, 0); - let _ = rd.read_u32()?; + let size1 = rd.read_u32()?; let esh: ESH = rd.read()?; if esh.props["Binary"] == ESHValue::Bool(false) { return Err(anyhow!("Attributes Binary == false")); @@ -288,8 +294,8 @@ impl Attributes { if let ESHValue::Binary(binary) = &esh.props["esbin"] { let mut rd = ReadStream::new(&binary, 0); - let _ = rd.read_u32()?; - let _: Tag = rd.read()?; + let size2 = rd.read_u32()?; + let tag: Tag = rd.read()?; for i in 0..MAX_STATS { stats.insert(STATS[i], rd.read_u32()?); @@ -316,8 +322,13 @@ impl Attributes { addictions.insert(ADDICTIONS[i], rd.read_u32()?); } + let enc_size = binary.len(); Ok(Attributes { esh, + size1, + size2, + tag, + enc_size, stats, traits, derived, @@ -331,4 +342,47 @@ impl Attributes { return Err(anyhow!("Attributes has no esbin")); } } + + pub fn into_binary(mut self) -> Result> { + let esbin = { + let mut wd = WriteStream::new(self.enc_size); + + wd.write_u32(self.size2)?; + wd.write(&self.tag)?; + + for (_, value) in self.stats { + wd.write_u32(value)?; + } + for (_, value) in self.traits { + wd.write_u32(value)?; + } + for (_, value) in self.derived { + wd.write_u32(value)?; + } + for (_, value) in self.skills { + wd.write_u32(value)?; + } + for (_, value) in self.skill_tags { + wd.write_bool(value)?; + } + for (_, value) in self.opt_traits { + wd.write_bool(value)?; + } + for (_, value) in self.perks { + wd.write_u32(value)?; + } + for (_, value) in self.addictions { + wd.write_u32(value)?; + } + + wd.into_vec() + }; + self.esh.set("esbin", ESHValue::Binary(esbin)); + + let mut wd = WriteStream::new(self.esh.get_enc_size()); + wd.write_u32(self.size1)?; + wd.write(&self.esh)?; + + Ok(wd.into_vec()) + } } diff --git a/src/fot/entity.rs b/src/fot/entity.rs index 78b7ee5..c02d7d3 100644 --- a/src/fot/entity.rs +++ b/src/fot/entity.rs @@ -42,6 +42,13 @@ impl Entity { Err(anyhow!("Attributes is not binary")) } } + + pub fn set_attributes(&mut self, attrs: Attributes) -> Result<()> { + self.get_esh_mut()? + .set("Attributes", ESHValue::Binary(attrs.into_binary()?)); + + Ok(()) + } } impl DecoderCtx<&mut EntityList, &EntityList> for Entity { diff --git a/src/fot/entitylist.rs b/src/fot/entitylist.rs index a29306d..498cf7c 100644 --- a/src/fot/entitylist.rs +++ b/src/fot/entitylist.rs @@ -62,6 +62,10 @@ impl EntityList { &self.ents[id - 1] } + pub fn get_entity_mut(&mut self, id: usize) -> &mut Entity { + &mut self.ents[id - 1] + } + pub fn dump_to_entfile(&self, ent: &Entity, path: &Path) -> Result<()> { let esh = match &ent.esh { Some(esh) => esh, diff --git a/src/fot/world.rs b/src/fot/world.rs index d22b83b..462b9ca 100644 --- a/src/fot/world.rs +++ b/src/fot/world.rs @@ -38,7 +38,8 @@ impl World { pub fn test(&mut self) -> Result<()> { //let actor_type = self.entlist.get_type_idx("Actor").unwrap(); - let ent = self.entlist.get_entity(2122); + //let ent = self.entlist.get_entity_mut(2122); + let ent = self.entlist.get_entity_mut(2158); let esh = ent.get_esh()?; for (name, value) in &esh.props { println!("{} {}", name, value); @@ -46,8 +47,23 @@ impl World { //self.entlist.dump_to_entfile(ent, Path::new("D:\\actor.ent"))?; println!(""); - let attributes = ent.get_attributes()?; - dbg!(attributes); + let mut attributes = ent.get_attributes()?; + if let ESHValue::Binary(bin) = &esh.get("Attributes").unwrap() { + dbg!(bin.len()); + } + attributes.stats["strength"] = 10; + attributes.stats["perception"] = 10; + attributes.stats["endurance"] = 10; + attributes.stats["charisma"] = 10; + attributes.stats["intelligence"] = 10; + attributes.stats["agility"] = 10; + attributes.stats["luck"] = 10; + ent.set_attributes(attributes)?; + + let esh = ent.get_esh()?; + if let ESHValue::Binary(bin) = &esh.get("Attributes").unwrap() { + dbg!(bin.len()); + } Ok(()) } diff --git a/src/main.rs b/src/main.rs index 667ccf7..e5ae789 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,5 +15,5 @@ fn main() { let mut save = Save::load(Path::new(save_path)).expect("load save"); save.world.test().expect("test"); - //save.save(Path::new("out.sav")).expect("failed to save"); + save.save(Path::new("out.sav")).expect("failed to save"); }