Reworked autosave system - rotating saves no longer get overwritten by regular autosaves on travel and sleep
This commit is contained in:
parent
b46a7f7071
commit
962a0861cd
@ -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)
BIN
SKSE/Plugins/EnderalSE.dll
(Stored with Git LFS)
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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)
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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": {
|
||||||
|
@ -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
|
||||||
|
@ -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
|
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user