mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-30 01:45:33 +00:00
Finished all basic parsers. Added --quiet option to esmtool.
This commit is contained in:
parent
2302e1f712
commit
db56985828
12 changed files with 194 additions and 105 deletions
|
@ -6,7 +6,7 @@
|
|||
namespace ESM {
|
||||
|
||||
/*
|
||||
* Books
|
||||
* Books, magic scrolls, notes and so on
|
||||
*/
|
||||
|
||||
struct Book
|
||||
|
|
|
@ -57,12 +57,11 @@ struct Cell
|
|||
if(esm.isNextSub("DELE")) esm.skipHSub();
|
||||
|
||||
esm.getHNT(data, "DATA", 12);
|
||||
region = esm.getHNOString("RGNN");
|
||||
|
||||
// Save position and move on
|
||||
context = esm.getContext();
|
||||
esm.skipRecord();
|
||||
|
||||
region = esm.getHNOString("RGNN");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -22,9 +22,9 @@ struct InventoryList
|
|||
void load(ESMReader &esm)
|
||||
{
|
||||
ContItem ci;
|
||||
while(esm.hasMoreSubs())
|
||||
while(esm.isNextSub("NPCO"))
|
||||
{
|
||||
esm.getHNT(ci, "NPCO", 36);
|
||||
esm.getHT(ci, 36);
|
||||
list.push_back(ci);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,6 +72,7 @@ struct Creature
|
|||
esm.getHNT(data, "NPDT", 96);
|
||||
|
||||
esm.getHNT(flags, "FLAG");
|
||||
scale = 1.0;
|
||||
esm.getHNOT(scale, "XSCL");
|
||||
|
||||
inventory.load(esm);
|
||||
|
|
46
esm/loaddial.hpp
Normal file
46
esm/loaddial.hpp
Normal file
|
@ -0,0 +1,46 @@
|
|||
#ifndef _ESM_DIAL_H
|
||||
#define _ESM_DIAL_H
|
||||
|
||||
#include "esm_reader.hpp"
|
||||
|
||||
namespace ESM {
|
||||
|
||||
/*
|
||||
* Dialogue topic and journal entries. The actual data is contained in
|
||||
* the INFO records following the DIAL.
|
||||
*/
|
||||
|
||||
struct Dialogue
|
||||
{
|
||||
enum Type
|
||||
{
|
||||
Topic = 0,
|
||||
Voice = 1,
|
||||
Greeting = 2,
|
||||
Persuasion = 3,
|
||||
Journal = 4,
|
||||
Deleted = -1
|
||||
};
|
||||
|
||||
char type;
|
||||
|
||||
void load(ESMReader &esm)
|
||||
{
|
||||
esm.getSubNameIs("DATA");
|
||||
esm.getSubHeader();
|
||||
int si = esm.getSubSize();
|
||||
if(si == 1)
|
||||
esm.getT(type);
|
||||
else if(si == 4)
|
||||
{
|
||||
// These are just markers, their values are not used.
|
||||
int i;
|
||||
esm.getT(i);
|
||||
esm.getHNT(i,"DELE");
|
||||
type = Deleted;
|
||||
}
|
||||
else esm.fail("Unknown sub record size");
|
||||
}
|
||||
};
|
||||
}
|
||||
#endif
|
|
@ -203,6 +203,8 @@ struct GameSetting
|
|||
|
||||
void load(ESMReader &esm)
|
||||
{
|
||||
assert(id != "");
|
||||
|
||||
dirty = false;
|
||||
|
||||
// We are apparently allowed to be empty
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "loadcont.hpp"
|
||||
#include "loadcrea.hpp"
|
||||
#include "loadcrec.hpp"
|
||||
#include "loaddial.hpp"
|
||||
#include "loaddoor.hpp"
|
||||
#include "loadench.hpp"
|
||||
#include "loadfact.hpp"
|
||||
|
|
|
@ -42,6 +42,8 @@ int main(int argc, char**argv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool quiet = info.quiet_given;
|
||||
|
||||
esm.open(filename);
|
||||
|
||||
cout << "Author: " << esm.getAuthor() << endl;
|
||||
|
@ -57,10 +59,11 @@ int main(int argc, char**argv)
|
|||
while(esm.hasMoreRecs())
|
||||
{
|
||||
NAME n = esm.getRecName();
|
||||
cout << "\nRecord: " << n.toString();
|
||||
esm.getRecHeader();
|
||||
string id = esm.getHNOString("NAME");
|
||||
cout << " '" << id << "'\n";
|
||||
if(!quiet)
|
||||
cout << "\nRecord: " << n.toString()
|
||||
<< " '" << id << "'\n";
|
||||
|
||||
switch(n.val)
|
||||
{
|
||||
|
@ -68,15 +71,33 @@ int main(int argc, char**argv)
|
|||
{
|
||||
Activator ac;
|
||||
ac.load(esm);
|
||||
if(quiet) break;
|
||||
cout << " Name: " << ac.name << endl;
|
||||
cout << " Mesh: " << ac.model << endl;
|
||||
cout << " Script: " << ac.script << endl;
|
||||
break;
|
||||
}
|
||||
case REC_ALCH:
|
||||
{
|
||||
Potion p;
|
||||
p.load(esm);
|
||||
if(quiet) break;
|
||||
cout << " Name: " << p.name << endl;
|
||||
break;
|
||||
}
|
||||
case REC_APPA:
|
||||
{
|
||||
Apparatus p;
|
||||
p.load(esm);
|
||||
if(quiet) break;
|
||||
cout << " Name: " << p.name << endl;
|
||||
break;
|
||||
}
|
||||
case REC_ARMO:
|
||||
{
|
||||
Armor am;
|
||||
am.load(esm);
|
||||
if(quiet) break;
|
||||
cout << " Name: " << am.name << endl;
|
||||
cout << " Mesh: " << am.model << endl;
|
||||
cout << " Icon: " << am.icon << endl;
|
||||
|
@ -90,23 +111,83 @@ int main(int argc, char**argv)
|
|||
{
|
||||
BodyPart bp;
|
||||
bp.load(esm);
|
||||
if(quiet) break;
|
||||
cout << " Name: " << bp.name << endl;
|
||||
cout << " Mesh: " << bp.model << endl;
|
||||
break;
|
||||
}
|
||||
case REC_BOOK:
|
||||
{
|
||||
Book b;
|
||||
b.load(esm);
|
||||
if(quiet) break;
|
||||
cout << " Name: " << b.name << endl;
|
||||
cout << " Mesh: " << b.model << endl;
|
||||
break;
|
||||
}
|
||||
case REC_BSGN:
|
||||
{
|
||||
BirthSign bs;
|
||||
bs.load(esm);
|
||||
if(quiet) break;
|
||||
cout << " Name: " << bs.name << endl;
|
||||
cout << " Texture: " << bs.texture << endl;
|
||||
cout << " Description: " << bs.description << endl;
|
||||
break;
|
||||
}
|
||||
case REC_CELL:
|
||||
{
|
||||
Cell b;
|
||||
b.load(esm);
|
||||
if(quiet) break;
|
||||
cout << " Name: " << b.name << endl;
|
||||
cout << " Region: " << b.region << endl;
|
||||
break;
|
||||
}
|
||||
case REC_CLAS:
|
||||
{
|
||||
Class b;
|
||||
b.load(esm);
|
||||
if(quiet) break;
|
||||
cout << " Name: " << b.name << endl;
|
||||
cout << " Description: " << b.description << endl;
|
||||
break;
|
||||
}
|
||||
case REC_CLOT:
|
||||
{
|
||||
Clothing b;
|
||||
b.load(esm);
|
||||
if(quiet) break;
|
||||
cout << " Name: " << b.name << endl;
|
||||
break;
|
||||
}
|
||||
case REC_CONT:
|
||||
{
|
||||
Container b;
|
||||
b.load(esm);
|
||||
if(quiet) break;
|
||||
cout << " Name: " << b.name << endl;
|
||||
break;
|
||||
}
|
||||
case REC_CREA:
|
||||
{
|
||||
Creature b;
|
||||
b.load(esm);
|
||||
if(quiet) break;
|
||||
cout << " Name: " << b.name << endl;
|
||||
break;
|
||||
}
|
||||
case REC_DIAL:
|
||||
{
|
||||
Dialogue b;
|
||||
b.load(esm);
|
||||
break;
|
||||
}
|
||||
case REC_DOOR:
|
||||
{
|
||||
Door d;
|
||||
d.load(esm);
|
||||
if(quiet) break;
|
||||
cout << " Name: " << d.name << endl;
|
||||
cout << " Mesh: " << d.model << endl;
|
||||
cout << " Script: " << d.script << endl;
|
||||
|
@ -114,10 +195,42 @@ int main(int argc, char**argv)
|
|||
cout << " CloseSound: " << d.closeSound << endl;
|
||||
break;
|
||||
}
|
||||
case REC_ENCH:
|
||||
{
|
||||
Enchantment b;
|
||||
b.load(esm);
|
||||
break;
|
||||
}
|
||||
case REC_GMST:
|
||||
{
|
||||
GameSetting b;
|
||||
b.id = id;
|
||||
b.load(esm);
|
||||
if(quiet) break;
|
||||
cout << " Value: ";
|
||||
if(b.type == VT_String)
|
||||
cout << "'" << b.str << "' (string)";
|
||||
else if(b.type == VT_Float)
|
||||
cout << b.f << " (float)";
|
||||
else if(b.type == VT_Int)
|
||||
cout << b.i << " (int)";
|
||||
cout << "\n Dirty: " << b.dirty << endl;
|
||||
break;
|
||||
}
|
||||
case REC_INFO:
|
||||
{
|
||||
DialInfo p;
|
||||
p.load(esm);
|
||||
if(quiet) break;
|
||||
cout << " Id: " << p.id << endl;
|
||||
cout << " Text: " << p.response << endl;
|
||||
break;
|
||||
}
|
||||
case REC_SOUN:
|
||||
{
|
||||
Sound d;
|
||||
d.load(esm);
|
||||
if(quiet) break;
|
||||
cout << " Sound: " << d.sound << endl;
|
||||
cout << " Volume: " << (int)d.data.volume << endl;
|
||||
break;
|
||||
|
@ -126,12 +239,14 @@ int main(int argc, char**argv)
|
|||
{
|
||||
Spell s;
|
||||
s.load(esm);
|
||||
if(quiet) break;
|
||||
cout << " Name: " << s.name << endl;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
cout << " Skipping\n";
|
||||
esm.skipRecord();
|
||||
if(quiet) break;
|
||||
cout << " Skipping\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,5 +4,6 @@ purpose "Inspect and extract from Morrowind ES files (ESM, ESP, ESS)"
|
|||
args "--unamed-opts=ES-FILE -F esmtool_cmd -G"
|
||||
|
||||
option "raw" r "Show an unformattet list of all records and subrecords" optional
|
||||
option "quiet" q "Supress all record information. Useful for speed tests." optional
|
||||
|
||||
text "\nIf no option is given, the default action is to parse the entire archive and diplay diagnostic information."
|
||||
|
|
|
@ -34,6 +34,7 @@ const char *gengetopt_args_info_help[] = {
|
|||
" -h, --help Print help and exit",
|
||||
" -V, --version Print version and exit",
|
||||
" -r, --raw Show an unformattet list of all records and subrecords",
|
||||
" -q, --quiet Supress all record information. Useful for speed tests.",
|
||||
"\nIf no option is given, the default action is to parse the entire archive and \ndiplay diagnostic information.",
|
||||
0
|
||||
};
|
||||
|
@ -60,6 +61,7 @@ void clear_given (struct gengetopt_args_info *args_info)
|
|||
args_info->help_given = 0 ;
|
||||
args_info->version_given = 0 ;
|
||||
args_info->raw_given = 0 ;
|
||||
args_info->quiet_given = 0 ;
|
||||
}
|
||||
|
||||
static
|
||||
|
@ -77,6 +79,7 @@ void init_args_info(struct gengetopt_args_info *args_info)
|
|||
args_info->help_help = gengetopt_args_info_help[0] ;
|
||||
args_info->version_help = gengetopt_args_info_help[1] ;
|
||||
args_info->raw_help = gengetopt_args_info_help[2] ;
|
||||
args_info->quiet_help = gengetopt_args_info_help[3] ;
|
||||
|
||||
}
|
||||
|
||||
|
@ -192,6 +195,8 @@ cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info)
|
|||
write_into_file(outfile, "version", 0, 0 );
|
||||
if (args_info->raw_given)
|
||||
write_into_file(outfile, "raw", 0, 0 );
|
||||
if (args_info->quiet_given)
|
||||
write_into_file(outfile, "quiet", 0, 0 );
|
||||
|
||||
|
||||
i = EXIT_SUCCESS;
|
||||
|
@ -1019,6 +1024,7 @@ cmdline_parser_internal (
|
|||
{ "help", 0, NULL, 'h' },
|
||||
{ "version", 0, NULL, 'V' },
|
||||
{ "raw", 0, NULL, 'r' },
|
||||
{ "quiet", 0, NULL, 'q' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
|
@ -1027,7 +1033,7 @@ cmdline_parser_internal (
|
|||
custom_opterr = opterr;
|
||||
custom_optopt = optopt;
|
||||
|
||||
c = custom_getopt_long (argc, argv, "hVr", long_options, &option_index);
|
||||
c = custom_getopt_long (argc, argv, "hVrq", long_options, &option_index);
|
||||
|
||||
optarg = custom_optarg;
|
||||
optind = custom_optind;
|
||||
|
@ -1060,6 +1066,18 @@ cmdline_parser_internal (
|
|||
goto failure;
|
||||
|
||||
break;
|
||||
case 'q': /* Supress all record information. Useful for speed tests.. */
|
||||
|
||||
|
||||
if (update_arg( 0 ,
|
||||
0 , &(args_info->quiet_given),
|
||||
&(local_args_info.quiet_given), optarg, 0, 0, ARG_NO,
|
||||
check_ambiguity, override, 0, 0,
|
||||
"quiet", 'q',
|
||||
additional_error))
|
||||
goto failure;
|
||||
|
||||
break;
|
||||
|
||||
case 0: /* Long option with no short option */
|
||||
case '?': /* Invalid option. */
|
||||
|
|
|
@ -40,10 +40,12 @@ struct gengetopt_args_info
|
|||
const char *help_help; /**< @brief Print help and exit help description. */
|
||||
const char *version_help; /**< @brief Print version and exit help description. */
|
||||
const char *raw_help; /**< @brief Show an unformattet list of all records and subrecords help description. */
|
||||
const char *quiet_help; /**< @brief Supress all record information. Useful for speed tests. help description. */
|
||||
|
||||
unsigned int help_given ; /**< @brief Whether help was given. */
|
||||
unsigned int version_given ; /**< @brief Whether version was given. */
|
||||
unsigned int raw_given ; /**< @brief Whether raw was given. */
|
||||
unsigned int quiet_given ; /**< @brief Whether quiet was given. */
|
||||
|
||||
char **inputs ; /**< @brief unamed options (options without names) */
|
||||
unsigned inputs_num ; /**< @brief unamed options number */
|
||||
|
|
|
@ -1,96 +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 (loadspel.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.loadspel;
|
||||
import esm.imports;
|
||||
|
||||
/*
|
||||
* Spell
|
||||
*/
|
||||
|
||||
struct SpellList
|
||||
{
|
||||
RegionBuffer!(Spell*) list;
|
||||
|
||||
void load()
|
||||
{
|
||||
list = esFile.getRegion().getBuffer!(Spell*)(0,1);
|
||||
|
||||
while(esFile.isNextSub("NPCS"))
|
||||
list ~= esFile.getHPtr!(Spell)(spells);
|
||||
}
|
||||
}
|
||||
|
||||
struct Spell
|
||||
{
|
||||
char[] id;
|
||||
LoadState state;
|
||||
|
||||
enum SpellType
|
||||
{
|
||||
Spell = 0, // Normal spell, must be cast and costs mana
|
||||
Ability = 1, // Inert ability, always in effect
|
||||
Blight = 2, // Blight disease
|
||||
Disease = 3, // Common disease
|
||||
Curse = 4, // Curse (?)
|
||||
Power = 5 // Power, can use once a day
|
||||
}
|
||||
|
||||
enum Flags
|
||||
{
|
||||
Autocalc = 1,
|
||||
PCStart = 2,
|
||||
Always = 4 // Casting always succeeds
|
||||
}
|
||||
|
||||
align(1) struct SPDTstruct
|
||||
{
|
||||
SpellType type;
|
||||
int cost;
|
||||
Flags flags;
|
||||
|
||||
static assert(SPDTstruct.sizeof==12);
|
||||
}
|
||||
|
||||
SPDTstruct data;
|
||||
|
||||
char[] name;
|
||||
EffectList effects;
|
||||
|
||||
void load()
|
||||
{with(esFile){
|
||||
name = getHNOString("FNAM");
|
||||
readHNExact(&data, data.sizeof, "SPDT");
|
||||
|
||||
effects = getRegion().getBuffer!(ENAMstruct)(0,1);
|
||||
|
||||
while(isNextSub("ENAM"))
|
||||
{
|
||||
effects.length = effects.length + 1;
|
||||
readHExact(&effects.array[$-1], effects.array[$-1].sizeof);
|
||||
}
|
||||
}}
|
||||
|
||||
}
|
||||
|
||||
ListID!(Spell) spells;
|
Loading…
Reference in a new issue