Reworked autosave system - rotating saves no longer get overwritten by regular autosaves on travel and sleep

This commit is contained in:
Eddoursul 2023-12-03 23:45:37 +01:00
parent b46a7f7071
commit 962a0861cd
11 changed files with 95 additions and 44 deletions

View File

@ -9,7 +9,7 @@ sResourceArchiveList=Skyrim - Misc.bsa, Skyrim - Shaders.bsa, Skyrim - Interface
sResourceArchiveList2=Skyrim - Textures8.bsa, Skyrim - Patch.bsa, E - Meshes.bsa, E - Textures1.bsa, E - Textures2.bsa, E - Sounds.bsa, L - Voices.bsa, E - Misc.bsa, E - Update.bsa, L - Textures.bsa sResourceArchiveList2=Skyrim - Textures8.bsa, Skyrim - Patch.bsa, E - Meshes.bsa, E - Textures1.bsa, E - Textures2.bsa, E - Sounds.bsa, L - Voices.bsa, E - Misc.bsa, E - Update.bsa, L - Textures.bsa
[SaveGame] [SaveGame]
iAutoSaveCount=10 iAutoSaveCount=5
[MapMenu] [MapMenu]
; Paper map settings ; Paper map settings

BIN
SKSE/Plugins/EnderalSE.dll (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

View File

@ -6,7 +6,7 @@ message("Using toolchain file ${CMAKE_TOOLCHAIN_FILE}.")
######################################################################################################################## ########################################################################################################################
project( project(
EnderalSE EnderalSE
VERSION 1.1.0 VERSION 2.1.0
DESCRIPTION "Enderal SE DLL" DESCRIPTION "Enderal SE DLL"
LANGUAGES CXX) LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD 23)

View File

@ -62,6 +62,31 @@ namespace Papyrus::PapyrusFunctions
return result; return result;
} }
// Copied from Named Quicksaves by Ryan McKenzie (MIT)
RE::BSFixedString GetPlayerHash(RE::StaticFunctionTag*)
{
char buf[] = "DEADBEEF";
auto saveData = RE::BSWin32SaveDataSystemUtility::GetSingleton();
if (saveData->profileHash == static_cast<std::uint32_t>(-1)) {
std::snprintf(buf, sizeof(buf), "%08o", 0);
} else {
std::snprintf(buf, sizeof(buf), "%08X", saveData->profileHash);
}
return buf;
}
RE::BSFixedString StringToHex(RE::StaticFunctionTag*, RE::BSFixedString a_string)
{
std::string_view str(a_string);
std::stringstream sstream;
for (auto ch : str) {
sstream << std::uppercase << std::hex << static_cast<int>(ch);
}
return sstream.str();
}
inline void Bind(VM& a_vm) inline void Bind(VM& a_vm)
{ {
BIND(CreatePotion); BIND(CreatePotion);
@ -72,5 +97,9 @@ namespace Papyrus::PapyrusFunctions
logger::info("{}", "Registered GetCurrentContainer"sv); logger::info("{}", "Registered GetCurrentContainer"sv);
BIND(GetPlayerFollowers); BIND(GetPlayerFollowers);
logger::info("{}", "Registered GetPlayerFollowers"sv); logger::info("{}", "Registered GetPlayerFollowers"sv);
BIND(GetPlayerHash);
logger::info("{}", "Registered GetPlayerHash"sv);
BIND(StringToHex);
logger::info("{}", "Registered StringToHex"sv);
} }
} }

View File

@ -1,10 +1,10 @@
{ {
"$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json", "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json",
"name": "enderal-se", "name": "enderal-se",
"version-string": "1.0.0", "version-string": "2.1.0",
"port-version": 0, "port-version": 0,
"description": "Enderal SE Helper", "description": "Enderal SE Helper",
"homepage": "https://eddoursul.win/mods/enderal-se/", "homepage": "https://mod.pub/enderal-se/38-enderal-se",
"license": "LGPL-3.0", "license": "LGPL-3.0",
"features": { "features": {
"plugin": { "plugin": {

View File

@ -1,7 +1,9 @@
Scriptname _00E_AutosaveIntervalAlias extends ReferenceAlias Hidden Scriptname _00E_AutosaveIntervalAlias extends ReferenceAlias Hidden
Event OnPlayerLoadGame() Event OnInit()
(GetOwningQuest() as _00E_AutoSaveSystem_Functions).UpdateAutoSaveInterval()
EndEvent
Event OnPlayerLoadGame()
(GetOwningQuest() as _00E_AutoSaveSystem_Functions).UpdateAutoSaveInterval() (GetOwningQuest() as _00E_AutoSaveSystem_Functions).UpdateAutoSaveInterval()
EndEvent EndEvent

View File

@ -1,38 +1,47 @@
Scriptname _00E_AutoSaveSystem_Functions extends Quest Scriptname _00E_AutoSaveSystem_Functions extends Quest
Event OnInit() ; Save Name Structure (from NQS NamedQuicksaves by Ryan McKenzie)
fUpdateTime = Utility.GetIniFloat("fAutosaveEveryXMins:SaveGame") ; Save3_0C2D58E2_0_507269736F6E6572_Tamriel_000002_20180503063315_4_1.ess
If fUpdateTime <= 0.0 ; just in case ; Save3: Type and index of save
fUpdateTime = 60 ; 0C2D58E2: Unique hash used to identify your save profile. Regenerated on closing racemenu.
EndIf ; 0: Flag for modded game.
; 507269736F6E6572: Character name in hex.
RegisterForSingleUpdate(fUpdateTime*60) ; Tamriel: coc code.
; 000002: Days, hours, minutes played.
EndEvent ; 20180503063315: Year, month, day, hour, minute, second in GMT + 0.
; 4: Player level.
; 1: Unknown flag.
Event OnUpdate() Event OnUpdate()
If bAutosaveSystemStopped == false If bAutosaveSystemStopped
If Utility.IsInMenuMode() == false && UI.IsTextInputEnabled() == false && UI.IsMenuOpen("Dialogue Menu") == false && PlayerREF.IsDead() == false && PlayerREF.IsInCombat() == false && Game.IsFightingControlsEnabled() == true return
Game.RequestAutoSave() EndIf
RegisterForSingleUpdate(fUpdateTime*60)
Else Actor PlayerREF = Game.GetForm(0x14) as Actor
If PlayerREF.IsInCombat() || ! Game.IsFightingControlsEnabled() || PlayerREF.IsDead() || Utility.IsInMenuMode() || UI.IsTextInputEnabled() || UI.IsMenuOpen("Dialogue Menu")
RegisterForSingleUpdate(5) RegisterForSingleUpdate(5)
EndIf return
EndIf endif
; Eddoursul: Index prefixed with 0 ensures the engine does not rotate these saves out
Game.SaveGame("Autosave0" + iAutosaveIndex + "_" + EnderalFunctions.GetPlayerHash() + "_0_" + EnderalFunctions.StringToHex(PlayerREF.GetActorBase().GetName()) + "_EnderalSE_000000_00000000000000_1_1")
iAutosaveIndex += 1
if iAutosaveIndex >= Utility.GetIniInt("iAutoSaveCount:SaveGame")
iAutosaveIndex = 0
endif
RegisterForSingleUpdate(fUpdateTime*60)
EndEvent EndEvent
; called from _00E_AutosaveIntervalAlias to update ini setting fAutosaveEveryXMins in case it was changed ; called from _00E_AutosaveIntervalAlias to update ini setting fAutosaveEveryXMins in case it was changed
Function UpdateAutoSaveInterval() Function UpdateAutoSaveInterval()
fUpdateTime = Utility.GetIniFloat("fAutosaveEveryXMins:SaveGame") fUpdateTime = GetAutosaveEveryXMins()
If fUpdateTime <= 0.0 ; just in case
fUpdateTime = 60
EndIf
UnregisterForUpdate()
RegisterForSingleUpdate(fUpdateTime*60) RegisterForSingleUpdate(fUpdateTime*60)
EndFunction EndFunction
@ -46,26 +55,28 @@ Function ResumeAutosaveSystemInXMinutes(float _fMinutes = 0.0)
If _fMinutes == 0.0 If _fMinutes == 0.0
_fMinutes = fUpdateTime _fMinutes = fUpdateTime
If _fMinutes == 0.0 ; just in case If _fMinutes <= 0.0 ; just in case
_fMinutes = 60 _fMinutes = 30
EndIf EndIf
EndIf EndIf
UnregisterForUpdate() ; just in case again
RegisterForSingleUpdate(_fMinutes*60) RegisterForSingleUpdate(_fMinutes*60)
bAutosaveSystemStopped = false bAutosaveSystemStopped = false
EndFunction EndFunction
; not used yet btw / maybe will never be used float function GetAutosaveEveryXMins()
; called shortly before the end of every quest, parameter is always the quest name
Function RequestHardSave(string _sQuestName)
Utility.Wait(0.1) ; in case we are in a menu (debug message boxes / dialogue etc) float fUpdateMinutes = Utility.GetIniFloat("fAutosaveEveryXMins:SaveGame")
Game.SaveGame(_sQuestName)
EndFunction If fUpdateMinutes <= 0.0 ; just in case
fUpdateMinutes = 30
EndIf
return fUpdateMinutes
endfunction
bool bAutosaveSystemStopped = false bool bAutosaveSystemStopped = false
int iAutosaveIndex = 0
float fUpdateTime float fUpdateTime
Actor Property PlayerREF Auto

View File

@ -10,6 +10,15 @@ int function GetNewGameCount() native global
Actor[] function GetPlayerFollowers() native global Actor[] function GetPlayerFollowers() native global
; Gets the player hash used to uniquely identify the player's save profile.
; RETURN - Returns the player hash as an 8-digit string.
String Function GetPlayerHash() Global Native
; Converts the given string to it's hexadecimal equivalent. Preserves case.
; a_string - The string to convert to hexadecimal.
; RETURN - Returns the hexadecimal equivalent of the passed string.
String Function StringToHex(String a_string) Global Native
bool function IsDLLLoaded() global bool function IsDLLLoaded() global
int iVer = SKSE.GetPluginVersion("EnderalSE") int iVer = SKSE.GetPluginVersion("EnderalSE")
return iVer > 0 return iVer > 0