mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Changed the implementation of AutoQuickSave
* now it sets the number of pages used for quick saving. Added related macros for controlling the save slot with scripts.
This commit is contained in:
+4
-4
@@ -500,12 +500,12 @@ UseScrollingQuestsList=1
|
|||||||
ExtraSaveSlots=0
|
ExtraSaveSlots=0
|
||||||
|
|
||||||
;To use more than one save slot for quick saving (F6 key) without picking a slot beforehand, set the next two lines
|
;To use more than one save slot for quick saving (F6 key) without picking a slot beforehand, set the next two lines
|
||||||
;AutoQuickSave sets how many save slots on a page you want to use for quick saving (valid range: 1..10)
|
;AutoQuickSave sets how many pages you want to use for quick saving (valid range: 1..10)
|
||||||
;AutoQuickSavePage is the page number to use (valid range: 1..1000) if ExtraSaveSlots is enabled
|
;AutoQuickSavePage is the page number to start at (valid range: 1..1000, if ExtraSaveSlots is enabled)
|
||||||
;The quick saves will be rotated from the first slot on the page to the n-th slot
|
;The quick saves will be rotated from the first slot on the page to the last slot on the n-th page
|
||||||
;Set to 0 to disable. AutoQuickSave will use the current selected page if AutoQuickSavePage is disabled
|
;Set to 0 to disable. AutoQuickSave will use the current selected page if AutoQuickSavePage is disabled
|
||||||
AutoQuickSave=0
|
AutoQuickSave=0
|
||||||
AutoQuickSavePage=0
|
AutoQuickSavePage=1
|
||||||
|
|
||||||
;Set to 1 to speed up the HP/AC counter animations
|
;Set to 1 to speed up the HP/AC counter animations
|
||||||
;Set to 2 to update the HP/AC counters instantly
|
;Set to 2 to update the HP/AC counters instantly
|
||||||
|
|||||||
@@ -283,16 +283,10 @@
|
|||||||
if (get_flags(obj1) bwand FLAG_MULTIHEX) then distance--; \
|
if (get_flags(obj1) bwand FLAG_MULTIHEX) then distance--; \
|
||||||
if (get_flags(obj2) bwand FLAG_MULTIHEX) then distance--
|
if (get_flags(obj2) bwand FLAG_MULTIHEX) then distance--
|
||||||
|
|
||||||
|
|
||||||
/* sfall metarule3 function macros */
|
|
||||||
// sets the number of days (range 1...127) for the Frank Horrigan encounter, or disable the encounter if days is set to 0
|
|
||||||
#define set_horrigan_days(day) metarule3(200, day, 0, 0)
|
|
||||||
// clears the keyboard input buffer, use it in the HOOK_KEYPRESS hook to clear keyboard events before calling functions that are waiting for keyboard input
|
|
||||||
#define clear_keyboard_buffer metarule3(201, 0, 0, 0)
|
|
||||||
|
|
||||||
// checks if the specified PID number exists in the list of registered protos
|
// checks if the specified PID number exists in the list of registered protos
|
||||||
#define check_pid(pid) (get_proto_data(pid, 0) != -1)
|
#define check_pid(pid) (get_proto_data(pid, 0) != -1)
|
||||||
|
|
||||||
|
|
||||||
/* sfall_funcX macros */
|
/* sfall_funcX macros */
|
||||||
#define add_extra_msg_file(name) sfall_func1("add_extra_msg_file", name)
|
#define add_extra_msg_file(name) sfall_func1("add_extra_msg_file", name)
|
||||||
#define add_global_timer_event(time, fixedParam) sfall_func2("add_g_timer_event", time, fixedParam)
|
#define add_global_timer_event(time, fixedParam) sfall_func2("add_g_timer_event", time, fixedParam)
|
||||||
@@ -407,4 +401,19 @@
|
|||||||
#define set_fake_trait_npc(npc, trait, active, image, desc) sfall_func5("set_fake_trait_npc", npc, trait, active, image, desc)
|
#define set_fake_trait_npc(npc, trait, active, image, desc) sfall_func5("set_fake_trait_npc", npc, trait, active, image, desc)
|
||||||
#define set_selectable_perk_npc(npc, perk, active, image, desc) sfall_func5("set_selectable_perk_npc", npc, perk, active, image, desc)
|
#define set_selectable_perk_npc(npc, perk, active, image, desc) sfall_func5("set_selectable_perk_npc", npc, perk, active, image, desc)
|
||||||
|
|
||||||
|
|
||||||
|
/* sfall metarule3 function macros */
|
||||||
|
// sets the number of days (range 1...127) for the Frank Horrigan encounter, or disable the encounter if days is set to 0
|
||||||
|
#define set_horrigan_days(day) metarule3(200, day, 0, 0)
|
||||||
|
// clears the keyboard input buffer, use it in the HOOK_KEYPRESS hook to clear keyboard events before calling functions that are waiting for keyboard input
|
||||||
|
#define clear_keyboard_buffer metarule3(201, 0, 0, 0)
|
||||||
|
|
||||||
|
// functions to control the save slot
|
||||||
|
// Note: page and slot here are 0-indexed instead of 1-indexed displayed in game
|
||||||
|
#define get_current_save_slot metarule3(1000, 0, 0, 0) // returns the amount: page + slot
|
||||||
|
#define set_current_save_slot(page, slot) metarule3(1001, page, slot, 0)
|
||||||
|
#define get_current_quick_save_page metarule3(1002, 0, 0, 0)
|
||||||
|
#define get_current_quick_save_slot metarule3(1003, 0, 0, 0)
|
||||||
|
#define set_current_quick_save_slot(page, slot, check) metarule3(1004, page, slot, check) // check: 1 - don't check slot when saving
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -26,14 +26,23 @@
|
|||||||
namespace sfall
|
namespace sfall
|
||||||
{
|
{
|
||||||
|
|
||||||
DWORD LSPageOffset = 0;
|
static long LSPageOffset = 0;
|
||||||
|
|
||||||
static long LSButtDN = 0;
|
static long LSButtDN = 0;
|
||||||
static BYTE* SaveLoadSurface = nullptr;
|
static BYTE* SaveLoadSurface = nullptr;
|
||||||
|
|
||||||
static const char* filename = "%s\\savegame\\slotdat.ini";
|
static const char* filename = "%s\\savegame\\slotdat.ini";
|
||||||
|
|
||||||
static void SavePageOffsets() {
|
long ExtraSaveSlots::GetSaveSlot() {
|
||||||
|
return LSPageOffset + fo::var::slot_cursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExtraSaveSlots::SetSaveSlot(long page, long slot) {
|
||||||
|
if (GetQuickSavePage() >= 0 && page >= 0 && page <= 9990) LSPageOffset = page - (page % 10);;
|
||||||
|
if (slot >= 0 && slot < 10) fo::var::slot_cursor = slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
// save last slot position values to file
|
||||||
|
static long save_page_offsets() {
|
||||||
char SavePath[MAX_PATH], buffer[6];
|
char SavePath[MAX_PATH], buffer[6];
|
||||||
|
|
||||||
sprintf_s(SavePath, MAX_PATH, filename, fo::var::patches);
|
sprintf_s(SavePath, MAX_PATH, filename, fo::var::patches);
|
||||||
@@ -43,16 +52,8 @@ static void SavePageOffsets() {
|
|||||||
|
|
||||||
_itoa_s(LSPageOffset, buffer, 10);
|
_itoa_s(LSPageOffset, buffer, 10);
|
||||||
WritePrivateProfileStringA("POSITION", "PageOffset", buffer, SavePath);
|
WritePrivateProfileStringA("POSITION", "PageOffset", buffer, SavePath);
|
||||||
}
|
|
||||||
|
|
||||||
static void __declspec(naked) save_page_offsets(void) {
|
return fo::var::lsgwin; // restore original code
|
||||||
__asm {
|
|
||||||
// save last slot position values to file
|
|
||||||
call SavePageOffsets;
|
|
||||||
// restore original code
|
|
||||||
mov eax, dword ptr ds:[FO_VAR_lsgwin];
|
|
||||||
retn;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LoadPageOffsets() {
|
static void LoadPageOffsets() {
|
||||||
@@ -74,13 +75,12 @@ static void __declspec(naked) load_page_offsets(void) {
|
|||||||
__asm {
|
__asm {
|
||||||
// load last slot position values from file
|
// load last slot position values from file
|
||||||
call LoadPageOffsets;
|
call LoadPageOffsets;
|
||||||
// restore original code
|
mov edx, 0x50A480; // ASCII "SAV" (restore original code)
|
||||||
mov edx, 0x50A480; // ASCII "SAV"
|
|
||||||
retn;
|
retn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CreateButtons() {
|
static long create_page_buttons() {
|
||||||
DWORD winRef = fo::var::lsgwin;
|
DWORD winRef = fo::var::lsgwin;
|
||||||
|
|
||||||
// left button -10 | X | Y | W | H |HOn |HOff |BDown |BUp |PicUp |PicDown |? |ButType
|
// left button -10 | X | Y | W | H |HOn |HOff |BDown |BUp |PicUp |PicDown |? |ButType
|
||||||
@@ -93,14 +93,8 @@ static void CreateButtons() {
|
|||||||
fo::func::win_register_button(winRef, 248, 60, 24, 20, -1, 0x500, 0x551, 0x151, 0, 0, 0, 32);
|
fo::func::win_register_button(winRef, 248, 60, 24, 20, -1, 0x500, 0x551, 0x151, 0, 0, 0, 32);
|
||||||
// Set Number button
|
// Set Number button
|
||||||
fo::func::win_register_button(winRef, 140, 60, 60, 20, -1, -1, 'p', -1, 0, 0, 0, 32);
|
fo::func::win_register_button(winRef, 140, 60, 60, 20, -1, -1, 'p', -1, 0, 0, 0, 32);
|
||||||
}
|
|
||||||
|
|
||||||
static void __declspec(naked) create_page_buttons(void) {
|
return 101; // restore original value
|
||||||
__asm {
|
|
||||||
call CreateButtons;
|
|
||||||
mov eax, 0x65; // restore original code
|
|
||||||
retn;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetPageNum() {
|
static void SetPageNum() {
|
||||||
@@ -215,12 +209,12 @@ static long __fastcall CheckPage(long button) {
|
|||||||
break;
|
break;
|
||||||
case 0x14D: // right button
|
case 0x14D: // right button
|
||||||
LSPageOffset += 10;
|
LSPageOffset += 10;
|
||||||
if (LSPageOffset > 9990) LSPageOffset -= 10000; // to the first page
|
if (LSPageOffset >= 10000) LSPageOffset -= 10000; // to the first page
|
||||||
__asm call fo::funcoffs::gsound_red_butt_press_;
|
__asm call fo::funcoffs::gsound_red_butt_press_;
|
||||||
break;
|
break;
|
||||||
case 0x151: // fast right PGDN button
|
case 0x151: // fast right PGDN button
|
||||||
LSPageOffset += 100;
|
LSPageOffset += 100;
|
||||||
if (LSPageOffset > 9990) LSPageOffset -= 10000;
|
if (LSPageOffset >= 10000) LSPageOffset -= 10000;
|
||||||
__asm call fo::funcoffs::gsound_red_butt_press_;
|
__asm call fo::funcoffs::gsound_red_butt_press_;
|
||||||
break;
|
break;
|
||||||
case 'p': // p/P button pressed - start SetPageNum func
|
case 'p': // p/P button pressed - start SetPageNum func
|
||||||
@@ -237,15 +231,17 @@ static long __fastcall CheckPage(long button) {
|
|||||||
|
|
||||||
static void __declspec(naked) check_page_buttons(void) {
|
static void __declspec(naked) check_page_buttons(void) {
|
||||||
__asm {
|
__asm {
|
||||||
pushad;
|
push eax;
|
||||||
|
push ecx;
|
||||||
mov ecx, eax;
|
mov ecx, eax;
|
||||||
call CheckPage;
|
call CheckPage;
|
||||||
test eax, eax;
|
test eax, eax;
|
||||||
popad;
|
pop ecx;
|
||||||
jnz CheckUp;
|
pop eax;
|
||||||
|
jnz checkUp;
|
||||||
add dword ptr ds:[esp], 26; // set return to button pressed code
|
add dword ptr ds:[esp], 26; // set return to button pressed code
|
||||||
jmp fo::funcoffs::GetSlotList_; // reset page save list func
|
jmp fo::funcoffs::GetSlotList_; // reset page save list func
|
||||||
CheckUp:
|
checkUp:
|
||||||
// restore original code
|
// restore original code
|
||||||
cmp eax, 0x148; // up button
|
cmp eax, 0x148; // up button
|
||||||
retn;
|
retn;
|
||||||
@@ -326,25 +322,25 @@ static void DrawPageText() {
|
|||||||
|
|
||||||
static void __declspec(naked) draw_page_text(void) {
|
static void __declspec(naked) draw_page_text(void) {
|
||||||
__asm {
|
__asm {
|
||||||
pushad;
|
push eax;
|
||||||
call DrawPageText;
|
call DrawPageText;
|
||||||
popad;
|
pop eax;
|
||||||
mov ebp, 0x57; // restore original code
|
mov ebp, 87; // restore original code
|
||||||
retn;
|
retn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// add page num offset when reading and writing various save data files
|
// add page num offset when reading and writing various save data files
|
||||||
static void __declspec(naked) AddPageOffset01(void) {
|
static void __declspec(naked) add_page_offset_hack1(void) {
|
||||||
__asm {
|
__asm {
|
||||||
mov eax, dword ptr ds:[FO_VAR_slot_cursor]; // list position 0-9
|
mov eax, dword ptr ds:[FO_VAR_slot_cursor]; // list position 0-9
|
||||||
add eax, LSPageOffset; // add page num offset
|
add eax, LSPageOffset; // add page num offset
|
||||||
retn;
|
retn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// getting info for the 10 currently displayed save slots from save.dats
|
// getting info for the 10 currently displayed save slots from save.dats
|
||||||
static void __declspec(naked) AddPageOffset02(void) {
|
static void __declspec(naked) add_page_offset_hack2(void) {
|
||||||
__asm {
|
__asm {
|
||||||
push 0x50A514; // ASCII "SAVE.DAT"
|
push 0x50A514; // ASCII "SAVE.DAT"
|
||||||
lea eax, [ebx + 1];
|
lea eax, [ebx + 1];
|
||||||
@@ -355,7 +351,7 @@ static void __declspec(naked) AddPageOffset02(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// printing current 10 slot numbers
|
// printing current 10 slot numbers
|
||||||
static void __declspec(naked) AddPageOffset03(void) {
|
static void __declspec(naked) add_page_offset_hack3(void) {
|
||||||
__asm {
|
__asm {
|
||||||
inc eax;
|
inc eax;
|
||||||
add eax, LSPageOffset; // add page num offset
|
add eax, LSPageOffset; // add page num offset
|
||||||
@@ -366,32 +362,36 @@ static void __declspec(naked) AddPageOffset03(void) {
|
|||||||
|
|
||||||
static void EnableSuperSaving() {
|
static void EnableSuperSaving() {
|
||||||
// save/load button setup func
|
// save/load button setup func
|
||||||
MakeCalls(create_page_buttons, {0x47D80D});
|
MakeCall(0x47D80D, create_page_buttons); // LSGameStart_
|
||||||
|
|
||||||
// Draw button text
|
// Draw button text
|
||||||
MakeCalls(draw_page_text, {0x47E6E8});
|
MakeCall(0x47E6E8, draw_page_text); // ShowSlotList_
|
||||||
|
|
||||||
// check save/load buttons
|
// check save/load buttons
|
||||||
MakeCalls(check_page_buttons, {0x47BD49, 0x47CB1C});
|
MakeCalls(check_page_buttons, {0x47BD49, 0x47CB1C}); // SaveGame_, LoadGame_
|
||||||
|
|
||||||
// save current page and list positions to file on load/save scrn exit
|
// save current page and list positions to file on load/save scrn exit
|
||||||
MakeCalls(save_page_offsets, {0x47D828});
|
MakeCall(0x47D828, save_page_offsets); // LSGameEnd_
|
||||||
|
|
||||||
// load saved page and list positions from file
|
// load saved page and list positions from file
|
||||||
MakeCalls(load_page_offsets, {0x47B82B});
|
MakeCall(0x47B82B, load_page_offsets); // InitLoadSave_
|
||||||
|
|
||||||
// Add Load/Save page offset to Load/Save folder number
|
// Add Load/Save page offset to Load/Save folder number
|
||||||
MakeCalls(AddPageOffset01, {
|
MakeCalls(add_page_offset_hack1, {
|
||||||
0x47B929, 0x47D8DB, 0x47D9B0, 0x47DA34, 0x47DABF, 0x47DB58, 0x47DBE9,
|
0x47B929, // SaveGame_
|
||||||
0x47DC9C, 0x47EC77, 0x47F5AB, 0x47F694, 0x47F6EB, 0x47F7FB, 0x47F892,
|
0x47D8DB, 0x47D9B0, 0x47DA34, 0x47DABF, 0x47DB58, 0x47DBE9, // SaveSlot_
|
||||||
0x47FB86, 0x47FC3A, 0x47FCF2, 0x480117, 0x4801CF, 0x480234, 0x480310,
|
0x47DC9C, // LoadSlot_
|
||||||
0x4803F3, 0x48049F, 0x480512, 0x4805F2, 0x480767, 0x4807E6, 0x480839,
|
0x47EC77, // LoadTumbSlot_
|
||||||
0x4808D3
|
0x47F5AB, 0x47F694, 0x47F6EB, 0x47F7FB, 0x47F892, // GameMap2Slot_
|
||||||
|
0x47FB86, 0x47FC3A, 0x47FCF2, // SlotMap2Game_
|
||||||
|
0x480117, 0x4801CF, 0x480234, 0x480310, // SaveBackup_
|
||||||
|
0x4803F3, 0x48049F, 0x480512, 0x4805F2, // RestoreSave_
|
||||||
|
0x480767, 0x4807E6, 0x480839, 0x4808D3 // EraseSave_
|
||||||
});
|
});
|
||||||
|
|
||||||
MakeJump(0x47E5E1, AddPageOffset02);
|
MakeJump(0x47E5E1, add_page_offset_hack2); // GetSlotList_
|
||||||
|
|
||||||
MakeCalls(AddPageOffset03, {0x47E756});
|
MakeCall(0x47E756, add_page_offset_hack3); // ShowSlotList_
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GetSaveFileTime(char* filename, FILETIME* ftSlot) {
|
static void GetSaveFileTime(char* filename, FILETIME* ftSlot) {
|
||||||
@@ -408,43 +408,69 @@ static void GetSaveFileTime(char* filename, FILETIME* ftSlot) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* commentFmt = "%02d/%02d/%d - %02d:%02d:%02d";
|
static const char* autoFmt = "AUTO: %02d/%02d/%d - %02d:%02d:%02d";
|
||||||
|
static const char* quickFmt = "QUICK: %02d/%02d/%d - %02d:%02d:%02d";
|
||||||
|
|
||||||
static void CreateSaveComment(char* bufstr) {
|
static void CreateSaveComment(char* bufstr, bool isAuto) {
|
||||||
SYSTEMTIME stUTC, stLocal;
|
SYSTEMTIME stUTC, stLocal;
|
||||||
GetSystemTime(&stUTC);
|
GetSystemTime(&stUTC);
|
||||||
SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal);
|
SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal);
|
||||||
|
|
||||||
char buf[30];
|
const char* fmt = (isAuto) ? autoFmt : quickFmt;
|
||||||
sprintf_s(buf, commentFmt, stLocal.wDay, stLocal.wMonth, stLocal.wYear, stLocal.wHour, stLocal.wMinute, stLocal.wSecond);
|
sprintf_s(bufstr, 30, fmt, stLocal.wDay, stLocal.wMonth, stLocal.wYear, stLocal.wHour, stLocal.wMinute, stLocal.wSecond);
|
||||||
strcpy(bufstr, buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static long autoQuickSave = 0;
|
static long quickSavePageInit = -1;
|
||||||
static long quickSavePage = 0;
|
static long quickSavePageCount;
|
||||||
|
static long currentPageCount;
|
||||||
|
|
||||||
|
static long quickSavePage = -1;
|
||||||
|
static long quickSaveSlot = 0;
|
||||||
|
|
||||||
|
static long dontCheckSlot = 0;
|
||||||
|
static bool qFirst = true;
|
||||||
|
|
||||||
static FILETIME ftPrevSlot;
|
static FILETIME ftPrevSlot;
|
||||||
|
|
||||||
static DWORD __stdcall QuickSaveGame(fo::DbFile* file, char* filename) {
|
static DWORD __stdcall QuickSaveGame(fo::DbFile* file, char* filename) {
|
||||||
long currSlot = fo::var::slot_cursor;
|
long currSlot = quickSaveSlot;
|
||||||
|
|
||||||
if (file) { // This slot is not empty
|
if (dontCheckSlot) {
|
||||||
fo::func::db_fclose(file);
|
if (file) fo::func::db_fclose(file);
|
||||||
|
} else {
|
||||||
|
// for quick feature
|
||||||
|
if (file) { // This slot is not empty
|
||||||
|
fo::func::db_fclose(file);
|
||||||
|
|
||||||
FILETIME ftCurrSlot;
|
FILETIME ftCurrSlot;
|
||||||
GetSaveFileTime(filename, &ftCurrSlot);
|
GetSaveFileTime(filename, &ftCurrSlot);
|
||||||
|
|
||||||
if (currSlot == 0 || ftCurrSlot.dwHighDateTime > ftPrevSlot.dwHighDateTime ||
|
if (currSlot == 0 ||
|
||||||
(ftCurrSlot.dwHighDateTime == ftPrevSlot.dwHighDateTime && ftCurrSlot.dwLowDateTime > ftPrevSlot.dwLowDateTime))
|
ftCurrSlot.dwHighDateTime > ftPrevSlot.dwHighDateTime ||
|
||||||
{
|
(ftCurrSlot.dwHighDateTime == ftPrevSlot.dwHighDateTime && ftCurrSlot.dwLowDateTime > ftPrevSlot.dwLowDateTime))
|
||||||
ftPrevSlot.dwHighDateTime = ftCurrSlot.dwHighDateTime;
|
{
|
||||||
ftPrevSlot.dwLowDateTime = ftCurrSlot.dwLowDateTime;
|
ftPrevSlot.dwHighDateTime = ftCurrSlot.dwHighDateTime;
|
||||||
|
ftPrevSlot.dwLowDateTime = ftCurrSlot.dwLowDateTime;
|
||||||
|
|
||||||
if (++currSlot > autoQuickSave) {
|
if (!qFirst && currSlot < 9) {
|
||||||
currSlot = 0;
|
fo::var::slot_cursor = ++quickSaveSlot;
|
||||||
} else {
|
return 0x47B929; // check next slot
|
||||||
fo::var::slot_cursor = currSlot;
|
}
|
||||||
return 0x47B929; // check next slot
|
currSlot = 0; // set if currSlot >= 9
|
||||||
|
qFirst = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// next save slot
|
||||||
|
if (++quickSaveSlot >= 10) {
|
||||||
|
quickSaveSlot = 0;
|
||||||
|
// next page
|
||||||
|
if (quickSavePageCount > 1 && quickSavePageInit != -1) {
|
||||||
|
if (++currentPageCount >= quickSavePageCount) {
|
||||||
|
currentPageCount = 0;
|
||||||
|
quickSavePage = quickSavePageInit;
|
||||||
|
} else if (quickSavePage <= 9980) {
|
||||||
|
quickSavePage += 10;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -452,7 +478,7 @@ static DWORD __stdcall QuickSaveGame(fo::DbFile* file, char* filename) {
|
|||||||
// Save to slot
|
// Save to slot
|
||||||
fo::var::slot_cursor = currSlot;
|
fo::var::slot_cursor = currSlot;
|
||||||
fo::LSData* saveData = (fo::LSData*)FO_VAR_LSData;
|
fo::LSData* saveData = (fo::LSData*)FO_VAR_LSData;
|
||||||
CreateSaveComment(saveData[currSlot].comment);
|
CreateSaveComment(saveData[currSlot].comment, dontCheckSlot != 0);
|
||||||
fo::var::quick_done = 1;
|
fo::var::quick_done = 1;
|
||||||
|
|
||||||
return 0x47B9A4; // normal return
|
return 0x47B9A4; // normal return
|
||||||
@@ -472,13 +498,28 @@ static void __declspec(naked) SaveGame_hack0() {
|
|||||||
|
|
||||||
static void __declspec(naked) SaveGame_hack1() {
|
static void __declspec(naked) SaveGame_hack1() {
|
||||||
__asm {
|
__asm {
|
||||||
mov ds:[FO_VAR_slot_cursor], 0;
|
mov eax, quickSaveSlot;
|
||||||
|
mov ds:[FO_VAR_slot_cursor], eax;
|
||||||
mov eax, quickSavePage;
|
mov eax, quickSavePage;
|
||||||
mov LSPageOffset, eax;
|
mov LSPageOffset, eax;
|
||||||
retn;
|
retn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long ExtraSaveSlots::GetQuickSavePage() {
|
||||||
|
return quickSavePage;
|
||||||
|
}
|
||||||
|
|
||||||
|
long ExtraSaveSlots::GetQuickSaveSlot() {
|
||||||
|
return quickSaveSlot;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExtraSaveSlots::SetQuickSaveSlot(long page, long slot, long check) {
|
||||||
|
if (quickSavePage >= 0 && page >= 0 && page <= 9990) quickSavePage = page - (page % 10);
|
||||||
|
if (slot >= 0 && slot < 10) quickSaveSlot = slot;
|
||||||
|
dontCheckSlot = check;
|
||||||
|
}
|
||||||
|
|
||||||
void ExtraSaveSlots::init() {
|
void ExtraSaveSlots::init() {
|
||||||
bool extraSaveSlots = (IniReader::GetConfigInt("Misc", "ExtraSaveSlots", 0) != 0);
|
bool extraSaveSlots = (IniReader::GetConfigInt("Misc", "ExtraSaveSlots", 0) != 0);
|
||||||
if (extraSaveSlots) {
|
if (extraSaveSlots) {
|
||||||
@@ -487,19 +528,19 @@ void ExtraSaveSlots::init() {
|
|||||||
dlogr(" Done", DL_INIT);
|
dlogr(" Done", DL_INIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
autoQuickSave = IniReader::GetConfigInt("Misc", "AutoQuickSave", 0);
|
quickSavePageCount = IniReader::GetConfigInt("Misc", "AutoQuickSave", 0);
|
||||||
if (autoQuickSave > 0) {
|
if (quickSavePageCount > 0) {
|
||||||
dlog("Applying auto quick save patch.", DL_INIT);
|
dlog("Applying auto quick save patch.", DL_INIT);
|
||||||
if (autoQuickSave > 10) autoQuickSave = 10;
|
if (quickSavePageCount > 10) quickSavePageCount = 10;
|
||||||
autoQuickSave--; // reserved slot count
|
|
||||||
|
|
||||||
quickSavePage = IniReader::GetConfigInt("Misc", "AutoQuickSavePage", 0);
|
quickSavePage = IniReader::GetConfigInt("Misc", "AutoQuickSavePage", 1);
|
||||||
if (quickSavePage > 1000) quickSavePage = 1000;
|
if (quickSavePage > 1000) quickSavePage = 1000;
|
||||||
|
|
||||||
if (extraSaveSlots && quickSavePage > 0) {
|
if (extraSaveSlots && quickSavePage > 0) {
|
||||||
quickSavePage = (quickSavePage - 1) * 10;
|
quickSavePage = (quickSavePage - 1) * 10;
|
||||||
|
quickSavePageInit = quickSavePage;
|
||||||
MakeCall(0x47B923, SaveGame_hack1, 1);
|
MakeCall(0x47B923, SaveGame_hack1, 1);
|
||||||
} else {
|
} else { // for quickSavePage == 0
|
||||||
SafeWrite8(0x47B923, 0x89);
|
SafeWrite8(0x47B923, 0x89);
|
||||||
SafeWrite32(0x47B924, 0x5193B83D); // mov [slot_cursor], edi = 0
|
SafeWrite32(0x47B924, 0x5193B83D); // mov [slot_cursor], edi = 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,13 +23,18 @@
|
|||||||
namespace sfall
|
namespace sfall
|
||||||
{
|
{
|
||||||
|
|
||||||
extern DWORD LSPageOffset;
|
|
||||||
|
|
||||||
class ExtraSaveSlots : public Module {
|
class ExtraSaveSlots : public Module {
|
||||||
public:
|
public:
|
||||||
const char* name() { return "SuperSave"; }
|
const char* name() { return "SuperSave"; }
|
||||||
void init();
|
void init();
|
||||||
void exit() override;
|
void exit() override;
|
||||||
|
|
||||||
|
static long GetSaveSlot();
|
||||||
|
static void SetSaveSlot(long page, long slot);
|
||||||
|
|
||||||
|
static long GetQuickSavePage();
|
||||||
|
static long GetQuickSaveSlot();
|
||||||
|
static void SetQuickSaveSlot(long page, long slot, long check);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -215,10 +215,10 @@ capsMultiDrop:
|
|||||||
static void __declspec(naked) InvenActionExplosiveDropHack() {
|
static void __declspec(naked) InvenActionExplosiveDropHack() {
|
||||||
__asm {
|
__asm {
|
||||||
pushadc;
|
pushadc;
|
||||||
xor ecx, ecx; // no itemReplace
|
xor ecx, ecx; // no itemReplace
|
||||||
push 6; // event: item drop ground
|
push 6; // event: item drop ground
|
||||||
call InventoryMoveHook_Script; // edx - item
|
call InventoryMoveHook_Script; // edx - item
|
||||||
cmp eax, -1; // ret value
|
cmp eax, -1; // ret value
|
||||||
popadc;
|
popadc;
|
||||||
jnz noDrop;
|
jnz noDrop;
|
||||||
mov dword ptr ds:[FO_VAR_dropped_explosive], ebp; // overwritten engine code (ebp = 1)
|
mov dword ptr ds:[FO_VAR_dropped_explosive], ebp; // overwritten engine code (ebp = 1)
|
||||||
@@ -226,7 +226,7 @@ static void __declspec(naked) InvenActionExplosiveDropHack() {
|
|||||||
retn;
|
retn;
|
||||||
noDrop:
|
noDrop:
|
||||||
add esp, 4;
|
add esp, 4;
|
||||||
jmp InvenActionObjDropRet; // no drop
|
jmp InvenActionObjDropRet; // no drop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -626,15 +626,14 @@ void Inject_InventoryMoveHook() {
|
|||||||
Inject_SwitchHandHook();
|
Inject_SwitchHandHook();
|
||||||
MakeJump(0x4713A9, UseArmorHack); // old 0x4713A3
|
MakeJump(0x4713A9, UseArmorHack); // old 0x4713A3
|
||||||
MakeJump(0x476491, DropIntoContainerHack);
|
MakeJump(0x476491, DropIntoContainerHack);
|
||||||
MakeJump(0x471338, DropIntoContainerHandSlotHack);
|
MakeJumps(DropIntoContainerHandSlotHack, { 0x471338, 0x4712AB });
|
||||||
MakeJump(0x4712AB, DropIntoContainerHandSlotHack);
|
|
||||||
HookCall(0x471200, MoveInventoryHook);
|
HookCall(0x471200, MoveInventoryHook);
|
||||||
HookCall(0x476549, DropAmmoIntoWeaponHook); // old 0x476588
|
HookCall(0x476549, DropAmmoIntoWeaponHook); // old 0x476588
|
||||||
HookCalls(InvenActionCursorObjDropHook, {
|
HookCalls(InvenActionCursorObjDropHook, {
|
||||||
0x473851, 0x47386F,
|
0x473851, 0x47386F,
|
||||||
0x47379A // caps multi drop
|
0x47379A // caps multi drop
|
||||||
});
|
});
|
||||||
MakeCall(0x473807, InvenActionExplosiveDropHack, 1); // drop active explosives
|
MakeCall(0x473807, InvenActionExplosiveDropHack, 1); // drop active explosives
|
||||||
|
|
||||||
MakeCall(0x49B660, PickupObjectHack);
|
MakeCall(0x49B660, PickupObjectHack);
|
||||||
SafeWrite32(0x49B665, 0x850FD285); // test edx, edx
|
SafeWrite32(0x49B665, 0x850FD285); // test edx, edx
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ void __stdcall SetInLoop(DWORD mode, LoopFlag flag) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GetSavePath(char* buf, char* ftype) {
|
void GetSavePath(char* buf, char* ftype) {
|
||||||
sprintf(buf, "%s\\savegame\\slot%.2d\\sfall%s.sav", fo::var::patches, fo::var::slot_cursor + 1 + LSPageOffset, ftype); //add SuperSave Page offset
|
sprintf(buf, "%s\\savegame\\slot%.2d\\sfall%s.sav", fo::var::patches, ExtraSaveSlots::GetSaveSlot() + 1, ftype); //add SuperSave Page offset
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __stdcall SaveGame2() {
|
static void __stdcall SaveGame2() {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include "..\main.h"
|
#include "..\main.h"
|
||||||
#include "..\FalloutEngine\Fallout2.h"
|
#include "..\FalloutEngine\Fallout2.h"
|
||||||
|
#include "ExtraSaveSlots.h"
|
||||||
#include "LoadGameHook.h"
|
#include "LoadGameHook.h"
|
||||||
#include "PartyControl.h"
|
#include "PartyControl.h"
|
||||||
|
|
||||||
@@ -36,7 +37,14 @@ static bool HorriganEncounterDisabled = false;
|
|||||||
enum class MetaruleFunction : long {
|
enum class MetaruleFunction : long {
|
||||||
SET_HORRIGAN_ENCOUNTER = 200, // sets the number of days for the Frank Horrigan encounter or disable encounter
|
SET_HORRIGAN_ENCOUNTER = 200, // sets the number of days for the Frank Horrigan encounter or disable encounter
|
||||||
CLEAR_KEYBOARD_BUFFER = 201, // clears the keyboard input buffer, should be used in the HOOK_KEYPRESS hook to clear keyboard events in some cases
|
CLEAR_KEYBOARD_BUFFER = 201, // clears the keyboard input buffer, should be used in the HOOK_KEYPRESS hook to clear keyboard events in some cases
|
||||||
EXT_PARTY_ORDER_ATTACK = 999
|
PARTY_ORDER_ATTACK = 999,
|
||||||
|
|
||||||
|
// save slot controls
|
||||||
|
GET_CURRENT_SAVE_SLOT = 1000,
|
||||||
|
SET_CURRENT_SAVE_SLOT = 1001,
|
||||||
|
GET_CURRENT_QSAVE_PAGE = 1002,
|
||||||
|
GET_CURRENT_QSAVE_SLOT = 1003,
|
||||||
|
SET_CURRENT_QSAVE_SLOT = 1004,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -63,9 +71,24 @@ static long __fastcall op_metarule3_ext(long metafunc, long* args) {
|
|||||||
case MetaruleFunction::CLEAR_KEYBOARD_BUFFER:
|
case MetaruleFunction::CLEAR_KEYBOARD_BUFFER:
|
||||||
__asm call fo::funcoffs::kb_clear_;
|
__asm call fo::funcoffs::kb_clear_;
|
||||||
break;
|
break;
|
||||||
case MetaruleFunction::EXT_PARTY_ORDER_ATTACK:
|
case MetaruleFunction::PARTY_ORDER_ATTACK:
|
||||||
PartyControl::OrderAttackPatch();
|
PartyControl::OrderAttackPatch();
|
||||||
break;
|
break;
|
||||||
|
case MetaruleFunction::GET_CURRENT_SAVE_SLOT:
|
||||||
|
result = ExtraSaveSlots::GetSaveSlot();
|
||||||
|
break;
|
||||||
|
case MetaruleFunction::SET_CURRENT_SAVE_SLOT:
|
||||||
|
ExtraSaveSlots::SetSaveSlot(args[0], args[1]);
|
||||||
|
break;
|
||||||
|
case MetaruleFunction::GET_CURRENT_QSAVE_PAGE:
|
||||||
|
result = ExtraSaveSlots::GetQuickSavePage();
|
||||||
|
break;
|
||||||
|
case MetaruleFunction::GET_CURRENT_QSAVE_SLOT:
|
||||||
|
result = ExtraSaveSlots::GetQuickSaveSlot();
|
||||||
|
break;
|
||||||
|
case MetaruleFunction::SET_CURRENT_QSAVE_SLOT:
|
||||||
|
ExtraSaveSlots::SetQuickSaveSlot(args[0], args[1], args[2]);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
fo::func::debug_printf("\nOPCODE ERROR: metarule3(%d, ...) - metarule function number does not exist.\n > Script: %s, procedure %s.",
|
fo::func::debug_printf("\nOPCODE ERROR: metarule3(%d, ...) - metarule function number does not exist.\n > Script: %s, procedure %s.",
|
||||||
metafunc, fo::var::currentProgram->fileName, fo::func::findCurrentProc(fo::var::currentProgram));
|
metafunc, fo::var::currentProgram->fileName, fo::func::findCurrentProc(fo::var::currentProgram));
|
||||||
|
|||||||
Reference in New Issue
Block a user