forked from mirror/openmw-tes3mp
Finished GMST
This commit is contained in:
parent
7b42ba6e20
commit
35ddfcfbf5
4 changed files with 269 additions and 331 deletions
|
@ -22,6 +22,24 @@ enum Version
|
||||||
VER_13 = 0x3fa66666
|
VER_13 = 0x3fa66666
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum FileType
|
||||||
|
{
|
||||||
|
FT_ESP = 0, // Plugin
|
||||||
|
FT_ESM = 1, // Master
|
||||||
|
FT_ESS = 32 // Savegame
|
||||||
|
};
|
||||||
|
|
||||||
|
// Used to mark special files. The original ESM files are given
|
||||||
|
// special treatment in a few places, most noticably in loading and
|
||||||
|
// filtering out "dirtly" GMST entries correctly.
|
||||||
|
enum SpecialFile
|
||||||
|
{
|
||||||
|
SF_Other,
|
||||||
|
SF_Morrowind,
|
||||||
|
SF_Tribunal,
|
||||||
|
SF_Bloodmoon
|
||||||
|
};
|
||||||
|
|
||||||
/* A structure used for holding fixed-length strings. In the case of
|
/* 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
|
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.
|
number, therefore the struct is implemented as a union with an int.
|
||||||
|
@ -103,24 +121,6 @@ public:
|
||||||
|
|
||||||
typedef std::vector<MasterData> MasterList;
|
typedef std::vector<MasterData> MasterList;
|
||||||
|
|
||||||
enum FileType
|
|
||||||
{
|
|
||||||
FT_ESP = 0, // Plugin
|
|
||||||
FT_ESM = 1, // Master
|
|
||||||
FT_ESS = 32 // Savegame
|
|
||||||
};
|
|
||||||
|
|
||||||
// Used to mark special files. The original ESM files are given
|
|
||||||
// special treatment in a few places, most noticably in loading and
|
|
||||||
// filtering out "dirtly" GMST entries correctly.
|
|
||||||
enum SpecialFile
|
|
||||||
{
|
|
||||||
SF_Other,
|
|
||||||
SF_Morrowind,
|
|
||||||
SF_Tribunal,
|
|
||||||
SF_Bloodmoon
|
|
||||||
};
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
*
|
*
|
||||||
* Information retrieval
|
* Information retrieval
|
||||||
|
|
248
esm/loadgmst.hpp
Normal file
248
esm/loadgmst.hpp
Normal file
|
@ -0,0 +1,248 @@
|
||||||
|
#ifndef _ESM_GMST_H
|
||||||
|
#define _ESM_GMST_H
|
||||||
|
|
||||||
|
#include "esm_reader.hpp"
|
||||||
|
#include "defs.hpp"
|
||||||
|
|
||||||
|
namespace ESM {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Game setting, with automatic cleaning of "dirty" entries.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct GameSetting
|
||||||
|
{
|
||||||
|
std::string id;
|
||||||
|
|
||||||
|
// One of these is used depending on the variable type
|
||||||
|
std::string str;
|
||||||
|
int i;
|
||||||
|
float f;
|
||||||
|
VarType type;
|
||||||
|
|
||||||
|
// Set to true if this is a 'dirty' entry which should be ignored
|
||||||
|
bool dirty;
|
||||||
|
|
||||||
|
/*
|
||||||
|
These functions check if this game setting is one of the "dirty"
|
||||||
|
GMST records found in many mods. These are due to a serious bug in
|
||||||
|
the official TES3 editor. It only occurs in the newer editor
|
||||||
|
versions that came with Tribunal and Bloodmoon, and only if a
|
||||||
|
modder tries to make a mod without loading the corresponding
|
||||||
|
expansion master file. For example, if you have Tribunal installed
|
||||||
|
and try to make a mod without loading Tribunal.esm, the editor
|
||||||
|
will insert these GMST records as a replacement for the entries it
|
||||||
|
cannot find in the ESMs.
|
||||||
|
|
||||||
|
The values of these "dirty" records differ in general from their
|
||||||
|
values as defined in Tribunal.esm and Bloodmoon.esm, and are
|
||||||
|
always set to the same "default" values. Most of these values are
|
||||||
|
nonsensical, ie. changing the "Seller Max" string to "Max Sale",
|
||||||
|
or change the stats of werewolves to useless values like 1. Some
|
||||||
|
of them break certain spell effects.
|
||||||
|
|
||||||
|
It is most likely that these values are just leftover values from
|
||||||
|
an early stage of development that are inserted as default values
|
||||||
|
by the editor code. They are supposed to be overridden when the
|
||||||
|
correct esm file is loaded. When it isn't loaded however, you get
|
||||||
|
stuck with the initial value, and this gets written to every mod
|
||||||
|
by the editor, for some reason.
|
||||||
|
|
||||||
|
Bethesda themselves have fallen for this bug. If you install both
|
||||||
|
Tribunal and Bloodmoon, the updated Tribunal.esm will contain the
|
||||||
|
dirty GMST settings from Bloodmoon, and Bloodmoon.esm will contain
|
||||||
|
some of the dirty settings from Tribunal. In other words, this bug
|
||||||
|
affects the game EVEN IF YOU DO NOT USE ANY MODS!
|
||||||
|
|
||||||
|
The guys at Bethesda are well aware of this bug (and many others),
|
||||||
|
as the mod community and fan base complained about them for a long
|
||||||
|
time. But unfortunately it was never fixed.
|
||||||
|
|
||||||
|
There are several tools available to help modders remove these
|
||||||
|
records from their files, but not all modders use them, and they
|
||||||
|
really shouldn't have to. In this file we choose instead to reject
|
||||||
|
all the corrupt values at load time.
|
||||||
|
|
||||||
|
These functions checks if the current game setting is one of the
|
||||||
|
"dirty" ones as described above. TODO: I have not checked this
|
||||||
|
against other sources yet, do that later. Currently recognizes 22
|
||||||
|
values for tribunal and 50 for bloodmoon. Legitimate GMSTs in mods
|
||||||
|
(setting values other than the default "dirty" ones) are not
|
||||||
|
affected and will work correctly.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Some handy macros
|
||||||
|
#define cI(s,x) { if(id == (s)) return (i == (x)); }
|
||||||
|
#define cF(s,x) { if(id == (s)) return (f == (x)); }
|
||||||
|
#define cS(s,x) { if(id == (s)) return (str == (x)); }
|
||||||
|
|
||||||
|
/*
|
||||||
|
Checks for dirty tribunal values. These will be ignored if found
|
||||||
|
in any file except when they are found in "Tribunal.esm".
|
||||||
|
*/
|
||||||
|
bool isDirtyTribunal()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Here, id contains the game setting name, and we check the
|
||||||
|
setting for certain values. If it matches, this is a "dirty"
|
||||||
|
entry. The correct entry (as defined in Tribunal and Bloodmoon
|
||||||
|
esms) are given in the comments. Many of the values are correct,
|
||||||
|
and are marked as 'same'. We still ignore them though, as they
|
||||||
|
are still in the wrong file and might override custom values
|
||||||
|
from other mods.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Strings
|
||||||
|
cS("sProfitValue", "Profit Value"); // 'Profit:'
|
||||||
|
cS("sEditNote", "Edit Note"); // same
|
||||||
|
cS("sDeleteNote", "Delete Note?"); // same
|
||||||
|
cS("sMaxSale", "Max Sale"); // 'Seller Max'
|
||||||
|
cS("sMagicFabricantID", "Fabricant"); // 'Fabricant_summon'
|
||||||
|
cS("sTeleportDisabled",
|
||||||
|
"Teleportation magic does not work here.");// same
|
||||||
|
cS("sLevitateDisabled",
|
||||||
|
"Levitation magic does not work here."); // same
|
||||||
|
cS("sCompanionShare", "Companion Share"); // 'Share'
|
||||||
|
cS("sCompanionWarningButtonOne",
|
||||||
|
"Let the mercenary quit."); // same
|
||||||
|
cS("sCompanionWarningButtonTwo",
|
||||||
|
"Return to Companion Share display."); // same
|
||||||
|
cS("sCompanionWarningMessage",
|
||||||
|
"Your mercenary is poorer now than when he contracted with you. Your mercenary will quit if you do not give him gold or goods to bring his Profit Value to a positive value.");
|
||||||
|
// 'Your mercenary is poorer now than when he contracted with
|
||||||
|
// you. Your mercenary will quit if you do not give him gold
|
||||||
|
// or goods to bring his Profit to a positive value.'
|
||||||
|
// [The difference here is "Profit Value" -> "Profit"]
|
||||||
|
|
||||||
|
// Strings that matches the id
|
||||||
|
cS("sEffectSummonFabricant", id);// 'Summon Fabricant'
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bloodmoon variant
|
||||||
|
bool isDirtyBloodmoon()
|
||||||
|
{
|
||||||
|
// Strings
|
||||||
|
cS("sWerewolfPopup", "Werewolf"); // same
|
||||||
|
cS("sWerewolfRestMessage",
|
||||||
|
"You cannot rest in werewolf form."); // same
|
||||||
|
cS("sWerewolfRefusal",
|
||||||
|
"You cannot do this as a werewolf."); // same
|
||||||
|
cS("sWerewolfAlarmMessage",
|
||||||
|
"You have been detected changing from a werewolf state.");
|
||||||
|
// 'You have been detected as a known werewolf.'
|
||||||
|
|
||||||
|
// Strings that matches the id
|
||||||
|
cS("sMagicCreature01ID", id); // 'BM_wolf_grey_summon'
|
||||||
|
cS("sMagicCreature02ID", id); // 'BM_bear_black_summon'
|
||||||
|
cS("sMagicCreature03ID", id); // 'BM_wolf_bone_summon'
|
||||||
|
cS("sMagicCreature04ID", id); // same
|
||||||
|
cS("sMagicCreature05ID", id); // same
|
||||||
|
cS("sEffectSummonCreature01", id); // 'Calf Wolf'
|
||||||
|
cS("sEffectSummonCreature02", id); // 'Calf Bear'
|
||||||
|
cS("sEffectSummonCreature03", id); // 'Summon Bonewolf'
|
||||||
|
cS("sEffectSummonCreature04", id); // same
|
||||||
|
cS("sEffectSummonCreature05", id); // same
|
||||||
|
|
||||||
|
// Integers
|
||||||
|
cI("iWereWolfBounty", 10000); // 1000
|
||||||
|
cI("iWereWolfFightMod", 100); // same
|
||||||
|
cI("iWereWolfFleeMod", 100); // same
|
||||||
|
cI("iWereWolfLevelToAttack", 20); // same
|
||||||
|
|
||||||
|
// Floats
|
||||||
|
cF("fFleeDistance", 3000); // same
|
||||||
|
cF("fCombatDistanceWerewolfMod", 0.3); // same
|
||||||
|
cF("fWereWolfFatigue", 400); // same
|
||||||
|
cF("fWereWolfEnchant", 1); // 0
|
||||||
|
cF("fWereWolfArmorer", 1); // 0
|
||||||
|
cF("fWereWolfBlock", 1); // 0
|
||||||
|
cF("fWereWolfSneak", 1); // 95
|
||||||
|
cF("fWereWolfDestruction", 1); // 0
|
||||||
|
cF("fWereWolfEndurance", 150); // same
|
||||||
|
cF("fWereWolfConjuration", 1); // 0
|
||||||
|
cF("fWereWolfRestoration", 1); // 0
|
||||||
|
cF("fWereWolfAthletics", 150); // 50
|
||||||
|
cF("fWereWolfLuck", 1); // 25
|
||||||
|
cF("fWereWolfSilverWeaponDamageMult", 1.5); // 2
|
||||||
|
cF("fWereWolfMediumArmor", 1); // 0
|
||||||
|
cF("fWereWolfShortBlade", 1); // 0
|
||||||
|
cF("fWereWolfAcrobatics", 150); // 80
|
||||||
|
cF("fWereWolfSpeechcraft", 1); // 0
|
||||||
|
cF("fWereWolfAlteration", 1); // 0
|
||||||
|
cF("fWereWolfIllusion", 1); // 0
|
||||||
|
cF("fWereWolfLongBlade", 1); // 0
|
||||||
|
cF("fWereWolfMarksman", 1); // 0
|
||||||
|
cF("fWereWolfHandtoHand", 100); // same
|
||||||
|
cF("fWereWolfIntellegence", 1); // 0
|
||||||
|
cF("fWereWolfAlchemy", 1); // 0
|
||||||
|
cF("fWereWolfUnarmored", 100); // same
|
||||||
|
cF("fWereWolfAxe", 1); // 0
|
||||||
|
cF("fWereWolfRunMult", 1.5); // 1.3
|
||||||
|
cF("fWereWolfMagicka", 100); // same
|
||||||
|
cF("fWereWolfAgility", 150); // same
|
||||||
|
cF("fWereWolfBluntWeapon", 1); // 0
|
||||||
|
cF("fWereWolfSecurity", 1); // 0
|
||||||
|
cF("fWereWolfPersonality", 1); // 0
|
||||||
|
cF("fWereWolfMerchantile", 1); // 0
|
||||||
|
cF("fWereWolfHeavyArmor", 1); // 0
|
||||||
|
cF("fWereWolfSpear", 1); // 0
|
||||||
|
cF("fWereWolfStrength", 150); // same
|
||||||
|
cF("fWereWolfHealth", 2); // same
|
||||||
|
cF("fWereWolfMysticism", 1); // 0
|
||||||
|
cF("fWereWolfLightArmor", 1); // 0
|
||||||
|
cF("fWereWolfWillPower", 1); // 0
|
||||||
|
cF("fWereWolfSpeed", 150); // 90
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef cI
|
||||||
|
#undef cF
|
||||||
|
#undef cS
|
||||||
|
|
||||||
|
void load(ESMReader &esm)
|
||||||
|
{
|
||||||
|
dirty = false;
|
||||||
|
|
||||||
|
// We are apparently allowed to be empty
|
||||||
|
if(!esm.hasMoreSubs())
|
||||||
|
{
|
||||||
|
type = VT_None;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load some data
|
||||||
|
esm.getSubName();
|
||||||
|
NAME n = esm.retSubName();
|
||||||
|
if(n == "STRV")
|
||||||
|
{
|
||||||
|
str = esm.getHString();
|
||||||
|
type = VT_String;
|
||||||
|
}
|
||||||
|
else if(n == "INTV")
|
||||||
|
{
|
||||||
|
esm.getHT(i);
|
||||||
|
type = VT_Int;
|
||||||
|
}
|
||||||
|
else if(n == "FLTV")
|
||||||
|
{
|
||||||
|
esm.getHT(f);
|
||||||
|
type = VT_Float;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
esm.fail("Unwanted subrecord type");
|
||||||
|
|
||||||
|
int spf = esm.getSpecial();
|
||||||
|
|
||||||
|
// Check if this is one of the dirty values mentioned above. If it
|
||||||
|
// is, we set the dirty flag. This will ONLY work if you've set
|
||||||
|
// the 'id' string correctly before calling load().
|
||||||
|
|
||||||
|
if( ( spf != SF_Tribunal && isDirtyTribunal() ) ||
|
||||||
|
( spf != SF_Bloodmoon && isDirtyBloodmoon() ) )
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -17,6 +17,7 @@
|
||||||
#include "loadench.hpp"
|
#include "loadench.hpp"
|
||||||
#include "loadfact.hpp"
|
#include "loadfact.hpp"
|
||||||
#include "loadglob.hpp"
|
#include "loadglob.hpp"
|
||||||
|
#include "loadgmst.hpp"
|
||||||
#include "loadingr.hpp"
|
#include "loadingr.hpp"
|
||||||
#include "loadligh.hpp"
|
#include "loadligh.hpp"
|
||||||
#include "loadlocks.hpp"
|
#include "loadlocks.hpp"
|
||||||
|
@ -62,6 +63,7 @@ enum RecNameInts
|
||||||
REC_GMST = 0x54534d47,
|
REC_GMST = 0x54534d47,
|
||||||
REC_INFO = 0x4f464e49,
|
REC_INFO = 0x4f464e49,
|
||||||
REC_INGR = 0x52474e49,
|
REC_INGR = 0x52474e49,
|
||||||
|
REC_LAND = 0x0,
|
||||||
REC_LEVC = 0x4356454c,
|
REC_LEVC = 0x4356454c,
|
||||||
REC_LEVI = 0x4956454c,
|
REC_LEVI = 0x4956454c,
|
||||||
REC_LIGH = 0x4847494c,
|
REC_LIGH = 0x4847494c,
|
||||||
|
@ -71,6 +73,7 @@ enum RecNameInts
|
||||||
REC_MISC = 0x4353494d,
|
REC_MISC = 0x4353494d,
|
||||||
REC_NPC_ = 0x5f43504e,
|
REC_NPC_ = 0x5f43504e,
|
||||||
REC_NPCC = 0x4343504e,
|
REC_NPCC = 0x4343504e,
|
||||||
|
REC_PGRC = 0x0,
|
||||||
REC_PROB = 0x424f5250,
|
REC_PROB = 0x424f5250,
|
||||||
REC_RACE = 0x45434152,
|
REC_RACE = 0x45434152,
|
||||||
REC_REGN = 0x4e474552,
|
REC_REGN = 0x4e474552,
|
||||||
|
|
|
@ -1,313 +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 (loadgmst.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.loadgmst;
|
|
||||||
import esm.imports;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Game setting
|
|
||||||
*/
|
|
||||||
|
|
||||||
// TODO: It's likely that we don't need this struct any longer, given
|
|
||||||
// that game settings are now stored in Monster code. We will still
|
|
||||||
// use the loading code and the dirty value cleaning code of course,
|
|
||||||
// but there's no longer any need to store it in a separate lookup
|
|
||||||
// list, since Monster variables can be looked up just as fast.
|
|
||||||
struct GameSetting
|
|
||||||
{
|
|
||||||
LoadState state;
|
|
||||||
char[] id;
|
|
||||||
|
|
||||||
union
|
|
||||||
{
|
|
||||||
char[] str;
|
|
||||||
int i;
|
|
||||||
float f;
|
|
||||||
}
|
|
||||||
VarType type;
|
|
||||||
|
|
||||||
// These functions check if this game setting is one of the "dirty"
|
|
||||||
// GMST records found in many mods. These are due to a serious bug
|
|
||||||
// in the official TES3 editor. It only occurs in the newer editor
|
|
||||||
// versions that came with Tribunal and Bloodmoon, and only if a
|
|
||||||
// modder tries to make a mod without loading the corresponding
|
|
||||||
// expansion master file. For example, if you have Tribunal
|
|
||||||
// installed and try to make a mod without loading Tribunal.esm, the
|
|
||||||
// editor will insert these GMST records.
|
|
||||||
|
|
||||||
// The values of these "dirty" records differ in general from their
|
|
||||||
// values as defined in Tribunal.esm and Bloodmoon.esm, and are
|
|
||||||
// always set to the same "default" values. Most of these values are
|
|
||||||
// nonsensical, ie. changing the "Seller Max" string to "Max Sale",
|
|
||||||
// or change the stats of werewolves to useless values like 1. Some
|
|
||||||
// of them break certain spell effects.
|
|
||||||
|
|
||||||
// It is most likely that these values are just leftover values from
|
|
||||||
// an early stage of development that are inserted as default values
|
|
||||||
// by the editor code. They are supposed to be overridden when the
|
|
||||||
// correct esm file is loaded. When it isn't loaded, you get stuck
|
|
||||||
// with the initial value, and this gets written to every mod for
|
|
||||||
// some reason.
|
|
||||||
|
|
||||||
// Bethesda themselves have fallen for this bug. If you install both
|
|
||||||
// Tribunal and Bloodmoon, the updated Tribunal.esm will contain the
|
|
||||||
// dirty GMST settings from Bloodmoon, and Bloodmoon.esm will
|
|
||||||
// contain some of the dirty settings from Tribunal. In other words,
|
|
||||||
// this bug affects the game EVEN IF YOU DO NOT USE ANY MODS!
|
|
||||||
|
|
||||||
// The guys at Bethesda are well aware of this bug (and many
|
|
||||||
// others), as the mod community and fan base complained about them
|
|
||||||
// for a long time. But it was never fixed.
|
|
||||||
|
|
||||||
// There are several programs available to help modders remove these
|
|
||||||
// records from their files, but not all modders use them, and they
|
|
||||||
// really shouldn't have to. In this file we choose instead to
|
|
||||||
// reject all the corrupt values at load time.
|
|
||||||
|
|
||||||
// These functions checks if the current game setting is one of the
|
|
||||||
// "dirty" ones as described above. TODO: I have not checked this
|
|
||||||
// against other sources yet, do that later. Currently recognizes 22
|
|
||||||
// values for tribunal and 50 for bloodmoon. Legitimate GMSTs in
|
|
||||||
// mods (setting values other than the default "dirty" ones) are not
|
|
||||||
// affected and will work correctly.
|
|
||||||
|
|
||||||
// Checks for dirty tribunal values. These will be ignored if found
|
|
||||||
// in any file except when they are found in "Tribunal.esm".
|
|
||||||
bool isDirtyTribunal()
|
|
||||||
{
|
|
||||||
bool result = false;
|
|
||||||
void cI(int ii) { if(ii == i) result = true; }
|
|
||||||
void cF(float ff) { if(ff == f) result = true; }
|
|
||||||
void cS(char[] ss) { if(ss == str) result = true; }
|
|
||||||
|
|
||||||
// Here, id contains the game setting name, and we check the
|
|
||||||
// setting for certain values. If it matches, this is a "dirty"
|
|
||||||
// entry. The correct entry (as defined in Tribunal and Bloodmoon
|
|
||||||
// esms) are given in the comments. Many of the values are
|
|
||||||
// correct, and are marked as 'same'. We still ignore them though,
|
|
||||||
// as they are still in the wrong file and might override custom
|
|
||||||
// values from other mods.
|
|
||||||
|
|
||||||
switch(id)
|
|
||||||
{
|
|
||||||
// Strings
|
|
||||||
case "sProfitValue": cS("Profit Value"); break; // 'Profit:'
|
|
||||||
case "sEditNote": cS("Edit Note"); break; // same
|
|
||||||
case "sDeleteNote": cS("Delete Note?"); break; // same
|
|
||||||
case "sMaxSale": cS("Max Sale"); break; // 'Seller Max'
|
|
||||||
case "sMagicFabricantID": cS("Fabricant"); break; // 'Fabricant_summon'
|
|
||||||
case "sTeleportDisabled": cS("Teleportation magic does not work here.");
|
|
||||||
break; // same
|
|
||||||
case "sLevitateDisabled": cS("Levitation magic does not work here.");
|
|
||||||
break; // same
|
|
||||||
case "sCompanionShare": cS("Companion Share"); break; // 'Share'
|
|
||||||
case "sCompanionWarningButtonOne": cS("Let the mercenary quit.");
|
|
||||||
break; // same
|
|
||||||
case "sCompanionWarningButtonTwo": cS("Return to Companion Share display."); break; // same
|
|
||||||
case "sCompanionWarningMessage": cS("Your mercenary is poorer now than when he contracted with you. Your mercenary will quit if you do not give him gold or goods to bring his Profit Value to a positive value."); break;
|
|
||||||
// 'Your mercenary is poorer now than when he contracted with
|
|
||||||
// you. Your mercenary will quit if you do not give him gold
|
|
||||||
// or goods to bring his Profit to a positive value.'
|
|
||||||
// [The difference here is "Profit Value" -> "Profit"}
|
|
||||||
|
|
||||||
// Strings that matches the id
|
|
||||||
case "sEffectSummonFabricant": // 'Summon Fabricant'
|
|
||||||
cS(id);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bloodmoon variant
|
|
||||||
bool isDirtyBloodmoon()
|
|
||||||
{
|
|
||||||
bool result = false;
|
|
||||||
void cI(int ii) { if(ii == i) result = true; }
|
|
||||||
void cF(float ff) { if(ff == f) result = true; }
|
|
||||||
void cS(char[] ss) { if(ss == str) result = true; }
|
|
||||||
|
|
||||||
switch(id)
|
|
||||||
{
|
|
||||||
// Strings
|
|
||||||
case "sWerewolfPopup": cS("Werewolf"); break; // same
|
|
||||||
case "sWerewolfRestMessage": cS("You cannot rest in werewolf form.");
|
|
||||||
break; // same
|
|
||||||
case "sWerewolfRefusal": cS("You cannot do this as a werewolf.");
|
|
||||||
break; // same
|
|
||||||
case "sWerewolfAlarmMessage": cS("You have been detected changing from a werewolf state."); break;
|
|
||||||
// 'You have been detected as a known werewolf.'
|
|
||||||
|
|
||||||
// Strings that matches the id
|
|
||||||
case "sMagicCreature01ID": // 'BM_wolf_grey_summon'
|
|
||||||
case "sMagicCreature02ID": // 'BM_bear_black_summon'
|
|
||||||
case "sMagicCreature03ID": // 'BM_wolf_bone_summon'
|
|
||||||
case "sMagicCreature04ID": // same
|
|
||||||
case "sMagicCreature05ID": // same
|
|
||||||
case "sEffectSummonCreature01": // 'Calf Wolf'
|
|
||||||
case "sEffectSummonCreature02": // 'Calf Bear'
|
|
||||||
case "sEffectSummonCreature03": // 'Summon Bonewolf'
|
|
||||||
case "sEffectSummonCreature04": // same
|
|
||||||
case "sEffectSummonCreature05": // same
|
|
||||||
cS(id);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Integers
|
|
||||||
case "iWereWolfBounty": cI(10000); break; // 1000
|
|
||||||
case "iWereWolfFightMod": cI(100); break; // same
|
|
||||||
case "iWereWolfFleeMod": cI(100); break; // same
|
|
||||||
case "iWereWolfLevelToAttack": cI(20); break; // same
|
|
||||||
|
|
||||||
// Floats
|
|
||||||
case "fFleeDistance": cF(3000); break; // same
|
|
||||||
case "fCombatDistanceWerewolfMod": cF(0.3); break; // same
|
|
||||||
case "fWereWolfFatigue": cF(400); break; // same
|
|
||||||
case "fWereWolfEnchant": cF(1); break; // 0
|
|
||||||
case "fWereWolfArmorer": cF(1); break; // 0
|
|
||||||
case "fWereWolfBlock": cF(1); break; // 0
|
|
||||||
case "fWereWolfSneak": cF(1); break; // 95
|
|
||||||
case "fWereWolfDestruction": cF(1); break; // 0
|
|
||||||
case "fWereWolfEndurance": cF(150); break; // same
|
|
||||||
case "fWereWolfConjuration": cF(1); break; // 0
|
|
||||||
case "fWereWolfRestoration": cF(1); break; // 0
|
|
||||||
case "fWereWolfAthletics": cF(150); break; // 50
|
|
||||||
case "fWereWolfLuck": cF(1); break; // 25
|
|
||||||
case "fWereWolfSilverWeaponDamageMult": cF(1.5); break; // 2
|
|
||||||
case "fWereWolfMediumArmor": cF(1); break; // 0
|
|
||||||
case "fWereWolfShortBlade": cF(1); break; // 0
|
|
||||||
case "fWereWolfAcrobatics": cF(150); break; // 80
|
|
||||||
case "fWereWolfSpeechcraft": cF(1); break; // 0
|
|
||||||
case "fWereWolfAlteration": cF(1); break; // 0
|
|
||||||
case "fWereWolfIllusion": cF(1); break; // 0
|
|
||||||
case "fWereWolfLongBlade": cF(1); break; // 0
|
|
||||||
case "fWereWolfMarksman": cF(1); break; // 0
|
|
||||||
case "fWereWolfHandtoHand": cF(100); break; // same
|
|
||||||
case "fWereWolfIntellegence": cF(1); break; // 0
|
|
||||||
case "fWereWolfAlchemy": cF(1); break; // 0
|
|
||||||
case "fWereWolfUnarmored": cF(100); break; // same
|
|
||||||
case "fWereWolfAxe": cF(1); break; // 0
|
|
||||||
case "fWereWolfRunMult": cF(1.5); break; // 1.3
|
|
||||||
case "fWereWolfMagicka": cF(100); break; // same
|
|
||||||
case "fWereWolfAgility": cF(150); break; // same
|
|
||||||
case "fWereWolfBluntWeapon": cF(1); break; // 0
|
|
||||||
case "fWereWolfSecurity": cF(1); break; // 0
|
|
||||||
case "fWereWolfPersonality": cF(1); break; // 0
|
|
||||||
case "fWereWolfMerchantile": cF(1); break; // 0
|
|
||||||
case "fWereWolfHeavyArmor": cF(1); break; // 0
|
|
||||||
case "fWereWolfSpear": cF(1); break; // 0
|
|
||||||
case "fWereWolfStrength": cF(150); break; // same
|
|
||||||
case "fWereWolfHealth": cF(2); break; // same
|
|
||||||
case "fWereWolfMysticism": cF(1); break; // 0
|
|
||||||
case "fWereWolfLightArmor": cF(1); break; // 0
|
|
||||||
case "fWereWolfWillPower": cF(1); break; // 0
|
|
||||||
case "fWereWolfSpeed": cF(150); break; // 90
|
|
||||||
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
char[] toString()
|
|
||||||
{
|
|
||||||
if(type == VarType.Int) return format(i);
|
|
||||||
else if(type == VarType.Float) return format(f);
|
|
||||||
else if(type == VarType.String) return str;
|
|
||||||
else if(type == VarType.None) return "(no value)";
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void load()
|
|
||||||
{
|
|
||||||
// We are apparently allowed not to have any value at all.
|
|
||||||
if(!esFile.hasMoreSubs())
|
|
||||||
{
|
|
||||||
if(state == LoadState.Previous)
|
|
||||||
writefln("Warning: Overwriting game setting %s with void value", id);
|
|
||||||
type = VarType.None;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this is not the first record of this type to be loaded, then
|
|
||||||
// we do a little "trick" to avoid overwriting the current data
|
|
||||||
// with one of the dirty GMSTs.
|
|
||||||
if(state == LoadState.Previous)
|
|
||||||
{
|
|
||||||
// Load the data in a temporary game setting instead
|
|
||||||
GameSetting g;
|
|
||||||
g.state = LoadState.Unloaded;
|
|
||||||
g.id = id;
|
|
||||||
g.load();
|
|
||||||
|
|
||||||
// Only copy it if it was valid
|
|
||||||
if(g.type != VarType.Ignored)
|
|
||||||
{
|
|
||||||
// Don't allow a change of type, unless the setting we are
|
|
||||||
// overwriting is an ignored value.
|
|
||||||
if(g.type != type && type != VarType.Ignored)
|
|
||||||
esFile.fail(format("GMST changed type from %d to %d",
|
|
||||||
cast(int)type, cast(int)g.type));
|
|
||||||
|
|
||||||
str = g.str; // This will copy all the data no matter what
|
|
||||||
// type it is
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actually load some data
|
|
||||||
esFile.getSubName();
|
|
||||||
switch(esFile.retSubName())
|
|
||||||
{
|
|
||||||
case "STRV":
|
|
||||||
str = esFile.getHString();
|
|
||||||
type = VarType.String;
|
|
||||||
break;
|
|
||||||
case "INTV":
|
|
||||||
i = esFile.getHInt();
|
|
||||||
type = VarType.Int;
|
|
||||||
break;
|
|
||||||
case "FLTV":
|
|
||||||
f = esFile.getHFloat();
|
|
||||||
type = VarType.Float;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
esFile.fail("Unwanted subrecord type");
|
|
||||||
}
|
|
||||||
|
|
||||||
SpecialFile spf = esFile.getSpecial();
|
|
||||||
|
|
||||||
// Check if this is one of the dirty values mentioned above. If it
|
|
||||||
// is, we set the VarType to Ignored. This leaves the posibility
|
|
||||||
// that this becomes the final var type, for example if you load a
|
|
||||||
// plugin with tribunal-gmst settings without loading tribunal
|
|
||||||
// first. (Then there would only exist dirty values for this
|
|
||||||
// settings, no "real" value.) But this is not likely a problem,
|
|
||||||
// since these empty values will never be used and we can check
|
|
||||||
// for them in any case.
|
|
||||||
|
|
||||||
if( ( spf != SpecialFile.Tribunal && isDirtyTribunal() ) ||
|
|
||||||
( spf != SpecialFile.Bloodmoon && isDirtyBloodmoon() ) )
|
|
||||||
type = VarType.Ignored;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ListID!(GameSetting) gameSettings;
|
|
Loading…
Reference in a new issue