1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-30 07:15:34 +00:00

Adding basic save functions to all record types.

This commit is contained in:
Alexander "Ace" Olofsson 2012-04-06 21:04:30 +02:00
parent 8bf9b371c7
commit ba602929ef
86 changed files with 894 additions and 96 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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