From ba602929ef5573942d73721596e07a6a19d0d57c Mon Sep 17 00:00:00 2001 From: "Alexander \"Ace\" Olofsson" Date: Fri, 6 Apr 2012 21:04:30 +0200 Subject: [PATCH] Adding basic save functions to all record types. --- components/CMakeLists.txt | 2 +- components/esm/defs.hpp | 13 +++++ components/esm/esm_common.hpp | 102 +++++++++++++++++++++++++++++++++ components/esm/esm_reader.hpp | 96 +------------------------------ components/esm/esm_writer.cpp | 28 +++++++++ components/esm/esm_writer.hpp | 71 +++++++++++++++++++++++ components/esm/loadacti.cpp | 9 +++ components/esm/loadacti.hpp | 2 + components/esm/loadalch.cpp | 12 ++++ components/esm/loadalch.hpp | 2 + components/esm/loadappa.cpp | 9 +++ components/esm/loadappa.hpp | 2 + components/esm/loadarmo.cpp | 27 +++++++++ components/esm/loadarmo.hpp | 3 + components/esm/loadbody.cpp | 6 ++ components/esm/loadbody.hpp | 2 + components/esm/loadbook.cpp | 15 +++++ components/esm/loadbook.hpp | 2 + components/esm/loadbsgn.cpp | 10 ++++ components/esm/loadbsgn.hpp | 2 + components/esm/loadcell.cpp | 67 ++++++++++++++++++++++ components/esm/loadcell.hpp | 4 ++ components/esm/loadclas.cpp | 7 +++ components/esm/loadclas.hpp | 2 + components/esm/loadclot.cpp | 17 ++++++ components/esm/loadclot.hpp | 2 + components/esm/loadcont.cpp | 22 +++++++ components/esm/loadcont.hpp | 3 + components/esm/loadcrea.cpp | 16 ++++++ components/esm/loadcrea.hpp | 2 + components/esm/loadcrec.hpp | 9 +++ components/esm/loaddial.cpp | 11 ++++ components/esm/loaddial.hpp | 2 + components/esm/loaddoor.cpp | 12 ++++ components/esm/loaddoor.hpp | 2 + components/esm/loadench.cpp | 5 ++ components/esm/loadench.hpp | 2 + components/esm/loadfact.cpp | 17 ++++++ components/esm/loadfact.hpp | 2 + components/esm/loadglob.cpp | 13 +++++ components/esm/loadglob.hpp | 2 + components/esm/loadgmst.cpp | 10 ++++ components/esm/loadgmst.hpp | 2 + components/esm/loadinfo.cpp | 39 +++++++++++++ components/esm/loadinfo.hpp | 2 + components/esm/loadingr.cpp | 10 ++++ components/esm/loadingr.hpp | 2 + components/esm/loadland.cpp | 26 +++++++++ components/esm/loadland.hpp | 4 ++ components/esm/loadlevlist.cpp | 12 ++++ components/esm/loadlevlist.hpp | 2 + components/esm/loadligh.cpp | 13 +++++ components/esm/loadligh.hpp | 2 + components/esm/loadlocks.cpp | 24 ++++++++ components/esm/loadlocks.hpp | 10 ++++ components/esm/loadltex.cpp | 5 ++ components/esm/loadltex.hpp | 2 + components/esm/loadmgef.cpp | 19 ++++++ components/esm/loadmgef.hpp | 2 + components/esm/loadmisc.cpp | 8 +++ components/esm/loadmisc.hpp | 2 + components/esm/loadnpc.cpp | 30 ++++++++++ components/esm/loadnpc.hpp | 3 + components/esm/loadnpcc.hpp | 4 ++ components/esm/loadpgrd.cpp | 23 ++++++++ components/esm/loadpgrd.hpp | 2 + components/esm/loadrace.cpp | 7 +++ components/esm/loadrace.hpp | 2 + components/esm/loadregn.cpp | 14 +++++ components/esm/loadregn.hpp | 2 + components/esm/loadscpt.cpp | 16 ++++++ components/esm/loadscpt.hpp | 2 + components/esm/loadskil.cpp | 6 ++ components/esm/loadskil.hpp | 2 + components/esm/loadsndg.cpp | 6 ++ components/esm/loadsndg.hpp | 2 + components/esm/loadsoun.cpp | 5 ++ components/esm/loadsoun.hpp | 2 + components/esm/loadspel.cpp | 6 ++ components/esm/loadspel.hpp | 2 + components/esm/loadsscr.cpp | 5 ++ components/esm/loadsscr.hpp | 2 + components/esm/loadstat.cpp | 4 ++ components/esm/loadstat.hpp | 2 + components/esm/loadweap.cpp | 9 +++ components/esm/loadweap.hpp | 2 + 86 files changed, 894 insertions(+), 96 deletions(-) create mode 100644 components/esm/esm_common.hpp create mode 100644 components/esm/esm_writer.cpp create mode 100644 components/esm/esm_writer.hpp diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index b48c50640..83ebcefe1 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -35,7 +35,7 @@ add_component_dir (esm_store ) add_component_dir (esm - attr defs esm_reader loadacti loadalch loadappa loadarmo loadbody loadbook loadbsgn loadcell + attr defs esm_reader esm_writer loadacti loadalch loadappa loadarmo loadbody loadbook loadbsgn loadcell loadclas loadclot loadcont loadcrea loadcrec loaddial loaddoor loadench loadfact loadglob loadgmst loadinfo loadingr loadland loadlevlist loadligh loadlocks loadltex loadmgef loadmisc loadnpcc loadnpc loadpgrd loadrace loadregn loadscpt loadskil loadsndg loadsoun loadspel loadsscr loadstat diff --git a/components/esm/defs.hpp b/components/esm/defs.hpp index 917c1031f..a33247906 100644 --- a/components/esm/defs.hpp +++ b/components/esm/defs.hpp @@ -2,6 +2,7 @@ #define _ESM_DEFS_H #include "esm_reader.hpp" +#include "esm_writer.hpp" namespace ESM { @@ -47,6 +48,11 @@ struct SpellList while (esm.isNextSub("NPCS")) list.push_back(esm.getHString()); } + void save(ESMWriter &esm) + { + for (std::vector::iterator it = list.begin(); it != list.end(); ++it) + esm.writeHNString("NPCS", *it); + } }; /** Defines a spell effect. Shared between SPEL (Spells), ALCH @@ -92,6 +98,13 @@ struct EffectList list.push_back(s); } } + void save(ESMWriter &esm) + { + for (std::vector::iterator it = list.begin(); it != list.end(); ++it) + { + esm.writeHNT("ENAM", *it, 24); + } + } }; } diff --git a/components/esm/esm_common.hpp b/components/esm/esm_common.hpp new file mode 100644 index 000000000..abe0250df --- /dev/null +++ b/components/esm/esm_common.hpp @@ -0,0 +1,102 @@ +#ifndef _ESM_COMMON_H +#define _ESM_COMMON_H + +#include + +namespace ESM +{ +enum Version + { + VER_12 = 0x3f99999a, + VER_13 = 0x3fa66666 + }; + +enum FileType + { + FT_ESP = 0, // Plugin + FT_ESM = 1, // Master + FT_ESS = 32 // Savegame + }; + +// Used to mark special files. The original ESM files are given +// special treatment in a few places, most noticably in loading and +// filtering out "dirtly" GMST entries correctly. +enum SpecialFile + { + SF_Other, + SF_Morrowind, + SF_Tribunal, + SF_Bloodmoon + }; + +/* A structure used for holding fixed-length strings. In the case of + LEN=4, it can be more efficient to match the string as a 32 bit + number, therefore the struct is implemented as a union with an int. + */ +template +union NAME_T +{ + char name[LEN]; + int32_t val; + + bool operator==(const char *str) + { + for(int i=0; i NAME; +typedef NAME_T<32> NAME32; +typedef NAME_T<64> NAME64; +typedef NAME_T<256> NAME256; + +#pragma pack(push) +#pragma pack(1) +/// File header data for all ES files +struct HEDRstruct +{ + /* File format version. This is actually a float, the supported + versions are 1.2 and 1.3. These correspond to: + 1.2 = 0x3f99999a and 1.3 = 0x3fa66666 + */ + int version; + int type; // 0=esp, 1=esm, 32=ess + NAME32 author; // Author's name + NAME256 desc; // File description + int records; // Number of records? Not used. +}; + +// Defines another files (esm or esp) that this file depends upon. +struct MasterData +{ + std::string name; + uint64_t size; +}; + +// Data that is only present in save game files +struct SaveData +{ + float pos[6]; // Player position and rotation + NAME64 cell; // Cell name + float unk2; // Unknown value - possibly game time? + NAME32 player; // Player name +}; +#pragma pack(pop) +} + +#endif diff --git a/components/esm/esm_reader.hpp b/components/esm/esm_reader.hpp index 0420f37cd..6e5592cf7 100644 --- a/components/esm/esm_reader.hpp +++ b/components/esm/esm_reader.hpp @@ -16,103 +16,9 @@ #include #include +#include "esm_common.hpp" namespace ESM { - -enum Version - { - VER_12 = 0x3f99999a, - VER_13 = 0x3fa66666 - }; - -enum FileType - { - FT_ESP = 0, // Plugin - FT_ESM = 1, // Master - FT_ESS = 32 // Savegame - }; - -// Used to mark special files. The original ESM files are given -// special treatment in a few places, most noticably in loading and -// filtering out "dirtly" GMST entries correctly. -enum SpecialFile - { - SF_Other, - SF_Morrowind, - SF_Tribunal, - SF_Bloodmoon - }; - -/* A structure used for holding fixed-length strings. In the case of - LEN=4, it can be more efficient to match the string as a 32 bit - number, therefore the struct is implemented as a union with an int. - */ -template -union NAME_T -{ - char name[LEN]; - int32_t val; - - bool operator==(const char *str) - { - for(int i=0; i NAME; -typedef NAME_T<32> NAME32; -typedef NAME_T<64> NAME64; -typedef NAME_T<256> NAME256; - -#pragma pack(push) -#pragma pack(1) -/// File header data for all ES files -struct HEDRstruct -{ - /* File format version. This is actually a float, the supported - versions are 1.2 and 1.3. These correspond to: - 1.2 = 0x3f99999a and 1.3 = 0x3fa66666 - */ - int version; - int type; // 0=esp, 1=esm, 32=ess - NAME32 author; // Author's name - NAME256 desc; // File description - int records; // Number of records? Not used. -}; - -// Defines another files (esm or esp) that this file depends upon. -struct MasterData -{ - std::string name; - uint64_t size; -}; - -// Data that is only present in save game files -struct SaveData -{ - float pos[6]; // Player position and rotation - NAME64 cell; // Cell name - float unk2; // Unknown value - possibly game time? - NAME32 player; // Player name -}; -#pragma pack(pop) - - /* This struct defines a file 'context' which can be saved and later restored by an ESMReader instance. It will save the position within a file, and when restored will let you read from that position as diff --git a/components/esm/esm_writer.cpp b/components/esm/esm_writer.cpp new file mode 100644 index 000000000..da040c664 --- /dev/null +++ b/components/esm/esm_writer.cpp @@ -0,0 +1,28 @@ +#include "esm_writer.hpp" + +namespace ESM +{ + +void ESMWriter::writeHNString(const std::string& name, const std::string& data) +{ + writeName(name); + writeHString(data); +} + +void ESMWriter::writeHString(const std::string& data) +{ + writeT(data.size()-1); + write(data.c_str(), data.size()-1); +} + +void ESMWriter::writeName(const std::string& name) +{ + write(name.c_str(), name.size()-1); +} + +void ESMWriter::write(const char* data, int size) +{ + m_stream.write(data, size); +} + +} diff --git a/components/esm/esm_writer.hpp b/components/esm/esm_writer.hpp new file mode 100644 index 000000000..5adf32049 --- /dev/null +++ b/components/esm/esm_writer.hpp @@ -0,0 +1,71 @@ +#ifndef _ESM_WRITER_H +#define _ESM_WRITER_H + +#include +#include + +#include "esm_common.hpp" + +namespace ESM { + +class ESMWriter +{ +public: + void writeHNString(const std::string& name, const std::string& data); + void writeHNOString(const std::string& name, const std::string& data) + { + if (!data.empty()) + writeHNString(name, data); + } + + template + void writeHNT(const std::string& name, const T& data) + { + writeName(name); + writeT(data); + } + + template + void writeHNT(const std::string& name, const T& data, int size) + { + assert(sizeof(T) == size); + writeHNT(name, data); + } + + template + void writeHT(const T& data) + { + writeT((unsigned int)sizeof(T)); + writeT(data); + } + + template + void writeHT(const T& data, int size) + { + assert(sizeof(T) == size); + writeHT(data); + } + + template + void writeT(const T& data) + { + write((char*)&data, sizeof(T)); + } + + template + void writeT(const T& data, int size) + { + assert(sizeof(T) == size); + writeT(data); + } + + void writeHString(const std::string& data); + void writeName(const std::string& data); + void write(const char* data, int size); + +private: + std::ostream m_stream; +}; + +} +#endif diff --git a/components/esm/loadacti.cpp b/components/esm/loadacti.cpp index 40c9b635c..a5e59a006 100644 --- a/components/esm/loadacti.cpp +++ b/components/esm/loadacti.cpp @@ -8,4 +8,13 @@ void Activator::load(ESMReader &esm) name = esm.getHNString("FNAM"); script = esm.getHNOString("SCRI"); } +void Activator::save(ESMWriter &esm) +{ + esm.writeHNString("MODL", model); + esm.writeHNString("FNAM", name); + if (!script.empty()) + { + esm.writeHNString("SCRI", script); + } +} } diff --git a/components/esm/loadacti.hpp b/components/esm/loadacti.hpp index 783559e11..3f968bc7c 100644 --- a/components/esm/loadacti.hpp +++ b/components/esm/loadacti.hpp @@ -2,6 +2,7 @@ #define _ESM_ACTI_H #include "esm_reader.hpp" +#include "esm_writer.hpp" namespace ESM { @@ -11,6 +12,7 @@ struct Activator std::string name, script, model; void load(ESMReader &esm); + void save(ESMWriter &esm); }; } #endif diff --git a/components/esm/loadalch.cpp b/components/esm/loadalch.cpp index d3bc36a77..7db9ef9ac 100644 --- a/components/esm/loadalch.cpp +++ b/components/esm/loadalch.cpp @@ -11,4 +11,16 @@ void Potion::load(ESMReader &esm) esm.getHNT(data, "ALDT", 12); effects.load(esm); } +void Potion::save(ESMWriter &esm) +{ + esm.writeHNString("MODL", model); + if (!icon.empty()) + esm.writeHNString("TEXT", icon); + if (!script.empty()) + esm.writeHNString("SCRI", script); + if (!name.empty()) + esm.writeHNString("FNAM", name); + esm.writeHNT("ALDT", data, 12); + effects.save(esm); +} } diff --git a/components/esm/loadalch.hpp b/components/esm/loadalch.hpp index c21e5dea0..b447fe50c 100644 --- a/components/esm/loadalch.hpp +++ b/components/esm/loadalch.hpp @@ -2,6 +2,7 @@ #define _ESM_ALCH_H #include "esm_reader.hpp" +#include "esm_writer.hpp" #include "defs.hpp" namespace ESM @@ -25,6 +26,7 @@ struct Potion EffectList effects; void load(ESMReader &esm); + void save(ESMWriter &esm); }; } #endif diff --git a/components/esm/loadappa.cpp b/components/esm/loadappa.cpp index c76ad5350..17cc22087 100644 --- a/components/esm/loadappa.cpp +++ b/components/esm/loadappa.cpp @@ -10,4 +10,13 @@ void Apparatus::load(ESMReader &esm) script = esm.getHNOString("SCRI"); icon = esm.getHNString("ITEX"); } +void Apparatus::save(ESMWriter &esm) +{ + esm.writeHNString("MODL", model); + esm.writeHNString("FNAM", name); + esm.writeHNT("AADT", data, 16); + if (!script.empty()) + esm.writeHNString("SCRI", script); + esm.writeHNString("ITEX", icon); +} } diff --git a/components/esm/loadappa.hpp b/components/esm/loadappa.hpp index 2caca32b3..ff105a307 100644 --- a/components/esm/loadappa.hpp +++ b/components/esm/loadappa.hpp @@ -2,6 +2,7 @@ #define _ESM_APPA_H #include "esm_reader.hpp" +#include "esm_writer.hpp" namespace ESM { @@ -32,6 +33,7 @@ struct Apparatus std::string model, icon, script, name; void load(ESMReader &esm); + void save(ESMWriter &esm); }; } #endif diff --git a/components/esm/loadarmo.cpp b/components/esm/loadarmo.cpp index ddc25e176..14cb056bf 100644 --- a/components/esm/loadarmo.cpp +++ b/components/esm/loadarmo.cpp @@ -11,6 +11,19 @@ void PartReferenceList::load(ESMReader &esm) esm.getHT(pr.part); // The INDX byte pr.male = esm.getHNOString("BNAM"); pr.female = esm.getHNOString("CNAM"); + parts.push_back(pr); + } +} + +void PartReferenceList::save(ESMWriter &esm) +{ + for (std::vector::iterator it = parts.begin(); it != parts.end(); ++it) + { + esm.writeHT(it->part); + if (!it->male.empty()) + esm.writeHNString("BNAM", it->male); + if (!it->female.empty()) + esm.writeHNString("CNAM", it->female); } } @@ -25,4 +38,18 @@ void Armor::load(ESMReader &esm) enchant = esm.getHNOString("ENAM"); } +void Armor::save(ESMWriter &esm) +{ + esm.writeHNString("MODL", model); + esm.writeHNString("FNAM", name); + if (!script.empty()) + esm.writeHNString("SCRI", script); + esm.writeHNT("AODT", data, 24); + if (!icon.empty()) + esm.writeHNString("ITEX", icon); + parts.save(esm); + if (!enchant.empty()) + esm.writeHNString("ENAM", enchant); +} + } diff --git a/components/esm/loadarmo.hpp b/components/esm/loadarmo.hpp index 16b6b1d3a..5026696c2 100644 --- a/components/esm/loadarmo.hpp +++ b/components/esm/loadarmo.hpp @@ -2,6 +2,7 @@ #define _ESM_ARMO_H #include "esm_reader.hpp" +#include "esm_writer.hpp" namespace ESM { @@ -50,6 +51,7 @@ struct PartReferenceList std::vector parts; void load(ESMReader &esm); + void save(ESMWriter &esm); }; struct Armor @@ -82,6 +84,7 @@ struct Armor std::string name, model, icon, script, enchant; void load(ESMReader &esm); + void save(ESMWriter &esm); }; } #endif diff --git a/components/esm/loadbody.cpp b/components/esm/loadbody.cpp index 1c72b0fe0..72d56eac3 100644 --- a/components/esm/loadbody.cpp +++ b/components/esm/loadbody.cpp @@ -9,5 +9,11 @@ void BodyPart::load(ESMReader &esm) name = esm.getHNString("FNAM"); esm.getHNT(data, "BYDT", 4); } +void BodyPart::save(ESMWriter &esm) +{ + esm.writeHNString("MODL", model); + esm.writeHNString("FNAM", name); + esm.writeHNT("BYDT", data, 4); +} } diff --git a/components/esm/loadbody.hpp b/components/esm/loadbody.hpp index de3db40fc..46cb1d899 100644 --- a/components/esm/loadbody.hpp +++ b/components/esm/loadbody.hpp @@ -2,6 +2,7 @@ #define _ESM_BODY_H #include "esm_reader.hpp" +#include "esm_writer.hpp" namespace ESM { @@ -52,6 +53,7 @@ struct BodyPart std::string model, name; void load(ESMReader &esm); + void save(ESMWriter &esm); }; } #endif diff --git a/components/esm/loadbook.cpp b/components/esm/loadbook.cpp index ffa958e14..829b7d297 100644 --- a/components/esm/loadbook.cpp +++ b/components/esm/loadbook.cpp @@ -13,5 +13,20 @@ void Book::load(ESMReader &esm) text = esm.getHNOString("TEXT"); enchant = esm.getHNOString("ENAM"); } +void Book::save(ESMWriter &esm) +{ + esm.writeHNString("MODL", model); + if (!name.empty()) + esm.writeHNString("FNAM", name); + esm.writeHNT("BKDT", data, 20); + if (!script.empty()) + esm.writeHNString("SCRI", script); + if (!icon.empty()) + esm.writeHNString("ITEX", icon); + if (!text.empty()) + esm.writeHNString("TEXT", text); + if (!enchant.empty()) + esm.writeHNString("ENAM", enchant); +} } diff --git a/components/esm/loadbook.hpp b/components/esm/loadbook.hpp index 3a4ab441e..a46135cc0 100644 --- a/components/esm/loadbook.hpp +++ b/components/esm/loadbook.hpp @@ -2,6 +2,7 @@ #define _ESM_BOOK_H #include "esm_reader.hpp" +#include "esm_writer.hpp" namespace ESM { @@ -22,6 +23,7 @@ struct Book std::string name, model, icon, script, enchant, text; void load(ESMReader &esm); + void save(ESMWriter &esm); }; } #endif diff --git a/components/esm/loadbsgn.cpp b/components/esm/loadbsgn.cpp index 976cb7d20..9488f355f 100644 --- a/components/esm/loadbsgn.cpp +++ b/components/esm/loadbsgn.cpp @@ -11,5 +11,15 @@ void BirthSign::load(ESMReader &esm) powers.load(esm); } +void BirthSign::save(ESMWriter &esm) +{ + esm.writeHNString("FNAM", name); + if (!texture.empty()) + esm.writeHNString("TNAM", texture); + if (!description.empty()) + esm.writeHNString("DESC", description); + + powers.save(esm); +} } diff --git a/components/esm/loadbsgn.hpp b/components/esm/loadbsgn.hpp index 53964b02c..d00664bff 100644 --- a/components/esm/loadbsgn.hpp +++ b/components/esm/loadbsgn.hpp @@ -3,6 +3,7 @@ #include "defs.hpp" #include "esm_reader.hpp" +#include "esm_writer.hpp" namespace ESM { @@ -15,6 +16,7 @@ struct BirthSign SpellList powers; void load(ESMReader &esm); + void save(ESMWriter &esm); }; } #endif diff --git a/components/esm/loadcell.cpp b/components/esm/loadcell.cpp index 158cc0867..8b3d09183 100644 --- a/components/esm/loadcell.cpp +++ b/components/esm/loadcell.cpp @@ -6,6 +6,49 @@ namespace ESM { +void CellRef::save(ESMWriter &esm) +{ + esm.writeHNT("FRMR", refnum); + esm.writeHNString("NAME", refID); + + if (scale != 1.0) + esm.writeHNT("XSCL", scale); + + esm.writeHNOString("ANAM", owner); + esm.writeHNOString("BNAM", glob); + esm.writeHNOString("SXOL", soul); + + esm.writeHNOString("CNAM", faction); + if (factIndex != -1) + esm.writeHNT("INDX", factIndex); + + if (charge != -1.0) + esm.writeHNT("XCHG", charge); + + if (intv != 0) + esm.writeHNT("INTV", intv); + if (nam9 != 0) + esm.writeHNT("NAM9", nam9); + + if (teleport) + { + esm.writeHNT("DODT", doorDest); + esm.writeHNOString("DNAM", destCell); + } + + if (lockLevel != 0) + esm.writeHNT("FLTV", lockLevel); + esm.writeHNOString("KNAM", key); + esm.writeHNOString("TNAM", trap); + + if (unam != 0) + esm.writeHNT("UNAM", unam); + if (fltv != 0) + esm.writeHNT("FLTV", fltv); + + esm.writeHNT("DATA", pos, 24); +} + void Cell::load(ESMReader &esm) { // Ignore this for now, it might mean we should delete the entire @@ -50,6 +93,30 @@ void Cell::load(ESMReader &esm) esm.skipRecord(); } +void Cell::save(ESMWriter &esm) +{ + esm.writeHNT("DATA", data, 12); + if (data.flags & Interior) + { + if (water != 0) + esm.writeHNT("WHGT", water); + if (data.flags & QuasiEx) + { + if (!region.empty()) + esm.writeHNString("RGNN", region); + } + else + esm.writeHNT("AMBI", ambi, 16); + } + else + { + if (!region.empty()) + esm.writeHNString("RGNN", region); + if (mapColor != 0) + esm.writeHNT("NAM5", mapColor); + } +} + void Cell::restore(ESMReader &esm) const { esm.restoreContext(context); diff --git a/components/esm/loadcell.hpp b/components/esm/loadcell.hpp index 8070f9c03..8d461369c 100644 --- a/components/esm/loadcell.hpp +++ b/components/esm/loadcell.hpp @@ -2,6 +2,7 @@ #define _ESM_CELL_H #include "esm_reader.hpp" +#include "esm_writer.hpp" #include "defs.hpp" namespace ESM { @@ -71,6 +72,8 @@ public: // Position and rotation of this object within the cell Position pos; + + void save(ESMWriter &esm); }; /* Cells hold data about objects, creatures, statics (rocks, walls, @@ -118,6 +121,7 @@ struct Cell int mapColor; void load(ESMReader &esm); + void save(ESMWriter &esm); bool isExterior() const { diff --git a/components/esm/loadclas.cpp b/components/esm/loadclas.cpp index b15852cc2..05cbfe709 100644 --- a/components/esm/loadclas.cpp +++ b/components/esm/loadclas.cpp @@ -25,5 +25,12 @@ void Class::load(ESMReader &esm) description = esm.getHNOString("DESC"); } +void Class::save(ESMWriter &esm) +{ + esm.writeHNString("FNAM", name); + esm.writeHNT("CLDT", data, 60); + if (!description.empty()) + esm.writeHNString("DESC", description); +} } diff --git a/components/esm/loadclas.hpp b/components/esm/loadclas.hpp index 08412c838..a89481a7a 100644 --- a/components/esm/loadclas.hpp +++ b/components/esm/loadclas.hpp @@ -2,6 +2,7 @@ #define _ESM_CLAS_H #include "esm_reader.hpp" +#include "esm_writer.hpp" namespace ESM { @@ -61,6 +62,7 @@ struct Class CLDTstruct data; void load(ESMReader &esm); + void save(ESMWriter &esm); }; } #endif diff --git a/components/esm/loadclot.cpp b/components/esm/loadclot.cpp index 1d6c9d4a1..b1c678348 100644 --- a/components/esm/loadclot.cpp +++ b/components/esm/loadclot.cpp @@ -16,5 +16,22 @@ void Clothing::load(ESMReader &esm) enchant = esm.getHNOString("ENAM"); } +void Clothing::save(ESMWriter &esm) +{ + esm.writeHNString("MODL", model); + if (!name.empty()) + esm.writeHNString("FNAM", name); + esm.writeHNT("CTDT", data, 12); + + if (!script.empty()) + esm.writeHNString("SCRI", script); + if (!icon.empty()) + esm.writeHNString("ITEX", icon); + + parts.save(esm); + + if (!enchant.empty()) + esm.writeHNString("ENAM", enchant); +} } diff --git a/components/esm/loadclot.hpp b/components/esm/loadclot.hpp index 8fa06e7e4..77ef3786a 100644 --- a/components/esm/loadclot.hpp +++ b/components/esm/loadclot.hpp @@ -2,6 +2,7 @@ #define _ESM_CLOT_H #include "esm_reader.hpp" +#include "esm_writer.hpp" #include "loadarmo.hpp" namespace ESM @@ -41,6 +42,7 @@ struct Clothing std::string name, model, icon, enchant, script; void load(ESMReader &esm); + void save(ESMWriter &esm); }; } #endif diff --git a/components/esm/loadcont.cpp b/components/esm/loadcont.cpp index 14699ccc5..ba90e52ce 100644 --- a/components/esm/loadcont.cpp +++ b/components/esm/loadcont.cpp @@ -13,6 +13,14 @@ void InventoryList::load(ESMReader &esm) } } +void InventoryList::save(ESMWriter &esm) +{ + for (std::vector::iterator it = list.begin(); it != list.end(); ++it) + { + esm.writeHNT("NPCO", *it, 36); + } +} + void Container::load(ESMReader &esm) { model = esm.getHNString("MODL"); @@ -30,4 +38,18 @@ void Container::load(ESMReader &esm) inventory.load(esm); } +void Container::save(ESMWriter &esm) +{ + esm.writeHNString("MODL", model); + if (!name.empty()) + esm.writeHNString("FNAM", name); + esm.writeHNT("CNDT", weight, 4); + esm.writeHNT("FLAG", flags, 4); + + if (!script.empty()) + esm.writeHNString("SCRI", script); + + inventory.save(esm); +} + } diff --git a/components/esm/loadcont.hpp b/components/esm/loadcont.hpp index 4614c4230..bf6994f9a 100644 --- a/components/esm/loadcont.hpp +++ b/components/esm/loadcont.hpp @@ -2,6 +2,7 @@ #define _ESM_CONT_H #include "esm_reader.hpp" +#include "esm_writer.hpp" namespace ESM { @@ -21,6 +22,7 @@ struct InventoryList std::vector list; void load(ESMReader &esm); + void save(ESMWriter &esm); }; struct Container @@ -39,6 +41,7 @@ struct Container InventoryList inventory; void load(ESMReader &esm); + void save(ESMWriter &esm); }; } #endif diff --git a/components/esm/loadcrea.cpp b/components/esm/loadcrea.cpp index 651d9a318..0cab2761e 100644 --- a/components/esm/loadcrea.cpp +++ b/components/esm/loadcrea.cpp @@ -37,4 +37,20 @@ void Creature::load(ESMReader &esm, const std::string& id) esm.skipRecord(); } +void Creature::save(ESMWriter &esm) +{ + esm.writeHNString("MODL", model); + if (!original.empty()) + esm.writeHNString("CNAM", original); + if (!name.empty()) + esm.writeHNString("FNAM", name); + if (!script.empty()) + esm.writeHNString("SCRI", script); + esm.writeHNT("NPDT", data, 96); + esm.writeHNT("FLAG", flags); + if (scale != 1.0) + esm.writeHNT("XSCL", scale); + inventory.save(esm); +} + } diff --git a/components/esm/loadcrea.hpp b/components/esm/loadcrea.hpp index 3c334ebbd..2f5f4061d 100644 --- a/components/esm/loadcrea.hpp +++ b/components/esm/loadcrea.hpp @@ -2,6 +2,7 @@ #define _ESM_CREA_H #include "esm_reader.hpp" +#include "esm_writer.hpp" #include "loadcont.hpp" namespace ESM @@ -64,6 +65,7 @@ struct Creature std::string mId; void load(ESMReader &esm, const std::string& id); + void save(ESMWriter &esm); }; } #endif diff --git a/components/esm/loadcrec.hpp b/components/esm/loadcrec.hpp index 4d38d4a23..056f572ae 100644 --- a/components/esm/loadcrec.hpp +++ b/components/esm/loadcrec.hpp @@ -2,6 +2,7 @@ #define _ESM_CREC_H #include "esm_reader.hpp" +#include "esm_writer.hpp" namespace ESM { @@ -15,6 +16,10 @@ struct LoadCREC { esm.skipRecord(); } + + void save(ESMWriter &esm) + { + } }; /// Changes an item list / container @@ -24,6 +29,10 @@ struct LoadCNTC { esm.skipRecord(); } + + void save(ESMWriter &esm) + { + } }; } #endif diff --git a/components/esm/loaddial.cpp b/components/esm/loaddial.cpp index d2283d351..bdee27586 100644 --- a/components/esm/loaddial.cpp +++ b/components/esm/loaddial.cpp @@ -22,4 +22,15 @@ void Dialogue::load(ESMReader &esm) esm.fail("Unknown sub record size"); } +void Dialogue::save(ESMWriter &esm) +{ + if (type != Deleted) + esm.writeHNT("DATA", type); + else + { + esm.writeHNT("DATA", (int)1); + esm.writeHNT("DELE", (int)1); + } +} + } diff --git a/components/esm/loaddial.hpp b/components/esm/loaddial.hpp index 1f18a49d0..a19b0c7ad 100644 --- a/components/esm/loaddial.hpp +++ b/components/esm/loaddial.hpp @@ -4,6 +4,7 @@ #include #include "esm_reader.hpp" +#include "esm_writer.hpp" #include "loadinfo.hpp" namespace ESM @@ -30,6 +31,7 @@ struct Dialogue std::vector mInfo; void load(ESMReader &esm); + void save(ESMWriter &esm); }; } #endif diff --git a/components/esm/loaddoor.cpp b/components/esm/loaddoor.cpp index d3cc69bd4..513eac753 100644 --- a/components/esm/loaddoor.cpp +++ b/components/esm/loaddoor.cpp @@ -11,5 +11,17 @@ void Door::load(ESMReader &esm) openSound = esm.getHNOString("SNAM"); closeSound = esm.getHNOString("ANAM"); } +void Door::save(ESMWriter &esm) +{ + esm.writeHNString("MODL", model); + if (!name.empty()) + esm.writeHNString("FNAM", name); + if (!script.empty()) + esm.writeHNString("SCRI", script); + if (!openSound.empty()) + esm.writeHNString("SNAM", openSound); + if (!closeSound.empty()) + esm.writeHNString("ANAM", closeSound); +} } diff --git a/components/esm/loaddoor.hpp b/components/esm/loaddoor.hpp index 2c0db4064..1234ac7f9 100644 --- a/components/esm/loaddoor.hpp +++ b/components/esm/loaddoor.hpp @@ -2,6 +2,7 @@ #define _ESM_DOOR_H #include "esm_reader.hpp" +#include "esm_writer.hpp" namespace ESM { @@ -11,6 +12,7 @@ struct Door std::string name, model, script, openSound, closeSound; void load(ESMReader &esm); + void save(ESMWriter &esm); }; } #endif diff --git a/components/esm/loadench.cpp b/components/esm/loadench.cpp index b2787492d..6157463cf 100644 --- a/components/esm/loadench.cpp +++ b/components/esm/loadench.cpp @@ -8,5 +8,10 @@ void Enchantment::load(ESMReader &esm) esm.getHNT(data, "ENDT", 16); effects.load(esm); } +void Enchantment::save(ESMWriter &esm) +{ + esm.writeHNT("ENDT", data, 16); + effects.save(esm); +} } diff --git a/components/esm/loadench.hpp b/components/esm/loadench.hpp index 449589e25..609166983 100644 --- a/components/esm/loadench.hpp +++ b/components/esm/loadench.hpp @@ -2,6 +2,7 @@ #define _ESM_ENCH_H #include "esm_reader.hpp" +#include "esm_writer.hpp" #include "defs.hpp" namespace ESM @@ -34,6 +35,7 @@ struct Enchantment EffectList effects; void load(ESMReader &esm); + void save(ESMWriter &esm); }; } #endif diff --git a/components/esm/loadfact.cpp b/components/esm/loadfact.cpp index 346ad2a2e..fdbedcbd0 100644 --- a/components/esm/loadfact.cpp +++ b/components/esm/loadfact.cpp @@ -27,5 +27,22 @@ void Faction::load(ESMReader &esm) reactions.push_back(r); } } +void Faction::save(ESMWriter &esm) +{ + esm.writeHNString("FNAM", name); + + for (int i = 0; !ranks[i].empty(); i++) + { + esm.writeHNString("RNAM", ranks[i]); + } + + esm.writeHNT("FADT", data, 240); + + for (std::vector::iterator it = reactions.begin(); it != reactions.end(); ++it) + { + esm.writeHNString("ANAM", it->faction); + esm.writeHNT("INTV", it->reaction); + } +} } diff --git a/components/esm/loadfact.hpp b/components/esm/loadfact.hpp index 85874aa78..686554da3 100644 --- a/components/esm/loadfact.hpp +++ b/components/esm/loadfact.hpp @@ -2,6 +2,7 @@ #define _ESM_FACT_H #include "esm_reader.hpp" +#include "esm_writer.hpp" namespace ESM { @@ -53,6 +54,7 @@ struct Faction std::string ranks[10]; void load(ESMReader &esm); + void save(ESMWriter &esm); }; } #endif diff --git a/components/esm/loadglob.cpp b/components/esm/loadglob.cpp index c946b3fa0..cf43de957 100644 --- a/components/esm/loadglob.cpp +++ b/components/esm/loadglob.cpp @@ -21,4 +21,17 @@ void Global::load(ESMReader &esm) esm.getHNT(value, "FLTV"); } +void Global::save(ESMWriter &esm) +{ + switch(type) + { + case VT_Short: esm.writeHNString("FNAM", "s"); break; + case VT_Int: esm.writeHNString("FNAM", "l"); break; + case VT_Float: esm.writeHNString("FNAM", "f"); break; + default: return; + } + + esm.writeHNT("FLTV", value); +} + } diff --git a/components/esm/loadglob.hpp b/components/esm/loadglob.hpp index 5028679dd..669475fe7 100644 --- a/components/esm/loadglob.hpp +++ b/components/esm/loadglob.hpp @@ -2,6 +2,7 @@ #define _ESM_GLOB_H #include "esm_reader.hpp" +#include "esm_writer.hpp" #include "defs.hpp" namespace ESM @@ -17,6 +18,7 @@ struct Global VarType type; void load(ESMReader &esm); + void save(ESMWriter &esm); }; } #endif diff --git a/components/esm/loadgmst.cpp b/components/esm/loadgmst.cpp index 677642e31..21c2d1fb1 100644 --- a/components/esm/loadgmst.cpp +++ b/components/esm/loadgmst.cpp @@ -168,5 +168,15 @@ void GameSetting::load(ESMReader &esm) && isDirtyBloodmoon())) dirty = true; } +void GameSetting::save(ESMWriter &esm) +{ + switch(type) + { + case VT_String: esm.writeHNString("STRV", str); break; + case VT_Int: esm.writeHNT("INTV", i); break; + case VT_Float: esm.writeHNT("FLTV", f); break; + default: break; + } +} } diff --git a/components/esm/loadgmst.hpp b/components/esm/loadgmst.hpp index 01fbc3067..dc0400a4e 100644 --- a/components/esm/loadgmst.hpp +++ b/components/esm/loadgmst.hpp @@ -2,6 +2,7 @@ #define _ESM_GMST_H #include "esm_reader.hpp" +#include "esm_writer.hpp" #include "defs.hpp" namespace ESM @@ -83,6 +84,7 @@ struct GameSetting bool isDirtyBloodmoon(); void load(ESMReader &esm); + void save(ESMWriter &esm); }; } #endif diff --git a/components/esm/loadinfo.cpp b/components/esm/loadinfo.cpp index 0f08b3c8a..c240aba87 100644 --- a/components/esm/loadinfo.cpp +++ b/components/esm/loadinfo.cpp @@ -130,4 +130,43 @@ void DialInfo::load(ESMReader &esm) esm.skipRecord(); } +void DialInfo::save(ESMWriter &esm) +{ + esm.writeHNString("INAM", id); + esm.writeHNString("PNAM", prev); + esm.writeHNString("NNAM", next); + esm.writeHNT("DATA", data, 12); + esm.writeHNOString("ONAM", actor); + esm.writeHNOString("RNAM", race); + esm.writeHNOString("CNAM", clas); + esm.writeHNOString("FNAM", npcFaction); + esm.writeHNOString("ANAM", cell); + esm.writeHNOString("DNAM", pcFaction); + esm.writeHNOString("SNAM", sound); + esm.writeHNOString("NAME", response); + + for (std::vector::iterator it = selects.begin(); it != selects.end(); ++it) + { + esm.writeHNString("SCVR", it->selectRule); + switch(it->type) + { + case VT_Int: esm.writeHNT("INTV", it->i); break; + case VT_Float: esm.writeHNT("FLTV", it->f); break; + default: break; + } + } + + if (!resultScript.empty()) + esm.writeHNString("BNAM", resultScript); + + switch(questStatus) + { + case QS_Name: esm.writeHNT("QSTN",'\1'); break; + case QS_Finished: esm.writeHNT("QSTF", '\1'); break; + case QS_Restart: esm.writeHNT("QSTR", '\1'); break; + case QS_Deleted: esm.writeHNT("DELE", '\1'); break; + default: break; + } +} + } diff --git a/components/esm/loadinfo.hpp b/components/esm/loadinfo.hpp index c47af341e..6f2d5ab25 100644 --- a/components/esm/loadinfo.hpp +++ b/components/esm/loadinfo.hpp @@ -2,6 +2,7 @@ #define _ESM_INFO_H #include "esm_reader.hpp" +#include "esm_writer.hpp" #include "defs.hpp" namespace ESM @@ -98,6 +99,7 @@ struct DialInfo }; void load(ESMReader &esm); + void save(ESMWriter &esm); }; /* diff --git a/components/esm/loadingr.cpp b/components/esm/loadingr.cpp index 471f71780..b71f6f13d 100644 --- a/components/esm/loadingr.cpp +++ b/components/esm/loadingr.cpp @@ -11,5 +11,15 @@ void Ingredient::load(ESMReader &esm) script = esm.getHNOString("SCRI"); icon = esm.getHNOString("ITEX"); } +void Ingredient::save(ESMWriter &esm) +{ + esm.writeHNString("MODL", model); + esm.writeHNString("FNAM", name); + esm.writeHNT("IRDT", data, 56); + if (!script.empty()) + esm.writeHNString("SCRI", script); + if (!icon.empty()) + esm.writeHNString("ITEX", script); +} } diff --git a/components/esm/loadingr.hpp b/components/esm/loadingr.hpp index af9599ed0..040118bbf 100644 --- a/components/esm/loadingr.hpp +++ b/components/esm/loadingr.hpp @@ -2,6 +2,7 @@ #define _ESM_INGR_H #include "esm_reader.hpp" +#include "esm_writer.hpp" namespace ESM { @@ -25,6 +26,7 @@ struct Ingredient std::string name, model, icon, script; void load(ESMReader &esm); + void save(ESMWriter &esm); }; } #endif diff --git a/components/esm/loadland.cpp b/components/esm/loadland.cpp index 96afdf831..4d3a4a0ed 100644 --- a/components/esm/loadland.cpp +++ b/components/esm/loadland.cpp @@ -3,6 +3,17 @@ namespace ESM { +void Land::LandData::save(ESMWriter &esm) +{ + // TODO: Make this actually work. + + //esm.writeHNT("VNML", normals, sizeof(VNML)); + esm.writeHNT("VHGT", heights, sizeof(VHGT)); + esm.writeHNT("WNAM", 0, 81); + esm.writeHNT("VCLR", colours, 3*LAND_NUM_VERTS); + esm.writeHNT("VTEX", textures, 512); +} + Land::Land() : flags(0) , X(0) @@ -71,6 +82,21 @@ void Land::load(ESMReader &esm) landData = NULL; } +void Land::save(ESMWriter &esm) +{ + esm.writeHString("INTV"); + esm.writeT(X); + esm.writeT(Y); + + esm.writeHNT("DATA", flags); + + if (hasData && !dataLoaded) + loadData(); // I think it might be a good idea to have + // the data loaded before trying to save it + if (dataLoaded) + landData->save(esm); +} + void Land::loadData() { if (dataLoaded) diff --git a/components/esm/loadland.hpp b/components/esm/loadland.hpp index ebc314a28..ba506b63b 100644 --- a/components/esm/loadland.hpp +++ b/components/esm/loadland.hpp @@ -2,6 +2,7 @@ #define _ESM_LAND_H #include "esm_reader.hpp" +#include "esm_writer.hpp" namespace ESM { @@ -65,11 +66,14 @@ struct Land bool usingColours; char colours[3 * LAND_NUM_VERTS]; + + void save(ESMWriter &esm); }; LandData *landData; void load(ESMReader &esm); + void save(ESMWriter &esm); /** * Actually loads data diff --git a/components/esm/loadlevlist.cpp b/components/esm/loadlevlist.cpp index d1bff7972..811964775 100644 --- a/components/esm/loadlevlist.cpp +++ b/components/esm/loadlevlist.cpp @@ -30,5 +30,17 @@ void LeveledListBase::load(ESMReader &esm) esm.getHNT(li.level, "INTV"); } } +void LeveledListBase::save(ESMWriter &esm) +{ + esm.writeHNT("DATA", flags); + esm.writeHNT("NNAM", chanceNone); + esm.writeHNT("INDX", list.size()); + + for (std::vector::iterator it = list.begin(); it != list.end(); ++it) + { + esm.writeHNString("INAM", it->id); + esm.writeHNT("INTV", it->level); + } +} } diff --git a/components/esm/loadlevlist.hpp b/components/esm/loadlevlist.hpp index 4affce539..ff20ce9d1 100644 --- a/components/esm/loadlevlist.hpp +++ b/components/esm/loadlevlist.hpp @@ -2,6 +2,7 @@ #define _ESM_LEVLISTS_H #include "esm_reader.hpp" +#include "esm_writer.hpp" namespace ESM { @@ -43,6 +44,7 @@ struct LeveledListBase std::vector list; void load(ESMReader &esm); + void save(ESMWriter &esm); }; struct CreatureLevList: LeveledListBase diff --git a/components/esm/loadligh.cpp b/components/esm/loadligh.cpp index 721a818f7..b7530eb6c 100644 --- a/components/esm/loadligh.cpp +++ b/components/esm/loadligh.cpp @@ -13,5 +13,18 @@ void Light::load(ESMReader &esm) script = esm.getHNOString("SCRI"); sound = esm.getHNOString("SNAM"); } +void Light::save(ESMWriter &esm) +{ + esm.writeHNString("MODL", model); + if (!name.empty()) + esm.writeHNString("FNAM", name); + if (!icon.empty()) + esm.writeHNString("ITEX", icon); + esm.writeHNT("LHDT", data, 24); + if (!script.empty()) + esm.writeHNString("SCRI", script); + if (!sound.empty()) + esm.writeHNString("SNAM", sound); +} } diff --git a/components/esm/loadligh.hpp b/components/esm/loadligh.hpp index 178258a05..aecd8b99b 100644 --- a/components/esm/loadligh.hpp +++ b/components/esm/loadligh.hpp @@ -2,6 +2,7 @@ #define _ESM_LIGH_H #include "esm_reader.hpp" +#include "esm_writer.hpp" namespace ESM { @@ -41,6 +42,7 @@ struct Light std::string sound, script, model, icon, name; void load(ESMReader &esm); + void save(ESMWriter &esm); }; } #endif diff --git a/components/esm/loadlocks.cpp b/components/esm/loadlocks.cpp index 79e882d94..b9f1d35ca 100644 --- a/components/esm/loadlocks.cpp +++ b/components/esm/loadlocks.cpp @@ -17,14 +17,38 @@ void Tool::load(ESMReader &esm) if (n == "RIDT") { + type = Type_Repair; // Swap t.data.quality and t.data.uses for repair items (sigh) float tmp = *((float*) &data.uses); data.uses = *((int*) &data.quality); data.quality = tmp; } + else if (n == "LKDT") + type = Type_Pick; + else if (n == "PBDT") + type = Type_Probe; script = esm.getHNOString("SCRI"); icon = esm.getHNOString("ITEX"); } +void Tool::save(ESMWriter &esm) +{ + esm.writeHNString("MODL", model); + esm.writeHNString("FNAM", name); + + switch(type) + { + case Type_Repair: esm.writeHString("RIDT"); break; + case Type_Pick: esm.writeHString("LKDT"); break; + case Type_Probe: esm.writeHString("PBDT"); break; + } + + esm.writeT(data, 16); + if (!script.empty()) + esm.writeHNString("SCRI", script); + if (!icon.empty()) + esm.writeHNString("ITEX", icon); +} + } diff --git a/components/esm/loadlocks.hpp b/components/esm/loadlocks.hpp index a1e537a4c..1c2a709f1 100644 --- a/components/esm/loadlocks.hpp +++ b/components/esm/loadlocks.hpp @@ -2,6 +2,7 @@ #define _ESM_LOCKS_H #include "esm_reader.hpp" +#include "esm_writer.hpp" namespace ESM { @@ -13,6 +14,13 @@ namespace ESM struct Tool { + enum Type + { + Type_Pick, + Type_Probe, + Type_Repair + }; + struct Data { float weight; @@ -25,9 +33,11 @@ struct Tool }; // Size = 16 Data data; + Type type; std::string name, model, icon, script; void load(ESMReader &esm); + void save(ESMWriter &esm); }; struct Probe: Tool diff --git a/components/esm/loadltex.cpp b/components/esm/loadltex.cpp index 08b1cf6dc..b4820d9ec 100644 --- a/components/esm/loadltex.cpp +++ b/components/esm/loadltex.cpp @@ -8,5 +8,10 @@ void LandTexture::load(ESMReader &esm) esm.getHNT(index, "INTV"); texture = esm.getHNString("DATA"); } +void LandTexture::save(ESMWriter &esm) +{ + esm.writeHNT("INTV", index); + esm.writeHNString("DATA", texture); +} } diff --git a/components/esm/loadltex.hpp b/components/esm/loadltex.hpp index fa4cac10a..d171c8e11 100644 --- a/components/esm/loadltex.hpp +++ b/components/esm/loadltex.hpp @@ -2,6 +2,7 @@ #define _ESM_LTEX_H #include "esm_reader.hpp" +#include "esm_writer.hpp" namespace ESM { @@ -28,6 +29,7 @@ struct LandTexture int index; void load(ESMReader &esm); + void save(ESMWriter &esm); }; } #endif diff --git a/components/esm/loadmgef.cpp b/components/esm/loadmgef.cpp index 2eda67b61..8de37f065 100644 --- a/components/esm/loadmgef.cpp +++ b/components/esm/loadmgef.cpp @@ -23,5 +23,24 @@ void MagicEffect::load(ESMReader &esm) description = esm.getHNOString("DESC"); } +void MagicEffect::save(ESMWriter &esm) +{ + esm.writeHNT("INDX", index); + esm.writeHNT("MEDT", data, 36); + + esm.writeHNOString("ITEX", icon); + esm.writeHNOString("PTEX", particle); + esm.writeHNOString("BSND", boltSound); + esm.writeHNOString("CSND", castSound); + esm.writeHNOString("HSND", hitSound); + esm.writeHNOString("ASND", areaSound); + + esm.writeHNOString("CVFX", casting); + esm.writeHNOString("BVFX", bolt); + esm.writeHNOString("HVFX", hit); + esm.writeHNOString("AVFX", area); + + esm.writeHNOString("DESC", description); +} } diff --git a/components/esm/loadmgef.hpp b/components/esm/loadmgef.hpp index b0b330aeb..ed0b03d0b 100644 --- a/components/esm/loadmgef.hpp +++ b/components/esm/loadmgef.hpp @@ -2,6 +2,7 @@ #define _ESM_MGEF_H #include "esm_reader.hpp" +#include "esm_writer.hpp" namespace ESM { @@ -46,6 +47,7 @@ struct MagicEffect int index; void load(ESMReader &esm); + void save(ESMWriter &esm); }; } #endif diff --git a/components/esm/loadmisc.cpp b/components/esm/loadmisc.cpp index 0206661c4..cf5cf92ae 100644 --- a/components/esm/loadmisc.cpp +++ b/components/esm/loadmisc.cpp @@ -11,5 +11,13 @@ void Miscellaneous::load(ESMReader &esm) script = esm.getHNOString("SCRI"); icon = esm.getHNOString("ITEX"); } +void Miscellaneous::save(ESMWriter &esm) +{ + esm.writeHNString("MODL", model); + esm.writeHNOString("FNAM", name); + esm.writeHNT("MCDT", data, 12); + esm.writeHNOString("SCRI", script); + esm.writeHNOString("ITEX", icon); +} } diff --git a/components/esm/loadmisc.hpp b/components/esm/loadmisc.hpp index 7e151f797..9aaa3c1be 100644 --- a/components/esm/loadmisc.hpp +++ b/components/esm/loadmisc.hpp @@ -2,6 +2,7 @@ #define _ESM_MISC_H #include "esm_reader.hpp" +#include "esm_writer.hpp" namespace ESM { @@ -26,6 +27,7 @@ struct Miscellaneous std::string name, model, icon, script; void load(ESMReader &esm); + void save(ESMWriter &esm); }; } #endif diff --git a/components/esm/loadnpc.cpp b/components/esm/loadnpc.cpp index 5b0e90c84..6cb6b64c7 100644 --- a/components/esm/loadnpc.cpp +++ b/components/esm/loadnpc.cpp @@ -23,9 +23,15 @@ void NPC::load(ESMReader &esm, const std::string& id) esm.getSubNameIs("NPDT"); esm.getSubHeader(); if (esm.getSubSize() == 52) + { + npdtType = 52; esm.getExact(&npdt52, 52); + } else if (esm.getSubSize() == 12) + { + npdtType = 12; esm.getExact(&npdt12, 12); + } else esm.fail("NPC_NPDT must be 12 or 52 bytes long"); @@ -44,5 +50,29 @@ void NPC::load(ESMReader &esm, const std::string& id) esm.skipRecord(); } +void NPC::save(ESMWriter &esm) +{ + esm.writeHNOString("MODL", model); + esm.writeHNOString("FNAM", name); + esm.writeHNString("RNAM", race); + esm.writeHNString("CNAM", cls); + esm.writeHNString("ANAM", faction); + esm.writeHNString("BNAM", head); + esm.writeHNString("KNAM", hair); + esm.writeHNOString("SCRI", script); + + if (npdtType == 52) + esm.writeHNT("NPDT", npdt52, 52); + else if (npdtType == 12) + esm.writeHNT("NPDT", npdt12, 12); + + esm.writeHNT("FLAG", flags); + + inventory.save(esm); + spells.save(esm); + + if (hasAI) + esm.writeHNT("AIDT", AI); +} } diff --git a/components/esm/loadnpc.hpp b/components/esm/loadnpc.hpp index 62a99e763..3e094a197 100644 --- a/components/esm/loadnpc.hpp +++ b/components/esm/loadnpc.hpp @@ -2,6 +2,7 @@ #define _ESM_NPC_H #include "esm_reader.hpp" +#include "esm_writer.hpp" #include "loadcont.hpp" #include "defs.hpp" @@ -83,6 +84,7 @@ struct NPC #pragma pack(pop) + char npdtType; NPDTstruct52 npdt52; NPDTstruct12 npdt12; // Use this if npdt52.gold == -10 @@ -101,6 +103,7 @@ struct NPC // Implementation moved to load_impl.cpp void load(ESMReader &esm, const std::string& id); + void save(ESMWriter &esm); }; } #endif diff --git a/components/esm/loadnpcc.hpp b/components/esm/loadnpcc.hpp index 592d5b57f..a65f6a6b3 100644 --- a/components/esm/loadnpcc.hpp +++ b/components/esm/loadnpcc.hpp @@ -2,6 +2,7 @@ #define _ESM_NPCC_H #include "esm_reader.hpp" +#include "esm_writer.hpp" namespace ESM { @@ -76,6 +77,9 @@ struct LoadNPCC { esm.skipRecord(); } + void save(ESMWriter &esm) + { + } }; } #endif diff --git a/components/esm/loadpgrd.cpp b/components/esm/loadpgrd.cpp index dc63ce335..572378dad 100644 --- a/components/esm/loadpgrd.cpp +++ b/components/esm/loadpgrd.cpp @@ -67,5 +67,28 @@ void Pathgrid::load(ESMReader &esm) } } } +void Pathgrid::save(ESMWriter &esm) +{ + esm.writeHNT("DATA", data, 12); + esm.writeHNString("NAME", cell); + + if (!points.empty()) + { + esm.writeHString("PGRP"); + for (PointList::iterator it = points.begin(); it != points.end(); ++it) + { + esm.writeT(*it); + } + } + + if (!edges.empty()) + { + esm.writeHString("PGRC"); + for (std::vector::iterator it = edges.begin(); it != edges.end(); ++it) + { + esm.writeT(it->v1); + } + } +} } diff --git a/components/esm/loadpgrd.hpp b/components/esm/loadpgrd.hpp index 6e2c6e134..ec339240f 100644 --- a/components/esm/loadpgrd.hpp +++ b/components/esm/loadpgrd.hpp @@ -2,6 +2,7 @@ #define _ESM_PGRD_H #include "esm_reader.hpp" +#include "esm_writer.hpp" namespace ESM { @@ -42,6 +43,7 @@ struct Pathgrid EdgeList edges; void load(ESMReader &esm); + void save(ESMWriter &esm); }; } #endif diff --git a/components/esm/loadrace.cpp b/components/esm/loadrace.cpp index ce64f5f72..04752add1 100644 --- a/components/esm/loadrace.cpp +++ b/components/esm/loadrace.cpp @@ -10,5 +10,12 @@ void Race::load(ESMReader &esm) powers.load(esm); description = esm.getHNOString("DESC"); } +void Race::save(ESMWriter &esm) +{ + esm.writeHNString("FNAM", name); + esm.writeHNT("RADT", data, 140); + powers.save(esm); + esm.writeHNOString("DESC", description); +} } diff --git a/components/esm/loadrace.hpp b/components/esm/loadrace.hpp index d4506dbef..15fa43984 100644 --- a/components/esm/loadrace.hpp +++ b/components/esm/loadrace.hpp @@ -2,6 +2,7 @@ #define _ESM_RACE_H #include "esm_reader.hpp" +#include "esm_writer.hpp" #include "defs.hpp" namespace ESM @@ -58,6 +59,7 @@ struct Race SpellList powers; void load(ESMReader &esm); + void save(ESMWriter &esm); }; } #endif diff --git a/components/esm/loadregn.cpp b/components/esm/loadregn.cpp index f31c9a827..d67922b4d 100644 --- a/components/esm/loadregn.cpp +++ b/components/esm/loadregn.cpp @@ -25,5 +25,19 @@ void Region::load(ESMReader &esm) soundList.push_back(sr); } } +void Region::save(ESMWriter &esm) +{ + esm.writeHNString("FNAM", name); + + esm.writeHNT("WEAT", data); + + esm.writeHNOString("BNAM", sleepList); + + esm.writeHNT("CNAM", mapColor); + for (std::vector::iterator it = soundList.begin(); it != soundList.end(); ++it) + { + esm.writeHNT("SNAM", *it); + } +} } diff --git a/components/esm/loadregn.hpp b/components/esm/loadregn.hpp index 1748b3d28..81b8bc51d 100644 --- a/components/esm/loadregn.hpp +++ b/components/esm/loadregn.hpp @@ -2,6 +2,7 @@ #define _ESM_REGN_H #include "esm_reader.hpp" +#include "esm_writer.hpp" namespace ESM { @@ -41,6 +42,7 @@ struct Region std::vector soundList; void load(ESMReader &esm); + void save(ESMWriter &esm); }; } #endif diff --git a/components/esm/loadscpt.cpp b/components/esm/loadscpt.cpp index 9c0176725..86d1d8e29 100644 --- a/components/esm/loadscpt.cpp +++ b/components/esm/loadscpt.cpp @@ -38,5 +38,21 @@ void Script::load(ESMReader &esm) // Script text scriptText = esm.getHNOString("SCTX"); } +void Script::save(ESMWriter &esm) +{ + esm.writeHNT("SCHD", data, 52); + + if (!varNames.empty()) + { + esm.writeHString("SCVR"); + for (std::vector::iterator it = varNames.begin(); it != varNames.end(); ++it) + { + esm.writeT(it->c_str(), it->size()); + } + } + + esm.writeHNT("SCDT", &scriptData[0], scriptData.size()); + esm.writeHNOString("SCDT", scriptText); +} } diff --git a/components/esm/loadscpt.hpp b/components/esm/loadscpt.hpp index 3ce3d9636..55cfb053a 100644 --- a/components/esm/loadscpt.hpp +++ b/components/esm/loadscpt.hpp @@ -2,6 +2,7 @@ #define _ESM_SCPT_H #include "esm_reader.hpp" +#include "esm_writer.hpp" namespace ESM { @@ -50,6 +51,7 @@ public: std::string scriptText; // Uncompiled script void load(ESMReader &esm); + void save(ESMWriter &esm); }; } #endif diff --git a/components/esm/loadskil.cpp b/components/esm/loadskil.cpp index aa7103efc..adce2f361 100644 --- a/components/esm/loadskil.cpp +++ b/components/esm/loadskil.cpp @@ -67,4 +67,10 @@ void Skill::load(ESMReader &esm) esm.getHNT(data, "SKDT", 24); description = esm.getHNOString("DESC"); } +void Skill::save(ESMWriter &esm) +{ + esm.writeHNT("INDX", index); + esm.writeHNT("SKDT", data, 24); + esm.writeHNOString("DESC", description); +} } diff --git a/components/esm/loadskil.hpp b/components/esm/loadskil.hpp index 836f70205..8cc90b063 100644 --- a/components/esm/loadskil.hpp +++ b/components/esm/loadskil.hpp @@ -4,6 +4,7 @@ #include #include "esm_reader.hpp" +#include "esm_writer.hpp" #include "defs.hpp" namespace ESM { @@ -67,6 +68,7 @@ struct Skill static const boost::array skillIds; void load(ESMReader &esm); + void save(ESMWriter &esm); }; } #endif diff --git a/components/esm/loadsndg.cpp b/components/esm/loadsndg.cpp index b7b568132..10f010f48 100644 --- a/components/esm/loadsndg.cpp +++ b/components/esm/loadsndg.cpp @@ -10,5 +10,11 @@ void SoundGenerator::load(ESMReader &esm) creature = esm.getHNOString("CNAM"); sound = esm.getHNOString("SNAM"); } +void SoundGenerator::save(ESMWriter &esm) +{ + esm.writeHNT("DATA", type, 4); + esm.writeHNOString("CNAM", creature); + esm.writeHNOString("SNAM", sound); +} } diff --git a/components/esm/loadsndg.hpp b/components/esm/loadsndg.hpp index 2953369c4..e9e20c212 100644 --- a/components/esm/loadsndg.hpp +++ b/components/esm/loadsndg.hpp @@ -2,6 +2,7 @@ #define _ESM_SNDG_H #include "esm_reader.hpp" +#include "esm_writer.hpp" namespace ESM { @@ -30,6 +31,7 @@ struct SoundGenerator std::string creature, sound; void load(ESMReader &esm); + void save(ESMWriter &esm); }; } #endif diff --git a/components/esm/loadsoun.cpp b/components/esm/loadsoun.cpp index cd47f0f17..a160f3d1c 100644 --- a/components/esm/loadsoun.cpp +++ b/components/esm/loadsoun.cpp @@ -14,5 +14,10 @@ void Sound::load(ESMReader &esm) << endl; */ } +void Sound::save(ESMWriter &esm) +{ + esm.writeHNString("FNAM", sound); + esm.writeHNT("DATA", data, 3); +} } diff --git a/components/esm/loadsoun.hpp b/components/esm/loadsoun.hpp index 775a664be..9f0bdf509 100644 --- a/components/esm/loadsoun.hpp +++ b/components/esm/loadsoun.hpp @@ -2,6 +2,7 @@ #define _ESM_SOUN_H #include "esm_reader.hpp" +#include "esm_writer.hpp" namespace ESM { @@ -17,6 +18,7 @@ struct Sound std::string sound; void load(ESMReader &esm); + void save(ESMWriter &esm); }; } #endif diff --git a/components/esm/loadspel.cpp b/components/esm/loadspel.cpp index c3c928ce6..a87dfb620 100644 --- a/components/esm/loadspel.cpp +++ b/components/esm/loadspel.cpp @@ -9,5 +9,11 @@ void Spell::load(ESMReader &esm) esm.getHNT(data, "SPDT", 12); effects.load(esm); } +void Spell::save(ESMWriter &esm) +{ + esm.writeHNOString("FNAM", name); + esm.writeHNT("SPDT", data, 12); + effects.save(esm); +} } diff --git a/components/esm/loadspel.hpp b/components/esm/loadspel.hpp index c97d037cd..971bf23a4 100644 --- a/components/esm/loadspel.hpp +++ b/components/esm/loadspel.hpp @@ -2,6 +2,7 @@ #define _ESM_SPEL_H #include "esm_reader.hpp" +#include "esm_writer.hpp" #include "defs.hpp" namespace ESM @@ -38,6 +39,7 @@ struct Spell EffectList effects; void load(ESMReader &esm); + void save(ESMWriter &esm); }; } #endif diff --git a/components/esm/loadsscr.cpp b/components/esm/loadsscr.cpp index f4e79271c..f1099e67b 100644 --- a/components/esm/loadsscr.cpp +++ b/components/esm/loadsscr.cpp @@ -9,5 +9,10 @@ void StartScript::load(ESMReader &esm) esm.skipHSub(); script = esm.getHNString("NAME"); } +void StartScript::save(ESMWriter &esm) +{ + esm.writeHNString("DATA", "NIET"); + esm.writeHNString("NAME", script); +} } diff --git a/components/esm/loadsscr.hpp b/components/esm/loadsscr.hpp index d18bde101..2cc7eccf9 100644 --- a/components/esm/loadsscr.hpp +++ b/components/esm/loadsscr.hpp @@ -2,6 +2,7 @@ #define _ESM_SSCR_H #include "esm_reader.hpp" +#include "esm_writer.hpp" namespace ESM { @@ -20,6 +21,7 @@ struct StartScript // Load a record and add it to the list void load(ESMReader &esm); + void save(ESMWriter &esm); }; } diff --git a/components/esm/loadstat.cpp b/components/esm/loadstat.cpp index 654bf290a..2252e9b03 100644 --- a/components/esm/loadstat.cpp +++ b/components/esm/loadstat.cpp @@ -7,5 +7,9 @@ void Static::load(ESMReader &esm) { model = esm.getHNString("MODL"); } +void Static::save(ESMWriter &esm) +{ + esm.writeHNString("MODL", model); +} } diff --git a/components/esm/loadstat.hpp b/components/esm/loadstat.hpp index 4f3121d18..a5b82c46d 100644 --- a/components/esm/loadstat.hpp +++ b/components/esm/loadstat.hpp @@ -2,6 +2,7 @@ #define _ESM_STAT_H #include "esm_reader.hpp" +#include "esm_writer.hpp" namespace ESM { @@ -22,6 +23,7 @@ struct Static std::string model; void load(ESMReader &esm); + void save(ESMWriter &esm); }; } #endif diff --git a/components/esm/loadweap.cpp b/components/esm/loadweap.cpp index 1910631bc..6cc7fa02d 100644 --- a/components/esm/loadweap.cpp +++ b/components/esm/loadweap.cpp @@ -12,5 +12,14 @@ void Weapon::load(ESMReader &esm) icon = esm.getHNOString("ITEX"); enchant = esm.getHNOString("ENAM"); } +void Weapon::save(ESMWriter &esm) +{ + esm.writeHNString("MODL", model); + esm.writeHNOString("FNAM", name); + esm.writeHNT("WPDT", data, 32); + esm.writeHNOString("SCRI", script); + esm.writeHNOString("ITEX", icon); + esm.writeHNOString("ENAM", enchant); +} } diff --git a/components/esm/loadweap.hpp b/components/esm/loadweap.hpp index 8bd3b147c..8e7947bf3 100644 --- a/components/esm/loadweap.hpp +++ b/components/esm/loadweap.hpp @@ -2,6 +2,7 @@ #define _ESM_WEAP_H #include "esm_reader.hpp" +#include "esm_writer.hpp" namespace ESM { @@ -56,6 +57,7 @@ struct Weapon std::string name, model, icon, enchant, script; void load(ESMReader &esm); + void save(ESMWriter &esm); }; } #endif