diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index b8463c8af0..6e80171c4e 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -116,12 +116,14 @@ add_component_dir (esm3terrain ) add_component_dir (esm4 - acti actor + cellgrid common dialogue effect formid + grid + grouptype inventory lighting loadachr @@ -203,11 +205,13 @@ add_component_dir (esm4 loadtxst loadweap loadwrld + magiceffectid reader + readerutils reference script - readerutils typetraits + vertex ) add_component_dir (misc diff --git a/components/esm4/cellgrid.hpp b/components/esm4/cellgrid.hpp new file mode 100644 index 0000000000..70f2546e3d --- /dev/null +++ b/components/esm4/cellgrid.hpp @@ -0,0 +1,44 @@ +/* + Copyright (C) 2015-2020 cc9cii + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + cc9cii cc9c@iinet.net.au + + Much of the information on the data structures are based on the information + from Tes4Mod:Mod_File_Format and Tes5Mod:File_Formats but also refined by + trial & error. See http://en.uesp.net/wiki for details. + +*/ +#ifndef OPENMW_COMPONENTS_ESM4_CELLGRID_H +#define OPENMW_COMPONENTS_ESM4_CELLGRID_H + +#include + +#include "formid.hpp" +#include "grid.hpp" + +namespace ESM4 +{ + union CellGrid + { + FormId cellId; + Grid grid; + }; +} + +#endif // OPENMW_COMPONENTS_ESM4_CELLGRID_H diff --git a/components/esm4/common.cpp b/components/esm4/common.cpp deleted file mode 100644 index 8af645c8f0..0000000000 --- a/components/esm4/common.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - Copyright (C) 2015-2016, 2018, 2021 cc9cii - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - cc9cii cc9c@iinet.net.au - - Much of the information on the data structures are based on the information - from Tes4Mod:Mod_File_Format and Tes5Mod:File_Formats but also refined by - trial & error. See http://en.uesp.net/wiki for details. - -*/ -#include "common.hpp" - -#include -#include -#include - -#include - -#include "formid.hpp" - -namespace ESM4 -{ - const char* sGroupType[] = { "Record Type", "World Child", "Interior Cell", "Interior Sub Cell", "Exterior Cell", - "Exterior Sub Cell", "Cell Child", "Topic Child", "Cell Persistent Child", "Cell Temporary Child", - "Cell Visible Dist Child", "Unknown" }; - - std::string printLabel(const GroupLabel& label, const std::uint32_t type) - { - std::ostringstream ss; - ss << std::string(sGroupType[std::min(type, (uint32_t)11)]); // avoid out of range - - switch (type) - { - case ESM4::Grp_RecordType: - { - ss << ": " << std::string((char*)label.recordType, 4); - break; - } - case ESM4::Grp_ExteriorCell: - case ESM4::Grp_ExteriorSubCell: - { - // short x, y; - // y = label & 0xff; - // x = (label >> 16) & 0xff; - ss << ": grid (x, y) " << std::dec << label.grid[1] << ", " << label.grid[0]; - - break; - } - case ESM4::Grp_InteriorCell: - case ESM4::Grp_InteriorSubCell: - { - ss << ": block 0x" << std::hex << label.value; - break; - } - case ESM4::Grp_WorldChild: - case ESM4::Grp_CellChild: - case ESM4::Grp_TopicChild: - case ESM4::Grp_CellPersistentChild: - case ESM4::Grp_CellTemporaryChild: - case ESM4::Grp_CellVisibleDistChild: - { - ss << ": FormId 0x" << formIdToString(label.value); - break; - } - default: - break; - } - - return ss.str(); - } - - void gridToString(std::int16_t x, std::int16_t y, std::string& str) - { - char buf[6 + 6 + 2 + 1]; // longest signed 16 bit number is 6 characters (-32768) - int res = snprintf(buf, 6 + 6 + 2 + 1, "#%d %d", x, y); - if (res > 0 && res < 6 + 6 + 2 + 1) - str.assign(buf); - else - throw std::runtime_error("possible buffer overflow while converting grid"); - } -} diff --git a/components/esm4/common.hpp b/components/esm4/common.hpp index 9d5b9e6bc6..77c24f6121 100644 --- a/components/esm4/common.hpp +++ b/components/esm4/common.hpp @@ -27,13 +27,8 @@ #ifndef ESM4_COMMON_H #define ESM4_COMMON_H -#include -#include - #include "components/esm/fourcc.hpp" -#include "formid.hpp" - namespace ESM4 { using ESM::fourCC; @@ -662,164 +657,6 @@ namespace ESM4 SUB_EFSD = fourCC("EFSD"), // FONV DeadMoney }; - enum MagicEffectID - { - // Alteration - EFI_BRDN = fourCC("BRDN"), - EFI_FTHR = fourCC("FTHR"), - EFI_FISH = fourCC("FISH"), - EFI_FRSH = fourCC("FRSH"), - EFI_OPEN = fourCC("OPNN"), - EFI_SHLD = fourCC("SHLD"), - EFI_LISH = fourCC("LISH"), - EFI_WABR = fourCC("WABR"), - EFI_WAWA = fourCC("WAWA"), - - // Conjuration - EFI_BABO = fourCC("BABO"), // Bound Boots - EFI_BACU = fourCC("BACU"), // Bound Cuirass - EFI_BAGA = fourCC("BAGA"), // Bound Gauntlets - EFI_BAGR = fourCC("BAGR"), // Bound Greaves - EFI_BAHE = fourCC("BAHE"), // Bound Helmet - EFI_BASH = fourCC("BASH"), // Bound Shield - EFI_BWAX = fourCC("BWAX"), // Bound Axe - EFI_BWBO = fourCC("BWBO"), // Bound Bow - EFI_BWDA = fourCC("BWDA"), // Bound Dagger - EFI_BWMA = fourCC("BWMA"), // Bound Mace - EFI_BWSW = fourCC("BWSW"), // Bound Sword - EFI_Z001 = fourCC("Z001"), // Summon Rufio's Ghost - EFI_Z002 = fourCC("Z002"), // Summon Ancestor Guardian - EFI_Z003 = fourCC("Z003"), // Summon Spiderling - EFI_Z005 = fourCC("Z005"), // Summon Bear - EFI_ZCLA = fourCC("ZCLA"), // Summon Clannfear - EFI_ZDAE = fourCC("ZDAE"), // Summon Daedroth - EFI_ZDRE = fourCC("ZDRE"), // Summon Dremora - EFI_ZDRL = fourCC("ZDRL"), // Summon Dremora Lord - EFI_ZFIA = fourCC("ZFIA"), // Summon Flame Atronach - EFI_ZFRA = fourCC("ZFRA"), // Summon Frost Atronach - EFI_ZGHO = fourCC("ZGHO"), // Summon Ghost - EFI_ZHDZ = fourCC("ZHDZ"), // Summon Headless Zombie - EFI_ZLIC = fourCC("ZLIC"), // Summon Lich - EFI_ZSCA = fourCC("ZSCA"), // Summon Scamp - EFI_ZSKE = fourCC("ZSKE"), // Summon Skeleton - EFI_ZSKA = fourCC("ZSKA"), // Summon Skeleton Guardian - EFI_ZSKH = fourCC("ZSKH"), // Summon Skeleton Hero - EFI_ZSKC = fourCC("ZSKC"), // Summon Skeleton Champion - EFI_ZSPD = fourCC("ZSPD"), // Summon Spider Daedra - EFI_ZSTA = fourCC("ZSTA"), // Summon Storm Atronach - EFI_ZWRA = fourCC("ZWRA"), // Summon Faded Wraith - EFI_ZWRL = fourCC("ZWRL"), // Summon Gloom Wraith - EFI_ZXIV = fourCC("ZXIV"), // Summon Xivilai - EFI_ZZOM = fourCC("ZZOM"), // Summon Zombie - EFI_TURN = fourCC("TURN"), // Turn Undead - - // Destruction - EFI_DGAT = fourCC("DGAT"), // Damage Attribute - EFI_DGFA = fourCC("DGFA"), // Damage Fatigue - EFI_DGHE = fourCC("DGHE"), // Damage Health - EFI_DGSP = fourCC("DGSP"), // Damage Magicka - EFI_DIAR = fourCC("DIAR"), // Disintegrate Armor - EFI_DIWE = fourCC("DIWE"), // Disintegrate Weapon - EFI_DRAT = fourCC("DRAT"), // Drain Attribute - EFI_DRFA = fourCC("DRFA"), // Drain Fatigue - EFI_DRHE = fourCC("DRHE"), // Drain Health - EFI_DRSP = fourCC("DRSP"), // Drain Magicka - EFI_DRSK = fourCC("DRSK"), // Drain Skill - EFI_FIDG = fourCC("FIDG"), // Fire Damage - EFI_FRDG = fourCC("FRDG"), // Frost Damage - EFI_SHDG = fourCC("SHDG"), // Shock Damage - EFI_WKDI = fourCC("WKDI"), // Weakness to Disease - EFI_WKFI = fourCC("WKFI"), // Weakness to Fire - EFI_WKFR = fourCC("WKFR"), // Weakness to Frost - EFI_WKMA = fourCC("WKMA"), // Weakness to Magic - EFI_WKNW = fourCC("WKNW"), // Weakness to Normal Weapons - EFI_WKPO = fourCC("WKPO"), // Weakness to Poison - EFI_WKSH = fourCC("WKSH"), // Weakness to Shock - - // Illusion - EFI_CALM = fourCC("CALM"), // Calm - EFI_CHML = fourCC("CHML"), // Chameleon - EFI_CHRM = fourCC("CHRM"), // Charm - EFI_COCR = fourCC("COCR"), // Command Creature - EFI_COHU = fourCC("COHU"), // Command Humanoid - EFI_DEMO = fourCC("DEMO"), // Demoralize - EFI_FRNZ = fourCC("FRNZ"), // Frenzy - EFI_INVI = fourCC("INVI"), // Invisibility - EFI_LGHT = fourCC("LGHT"), // Light - EFI_NEYE = fourCC("NEYE"), // Night-Eye - EFI_PARA = fourCC("PARA"), // Paralyze - EFI_RALY = fourCC("RALY"), // Rally - EFI_SLNC = fourCC("SLNC"), // Silence - - // Mysticism - EFI_DTCT = fourCC("DTCT"), // Detect Life - EFI_DSPL = fourCC("DSPL"), // Dispel - EFI_REDG = fourCC("REDG"), // Reflect Damage - EFI_RFLC = fourCC("RFLC"), // Reflect Spell - EFI_STRP = fourCC("STRP"), // Soul Trap - EFI_SABS = fourCC("SABS"), // Spell Absorption - EFI_TELE = fourCC("TELE"), // Telekinesis - - // Restoration - EFI_ABAT = fourCC("ABAT"), // Absorb Attribute - EFI_ABFA = fourCC("ABFA"), // Absorb Fatigue - EFI_ABHe = fourCC("ABHe"), // Absorb Health - EFI_ABSP = fourCC("ABSP"), // Absorb Magicka - EFI_ABSK = fourCC("ABSK"), // Absorb Skill - EFI_1400 = fourCC("1400"), // Cure Disease - EFI_CUPA = fourCC("CUPA"), // Cure Paralysis - EFI_CUPO = fourCC("CUPO"), // Cure Poison - EFI_FOAT = fourCC("FOAT"), // Fortify Attribute - EFI_FOFA = fourCC("FOFA"), // Fortify Fatigue - EFI_FOHE = fourCC("FOHE"), // Fortify Health - EFI_FOSP = fourCC("FOSP"), // Fortify Magicka - EFI_FOSK = fourCC("FOSK"), // Fortify Skill - EFI_RSDI = fourCC("RSDI"), // Resist Disease - EFI_RSFI = fourCC("RSFI"), // Resist Fire - EFI_RSFR = fourCC("RSFR"), // Resist Frost - EFI_RSMA = fourCC("RSMA"), // Resist Magic - EFI_RSNW = fourCC("RSNW"), // Resist Normal Weapons - EFI_RSPA = fourCC("RSPA"), // Resist Paralysis - EFI_RSPO = fourCC("RSPO"), // Resist Poison - EFI_RSSH = fourCC("RSSH"), // Resist Shock - EFI_REAT = fourCC("REAT"), // Restore Attribute - EFI_REFA = fourCC("REFA"), // Restore Fatigue - EFI_REHE = fourCC("REHE"), // Restore Health - EFI_RESP = fourCC("RESP"), // Restore Magicka - - // Effects - EFI_LOCK = fourCC("LOCK"), // Lock Lock - EFI_SEFF = fourCC("SEFF"), // Script Effect - EFI_Z020 = fourCC("Z020"), // Summon 20 Extra - EFI_MYHL = fourCC("MYHL"), // Summon Mythic Dawn Helmet - EFI_MYTH = fourCC("MYTH"), // Summon Mythic Dawn Armor - EFI_REAN = fourCC("REAN"), // Reanimate - EFI_DISE = fourCC("DISE"), // Disease Info - EFI_POSN = fourCC("POSN"), // Poison Info - EFI_DUMY = fourCC("DUMY"), // Mehrunes Dagon Custom Effect - EFI_STMA = fourCC("STMA"), // Stunted Magicka - EFI_SUDG = fourCC("SUDG"), // Sun Damage - EFI_VAMP = fourCC("VAMP"), // Vampirism - EFI_DARK = fourCC("DARK"), // Darkness - EFI_RSWD = fourCC("RSWD") // Resist Water Damage - }; - - // Based on http://www.uesp.net/wiki/Tes5Mod:Mod_File_Format#Groups - enum GroupType - { - Grp_RecordType = 0, - Grp_WorldChild = 1, - Grp_InteriorCell = 2, - Grp_InteriorSubCell = 3, - Grp_ExteriorCell = 4, - Grp_ExteriorSubCell = 5, - Grp_CellChild = 6, - Grp_TopicChild = 7, - Grp_CellPersistentChild = 8, - Grp_CellTemporaryChild = 9, - Grp_CellVisibleDistChild = 10 - }; - // Based on http://www.uesp.net/wiki/Tes5Mod:Mod_File_Format#Records enum RecordFlag { @@ -859,77 +696,6 @@ namespace ESM4 Rec_NoRespawn = 0x40000000, // (REFR) NoRespawn Rec_MultiBound = 0x80000000 // (REFR) MultiBound }; - -#pragma pack(push, 1) - // NOTE: the label field of a group is not reliable (http://www.uesp.net/wiki/Tes4Mod:Mod_File_Format) - union GroupLabel - { - std::uint32_t value; // formId, blockNo or raw int representation of type - char recordType[4]; // record type in ascii - std::int16_t grid[2]; // grid y, x (note the reverse order) - }; - - struct GroupTypeHeader - { - std::uint32_t typeId; - std::uint32_t groupSize; // includes the 24 bytes (20 for TES4) of header (i.e. this struct) - GroupLabel label; // format based on type - std::int32_t type; - std::uint16_t stamp; // & 0xff for day, & 0xff00 for months since Dec 2002 (i.e. 1 = Jan 2003) - std::uint16_t unknown; - std::uint16_t version; // not in TES4 - std::uint16_t unknown2; // not in TES4 - }; - - struct RecordTypeHeader - { - std::uint32_t typeId; - std::uint32_t dataSize; // does *not* include 24 bytes (20 for TES4) of header - std::uint32_t flags; - FormId id; - std::uint32_t revision; - std::uint16_t version; // not in TES4 - std::uint16_t unknown; // not in TES4 - }; - - union RecordHeader - { - struct GroupTypeHeader group; - struct RecordTypeHeader record; - }; - - struct SubRecordHeader - { - std::uint32_t typeId; - std::uint16_t dataSize; - }; - - // Grid, CellGrid and Vertex are shared by NVMI(NAVI) and NVNM(NAVM) - - struct Grid - { - std::int16_t x; - std::int16_t y; - }; - - union CellGrid - { - FormId cellId; - Grid grid; - }; - - struct Vertex - { - float x; - float y; - float z; - }; -#pragma pack(pop) - - // For pretty printing GroupHeader labels - std::string printLabel(const GroupLabel& label, const std::uint32_t type); - - void gridToString(std::int16_t x, std::int16_t y, std::string& str); } #endif // ESM4_COMMON_H diff --git a/components/esm4/grid.hpp b/components/esm4/grid.hpp new file mode 100644 index 0000000000..bebd091334 --- /dev/null +++ b/components/esm4/grid.hpp @@ -0,0 +1,41 @@ +/* + Copyright (C) 2015-2020 cc9cii + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + cc9cii cc9c@iinet.net.au + + Much of the information on the data structures are based on the information + from Tes4Mod:Mod_File_Format and Tes5Mod:File_Formats but also refined by + trial & error. See http://en.uesp.net/wiki for details. + +*/ +#ifndef OPENMW_COMPONENTS_ESM4_GRID_H +#define OPENMW_COMPONENTS_ESM4_GRID_H + +#include + +namespace ESM4 +{ + struct Grid + { + std::int16_t x; + std::int16_t y; + }; +} + +#endif // OPENMW_COMPONENTS_ESM4_GRID_H diff --git a/components/esm4/grouptype.hpp b/components/esm4/grouptype.hpp new file mode 100644 index 0000000000..45df3a0e74 --- /dev/null +++ b/components/esm4/grouptype.hpp @@ -0,0 +1,49 @@ +/* + Copyright (C) 2015-2020 cc9cii + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + cc9cii cc9c@iinet.net.au + + Much of the information on the data structures are based on the information + from Tes4Mod:Mod_File_Format and Tes5Mod:File_Formats but also refined by + trial & error. See http://en.uesp.net/wiki for details. + +*/ +#ifndef OPENMW_COMPONENTS_ESM4_GROUPTYPE_H +#define OPENMW_COMPONENTS_ESM4_GROUPTYPE_H + +namespace ESM4 +{ + // Based on http://www.uesp.net/wiki/Tes5Mod:Mod_File_Format#Groups + enum GroupType + { + Grp_RecordType = 0, + Grp_WorldChild = 1, + Grp_InteriorCell = 2, + Grp_InteriorSubCell = 3, + Grp_ExteriorCell = 4, + Grp_ExteriorSubCell = 5, + Grp_CellChild = 6, + Grp_TopicChild = 7, + Grp_CellPersistentChild = 8, + Grp_CellTemporaryChild = 9, + Grp_CellVisibleDistChild = 10 + }; +} + +#endif // OPENMW_COMPONENTS_ESM4_GROUPTYPE_H diff --git a/components/esm4/loadcell.cpp b/components/esm4/loadcell.cpp index 917172265d..421c20f91c 100644 --- a/components/esm4/loadcell.cpp +++ b/components/esm4/loadcell.cpp @@ -35,6 +35,7 @@ #include // FIXME: debug only #include +#include "grouptype.hpp" #include "reader.hpp" // #include "writer.hpp" diff --git a/components/esm4/loadnavi.hpp b/components/esm4/loadnavi.hpp index e7d5ede7b3..9a804efe0a 100644 --- a/components/esm4/loadnavi.hpp +++ b/components/esm4/loadnavi.hpp @@ -31,7 +31,8 @@ #include #include -#include "common.hpp" // CellGrid, Vertex +#include "cellgrid.hpp" +#include "vertex.hpp" namespace ESM4 { diff --git a/components/esm4/loadnavm.hpp b/components/esm4/loadnavm.hpp index 682c9d8f2f..a62ed47854 100644 --- a/components/esm4/loadnavm.hpp +++ b/components/esm4/loadnavm.hpp @@ -30,7 +30,8 @@ #include #include -#include "common.hpp" // CellGrid, Vertex +#include "cellgrid.hpp" +#include "vertex.hpp" namespace ESM4 { diff --git a/components/esm4/loadwrld.hpp b/components/esm4/loadwrld.hpp index 1916057b58..f5ba010ba8 100644 --- a/components/esm4/loadwrld.hpp +++ b/components/esm4/loadwrld.hpp @@ -31,7 +31,8 @@ #include #include -#include "common.hpp" +#include "formid.hpp" +#include "grid.hpp" namespace ESM4 { diff --git a/components/esm4/magiceffectid.hpp b/components/esm4/magiceffectid.hpp new file mode 100644 index 0000000000..2906aff045 --- /dev/null +++ b/components/esm4/magiceffectid.hpp @@ -0,0 +1,179 @@ +/* + Copyright (C) 2015-2020 cc9cii + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + cc9cii cc9c@iinet.net.au + + Much of the information on the data structures are based on the information + from Tes4Mod:Mod_File_Format and Tes5Mod:File_Formats but also refined by + trial & error. See http://en.uesp.net/wiki for details. + +*/ +#ifndef OPENMW_COMPONENTS_ESM4_MAGICEFFECTID_H +#define OPENMW_COMPONENTS_ESM4_MAGICEFFECTID_H + +#include "components/esm/fourcc.hpp" + +namespace ESM4 +{ + using ESM::fourCC; + + enum MagicEffectID + { + // Alteration + EFI_BRDN = fourCC("BRDN"), + EFI_FTHR = fourCC("FTHR"), + EFI_FISH = fourCC("FISH"), + EFI_FRSH = fourCC("FRSH"), + EFI_OPEN = fourCC("OPNN"), + EFI_SHLD = fourCC("SHLD"), + EFI_LISH = fourCC("LISH"), + EFI_WABR = fourCC("WABR"), + EFI_WAWA = fourCC("WAWA"), + + // Conjuration + EFI_BABO = fourCC("BABO"), // Bound Boots + EFI_BACU = fourCC("BACU"), // Bound Cuirass + EFI_BAGA = fourCC("BAGA"), // Bound Gauntlets + EFI_BAGR = fourCC("BAGR"), // Bound Greaves + EFI_BAHE = fourCC("BAHE"), // Bound Helmet + EFI_BASH = fourCC("BASH"), // Bound Shield + EFI_BWAX = fourCC("BWAX"), // Bound Axe + EFI_BWBO = fourCC("BWBO"), // Bound Bow + EFI_BWDA = fourCC("BWDA"), // Bound Dagger + EFI_BWMA = fourCC("BWMA"), // Bound Mace + EFI_BWSW = fourCC("BWSW"), // Bound Sword + EFI_Z001 = fourCC("Z001"), // Summon Rufio's Ghost + EFI_Z002 = fourCC("Z002"), // Summon Ancestor Guardian + EFI_Z003 = fourCC("Z003"), // Summon Spiderling + EFI_Z005 = fourCC("Z005"), // Summon Bear + EFI_ZCLA = fourCC("ZCLA"), // Summon Clannfear + EFI_ZDAE = fourCC("ZDAE"), // Summon Daedroth + EFI_ZDRE = fourCC("ZDRE"), // Summon Dremora + EFI_ZDRL = fourCC("ZDRL"), // Summon Dremora Lord + EFI_ZFIA = fourCC("ZFIA"), // Summon Flame Atronach + EFI_ZFRA = fourCC("ZFRA"), // Summon Frost Atronach + EFI_ZGHO = fourCC("ZGHO"), // Summon Ghost + EFI_ZHDZ = fourCC("ZHDZ"), // Summon Headless Zombie + EFI_ZLIC = fourCC("ZLIC"), // Summon Lich + EFI_ZSCA = fourCC("ZSCA"), // Summon Scamp + EFI_ZSKE = fourCC("ZSKE"), // Summon Skeleton + EFI_ZSKA = fourCC("ZSKA"), // Summon Skeleton Guardian + EFI_ZSKH = fourCC("ZSKH"), // Summon Skeleton Hero + EFI_ZSKC = fourCC("ZSKC"), // Summon Skeleton Champion + EFI_ZSPD = fourCC("ZSPD"), // Summon Spider Daedra + EFI_ZSTA = fourCC("ZSTA"), // Summon Storm Atronach + EFI_ZWRA = fourCC("ZWRA"), // Summon Faded Wraith + EFI_ZWRL = fourCC("ZWRL"), // Summon Gloom Wraith + EFI_ZXIV = fourCC("ZXIV"), // Summon Xivilai + EFI_ZZOM = fourCC("ZZOM"), // Summon Zombie + EFI_TURN = fourCC("TURN"), // Turn Undead + + // Destruction + EFI_DGAT = fourCC("DGAT"), // Damage Attribute + EFI_DGFA = fourCC("DGFA"), // Damage Fatigue + EFI_DGHE = fourCC("DGHE"), // Damage Health + EFI_DGSP = fourCC("DGSP"), // Damage Magicka + EFI_DIAR = fourCC("DIAR"), // Disintegrate Armor + EFI_DIWE = fourCC("DIWE"), // Disintegrate Weapon + EFI_DRAT = fourCC("DRAT"), // Drain Attribute + EFI_DRFA = fourCC("DRFA"), // Drain Fatigue + EFI_DRHE = fourCC("DRHE"), // Drain Health + EFI_DRSP = fourCC("DRSP"), // Drain Magicka + EFI_DRSK = fourCC("DRSK"), // Drain Skill + EFI_FIDG = fourCC("FIDG"), // Fire Damage + EFI_FRDG = fourCC("FRDG"), // Frost Damage + EFI_SHDG = fourCC("SHDG"), // Shock Damage + EFI_WKDI = fourCC("WKDI"), // Weakness to Disease + EFI_WKFI = fourCC("WKFI"), // Weakness to Fire + EFI_WKFR = fourCC("WKFR"), // Weakness to Frost + EFI_WKMA = fourCC("WKMA"), // Weakness to Magic + EFI_WKNW = fourCC("WKNW"), // Weakness to Normal Weapons + EFI_WKPO = fourCC("WKPO"), // Weakness to Poison + EFI_WKSH = fourCC("WKSH"), // Weakness to Shock + + // Illusion + EFI_CALM = fourCC("CALM"), // Calm + EFI_CHML = fourCC("CHML"), // Chameleon + EFI_CHRM = fourCC("CHRM"), // Charm + EFI_COCR = fourCC("COCR"), // Command Creature + EFI_COHU = fourCC("COHU"), // Command Humanoid + EFI_DEMO = fourCC("DEMO"), // Demoralize + EFI_FRNZ = fourCC("FRNZ"), // Frenzy + EFI_INVI = fourCC("INVI"), // Invisibility + EFI_LGHT = fourCC("LGHT"), // Light + EFI_NEYE = fourCC("NEYE"), // Night-Eye + EFI_PARA = fourCC("PARA"), // Paralyze + EFI_RALY = fourCC("RALY"), // Rally + EFI_SLNC = fourCC("SLNC"), // Silence + + // Mysticism + EFI_DTCT = fourCC("DTCT"), // Detect Life + EFI_DSPL = fourCC("DSPL"), // Dispel + EFI_REDG = fourCC("REDG"), // Reflect Damage + EFI_RFLC = fourCC("RFLC"), // Reflect Spell + EFI_STRP = fourCC("STRP"), // Soul Trap + EFI_SABS = fourCC("SABS"), // Spell Absorption + EFI_TELE = fourCC("TELE"), // Telekinesis + + // Restoration + EFI_ABAT = fourCC("ABAT"), // Absorb Attribute + EFI_ABFA = fourCC("ABFA"), // Absorb Fatigue + EFI_ABHe = fourCC("ABHe"), // Absorb Health + EFI_ABSP = fourCC("ABSP"), // Absorb Magicka + EFI_ABSK = fourCC("ABSK"), // Absorb Skill + EFI_1400 = fourCC("1400"), // Cure Disease + EFI_CUPA = fourCC("CUPA"), // Cure Paralysis + EFI_CUPO = fourCC("CUPO"), // Cure Poison + EFI_FOAT = fourCC("FOAT"), // Fortify Attribute + EFI_FOFA = fourCC("FOFA"), // Fortify Fatigue + EFI_FOHE = fourCC("FOHE"), // Fortify Health + EFI_FOSP = fourCC("FOSP"), // Fortify Magicka + EFI_FOSK = fourCC("FOSK"), // Fortify Skill + EFI_RSDI = fourCC("RSDI"), // Resist Disease + EFI_RSFI = fourCC("RSFI"), // Resist Fire + EFI_RSFR = fourCC("RSFR"), // Resist Frost + EFI_RSMA = fourCC("RSMA"), // Resist Magic + EFI_RSNW = fourCC("RSNW"), // Resist Normal Weapons + EFI_RSPA = fourCC("RSPA"), // Resist Paralysis + EFI_RSPO = fourCC("RSPO"), // Resist Poison + EFI_RSSH = fourCC("RSSH"), // Resist Shock + EFI_REAT = fourCC("REAT"), // Restore Attribute + EFI_REFA = fourCC("REFA"), // Restore Fatigue + EFI_REHE = fourCC("REHE"), // Restore Health + EFI_RESP = fourCC("RESP"), // Restore Magicka + + // Effects + EFI_LOCK = fourCC("LOCK"), // Lock Lock + EFI_SEFF = fourCC("SEFF"), // Script Effect + EFI_Z020 = fourCC("Z020"), // Summon 20 Extra + EFI_MYHL = fourCC("MYHL"), // Summon Mythic Dawn Helmet + EFI_MYTH = fourCC("MYTH"), // Summon Mythic Dawn Armor + EFI_REAN = fourCC("REAN"), // Reanimate + EFI_DISE = fourCC("DISE"), // Disease Info + EFI_POSN = fourCC("POSN"), // Poison Info + EFI_DUMY = fourCC("DUMY"), // Mehrunes Dagon Custom Effect + EFI_STMA = fourCC("STMA"), // Stunted Magicka + EFI_SUDG = fourCC("SUDG"), // Sun Damage + EFI_VAMP = fourCC("VAMP"), // Vampirism + EFI_DARK = fourCC("DARK"), // Darkness + EFI_RSWD = fourCC("RSWD") // Resist Water Damage + }; +} + +#endif // OPENMW_COMPONENTS_ESM4_MAGICEFFECTID_H diff --git a/components/esm4/reader.cpp b/components/esm4/reader.cpp index 091df5abf1..f62cd36262 100644 --- a/components/esm4/reader.cpp +++ b/components/esm4/reader.cpp @@ -53,6 +53,7 @@ #include #include "formid.hpp" +#include "grouptype.hpp" namespace ESM4 { @@ -380,7 +381,7 @@ namespace ESM4 boost::iostreams::copy(inputStreamBuf, sr); // For debugging only - //#if 0 + // #if 0 if (dump) { std::ostringstream ss; @@ -398,7 +399,7 @@ namespace ESM4 } std::cout << ss.str() << std::endl; } - //#endif + // #endif mStream = std::make_unique>(std::move(memoryStreamPtr)); } } @@ -516,11 +517,11 @@ namespace ESM4 lastGroupSize = mCtx.groupStack.back().first.groupSize; assert(lastGroupSize >= mCtx.groupStack.back().second && "Read more records than available"); - //#if 0 + // #if 0 if (mCtx.groupStack.back().second > lastGroupSize) // FIXME: debugging only std::cerr << printLabel(mCtx.groupStack.back().first.label, mCtx.groupStack.back().first.type) << " read more records than available" << std::endl; - //#endif + // #endif } } @@ -742,4 +743,66 @@ namespace ESM4 return true; } + namespace + { + constexpr std::string_view sGroupType[] = { + "Record Type", + "World Child", + "Interior Cell", + "Interior Sub Cell", + "Exterior Cell", + "Exterior Sub Cell", + "Cell Child", + "Topic Child", + "Cell Persistent Child", + "Cell Temporary Child", + "Cell Visible Dist Child", + "Unknown", + }; + } + + std::string printLabel(const GroupLabel& label, const std::uint32_t type) + { + std::ostringstream ss; + ss << sGroupType[std::min(type, std::size(sGroupType))]; // avoid out of range + + switch (type) + { + case ESM4::Grp_RecordType: + { + ss << ": " << std::string((char*)label.recordType, 4); + break; + } + case ESM4::Grp_ExteriorCell: + case ESM4::Grp_ExteriorSubCell: + { + // short x, y; + // y = label & 0xff; + // x = (label >> 16) & 0xff; + ss << ": grid (x, y) " << std::dec << label.grid[1] << ", " << label.grid[0]; + + break; + } + case ESM4::Grp_InteriorCell: + case ESM4::Grp_InteriorSubCell: + { + ss << ": block 0x" << std::hex << label.value; + break; + } + case ESM4::Grp_WorldChild: + case ESM4::Grp_CellChild: + case ESM4::Grp_TopicChild: + case ESM4::Grp_CellPersistentChild: + case ESM4::Grp_CellTemporaryChild: + case ESM4::Grp_CellVisibleDistChild: + { + ss << ": FormId 0x" << formIdToString(label.value); + break; + } + default: + break; + } + + return ss.str(); + } } diff --git a/components/esm4/reader.hpp b/components/esm4/reader.hpp index 91bd44a156..3caaf66f6d 100644 --- a/components/esm4/reader.hpp +++ b/components/esm4/reader.hpp @@ -29,6 +29,7 @@ #include #include +#include "cellgrid.hpp" #include "common.hpp" #include "loadtes4.hpp" @@ -42,6 +43,51 @@ namespace ToUTF8 namespace ESM4 { +#pragma pack(push, 1) + // NOTE: the label field of a group is not reliable (http://www.uesp.net/wiki/Tes4Mod:Mod_File_Format) + union GroupLabel + { + std::uint32_t value; // formId, blockNo or raw int representation of type + char recordType[4]; // record type in ascii + std::int16_t grid[2]; // grid y, x (note the reverse order) + }; + + struct GroupTypeHeader + { + std::uint32_t typeId; + std::uint32_t groupSize; // includes the 24 bytes (20 for TES4) of header (i.e. this struct) + GroupLabel label; // format based on type + std::int32_t type; + std::uint16_t stamp; // & 0xff for day, & 0xff00 for months since Dec 2002 (i.e. 1 = Jan 2003) + std::uint16_t unknown; + std::uint16_t version; // not in TES4 + std::uint16_t unknown2; // not in TES4 + }; + + struct RecordTypeHeader + { + std::uint32_t typeId; + std::uint32_t dataSize; // does *not* include 24 bytes (20 for TES4) of header + std::uint32_t flags; + FormId id; + std::uint32_t revision; + std::uint16_t version; // not in TES4 + std::uint16_t unknown; // not in TES4 + }; + + union RecordHeader + { + GroupTypeHeader group; + RecordTypeHeader record; + }; + + struct SubRecordHeader + { + std::uint32_t typeId; + std::uint16_t dataSize; + }; +#pragma pack(pop) + // bytes read from group, updated by // getRecordHeader() in advance // | @@ -316,6 +362,9 @@ namespace ESM4 std::vector* getGlobalReaderList() { return mGlobalReaderList; } }; + + // For pretty printing GroupHeader labels + std::string printLabel(const GroupLabel& label, const std::uint32_t type); } #endif // ESM4_READER_H diff --git a/components/esm4/readerutils.hpp b/components/esm4/readerutils.hpp index 541568d3d2..c31d85e3bd 100644 --- a/components/esm4/readerutils.hpp +++ b/components/esm4/readerutils.hpp @@ -1,7 +1,9 @@ #ifndef OPENMW_COMPONENTS_ESM4_READERUTILS #define OPENMW_COMPONENTS_ESM4_READERUTILS -#include +#include "grouptype.hpp" +#include "reader.hpp" + namespace ESM4 { struct ReaderUtils diff --git a/components/esm4/vertex.hpp b/components/esm4/vertex.hpp new file mode 100644 index 0000000000..ead8b1f34e --- /dev/null +++ b/components/esm4/vertex.hpp @@ -0,0 +1,40 @@ +/* + Copyright (C) 2015-2020 cc9cii + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + cc9cii cc9c@iinet.net.au + + Much of the information on the data structures are based on the information + from Tes4Mod:Mod_File_Format and Tes5Mod:File_Formats but also refined by + trial & error. See http://en.uesp.net/wiki for details. + +*/ +#ifndef OPENMW_COMPONENTS_ESM4_VERTEX_H +#define OPENMW_COMPONENTS_ESM4_VERTEX_H + +namespace ESM4 +{ + struct Vertex + { + float x; + float y; + float z; + }; +} + +#endif // OPENMW_COMPONENTS_ESM4_VERTEX_H