forked from mirror/openmw-tes3mp
Ported CREA, LTEX, MGEF, NPCC, REGN and SCPT. Only the big ones left.
parent
bd71031206
commit
7b42ba6e20
@ -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
|
@ -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
|
@ -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…
Reference in New Issue