Improved the functionality of ElevatorsFile to allow to change the FRM images of the elevator panel and create new elevator types (from Mr.Stalin)

This commit is contained in:
NovaRain
2018-12-31 10:10:06 +08:00
parent 26ab38c6c3
commit f36bd6fb61
3 changed files with 120 additions and 73 deletions
+23 -3
View File
@@ -1,11 +1,12 @@
;Controls the elevators ;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 ;Make sure you specify the correct number of exit targets
;The maximum number of elevators is currently capped at 50 ;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 ;Override elevator 0
[000] [0]
;This elevator uses the frm of the original forth elevator ;This elevator will use the settings of the original forth elevator
Image=4 Image=4
;Set up the first exit point ;Set up the first exit point
@@ -24,3 +25,22 @@ Elevation3=0
Tile3=12944 Tile3=12944
;No forth exit point ;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)
+2 -2
View File
@@ -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. - In this case use force_encounter_with_flags with the ENCOUNTER_FLAG_NO_CAR flag set.
> int get_light_level() > 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. - 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) > 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) - 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) > 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) > 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) - returns first object which blocks direct linear path from objFrom to tileTo using selected blocking function (see BLOCKING_TYPE_* constants in sfall.h)
+86 -59
View File
@@ -21,8 +21,11 @@
#include "Elevators.h" #include "Elevators.h"
#include "FalloutEngine.h" #include "FalloutEngine.h"
static const int ElevatorCount = 50; static const int exitsPerElevator = 4;
static char File[MAX_PATH]; static const int vanillaElevatorCount = 24;
static const int elevatorCount = 50;
static char elevFile[MAX_PATH] = ".\\";
struct sElevator { struct sElevator {
DWORD ID1; DWORD ID1;
@@ -39,119 +42,143 @@ struct sElevator {
DWORD Tile4; DWORD Tile4;
}; };
static sElevator Elevators[ElevatorCount]; struct sElevatorFrms {
static DWORD Menus[ElevatorCount]; DWORD main;
DWORD buttons;
};
void SetElevator(DWORD id, DWORD index, DWORD value) { static DWORD elevatorType[elevatorCount];
if (id >= ElevatorCount || index >= 12) return; static sElevator elevators[elevatorCount]; // _retvals
*(DWORD*)(((DWORD)&Elevators[id]) + index * 4) = value; static sElevatorFrms elevatorsFrms[elevatorCount]; // _intotal
} static DWORD elevatorsBtnCount[elevatorCount]; // _btncount
static void __declspec(naked) GetMenuHook() { static void __declspec(naked) GetMenuHook() {
__asm { __asm {
push ebx; lea edx, elevatorType;
lea ebx, Menus;
shl eax, 2; shl eax, 2;
mov eax, [ebx+eax]; mov eax, [edx + eax];
call elevator_start_; jmp elevator_start_;
pop ebx;
ret;
} }
} }
static void __declspec(naked) UnknownHook() { static void __declspec(naked) CheckHotKeysHook() {
__asm { __asm {
cmp eax, vanillaElevatorCount;
jge skip; // skip hotkeys data
push ebx; push ebx;
lea ebx, Menus; lea ebx, elevatorType;
shl eax, 2; shl eax, 2;
mov eax, [ebx + eax]; mov eax, [ebx + eax];
call Check4Keys_; call Check4Keys_;
pop ebx; pop ebx;
ret; retn;
skip:
xor eax, eax;
retn;
} }
} }
/*
static void __declspec(naked) UnknownHook2() { static void __declspec(naked) UnknownHook2() {
__asm { __asm {
push ebx; lea edx, elevatorType;
lea ebx, Menus;
shl eax, 2; shl eax, 2;
mov eax, [ebx+eax]; mov eax, [edx + eax];
call elevator_end_; jmp elevator_end_;
pop ebx;
ret;
} }
} }
*/
static void __declspec(naked) GetNumButtonsHook1() { static void __declspec(naked) GetNumButtonsHook1() {
__asm { __asm {
lea esi, Menus; lea esi, elevatorType;
mov eax, [esi + edi * 4]; mov eax, [esi + edi * 4];
mov eax, [_btncnt+eax*4]; mov eax, [elevatorsBtnCount + eax * 4];
retn; retn;
} }
} }
static void __declspec(naked) GetNumButtonsHook2() { static void __declspec(naked) GetNumButtonsHook2() {
__asm { __asm {
lea edx, Menus; lea edx, elevatorType;
mov eax, [edx + edi * 4]; mov eax, [edx + edi * 4];
mov eax, [_btncnt+eax*4]; mov eax, [elevatorsBtnCount + eax * 4];
retn; retn;
} }
} }
static void __declspec(naked) GetNumButtonsHook3() { static void __declspec(naked) GetNumButtonsHook3() {
__asm { __asm {
lea eax, Menus; lea eax, elevatorType;
mov eax, [eax + edi * 4]; mov eax, [eax + edi * 4];
mov eax, [_btncnt+eax*4]; mov eax, [elevatorsBtnCount + eax * 4];
retn; retn;
} }
} }
void ResetElevators() { void ResetElevators() {
memcpy(Elevators, (void*)_retvals, sizeof(sElevator) * 24); memcpy(elevators, (void*)_retvals, sizeof(sElevator) * vanillaElevatorCount);
memset(&Elevators[24], 0, sizeof(sElevator) * (ElevatorCount - 24)); memset(&elevators[vanillaElevatorCount], 0, sizeof(sElevator) * (elevatorCount - vanillaElevatorCount));
for (int i = 0; i < 24; i++) Menus[i] = i;
for (int i = 24; i < ElevatorCount; i++) Menus[i] = 0; 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]; char section[4];
if (File) { if (elevFile) {
for (int i = 0; i < ElevatorCount; i++) { for (int i = 0; i < elevatorCount; i++) {
_itoa_s(i, section, 10); _itoa_s(i, section, 10);
Menus[i] = GetPrivateProfileIntA(section, "Image", Menus[i], File); int type = GetPrivateProfileIntA(section, "Image", elevatorType[i], elevFile);
Elevators[i].ID1 = GetPrivateProfileIntA(section, "ID1", Elevators[i].ID1, File); elevatorType[i] = min(type, elevatorCount - 1);
Elevators[i].ID2 = GetPrivateProfileIntA(section, "ID2", Elevators[i].ID2, File); if (i >= vanillaElevatorCount) {
Elevators[i].ID3 = GetPrivateProfileIntA(section, "ID3", Elevators[i].ID3, File); int cBtn = GetPrivateProfileIntA(section, "ButtonCount", 2, elevFile);
Elevators[i].ID4 = GetPrivateProfileIntA(section, "ID4", Elevators[i].ID4, File); if (cBtn > exitsPerElevator) cBtn = exitsPerElevator;
Elevators[i].Elevation1 = GetPrivateProfileIntA(section, "Elevation1", Elevators[i].Elevation1, File); elevatorsBtnCount[i] = max(2, cBtn);
Elevators[i].Elevation2 = GetPrivateProfileIntA(section, "Elevation2", Elevators[i].Elevation2, File); }
Elevators[i].Elevation3 = GetPrivateProfileIntA(section, "Elevation3", Elevators[i].Elevation3, File); elevatorsFrms[i].main = GetPrivateProfileIntA(section, "MainFrm", elevatorsFrms[i].main, elevFile);
Elevators[i].Elevation4 = GetPrivateProfileIntA(section, "Elevation4", Elevators[i].Elevation4, File); elevatorsFrms[i].buttons = GetPrivateProfileIntA(section, "ButtonsFrm", elevatorsFrms[i].buttons, elevFile);
Elevators[i].Tile1 = GetPrivateProfileIntA(section, "Tile1", Elevators[i].Tile1, File); elevatorType[i] = GetPrivateProfileIntA(section, "Image", elevatorType[i], elevFile);
Elevators[i].Tile2 = GetPrivateProfileIntA(section, "Tile2", Elevators[i].Tile2, File); elevators[i].ID1 = GetPrivateProfileIntA(section, "ID1", elevators[i].ID1, elevFile);
Elevators[i].Tile3 = GetPrivateProfileIntA(section, "Tile3", Elevators[i].Tile3, File); elevators[i].ID2 = GetPrivateProfileIntA(section, "ID2", elevators[i].ID2, elevFile);
Elevators[i].Tile4 = GetPrivateProfileIntA(section, "Tile4", Elevators[i].Tile4, File); 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) { void ElevatorsInit(char* file) {
strcpy_s(File, ".\\"); strcat_s(elevFile, file);
strcat_s(File, file);
HookCall(0x43EF83, GetMenuHook); HookCall(0x43EF83, GetMenuHook);
HookCall(0x43F141, UnknownHook); HookCall(0x43F141, CheckHotKeysHook);
HookCall(0x43F2D2, UnknownHook2); //HookCall(0x43F2D2, UnknownHook2); // unused
SafeWrite8(0x43EF76, (BYTE)ElevatorCount); SafeWrite8(0x43EF76, (BYTE)elevatorCount);
SafeWrite32(0x43EFA4, (DWORD)Elevators); SafeWrite32(0x43EFA4, (DWORD)elevators);
SafeWrite32(0x43EFB9, (DWORD)Elevators); SafeWrite32(0x43EFB9, (DWORD)elevators);
SafeWrite32(0x43EFEA, (DWORD)&Elevators[0].Tile1); SafeWrite32(0x43F2FC, (DWORD)elevators);
SafeWrite32(0x43F2FC, (DWORD)Elevators); SafeWrite32(0x43EFEA, (DWORD)&elevators[0].Tile1);
SafeWrite32(0x43F309, (DWORD)&Elevators[0].Elevation1); SafeWrite32(0x43F315, (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(0x43F05D, GetNumButtonsHook1, 2);
MakeCall(0x43F184, GetNumButtonsHook2, 2); MakeCall(0x43F184, GetNumButtonsHook2, 2);
MakeCall(0x43F1E4, GetNumButtonsHook3, 2); MakeCall(0x43F1E4, GetNumButtonsHook3, 2);