Merge branch 'develop'

This commit is contained in:
NovaRain
2019-02-12 09:22:18 +08:00
58 changed files with 1625 additions and 1410 deletions
+6 -5
View File
@@ -14,17 +14,18 @@ Part_0=1 ; Tell sfall that we want to modify the head entries
[c_00_0] ; The entries for the head table of the men critter type.
e0_DamageMultiplier=100 ;First level critical
e0_EffectFlags=0
e0_EffectFlags=0 ; The value of the flags (see DAM_* in Define.h)
; For multiple effects, use the sum of the flags (e.g. 2050 = knocked down + bypass armor)
e0_StatCheck=0
e0_StatMod=0
e0_FailureEffect=0
e0_Message=0 ; This is an index into the msg file, not a string
e0_FailMessage=0
e1_... ; Second level critical
... ; And so on up to the hardest hitting level 5 critical
e5_...
;e1_... ; Second level critical
;... ; And so on up to the hardest hitting level 5 critical
;e5_...
;You can skip any entries from this section to leave them at their defaults
;Any missing entries for critters 19-37 will be replaced by a 0, since they have no default
;Note that the UOP fixes are included in the defaults, and do not need to be
; added manually when using this override format, as opposed to the old one
; added manually when using this override format, as opposed to the old one
+6 -5
View File
@@ -1,12 +1,13 @@
; Allows to reassign books to different object PIDs, text messages.
; Maximum 30 books are allowed (25 if overrideVanilla is 0)
; Allows to reassign books to different object PIDs, text messages, and skills.
; Maximum 50 books are allowed
[main]
; total number of books in this file
count=5
count=1
; set to 1 to override all vanilla books, so you will have to define ALL books in this file;
; otherwise only new books are defined here
; set to 1 to override all vanilla books, so you will have to define ALL the necessary books in this file;
; otherwise only new books are defined here. To just override the text/skill of a vanilla book,
; specify its PID in the new book and set the parameters
overrideVanilla=0
; count starts from 1
+25 -13
View File
@@ -1,5 +1,5 @@
;sfall configuration settings
;v4.1.4
;v4.1.5
[Main]
;Change to 1 if you want to use command line args to tell sfall to use another ini file.
@@ -34,18 +34,21 @@ Enable=1
;The speeds corresponding to each slot in percent. (i.e. 100 is normal speed)
SpeedMulti0=50
SpeedMulti1=100
SpeedMulti2=150
SpeedMulti3=200
SpeedMulti4=300
SpeedMulti2=200
SpeedMulti3=300
SpeedMulti4=400
SpeedMulti5=500
SpeedMulti6=1000
SpeedMulti7=100
SpeedMulti8=100
SpeedMulti9=100
SpeedMulti6=600
SpeedMulti7=700
SpeedMulti8=800
SpeedMulti9=900
;The initial speed at game startup
SpeedMultiInitial=100
;Set to 1 to also affect the playback speed of mve video files without an audio track
AffectPlayback=0
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
[Graphics]
;Set to 0 for 8 bit fullscreen
@@ -159,8 +162,7 @@ DebugEditorKey=0
;Time limit in years. Must be between -3 and 13
;Set to 0 if you want to die the instant you leave arroyo
;Set to -1 to remove the time limit, and automatically reset the date back to 2241 each time you would have reached it
;Set to -2 to remove the time limit without resetting the date. The game will lock up on 8th of March 2255
;Set to -3 to remove the time limit, automatically reset the date, but override Fallout's GetDate function to return the correct year
;Set to -2 or -3 to remove the time limit, automatically reset the date, but override Fallout's GetDate function to return the correct year
TimeLimit=13
;World map travel time percentage modifier
@@ -168,9 +170,6 @@ TimeLimit=13
;100 is normal speed, 0 stops time from passing
WorldMapTimeMod=100
;Set to 1 to enable functions relating to overriding the file system
UseFileSystemOverride=0
;Set to 1 to use the Fallout 1 code to control world map speed
WorldMapFPSPatch=1
@@ -197,6 +196,9 @@ WorldMapSlots=0
;To use a config file other than fallout2.cfg, uncomment the next line and add the name of your new file
;ConfigFile=
;Set to 1 to enable functions relating to overriding the file system
UseFileSystemOverride=0
;To use a patch file other than patch000.dat, uncomment the next line and add your new file name
;If you want to check for multiple patch files, you can include a %d in the file name (sprintf syntax)
;By default, only the first patch file found will be used.
@@ -532,6 +534,13 @@ ObjCanHearObjFix=0
;If the argument value is -1, the mood will be determined by the local variable 0 of the script (vanilla behavior)
StartGDialogFix=0
;Set to 1 to fix and repurpose the unused called_shot/num_attacks arguments of attack_complex script function
;This also changes the behavior of the result flags arguments
;called_shot - additional damage, when the damage received by the target is above the specified minimum damage
;num_attacks - the number of free action points on the first turn only
;attacker_results - unused, must be 0 or not equal to the target_results argument when specifying result flags for the target
AttackComplexFix=0
;Set to 1 to enable the balanced bullet distribution formula for burst attacks
ComputeSprayMod=0
@@ -713,6 +722,9 @@ AlwaysFindScripts=0
;Set to 1 to force sfall to inject all hooks code into the game, even if corresponding hook scripts don't exist
InjectAllGameHooks=0
;Set to 1 to hide error messages in debug output when a null value is passed to the function as an object
HideObjIsNullMsg=0
;These options control what output is saved in the debug log (sfall-log.txt)
;Prints messages duing sfall initialization
Binary file not shown.
@@ -1,7 +1,7 @@
/*
Auto Doors mod for Fallout 2 by Mr.Stalin
-----------------------------------------
Auto Doors mod v1.1 for Fallout 2 by Mr.Stalin
----------------------------------------------
- allows the player to automatically open/walk through unlocked doors when not in combat
@@ -12,66 +12,91 @@ NOTE: this script requires compiler from sfall modderspack with -s option
*/
/* Include Files */
#include "..\headers\define.h"
#include "..\headers\command.h"
#include "..\headers\sfall\sfall.h"
#include "..\headers\sfall\define_extra.h"
//#include "..\headers\command.h"
#include "..\..\scripting_docs\headers\sfall.h"
#include "..\..\scripting_docs\headers\define_extra.h"
/* Standard Script Procedures */
procedure start;
procedure map_enter_p_proc;
procedure set_door_flag(variable state);
procedure set_door_flag_array(variable state);
procedure combatturn_handler;
/* Defines */
#define PORTAL (0)
#define DOOR_FLAGS (0x24)
variable only_once := 0;
variable arrayPid;
procedure start begin
if game_loaded then begin
if (sfall_ver_major >= 4) then
register_hook_proc(HOOK_COMBATTURN, combatturn_handler);
else
set_global_script_repeat(60);
set_global_script_repeat(40); // for sfall 3.x
call map_enter_p_proc;
end else begin
if (only_once == 1 and combat_is_initialized) then begin
only_once := 2;
call set_door_flag(false);
call set_door_flag(0); // reset flag when entering combat mode
end else if (only_once == 2 and not(combat_is_initialized)) then begin
only_once := 1;
if (sfall_ver_major >= 4) then
set_global_script_repeat(0);
call set_door_flag(FLAG_WALKTHRU);
if (sfall_ver_major >= 4) then set_global_script_repeat(0);
call set_door_flag(FLAG_WALKTHRU); // set flag after combat mode ends
end
end
end
procedure map_enter_p_proc begin
if (arrayPid) then begin
// when changing maps, delete the current array to create a new one
free_array(arrayPid);
arrayPid := 0;
end
only_once := 1;
call set_door_flag(FLAG_WALKTHRU);
call set_door_flag(FLAG_WALKTHRU); // set flag when entering the map
end
procedure set_door_flag(variable state) begin
variable objectMap, obj, objPid, arrayPid, i;
variable objectMap, obj, objPid, i;
if (arrayPid) then begin
call set_door_flag_array(state);
return;
end
objectMap := list_as_array(LIST_SCENERY);
arrayPid := temp_array(1, 0);
arrayPid := create_array(0, 0);
foreach (obj in objectMap) begin
objPid := obj_pid(obj);
if (proto_data(objPid, sc_type) != PORTAL) or is_in_array(objPid, arrayPid) then
continue;
continue; // next object
resize_array(arrayPid, i + 1);
arrayPid[i] := objPid;
i++;
resize_array(arrayPid, i + 1);
set_proto_data(objPid, DOOR_FLAGS, state);
end
end
procedure set_door_flag_array(variable state) begin
variable objPid;
foreach (objPid in arrayPid) begin
set_proto_data(objPid, DOOR_FLAGS, state);
end
end
procedure combatturn_handler begin
if (only_once == 1) then
if (only_once == 1) then begin
only_once := 2;
call set_door_flag_array(0);
set_global_script_repeat(60);
end
end
+2 -2
View File
@@ -1,5 +1,5 @@
Auto Doors mod for Fallout 2 by Mr.Stalin
-----------------------------------------
Auto Doors mod v1.1 for Fallout 2 by Mr.Stalin
----------------------------------------------
- allows the player to automatically open/walk through unlocked doors when not in combat
+1
View File
@@ -238,6 +238,7 @@
#define party_member_list_all party_member_list(1)
#define art_cache_clear sfall_func0("art_cache_clear")
#define attack_is_aimed sfall_func0("attack_is_aimed")
#define car_gas_amount sfall_func0("car_gas_amount")
#define create_win(winName, x, y, w, h) sfall_func5("create_win", winName, x, y, w, h)
+1 -1
View File
@@ -464,7 +464,7 @@ Runs before and after each turn in combat (for both PC and NPC).
int arg1 - event type: 1 - start of turn, 0 - normal end of turn, -1 - combat ended abruptly (by script or by pressing Enter during PC turn)
int arg2 - critter doing the turn
int arg3 - unknown boolean argument
bool arg3 - set to 1 at the start of the player's turn after the game has been loaded, 0 otherwise
int ret1 - pass 1 at the start of turn to skip the turn, pass -1 at the end of turn to force end of combat
+8 -4
View File
@@ -40,7 +40,7 @@ get/set_critter_current_ap functions should only be used during the target critt
The 'type' value in the weapon knockback functions can be 0 or 1. If 0, the value becomes an absolute distance that targets will be knocked back. If 1, the value is multiplied by the distance they would normally have been knocked back. Weapon knockback modifiers are applied in the order weapon -> attacker -> target, so a x2 weapon wielded by an abs 6 attacker hitting a /2 target will knock the target back 3 squares. The knockback functions will not override the stonewall perk or knockdowns resulting from criticals. knockback values set on weapons or critters are not saved, and must be reset each time the player reloads.
The get/set_sfall_global functions require an 8 character long case sensitive string for the variable name. The variables behave the same as normal Fallout globals, except that they don't have to be declared beforehand in vault13.gam. Trying to get a variable which hasn't been set will always return 0. These functions are intended for use when a patch to a mod requires the addition of a new global variable, a case which would otherwise require the player to start a new game.
The get/set_sfall_global functions require an 8 characters long case sensitive string for the variable name. The variables behave the same as normal Fallout globals, except that they don't have to be declared beforehand in vault13.gam. Trying to get a variable which hasn't been set will always return 0. These functions are intended for use when a patch to a mod requires the addition of a new global variable, a case which would otherwise require the player to start a new game.
set_pickpocket_max and set_hit_chance_max effect all critters rather than just the player. set_skill_max can't be used to increase the skill cap above 300. set_perk_level_mod sets a modifier between +25 and -25 that is added/subtracted from the players level for the purposes of deciding which perks can be chosen.
@@ -60,7 +60,7 @@ get/set_unspent_ap_bonus alter the AC bonus you receive per unused action point
nb_* functions are reserved for the brotherhood tactical training mod, and should be avoided.
The fs_* functions are used to manipulate a virtual file system. Files saved here should have paths relative to the data folder, and use backslashes as the directory separator. They will take precedence over files stored in the normal data folder. They will also be saved into save games, so be avoid creating large files. Using fs_copy followed by fs_read_xxx, you can read the contents of existing files.
The fs_* functions are used to manipulate a virtual file system. Files saved here should have paths relative to the data folder, and use backslashes as the directory separator. They will take precedence over files stored in the normal data folder. They will also be saved into save games if you set a flag for them using fs_resize(fileId, -1), so be avoid creating large files. Using fs_copy followed by fs_read_xxx, you can read the contents of existing files.
get/set_proto_data are used to manipulate the in memory copies of the .pro files Fallout makes when they are loaded. The offset refers to the offset in memory from the start of the proto to the element you are reading. Changes are not stored on disc, and are not permanent. If you modify the protos, and then Fallout subsequently reloads the file your changes will be lost.
@@ -163,8 +163,9 @@ array - array ID to be used with array-related functions (actually an integer)
- overrides the scripts self_obj for the next function call.
- It is primarily used to allow the calling of functions which take an implicit self_obj parameter (e.g. drop_obj) from global scripts, but it can also be used from normal scripts;
- self_obj will revert back to its original value after the next function call.
- calling self_obj(0) will also revert self_obj to original value
- calling self_obj(0) will also revert self_obj to original value. It is recommended to call this after each use of set_self in normal scripts in order to avoid unforeseen side effects.
- source_obj, target_obj, and similar functions will not work if preceded by "set_self"
- NOTE: for use_obj/use_obj_on_obj vanilla functions to work correctly, it is required to call set_self twice.
> void mod_skill_points_per_level(int x)
- accepts a value of between -100 and 100, and modifies the number of skill points the player receives when they level up.
@@ -292,7 +293,7 @@ Some utility/math functions are available:
> float sqrt(float x)
- square root of x
> float abs(float x)
> int/float abs(int/float x)
- absolute (positive) value of x
> float sin(float x)
@@ -560,6 +561,9 @@ Some utility/math functions are available:
- returns the setting value from the AI packet of an object (critter)
- use AI_CAP_* constants from define_extra.h for the aiParam argument to get AI value
> void sfall_func0("art_cache_clear")
- clears the cache of FRM image files loaded into memory
------------------------
------ MORE INFO -------
------------------------
+1 -1
View File
@@ -219,7 +219,7 @@
0x81e9 - int get_unspent_ap_perk_bonus()
0x81ec - float sqrt(float)
0x81ed - float abs(float)
0x81ed - int/float abs(int/float)
0x81ee - float sin(float)
0x81ef - float cos(float)
0x81f0 - float tan(float)
+6 -1
View File
@@ -631,7 +631,12 @@ enum AttackType : long
#define CRITTER_EYEDAMAGE (0x40)
#define WEAPON_TWO_HANDED (0x200)
#define WEAPON_TWO_HANDED (0x200)
enum TicksTime : unsigned long
{
ONE_GAME_YEAR = 315360000
};
enum RollResult
{
+9
View File
@@ -700,4 +700,13 @@ struct AIcap {
long general_type;
};
#pragma pack(1)
struct Queue {
DWORD time;
long type;
GameObject* object;
long data;
Queue* next;
};
}
+1
View File
@@ -28,6 +28,7 @@
#define FO_VAR_character_points 0x518538
#define FO_VAR_cmap 0x51DF34
#define FO_VAR_colorTable 0x6A38D0
#define FO_VAR_combat_end_due_to_load 0x517F98
#define FO_VAR_combat_free_move 0x56D39C
#define FO_VAR_combat_list 0x56D390
#define FO_VAR_combat_state 0x510944
+13 -15
View File
@@ -49,7 +49,7 @@ static double mousePartX;
static double mousePartY;
#define MAX_KEYS (264)
static DWORD keysDown[MAX_KEYS];
static DWORD keysDown[MAX_KEYS] = {0};
static int mouseX;
static int mouseY;
@@ -125,9 +125,9 @@ void _stdcall TapKey(DWORD key) {
data.dwTimeStamp = 0;
data.dwSequence = 0;
data.dwOfs = key;
data.dwData = 0x80;
data.dwData = 0x80; // flag pressed
bufferedPresses.push(data);
data.dwData = 0x00;
data.dwData = 0x00; // flag released
bufferedPresses.push(data);
}
@@ -193,7 +193,7 @@ public:
return RealDevice->Unacquire();
}
//Only called for the mouse
// Only called for the mouse
HRESULT _stdcall GetDeviceState(DWORD a, LPVOID b) {
if (forcingGraphicsRefresh) RefreshGraphics();
if (DeviceType != kDeviceType_MOUSE) {
@@ -212,10 +212,10 @@ public:
MouseState.rgbButtons[1] = tmp;
}
if (adjustMouseSpeed) {
double d = ((double)MouseState.lX)*mouseSpeedMod + mousePartX;
double d = ((double)MouseState.lX) * mouseSpeedMod + mousePartX;
mousePartX = modf(d, &d);
MouseState.lX = (LONG)d;
d = ((double)MouseState.lY)*mouseSpeedMod + mousePartY;
d = ((double)MouseState.lY) * mouseSpeedMod + mousePartY;
mousePartY = modf(d, &d);
MouseState.lY = (LONG)d;
}
@@ -263,7 +263,7 @@ public:
return 0;
}
//Only called for the keyboard
// Only called for the keyboard
HRESULT _stdcall GetDeviceData(DWORD a, DIDEVICEOBJECTDATA* b, DWORD* c, DWORD d) {
if (DeviceType != kDeviceType_KEYBOARD) {
return RealDevice->GetDeviceData(a, b, c, d);
@@ -271,7 +271,7 @@ public:
onInputLoop.invoke();
if (!b || bufferedPresses.empty() || (d&DIGDD_PEEK)) {
if (!b || bufferedPresses.empty() || (d & DIGDD_PEEK)) {
HRESULT hr = RealDevice->GetDeviceData(a, b, c, d);
if (FAILED(hr) || !b || !(*c)) return hr;
for (DWORD i = 0; i < *c; i++) {
@@ -295,7 +295,7 @@ public:
}
HRESULT _stdcall SetDataFormat(const DIDATAFORMAT* a) {
if (formatLock&&oldFormat.dwSize) return RealDevice->SetDataFormat(&oldFormat);
if (formatLock && oldFormat.dwSize) return RealDevice->SetDataFormat(&oldFormat);
memcpy(&oldFormat, a, sizeof(DIDATAFORMAT));
return RealDevice->SetDataFormat(a);
}
@@ -305,8 +305,8 @@ public:
}
HRESULT _stdcall SetCooperativeLevel(HWND a, DWORD b) {
if (DeviceType == kDeviceType_KEYBOARD&&backgroundKeyboard) b = DISCL_BACKGROUND | DISCL_NONEXCLUSIVE;
if (DeviceType == kDeviceType_MOUSE&&backgroundMouse) b = DISCL_BACKGROUND | DISCL_NONEXCLUSIVE;
if (DeviceType == kDeviceType_KEYBOARD && backgroundKeyboard) b = DISCL_BACKGROUND | DISCL_NONEXCLUSIVE;
if (DeviceType == kDeviceType_MOUSE && backgroundMouse) b = DISCL_BACKGROUND | DISCL_NONEXCLUSIVE;
return RealDevice->SetCooperativeLevel(a, b);
}
@@ -362,8 +362,8 @@ public:
/*** IDirectInput8A methods ***/
HRESULT _stdcall CreateDevice(REFGUID r, IDirectInputDeviceA** device, IUnknown* unused) {
GUID GUID_SysMouse = { 0x6F1D2B60, 0xD5A0, 0x11CF, { 0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00} };
GUID GUID_SysKeyboard = { 0x6F1D2B61, 0xD5A0, 0x11CF, { 0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00} };
GUID GUID_SysMouse = { 0x6F1D2B60, 0xD5A0, 0x11CF, { 0xBF, 0xC7, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00} };
GUID GUID_SysKeyboard = { 0x6F1D2B61, 0xD5A0, 0x11CF, { 0xBF, 0xC7, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00} };
if (r != GUID_SysKeyboard && r != GUID_SysMouse) {
return RealInput->CreateDevice(r, device, unused);
@@ -406,8 +406,6 @@ public:
};
inline void InitInputFeatures() {
ZeroMemory(keysDown, sizeof(keysDown));
reverseMouse = GetConfigInt("Input", "ReverseMouseButtons", 0) != 0;
useScrollWheel = GetConfigInt("Input", "UseScrollWheel", 1) != 0;
+55 -52
View File
@@ -22,12 +22,11 @@
#include "Books.h"
namespace sfall
namespace sfall
{
static int BooksCount = 0;
static const int BooksMax = 30;
static char iniBooks[MAX_PATH];
static const int BooksMax = 50;
struct sBook {
DWORD bookPid;
@@ -35,10 +34,10 @@ struct sBook {
DWORD skill;
};
static sBook books[BooksMax];
static sBook* books = nullptr;
static sBook* _stdcall FindBook(DWORD pid) {
for (int i = 0; i < BooksCount; i++) {
static sBook* __fastcall FindBook(DWORD pid) {
for (int i = BooksCount; i >= 0; i--) {
if (books[i].bookPid == pid) {
return &books[i];
}
@@ -49,73 +48,77 @@ static sBook* _stdcall FindBook(DWORD pid) {
static const DWORD obj_use_book_hook_back = 0x49BA5A;
static void __declspec(naked) obj_use_book_hook() {
__asm {
push eax;
mov edi, -1;
mov ecx, eax;
call FindBook;
test eax, eax;
jnz found;
mov edi, -1;
jmp end;
found:
mov edi, [eax + 4];
mov ecx, [eax + 8];
end:
jmp obj_use_book_hook_back;
cmovnz edi, [eax + 4]; // msgID
cmovnz ecx, [eax + 8]; // skill
jmp obj_use_book_hook_back;
}
}
void LoadVanillaBooks() {
int i = BooksCount;
static void LoadVanillaBooks() {
// book of science
books[i + 0].bookPid = 73;
books[i + 0].msgID = 802;
books[i + 0].skill = 12;
books[0].bookPid = 73;
books[0].msgID = 802;
books[0].skill = 12;
// Dean's electronics
books[i + 1].bookPid = 76;
books[i + 1].msgID = 803;
books[i + 1].skill = 13;
books[1].bookPid = 76;
books[1].msgID = 803;
books[1].skill = 13;
// First Aid
books[i + 2].bookPid = 80;
books[i + 2].msgID = 804;
books[i + 2].skill = 6;
books[2].bookPid = 80;
books[2].msgID = 804;
books[2].skill = 6;
// Guns & Bullets
books[i + 3].bookPid = 102;
books[i + 3].msgID = 805;
books[i + 3].skill = 0;
books[3].bookPid = 102;
books[3].msgID = 805;
books[3].skill = 0;
// Scouts Handbook
books[i + 4].bookPid = 86;
books[i + 4].msgID = 806;
books[i + 4].skill = 17;
BooksCount += 5;
books[4].bookPid = 86;
books[4].msgID = 806;
books[4].skill = 17;
}
void Books::init() {
auto booksFile = GetConfigString("Misc", "BooksFile", "", MAX_PATH);
if (booksFile.size() > 0) {
sprintf(iniBooks, ".\\%s", booksFile.c_str());
if (!booksFile.empty()) {
dlog("Applying books patch...", DL_INIT);
memset(books, 0, sizeof(sBook)*BooksCount);
const char* iniBooks = booksFile.insert(0, ".\\").c_str();
int i, n = 0, count;
if (GetPrivateProfileIntA("main", "overrideVanilla", 0, iniBooks) == 0) {
LoadVanillaBooks();
}
count = GetPrivateProfileIntA("main", "count", 0, iniBooks);
bool includeVanilla = (GetPrivateProfileIntA("main", "overrideVanilla", 0, iniBooks) == 0);
if (includeVanilla) BooksCount = 5;
char section[4];
for (i = 1; i <= count; i++) {
_itoa_s(i, section, 10);
if (BooksCount >= BooksMax) break;
if (books[BooksCount].bookPid = GetPrivateProfileIntA(section, "PID", 0, iniBooks)) {
books[BooksCount].msgID = GetPrivateProfileIntA(section, "TextID", 0, iniBooks);
books[BooksCount].skill = GetPrivateProfileIntA(section, "Skill", 0, iniBooks);
n++;
BooksCount++;
int count = max(0, GetPrivateProfileIntA("main", "count", 0, iniBooks));
if (count > BooksMax) count = BooksMax;
int n = 0;
if (count > 0) {
books = new sBook[BooksCount + count];
if (includeVanilla) LoadVanillaBooks();
char section[4];
for (int i = 1; i <= count; i++) {
_itoa_s(i, section, 10);
if (books[BooksCount].bookPid = GetPrivateProfileIntA(section, "PID", 0, iniBooks)) {
books[BooksCount].msgID = GetPrivateProfileIntA(section, "TextID", 0, iniBooks);
books[BooksCount].skill = GetPrivateProfileIntA(section, "Skill", 0, iniBooks);
BooksCount++;
n++;
}
}
}
BooksCount--; // set to last index
MakeJump(0x49B9FB, obj_use_book_hook);
MakeJump(0x49B9FB, obj_use_book_hook);
}
dlog_f(" (%d/%d books) Done\n", DL_INIT, n, count);
}
}
void Books::exit() {
if (books) delete[] books;
}
}
+1
View File
@@ -27,6 +27,7 @@ class Books : public Module {
public:
const char* name() { return "Books"; }
void init();
void exit() override;
};
}
+141 -32
View File
@@ -17,9 +17,9 @@ static DWORD weightOnBody = 0;
static char textBuf[355];
void ResetBodyState() {
_asm mov critterBody, 0;
_asm mov sizeOnBody, 0;
_asm mov weightOnBody, 0;
__asm mov critterBody, 0;
__asm mov sizeOnBody, 0;
__asm mov weightOnBody, 0;
}
void GameInitialization() {
@@ -1166,13 +1166,13 @@ end:
static void __declspec(naked) use_inventory_on_hack() {
__asm {
inc ecx
mov edx, [eax] // Inventory.inv_size
sub edx, ecx
jge end
mov edx, [eax] // Inventory.inv_size
inc ecx;
mov edx, [eax]; // Inventory.inv_size
sub edx, ecx;
jge end;
mov edx, [eax]; // Inventory.inv_size
end:
retn
retn;
}
}
@@ -1610,7 +1610,7 @@ static void __declspec(naked) op_start_gdialog_hack() {
mov eax, dword ptr [esp + 0x3C - 0x30 + 4]; // fix dialog_target (overwritten engine code)
retn;
useMood:
add esp, 4; // Destroy the return address
add esp, 4; // Destroy the return address
jmp op_start_gdialog_ret;
}
}
@@ -1741,6 +1741,72 @@ skip:
}
}
static void __declspec(naked) combat_attack_hack() {
__asm {
mov ebx, ds:[FO_VAR_main_ctd + 0x2C]; // amountTarget
test ebx, ebx;
jz end;
retn;
end:
add esp, 4;
mov ebx, 0x423039;
jmp ebx;
}
}
static void __declspec(naked) op_attack_hook() {
__asm {
mov esi, dword ptr [esp + 0x3C + 4]; // free_move
mov ebx, dword ptr [esp + 0x40 + 4]; // add amount damage to target
jmp fo::funcoffs::gdialogActive_;
}
}
static void __declspec(naked) op_use_obj_on_obj_hack() {
__asm {
test eax, eax; // source
jz fail;
mov edx, [eax + protoId];
shr edx, 24;
retn;
fail:
add esp, 4;
mov edx, 0x45C3A3; // exit func
jmp edx;
}
}
static void __declspec(naked) op_use_obj_hack() {
__asm {
test eax, eax; // source
jz fail;
mov edx, [eax + protoId];
shr edx, 24;
retn;
fail:
add esp, 4;
mov edx, 0x456ABA; // exit func
jmp edx;
}
}
static const DWORD combat_End = 0x422E45;
static const DWORD combat_Load = 0x422E91;
static void __declspec(naked) combat_hack_load() {
__asm {
cmp eax, -1;
je skip;
retn;
skip:
add esp, 4; // destroy addr
cmp ds:[FO_VAR_combat_end_due_to_load], 0;
jnz isLoad;
jmp combat_End;
isLoad:
jmp combat_Load;
}
}
void BugFixes::init()
{
@@ -1771,7 +1837,7 @@ void BugFixes::init()
dlog("Applying Sharpshooter patch.", DL_INIT);
// http://www.nma-fallout.com/threads/fo2-engine-tweaks-sfall.178390/page-119#post-4050162
// by Slider2k
HookCall(0x4244AB, &SharpShooterFix); // hooks stat_level_() call in detemine_to_hit_func_()
HookCall(0x4244AB, SharpShooterFix); // hooks stat_level_() call in detemine_to_hit_func_()
// // removes this line by making unconditional jump:
// if ( who == obj_dude )
// dist -= 2 * perk_level_(obj_dude, PERK_sharpshooter);
@@ -1792,8 +1858,8 @@ void BugFixes::init()
// Fix for "Too Many Items" bug
//if (GetConfigInt("Misc", "TooManyItemsBugFix", 1)) {
dlog("Applying preventive patch for \"Too Many Items\" bug.", DL_INIT);
HookCall(0x4A596A, &scr_write_ScriptNode_hook);
HookCall(0x4A59C1, &scr_write_ScriptNode_hook);
HookCall(0x4A596A, scr_write_ScriptNode_hook);
HookCall(0x4A59C1, scr_write_ScriptNode_hook);
dlogr(" Done", DL_INIT);
//}
@@ -1814,7 +1880,7 @@ void BugFixes::init()
// Fix crash when leaving the map while waiting for someone to die of a super stimpak overdose
dlog("Applying fix for \"leaving the map while waiting for a super stimpak overdose death\" crash.", DL_INIT);
HookCall(0x4A27E7, &queue_clear_type_mem_free_hook); // hooks mem_free_()
HookCall(0x4A27E7, queue_clear_type_mem_free_hook); // hooks mem_free_()
dlogr(" Done", DL_INIT);
// Evil bug! If party member has the same armor type in inventory as currently equipped, then
@@ -1822,14 +1888,14 @@ void BugFixes::init()
// The same happens if you just order NPC to remove the armor through dialogue.
//if (GetConfigInt("Misc", "ArmorCorruptsNPCStatsFix", 1)) {
dlog("Applying fix for armor reducing NPC original stats when removed.", DL_INIT);
HookCall(0x495F3B, &partyMemberCopyLevelInfo_stat_level_hook);
HookCall(0x45419B, &correctFidForRemovedItem_adjust_ac_hook);
HookCall(0x495F3B, partyMemberCopyLevelInfo_stat_level_hook);
HookCall(0x45419B, correctFidForRemovedItem_adjust_ac_hook);
dlogr(" Done", DL_INIT);
//}
// Fix of invalid stats when party member gains a level while being on drugs
dlog("Applying fix for addicted party member level up bug.", DL_INIT);
HookCall(0x495D5C, &partyMemberCopyLevelInfo_hook);
HookCall(0x495D5C, partyMemberCopyLevelInfo_hook);
dlogr(" Done", DL_INIT);
// Allow 9 options (lines of text) to be displayed correctly in a dialog window
@@ -1841,7 +1907,7 @@ void BugFixes::init()
// Fix for "Unlimited Ammo" exploit
dlog("Applying fix for Unlimited Ammo exploit.", DL_INIT);
HookCall(0x472957, &invenWieldFunc_item_get_type_hook); // hooks item_get_type_()
HookCall(0x472957, invenWieldFunc_item_get_type_hook); // hooks item_get_type_()
dlogr(" Done", DL_INIT);
// Fix for negative values in Skilldex window ("S")
@@ -1853,8 +1919,8 @@ void BugFixes::init()
dlog("Applying fix for negative SPECIAL values in character creation.", DL_INIT);
MakeCall(0x43DF6F, is_supper_bonus_hack);
MakeCall(0x434BFF, PrintBasicStat_hack);
HookCall(0x437AB4, &StatButtonUp_hook);
HookCall(0x437B26, &StatButtonDown_hook);
HookCall(0x437AB4, StatButtonUp_hook);
HookCall(0x437B26, StatButtonDown_hook);
dlogr(" Done", DL_INIT);
// Fix for not counting in the weight/size of equipped items on NPC when stealing or bartering
@@ -1883,7 +1949,7 @@ void BugFixes::init()
// also for reverse order error
MakeJump(0x47114A, inven_pickup_hack2);
// Fix for using only one box of ammo when a weapon is above the ammo in the inventory list
HookCall(0x476598, &drop_ammo_into_weapon_hook);
HookCall(0x476598, drop_ammo_into_weapon_hook);
dlogr(" Done", DL_INIT);
//}
@@ -1895,13 +1961,13 @@ void BugFixes::init()
//if (GetConfigInt("Misc", "BlackSkilldexFix", 1)) {
dlog("Applying black Skilldex patch.", DL_INIT);
HookCall(0x497D0F, &PipStatus_AddHotLines_hook);
HookCall(0x497D0F, PipStatus_AddHotLines_hook);
dlogr(" Done", DL_INIT);
//}
//if (GetConfigInt("Misc", "FixWithdrawalPerkDescCrash", 1)) {
dlog("Applying withdrawal perk description crash fix.", DL_INIT);
HookCall(0x47A501, &perform_withdrawal_start_display_print_hook);
HookCall(0x47A501, perform_withdrawal_start_display_print_hook);
dlogr(" Done", DL_INIT);
//}
@@ -1940,7 +2006,7 @@ void BugFixes::init()
//if (GetConfigInt("Misc", "WieldObjCritterFix", 1)) {
dlog("Applying wield_obj_critter fix.", DL_INIT);
SafeWrite8(0x456912, 0x1E);
HookCall(0x45697F, &op_wield_obj_critter_adjust_ac_hook);
HookCall(0x45697F, op_wield_obj_critter_adjust_ac_hook);
dlogr(" Done", DL_INIT);
//}
@@ -1966,7 +2032,7 @@ void BugFixes::init()
MakeCall(0x424F8E, set_new_results_hack);
MakeJump(0x42E46E, critter_wake_clear_hack);
MakeJump(0x488EF3, obj_load_func_hack);
HookCall(0x4949B2, &partyMemberPrepLoadInstance_hook);
HookCall(0x4949B2, partyMemberPrepLoadInstance_hook);
dlogr(" Done", DL_INIT);
//}
@@ -1985,7 +2051,7 @@ void BugFixes::init()
SafeWrite8(0x478115, 0xBA);
SafeWrite8(0x478138, 0xBA);
MakeJump(0x474D22, barter_attempt_transaction_hack);
HookCall(0x4798B1, &item_m_turn_off_hook);
HookCall(0x4798B1, item_m_turn_off_hook);
dlogr(" Done", DL_INIT);
}
@@ -2020,7 +2086,7 @@ void BugFixes::init()
// Fix for display issues when calling gdialog_mod_barter with critters with no "Barter" flag set
//if (GetConfigInt("Misc", "gdBarterDispFix", 1)) {
dlog("Applying gdialog_mod_barter display fix.", DL_INIT);
HookCall(0x448250, &gdActivateBarter_hook);
HookCall(0x448250, gdActivateBarter_hook);
dlogr(" Done", DL_INIT);
//}
@@ -2052,7 +2118,7 @@ void BugFixes::init()
// Fix for Bonus Move APs being replenished when you save and load the game in combat
//if (GetConfigInt("Misc", "BonusMoveFix", 1)) {
dlog("Applying fix for Bonus Move exploit.", DL_INIT);
HookCall(0x420E93, &combat_load_hook);
HookCall(0x420E93, combat_load_hook);
MakeCall(0x422A06, combat_turn_hack);
dlogr(" Done", DL_INIT);
//}
@@ -2067,7 +2133,7 @@ void BugFixes::init()
//if (GetConfigInt("Misc", "SilentDeathFix", 1)) {
dlog("Applying Silent Death patch.", DL_INIT);
SafeWrite8(0x4238DF, 0x8C); // jl loc_423A0D
HookCall(0x423A99, &compute_attack_hook);
HookCall(0x423A99, compute_attack_hook);
dlogr(" Done", DL_INIT);
//}
@@ -2075,7 +2141,7 @@ void BugFixes::init()
MakeCall(0x495FF6, partyMemberGetCurLevel_hack, 1);
// Fix for player's base EMP DR not being properly initialized when creating a new character and then starting the game
HookCall(0x4A22DF, &ResetPlayer_hook);
HookCall(0x4A22DF, ResetPlayer_hook);
// Fix for add_mult_objs_to_inven only adding 500 of an object when the value of "count" argument is over 99999
SafeWrite32(0x45A2A0, 0x1869F); // 99999
@@ -2200,8 +2266,51 @@ void BugFixes::init()
// number of values (for chem_primary_desire)
MakeJump(0x42C12C, config_get_values_hack);
// Fix returned result value
HookCall(0x4C6162, db_freadInt_hook); // TODO: Resolve conflict in FileSystem.cpp
// Fix returned result value when the file is missing
HookCall(0x4C6162, db_freadInt_hook);
// Fix for attack_complex still causing minimum damage to the target when the attacker misses
MakeCall(0x422FE5, combat_attack_hack, 1);
// Fix for critter_mod_skill taking a negative amount value as a positive
dlog("Applying critter_mod_skill fix.", DL_INIT);
SafeWrite8(0x45B910, 0x7E); // jbe > jle
dlogr(" Done", DL_INIT);
// Fix and repurpose the unused called_shot/num_attack arguments of attack_complex function
// also change the behavior of the result flags arguments
// called_shot - additional damage, when the damage received by the target is above the specified minimum
// num_attacks - the number of free action points on the first turn only
// attacker_results - unused, must be 0 or not equal to the target_results argument when specifying result flags for the target
if (GetConfigInt("Misc", "AttackComplexFix", 0)) {
dlog("Applying attack_complex fix.", DL_INIT);
HookCall(0x456D4A, op_attack_hook);
SafeWrite8(0x456D61, 0x74); // mov [esp+x], esi
SafeWrite8(0x456D92, 0x5C); // mov [esp+x], ebx
SafeWrite8(0x456D98, 0x94); // setnz > setz (fix setting result flags)
dlogr(" Done", DL_INIT);
}
// Fix crash when calling use_obj/use_obj_on_obj without using set_self in global scripts
MakeCall(0x45C376, op_use_obj_on_obj_hack, 1);
MakeCall(0x456A92, op_use_obj_hack, 1);
// Fix pickup_obj/drop_obj/use_obj functions, change them to get pointer from script.self instead of script.target
// script.target contains an incorrect pointer, which may vary depending on the situations in the game
dlog("Applying pickup_obj/drop_obj/use_obj fix.", DL_INIT);
SafeWriteBatch<BYTE>(0x34, { // script.target > script.self
0x456554, // op_pickup_obj_
0x456600, // op_drop_obj_
0x456A6D, // op_use_obj_
0x456AA4 // op_use_obj_
});
dlogr(" Done", DL_INIT);
// Fix for critters not attacking the player in combat when loading a game saved in combat mode
BlockCall(0x48D6F0); // obj_fix_combat_cid_for_dude_
// Fix for the player's turn being skipped when loading a game saved in combat mode
MakeCall(0x422E25, combat_hack_load);
}
}
+10 -8
View File
@@ -43,10 +43,12 @@ static const char* critNames[] = {
"FailMessage",
};
static fo::CritInfo baseCritTable[Criticals::critTableCount][9][6]; // Base critical table set up via enabling OverrideCriticalTable in ddraw.ini
static fo::CritInfo baseCritTable[Criticals::critTableCount][9][6] = {0}; // Base critical table set up via enabling OverrideCriticalTable in ddraw.ini
static fo::CritInfo critTable[Criticals::critTableCount][9][6];
static fo::CritInfo (*playerCrit)[9][6];
static bool Inited = false;
static const char* errorTable = "\nError: %s - function requires enabling OverrideCriticalTable in ddraw.ini.";
void Criticals::SetCriticalTable(DWORD critter, DWORD bodypart, DWORD slot, DWORD element, DWORD value) {
@@ -73,12 +75,11 @@ void Criticals::ResetCriticalTable(DWORD critter, DWORD bodypart, DWORD slot, DW
critTable[critter][bodypart][slot].values[element] = baseCritTable[critter][bodypart][slot].values[element];
}
void CritLoad() {
static void CritLoad() {
if (!Inited) return;
if (mode == 1) {
dlogr("Setting up critical hit table using CriticalOverrides.ini", DL_CRITICALS);
char section[16];
memset(baseCritTable, 0, sizeof(critTable));
for (DWORD critter = 0; critter < 20; critter++) {
for (DWORD part = 0; part < 9; part++) {
for (DWORD crit = 0; crit < 6; crit++) {
@@ -102,8 +103,8 @@ void CritLoad() {
} else {
dlogr("Setting up critical hit table using RP fixes", DL_CRITICALS);
memcpy(baseCritTable, fo::var::crit_succ_eff, sizeof(critTable));
memset(&baseCritTable[19], 0, 6 * 9 * 19 * sizeof(fo::CritInfo));
memcpy(&baseCritTable[38], &fo::var::pc_crit_succ_eff, 6 * 9 * sizeof(fo::CritInfo)); // PC crit table
//memset(&baseCritTable[19], 0, 6 * 9 * 19 * sizeof(fo::CritInfo));
memcpy(&baseCritTable[38], fo::var::pc_crit_succ_eff, 6 * 9 * sizeof(fo::CritInfo)); // PC crit table
if (mode == 3) {
char buf[32], buf2[32], buf3[32];
@@ -134,13 +135,14 @@ void CritLoad() {
}
#define SetEntry(critter, bodypart, effect, param, value) fo::var::crit_succ_eff[critter][bodypart][effect].values[param] = value;
void CriticalTableOverride() {
static void CriticalTableOverride() {
dlog("Initializing critical table override.", DL_INIT);
playerCrit = &critTable[38];
SafeWrite32(0x423F96, (DWORD)playerCrit);
SafeWrite32(0x423FB3, (DWORD)critTable);
if (mode == 2 || mode == 3) {
if (mode == 2 || mode == 3) { // bug fixes
SetEntry(2, 4, 1, 4, 0);
SetEntry(2, 4, 1, 5, 5216);
SetEntry(2, 4, 1, 6, 5000);
@@ -242,7 +244,7 @@ void CriticalTableOverride() {
}
#undef SetEntry
void RemoveCriticalTimeLimitsPatch() {
static void RemoveCriticalTimeLimitsPatch() {
if (GetConfigInt("Misc", "RemoveCriticalTimelimits", 0)) {
dlog("Removing critical time limits.", DL_INIT);
SafeWrite8(0x424118, 0xEB); // jmps 0x424131
+75 -7
View File
@@ -43,6 +43,11 @@ namespace sfall
#define CODE_GET_ARRAY (9)
#define CODE_SET_ARRAY (10)
static const char* debugLog = "LOG";
static const char* debugGnw = "GNW";
static DWORD debugEditorKey = 0;
static bool SetBlocking(SOCKET s, bool block) {
DWORD d = !block;
ioctlsocket(s, FIONBIO, &d);
@@ -149,7 +154,7 @@ static void RunEditorInternal(SOCKET &s) {
sglobals[id].val = val;
break;
case 9:
{
{
InternalRecv(s, &id, 4);
DWORD *types = new DWORD[arrays[id * 3 + 1]];
char *data = new char[arrays[id * 3 + 1] * arrays[id * 3 + 2]];
@@ -158,17 +163,17 @@ static void RunEditorInternal(SOCKET &s) {
InternalSend(s, data, arrays[id * 3 + 1] * arrays[id * 3 + 2]);
delete[] data;
delete[] types;
}
break;
}
break;
case 10:
{
{
InternalRecv(s, &id, 4);
char *data = new char[arrays[id * 3 + 1] * arrays[id * 3 + 2]];
InternalRecv(s, data, arrays[id * 3 + 1] * arrays[id * 3 + 2]);
script::DESetArray(arrays[id * 3], 0, data);
delete[] data;
}
break;
}
break;
}
}
@@ -238,10 +243,69 @@ void RunDebugEditor() {
WSACleanup();
}
static DWORD debugEditorKey = 0;
static void __declspec(naked) dbg_error_hack() {
__asm {
cmp ebx, 1;
je hide;
sub esp, 0x104;
retn;
hide:
add esp, 4; // destroy this return addr
pop esi;
pop ecx;
retn;
}
}
static void __declspec(naked) win_debug_hook() {
__asm {
call fo::funcoffs::debug_log_;
xor eax, eax;
cmp ds:[FO_VAR_GNW_win_init_flag], eax;
retn;
}
}
void DebugModePatch() {
DWORD dbgMode = GetPrivateProfileIntA("Debugging", "DebugMode", 0, ::sfall::ddrawIni);
if (dbgMode) {
dlog("Applying debugmode patch.", DL_INIT);
//If the player is using an exe with the debug patch already applied, just skip this block without erroring
if (*((DWORD*)0x444A64) != 0x082327E8) {
SafeWrite32(0x444A64, 0x082327E8); // call debug_register_env_
SafeWrite32(0x444A68, 0x0120E900); // jmp 0x444B8E
SafeWrite8(0x444A6D, 0);
SafeWrite32(0x444A6E, 0x90909090);
}
SafeWrite8(0x4C6D9B, 0xB8); // mov eax, GNW/LOG
if (dbgMode & 2) {
SafeWrite32(0x4C6D9C, (DWORD)debugLog);
if (dbgMode & 1) {
SafeWrite16(0x4C6E75, 0x66EB); // jmps 0x4C6EDD
SafeWrite8(0x4C6EF2, 0xEB);
SafeWrite8(0x4C7034, 0x0);
MakeCall(0x4DC319, win_debug_hook, 2);
}
} else {
SafeWrite32(0x4C6D9C, (DWORD)debugGnw);
}
dlogr(" Done", DL_INIT);
}
}
void DontDeleteProtosPatch() {
if (GetPrivateProfileIntA("Debugging", "DontDeleteProtos", 0, ::sfall::ddrawIni)) {
dlog("Applying permanent protos patch.", DL_INIT);
SafeWrite8(0x48007E, 0xEB);
dlogr(" Done", DL_INIT);
}
}
void DebugEditor::init() {
if (!isDebug) return;
DebugModePatch();
DontDeleteProtosPatch();
debugEditorKey = GetConfigInt("Input", "DebugEditorKey", 0);
if (debugEditorKey != 0) {
OnKeyPressed() += [](DWORD scanCode, bool pressed) {
@@ -250,6 +314,10 @@ void DebugEditor::init() {
}
};
}
if (GetPrivateProfileIntA("Debugging", "HideObjIsNullMsg", 0, ::sfall::ddrawIni)) {
MakeCall(0x453FD2, dbg_error_hack, 1);
}
}
}
+19 -18
View File
@@ -28,12 +28,12 @@ static const int exitsPerElevator = 4;
static const int vanillaElevatorCount = 24;
static const int elevatorCount = 50;
static char elevFile[MAX_PATH] = ".\\";
//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 DWORD elevatorType[elevatorCount] = {0};
static fo::ElevatorExit elevatorExits[elevatorCount][exitsPerElevator] = {0}; // _retvals
static fo::ElevatorFrms elevatorsFrms[elevatorCount] = {0}; // _intotal
static DWORD elevatorsBtnCount[elevatorCount] = {0}; // _btncount
static void __declspec(naked) GetMenuHook() {
__asm {
@@ -100,16 +100,19 @@ static void __declspec(naked) GetNumButtonsHook3() {
}
void ResetElevators() {
//memset(&elevatorExits[vanillaElevatorCount], 0, sizeof(fo::ElevatorExit) * (elevatorCount - vanillaElevatorCount) * exitsPerElevator);
//memset(&elevatorsFrms[vanillaElevatorCount], 0, sizeof(fo::ElevatorFrms) * (elevatorCount - vanillaElevatorCount));
//for (int i = vanillaElevatorCount; i < elevatorCount; i++) elevatorType[i] = 0;
}
static void LoadElevators(const char* elevFile) {
//ResetElevators();
memcpy(elevatorExits, fo::var::retvals, sizeof(fo::ElevatorExit) * vanillaElevatorCount * exitsPerElevator);
memset(&elevatorExits[vanillaElevatorCount], 0, sizeof(fo::ElevatorExit) * (elevatorCount - vanillaElevatorCount) * exitsPerElevator);
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) {
@@ -137,9 +140,7 @@ void ResetElevators() {
}
}
void ElevatorsInit(const char* file) {
strcat_s(elevFile, file);
void ElevatorsInit() {
HookCall(0x43EF83, GetMenuHook);
HookCall(0x43F141, CheckHotKeysHook);
//HookCall(0x43F2D2, UnknownHook2); // unused
@@ -161,15 +162,15 @@ void ElevatorsInit(const char* file) {
MakeCall(0x43F05D, GetNumButtonsHook1, 2);
MakeCall(0x43F184, GetNumButtonsHook2, 2);
MakeCall(0x43F1E4, GetNumButtonsHook3, 2);
ResetElevators();
}
void Elevators::init() {
auto elevPath = GetConfigString("Misc", "ElevatorsFile", "", MAX_PATH);
if (elevPath.size() > 0) {
dlogr("Applying elevator patch.", DL_INIT);
ElevatorsInit(elevPath.c_str());
if (!elevPath.empty()) {
dlog("Applying elevator patch.", DL_INIT);
ElevatorsInit();
LoadElevators(elevPath.insert(0, ".\\").c_str());
dlogr(" Done", DL_INIT);
}
}

Some files were not shown because too many files have changed in this diff Show More