Ported CREA, LTEX, MGEF, NPCC, REGN and SCPT. Only the big ones left.

actorid
Nicolay Korslund 15 years ago
parent bd71031206
commit 7b42ba6e20

@ -16,6 +16,12 @@
namespace ESM {
enum Version
{
VER_12 = 0x3f99999a,
VER_13 = 0x3fa66666
};
/* 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.
@ -97,12 +103,6 @@ public:
typedef std::vector<MasterData> MasterList;
enum Version
{
VER_12 = 0x3f99999a,
VER_13 = 0x3fa66666
};
enum FileType
{
FT_ESP = 0, // Plugin
@ -252,6 +252,14 @@ public:
getHT(x);
}
// Optional version of getHNT
template <typename X>
void getHNOT(X &x, const char* name)
{
if(isNextSub(name))
getHT(x);
}
// Version with extra size checking, to make sure the compiler
// doesn't mess up our struct padding.
template <typename X>
@ -325,6 +333,22 @@ public:
return getString(leftSub);
}
// Read the given number of bytes from a subrecord
void getHExact(void*p, int size)
{
getSubHeader();
if(size != leftSub)
fail("getHExact() size mismatch");
getExact(p,size);
}
// Read the given number of bytes from a named subrecord
void getHNExact(void*p, int size, const char* name)
{
getSubNameIs(name);
getHExact(p,size);
}
/*************************************************************************
*
* Low level sub-record methods

@ -0,0 +1,98 @@
#ifndef _ESM_CREA_H
#define _ESM_CREA_H
#include "esm_reader.hpp"
#include "loadcont.hpp"
namespace ESM {
/*
* Creature definition
*
*/
struct Creature
{
// Default is 0x48?
enum Flags
{
Biped = 0x001,
Respawn = 0x002,
Weapon = 0x004, // Has weapon and shield
None = 0x008, // ??
Swims = 0x010,
Flies = 0x020, // Don't know what happens if several
Walks = 0x040, // of these are set
Essential = 0x080,
Skeleton = 0x400, // Does not have normal blood
Metal = 0x800 // Has 'golden' blood
};
enum Type
{
Creatures = 0,
Deadra = 1,
Undead = 2,
Humanoid = 3
};
struct NPDTstruct
{
int type;
// For creatures we obviously have to use ints, not shorts and
// bytes like we use for NPCs.... this file format just makes so
// much sense! (Still, _much_ easier to decode than the NIFs.)
int level;
int strength, intelligence, willpower, agility, speed, endurance,
personality, luck, health, mana, fatigue; // Stats
int soul; // The creatures soul value (used with soul gems.)
int combat, magic, stealth; // Don't know yet.
int attack[6]; // AttackMin1, AttackMax1, ditto2, ditto3
int gold;
}; // 96 bytes
NPDTstruct data;
int flags;
float scale;
std::string model, name, script,
original; // Base creature that this is a modification of
// Defined in loadcont.hpp
InventoryList inventory;
void load(ESMReader &esm)
{
model = esm.getHNString("MODL");
original = esm.getHNOString("CNAM");
name = esm.getHNOString("FNAM");
script = esm.getHNOString("SCRI");
esm.getHNT(data, "NPDT", 96);
esm.getHNT(flags, "FLAG");
esm.getHNOT(scale, "XSCL");
inventory.load(esm);
// More subrecords:
// AIDT - data (12 bytes, unknown)
// AI_W - wander (14 bytes, i don't understand it)
// short distance
// byte duration
// byte timeOfDay
// byte idle[10]
//
// Rest is optional:
// AI_T - travel?
// AI_F - follow?
// AI_E - escort?
// AI_A - activate?
esm.skipRecord();
}
};
}
#endif

@ -0,0 +1,37 @@
#ifndef _ESM_LTEX_H
#define _ESM_LTEX_H
#include "esm_reader.hpp"
namespace ESM {
/*
* Texture used for texturing landscape.
*
* They are probably indexed by 'num', not 'id', but I don't know for
* sure. And num is not unique between files, so one option is to keep
* a separate list for each input file (that has LTEX records, of
* course.) We also need to resolve references to already existing
* land textures to save space.
* I'm not sure if it is even possible to override existing land
* textures, probably not. I'll have to try it, and have to mimic the
* behaviour of morrowind. First, check what you are allowed to do in
* the editor. Then make an esp which changes a commonly used land
* texture, and see if it affects the game.
*/
struct LandTexture
{
std::string name, texture;
int index;
void load(ESMReader &esm)
{
name = esm.getHNString("NAME");
esm.getHNT(index, "INTV");
texture = esm.getHNString("DATA");
}
};
}
#endif

@ -0,0 +1,70 @@
#ifndef _ESM_MGEF_H
#define _ESM_MGEF_H
#include "esm_reader.hpp"
namespace ESM {
struct MagicEffect
{
enum Flags
{
SpellMaking = 0x0200,
Enchanting = 0x0400,
Negative = 0x0800 // A harmful effect. Will determine whether
// eg. NPCs regard this spell as an attack.
};
struct MEDTstruct
{
int school; // SpellSchool, see defs.hpp
float baseCost;
int flags;
// Properties of the fired magic 'ball' I think
int red, blue, green;
float speed, size, sizeCap;
}; // 36 bytes
MEDTstruct data;
std::string icon, particle, // Textures
casting, hit, area, // Statics
bolt, // Weapon
castSound, boltSound,
hitSound, areaSound, // Sounds
description;
// Index of this magical effect. Corresponds to one of the
// hard-coded effects in the original engine:
// 0-136 in Morrowind
// 137 in Tribunal
// 138-140 in Bloodmoon (also changes 64?)
// 141-142 are summon effects introduced in bloodmoon, but not used
// there. They can be redefined in mods by setting the name in GMST
// sEffectSummonCreature04/05 creature id in
// sMagicCreature04ID/05ID.
int index;
void load(ESMReader &esm)
{
esm.getHNT(index, "INDX");
esm.getHNT(data, "MEDT", 36);
icon = esm.getHNOString("ITEX");
particle = esm.getHNOString("PTEX");
boltSound = esm.getHNOString("BSND");
castSound = esm.getHNOString("CSND");
hitSound = esm.getHNOString("HSND");
areaSound = esm.getHNOString("ASND");
casting = esm.getHNOString("CVFX");
bolt = esm.getHNOString("BVFX");
hit = esm.getHNOString("HVFX");
area = esm.getHNOString("AVFX");
description = esm.getHNOString("DESC");
}
};
}
#endif

@ -1,28 +1,9 @@
/*
OpenMW - The completely unofficial reimplementation of Morrowind
Copyright (C) 2008 Nicolay Korslund
Email: < korslund@gmail.com >
WWW: http://openmw.snaptoad.com/
This file (loadnpcc.d) is part of the OpenMW package.
#ifndef _ESM_NPCC_H
#define _ESM_NPCC_H
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.
#include "esm_reader.hpp"
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.loadnpcc;
import esm.imports;
namespace ESM {
/*
* NPC change information (found in savegame files only). We can't
@ -51,14 +32,14 @@ import esm.imports;
*
* FMAP - MAPH and MAPD, probably map data.
*
* JOUR - the entire bloody journal in html
* JOUR - the entire journal in html
*
* QUES - seems to contain all the quests in the game, not just the
* ones you have done or begun.
*
* REGN - lists all regions in the game, even unvisited ones.
*
* The DIAL/INFO blocks contain changes to characters dialog status.
* The DIAL/INFO blocks contain changes to characters' dialog status.
*
* Dammit there's a lot of stuff in there! Should really have
* suspected as much. The strategy further is to completely ignore
@ -91,14 +72,10 @@ import esm.imports;
struct LoadNPCC
{
void load(TES3File f)
{
writefln("NPC-changer: %s", f.getHNString("NAME"));
while(f.hasMoreSubs)
{
f.getSubName();
f.skipHSub();
}
}
void load(ESMReader &esm)
{
esm.skipRecord();
}
};
}
#endif

@ -0,0 +1,63 @@
#ifndef _ESM_REGN_H
#define _ESM_REGN_H
#include "esm_reader.hpp"
namespace ESM {
/*
* Region data
*/
struct Region
{
struct WEATstruct
{
// I guess these are probabilities
char clear, cloudy, foggy, overcast, rain, thunder, ash,
blight,
// Unknown weather, probably snow and something. Only
// present in file version 1.3.
a,b;
}; // 10 bytes
// Reference to a sound that is played randomly in this region
struct SoundRef
{
NAME32 sound;
char chance;
}; // 33 bytes
WEATstruct data;
int mapColor; // RGBA
// sleepList refers to a eveled list of creatures you can meet if
// you sleep outside in this region.
std::string name, sleepList;
std::vector<SoundRef> soundList;
void load(ESMReader &esm)
{
name = esm.getHNString("FNAM");
if(esm.getVer() == VER_12)
esm.getHNExact(&data, sizeof(data)-2, "WEAT");
else if(esm.getVer() == VER_13)
esm.getHNExact(&data, sizeof(data), "WEAT");
else esm.fail("Don't know what to do in this version");
sleepList = esm.getHNOString("BNAM");
esm.getHNT(mapColor, "CNAM");
while(esm.hasMoreSubs())
{
SoundRef sr;
esm.getHNT(sr, "SNAM", 33);
soundList.push_back(sr);
}
}
};
}
#endif

@ -0,0 +1,90 @@
#ifndef _ESM_SCPT_H
#define _ESM_SCPT_H
#include "esm_reader.hpp"
namespace ESM {
/*
* Script definitions
*/
struct Script
{
struct SCHDstruct
{
/* Script name.
NOTE: You should handle the name "Main" (case insensitive) with
care. With tribunal, modders got the ability to add 'start
scripts' to their mods, which is a script that is run at
startup and which runs throughout the game (I think.)
However, before Tribunal, there was only one startup script,
called "Main". If mods wanted to make their own start scripts,
they had to overwrite Main. This is obviously problem if
multiple mods to this at the same time.
Although most mods have switched to using Trib-style startup
scripts, some legacy mods might still overwrite Main, and this
can cause problems if several mods do it. I think the best
course of action is to NEVER overwrite main, but instead add
each with a separate unique name and add them to the start
script list. But there might be other problems with this
approach though.
*/
NAME32 name;
// These describe the sizes we need to allocate for the script
// data.
int numShorts, numLongs, numFloats,
scriptDataSize, stringTableSize;
}; // 52 bytes
SCHDstruct data;
std::vector<std::string> varNames; // Variable names
std::vector<char> scriptData; // Compiled bytecode
std::string scriptText; // Uncompiled script
void load(ESMReader &esm)
{
esm.getHNT(data, "SCHD", 52);
// List of local variables
if(esm.isNextSub("SCVR"))
{
int s = data.stringTableSize;
char* tmp = new char[s];
esm.getHExact(tmp, s);
// Set up the list of variable names
varNames.resize(data.numShorts +
data.numLongs +
data.numFloats);
// The tmp buffer is a null-byte separated string list, we
// just have to pick out one string at a time.
char* str = tmp;
for(int i=0; i< varNames.size(); i++)
{
varNames[i] = std::string(str);
str += varNames[i].size()+1;
if(str - tmp > s)
esm.fail("String table overflow");
}
delete[] tmp;
}
// Script data
scriptData.resize(data.scriptDataSize);
esm.getHNExact(&scriptData[0], scriptData.size(), "SCDT");
// Script text
scriptText = esm.getHNOString("SCTX");
}
};
}
#endif

@ -11,6 +11,7 @@
#include "loadclas.hpp"
#include "loadclot.hpp"
#include "loadcont.hpp"
#include "loadcrea.hpp"
#include "loadcrec.hpp"
#include "loaddoor.hpp"
#include "loadench.hpp"
@ -19,8 +20,13 @@
#include "loadingr.hpp"
#include "loadligh.hpp"
#include "loadlocks.hpp"
#include "loadltex.hpp"
#include "loadmgef.hpp"
#include "loadmisc.hpp"
#include "loadnpcc.hpp"
#include "loadrace.hpp"
#include "loadregn.hpp"
#include "loadscpt.hpp"
#include "loadskil.hpp"
#include "loadsndg.hpp"
#include "loadsoun.hpp"

@ -1,156 +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 (loadcrea.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.loadcrea;
import esm.imports;
import esm.loadcont;
/*
* Creature definition
*
* Container structs are in loadcont.d
*/
struct Creature
{
// Default is 0x48?
enum Flags
{
Biped = 0x001,
Respawn = 0x002,
Weapon = 0x004, // Has weapon and shield
None = 0x008, // ??
Swims = 0x010,
Flies = 0x020, // Don't know what happens if several
Walks = 0x040, // of these are set
Essential = 0x080,
Skeleton = 0x400, // Does not have normal blood
Metal = 0x800 // Has 'golden' blood
}
enum Type : int
{
Creature = 0,
Deadra = 1,
Undead = 2,
Humanoid = 3
}
align(1) struct NPDTstruct
{
Type type;
// For creatures we obviously have to use ints, not shorts and
// bytes like we use for NPCs.... this file format just makes so
// much sense! (Still, _much_ easier to decode than the NIFs.)
int level;
int strength, intelligence, willpower, agility, speed, endurance,
personality, luck, health, mana, fatigue; // Stats
int soul; // The creatures soul value (used with soul gems.)
int combat, magic, stealth; // Don't know yet.
int attack[6]; // AttackMin1, AttackMax1, ditto2, ditto3
int gold;
static assert(NPDTstruct.sizeof == 96);
}
NPDTstruct data;
Flags flags;
mixin LoadT;
MeshIndex model;
// Base creature. Any missing data must be taken from here, I quess.
Creature *original;
Script *script;
float scale;
InventoryList inventory;
void load()
{with(esFile){
model = getMesh();
original = getHNOPtr!(Creature)("CNAM", creatures);
name = getHNOString("FNAM");
script = getHNOPtr!(Script)("SCRI", scripts);
readHNExact(&data, data.sizeof, "NPDT");
flags = cast(Flags)getHNInt("FLAG");
scale = getHNOFloat("XSCL", 1.0);
inventory.load();
// AIDT - data (12 bytes, unknown)
// AI_W - wander (14 bytes, i don't understand it)
// short distance
// byte duration
// byte timeOfDay
// byte idle[10]
//
// Rest is optional:
// AI_T - travel?
// AI_F - follow?
// AI_E - escort?
// AI_A - activate?
//*
skipRecord();
//*/
makeProto();
proto.setInt("level", data.level);
proto.setInt("gold", data.gold);
proto.setInt("baseStrength", data.strength);
proto.setInt("baseIntelligence", data.intelligence);
proto.setInt("baseWillpower", data.willpower);
proto.setInt("baseAgility", data.agility);
proto.setInt("baseSpeed", data.speed);
proto.setInt("baseEndurance", data.endurance);
proto.setInt("basePersonality", data.personality);
proto.setInt("baseLuck", data.luck);
proto.setInt("baseMaxHealth", data.health);
proto.setInt("baseMaxMana", data.mana);
proto.setInt("baseMaxFatigue", data.fatigue);
proto.setInt("combat", data.combat);
proto.setInt("magic", data.magic);
proto.setInt("stealth", data.stealth);
proto.setInt("soul", data.soul);
proto.setInt("attackMin1", data.attack[0]);
proto.setInt("attackMax1", data.attack[1]);
proto.setInt("attackMin2", data.attack[2]);
proto.setInt("attackMax2", data.attack[3]);
proto.setInt("attackMin3", data.attack[4]);
proto.setInt("attackMax3", data.attack[5]);
}}
}
ListID!(Creature) creatures;

@ -1,103 +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 (loadltex.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.loadltex;
import esm.imports;
/*
* Texture used for texturing landscape?
*
* Not sure how to store these yet. They are probably indexed by
* 'num', not 'id', but I don't know for sure. And num is not unique
* between files, so one option is to keep a separate list for each
* input file (that has LTEX records, of course.) We also need to
* resolve references to already existing land textures to save space.
* I'm not sure if it is even possible to override existing land
* textures, probably not. I'll have to try it, and have to mimic the
* behaviour of morrowind. First, check what you are allowed to do in
* the editor. Then make an esp which changes a commonly used land
* texture, and see if it affects the game.
*/
class LandTextureList : ListKeeper
{
// Number of textures inserted in this file.
int num;
alias RegionBuffer!(TextureIndex) TextureList;
// Contains the list of land textures for each file, indexed by
// file. TODO: Use some handle system here too instead of raw
// filename?
HashTable!(char[], TextureList, ESMRegionAlloc, CITextHash) files;
// The texture list for the current file
TextureList current;
this()
{
num = 0;
endFile();
// The first file (Morrowind.esm) typically needs a little more
// than most others
current = esmRegion.getBuffer!(TextureIndex)(0,120);
}
void load()
{with(esFile){
getHNString("NAME");
int n = getHNInt("INTV");
if(n != num++)
{
//writefln("Warning: Wanted land texture %d, got %d", num-1, n);
current.length = n;
num = n+1;
}
current ~= resources.lookupTexture(getHNString("DATA"));
}}
void endFile()
{
if(num)
{
files[esFile.getFilename()] = current;
current = esmRegion.getBuffer!(TextureIndex)(0,50);
num = 0;
}
}
uint length() { return files.length; }
void* lookup(char[] s) { assert(0); }
// This requires the correct file to be open
TextureIndex lookup(int index)
{
return files[esFile.getFilename()][index];
}
}
LandTextureList landTextures;

@ -1,114 +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 (loadmgef.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.loadmgef;
import esm.imports;
import esm.loadweap;
import esm.loadstat;
struct MagicEffect
{
enum Flags : int
{
SpellMaking = 0x0200,
Enchanting = 0x0400,
Negative = 0x0800 // A harmful effect
}
align(1) struct MEDTstruct
{
SpellSchool school;
float baseCost;
Flags flags;
int red, blue, green;
float speed, size, sizeCap; // Noe clue
static assert(MEDTstruct.sizeof == 36);
}
MEDTstruct data;
IconIndex icon;
TextureIndex particle;
Static* casting, hit, area;
Weapon* bolt;
Sound* castSound, boltSound, hitSound, areaSound;
char[] description;
int index;
void load()
{with(esFile){
readHNExact(&data, data.sizeof,"MEDT");
icon = getOIcon();
particle = getOTexture("PTEX");
boltSound = getHNOPtr!(Sound)("BSND", sounds);
castSound = getHNOPtr!(Sound)("CSND", sounds);
hitSound = getHNOPtr!(Sound)("HSND", sounds);
areaSound = getHNOPtr!(Sound)("ASND", sounds);
casting = getHNOPtr!(Static)("CVFX", statics);
bolt = getHNOPtr!(Weapon)("BVFX", weapons);
hit = getHNOPtr!(Static)("HVFX", statics);
area = getHNOPtr!(Static)("AVFX", statics);
description = getHNOString("DESC");
}}
}
class MagicEffectList : ListKeeper
{
// 0-136 in Morrowind
// 137 in Tribunal
// 138-140 in Bloodmoon (also changes 64?)
// 141-142 are summon effects introduced in bloodmoon, but not used
// there. They can be redefined in mods by setting the name in GMST
// sEffectSummonCreature04/05 creature id in
// sMagicCreature04ID/05ID.
MagicEffect[143] list;
override:
void load()
{
int index = esFile.getHNInt("INDX");
if(index < 0 || index >= list.length)
esFile.fail("Invalid magic effect number " ~ .toString(index));
list[index].load();
}
void endFile() {}
uint length() { return list.length; }
void* lookup(char[] s) { assert(0); }
}
MagicEffectList effects;

@ -1,113 +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 (loadregn.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.loadregn;
import esm.imports;
import esm.loadlevlist;
/*
* Region data
*/
struct Region
{
align(1) struct WEATstruct
{
byte clear, // Don't know if these are probabilities or what.
cloudy,
foggy,
overcast,
rain,
thunder,
ash,
blight,
a,b;// Unknown weather, probably snow and something. Only
// present in file version 1.3.
}
static assert(WEATstruct.sizeof==10);
LoadState state;
char[] id, name;
WEATstruct data;
Color mapColor;
// Leveled list of creatures you can meet if you sleep outside in
// this region.
LeveledCreatures *sleepList;
// Sounds that are played randomly when you are in this region
struct SoundRef{ Sound* sound; ubyte chance; }
RegionBuffer!(SoundRef) soundList;
void load()
{with(esFile){
name = getHNString("FNAM");
if(isVer12())
readHNExact(&data, data.sizeof-2, "WEAT");
else if(isVer13())
readHNExact(&data, data.sizeof, "WEAT");
else fail("Don't know what to do in this version");
// TODO: Calculate weather probabilities here? Or sum them, or
// whatever?
sleepList = getHNOPtr!(LeveledCreatures)("BNAM", creatureLists);
/*
if(getFileType == FileType.Savegame)
{
// Probably says which weather condition this region is
// currently experiencing.
writefln("WNAM: ", getHNInt("WNAM"));
return
}
*/
readHNExact(&mapColor, mapColor.sizeof, "CNAM");
soundList = esmRegion.getBuffer!(SoundRef)(0,20);
while(isNextSub("SNAM"))
{
char[32] buffer;
getSubHeaderIs(33);
soundList.length = soundList.length + 1;
with(soundList.array[$-1])
{
// Get and chop sound name
sound = cast(Sound*) sounds.lookup(getString(buffer));
// Get sound probability
getUByte(chance);
}
}
}}
}
ListID!(Region) regions;

@ -1,140 +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 (loadscpt.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.loadscpt;
import esm.imports;
//private import std.string;
/*
* Script
*/
struct Script
{
char[] id;
LoadState state;
uint numShorts, numLongs, numFloats;
char[][] localVars;
ubyte[] scriptData;
char[] scriptText;
uint scriptDataSize, localVarSize;
void load()
{with(esFile){
/* Assume start of the header has already been read
getSubNameIs("SCHD");
getSubHeaderIs(52);
id = getString(32);
*/
getUint(numShorts);
getUint(numLongs);
getUint(numFloats);
getUint(scriptDataSize);
getUint(localVarSize);
/* // In save games this is all that follows the header
if(getFileType == FileType.Ess)
{
getSubNameIs("SLCS");
skipHSubSize(12);
if(isNextSub("SLSD"))
skipHSub();
if(isNextSub("SLFD"))
skipHSub();
if(isNextSub("RNAM"))
skipHSubSize(4);
return;
}//*/
// List of local variables
if(isNextSub("SCVR"))
{
char[] tmp = getRegion().getString(localVarSize);
readHExact(tmp.ptr, tmp.length);
// At this point we can't use GC allocations at all, since
// our references are not in a root area. Thus the data
// could be collected while still in use.
localVars = getRegion().allocateT!(char[])
( numShorts + numLongs + numFloats );
// The tmp buffer is a null-byte separated string list, we
// just have to pick out one string at a time.
foreach(ref char[] result; localVars)
{
result = stripz(tmp);
tmp = tmp[result.length+1..$];
}
if(tmp.length) fail("Variable table size mismatch");
}
else localVars = null;
// Script data
scriptData = getRegion().allocate(scriptDataSize);
readHNExact(scriptData.ptr, scriptData.length, "SCDT");
// Script text
scriptText = getHNOString("SCTX");
}}
}
class ScriptList : ListID!(Script)
{
this(uint s) { super(s); }
override char[] getID()
{
// Script header
esFile.getSubNameIs("SCHD");
esFile.getSubHeaderIs(52);
char[] id = esFile.getString(32);
// TODO: Handle multiple Main scripts here. With tribunal,
// modders got the ability to add 'start scripts' to their mods,
// which is a script that is run at startup (I think.) Before
// that, there was only one startup script, called
// "Main". Although most mods have switched to using startup
// scripts, some legacy mods might still overwrite Main, and
// this can cause problems if several mods do it. I think the
// best course of action is to NEVER overwrite main, but instead
// add each with a separate unique name and add them to the
// start script list.
if(esFile.getSpecial() != SpecialFile.Morrowind && icmp(id,"Main")==0)
writefln("Found MAIN script in %s ", esFile.getFilename());
return id;
}
}
ScriptList scripts;
Loading…
Cancel
Save