forked from mirror/openmw-tes3mp
Finished cell loading code in esm/loadcell.hpp
This commit is contained in:
parent
7238847b8b
commit
5d2394a78b
2 changed files with 184 additions and 14 deletions
11
esm/defs.hpp
11
esm/defs.hpp
|
@ -5,6 +5,9 @@
|
||||||
|
|
||||||
namespace ESM {
|
namespace ESM {
|
||||||
|
|
||||||
|
// Pixel color value. Standard four-byte rr,gg,bb,aa format.
|
||||||
|
typedef int32_t Color;
|
||||||
|
|
||||||
enum VarType
|
enum VarType
|
||||||
{
|
{
|
||||||
VT_Unknown,
|
VT_Unknown,
|
||||||
|
@ -43,6 +46,14 @@ struct SpellList
|
||||||
*/
|
*/
|
||||||
#pragma pack(push)
|
#pragma pack(push)
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
|
|
||||||
|
// Position and rotation
|
||||||
|
struct Position
|
||||||
|
{
|
||||||
|
float pos[3];
|
||||||
|
float rot[3];
|
||||||
|
};
|
||||||
|
|
||||||
struct ENAMstruct
|
struct ENAMstruct
|
||||||
{
|
{
|
||||||
// Magical effect, hard-coded ID
|
// Magical effect, hard-coded ID
|
||||||
|
|
187
esm/loadcell.hpp
187
esm/loadcell.hpp
|
@ -2,9 +2,77 @@
|
||||||
#define _ESM_CELL_H
|
#define _ESM_CELL_H
|
||||||
|
|
||||||
#include "esm_reader.hpp"
|
#include "esm_reader.hpp"
|
||||||
|
#include "defs.hpp"
|
||||||
|
|
||||||
namespace ESM {
|
namespace ESM {
|
||||||
|
|
||||||
|
/* Cell reference. This represents ONE object (of many) inside the
|
||||||
|
cell. The cell references are not loaded as part of the normal
|
||||||
|
loading process, but are rather loaded later on demand when we are
|
||||||
|
setting up a specific cell.
|
||||||
|
*/
|
||||||
|
struct CellRef
|
||||||
|
{
|
||||||
|
int refnum; // Reference number
|
||||||
|
std::string refID; // ID of object being referenced
|
||||||
|
|
||||||
|
float scale; // Scale applied to mesh
|
||||||
|
|
||||||
|
// The NPC that owns this object (and will get angry if you steal
|
||||||
|
// it)
|
||||||
|
std::string owner;
|
||||||
|
|
||||||
|
// I have no idea, looks like a link to a global variable?
|
||||||
|
std::string glob;
|
||||||
|
|
||||||
|
// ID of creature trapped in this soul gem (?)
|
||||||
|
std::string soul;
|
||||||
|
|
||||||
|
// ?? CNAM has a faction name, might be for objects/beds etc
|
||||||
|
// belonging to a faction.
|
||||||
|
std::string faction;
|
||||||
|
|
||||||
|
// INDX might be PC faction rank required to use the item? Sometimes
|
||||||
|
// is -1, which I assume means "any rank".
|
||||||
|
int factIndex;
|
||||||
|
|
||||||
|
// Depends on context - possibly weapon health, number of uses left
|
||||||
|
// or weapon magic charge?
|
||||||
|
float charge;
|
||||||
|
|
||||||
|
// I have no idea, these are present some times, often along with
|
||||||
|
// owner (ANAM) and sometimes otherwise. Is NAM9 is always 1? INTV
|
||||||
|
// is usually one, but big for lights. Perhaps something to do with
|
||||||
|
// remaining light "charge". I haven't tried reading it as a float
|
||||||
|
// in those cases.
|
||||||
|
int intv, nam9;
|
||||||
|
|
||||||
|
// For doors - true if this door teleports to somewhere else, false
|
||||||
|
// if it should open through animation.
|
||||||
|
bool teleport;
|
||||||
|
|
||||||
|
// Teleport location for the door, if this is a teleporting door.
|
||||||
|
Position doorDest;
|
||||||
|
|
||||||
|
// Destination cell for doors (optional)
|
||||||
|
std::string destCell;
|
||||||
|
|
||||||
|
// Lock level for doors and containers
|
||||||
|
int lockLevel;
|
||||||
|
std::string key, trap; // Key and trap ID names, if any
|
||||||
|
|
||||||
|
// No idea - occurs ONCE in Morrowind.esm, for an activator
|
||||||
|
char unam;
|
||||||
|
|
||||||
|
// Occurs in Tribunal.esm, eg. in the cell "Mournhold, Plaza
|
||||||
|
// Brindisi Dorom", where it has the value 100. Also only for
|
||||||
|
// activators.
|
||||||
|
int fltv;
|
||||||
|
|
||||||
|
// Position and rotation of this object within the cell
|
||||||
|
Position pos;
|
||||||
|
};
|
||||||
|
|
||||||
/* Cells hold data about objects, creatures, statics (rocks, walls,
|
/* Cells hold data about objects, creatures, statics (rocks, walls,
|
||||||
buildings) and landscape (for exterior cells). Cells frequently
|
buildings) and landscape (for exterior cells). Cells frequently
|
||||||
also has other associated LAND and PGRD records. Combined, all this
|
also has other associated LAND and PGRD records. Combined, all this
|
||||||
|
@ -12,12 +80,7 @@ namespace ESM {
|
||||||
the strategy we use is to remember the file position of each cell
|
the strategy we use is to remember the file position of each cell
|
||||||
(using ESMReader::getContext()) and jumping back into place
|
(using ESMReader::getContext()) and jumping back into place
|
||||||
whenever we need to load a given cell.
|
whenever we need to load a given cell.
|
||||||
|
|
||||||
TODO: We should handle the actual cell content loading in this file
|
|
||||||
too, although the solution should be as open as possible and let
|
|
||||||
the user handle all data storage.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct Cell
|
struct Cell
|
||||||
{
|
{
|
||||||
enum Flags
|
enum Flags
|
||||||
|
@ -35,34 +98,130 @@ struct Cell
|
||||||
int gridX, gridY;
|
int gridX, gridY;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AMBIstruct
|
||||||
|
{
|
||||||
|
Color ambient, sunlight, fog;
|
||||||
|
float fogDensity;
|
||||||
|
};
|
||||||
|
|
||||||
// Interior cells are indexed by this (it's the 'id'), for exterior
|
// Interior cells are indexed by this (it's the 'id'), for exterior
|
||||||
// cells it is optional.
|
// cells it is optional.
|
||||||
std::string name,
|
std::string name,
|
||||||
|
|
||||||
// Optional region name for exterior cells.
|
// Optional region name for exterior and quasi-exterior cells.
|
||||||
region;
|
region;
|
||||||
|
|
||||||
// File position
|
ESM_Context context; // File position
|
||||||
ESM_Context context;
|
|
||||||
|
|
||||||
DATAstruct data;
|
DATAstruct data;
|
||||||
|
AMBIstruct ambi;
|
||||||
|
int water; // Water level
|
||||||
|
int mapColor;
|
||||||
|
|
||||||
void load(ESMReader &esm)
|
void load(ESMReader &esm)
|
||||||
{
|
{
|
||||||
// This is implicit?
|
|
||||||
//name = esm.getHNString("NAME");
|
|
||||||
|
|
||||||
// Ignore this for now, it might mean we should delete the entire
|
// Ignore this for now, it might mean we should delete the entire
|
||||||
// cell?
|
// cell?
|
||||||
if(esm.isNextSub("DELE")) esm.skipHSub();
|
if(esm.isNextSub("DELE")) esm.skipHSub();
|
||||||
|
|
||||||
esm.getHNT(data, "DATA", 12);
|
esm.getHNT(data, "DATA", 12);
|
||||||
region = esm.getHNOString("RGNN");
|
|
||||||
|
|
||||||
// Save position and move on
|
// Water level
|
||||||
|
water = 0;
|
||||||
|
|
||||||
|
if(data.flags & Interior)
|
||||||
|
{
|
||||||
|
// Interior cells
|
||||||
|
|
||||||
|
if(esm.isNextSub("INTV") || esm.isNextSub("WHGT"))
|
||||||
|
esm.getHT(water);
|
||||||
|
|
||||||
|
// Quasi-exterior cells have a region (which determines the
|
||||||
|
// weather), pure interior cells have ambient lighting
|
||||||
|
// instead.
|
||||||
|
if(data.flags & QuasiEx)
|
||||||
|
region = esm.getHNOString("RGNN");
|
||||||
|
else
|
||||||
|
esm.getHNT(ambi, "AMBI", 16);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Exterior cells
|
||||||
|
region = esm.getHNOString("RGNN");
|
||||||
|
esm.getHNOT(mapColor, "NAM5");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save position of the cell references and move on
|
||||||
context = esm.getContext();
|
context = esm.getContext();
|
||||||
esm.skipRecord();
|
esm.skipRecord();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Restore the given reader to the stored position. Will try to open
|
||||||
|
// the file matching the stored file name. If you want to read from
|
||||||
|
// somewhere other than the file system, you need to pre-open the
|
||||||
|
// ESMReader, and the filename must match the stored filename
|
||||||
|
// exactly.
|
||||||
|
void restore(ESMReader &esm)
|
||||||
|
{ esm.restoreContext(context); }
|
||||||
|
|
||||||
|
// Get the next reference in this cell, if any. Returns false when
|
||||||
|
// there are no more references in the cell.
|
||||||
|
bool getNextRef(ESMReader &esm, CellRef &ref)
|
||||||
|
{
|
||||||
|
if(!esm.hasMoreSubs()) return false;
|
||||||
|
|
||||||
|
// Number of references in the cell? Maximum once in each cell,
|
||||||
|
// but not always at the beginning, and not always right. In other
|
||||||
|
// words, completely useless.
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
esm.getHNOT(i, "NAM0");
|
||||||
|
}
|
||||||
|
|
||||||
|
esm.getHNT(ref.refnum, "FRMR");
|
||||||
|
ref.refID = esm.getHNString("NAME");
|
||||||
|
|
||||||
|
// getHNOT will not change the existing value (1.0) if the
|
||||||
|
// subrecord is missing
|
||||||
|
ref.scale = 1.0;
|
||||||
|
esm.getHNOT(ref.scale, "XSCL");
|
||||||
|
|
||||||
|
ref.owner = esm.getHNOString("ANAM");
|
||||||
|
ref.glob = esm.getHNOString("BNAM");
|
||||||
|
ref.soul = esm.getHNOString("XSOL");
|
||||||
|
|
||||||
|
ref.faction = esm.getHNOString("CNAM");
|
||||||
|
esm.getHNOT(ref.factIndex, "INDX");
|
||||||
|
|
||||||
|
ref.charge = 0.0;
|
||||||
|
esm.getHNOT(ref.charge, "XCHG");
|
||||||
|
|
||||||
|
ref.intv = 0;
|
||||||
|
ref.nam9 = 0;
|
||||||
|
esm.getHNOT(ref.intv, "INTV");
|
||||||
|
esm.getHNOT(ref.nam9, "NAM9");
|
||||||
|
|
||||||
|
// Present for doors that teleport you to another cell.
|
||||||
|
if(esm.isNextSub("DODT"))
|
||||||
|
{
|
||||||
|
ref.teleport = true;
|
||||||
|
esm.getHT(ref.doorDest);
|
||||||
|
ref.destCell = esm.getHNOString("DNAM");
|
||||||
|
}
|
||||||
|
else ref.teleport = false;
|
||||||
|
|
||||||
|
esm.getHNOT(ref.lockLevel, "FLTV"); // int, despite the name
|
||||||
|
ref.key = esm.getHNOString("KNAM");
|
||||||
|
ref.trap = esm.getHNOString("TNAM");
|
||||||
|
|
||||||
|
ref.unam = 0;
|
||||||
|
ref.fltv = 0;
|
||||||
|
esm.getHNOT(ref.unam, "UNAM");
|
||||||
|
esm.getHNOT(ref.fltv, "FLTV");
|
||||||
|
|
||||||
|
esm.getHNT(ref.pos, "DATA", 24);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue