From d89603e56dd595e5f49122d5c9d073c7ff0b325c Mon Sep 17 00:00:00 2001 From: NovaRain Date: Mon, 31 Dec 2018 10:05:59 +0800 Subject: [PATCH] Improved the functionality of ElevatorsFile to allow to change the FRM images of the elevator panel and create new elevator types (from Mr.Stalin) --- artifacts/config_files/elevators.ini | 28 ++++++-- sfall/FalloutEngine/Structs.h | 6 ++ sfall/Modules/Elevators.cpp | 104 ++++++++++++++++----------- 3 files changed, 94 insertions(+), 44 deletions(-) diff --git a/artifacts/config_files/elevators.ini b/artifacts/config_files/elevators.ini index 578c8ddd..52063693 100644 --- a/artifacts/config_files/elevators.ini +++ b/artifacts/config_files/elevators.ini @@ -1,11 +1,12 @@ ;Controls the elevators -;Image must match up with the image of an existing elevator +;Image must match up with the image of an existing elevator (can be overrided in sfall 4.1.4 or newer) ;Make sure you specify the correct number of exit targets ;The maximum number of elevators is currently capped at 50 +;Use the line number (0-indexed) of the corresponding FRM in intrface.lst to set the appearance of the elevator ;Override elevator 0 -[000] -;This elevator uses the frm of the original forth elevator +[0] +;This elevator will use the settings of the original forth elevator Image=4 ;Set up the first exit point @@ -23,4 +24,23 @@ ID3=50 Elevation3=0 Tile3=12944 -;No forth exit point \ No newline at end of file +;No forth exit point + +;Override FRM images of elevator 0. Set ButtonsFrm to -1 to use default buttons from MainFrm +MainFrm=143 +ButtonsFrm=-1 + + +;An example of a new elevator +[24] +;Set Image to 24 to create a new elevator type (0-23 are the original elevator types) +Image=24 + +;Set the number of buttons +ButtonCount=3 + +;Set up the appearance of the elevator +MainFrm=148 +ButtonsFrm=151 + +;Set up the exit points for all three buttons (see examples above) diff --git a/sfall/FalloutEngine/Structs.h b/sfall/FalloutEngine/Structs.h index dcc6ff4b..4c813873 100644 --- a/sfall/FalloutEngine/Structs.h +++ b/sfall/FalloutEngine/Structs.h @@ -260,6 +260,12 @@ struct ElevatorExit { long tile; }; +#pragma pack(1) +struct ElevatorFrms { + DWORD main; + DWORD buttons; +}; + #pragma pack(1) struct FrmFile { long id; //0x00 diff --git a/sfall/Modules/Elevators.cpp b/sfall/Modules/Elevators.cpp index 557248c4..b7464640 100644 --- a/sfall/Modules/Elevators.cpp +++ b/sfall/Modules/Elevators.cpp @@ -27,70 +27,74 @@ namespace sfall static const int exitsPerElevator = 4; static const int vanillaElevatorCount = 24; static const int elevatorCount = 50; -static char elevFile[MAX_PATH]; -static fo::ElevatorExit elevatorExits[elevatorCount][exitsPerElevator]; -static DWORD menus[elevatorCount]; +static char elevFile[MAX_PATH] = ".\\"; + +static DWORD elevatorType[elevatorCount]; +static fo::ElevatorExit elevatorExits[elevatorCount][exitsPerElevator]; // _retvals +static fo::ElevatorFrms elevatorsFrms[elevatorCount]; // _intotal +static DWORD elevatorsBtnCount[elevatorCount]; // _btncount static void __declspec(naked) GetMenuHook() { __asm { - push ebx; - lea ebx, menus; - shl eax, 2; - mov eax, [ebx+eax]; - call fo::funcoffs::elevator_start_; - pop ebx; - ret; + lea edx, elevatorType; + shl eax, 2; + mov eax, [edx + eax]; + jmp fo::funcoffs::elevator_start_; } } -static void __declspec(naked) UnknownHook() { +static void __declspec(naked) CheckHotKeysHook() { __asm { + cmp eax, vanillaElevatorCount; + jge skip; // skip hotkeys data push ebx; - lea ebx, menus; - shl eax, 2; - mov eax, [ebx+eax]; + lea ebx, elevatorType; + shl eax, 2; + mov eax, [ebx + eax]; call fo::funcoffs::Check4Keys_; - pop ebx; - ret; + pop ebx; + retn; +skip: + xor eax, eax; + retn; } } +/* static void __declspec(naked) UnknownHook2() { __asm { - push ebx; - lea ebx, menus; - shl eax, 2; - mov eax, [ebx+eax]; - call fo::funcoffs::elevator_end_; - pop ebx; - ret; + lea edx, elevatorType; + shl eax, 2; + mov eax, [edx + eax]; + jmp fo::funcoffs::elevator_end_; } } +*/ static void __declspec(naked) GetNumButtonsHook1() { __asm { - lea esi, menus; - mov eax, [esi+edi*4]; - mov eax, [FO_VAR_btncnt + eax*4]; + lea esi, elevatorType; + mov eax, [esi + edi * 4]; + mov eax, [elevatorsBtnCount + eax * 4]; retn; } } static void __declspec(naked) GetNumButtonsHook2() { __asm { - lea edx, menus; - mov eax, [edx+edi*4]; - mov eax, [FO_VAR_btncnt + eax*4]; + lea edx, elevatorType; + mov eax, [edx + edi * 4]; + mov eax, [elevatorsBtnCount + eax * 4]; retn; } } static void __declspec(naked) GetNumButtonsHook3() { __asm { - lea eax, menus; - mov eax, [eax+edi*4]; - mov eax, [FO_VAR_btncnt+eax*4]; + lea eax, elevatorType; + mov eax, [eax + edi * 4]; + mov eax, [elevatorsBtnCount + eax * 4]; retn; } } @@ -98,13 +102,28 @@ static void __declspec(naked) GetNumButtonsHook3() { void ResetElevators() { memcpy(elevatorExits, fo::var::retvals, sizeof(fo::ElevatorExit) * vanillaElevatorCount * exitsPerElevator); memset(&elevatorExits[vanillaElevatorCount], 0, sizeof(fo::ElevatorExit) * (elevatorCount - vanillaElevatorCount) * exitsPerElevator); - for (int i = 0; i < vanillaElevatorCount; i++) menus[i] = i; - for (int i = vanillaElevatorCount; i < elevatorCount; i++) menus[i] = 0; + + memcpy(elevatorsFrms, (void*)FO_VAR_intotal, sizeof(fo::ElevatorFrms) * vanillaElevatorCount); + memset(&elevatorsFrms[vanillaElevatorCount], 0, sizeof(fo::ElevatorFrms) * (elevatorCount - vanillaElevatorCount)); + + memcpy(elevatorsBtnCount, (void*)FO_VAR_btncnt, sizeof(DWORD) * vanillaElevatorCount); + + for (int i = 0; i < vanillaElevatorCount; i++) elevatorType[i] = i; + for (int i = vanillaElevatorCount; i < elevatorCount; i++) elevatorType[i] = 0; + char section[4]; if (elevFile) { for (int i = 0; i < elevatorCount; i++) { _itoa_s(i, section, 10); - menus[i] = GetPrivateProfileIntA(section, "Image", menus[i], elevFile); + int type = GetPrivateProfileIntA(section, "Image", elevatorType[i], elevFile); + elevatorType[i] = min(type, elevatorCount - 1); + if (i >= vanillaElevatorCount) { + int cBtn = GetPrivateProfileIntA(section, "ButtonCount", 2, elevFile); + if (cBtn > exitsPerElevator) cBtn = exitsPerElevator; + elevatorsBtnCount[i] = max(2, cBtn); + } + elevatorsFrms[i].main = GetPrivateProfileIntA(section, "MainFrm", elevatorsFrms[i].main, elevFile); + elevatorsFrms[i].buttons = GetPrivateProfileIntA(section, "ButtonsFrm", elevatorsFrms[i].buttons, elevFile); char setting[32]; for (int j = 0; j < exitsPerElevator; j++) { sprintf_s(setting, "ID%d", j + 1); @@ -119,21 +138,26 @@ void ResetElevators() { } void ElevatorsInit(const char* file) { - strcpy_s(elevFile, ".\\"); strcat_s(elevFile, file); HookCall(0x43EF83, GetMenuHook); - HookCall(0x43F141, UnknownHook); - HookCall(0x43F2D2, UnknownHook2); + HookCall(0x43F141, CheckHotKeysHook); + //HookCall(0x43F2D2, UnknownHook2); // unused SafeWrite8(0x43EF76, (BYTE)elevatorCount); SafeWrite32(0x43EFA4, (DWORD)elevatorExits); SafeWrite32(0x43EFB9, (DWORD)elevatorExits); - SafeWrite32(0x43EFEA, (DWORD)&elevatorExits[0][0].tile); SafeWrite32(0x43F2FC, (DWORD)elevatorExits); - SafeWrite32(0x43F309, (DWORD)&elevatorExits[0][0].elevation); + SafeWrite32(0x43EFEA, (DWORD)&elevatorExits[0][0].tile); SafeWrite32(0x43F315, (DWORD)&elevatorExits[0][0].tile); + SafeWrite32(0x43F309, (DWORD)&elevatorExits[0][0].elevation); + SafeWrite32(0x43F438, (DWORD)&elevatorsFrms[0].main); + SafeWrite32(0x43F475, (DWORD)&elevatorsFrms[0].buttons); + + // _btncnt + SafeWrite32(0x43F65E, (DWORD)elevatorsBtnCount); + SafeWrite32(0x43F6BB, (DWORD)elevatorsBtnCount); MakeCall(0x43F05D, GetNumButtonsHook1, 2); MakeCall(0x43F184, GetNumButtonsHook2, 2); MakeCall(0x43F1E4, GetNumButtonsHook3, 2);