From f36bd6fb618ba6fbbcafb8597ef1f9cbcc72d496 Mon Sep 17 00:00:00 2001 From: NovaRain Date: Mon, 31 Dec 2018 10:10:06 +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 +++- artifacts/scripting/sfall function notes.txt | 4 +- sfall/Elevators.cpp | 161 +++++++++++-------- 3 files changed, 120 insertions(+), 73 deletions(-) diff --git a/artifacts/config_files/elevators.ini b/artifacts/config_files/elevators.ini index 578c8ddd..5ba7817d 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 3.8.14 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/artifacts/scripting/sfall function notes.txt b/artifacts/scripting/sfall function notes.txt index efc2a3de..a30be25c 100644 --- a/artifacts/scripting/sfall function notes.txt +++ b/artifacts/scripting/sfall function notes.txt @@ -141,7 +141,7 @@ array - array ID to be used with array-related functions (actually an integer) - In this case use force_encounter_with_flags with the ENCOUNTER_FLAG_NO_CAR flag set. > int get_light_level() -- ambient light level in range 0..65535 +- ambient light level in range 0..65536 - The value returned by get_light_level may not exactly match that set by set_light_level, as set_light_level applies modifiers from the night vision perk. > void set_map_time_multi(float multi) @@ -310,7 +310,7 @@ Some utility/math functions are available: - this calls an internal engine function which is used to determine the perception range of critters (which you can override using HOOK_WITHINPERCEPTION) > int tile_light(int elevation, int tileNum) -- returns light intensity at the given tile in range from 0 to 65535 +- returns light intensity at the given tile in range from 0 to 65536 > object obj_blocking_line(object objFrom, int tileTo, int blockingType) - returns first object which blocks direct linear path from objFrom to tileTo using selected blocking function (see BLOCKING_TYPE_* constants in sfall.h) diff --git a/sfall/Elevators.cpp b/sfall/Elevators.cpp index 04178de0..7432af69 100644 --- a/sfall/Elevators.cpp +++ b/sfall/Elevators.cpp @@ -21,8 +21,11 @@ #include "Elevators.h" #include "FalloutEngine.h" -static const int ElevatorCount = 50; -static char File[MAX_PATH]; +static const int exitsPerElevator = 4; +static const int vanillaElevatorCount = 24; +static const int elevatorCount = 50; + +static char elevFile[MAX_PATH] = ".\\"; struct sElevator { DWORD ID1; @@ -39,119 +42,143 @@ struct sElevator { DWORD Tile4; }; -static sElevator Elevators[ElevatorCount]; -static DWORD Menus[ElevatorCount]; +struct sElevatorFrms { + DWORD main; + DWORD buttons; +}; -void SetElevator(DWORD id, DWORD index, DWORD value) { - if (id >= ElevatorCount || index >= 12) return; - *(DWORD*)(((DWORD)&Elevators[id]) + index * 4) = value; -} +static DWORD elevatorType[elevatorCount]; +static sElevator elevators[elevatorCount]; // _retvals +static sElevatorFrms 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 elevator_start_; - pop ebx; - ret; + lea edx, elevatorType; + shl eax, 2; + mov eax, [edx + eax]; + jmp 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 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 elevator_end_; - pop ebx; - ret; + lea edx, elevatorType; + shl eax, 2; + mov eax, [edx + eax]; + jmp elevator_end_; } } +*/ static void __declspec(naked) GetNumButtonsHook1() { __asm { - lea esi, Menus; - mov eax, [esi+edi*4]; - mov eax, [_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, [_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, [_btncnt+eax*4]; + lea eax, elevatorType; + mov eax, [eax + edi * 4]; + mov eax, [elevatorsBtnCount + eax * 4]; retn; } } void ResetElevators() { - memcpy(Elevators, (void*)_retvals, sizeof(sElevator) * 24); - memset(&Elevators[24], 0, sizeof(sElevator) * (ElevatorCount - 24)); - for (int i = 0; i < 24; i++) Menus[i] = i; - for (int i = 24; i < ElevatorCount; i++) Menus[i] = 0; + memcpy(elevators, (void*)_retvals, sizeof(sElevator) * vanillaElevatorCount); + memset(&elevators[vanillaElevatorCount], 0, sizeof(sElevator) * (elevatorCount - vanillaElevatorCount)); + + memcpy(elevatorsFrms, (void*)_intotal, sizeof(sElevatorFrms) * vanillaElevatorCount); + memset(&elevatorsFrms[vanillaElevatorCount], 0, sizeof(sElevatorFrms) * (elevatorCount - vanillaElevatorCount)); + + memcpy(elevatorsBtnCount, (void*)_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 (File) { - for (int i = 0; i < ElevatorCount; i++) { + if (elevFile) { + for (int i = 0; i < elevatorCount; i++) { _itoa_s(i, section, 10); - Menus[i] = GetPrivateProfileIntA(section, "Image", Menus[i], File); - Elevators[i].ID1 = GetPrivateProfileIntA(section, "ID1", Elevators[i].ID1, File); - Elevators[i].ID2 = GetPrivateProfileIntA(section, "ID2", Elevators[i].ID2, File); - Elevators[i].ID3 = GetPrivateProfileIntA(section, "ID3", Elevators[i].ID3, File); - Elevators[i].ID4 = GetPrivateProfileIntA(section, "ID4", Elevators[i].ID4, File); - Elevators[i].Elevation1 = GetPrivateProfileIntA(section, "Elevation1", Elevators[i].Elevation1, File); - Elevators[i].Elevation2 = GetPrivateProfileIntA(section, "Elevation2", Elevators[i].Elevation2, File); - Elevators[i].Elevation3 = GetPrivateProfileIntA(section, "Elevation3", Elevators[i].Elevation3, File); - Elevators[i].Elevation4 = GetPrivateProfileIntA(section, "Elevation4", Elevators[i].Elevation4, File); - Elevators[i].Tile1 = GetPrivateProfileIntA(section, "Tile1", Elevators[i].Tile1, File); - Elevators[i].Tile2 = GetPrivateProfileIntA(section, "Tile2", Elevators[i].Tile2, File); - Elevators[i].Tile3 = GetPrivateProfileIntA(section, "Tile3", Elevators[i].Tile3, File); - Elevators[i].Tile4 = GetPrivateProfileIntA(section, "Tile4", Elevators[i].Tile4, File); + 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); + elevatorType[i] = GetPrivateProfileIntA(section, "Image", elevatorType[i], elevFile); + elevators[i].ID1 = GetPrivateProfileIntA(section, "ID1", elevators[i].ID1, elevFile); + elevators[i].ID2 = GetPrivateProfileIntA(section, "ID2", elevators[i].ID2, elevFile); + elevators[i].ID3 = GetPrivateProfileIntA(section, "ID3", elevators[i].ID3, elevFile); + elevators[i].ID4 = GetPrivateProfileIntA(section, "ID4", elevators[i].ID4, elevFile); + elevators[i].Elevation1 = GetPrivateProfileIntA(section, "Elevation1", elevators[i].Elevation1, elevFile); + elevators[i].Elevation2 = GetPrivateProfileIntA(section, "Elevation2", elevators[i].Elevation2, elevFile); + elevators[i].Elevation3 = GetPrivateProfileIntA(section, "Elevation3", elevators[i].Elevation3, elevFile); + elevators[i].Elevation4 = GetPrivateProfileIntA(section, "Elevation4", elevators[i].Elevation4, elevFile); + elevators[i].Tile1 = GetPrivateProfileIntA(section, "Tile1", elevators[i].Tile1, elevFile); + elevators[i].Tile2 = GetPrivateProfileIntA(section, "Tile2", elevators[i].Tile2, elevFile); + elevators[i].Tile3 = GetPrivateProfileIntA(section, "Tile3", elevators[i].Tile3, elevFile); + elevators[i].Tile4 = GetPrivateProfileIntA(section, "Tile4", elevators[i].Tile4, elevFile); } } } void ElevatorsInit(char* file) { - strcpy_s(File, ".\\"); - strcat_s(File, file); + 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)Elevators); - SafeWrite32(0x43EFB9, (DWORD)Elevators); - SafeWrite32(0x43EFEA, (DWORD)&Elevators[0].Tile1); - SafeWrite32(0x43F2FC, (DWORD)Elevators); - SafeWrite32(0x43F309, (DWORD)&Elevators[0].Elevation1); - SafeWrite32(0x43F315, (DWORD)&Elevators[0].Tile1); + SafeWrite8(0x43EF76, (BYTE)elevatorCount); + SafeWrite32(0x43EFA4, (DWORD)elevators); + SafeWrite32(0x43EFB9, (DWORD)elevators); + SafeWrite32(0x43F2FC, (DWORD)elevators); + SafeWrite32(0x43EFEA, (DWORD)&elevators[0].Tile1); + SafeWrite32(0x43F315, (DWORD)&elevators[0].Tile1); + SafeWrite32(0x43F309, (DWORD)&elevators[0].Elevation1); + 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);