forked from mirror/openmw-tes3mp
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
This commit is contained in:
parent
5715235a17
commit
e2e1c3b54b
4 changed files with 95 additions and 22 deletions
|
@ -25,6 +25,8 @@ module esm.esmmain;
|
||||||
|
|
||||||
public import esm.records;
|
public import esm.records;
|
||||||
|
|
||||||
|
import ogre.ogre;
|
||||||
|
|
||||||
/* This file is the main module for loading from ESM, ESP and ESS
|
/* This file is the main module for loading from ESM, ESP and ESS
|
||||||
files. It stores all the data in the appropriate data structures
|
files. It stores all the data in the appropriate data structures
|
||||||
for later referal. TODO: Put this in a class or whatever? Nah, we
|
for later referal. TODO: Put this in a class or whatever? Nah, we
|
||||||
|
@ -115,11 +117,21 @@ void loadTESFiles(char[][] files)
|
||||||
hyperlinks.sort();
|
hyperlinks.sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load a TES savegame file (.ess). Currently VERY limited, only reads
|
// Contains the small bits of information that we currently extract
|
||||||
// the header.
|
// from savegames.
|
||||||
void importSavegame(char[] file)
|
struct PlayerSaveInfo
|
||||||
{
|
{
|
||||||
writefln("Loading savegame %s", file);
|
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)
|
||||||
|
{
|
||||||
|
PlayerSaveInfo pi;
|
||||||
|
|
||||||
esFile.open(file, esmRegion);
|
esFile.open(file, esmRegion);
|
||||||
scope(exit) esFile.close();
|
scope(exit) esFile.close();
|
||||||
|
|
||||||
|
@ -128,14 +140,28 @@ void importSavegame(char[] file)
|
||||||
|
|
||||||
with(esFile.saveData)
|
with(esFile.saveData)
|
||||||
{
|
{
|
||||||
writefln("Floats:");
|
pi.cellName = stripz(cell);
|
||||||
foreach(i, f; unknown)
|
pi.playerName = stripz(player);
|
||||||
writefln(" %s: %s", i, f);
|
|
||||||
|
|
||||||
writefln("Cell name: ", stripz(cell));
|
|
||||||
|
|
||||||
writefln("Strange value: ", unk2);
|
|
||||||
writefln("Player name: ", stripz(player));
|
|
||||||
}
|
}
|
||||||
writefln();
|
|
||||||
|
with(esFile)
|
||||||
|
{
|
||||||
|
while(hasMoreRecs())
|
||||||
|
{
|
||||||
|
if(isNextHRec("REFR"))
|
||||||
|
{
|
||||||
|
while(hasMoreSubs())
|
||||||
|
{
|
||||||
|
getSubName();
|
||||||
|
if(retSubName() == "DATA")
|
||||||
|
readHExact(&pi.pos, pi.pos.sizeof);
|
||||||
|
else
|
||||||
|
skipHSub();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
skipHRecord();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pi;
|
||||||
}
|
}
|
||||||
|
|
|
@ -174,7 +174,7 @@ struct TES3File
|
||||||
// name.
|
// name.
|
||||||
struct _saveData
|
struct _saveData
|
||||||
{
|
{
|
||||||
float[6] unknown; // 24 bytes
|
float[6] unknown;
|
||||||
char[64] cell; // Cell name
|
char[64] cell; // Cell name
|
||||||
float unk2; // Unknown value
|
float unk2; // Unknown value
|
||||||
char[32] player; // Player name
|
char[32] player; // Player name
|
||||||
|
@ -534,13 +534,26 @@ struct TES3File
|
||||||
// Size of current sub record
|
// Size of current sub record
|
||||||
uint getSubSize() { return leftSub; }
|
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()
|
void skipRecord()
|
||||||
{
|
{
|
||||||
file.seekCur(leftRec);
|
file.seekCur(leftRec);
|
||||||
leftRec = 0;
|
leftRec = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Skip an entire record
|
||||||
|
void skipHRecord()
|
||||||
|
{
|
||||||
|
if(!leftFile) return;
|
||||||
|
|
||||||
|
uint flags;
|
||||||
|
|
||||||
|
getRecName();
|
||||||
|
getRecHeader(flags);
|
||||||
|
skipRecord();
|
||||||
|
}
|
||||||
|
|
||||||
// Skip current sub record and return size
|
// Skip current sub record and return size
|
||||||
uint skipHSub()
|
uint skipHSub()
|
||||||
{
|
{
|
||||||
|
|
|
@ -160,7 +160,7 @@ struct NPC
|
||||||
readHExact(&AI, AI.sizeof);
|
readHExact(&AI, AI.sizeof);
|
||||||
hasAI = true;
|
hasAI = true;
|
||||||
}
|
}
|
||||||
else hasAI = false;
|
else hasAI = false;
|
||||||
|
|
||||||
skipRecord();
|
skipRecord();
|
||||||
|
|
||||||
|
|
46
openmw.d
46
openmw.d
|
@ -38,6 +38,7 @@ import bullet.bullet;
|
||||||
import scene.celldata;
|
import scene.celldata;
|
||||||
import scene.soundlist;
|
import scene.soundlist;
|
||||||
import scene.gamesettings;
|
import scene.gamesettings;
|
||||||
|
import scene.player;
|
||||||
|
|
||||||
import core.resource;
|
import core.resource;
|
||||||
import core.memory;
|
import core.memory;
|
||||||
|
@ -90,6 +91,8 @@ void main(char[][] args)
|
||||||
bool debugOut = false;
|
bool debugOut = false;
|
||||||
bool extTest = false;
|
bool extTest = false;
|
||||||
bool doGen = false;
|
bool doGen = false;
|
||||||
|
bool nextSave = false;
|
||||||
|
bool loadSave = false;
|
||||||
|
|
||||||
// Some examples to try:
|
// Some examples to try:
|
||||||
//
|
//
|
||||||
|
@ -107,6 +110,9 @@ void main(char[][] args)
|
||||||
// Cells to load
|
// Cells to load
|
||||||
char[][] cells;
|
char[][] cells;
|
||||||
|
|
||||||
|
// Savegame to load
|
||||||
|
char[] savefile;
|
||||||
|
|
||||||
foreach(char[] a; args[1..$])
|
foreach(char[] a; args[1..$])
|
||||||
if(a == "-n") render = false;
|
if(a == "-n") render = false;
|
||||||
else if(a == "-ex") extTest = true;
|
else if(a == "-ex") extTest = true;
|
||||||
|
@ -115,6 +121,7 @@ void main(char[][] args)
|
||||||
else if(a == "-rk") resetKeys = true;
|
else if(a == "-rk") resetKeys = true;
|
||||||
else if(a == "-oc") showOgreFlag = true;
|
else if(a == "-oc") showOgreFlag = true;
|
||||||
else if(a == "-ns") config.noSound = true;
|
else if(a == "-ns") config.noSound = true;
|
||||||
|
else if(a == "-save") nextSave = true;
|
||||||
else if(a == "-debug")
|
else if(a == "-debug")
|
||||||
{
|
{
|
||||||
// Enable Monster debug output
|
// Enable Monster debug output
|
||||||
|
@ -123,6 +130,11 @@ void main(char[][] args)
|
||||||
// Tell OGRE to do the same later on
|
// Tell OGRE to do the same later on
|
||||||
debugOut = true;
|
debugOut = true;
|
||||||
}
|
}
|
||||||
|
else if(nextSave)
|
||||||
|
{
|
||||||
|
savefile = a;
|
||||||
|
nextSave = false;
|
||||||
|
}
|
||||||
else cells ~= a;
|
else cells ~= a;
|
||||||
|
|
||||||
if(cells.length > 1)
|
if(cells.length > 1)
|
||||||
|
@ -142,6 +154,7 @@ void main(char[][] args)
|
||||||
writefln(" -oc Show the Ogre config dialogue");
|
writefln(" -oc Show the Ogre config dialogue");
|
||||||
writefln(" -ns Completely disable sound");
|
writefln(" -ns Completely disable sound");
|
||||||
writefln(" -debug Print debug information");
|
writefln(" -debug Print debug information");
|
||||||
|
writefln(" -save <file> Load cell/pos from savegame");
|
||||||
writefln(" -h Show this help");
|
writefln(" -h Show this help");
|
||||||
writefln("");
|
writefln("");
|
||||||
writefln("Specifying more than one cell implies -n");
|
writefln("Specifying more than one cell implies -n");
|
||||||
|
@ -156,11 +169,28 @@ void main(char[][] args)
|
||||||
initializeMemoryRegions();
|
initializeMemoryRegions();
|
||||||
initMonsterScripts();
|
initMonsterScripts();
|
||||||
|
|
||||||
/*
|
// This is getting increasingly hackish, but this entire engine
|
||||||
importSavegame("data/quiksave.ess");
|
// design is now quickly outgrowing its usefulness, and a rewrite is
|
||||||
importSavegame("data/Perm1hal0000.ess");
|
// coming soon anyway.
|
||||||
return;
|
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);
|
config.initialize(resetKeys);
|
||||||
scope(exit) config.writeConfig();
|
scope(exit) config.writeConfig();
|
||||||
|
@ -181,7 +211,7 @@ void main(char[][] args)
|
||||||
if(config.defaultCell.length)
|
if(config.defaultCell.length)
|
||||||
cells ~= config.defaultCell;
|
cells ~= config.defaultCell;
|
||||||
|
|
||||||
if(cells.length == 1)
|
if(cells.length == 1 && !loadSave)
|
||||||
config.defaultCell = cells[0];
|
config.defaultCell = cells[0];
|
||||||
|
|
||||||
if(cells.length == 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.");
|
Try specifying another cell name on the command line, or edit openmw.ini.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we're loading from save, override the player position
|
||||||
|
if(loadSave)
|
||||||
|
*playerData.position = pi.pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simple safety hack
|
// Simple safety hack
|
||||||
|
|
Loading…
Reference in a new issue