mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Merge branch 'develop'
This commit is contained in:
@@ -14,15 +14,16 @@ 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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 -------
|
||||
------------------------
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -700,4 +700,13 @@ struct AIcap {
|
||||
long general_type;
|
||||
};
|
||||
|
||||
#pragma pack(1)
|
||||
struct Queue {
|
||||
DWORD time;
|
||||
long type;
|
||||
GameObject* object;
|
||||
long data;
|
||||
Queue* next;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
+54
-51
@@ -26,8 +26,7 @@ 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ class Books : public Module {
|
||||
public:
|
||||
const char* name() { return "Books"; }
|
||||
void init();
|
||||
void exit() override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+141
-32
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
Reference in New Issue
Block a user