Added -save switch: can now load player cell / pos from savegames

git-svn-id: https://openmw.svn.sourceforge.net/svnroot/openmw/trunk@137 ea6a568a-9f4f-0410-981a-c910a81bb256
actorid
nkorslund 15 years ago
parent 5715235a17
commit e2e1c3b54b

@ -25,6 +25,8 @@ module esm.esmmain;
public import esm.records;
import ogre.ogre;
/* This file is the main module for loading from ESM, ESP and ESS
files. It stores all the data in the appropriate data structures
for later referal. TODO: Put this in a class or whatever? Nah, we
@ -115,11 +117,21 @@ void loadTESFiles(char[][] files)
hyperlinks.sort();
}
// Load a TES savegame file (.ess). Currently VERY limited, only reads
// the header.
void importSavegame(char[] file)
// Contains the small bits of information that we currently extract
// from savegames.
struct PlayerSaveInfo
{
char[] cellName;
char[] playerName;
Placement pos;
}
// Load a TES savegame file (.ess). Currently VERY limited, reads the
// player's cell name and position
PlayerSaveInfo importSavegame(char[] file)
{
writefln("Loading savegame %s", file);
PlayerSaveInfo pi;
esFile.open(file, esmRegion);
scope(exit) esFile.close();
@ -128,14 +140,28 @@ void importSavegame(char[] file)
with(esFile.saveData)
{
writefln("Floats:");
foreach(i, f; unknown)
writefln(" %s: %s", i, f);
writefln("Cell name: ", stripz(cell));
pi.cellName = stripz(cell);
pi.playerName = stripz(player);
}
writefln("Strange value: ", unk2);
writefln("Player name: ", stripz(player));
with(esFile)
{
while(hasMoreRecs())
{
if(isNextHRec("REFR"))
{
while(hasMoreSubs())
{
getSubName();
if(retSubName() == "DATA")
readHExact(&pi.pos, pi.pos.sizeof);
else
skipHSub();
}
}
else
skipHRecord();
}
}
writefln();
return pi;
}

@ -174,7 +174,7 @@ struct TES3File
// name.
struct _saveData
{
float[6] unknown; // 24 bytes
float[6] unknown;
char[64] cell; // Cell name
float unk2; // Unknown value
char[32] player; // Player name
@ -534,13 +534,26 @@ struct TES3File
// Size of current sub record
uint getSubSize() { return leftSub; }
// Skip the rest of this record
// Skip the rest of this record. Assumes the name and header have
// already been read
void skipRecord()
{
file.seekCur(leftRec);
leftRec = 0;
}
// Skip an entire record
void skipHRecord()
{
if(!leftFile) return;
uint flags;
getRecName();
getRecHeader(flags);
skipRecord();
}
// Skip current sub record and return size
uint skipHSub()
{

@ -160,7 +160,7 @@ struct NPC
readHExact(&AI, AI.sizeof);
hasAI = true;
}
else hasAI = false;
else hasAI = false;
skipRecord();

@ -38,6 +38,7 @@ import bullet.bullet;
import scene.celldata;
import scene.soundlist;
import scene.gamesettings;
import scene.player;
import core.resource;
import core.memory;
@ -90,6 +91,8 @@ void main(char[][] args)
bool debugOut = false;
bool extTest = false;
bool doGen = false;
bool nextSave = false;
bool loadSave = false;
// Some examples to try:
//
@ -107,6 +110,9 @@ void main(char[][] args)
// Cells to load
char[][] cells;
// Savegame to load
char[] savefile;
foreach(char[] a; args[1..$])
if(a == "-n") render = false;
else if(a == "-ex") extTest = true;
@ -115,6 +121,7 @@ void main(char[][] args)
else if(a == "-rk") resetKeys = true;
else if(a == "-oc") showOgreFlag = true;
else if(a == "-ns") config.noSound = true;
else if(a == "-save") nextSave = true;
else if(a == "-debug")
{
// Enable Monster debug output
@ -123,6 +130,11 @@ void main(char[][] args)
// Tell OGRE to do the same later on
debugOut = true;
}
else if(nextSave)
{
savefile = a;
nextSave = false;
}
else cells ~= a;
if(cells.length > 1)
@ -142,6 +154,7 @@ void main(char[][] args)
writefln(" -oc Show the Ogre config dialogue");
writefln(" -ns Completely disable sound");
writefln(" -debug Print debug information");
writefln(" -save <file> Load cell/pos from savegame");
writefln(" -h Show this help");
writefln("");
writefln("Specifying more than one cell implies -n");
@ -156,11 +169,28 @@ void main(char[][] args)
initializeMemoryRegions();
initMonsterScripts();
/*
importSavegame("data/quiksave.ess");
importSavegame("data/Perm1hal0000.ess");
return;
*/
// This is getting increasingly hackish, but this entire engine
// design is now quickly outgrowing its usefulness, and a rewrite is
// coming soon anyway.
PlayerSaveInfo pi;
if(savefile != "")
{
if(cells.length)
{
writefln("Please don't specify both a savegame file (%s) and cell names (%s)", savefile, cells);
return;
}
loadSave = true;
writefln("Loading savegame %s", savefile);
pi = importSavegame(savefile);
writefln(" Player name: %s", pi.playerName);
writefln(" Cell name: %s", pi.cellName);
writefln(" Pos: %s", pi.pos.position);
writefln(" Rot: %s", pi.pos.rotation);
cells = [pi.cellName];
}
config.initialize(resetKeys);
scope(exit) config.writeConfig();
@ -181,7 +211,7 @@ void main(char[][] args)
if(config.defaultCell.length)
cells ~= config.defaultCell;
if(cells.length == 1)
if(cells.length == 1 && !loadSave)
config.defaultCell = cells[0];
if(cells.length == 0)
@ -218,6 +248,10 @@ Perhaps this cell does not exist in your Morrowind language version?
Try specifying another cell name on the command line, or edit openmw.ini.");
return;
}
// If we're loading from save, override the player position
if(loadSave)
*playerData.position = pi.pos;
}
// Simple safety hack

Loading…
Cancel
Save