Adding basic save functions to all record types.

pull/37/head
Alexander "Ace" Olofsson 13 years ago
parent 8bf9b371c7
commit ba602929ef

@ -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

@ -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<std::string>::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<ENAMstruct>::iterator it = list.begin(); it != list.end(); ++it)
{
esm.writeHNT<ENAMstruct>("ENAM", *it, 24);
}
}
};
}

@ -0,0 +1,102 @@
#ifndef _ESM_COMMON_H
#define _ESM_COMMON_H
#include <libs/platform/stdint.h>
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 <int LEN>
union NAME_T
{
char name[LEN];
int32_t val;
bool operator==(const char *str)
{
for(int i=0; i<LEN; i++)
if(name[i] != str[i]) return false;
else if(name[i] == 0) return true;
return str[LEN] == 0;
}
bool operator!=(const char *str) { return !((*this)==str); }
bool operator==(const std::string &str)
{
return (*this) == str.c_str();
}
bool operator!=(const std::string &str) { return !((*this)==str); }
bool operator==(int v) { return v == val; }
bool operator!=(int v) { return v != val; }
std::string toString() const { return std::string(name, strnlen(name, LEN)); }
};
typedef NAME_T<4> 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

@ -16,103 +16,9 @@
#include <components/misc/stringops.hpp>
#include <components/to_utf8/to_utf8.hpp>
#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 <int LEN>
union NAME_T
{
char name[LEN];
int32_t val;
bool operator==(const char *str)
{
for(int i=0; i<LEN; i++)
if(name[i] != str[i]) return false;
else if(name[i] == 0) return true;
return str[LEN] == 0;
}
bool operator!=(const char *str) { return !((*this)==str); }
bool operator==(const std::string &str)
{
return (*this) == str.c_str();
}
bool operator!=(const std::string &str) { return !((*this)==str); }
bool operator==(int v) { return v == val; }
bool operator!=(int v) { return v != val; }
std::string toString() const { return std::string(name, strnlen(name, LEN)); }
};
typedef NAME_T<4> 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

@ -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<int>(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);
}
}

@ -0,0 +1,71 @@
#ifndef _ESM_WRITER_H
#define _ESM_WRITER_H
#include <iostream>
#include <assert.h>
#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<typename T>
void writeHNT(const std::string& name, const T& data)
{
writeName(name);
writeT(data);
}
template<typename T>
void writeHNT(const std::string& name, const T& data, int size)
{
assert(sizeof(T) == size);
writeHNT(name, data);
}
template<typename T>
void writeHT(const T& data)
{
writeT((unsigned int)sizeof(T));
writeT(data);
}
template<typename T>
void writeHT(const T& data, int size)
{
assert(sizeof(T) == size);
writeHT(data);
}
template<typename T>
void writeT(const T& data)
{
write((char*)&data, sizeof(T));
}
template<typename T>
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

@ -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);
}
}
}

@ -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

@ -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);
}
}

@ -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

@ -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);
}
}

@ -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

@ -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<PartReference>::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);
}
}

@ -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<PartReference> 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

@ -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);
}
}

@ -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

@ -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);
}
}

@ -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

@ -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);
}
}

@ -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

@ -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);

@ -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
{

@ -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);
}
}

@ -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

@ -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);
}
}

@ -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

@ -13,6 +13,14 @@ void InventoryList::load(ESMReader &esm)
}
}
void InventoryList::save(ESMWriter &esm)
{
for (std::vector<ContItem>::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);
}
}

@ -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<ContItem> 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

@ -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);
}
}

@ -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

@ -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

@ -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);
}
}
}

@ -4,6 +4,7 @@
#include <vector>
#include "esm_reader.hpp"
#include "esm_writer.hpp"
#include "loadinfo.hpp"
namespace ESM
@ -30,6 +31,7 @@ struct Dialogue
std::vector<DialInfo> mInfo;
void load(ESMReader &esm);
void save(ESMWriter &esm);
};
}
#endif

@ -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);
}
}

@ -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

@ -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);
}
}

@ -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

@ -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<Reaction>::iterator it = reactions.begin(); it != reactions.end(); ++it)
{
esm.writeHNString("ANAM", it->faction);
esm.writeHNT("INTV", it->reaction);
}
}
}

@ -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

@ -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);
}
}

@ -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

@ -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;
}
}
}

@ -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

@ -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<SelectStruct>::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;
}
}
}

@ -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);
};
/*

@ -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);
}
}

@ -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

@ -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)

@ -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

@ -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<int>("INDX", list.size());
for (std::vector<LevelItem>::iterator it = list.begin(); it != list.end(); ++it)
{
esm.writeHNString("INAM", it->id);
esm.writeHNT("INTV", it->level);
}
}
}

@ -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<LevelItem> list;
void load(ESMReader &esm);
void save(ESMWriter &esm);
};
struct CreatureLevList: LeveledListBase

@ -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);
}
}

@ -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

@ -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);
}
}

@ -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

@ -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);
}
}

@ -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

@ -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);
}
}

@ -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

@ -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);
}
}

@ -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

@ -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);
}
}

@ -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

@ -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

@ -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<Edge>::iterator it = edges.begin(); it != edges.end(); ++it)
{
esm.writeT(it->v1);
}
}
}
}

@ -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

@ -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);
}
}

@ -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

@ -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<SoundRef>::iterator it = soundList.begin(); it != soundList.end(); ++it)
{
esm.writeHNT<SoundRef>("SNAM", *it);
}
}
}

@ -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<SoundRef> soundList;
void load(ESMReader &esm);
void save(ESMWriter &esm);
};
}
#endif

@ -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<std::string>::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);
}
}

@ -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

@ -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);
}
}

@ -4,6 +4,7 @@
#include <boost/array.hpp>
#include "esm_reader.hpp"
#include "esm_writer.hpp"
#include "defs.hpp"
namespace ESM {
@ -67,6 +68,7 @@ struct Skill
static const boost::array<SkillEnum, Length> skillIds;
void load(ESMReader &esm);
void save(ESMWriter &esm);
};
}
#endif

@ -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);
}
}

@ -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

@ -14,5 +14,10 @@ void Sound::load(ESMReader &esm)
<< endl;
*/
}
void Sound::save(ESMWriter &esm)
{
esm.writeHNString("FNAM", sound);
esm.writeHNT("DATA", data, 3);
}
}

@ -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

@ -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);
}
}

@ -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

@ -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);
}
}

@ -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);
};
}

@ -7,5 +7,9 @@ void Static::load(ESMReader &esm)
{
model = esm.getHNString("MODL");
}
void Static::save(ESMWriter &esm)
{
esm.writeHNString("MODL", model);
}
}

@ -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

@ -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);
}
}

@ -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

Loading…
Cancel
Save