mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-12-27 20:20:40 +00:00
- get load and save game menus and related CCMDs working again.
This commit is contained in:
parent
53c3a6fc9b
commit
2bb38f7d67
23 changed files with 806 additions and 750 deletions
|
@ -932,6 +932,7 @@ set (PCH_SOURCES
|
||||||
common/menu/optionmenu.cpp
|
common/menu/optionmenu.cpp
|
||||||
common/menu/resolutionmenu.cpp
|
common/menu/resolutionmenu.cpp
|
||||||
common/menu/menudef.cpp
|
common/menu/menudef.cpp
|
||||||
|
common/menu/savegamemanager.cpp
|
||||||
|
|
||||||
common/rendering/v_framebuffer.cpp
|
common/rendering/v_framebuffer.cpp
|
||||||
common/rendering/v_video.cpp
|
common/rendering/v_video.cpp
|
||||||
|
|
|
@ -80,8 +80,8 @@ struct GameInterface : ::GameInterface
|
||||||
void MenuClosed() override;
|
void MenuClosed() override;
|
||||||
bool CanSave() override;
|
bool CanSave() override;
|
||||||
bool StartGame(FNewGameStartup& gs) override;
|
bool StartGame(FNewGameStartup& gs) override;
|
||||||
bool SaveGame(FSaveGameNode*) override;
|
bool SaveGame() override;
|
||||||
bool LoadGame(FSaveGameNode*) override;
|
bool LoadGame() override;
|
||||||
void QuitToTitle() override;
|
void QuitToTitle() override;
|
||||||
FString GetCoordString() override;
|
FString GetCoordString() override;
|
||||||
ReservedSpace GetReservedScreenSpace(int viewsize) override;
|
ReservedSpace GetReservedScreenSpace(int viewsize) override;
|
||||||
|
|
|
@ -474,7 +474,7 @@ void LoadSave::Write(void *pData, int nSize)
|
||||||
ThrowError("File error #%d writing save file.", errno);
|
ThrowError("File error #%d writing save file.", errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GameInterface::LoadGame(FSaveGameNode* node)
|
bool GameInterface::LoadGame()
|
||||||
{
|
{
|
||||||
sndKillAllSounds();
|
sndKillAllSounds();
|
||||||
sfxKillAllSounds();
|
sfxKillAllSounds();
|
||||||
|
@ -534,7 +534,7 @@ bool GameInterface::LoadGame(FSaveGameNode* node)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GameInterface::SaveGame(FSaveGameNode* node)
|
bool GameInterface::SaveGame()
|
||||||
{
|
{
|
||||||
LoadSave::hSFile = WriteSavegameChunk("snapshot.bld");
|
LoadSave::hSFile = WriteSavegameChunk("snapshot.bld");
|
||||||
|
|
||||||
|
|
|
@ -41,8 +41,6 @@ public:
|
||||||
virtual void Load(void);
|
virtual void Load(void);
|
||||||
void Read(void *, int);
|
void Read(void *, int);
|
||||||
void Write(void *, int);
|
void Write(void *, int);
|
||||||
static void LoadGame(FSavegameNode *);
|
|
||||||
static void SaveGame(FSavegameNode*);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void LoadSaveSetup(void);
|
void LoadSaveSetup(void);
|
||||||
|
|
|
@ -1529,6 +1529,19 @@ void DrawFrame(F2DDrawer* twod, PalEntry color, int left, int top, int width, in
|
||||||
twod->AddColorOnlyQuad(right, top - offset, offset, height + 2 * offset, color);
|
twod->AddColorOnlyQuad(right, top - offset, offset, height + 2 * offset, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(_Screen, DrawLineFrame)
|
||||||
|
{
|
||||||
|
PARAM_PROLOGUE;
|
||||||
|
PARAM_COLOR(color);
|
||||||
|
PARAM_INT(left);
|
||||||
|
PARAM_INT(top);
|
||||||
|
PARAM_INT(width);
|
||||||
|
PARAM_INT(height);
|
||||||
|
PARAM_INT(thickness);
|
||||||
|
DrawFrame(twod, color, left, top, width, height, thickness);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void V_CalcCleanFacs(int designwidth, int designheight, int realwidth, int realheight, int* cleanx, int* cleany, int* _cx1, int* _cx2)
|
void V_CalcCleanFacs(int designwidth, int designheight, int realwidth, int realheight, int* cleanx, int* cleany, int* _cx1, int* _cx2)
|
||||||
{
|
{
|
||||||
if (designheight < 240 && realheight >= 480) designheight = 240;
|
if (designheight < 240 && realheight >= 480) designheight = 240;
|
||||||
|
|
541
source/common/menu/savegamemanager.cpp
Normal file
541
source/common/menu/savegamemanager.cpp
Normal file
|
@ -0,0 +1,541 @@
|
||||||
|
/*
|
||||||
|
** loadsavemenu.cpp
|
||||||
|
** The load game and save game menus
|
||||||
|
**
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
** Copyright 2001-2010 Randy Heit
|
||||||
|
** Copyright 2010-2020 Christoph Oelckers
|
||||||
|
** All rights reserved.
|
||||||
|
**
|
||||||
|
** Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions
|
||||||
|
** are met:
|
||||||
|
**
|
||||||
|
** 1. Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in the
|
||||||
|
** documentation and/or other materials provided with the distribution.
|
||||||
|
** 3. The name of the author may not be used to endorse or promote products
|
||||||
|
** derived from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "menu.h"
|
||||||
|
#include "version.h"
|
||||||
|
#include "m_png.h"
|
||||||
|
#include "filesystem.h"
|
||||||
|
#include "v_text.h"
|
||||||
|
#include "gstrings.h"
|
||||||
|
#include "serializer.h"
|
||||||
|
#include "vm.h"
|
||||||
|
#include "i_system.h"
|
||||||
|
#include "v_video.h"
|
||||||
|
#include "findfile.h"
|
||||||
|
#include "v_draw.h"
|
||||||
|
#include "savegamemanager.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
// Save data maintenance
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
void FSavegameManagerBase::ClearSaveGames()
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i<SaveGames.Size(); i++)
|
||||||
|
{
|
||||||
|
if (!SaveGames[i]->bNoDelete)
|
||||||
|
delete SaveGames[i];
|
||||||
|
}
|
||||||
|
SaveGames.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
FSavegameManagerBase::~FSavegameManagerBase()
|
||||||
|
{
|
||||||
|
ClearSaveGames();
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
// Save data maintenance
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
int FSavegameManagerBase::RemoveSaveSlot(int index)
|
||||||
|
{
|
||||||
|
int listindex = SaveGames[0]->bNoDelete ? index - 1 : index;
|
||||||
|
if (listindex < 0) return index;
|
||||||
|
|
||||||
|
remove(SaveGames[index]->Filename.GetChars());
|
||||||
|
UnloadSaveData();
|
||||||
|
|
||||||
|
FSaveGameNode *file = SaveGames[index];
|
||||||
|
|
||||||
|
if (quickSaveSlot == SaveGames[index])
|
||||||
|
{
|
||||||
|
quickSaveSlot = nullptr;
|
||||||
|
}
|
||||||
|
if (!file->bNoDelete) delete file;
|
||||||
|
|
||||||
|
if (LastSaved == listindex) LastSaved = -1;
|
||||||
|
else if (LastSaved > listindex) LastSaved--;
|
||||||
|
if (LastAccessed == listindex) LastAccessed = -1;
|
||||||
|
else if (LastAccessed > listindex) LastAccessed--;
|
||||||
|
|
||||||
|
SaveGames.Delete(index);
|
||||||
|
if ((unsigned)index >= SaveGames.Size()) index--;
|
||||||
|
ExtractSaveData(index);
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(FSavegameManager, RemoveSaveSlot)
|
||||||
|
{
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE(FSavegameManagerBase);
|
||||||
|
PARAM_INT(sel);
|
||||||
|
ACTION_RETURN_INT(self->RemoveSaveSlot(sel));
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
int FSavegameManagerBase::InsertSaveNode(FSaveGameNode *node)
|
||||||
|
{
|
||||||
|
if (SaveGames.Size() == 0)
|
||||||
|
{
|
||||||
|
return SaveGames.Push(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node->bOldVersion)
|
||||||
|
{ // Add node at bottom of list
|
||||||
|
return SaveGames.Push(node);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // Add node at top of list
|
||||||
|
unsigned int i = 0;
|
||||||
|
//if (SaveGames[0] == &NewSaveNode) i++; // To not insert above the "new savegame" dummy entry.
|
||||||
|
for (; i < SaveGames.Size(); i++)
|
||||||
|
{
|
||||||
|
if (SaveGames[i]->bOldVersion || node->SaveTitle.CompareNoCase(SaveGames[i]->SaveTitle) <= 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SaveGames.Insert(i, node);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
void FSavegameManagerBase::NotifyNewSave(const FString &file, const FString &title, bool okForQuicksave, bool forceQuicksave)
|
||||||
|
{
|
||||||
|
FSaveGameNode *node;
|
||||||
|
|
||||||
|
if (file.IsEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
ReadSaveStrings();
|
||||||
|
|
||||||
|
// See if the file is already in our list
|
||||||
|
for (unsigned i = 0; i<SaveGames.Size(); i++)
|
||||||
|
{
|
||||||
|
FSaveGameNode *node = SaveGames[i];
|
||||||
|
#ifdef __unix__
|
||||||
|
if (node->Filename.Compare(file) == 0)
|
||||||
|
#else
|
||||||
|
if (node->Filename.CompareNoCase(file) == 0)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
node->SaveTitle = title;
|
||||||
|
node->bOldVersion = false;
|
||||||
|
node->bMissingWads = false;
|
||||||
|
if (okForQuicksave)
|
||||||
|
{
|
||||||
|
if (quickSaveSlot == nullptr || quickSaveSlot == (FSaveGameNode*)1 || forceQuicksave) quickSaveSlot = node;
|
||||||
|
LastAccessed = LastSaved = i;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
node = new FSaveGameNode;
|
||||||
|
node->SaveTitle = title;
|
||||||
|
node->Filename = file;
|
||||||
|
node->bOldVersion = false;
|
||||||
|
node->bMissingWads = false;
|
||||||
|
int index = InsertSaveNode(node);
|
||||||
|
|
||||||
|
if (okForQuicksave)
|
||||||
|
{
|
||||||
|
if (quickSaveSlot == nullptr || quickSaveSlot == (FSaveGameNode*)1 || forceQuicksave) quickSaveSlot = node;
|
||||||
|
LastAccessed = LastSaved = index;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LastAccessed = ++LastSaved;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
// Loads the savegame
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
void FSavegameManagerBase::LoadSavegame(int Selected)
|
||||||
|
{
|
||||||
|
PerformLoadGame(SaveGames[Selected]->Filename.GetChars(), true);
|
||||||
|
if (quickSaveSlot == (FSaveGameNode*)1)
|
||||||
|
{
|
||||||
|
quickSaveSlot = SaveGames[Selected];
|
||||||
|
}
|
||||||
|
M_ClearMenus();
|
||||||
|
LastAccessed = Selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(FSavegameManager, LoadSavegame)
|
||||||
|
{
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE(FSavegameManagerBase);
|
||||||
|
PARAM_INT(sel);
|
||||||
|
self->LoadSavegame(sel);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
void FSavegameManagerBase::DoSave(int Selected, const char *savegamestring)
|
||||||
|
{
|
||||||
|
if (Selected != 0)
|
||||||
|
{
|
||||||
|
auto node = SaveGames[Selected];
|
||||||
|
PerformSaveGame(node->Filename.GetChars(), savegamestring);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Find an unused filename and save as that
|
||||||
|
FString filename;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0;; ++i)
|
||||||
|
{
|
||||||
|
filename = BuildSaveName("save", i);
|
||||||
|
if (!FileExists(filename))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PerformSaveGame(filename, savegamestring);
|
||||||
|
}
|
||||||
|
M_ClearMenus();
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(FSavegameManager, DoSave)
|
||||||
|
{
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE(FSavegameManagerBase);
|
||||||
|
PARAM_INT(sel);
|
||||||
|
PARAM_STRING(name);
|
||||||
|
self->DoSave(sel, name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
unsigned FSavegameManagerBase::ExtractSaveData(int index)
|
||||||
|
{
|
||||||
|
FResourceFile *resf;
|
||||||
|
FSaveGameNode *node;
|
||||||
|
|
||||||
|
if (index == -1)
|
||||||
|
{
|
||||||
|
if (SaveGames.Size() > 0 && SaveGames[0]->bNoDelete)
|
||||||
|
{
|
||||||
|
index = LastSaved + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
index = LastAccessed < 0? 0 : LastAccessed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UnloadSaveData();
|
||||||
|
|
||||||
|
if ((unsigned)index < SaveGames.Size() &&
|
||||||
|
(node = SaveGames[index]) &&
|
||||||
|
!node->Filename.IsEmpty() &&
|
||||||
|
!node->bOldVersion &&
|
||||||
|
(resf = FResourceFile::OpenResourceFile(node->Filename.GetChars(), true)) != nullptr)
|
||||||
|
{
|
||||||
|
FResourceLump *info = resf->FindLump("info.json");
|
||||||
|
if (info == nullptr)
|
||||||
|
{
|
||||||
|
// this should not happen because the file has already been verified.
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* data = info->Lock();
|
||||||
|
FSerializer arc;
|
||||||
|
if (!arc.OpenReader((const char*)data, info->LumpSize))
|
||||||
|
{
|
||||||
|
info->Unlock();
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
info->Unlock();
|
||||||
|
|
||||||
|
SaveCommentString = ExtractSaveComment(arc);
|
||||||
|
|
||||||
|
FResourceLump *pic = resf->FindLump("savepic.png");
|
||||||
|
if (pic != nullptr)
|
||||||
|
{
|
||||||
|
FileReader picreader;
|
||||||
|
|
||||||
|
picreader.OpenMemoryArray([=](TArray<uint8_t> &array)
|
||||||
|
{
|
||||||
|
auto cache = pic->Lock();
|
||||||
|
array.Resize(pic->LumpSize);
|
||||||
|
memcpy(&array[0], cache, pic->LumpSize);
|
||||||
|
pic->Unlock();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
PNGHandle *png = M_VerifyPNG(picreader);
|
||||||
|
if (png != nullptr)
|
||||||
|
{
|
||||||
|
SavePic = PNGTexture_CreateFromFile(png, node->Filename);
|
||||||
|
delete png;
|
||||||
|
if (SavePic && SavePic->GetDisplayWidth() == 1 && SavePic->GetDisplayHeight() == 1)
|
||||||
|
{
|
||||||
|
delete SavePic;
|
||||||
|
SavePic = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete resf;
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
void FSavegameManagerBase::UnloadSaveData()
|
||||||
|
{
|
||||||
|
if (SavePic != nullptr)
|
||||||
|
{
|
||||||
|
delete SavePic;
|
||||||
|
}
|
||||||
|
|
||||||
|
SaveCommentString = "";
|
||||||
|
SavePic = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(FSavegameManager, UnloadSaveData)
|
||||||
|
{
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE(FSavegameManagerBase);
|
||||||
|
self->UnloadSaveData();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
void FSavegameManagerBase::ClearSaveStuff()
|
||||||
|
{
|
||||||
|
UnloadSaveData();
|
||||||
|
if (quickSaveSlot == (FSaveGameNode*)1)
|
||||||
|
{
|
||||||
|
quickSaveSlot = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(FSavegameManager, ClearSaveStuff)
|
||||||
|
{
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE(FSavegameManagerBase);
|
||||||
|
self->ClearSaveStuff();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
bool FSavegameManagerBase::DrawSavePic(int x, int y, int w, int h)
|
||||||
|
{
|
||||||
|
if (SavePic == nullptr) return false;
|
||||||
|
DrawTexture(twod, SavePic, x, y, DTA_DestWidth, w, DTA_DestHeight, h, DTA_Masked, false, TAG_DONE);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(FSavegameManager, DrawSavePic)
|
||||||
|
{
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE(FSavegameManagerBase);
|
||||||
|
PARAM_INT(x);
|
||||||
|
PARAM_INT(y);
|
||||||
|
PARAM_INT(w);
|
||||||
|
PARAM_INT(h);
|
||||||
|
ACTION_RETURN_BOOL(self->DrawSavePic(x, y, w, h));
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
void FSavegameManagerBase::SetFileInfo(int Selected)
|
||||||
|
{
|
||||||
|
if (!SaveGames[Selected]->Filename.IsEmpty())
|
||||||
|
{
|
||||||
|
SaveCommentString.Format("File on disk:\n%s", SaveGames[Selected]->Filename.GetChars());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(FSavegameManager, SetFileInfo)
|
||||||
|
{
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE(FSavegameManagerBase);
|
||||||
|
PARAM_INT(i);
|
||||||
|
self->SetFileInfo(i);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
unsigned FSavegameManagerBase::SavegameCount()
|
||||||
|
{
|
||||||
|
return SaveGames.Size();
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(FSavegameManager, SavegameCount)
|
||||||
|
{
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE(FSavegameManagerBase);
|
||||||
|
ACTION_RETURN_INT(self->SavegameCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
FSaveGameNode *FSavegameManagerBase::GetSavegame(int i)
|
||||||
|
{
|
||||||
|
return SaveGames[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(FSavegameManager, GetSavegame)
|
||||||
|
{
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE(FSavegameManagerBase);
|
||||||
|
PARAM_INT(i);
|
||||||
|
ACTION_RETURN_POINTER(self->GetSavegame(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
void FSavegameManagerBase::InsertNewSaveNode()
|
||||||
|
{
|
||||||
|
NewSaveNode.SaveTitle = GStrings("NEWSAVE");
|
||||||
|
NewSaveNode.bNoDelete = true;
|
||||||
|
SaveGames.Insert(0, &NewSaveNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(FSavegameManager, InsertNewSaveNode)
|
||||||
|
{
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE(FSavegameManagerBase);
|
||||||
|
self->InsertNewSaveNode();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
bool FSavegameManagerBase::RemoveNewSaveNode()
|
||||||
|
{
|
||||||
|
if (SaveGames[0] == &NewSaveNode)
|
||||||
|
{
|
||||||
|
SaveGames.Delete(0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(FSavegameManager, RemoveNewSaveNode)
|
||||||
|
{
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE(FSavegameManagerBase);
|
||||||
|
ACTION_RETURN_INT(self->RemoveNewSaveNode());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(FSavegameManager, ReadSaveStrings)
|
||||||
|
{
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE(FSavegameManagerBase);
|
||||||
|
self->ReadSaveStrings();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(FSavegameManager, ExtractSaveData)
|
||||||
|
{
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE(FSavegameManagerBase);
|
||||||
|
PARAM_INT(sel);
|
||||||
|
ACTION_RETURN_INT(self->ExtractSaveData(sel));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DEFINE_FIELD(FSaveGameNode, SaveTitle);
|
||||||
|
DEFINE_FIELD(FSaveGameNode, Filename);
|
||||||
|
DEFINE_FIELD(FSaveGameNode, bOldVersion);
|
||||||
|
DEFINE_FIELD(FSaveGameNode, bMissingWads);
|
||||||
|
DEFINE_FIELD(FSaveGameNode, bNoDelete);
|
||||||
|
|
||||||
|
DEFINE_FIELD_X(SavegameManager, FSavegameManagerBase, WindowSize);
|
||||||
|
DEFINE_FIELD_X(SavegameManager, FSavegameManagerBase, quickSaveSlot);
|
||||||
|
DEFINE_FIELD_X(SavegameManager, FSavegameManagerBase, SaveCommentString);
|
||||||
|
|
61
source/common/menu/savegamemanager.h
Normal file
61
source/common/menu/savegamemanager.h
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "zstring.h"
|
||||||
|
#include "tarray.h"
|
||||||
|
|
||||||
|
class FGameTexture;
|
||||||
|
class FSerializer;
|
||||||
|
|
||||||
|
// The savegame manager contains too much code that is game specific. Parts are shareable but need more work first.
|
||||||
|
struct FSaveGameNode
|
||||||
|
{
|
||||||
|
FString SaveTitle;
|
||||||
|
FString Filename;
|
||||||
|
bool bOldVersion = false;
|
||||||
|
bool bMissingWads = false;
|
||||||
|
bool bNoDelete = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FSavegameManagerBase
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
TArray<FSaveGameNode*> SaveGames;
|
||||||
|
FSaveGameNode NewSaveNode;
|
||||||
|
int LastSaved = -1;
|
||||||
|
int LastAccessed = -1;
|
||||||
|
FGameTexture *SavePic = nullptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
int WindowSize = 0;
|
||||||
|
FString SaveCommentString;
|
||||||
|
FSaveGameNode *quickSaveSlot = nullptr;
|
||||||
|
virtual ~FSavegameManagerBase();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int InsertSaveNode(FSaveGameNode *node);
|
||||||
|
virtual void PerformSaveGame(const char *fn, const char *sgdesc) = 0;
|
||||||
|
virtual void PerformLoadGame(const char *fn, bool) = 0;
|
||||||
|
virtual FString ExtractSaveComment(FSerializer &arc) = 0;
|
||||||
|
virtual FString BuildSaveName(const char* prefix, int slot) = 0;
|
||||||
|
public:
|
||||||
|
void NotifyNewSave(const FString &file, const FString &title, bool okForQuicksave, bool forceQuicksave);
|
||||||
|
void ClearSaveGames();
|
||||||
|
|
||||||
|
virtual void ReadSaveStrings() = 0;
|
||||||
|
void UnloadSaveData();
|
||||||
|
|
||||||
|
int RemoveSaveSlot(int index);
|
||||||
|
void LoadSavegame(int Selected);
|
||||||
|
void DoSave(int Selected, const char *savegamestring);
|
||||||
|
unsigned ExtractSaveData(int index);
|
||||||
|
void ClearSaveStuff();
|
||||||
|
bool DrawSavePic(int x, int y, int w, int h);
|
||||||
|
void DrawSaveComment(FFont *font, int cr, int x, int y, int scalefactor);
|
||||||
|
void SetFileInfo(int Selected);
|
||||||
|
unsigned SavegameCount();
|
||||||
|
FSaveGameNode *GetSavegame(int i);
|
||||||
|
void InsertNewSaveNode();
|
||||||
|
bool RemoveNewSaveNode();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
|
@ -22,10 +22,8 @@ extern cycle_t drawtime, actortime, thinktime, gameupdatetime;
|
||||||
extern bool r_NoInterpolate;
|
extern bool r_NoInterpolate;
|
||||||
|
|
||||||
struct MapRecord;
|
struct MapRecord;
|
||||||
struct FSaveGameNode;
|
|
||||||
extern MapRecord* g_nextmap;
|
extern MapRecord* g_nextmap;
|
||||||
extern int g_nextskill;
|
extern int g_nextskill;
|
||||||
extern FSaveGameNode* g_savenode;
|
|
||||||
|
|
||||||
extern FMemArena dump; // this is for memory blocks than cannot be deallocated without some huge effort. Put them in here so that they do not register on shutdown.
|
extern FMemArena dump; // this is for memory blocks than cannot be deallocated without some huge effort. Put them in here so that they do not register on shutdown.
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,8 @@ enum gameaction_t : int
|
||||||
ga_savegame, // save the game
|
ga_savegame, // save the game
|
||||||
ga_autosave, // autosave the game (for triggering a save from within the game.)
|
ga_autosave, // autosave the game (for triggering a save from within the game.)
|
||||||
ga_completed, // Level was exited.
|
ga_completed, // Level was exited.
|
||||||
ga_nextlevel // Actually start the next level.
|
ga_nextlevel, // Actually start the next level.
|
||||||
|
ga_loadgamehidecon
|
||||||
};
|
};
|
||||||
extern gamestate_t gamestate;
|
extern gamestate_t gamestate;
|
||||||
extern gameaction_t gameaction;
|
extern gameaction_t gameaction;
|
||||||
|
|
|
@ -33,21 +33,6 @@ struct FSavegameInfo
|
||||||
int currentsavever;
|
int currentsavever;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FSaveGameNode
|
|
||||||
{
|
|
||||||
FString SaveTitle;
|
|
||||||
FString Filename;
|
|
||||||
bool bOldVersion = false;
|
|
||||||
bool bMissingWads = false;
|
|
||||||
bool bNoDelete = false;
|
|
||||||
bool bIsExt = false;
|
|
||||||
|
|
||||||
bool isValid() const
|
|
||||||
{
|
|
||||||
return Filename.IsNotEmpty() && !bOldVersion && !bMissingWads;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ReservedSpace
|
struct ReservedSpace
|
||||||
{
|
{
|
||||||
int top;
|
int top;
|
||||||
|
@ -83,8 +68,8 @@ struct GameInterface
|
||||||
virtual bool DrawSpecialScreen(const DVector2 &origin, int tilenum) { return false; }
|
virtual bool DrawSpecialScreen(const DVector2 &origin, int tilenum) { return false; }
|
||||||
virtual void DrawCenteredTextScreen(const DVector2& origin, const char* text, int position, bool withbg = true);
|
virtual void DrawCenteredTextScreen(const DVector2& origin, const char* text, int position, bool withbg = true);
|
||||||
virtual double SmallFontScale() { return 1; }
|
virtual double SmallFontScale() { return 1; }
|
||||||
virtual bool SaveGame(FSaveGameNode*) { return true; }
|
virtual bool SaveGame() { return true; }
|
||||||
virtual bool LoadGame(FSaveGameNode*) { return true; }
|
virtual bool LoadGame() { return true; }
|
||||||
virtual void SerializeGameState(FSerializer& arc) {}
|
virtual void SerializeGameState(FSerializer& arc) {}
|
||||||
virtual void DrawPlayerSprite(const DVector2& origin, bool onteam) {}
|
virtual void DrawPlayerSprite(const DVector2& origin, bool onteam) {}
|
||||||
virtual void QuitToTitle() {}
|
virtual void QuitToTitle() {}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
**
|
**
|
||||||
**---------------------------------------------------------------------------
|
**---------------------------------------------------------------------------
|
||||||
** Copyright 2001-2010 Randy Heit
|
** Copyright 2001-2010 Randy Heit
|
||||||
** Copyright 2010-2017 Christoph Oelckers
|
** Copyright 2010-2020 Christoph Oelckers
|
||||||
** All rights reserved.
|
** All rights reserved.
|
||||||
**
|
**
|
||||||
** Redistribution and use in source and binary forms, with or without
|
** Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -45,103 +45,7 @@
|
||||||
#include "v_video.h"
|
#include "v_video.h"
|
||||||
#include "findfile.h"
|
#include "findfile.h"
|
||||||
#include "v_draw.h"
|
#include "v_draw.h"
|
||||||
|
#include "savegamehelp.h"
|
||||||
// Save name length limit for old binary formats.
|
|
||||||
#define OLDSAVESTRINGSIZE 24
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
// Save data maintenance
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
void FSavegameManager::ClearSaveGames()
|
|
||||||
{
|
|
||||||
for (unsigned i = 0; i<SaveGames.Size(); i++)
|
|
||||||
{
|
|
||||||
if (!SaveGames[i]->bNoDelete)
|
|
||||||
delete SaveGames[i];
|
|
||||||
}
|
|
||||||
SaveGames.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
FSavegameManager::~FSavegameManager()
|
|
||||||
{
|
|
||||||
ClearSaveGames();
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
// Save data maintenance
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int FSavegameManager::RemoveSaveSlot(int index)
|
|
||||||
{
|
|
||||||
int listindex = SaveGames[0]->bNoDelete ? index - 1 : index;
|
|
||||||
if (listindex < 0) return index;
|
|
||||||
|
|
||||||
remove(SaveGames[index]->Filename.GetChars());
|
|
||||||
UnloadSaveData();
|
|
||||||
|
|
||||||
FSaveGameNode *file = SaveGames[index];
|
|
||||||
|
|
||||||
if (quickSaveSlot == SaveGames[index])
|
|
||||||
{
|
|
||||||
quickSaveSlot = nullptr;
|
|
||||||
}
|
|
||||||
if (!file->bNoDelete) delete file;
|
|
||||||
|
|
||||||
if (LastSaved == listindex) LastSaved = -1;
|
|
||||||
else if (LastSaved > listindex) LastSaved--;
|
|
||||||
if (LastAccessed == listindex) LastAccessed = -1;
|
|
||||||
else if (LastAccessed > listindex) LastAccessed--;
|
|
||||||
|
|
||||||
SaveGames.Delete(index);
|
|
||||||
if ((unsigned)index >= SaveGames.Size()) index--;
|
|
||||||
ExtractSaveData(index);
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(FSavegameManager, RemoveSaveSlot)
|
|
||||||
{
|
|
||||||
PARAM_SELF_STRUCT_PROLOGUE(FSavegameManager);
|
|
||||||
PARAM_INT(sel);
|
|
||||||
ACTION_RETURN_INT(self->RemoveSaveSlot(sel));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int FSavegameManager::InsertSaveNode(FSaveGameNode *node)
|
|
||||||
{
|
|
||||||
if (SaveGames.Size() == 0)
|
|
||||||
{
|
|
||||||
return SaveGames.Push(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node->bOldVersion)
|
|
||||||
{ // Add node at bottom of list
|
|
||||||
return SaveGames.Push(node);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // Add node at top of list
|
|
||||||
unsigned int i;
|
|
||||||
for (i = 0; i < SaveGames.Size(); i++)
|
|
||||||
{
|
|
||||||
if (SaveGames[i]->bOldVersion || node->SaveTitle.CompareNoCase(SaveGames[i]->SaveTitle) <= 0)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SaveGames.Insert(i, node);
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
//
|
//
|
||||||
|
@ -153,7 +57,6 @@ int FSavegameManager::InsertSaveNode(FSaveGameNode *node)
|
||||||
|
|
||||||
void FSavegameManager::ReadSaveStrings()
|
void FSavegameManager::ReadSaveStrings()
|
||||||
{
|
{
|
||||||
#if 0
|
|
||||||
if (SaveGames.Size() == 0)
|
if (SaveGames.Size() == 0)
|
||||||
{
|
{
|
||||||
void *filefirst;
|
void *filefirst;
|
||||||
|
@ -162,235 +65,46 @@ void FSavegameManager::ReadSaveStrings()
|
||||||
|
|
||||||
LastSaved = LastAccessed = -1;
|
LastSaved = LastAccessed = -1;
|
||||||
quickSaveSlot = nullptr;
|
quickSaveSlot = nullptr;
|
||||||
filter = G_BuildSaveName("*." SAVEGAME_EXT, -1);
|
filter = G_BuildSaveName("*");
|
||||||
filefirst = I_FindFirst(filter.GetChars(), &c_file);
|
filefirst = I_FindFirst(filter.GetChars(), &c_file);
|
||||||
if (filefirst != ((void *)(-1)))
|
if (filefirst != ((void *)(-1)))
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
// I_FindName only returns the file's name and not its full path
|
// I_FindName only returns the file's name and not its full path
|
||||||
FString filepath = G_BuildSaveName(I_FindName(&c_file), -1);
|
FString filepath = G_BuildSaveName(I_FindName(&c_file));
|
||||||
|
|
||||||
std::unique_ptr<FResourceFile> savegame(FResourceFile::OpenResourceFile(filepath, true, true));
|
FResourceFile *savegame = FResourceFile::OpenResourceFile(filepath, true, true);
|
||||||
if (savegame != nullptr)
|
if (savegame != nullptr)
|
||||||
{
|
{
|
||||||
bool oldVer = false;
|
|
||||||
bool missing = false;
|
|
||||||
FResourceLump *info = savegame->FindLump("info.json");
|
FResourceLump *info = savegame->FindLump("info.json");
|
||||||
if (info == nullptr)
|
if (info == nullptr)
|
||||||
{
|
{
|
||||||
// savegame info not found. This is not a savegame so leave it alone.
|
// savegame info not found. This is not a savegame so leave it alone.
|
||||||
|
delete savegame;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
void *data = info->Lock();
|
auto fr = info->NewReader();
|
||||||
FSerializer arc;
|
FString title;
|
||||||
if (arc.OpenReader((const char *)data, info->LumpSize))
|
int check = G_ValidateSavegame(fr, &title, true);
|
||||||
|
fr.Close();
|
||||||
|
delete savegame;
|
||||||
|
if (check != 0)
|
||||||
{
|
{
|
||||||
int savever = 0;
|
|
||||||
arc("Save Version", savever);
|
|
||||||
FString engine = arc.GetString("Engine");
|
|
||||||
FString iwad = arc.GetString("Game WAD");
|
|
||||||
FString title = arc.GetString("Title");
|
|
||||||
|
|
||||||
|
|
||||||
if (engine.Compare(GAMESIG) != 0 || savever > SAVEVER)
|
|
||||||
{
|
|
||||||
// different engine or newer version:
|
|
||||||
// not our business. Leave it alone.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (savever < MINSAVEVER)
|
|
||||||
{
|
|
||||||
// old, incompatible savegame. List as not usable.
|
|
||||||
oldVer = true;
|
|
||||||
}
|
|
||||||
else if (iwad.CompareNoCase(fileSystem.GetResourceFileName(fileSystem.GetIwadNum())) == 0)
|
|
||||||
{
|
|
||||||
missing = !G_CheckSaveGameWads(arc, false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// different game. Skip this.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
FSaveGameNode *node = new FSaveGameNode;
|
FSaveGameNode *node = new FSaveGameNode;
|
||||||
node->Filename = filepath;
|
node->Filename = filepath;
|
||||||
node->bOldVersion = oldVer;
|
node->bOldVersion = check == -1;
|
||||||
node->bMissingWads = missing;
|
node->bMissingWads = check == -2;
|
||||||
node->SaveTitle = title;
|
node->SaveTitle = title;
|
||||||
InsertSaveNode(node);
|
InsertSaveNode(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else // check for old formats.
|
} while (I_FindNext (filefirst, &c_file) == 0);
|
||||||
{
|
I_FindClose (filefirst);
|
||||||
FileReader file;
|
|
||||||
if (file.OpenFile(filepath))
|
|
||||||
{
|
|
||||||
PNGHandle *png;
|
|
||||||
char sig[16];
|
|
||||||
char title[OLDSAVESTRINGSIZE + 1];
|
|
||||||
bool oldVer = true;
|
|
||||||
bool addIt = false;
|
|
||||||
bool missing = false;
|
|
||||||
|
|
||||||
// ZDoom 1.23 betas 21-33 have the savesig first.
|
|
||||||
// Earlier versions have the savesig second.
|
|
||||||
// Later versions have the savegame encapsulated inside a PNG.
|
|
||||||
//
|
|
||||||
// Old savegame versions are always added to the menu so
|
|
||||||
// the user can easily delete them if desired.
|
|
||||||
|
|
||||||
title[OLDSAVESTRINGSIZE] = 0;
|
|
||||||
|
|
||||||
if (nullptr != (png = M_VerifyPNG(file)))
|
|
||||||
{
|
|
||||||
char *ver = M_GetPNGText(png, "ZDoom Save Version");
|
|
||||||
if (ver != nullptr)
|
|
||||||
{
|
|
||||||
// An old version
|
|
||||||
if (!M_GetPNGText(png, "Title", title, OLDSAVESTRINGSIZE))
|
|
||||||
{
|
|
||||||
strncpy(title, I_FindName(&c_file), OLDSAVESTRINGSIZE);
|
|
||||||
}
|
|
||||||
addIt = true;
|
|
||||||
delete[] ver;
|
|
||||||
}
|
|
||||||
delete png;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
file.Seek(0, FileReader::SeekSet);
|
|
||||||
if (file.Read(sig, 16) == 16)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (strncmp(sig, "ZDOOMSAVE", 9) == 0)
|
|
||||||
{
|
|
||||||
if (file.Read(title, OLDSAVESTRINGSIZE) == OLDSAVESTRINGSIZE)
|
|
||||||
{
|
|
||||||
addIt = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
memcpy(title, sig, 16);
|
|
||||||
if (file.Read(title + 16, OLDSAVESTRINGSIZE - 16) == OLDSAVESTRINGSIZE - 16 &&
|
|
||||||
file.Read(sig, 16) == 16 &&
|
|
||||||
strncmp(sig, "ZDOOMSAVE", 9) == 0)
|
|
||||||
{
|
|
||||||
addIt = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (addIt)
|
|
||||||
{
|
|
||||||
FSaveGameNode *node = new FSaveGameNode;
|
|
||||||
node->Filename = filepath;
|
|
||||||
node->bOldVersion = true;
|
|
||||||
node->bMissingWads = false;
|
|
||||||
node->SaveTitle = title;
|
|
||||||
InsertSaveNode(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (I_FindNext(filefirst, &c_file) == 0);
|
|
||||||
I_FindClose(filefirst);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(FSavegameManager, ReadSaveStrings)
|
|
||||||
{
|
|
||||||
PARAM_SELF_STRUCT_PROLOGUE(FSavegameManager);
|
|
||||||
self->ReadSaveStrings();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
void FSavegameManager::NotifyNewSave(const FString &file, const FString &title, bool okForQuicksave, bool forceQuicksave)
|
|
||||||
{
|
|
||||||
FSaveGameNode *node;
|
|
||||||
|
|
||||||
if (file.IsEmpty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
ReadSaveStrings();
|
|
||||||
|
|
||||||
// See if the file is already in our list
|
|
||||||
for (unsigned i = 0; i<SaveGames.Size(); i++)
|
|
||||||
{
|
|
||||||
FSaveGameNode *node = SaveGames[i];
|
|
||||||
#ifdef __unix__
|
|
||||||
if (node->Filename.Compare(file) == 0)
|
|
||||||
#else
|
|
||||||
if (node->Filename.CompareNoCase(file) == 0)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
node->SaveTitle = title;
|
|
||||||
node->bOldVersion = false;
|
|
||||||
node->bMissingWads = false;
|
|
||||||
if (okForQuicksave)
|
|
||||||
{
|
|
||||||
if (quickSaveSlot == nullptr || quickSaveSlot == (FSaveGameNode*)1 || forceQuicksave) quickSaveSlot = node;
|
|
||||||
LastAccessed = LastSaved = i;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
node = new FSaveGameNode;
|
|
||||||
node->SaveTitle = title;
|
|
||||||
node->Filename = file;
|
|
||||||
node->bOldVersion = false;
|
|
||||||
node->bMissingWads = false;
|
|
||||||
int index = InsertSaveNode(node);
|
|
||||||
|
|
||||||
if (okForQuicksave)
|
|
||||||
{
|
|
||||||
if (quickSaveSlot == nullptr || quickSaveSlot == (FSaveGameNode*)1 || forceQuicksave) quickSaveSlot = node;
|
|
||||||
LastAccessed = LastSaved = index;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LastAccessed = ++LastSaved;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
// Loads the savegame
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
void FSavegameManager::LoadSavegame(int Selected)
|
|
||||||
{
|
|
||||||
//G_LoadGame(SaveGames[Selected]->Filename.GetChars(), true);
|
|
||||||
if (quickSaveSlot == (FSaveGameNode*)1)
|
|
||||||
{
|
|
||||||
quickSaveSlot = SaveGames[Selected];
|
|
||||||
}
|
|
||||||
M_ClearMenus();
|
|
||||||
LastAccessed = Selected;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(FSavegameManager, LoadSavegame)
|
|
||||||
{
|
|
||||||
PARAM_SELF_STRUCT_PROLOGUE(FSavegameManager);
|
|
||||||
PARAM_INT(sel);
|
|
||||||
self->LoadSavegame(sel);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
//
|
//
|
||||||
|
@ -398,41 +112,19 @@ DEFINE_ACTION_FUNCTION(FSavegameManager, LoadSavegame)
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
void FSavegameManager::DoSave(int Selected, const char *savegamestring)
|
void FSavegameManager::PerformLoadGame(const char *f, bool s)
|
||||||
{
|
{
|
||||||
#if 0
|
G_LoadGame(f);
|
||||||
if (Selected != 0)
|
|
||||||
{
|
|
||||||
auto node = SaveGames[Selected];
|
|
||||||
G_SaveGame(node->Filename.GetChars(), savegamestring);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Find an unused filename and save as that
|
|
||||||
FString filename;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0;; ++i)
|
|
||||||
{
|
|
||||||
filename = G_BuildSaveName("save", i);
|
|
||||||
if (!FileExists(filename))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
G_SaveGame(filename, savegamestring);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
M_ClearMenus();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(FSavegameManager, DoSave)
|
void FSavegameManager::PerformSaveGame(const char *f, const char *s)
|
||||||
{
|
{
|
||||||
PARAM_SELF_STRUCT_PROLOGUE(FSavegameManager);
|
G_SaveGame(f, s, false, false);
|
||||||
PARAM_INT(sel);
|
}
|
||||||
PARAM_STRING(name);
|
|
||||||
self->DoSave(sel, name);
|
FString FSavegameManager::BuildSaveName(const char* fn, int slot)
|
||||||
return 0;
|
{
|
||||||
|
return G_BuildSaveName(FStringf("%s%04d", fn, slot));
|
||||||
}
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
@ -441,259 +133,19 @@ DEFINE_ACTION_FUNCTION(FSavegameManager, DoSave)
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
unsigned FSavegameManager::ExtractSaveData(int index)
|
FString FSavegameManager::ExtractSaveComment(FSerializer& arc)
|
||||||
{
|
{
|
||||||
FResourceFile *resf;
|
FString comment, fcomment, ncomment, mtime;
|
||||||
FSaveGameNode *node;
|
|
||||||
|
|
||||||
if (index == -1)
|
arc("Creation Time", comment)
|
||||||
{
|
("Map Label", fcomment)
|
||||||
if (SaveGames.Size() > 0 && SaveGames[0]->bNoDelete)
|
("Map Name", ncomment)
|
||||||
{
|
("Map Time", mtime);
|
||||||
index = LastSaved + 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
index = LastAccessed < 0? 0 : LastAccessed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UnloadSaveData();
|
comment.AppendFormat("\n%s - %s\n%s", fcomment.GetChars(), ncomment.GetChars(), mtime.GetChars());
|
||||||
|
return comment;
|
||||||
if ((unsigned)index < SaveGames.Size() &&
|
|
||||||
(node = SaveGames[index]) &&
|
|
||||||
!node->Filename.IsEmpty() &&
|
|
||||||
!node->bOldVersion &&
|
|
||||||
(resf = FResourceFile::OpenResourceFile(node->Filename.GetChars(), true)) != nullptr)
|
|
||||||
{
|
|
||||||
FResourceLump *info = resf->FindLump("info.json");
|
|
||||||
if (info == nullptr)
|
|
||||||
{
|
|
||||||
// this should not happen because the file has already been verified.
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
void *data = info->Lock();
|
|
||||||
FSerializer arc;
|
|
||||||
if (arc.OpenReader((const char *)data, info->LumpSize))
|
|
||||||
{
|
|
||||||
FString comment;
|
|
||||||
|
|
||||||
FString time = arc.GetString("Creation Time");
|
|
||||||
FString pcomment = arc.GetString("Comment");
|
|
||||||
|
|
||||||
comment = time;
|
|
||||||
if (time.Len() > 0) comment += "\n";
|
|
||||||
comment += pcomment;
|
|
||||||
SaveCommentString = comment;
|
|
||||||
|
|
||||||
// Extract pic
|
|
||||||
FResourceLump *pic = resf->FindLump("savepic.png");
|
|
||||||
if (pic != nullptr)
|
|
||||||
{
|
|
||||||
FileReader picreader;
|
|
||||||
|
|
||||||
picreader.OpenMemoryArray([=](TArray<uint8_t> &array)
|
|
||||||
{
|
|
||||||
auto cache = pic->Lock();
|
|
||||||
array.Resize(pic->LumpSize);
|
|
||||||
memcpy(&array[0], cache, pic->LumpSize);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
PNGHandle *png = M_VerifyPNG(picreader);
|
|
||||||
if (png != nullptr)
|
|
||||||
{
|
|
||||||
SavePic = PNGTexture_CreateFromFile(png, node->Filename);
|
|
||||||
delete png;
|
|
||||||
if (SavePic && SavePic->GetDisplayWidth() == 1 && SavePic->GetDisplayHeight() == 1)
|
|
||||||
{
|
|
||||||
delete SavePic;
|
|
||||||
SavePic = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete resf;
|
|
||||||
}
|
|
||||||
return index;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(FSavegameManager, ExtractSaveData)
|
|
||||||
{
|
|
||||||
PARAM_SELF_STRUCT_PROLOGUE(FSavegameManager);
|
|
||||||
PARAM_INT(sel);
|
|
||||||
ACTION_RETURN_INT(self->ExtractSaveData(sel));
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
void FSavegameManager::UnloadSaveData()
|
|
||||||
{
|
|
||||||
if (SavePic != nullptr)
|
|
||||||
{
|
|
||||||
delete SavePic;
|
|
||||||
}
|
|
||||||
|
|
||||||
SaveCommentString = "";
|
|
||||||
SavePic = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(FSavegameManager, UnloadSaveData)
|
|
||||||
{
|
|
||||||
PARAM_SELF_STRUCT_PROLOGUE(FSavegameManager);
|
|
||||||
self->UnloadSaveData();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
void FSavegameManager::ClearSaveStuff()
|
|
||||||
{
|
|
||||||
UnloadSaveData();
|
|
||||||
if (quickSaveSlot == (FSaveGameNode*)1)
|
|
||||||
{
|
|
||||||
quickSaveSlot = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(FSavegameManager, ClearSaveStuff)
|
|
||||||
{
|
|
||||||
PARAM_SELF_STRUCT_PROLOGUE(FSavegameManager);
|
|
||||||
self->ClearSaveStuff();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
bool FSavegameManager::DrawSavePic(int x, int y, int w, int h)
|
|
||||||
{
|
|
||||||
if (SavePic == nullptr) return false;
|
|
||||||
DrawTexture(twod, SavePic, x, y, DTA_DestWidth, w, DTA_DestHeight, h, DTA_Masked, false, TAG_DONE);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(FSavegameManager, DrawSavePic)
|
|
||||||
{
|
|
||||||
PARAM_SELF_STRUCT_PROLOGUE(FSavegameManager);
|
|
||||||
PARAM_INT(x);
|
|
||||||
PARAM_INT(y);
|
|
||||||
PARAM_INT(w);
|
|
||||||
PARAM_INT(h);
|
|
||||||
ACTION_RETURN_BOOL(self->DrawSavePic(x, y, w, h));
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
void FSavegameManager::SetFileInfo(int Selected)
|
|
||||||
{
|
|
||||||
if (!SaveGames[Selected]->Filename.IsEmpty())
|
|
||||||
{
|
|
||||||
SaveCommentString.Format("File on disk:\n%s", SaveGames[Selected]->Filename.GetChars());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(FSavegameManager, SetFileInfo)
|
|
||||||
{
|
|
||||||
PARAM_SELF_STRUCT_PROLOGUE(FSavegameManager);
|
|
||||||
PARAM_INT(i);
|
|
||||||
self->SetFileInfo(i);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
unsigned FSavegameManager::SavegameCount()
|
|
||||||
{
|
|
||||||
return SaveGames.Size();
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(FSavegameManager, SavegameCount)
|
|
||||||
{
|
|
||||||
PARAM_SELF_STRUCT_PROLOGUE(FSavegameManager);
|
|
||||||
ACTION_RETURN_INT(self->SavegameCount());
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
FSaveGameNode *FSavegameManager::GetSavegame(int i)
|
|
||||||
{
|
|
||||||
return SaveGames[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(FSavegameManager, GetSavegame)
|
|
||||||
{
|
|
||||||
PARAM_SELF_STRUCT_PROLOGUE(FSavegameManager);
|
|
||||||
PARAM_INT(i);
|
|
||||||
ACTION_RETURN_POINTER(self->GetSavegame(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
void FSavegameManager::InsertNewSaveNode()
|
|
||||||
{
|
|
||||||
NewSaveNode.SaveTitle = GStrings["NEWSAVE"];
|
|
||||||
NewSaveNode.bNoDelete = true;
|
|
||||||
SaveGames.Insert(0, &NewSaveNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(FSavegameManager, InsertNewSaveNode)
|
|
||||||
{
|
|
||||||
PARAM_SELF_STRUCT_PROLOGUE(FSavegameManager);
|
|
||||||
self->InsertNewSaveNode();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
bool FSavegameManager::RemoveNewSaveNode()
|
|
||||||
{
|
|
||||||
if (SaveGames[0] == &NewSaveNode)
|
|
||||||
{
|
|
||||||
SaveGames.Delete(0);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(FSavegameManager, RemoveNewSaveNode)
|
|
||||||
{
|
|
||||||
PARAM_SELF_STRUCT_PROLOGUE(FSavegameManager);
|
|
||||||
ACTION_RETURN_INT(self->RemoveNewSaveNode());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
FSavegameManager savegameManager;
|
FSavegameManager savegameManager;
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(FSavegameManager, GetManager)
|
DEFINE_ACTION_FUNCTION(FSavegameManager, GetManager)
|
||||||
|
@ -702,15 +154,3 @@ DEFINE_ACTION_FUNCTION(FSavegameManager, GetManager)
|
||||||
ACTION_RETURN_POINTER(&savegameManager);
|
ACTION_RETURN_POINTER(&savegameManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DEFINE_FIELD(FSaveGameNode, SaveTitle);
|
|
||||||
DEFINE_FIELD(FSaveGameNode, Filename);
|
|
||||||
DEFINE_FIELD(FSaveGameNode, bOldVersion);
|
|
||||||
DEFINE_FIELD(FSaveGameNode, bMissingWads);
|
|
||||||
DEFINE_FIELD(FSaveGameNode, bNoDelete);
|
|
||||||
|
|
||||||
DEFINE_FIELD(FSavegameManager, WindowSize);
|
|
||||||
DEFINE_FIELD(FSavegameManager, quickSaveSlot);
|
|
||||||
DEFINE_FIELD(FSavegameManager, SaveCommentString);
|
|
||||||
|
|
||||||
|
|
|
@ -61,6 +61,8 @@
|
||||||
#include "razemenu.h"
|
#include "razemenu.h"
|
||||||
#include "mapinfo.h"
|
#include "mapinfo.h"
|
||||||
#include "statistics.h"
|
#include "statistics.h"
|
||||||
|
#include "i_net.h"
|
||||||
|
#include "savegamehelp.h"
|
||||||
|
|
||||||
EXTERN_CVAR(Int, cl_gfxlocalization)
|
EXTERN_CVAR(Int, cl_gfxlocalization)
|
||||||
EXTERN_CVAR(Bool, m_quickexit)
|
EXTERN_CVAR(Bool, m_quickexit)
|
||||||
|
@ -131,12 +133,12 @@ bool M_SetSpecialMenu(FName& menu, int param)
|
||||||
case NAME_Quitmenu:
|
case NAME_Quitmenu:
|
||||||
// This is no separate class
|
// This is no separate class
|
||||||
C_DoCommand("menu_quit");
|
C_DoCommand("menu_quit");
|
||||||
return true;
|
return false;
|
||||||
|
|
||||||
case NAME_EndGameMenu:
|
case NAME_EndGameMenu:
|
||||||
// This is no separate class
|
// This is no separate class
|
||||||
C_DoCommand("menu_endgame");
|
C_DoCommand("menu_endgame");
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// End of special checks
|
// End of special checks
|
||||||
|
@ -251,54 +253,43 @@ CCMD(menu_endgame)
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
CCMD (quicksave)
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
CCMD(quicksave)
|
||||||
{ // F6
|
{ // F6
|
||||||
#if 0
|
if (!gi->CanSave()) return;
|
||||||
if (!usergame || (players[consoleplayer].health <= 0 && !multiplayer))
|
|
||||||
{
|
|
||||||
S_Sound (CHAN_VOICE, CHANF_UI, "menu/invalid", snd_menuvolume, ATTN_NONE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gamestate != GS_LEVEL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// If the quick save rotation is enabled, it handles the save slot.
|
|
||||||
if (quicksaverotation)
|
|
||||||
{
|
|
||||||
G_DoQuickSave();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (savegameManager.quickSaveSlot == NULL || savegameManager.quickSaveSlot == (FSaveGameNode*)1)
|
if (savegameManager.quickSaveSlot == NULL || savegameManager.quickSaveSlot == (FSaveGameNode*)1)
|
||||||
{
|
{
|
||||||
S_Sound(CHAN_VOICE, CHANF_UI, "menu/activate", snd_menuvolume, ATTN_NONE);
|
M_StartControlPanel(true);
|
||||||
M_StartControlPanel(false);
|
|
||||||
M_SetMenu(NAME_Savegamemenu);
|
M_SetMenu(NAME_Savegamemenu);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto slot = savegameManager.quickSaveSlot;
|
||||||
|
|
||||||
// [mxd]. Just save the game, no questions asked.
|
// [mxd]. Just save the game, no questions asked.
|
||||||
if (!saveloadconfirmation)
|
if (!saveloadconfirmation)
|
||||||
{
|
{
|
||||||
G_SaveGame(savegameManager.quickSaveSlot->Filename.GetChars(), savegameManager.quickSaveSlot->SaveTitle.GetChars());
|
G_SaveGame(savegameManager.quickSaveSlot->Filename, savegameManager.quickSaveSlot->SaveTitle, true, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
S_Sound(CHAN_VOICE, CHANF_UI, "menu/activate", snd_menuvolume, ATTN_NONE);
|
|
||||||
|
|
||||||
FString tempstring = GStrings("QSPROMPT");
|
FString tempstring = GStrings("QSPROMPT");
|
||||||
tempstring.Substitute("%s", savegameManager.quickSaveSlot->SaveTitle.GetChars());
|
tempstring.Substitute("%s", slot->SaveTitle.GetChars());
|
||||||
|
M_StartControlPanel(true);
|
||||||
|
|
||||||
DMenu *newmenu = CreateMessageBoxMenu(CurrentMenu, tempstring, 0, false, NAME_None, []()
|
DMenu* newmenu = CreateMessageBoxMenu(CurrentMenu, tempstring, 0, false, NAME_None, []()
|
||||||
{
|
{
|
||||||
G_SaveGame(savegameManager.quickSaveSlot->Filename.GetChars(), savegameManager.quickSaveSlot->SaveTitle.GetChars());
|
G_SaveGame(savegameManager.quickSaveSlot->Filename, savegameManager.quickSaveSlot->SaveTitle, true, true);
|
||||||
S_Sound(CHAN_VOICE, CHANF_UI, "menu/dismiss", snd_menuvolume, ATTN_NONE);
|
});
|
||||||
M_ClearMenus();
|
|
||||||
});
|
|
||||||
|
|
||||||
M_ActivateMenu(newmenu);
|
M_ActivateMenu(newmenu);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
@ -307,21 +298,20 @@ CCMD (quicksave)
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
CCMD (quickload)
|
CCMD(quickload)
|
||||||
{ // F9
|
{ // F9
|
||||||
#if 0
|
|
||||||
if (netgame)
|
if (netgame)
|
||||||
{
|
{
|
||||||
M_StartControlPanel(true);
|
M_StartControlPanel(true);
|
||||||
M_StartMessage (GStrings("QLOADNET"), 1);
|
M_StartMessage(GStrings("QLOADNET"), 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (savegameManager.quickSaveSlot == NULL || savegameManager.quickSaveSlot == (FSaveGameNode*)1)
|
if (savegameManager.quickSaveSlot == nullptr || savegameManager.quickSaveSlot == (FSaveGameNode*)1)
|
||||||
{
|
{
|
||||||
M_StartControlPanel(true);
|
M_StartControlPanel(true);
|
||||||
// signal that whatever gets loaded should be the new quicksave
|
// signal that whatever gets loaded should be the new quicksave
|
||||||
savegameManager.quickSaveSlot = (FSaveGameNode *)1;
|
savegameManager.quickSaveSlot = (FSaveGameNode*)1;
|
||||||
M_SetMenu(NAME_Loadgamemenu);
|
M_SetMenu(NAME_Loadgamemenu);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -329,7 +319,7 @@ CCMD (quickload)
|
||||||
// [mxd]. Just load the game, no questions asked.
|
// [mxd]. Just load the game, no questions asked.
|
||||||
if (!saveloadconfirmation)
|
if (!saveloadconfirmation)
|
||||||
{
|
{
|
||||||
G_LoadGame(savegameManager.quickSaveSlot->Filename.GetChars());
|
G_LoadGame(savegameManager.quickSaveSlot->Filename);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
FString tempstring = GStrings("QLPROMPT");
|
FString tempstring = GStrings("QLPROMPT");
|
||||||
|
@ -337,14 +327,11 @@ CCMD (quickload)
|
||||||
|
|
||||||
M_StartControlPanel(true);
|
M_StartControlPanel(true);
|
||||||
|
|
||||||
DMenu *newmenu = CreateMessageBoxMenu(CurrentMenu, tempstring, 0, false, NAME_None, []()
|
DMenu* newmenu = CreateMessageBoxMenu(CurrentMenu, tempstring, 0, false, NAME_None, []()
|
||||||
{
|
{
|
||||||
G_LoadGame(savegameManager.quickSaveSlot->Filename.GetChars());
|
G_LoadGame(savegameManager.quickSaveSlot->Filename);
|
||||||
S_Sound(CHAN_VOICE, CHANF_UI, "menu/dismiss", snd_menuvolume, ATTN_NONE);
|
|
||||||
M_ClearMenus();
|
|
||||||
});
|
});
|
||||||
M_ActivateMenu(newmenu);
|
M_ActivateMenu(newmenu);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
#include "gamestruct.h"
|
#include "gamestruct.h"
|
||||||
#include "c_cvars.h"
|
#include "c_cvars.h"
|
||||||
|
#include "savegamemanager.h"
|
||||||
|
|
||||||
extern bool help_disabled;
|
extern bool help_disabled;
|
||||||
|
|
||||||
|
@ -14,45 +15,13 @@ void M_StartupSkillMenu(FNewGameStartup *gs);
|
||||||
void SetDefaultMenuColors();
|
void SetDefaultMenuColors();
|
||||||
void BuildGameMenus();
|
void BuildGameMenus();
|
||||||
|
|
||||||
// The savegame manager contains too much code that is game specific. Parts are shareable but need more work first.
|
class FSavegameManager : public FSavegameManagerBase
|
||||||
|
|
||||||
struct FSavegameManager
|
|
||||||
{
|
{
|
||||||
private:
|
void PerformSaveGame(const char *fn, const char *sgdesc) override;
|
||||||
TArray<FSaveGameNode*> SaveGames;
|
void PerformLoadGame(const char *fn, bool) override;
|
||||||
FSaveGameNode NewSaveNode;
|
FString ExtractSaveComment(FSerializer &arc) override;
|
||||||
int LastSaved = -1;
|
FString BuildSaveName(const char* prefix, int slot) override;
|
||||||
int LastAccessed = -1;
|
void ReadSaveStrings() override;
|
||||||
FGameTexture *SavePic = nullptr;
|
|
||||||
|
|
||||||
public:
|
|
||||||
int WindowSize = 0;
|
|
||||||
FString SaveCommentString;
|
|
||||||
FSaveGameNode *quickSaveSlot = nullptr;
|
|
||||||
~FSavegameManager();
|
|
||||||
|
|
||||||
private:
|
|
||||||
int InsertSaveNode(FSaveGameNode *node);
|
|
||||||
public:
|
|
||||||
void NotifyNewSave(const FString &file, const FString &title, bool okForQuicksave, bool forceQuicksave);
|
|
||||||
void ClearSaveGames();
|
|
||||||
|
|
||||||
void ReadSaveStrings();
|
|
||||||
void UnloadSaveData();
|
|
||||||
|
|
||||||
int RemoveSaveSlot(int index);
|
|
||||||
void LoadSavegame(int Selected);
|
|
||||||
void DoSave(int Selected, const char *savegamestring);
|
|
||||||
unsigned ExtractSaveData(int index);
|
|
||||||
void ClearSaveStuff();
|
|
||||||
bool DrawSavePic(int x, int y, int w, int h);
|
|
||||||
void DrawSaveComment(FFont *font, int cr, int x, int y, int scalefactor);
|
|
||||||
void SetFileInfo(int Selected);
|
|
||||||
unsigned SavegameCount();
|
|
||||||
FSaveGameNode *GetSavegame(int i);
|
|
||||||
void InsertNewSaveNode();
|
|
||||||
bool RemoveNewSaveNode();
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern FSavegameManager savegameManager;
|
extern FSavegameManager savegameManager;
|
||||||
|
|
|
@ -61,6 +61,7 @@ static FResourceFile *savereader;
|
||||||
void LoadEngineState();
|
void LoadEngineState();
|
||||||
void SaveEngineState();
|
void SaveEngineState();
|
||||||
void WriteSavePic(FileWriter* file, int width, int height);
|
void WriteSavePic(FileWriter* file, int width, int height);
|
||||||
|
extern FString BackupSaveGame;
|
||||||
|
|
||||||
CVAR(String, cl_savedir, "", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
CVAR(String, cl_savedir, "", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
|
|
||||||
|
@ -592,6 +593,48 @@ static int nextquicksave = -1;
|
||||||
self = 1;
|
self = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DoLoadGame(const char* name)
|
||||||
|
{
|
||||||
|
if (OpenSaveGameForRead(name))
|
||||||
|
{
|
||||||
|
if (gi->LoadGame())
|
||||||
|
{
|
||||||
|
gameaction = ga_level;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
I_Error("%s: Failed to load savegame", name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
I_Error("%s: Failed to open savegame", name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void G_LoadGame(const char *filename)
|
||||||
|
{
|
||||||
|
inputState.ClearAllInput();
|
||||||
|
gi->FreeLevelData();
|
||||||
|
DoLoadGame(filename);
|
||||||
|
BackupSaveGame = filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
void G_SaveGame(const char *fn, const char *desc, bool ok4q, bool forceq)
|
||||||
|
{
|
||||||
|
if (OpenSaveGameForWrite(fn, desc))
|
||||||
|
{
|
||||||
|
if (gi->SaveGame() && FinishSavegameWrite())
|
||||||
|
{
|
||||||
|
savegameManager.NotifyNewSave(fn, desc, ok4q, forceq);
|
||||||
|
Printf(PRINT_NOTIFY, "%s\n", GStrings("GAME SAVED"));
|
||||||
|
BackupSaveGame = fn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void M_Autosave()
|
void M_Autosave()
|
||||||
{
|
{
|
||||||
if (disableautosave) return;
|
if (disableautosave) return;
|
||||||
|
@ -611,12 +654,11 @@ void M_Autosave()
|
||||||
num.Int = nextautosave;
|
num.Int = nextautosave;
|
||||||
autosavenum.ForceSet(num, CVAR_Int);
|
autosavenum.ForceSet(num, CVAR_Int);
|
||||||
|
|
||||||
FSaveGameNode sg;
|
auto Filename = G_BuildSaveName(FStringf("auto%04d", nextautosave));
|
||||||
sg.Filename = G_BuildSaveName(FStringf("auto%04d", nextautosave));
|
|
||||||
readableTime = myasctime();
|
readableTime = myasctime();
|
||||||
sg.SaveTitle.Format("Autosave %s", readableTime);
|
FStringf SaveTitle("Autosave %s", readableTime);
|
||||||
nextautosave = (nextautosave + 1) % count;
|
nextautosave = (nextautosave + 1) % count;
|
||||||
//savegameManager.SaveGame(&sg, false, false);
|
G_SaveGame(Filename, SaveTitle, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
CCMD(autosave)
|
CCMD(autosave)
|
||||||
|
@ -643,11 +685,11 @@ CCMD(rotatingquicksave)
|
||||||
quicksavenum.ForceSet(num, CVAR_Int);
|
quicksavenum.ForceSet(num, CVAR_Int);
|
||||||
|
|
||||||
FSaveGameNode sg;
|
FSaveGameNode sg;
|
||||||
sg.Filename = G_BuildSaveName(FStringf("quick%04d", nextquicksave));
|
auto Filename = G_BuildSaveName(FStringf("quick%04d", nextquicksave));
|
||||||
readableTime = myasctime();
|
readableTime = myasctime();
|
||||||
sg.SaveTitle.Format("Quicksave %s", readableTime);
|
FStringf SaveTitle("Quicksave %s", readableTime);
|
||||||
nextquicksave = (nextquicksave + 1) % count;
|
nextquicksave = (nextquicksave + 1) % count;
|
||||||
//savegameManager.SaveGame(&sg, false, false);
|
G_SaveGame(Filename, SaveTitle, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,9 @@ class FileReader;
|
||||||
FString G_BuildSaveName (const char *prefix);
|
FString G_BuildSaveName (const char *prefix);
|
||||||
int G_ValidateSavegame(FileReader &fr, FString *savetitle, bool formenu);
|
int G_ValidateSavegame(FileReader &fr, FString *savetitle, bool formenu);
|
||||||
|
|
||||||
|
void G_LoadGame(const char* filename);
|
||||||
|
void G_SaveGame(const char* fn, const char* desc, bool ok4q, bool forceq);
|
||||||
|
|
||||||
void SaveEngineState();
|
void SaveEngineState();
|
||||||
void LoadEngineState();
|
void LoadEngineState();
|
||||||
void M_Autosave();
|
void M_Autosave();
|
||||||
|
|
|
@ -243,8 +243,8 @@ struct GameInterface : ::GameInterface
|
||||||
void MenuClosed() override;
|
void MenuClosed() override;
|
||||||
bool StartGame(FNewGameStartup& gs) override;
|
bool StartGame(FNewGameStartup& gs) override;
|
||||||
FSavegameInfo GetSaveSig() override;
|
FSavegameInfo GetSaveSig() override;
|
||||||
bool LoadGame(FSaveGameNode* sv) override;
|
bool LoadGame() override;
|
||||||
bool SaveGame(FSaveGameNode* sv) override;
|
bool SaveGame() override;
|
||||||
bool CanSave() override;
|
bool CanSave() override;
|
||||||
ReservedSpace GetReservedScreenSpace(int viewsize) override { return { 0, 24 }; }
|
ReservedSpace GetReservedScreenSpace(int viewsize) override { return { 0, 24 }; }
|
||||||
void QuitToTitle() override;
|
void QuitToTitle() override;
|
||||||
|
|
|
@ -34,14 +34,14 @@ void LoadTextureState();
|
||||||
|
|
||||||
static TArray<SavegameHelper*> sghelpers(TArray<SavegameHelper*>::NoInit);
|
static TArray<SavegameHelper*> sghelpers(TArray<SavegameHelper*>::NoInit);
|
||||||
|
|
||||||
bool GameInterface::SaveGame(FSaveGameNode* sv)
|
bool GameInterface::SaveGame()
|
||||||
{
|
{
|
||||||
for (auto sgh : sghelpers) sgh->Save();
|
for (auto sgh : sghelpers) sgh->Save();
|
||||||
SaveTextureState();
|
SaveTextureState();
|
||||||
return 1; // CHECKME
|
return 1; // CHECKME
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GameInterface::LoadGame(FSaveGameNode* sv)
|
bool GameInterface::LoadGame()
|
||||||
{
|
{
|
||||||
|
|
||||||
for (auto sgh : sghelpers) sgh->Load();
|
for (auto sgh : sghelpers) sgh->Load();
|
||||||
|
|
|
@ -2193,8 +2193,8 @@ struct GameInterface : ::GameInterface
|
||||||
bool CanSave() override;
|
bool CanSave() override;
|
||||||
bool StartGame(FNewGameStartup& gs) override;
|
bool StartGame(FNewGameStartup& gs) override;
|
||||||
FSavegameInfo GetSaveSig() override;
|
FSavegameInfo GetSaveSig() override;
|
||||||
bool LoadGame(FSaveGameNode* sv) override;
|
bool LoadGame() override;
|
||||||
bool SaveGame(FSaveGameNode* sv) override;
|
bool SaveGame() override;
|
||||||
void SetAmbience(bool on) override { if (on) StartAmbientSound(); else StopAmbientSound(); }
|
void SetAmbience(bool on) override { if (on) StartAmbientSound(); else StopAmbientSound(); }
|
||||||
FString GetCoordString() override;
|
FString GetCoordString() override;
|
||||||
ReservedSpace GetReservedScreenSpace(int viewsize) override;
|
ReservedSpace GetReservedScreenSpace(int viewsize) override;
|
||||||
|
|
|
@ -204,7 +204,7 @@ int LoadSymCodeInfo(MFILE_READ fil, void **ptr)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool GameInterface::SaveGame(FSaveGameNode *sv)
|
bool GameInterface::SaveGame()
|
||||||
{
|
{
|
||||||
MFILE_WRITE fil;
|
MFILE_WRITE fil;
|
||||||
int i,j;
|
int i,j;
|
||||||
|
@ -643,7 +643,7 @@ bool GameInterface::SaveGame(FSaveGameNode *sv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool GameInterface::LoadGame(FSaveGameNode* sv)
|
bool GameInterface::LoadGame()
|
||||||
{
|
{
|
||||||
MFILE_READ fil;
|
MFILE_READ fil;
|
||||||
int i,j,saveisshot=0;
|
int i,j,saveisshot=0;
|
||||||
|
|
|
@ -377,11 +377,9 @@ ImageScroller "CreditsMenu"
|
||||||
|
|
||||||
ListMenu "LoadGameMenu"
|
ListMenu "LoadGameMenu"
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
Caption "$MNU_LOADGAME"
|
|
||||||
Position 0, 40
|
Position 0, 40
|
||||||
Class "LoadMenu" // uses its own implementation
|
Class "LoadMenu" // uses its own implementation
|
||||||
*/
|
CaptionItem "$MNU_LOADGAME"
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------------
|
||||||
|
@ -392,11 +390,9 @@ ListMenu "LoadGameMenu"
|
||||||
|
|
||||||
ListMenu "SaveGameMenu"
|
ListMenu "SaveGameMenu"
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
Caption "$MNU_SAVEGAME"
|
|
||||||
Position 0, 40
|
Position 0, 40
|
||||||
Class "SaveMenu" // uses its own implementation
|
Class "SaveMenu" // uses its own implementation
|
||||||
*/
|
CaptionItem "$MNU_SAVEGAME"
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -389,6 +389,7 @@ struct Screen native
|
||||||
native static vararg void DrawChar(Font font, int normalcolor, double x, double y, int character, ...);
|
native static vararg void DrawChar(Font font, int normalcolor, double x, double y, int character, ...);
|
||||||
native static vararg void DrawText(Font font, int normalcolor, double x, double y, String text, ...);
|
native static vararg void DrawText(Font font, int normalcolor, double x, double y, String text, ...);
|
||||||
native static void DrawLine(int x0, int y0, int x1, int y1, Color color, int alpha = 255);
|
native static void DrawLine(int x0, int y0, int x1, int y1, Color color, int alpha = 255);
|
||||||
|
native static void DrawLineFrame(Color color, int x0, int y0, int w, int h, int thickness = 1);
|
||||||
native static void DrawThickLine(int x0, int y0, int x1, int y1, double thickness, Color color, int alpha = 255);
|
native static void DrawThickLine(int x0, int y0, int x1, int y1, double thickness, Color color, int alpha = 255);
|
||||||
native static Vector2, Vector2 VirtualToRealCoords(Vector2 pos, Vector2 size, Vector2 vsize, bool vbottom=false, bool handleaspect=true);
|
native static Vector2, Vector2 VirtualToRealCoords(Vector2 pos, Vector2 size, Vector2 vsize, bool vbottom=false, bool handleaspect=true);
|
||||||
native static double GetAspectRatio();
|
native static double GetAspectRatio();
|
||||||
|
|
|
@ -6,3 +6,25 @@ enum ETranslationTable
|
||||||
TRANSLATION_Remap,
|
TRANSLATION_Remap,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum gameaction_t : int
|
||||||
|
{
|
||||||
|
ga_nothing,
|
||||||
|
ga_level, // Switch to play mode without any initialization
|
||||||
|
ga_intro,
|
||||||
|
ga_intermission,
|
||||||
|
|
||||||
|
ga_startup, // go back to intro after uninitializing the game state
|
||||||
|
ga_mainmenu, // go back to main menu after uninitializing the game state
|
||||||
|
ga_mainmenunostopsound, // Same but doesn't stop playing sounds.
|
||||||
|
ga_creditsmenu, // go to the credits menu after uninitializing the game state
|
||||||
|
ga_newgame, // start a new game
|
||||||
|
ga_recordgame, // start a new demo recording (later)
|
||||||
|
ga_loadgame, // load a savegame and resume play.
|
||||||
|
ga_loadgameplaydemo, // load a savegame and play a demo.
|
||||||
|
ga_autoloadgame, // load last autosave and resume play.
|
||||||
|
ga_savegame, // save the game
|
||||||
|
ga_autosave, // autosave the game (for triggering a save from within the game.)
|
||||||
|
ga_completed, // Level was exited.
|
||||||
|
ga_nextlevel, // Actually start the next level.
|
||||||
|
ga_loadgamehidecon
|
||||||
|
};
|
||||||
|
|
|
@ -91,14 +91,11 @@ class LoadSaveMenu : ListMenu
|
||||||
int listboxRows;
|
int listboxRows;
|
||||||
int listboxHeight;
|
int listboxHeight;
|
||||||
int listboxRight;
|
int listboxRight;
|
||||||
int listboxBottom;
|
|
||||||
|
|
||||||
int commentLeft;
|
int commentLeft;
|
||||||
int commentTop;
|
int commentTop;
|
||||||
int commentWidth;
|
int commentWidth;
|
||||||
int commentHeight;
|
int commentHeight;
|
||||||
int commentRight;
|
|
||||||
int commentBottom;
|
|
||||||
int commentRows;
|
int commentRows;
|
||||||
|
|
||||||
bool mEntering;
|
bool mEntering;
|
||||||
|
@ -118,33 +115,34 @@ class LoadSaveMenu : ListMenu
|
||||||
override void Init(Menu parent, ListMenuDescriptor desc)
|
override void Init(Menu parent, ListMenuDescriptor desc)
|
||||||
{
|
{
|
||||||
Super.Init(parent, desc);
|
Super.Init(parent, desc);
|
||||||
|
bool aspect43 = true;
|
||||||
|
int Width43 = screen.GetHeight() * 4 / 3;
|
||||||
|
int Left43 = (screen.GetWidth() - Width43) / 2;
|
||||||
|
|
||||||
manager = SavegameManager.GetManager();
|
manager = SavegameManager.GetManager();
|
||||||
manager.ReadSaveStrings();
|
manager.ReadSaveStrings();
|
||||||
|
double wScale = Width43 / 640.;
|
||||||
|
|
||||||
savepicLeft = 10;
|
savepicLeft = Left43 + int(20 * wScale);
|
||||||
savepicTop = 54*CleanYfac;
|
savepicTop = mDesc.mYpos * screen.GetHeight() / 200 ;
|
||||||
savepicWidth = 216*screen.GetWidth() / 640;
|
savepicWidth = int(240 * wScale);
|
||||||
savepicHeight = 135*screen.GetHeight() / 400;
|
savepicHeight = int(180 * wScale);
|
||||||
|
|
||||||
FontScale = max(screen.GetHeight() / 480, 1);
|
FontScale = max(screen.GetHeight() / 480, 1);
|
||||||
rowHeight = int(max((NewConsoleFont.GetHeight() + 1) * FontScale, 1));
|
rowHeight = int(max((NewConsoleFont.GetHeight() + 1) * FontScale, 1));
|
||||||
|
|
||||||
listboxLeft = savepicLeft + savepicWidth + 14;
|
listboxLeft = savepicLeft + savepicWidth + int(20*wScale);
|
||||||
listboxTop = savepicTop;
|
listboxTop = savepicTop;
|
||||||
listboxWidth = screen.GetWidth() - listboxLeft - 10;
|
listboxWidth = Width43 + Left43 - listboxLeft - int(30 * wScale);
|
||||||
int listboxHeight1 = screen.GetHeight() - listboxTop - 10;
|
int listboxHeight1 = screen.GetHeight() - listboxTop - int(20*wScale);
|
||||||
listboxRows = (listboxHeight1 - 1) / rowHeight;
|
listboxRows = (listboxHeight1 - 1) / rowHeight;
|
||||||
listboxHeight = listboxRows * rowHeight + 1;
|
listboxHeight = listboxRows * rowHeight + 1;
|
||||||
listboxRight = listboxLeft + listboxWidth;
|
listboxRight = listboxLeft + listboxWidth;
|
||||||
listboxBottom = listboxTop + listboxHeight;
|
|
||||||
|
|
||||||
commentLeft = savepicLeft;
|
commentLeft = savepicLeft;
|
||||||
commentTop = savepicTop + savepicHeight + 16;
|
commentTop = savepicTop + savepicHeight + int(16 * wScale);
|
||||||
commentWidth = savepicWidth;
|
commentWidth = savepicWidth;
|
||||||
//commentHeight = (51+(screen.GetHeight()>200?10:0))*CleanYfac;
|
commentHeight = listboxHeight - savepicHeight - int(16 * wScale);
|
||||||
commentHeight = listboxHeight - savepicHeight - 16;
|
|
||||||
commentRight = commentLeft + commentWidth;
|
|
||||||
commentBottom = commentTop + commentHeight;
|
|
||||||
commentRows = commentHeight / rowHeight;
|
commentRows = commentHeight / rowHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,7 +167,8 @@ class LoadSaveMenu : ListMenu
|
||||||
|
|
||||||
virtual void DrawFrame(int left, int top, int width, int height)
|
virtual void DrawFrame(int left, int top, int width, int height)
|
||||||
{
|
{
|
||||||
// Todo: Define this in subclasses
|
let framecolor = Color(255, 80, 80, 80);
|
||||||
|
Screen.DrawLineFrame(framecolor, left, top, width, height, screen.GetHeight() / 240);
|
||||||
}
|
}
|
||||||
|
|
||||||
override void Drawer ()
|
override void Drawer ()
|
||||||
|
@ -182,31 +181,30 @@ class LoadSaveMenu : ListMenu
|
||||||
bool didSeeSelected = false;
|
bool didSeeSelected = false;
|
||||||
|
|
||||||
// Draw picture area
|
// Draw picture area
|
||||||
/* (todo: move to subclass)
|
|
||||||
if (gameaction == ga_loadgame || gameaction == ga_loadgamehidecon || gameaction == ga_savegame)
|
if (gameaction == ga_loadgame || gameaction == ga_loadgamehidecon || gameaction == ga_savegame)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
DrawFrame (savepicLeft, savepicTop, savepicWidth, savepicHeight);
|
DrawFrame(savepicLeft, savepicTop, savepicWidth, savepicHeight);
|
||||||
if (!manager.DrawSavePic(savepicLeft, savepicTop, savepicWidth, savepicHeight))
|
if (!manager.DrawSavePic(savepicLeft, savepicTop, savepicWidth, savepicHeight))
|
||||||
{
|
{
|
||||||
screen.Clear (savepicLeft, savepicTop, savepicLeft+savepicWidth, savepicTop+savepicHeight, 0, 0);
|
screen.Dim(0, 0.6, savepicLeft, savepicTop, savepicWidth, savepicHeight);
|
||||||
|
|
||||||
if (manager.SavegameCount() > 0)
|
if (manager.SavegameCount() > 0)
|
||||||
{
|
{
|
||||||
|
if (Selected >= manager.SavegameCount()) Selected = 0;
|
||||||
String text = (Selected == -1 || !manager.GetSavegame(Selected).bOldVersion)? Stringtable.Localize("$MNU_NOPICTURE") : Stringtable.Localize("$MNU_DIFFVERSION");
|
String text = (Selected == -1 || !manager.GetSavegame(Selected).bOldVersion)? Stringtable.Localize("$MNU_NOPICTURE") : Stringtable.Localize("$MNU_DIFFVERSION");
|
||||||
int textlen = NewSmallFont.StringWidth(text) * CleanXfac;
|
int textlen = NewSmallFont.StringWidth(text);
|
||||||
|
|
||||||
screen.DrawText (NewSmallFont, Font.CR_GOLD, savepicLeft+(savepicWidth-textlen)/2,
|
screen.DrawText (NewSmallFont, Font.CR_GOLD, (savepicLeft+(savepicWidth-textlen)/2) / FontScale,
|
||||||
savepicTop+(savepicHeight-rowHeight)/2, text, DTA_CleanNoMove, true);
|
(savepicTop+(savepicHeight-rowHeight)/2) / FontScale, text, DTA_VirtualWidthF, screen.GetWidth() / FontScale, DTA_VirtualHeightF, screen.GetHeight() / FontScale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw comment area
|
// Draw comment area
|
||||||
DrawFrame (commentLeft, commentTop, commentWidth, commentHeight);
|
DrawFrame (commentLeft, commentTop, commentWidth, commentHeight);
|
||||||
screen.Clear (commentLeft, commentTop, commentRight, commentBottom, 0, 0);
|
screen.Dim(0, 0.6, commentLeft, commentTop, commentWidth, commentHeight);
|
||||||
|
|
||||||
int numlinestoprint = min(commentRows, BrokenSaveComment? BrokenSaveComment.Count() : 0);
|
int numlinestoprint = min(commentRows, BrokenSaveComment? BrokenSaveComment.Count() : 0);
|
||||||
for(int i = 0; i < numlinestoprint; i++)
|
for(int i = 0; i < numlinestoprint; i++)
|
||||||
|
@ -218,7 +216,7 @@ class LoadSaveMenu : ListMenu
|
||||||
|
|
||||||
// Draw file area
|
// Draw file area
|
||||||
DrawFrame (listboxLeft, listboxTop, listboxWidth, listboxHeight);
|
DrawFrame (listboxLeft, listboxTop, listboxWidth, listboxHeight);
|
||||||
screen.Clear (listboxLeft, listboxTop, listboxRight, listboxBottom, 0, 0);
|
screen.Dim(0, 0.6, listboxLeft, listboxTop, listboxWidth, listboxHeight);
|
||||||
|
|
||||||
if (manager.SavegameCount() == 0)
|
if (manager.SavegameCount() == 0)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue