diff --git a/esm/esm_reader.hpp b/esm/esm_reader.hpp index 7ab313e6d..62bc538f9 100644 --- a/esm/esm_reader.hpp +++ b/esm/esm_reader.hpp @@ -391,7 +391,7 @@ public: fail("skipHSubSize() mismatch"); } - /* Sub-record head This updates leftRec beyond the current + /* Sub-record header. This updates leftRec beyond the current sub-record as well. leftSub contains size of current sub-record. */ void getSubHeader() @@ -410,6 +410,14 @@ public: fail("Not enough bytes left in record for this subrecord."); } + /** Get sub header and check the size + */ + void getSubHeaderIs(int size) + { + getSubHeader(); + if(size != leftSub) + fail("getSubHeaderIs(): Sub header mismatch"); + } /************************************************************************* * diff --git a/esm/loadclas.hpp b/esm/loadclas.hpp new file mode 100644 index 000000000..93df3fea6 --- /dev/null +++ b/esm/loadclas.hpp @@ -0,0 +1,64 @@ +#ifndef _ESM_CLAS_H +#define _ESM_CLAS_H + +#include "esm_reader.hpp" + +namespace ESM { + +/* + * Character class definitions + */ + +// These flags tells us which items should be auto-calculated for this +// class +struct Class +{ + enum AutoCalc + { + Weapon = 0x00001, + Armor = 0x00002, + Clothing = 0x00004, + Books = 0x00008, + Ingredient = 0x00010, + Lockpick = 0x00020, + Probe = 0x00040, + Lights = 0x00080, + Apparatus = 0x00100, + Repair = 0x00200, + Misc = 0x00400, + Spells = 0x00800, + MagicItems = 0x01000, + Potions = 0x02000, + Training = 0x04000, + Spellmaking = 0x08000, + Enchanting = 0x10000, + RepairItem = 0x20000 + }; + + struct CLDTstruct + { + int attribute[2]; // Attributes that get class bonus + int specialization; // 0 = Combat, 1 = Magic, 2 = Stealth + int skills[5][2]; // Minor and major skills. + int isPlayable; // 0x0001 - Playable class + + // I have no idea how to autocalculate these items... + int calc; + }; // 60 bytes + + std::string name, description; + CLDTstruct data; + + void load(ESMReader &esm) + { + name = esm.getHNString("FNAM"); + esm.getHNT(data, "CLDT", 60); + + if(data.isPlayable > 1) + esm.fail("Unknown bool value"); + + description = esm.getHNOString("DESC"); + } +}; +} +#endif diff --git a/esm/loadcont.hpp b/esm/loadcont.hpp new file mode 100644 index 000000000..0ebedf723 --- /dev/null +++ b/esm/loadcont.hpp @@ -0,0 +1,64 @@ +#ifndef _ESM_CONT_H +#define _ESM_CONT_H + +#include "esm_reader.hpp" + +namespace ESM { + +/* + * Container definition + */ + +struct ContItem +{ + int count; + NAME32 item; +}; + +struct InventoryList +{ + std::vector list; + + void load(ESMReader &esm) + { + ContItem ci; + while(esm.hasMoreSubs()) + { + esm.getHNT(ci, "NPCO", 36); + list.push_back(ci); + } + } +}; + +struct Container +{ + enum Flags + { + Organic = 1, // Objects cannot be placed in this container + Respawn = 2, // Respawns after 4 months + Unknown = 8 + }; + + std::string name, model, script; + + float weight; // Not sure, might be max total weight allowed? + int flags; + InventoryList inventory; + + void load(ESMReader &esm) + { + model = esm.getHNString("MODL"); + name = esm.getHNOString("FNAM"); + esm.getHNT(weight, "CNDT", 4); + esm.getHNT(flags, "FLAG", 4); + + if(flags & 0xf4) esm.fail("Unknown flags"); + if(!(flags & 0x8)) esm.fail("Flag 8 not set"); + + script = esm.getHNOString("SCRI"); + + inventory.load(esm); + } +}; +} +#endif diff --git a/esm/loadfact.hpp b/esm/loadfact.hpp new file mode 100644 index 000000000..3b56c2c17 --- /dev/null +++ b/esm/loadfact.hpp @@ -0,0 +1,78 @@ +#ifndef _ESM_FACT_H +#define _ESM_FACT_H + +#include "esm_reader.hpp" + +namespace ESM { + +/* + * Faction definitions + */ + +// Requirements for each rank +struct RankData +{ + int attribute1, attribute2; // Attribute level + + int skill1, skill2; // Skill level (faction skills given in + // skillID below.) You need one skill at + // level 'skill1' and two skills at level + // 'skill2' to advance to this rank. + + int factReaction; // Reaction from faction members +}; + +struct Faction +{ + std::string id, name; + + struct FADTstruct + { + // Which attributes we like + int attribute1, attribute2; + + RankData rankData[10]; + + int skillID[6]; // IDs of skills this faction require + int unknown; // Always -1? + int isHidden; // 1 - hidden from player + }; // 240 bytes + + FADTstruct data; + + struct Reaction + { + std::string faction; + int reaction; + }; + + std::vector reactions; + + // Name of faction ranks (may be empty for NPC factions) + std::string ranks[10]; + + void load(ESMReader &esm) + { + name = esm.getHNString("FNAM"); + + // Read rank names. These are optional. + int i = 0; + while(esm.isNextSub("RNAM") && i<10) ranks[i++] = esm.getHString(); + + // Main data struct + esm.getHNT(data, "FADT", 240); + + if(data.isHidden > 1) esm.fail("Unknown flag!"); + + // Read faction response values + while(esm.hasMoreSubs()) + { + Reaction r; + r.faction = esm.getHNString("ANAM"); + esm.getHNT(r.reaction, "INTV"); + reactions.push_back(r); + } + } +}; +} +#endif diff --git a/esm/loadlocks.hpp b/esm/loadlocks.hpp new file mode 100644 index 000000000..acd8a7805 --- /dev/null +++ b/esm/loadlocks.hpp @@ -0,0 +1,54 @@ +#ifndef _ESM_LOCKS_H +#define _ESM_LOCKS_H + +#include "esm_reader.hpp" + +namespace ESM { + +/* + * This file covers lockpicks (LOCK), probes (PROB) and armor repair + * items (REPA). These have nearly identical data structures. + */ + +struct Tool +{ + struct Data + { + float weight; + int value; + + float quality; // And when I say nearly identical structure, I + int uses; // mean perfectly identical except that these two + // variables are swaped for repair items. Don't ask + // me why. + }; // Size = 16 + + Data data; + std::string name, model, icon, script; + + void load(ESMReader &esm) + { + model = esm.getHNString("MODL"); + name = esm.getHNString("FNAM"); + + esm.getSubName(); + NAME n = esm.retSubName(); + // The data name varies, RIDT for repair items, LKDT for lock + // picks, PBDT for probes + + esm.getHT(data, 16); + + if(n == "RIDT") + { + // 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; + } + + script = esm.getHNOString("SCRI"); + icon = esm.getHNOString("ITEX"); + } +}; +} +#endif diff --git a/esm/loadweap.hpp b/esm/loadweap.hpp new file mode 100644 index 000000000..b0cbf97f3 --- /dev/null +++ b/esm/loadweap.hpp @@ -0,0 +1,68 @@ +#ifndef _ESM_WEAP_H +#define _ESM_WEAP_H + +#include "esm_reader.hpp" + +namespace ESM { + +/* + * Weapon definition + */ + +struct Weapon +{ + enum Type + { + ShortBladeOneHand = 0, + LongBladeOneHand = 1, + LongBladeTwoHand = 2, + BluntOneHand = 3, + BluntTwoClose = 4, + BluntTwoWide = 5, + SpearTwoWide = 6, + AxeOneHand = 7, + AxeTwoHand = 8, + MarksmanBow = 9, + MarksmanCrossbow = 10, + MarksmanThrown = 11, + Arrow = 12, + Bolt = 13 + }; + + enum Flags + { + Magical = 0x01, + Silver = 0x02 + }; + +#pragma pack(push) +#pragma pack(1) + struct WPDTstruct + { + float weight; + int value; + short type; + short health; + float speed, reach; + short enchant; // Enchantment points + unsigned char chop[2], slash[2], thrust[2]; // Min and max + int flags; + }; // 32 bytes +#pragma pack(pop) + + WPDTstruct data; + + std::string name, model, icon, enchant, script; + + void load(ESMReader &esm) + { + model = esm.getHNString("MODL"); + name = esm.getHNOString("FNAM"); + esm.getHNT(data, "WPDT", 32); + script = esm.getHNOString("SCRI"); + icon = esm.getHNOString("ITEX"); + enchant = esm.getHNOString("ENAM"); + } +}; +} +#endif diff --git a/esm/records.hpp b/esm/records.hpp index 17051e752..d7254a24d 100644 --- a/esm/records.hpp +++ b/esm/records.hpp @@ -8,13 +8,17 @@ #include "loadbody.hpp" #include "loadbook.hpp" #include "loadbsgn.hpp" +#include "loadclas.hpp" #include "loadclot.hpp" +#include "loadcont.hpp" #include "loadcrec.hpp" #include "loaddoor.hpp" #include "loadench.hpp" +#include "loadfact.hpp" #include "loadglob.hpp" #include "loadingr.hpp" #include "loadligh.hpp" +#include "loadlocks.hpp" #include "loadmisc.hpp" #include "loadrace.hpp" #include "loadskil.hpp" @@ -23,6 +27,7 @@ #include "loadspel.hpp" #include "loadsscr.hpp" #include "loadstat.hpp" +#include "loadweap.hpp" namespace ESM { diff --git a/old_d_version/esm/loadclas.d b/old_d_version/esm/loadclas.d deleted file mode 100644 index 5e2fe7749..000000000 --- a/old_d_version/esm/loadclas.d +++ /dev/null @@ -1,93 +0,0 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2008 Nicolay Korslund - Email: < korslund@gmail.com > - WWW: http://openmw.snaptoad.com/ - - This file (loadclas.d) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - - */ -module esm.loadclas; - -import esm.imports; - -import esm.loadskil; - -/* - * Character class definitions - */ - -// These flags tells us which items should be auto-calculated for this -// class -struct Class -{ - enum AutoCalc : uint - { - Weapon = 0x00001, - Armor = 0x00002, - Clothing = 0x00004, - Books = 0x00008, - Ingredient = 0x00010, - Lockpick = 0x00020, - Probe = 0x00040, - Lights = 0x00080, - Apparatus = 0x00100, - Repair = 0x00200, - Misc = 0x00400, - Spells = 0x00800, - MagicItems = 0x01000, - Potions = 0x02000, - Training = 0x04000, - Spellmaking = 0x08000, - Enchanting = 0x10000, - RepairItem = 0x20000 - } - - align(1) struct CLDTstruct - { - Attribute attribute[2]; // Attributes that get class bonus - - Specialization specialization; // 0 = Combat, 1 = Magic, 2 = Stealth - - SkillEnum[2][5] skills; // Minor and major skills. - - uint isPlayable; // 0x0001 - Playable class - - // I have no idea how to autocalculate these items... - AutoCalc calc; - - static assert(CLDTstruct.sizeof == 60); - } - - mixin LoadT; - - char[] description; - CLDTstruct data; - - void load() - { - name = esFile.getHNString("FNAM"); - esFile.readHNExact(&data, data.sizeof, "CLDT"); - - if(data.isPlayable > 1) - esFile.fail("Unknown bool value"); - - description = esFile.getHNOString("DESC"); - - // no makeProto yet - } -} -ListID!(Class) classes; diff --git a/old_d_version/esm/loadcont.d b/old_d_version/esm/loadcont.d deleted file mode 100644 index 84178eba3..000000000 --- a/old_d_version/esm/loadcont.d +++ /dev/null @@ -1,108 +0,0 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2008 Nicolay Korslund - Email: < korslund@gmail.com > - WWW: http://openmw.snaptoad.com/ - - This file (loadcont.d) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - - */ - -module esm.loadcont; -import esm.imports; - -/* - * Container definition - */ - -struct ContItem -{ - Item item; - int count; -} - -struct InventoryList -{ - RegionBuffer!(ContItem) list; - - private static char[32] buffer; - - void load() - { - list = esFile.getRegion().getBuffer!(ContItem)(0,10); - - while(esFile.isNextSub("NPCO")) - { - esFile.getSubHeaderIs(36); - list.length = list.length + 1; - - with(list.array[$-1]) - { - esFile.getInt(count); - - // String is automatically chopped - item = items.lookup(esFile.getString(buffer)); - } - } - } -} - -struct Container -{ - enum Flags - { - Organic = 1, // Objects cannot be placed in this container - Respawn = 2, // Respawns after 4 months - Unknown = 8 - } - - MeshIndex model; - Script *script; - - float weight; // Not sure, might be max total weight allowed? - Flags flags; - InventoryList inventory; - - mixin LoadT!(); - - void load() - {with(esFile){ - model = getMesh(); - name = getHNOString("FNAM"); - weight = getHNFloat("CNDT"); - flags = cast(Flags)getHNUint("FLAG"); - - if(flags & 0xf4) fail("Unknown flags"); - if(!(flags & 0x8)) fail("Flag 8 not set"); - - /* - if(getFileType == FileType.Savegame) - { - int tmp = getHNInt("INDX"); - if(tmp) writefln("WARNING, INDX != 0: ", tmp); - } - */ - - script = getHNOPtr!(Script)("SCRI", scripts); - - inventory.load(); - - makeProto(); - proto.setFloat("weight", weight); - }} -} - -ListID!(Container) containers; diff --git a/old_d_version/esm/loadfact.d b/old_d_version/esm/loadfact.d deleted file mode 100644 index d7a234b1e..000000000 --- a/old_d_version/esm/loadfact.d +++ /dev/null @@ -1,106 +0,0 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2008 Nicolay Korslund - Email: < korslund@gmail.com > - WWW: http://openmw.snaptoad.com/ - - This file (loadfact.d) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - - */ - -module esm.loadfact; - -import esm.imports; - -/* - * Faction definitions - */ - -// Requirements for each rank -align(1) struct RankData -{ - int attribute1, attribute2; // Attribute level - - int skill1, skill2; // Skill level (faction skills given in - // skillID below.) You need one skill at - // level 'skill1' and two skills at level - // 'skill2' to advance to this rank. - - int factReaction; // Reaction from faction members -} - -struct Faction -{ - char[] id, name; - LoadState state; - - align(1) struct FADTstruct - { - // Which attributes we like - int attribute1, attribute2; - - RankData rankData[10]; - - int skillID[6]; // IDs of skills this faction require - int unknown; // Always -1? - uint isHidden; // 1 - hidden from player - - static assert(RankData.sizeof == 20); - static assert(FADTstruct.sizeof == 240); - } - - FADTstruct data; - - RankData rankData[10]; - - struct Reaction - { - Faction* faction; - int reaction; - } - - RegionBuffer!(Reaction) reactions; - - char[] ranks[10]; // Name of faction ranks (may be empty for NPC - // factions) - void load() - {with(esFile){ - name = getHNString("FNAM"); - - // Read rank names. These are optional. - ranks[] = null; - int i = 0; - while(isNextSub("RNAM") && i<10) ranks[i++] = getHString(); - if(isNextSub("RNAM")) fail("Too many rank names"); - - // Main data struct - readHNExact(&data, data.sizeof, "FADT"); - - if(data.isHidden > 1) fail("Unknown flag!"); - - // Read faction response values - reactions = getRegion().getBuffer!(Reaction)(); - while(hasMoreSubs()) - { - Reaction r; - r.faction = getHNPtr!(Faction)("ANAM", factions); - r.reaction = getHNInt("INTV"); - reactions ~= r; - } - }} -} - -ListID!(Faction) factions; diff --git a/old_d_version/esm/loadlocks.d b/old_d_version/esm/loadlocks.d deleted file mode 100644 index cfac77286..000000000 --- a/old_d_version/esm/loadlocks.d +++ /dev/null @@ -1,90 +0,0 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2008 Nicolay Korslund - Email: < korslund@gmail.com > - WWW: http://openmw.snaptoad.com/ - - This file (loadlocks.d) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - - */ - -module esm.loadlocks; -import esm.imports; - -/* - * This file covers lockpicks, probes and armor repair items, since - * these have nearly identical structure. - */ - -struct Tool -{ - align(1) struct Data - { - float weight; - int value; - - float quality; // And when I say nearly identical structure, I - int uses; // mean perfectly identical except that these two - // variables are swaped for repair items. Don't ask - // me why. - } - static assert(Data.sizeof == 16); - - Data data; - - mixin LoadT; - - MeshIndex model; - IconIndex icon; - Script* script; - - void load() - {with(esFile){ - model = getMesh(); - name = getHNString("FNAM"); - - char[] type; - bool isRep = false; - - if(isNextSub("LKDT")) type = "Lockpick"; - else if(isNextSub("PBDT")) type = "Probe"; - else - { - getSubNameIs("RIDT"); - type = "RepairItem"; - isRep = true; - } - - readHExact(&data, data.sizeof); - - if(isRep) - { - // Swap t.data.quality and t.data.uses (sigh) - float tmp = *(cast(float*)&data.uses); - data.uses = *(cast(int*)&data.quality); - data.quality = tmp; - } - - script = getHNOPtr!(Script)("SCRI", scripts); - icon = getOIcon(); - - - makeProto(type); - proto.setFloat("quality", data.quality); - proto.setInt("uses", data.uses); - }} -} -ListID!(Tool) lockpicks, probes, repairs; diff --git a/old_d_version/esm/loadweap.d b/old_d_version/esm/loadweap.d deleted file mode 100644 index eb56effdf..000000000 --- a/old_d_version/esm/loadweap.d +++ /dev/null @@ -1,98 +0,0 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2008 Nicolay Korslund - Email: < korslund@gmail.com > - WWW: http://openmw.snaptoad.com/ - - This file (loadweap.d) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - - */ - -module esm.loadweap; -import esm.imports; - -/* - * Weapon definition - */ - -struct Weapon -{ - enum Type : short - { - ShortBladeOneHand = 0, - LongBladeOneHand = 1, - LongBladeTwoHand = 2, - BluntOneHand = 3, - BluntTwoClose = 4, - BluntTwoWide = 5, - SpearTwoWide = 6, - AxeOneHand = 7, - AxeTwoHand = 8, - MarksmanBow = 9, - MarksmanCrossbow = 10, - MarksmanThrown = 11, - Arrow = 12, - Bolt = 13, - Length - } - - enum Flags : uint - { - Magical = 0x01, - Silver = 0x02 - } - - align(1) struct WPDTstruct - { - float weight; - int value; - Type type; - short health; - float speed, reach; - short enchant; // Enchantment points - ubyte[2] chop, slash, thrust; // Min and max - Flags flags; - - static assert(WPDTstruct.sizeof == 32); - } - - WPDTstruct data; - - mixin LoadT!(); - - MeshIndex model; - IconIndex icon; - Enchantment* enchant; - Script* script; - - void load() - {with(esFile){ - model = getMesh(); - name = getHNOString("FNAM"); - readHNExact(&data, data.sizeof, "WPDT"); - script = getHNOPtr!(Script)("SCRI", scripts); - icon = getOIcon(); - enchant = getHNOPtr!(Enchantment)("ENAM", enchants); - - makeProto(); - - proto.setFloat("speed", data.speed); - proto.setFloat("reach", data.reach); - - proto.setInt("health", data.health); - }} -} -ListID!(Weapon) weapons;