mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe5f4bb2aa | ||
|
|
715b55dda8 | ||
|
|
1d7fd442b0 | ||
|
|
9f0797f8ad | ||
|
|
ccd897281f | ||
|
|
d200262a2b | ||
|
|
d0c97f7118 | ||
|
|
41c8722179 | ||
|
|
1b3b5dc523 |
@@ -38,3 +38,17 @@ MotionScanner=0
|
||||
;If you want to control only specific critters, uncomment the PIDList line and set a comma delimited list of PIDs
|
||||
Mode=0
|
||||
;PIDList=62,89,97,107,160,161
|
||||
|
||||
;Choose a notification box to display the name of the controlled critter above the interface bar. Must be between 5 and 9
|
||||
;Set to 0 to disable
|
||||
DisplayName=0
|
||||
|
||||
;Set the color of display name, available colors:
|
||||
;0 - green
|
||||
;1 - red
|
||||
;2 - white
|
||||
;3 - yellow
|
||||
;4 - dark yellow
|
||||
;5 - blue
|
||||
;6 - purple
|
||||
DisplayNameColor=0
|
||||
|
||||
+8
-3
@@ -1,5 +1,5 @@
|
||||
;sfall configuration settings
|
||||
;v4.0.5
|
||||
;v4.0.8
|
||||
|
||||
[Main]
|
||||
;Change to 1 if you want to use command line args to tell sfall to use another ini file.
|
||||
@@ -345,6 +345,10 @@ SkipOpeningMovies=0
|
||||
;Set to 0 to disable
|
||||
NPCsTryToSpendExtraAP=0
|
||||
|
||||
;Set to 1 to fix NPCs not checking weapon perks properly when searching for the best weapon
|
||||
;Note that enabling this option can significantly affect the weapon choice of some NPCs in combat
|
||||
AIBestWeaponFix=0
|
||||
|
||||
;Allows the use of tiles over 80*36 in size. sfall will just split and resave them at startup
|
||||
;Set to 1 to check all tiles on started (slow)
|
||||
;Set to 2 if you provide a XLtiles.lst file in art/tiles/ containing a list of the tile ids that need checking
|
||||
@@ -366,7 +370,7 @@ Repair=293
|
||||
;Remove window position rounding
|
||||
RemoveWindowRounding=0
|
||||
|
||||
;Set to 1 to add scroll buttons to the pip boy quest list, and remove the quests per area limit
|
||||
;Set to 1 to add scroll buttons to the pipboy quest list, and remove the quests per area limit
|
||||
UseScrollingQuestsList=1
|
||||
|
||||
;Uncomment these lines to control the premade characters offered when starting a new game
|
||||
@@ -375,7 +379,7 @@ UseScrollingQuestsList=1
|
||||
;PremadeFIDs=201,203,202
|
||||
|
||||
;Use this line to modify the list of cities and their associated global variables used for city reputations
|
||||
;Syntax is 'city id : global id', with each city/global pair separated by a comma.
|
||||
;Syntax is 'city id:global id', with each city/global pair separated by a comma.
|
||||
;CityRepsList=0:47,2:48,1:49,4:50,5:51,3:52,8:53,6:54,7:55,13:56,10:57,11:59,14:61,17:63,19:64,18:65,25:66,9:294,20:308
|
||||
|
||||
;Set this to a valid path to save a copy of the console contents
|
||||
@@ -551,6 +555,7 @@ DontTurnOffSneakIfYouRun=0
|
||||
CanSellUsedGeiger=1
|
||||
|
||||
;Set to 1 to fix the issue with being able to charge the car by using cells on other scenary/critters
|
||||
;Set to 0 if another mod you're using has custom vehicles
|
||||
CarChargingFix=1
|
||||
|
||||
;Set to 1 to skip weapon equip/unequip animations when performing various actions
|
||||
|
||||
Binary file not shown.
@@ -12,12 +12,16 @@
|
||||
*/
|
||||
|
||||
#include "..\headers\define.h"
|
||||
#include "..\headers\command.h"
|
||||
#include "main.h"
|
||||
|
||||
variable
|
||||
configSection := "CombatControl",
|
||||
controlMode,
|
||||
pidList,
|
||||
displayName,
|
||||
displayNameColor,
|
||||
inControl := false,
|
||||
hasGeckoSkinning := false;
|
||||
|
||||
|
||||
@@ -33,25 +37,45 @@ procedure combatturn_handler begin
|
||||
if (status == 1
|
||||
and (len_array(pidList) == 0 or scan_array(pidList, pid bwand 0xFFFFFF) != -1)
|
||||
and (controlMode == 1 or party_member_obj(pid))) then begin
|
||||
set_dude_obj(critter);
|
||||
if hasGeckoSkinning then critter_add_trait(critter, TRAIT_PERK, PERK_gecko_skinning_perk, 1);
|
||||
end else begin
|
||||
if not(critter == real_dude_obj) then begin
|
||||
set_dude_obj(critter);
|
||||
if hasGeckoSkinning then critter_add_trait(critter, TRAIT_PERK, PERK_gecko_skinning_perk, 1);
|
||||
inControl := true;
|
||||
end
|
||||
if inControl then begin
|
||||
// center the screen on the controlled critter and remove roof tiles
|
||||
move_to(dude_obj, dude_tile, dude_elevation);
|
||||
if displayName then begin
|
||||
set_iface_tag_text(displayName, obj_name(critter), displayNameColor);
|
||||
show_iface_tag(displayName);
|
||||
end
|
||||
end
|
||||
end else if inControl then begin
|
||||
set_dude_obj(real_dude_obj);
|
||||
if displayName then hide_iface_tag(displayName);
|
||||
end
|
||||
end
|
||||
|
||||
procedure gamemodechange_handler begin
|
||||
if not(get_game_mode BWAND COMBAT) then inControl := false;
|
||||
end
|
||||
|
||||
procedure start begin
|
||||
if game_loaded and (sfall_ver_major >= 4) then begin
|
||||
set_perk_ranks(PERK_gecko_skinning_perk, 1);
|
||||
set_perk_level(PERK_gecko_skinning_perk, 999); // prevent it from appearing in the perk selection window
|
||||
controlMode := GetConfig("CombatControl", "Mode", 0);
|
||||
displayName := GetConfig("CombatControl", "DisplayName", 0);
|
||||
displayNameColor := GetConfig("CombatControl", "DisplayNameColor", 0);
|
||||
if (controlMode > 2) then controlMode := 0;
|
||||
if (displayName < 5 or displayName > 9) then displayName := 0;
|
||||
if (controlMode > 0) then begin
|
||||
pidList := GetConfigListInt("CombatControl", "PIDList");
|
||||
fix_array(pidList);
|
||||
if has_trait(TRAIT_PERK, dude_obj, PERK_gecko_skinning_perk) then hasGeckoSkinning := true;
|
||||
|
||||
register_hook_proc(HOOK_COMBATTURN, combatturn_handler);
|
||||
register_hook_proc(HOOK_GAMEMODECHANGE, gamemodechange_handler);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -234,6 +234,7 @@
|
||||
#define intface_is_hidden sfall_func0("intface_is_hidden")
|
||||
#define intface_redraw sfall_func0("intface_redraw")
|
||||
#define intface_show sfall_func0("intface_show")
|
||||
#define inventory_redraw(invSide) sfall_func1("inventory_redraw", invSide)
|
||||
#define item_weight(obj) sfall_func1("item_weight", obj)
|
||||
#define lock_is_jammed(obj) sfall_func1("lock_is_jammed", obj)
|
||||
#define outlined_object sfall_func0("outlined_object")
|
||||
|
||||
@@ -497,7 +497,7 @@ int arg2 - event type: 1 - when the resting ends normally, -1 - when pressin
|
||||
int arg3 - the hour part of the length of resting time
|
||||
int arg4 - the minute part of the length of resting time
|
||||
|
||||
int ret1 - pass 1 to interrupt the resting
|
||||
int ret1 - pass 1 to interrupt the resting, pass 0 to continue the rest if it was interrupted by pressing ESC key
|
||||
|
||||
-------------------------------------------
|
||||
|
||||
|
||||
@@ -486,6 +486,10 @@ Some utility/math functions are available:
|
||||
- The text is limited to 19 characters
|
||||
- available colors: 0 - green, 1 - red, 2 - white, 3 - yellow, 4 - dark yellow, 5 - blue, 6 - purple
|
||||
|
||||
> void sfall_func1("inventory_redraw", int invSide)
|
||||
- redraws inventory list in the inventory/use inventory item on/loot/barter screens
|
||||
- invSide specifies which side needs to be redrawn: 0 - the player, 1 - target (container/NPC in loot/barter screens)
|
||||
|
||||
------------------------
|
||||
------ MORE INFO -------
|
||||
------------------------
|
||||
|
||||
@@ -31,6 +31,8 @@ WRAP_WATCOM_FUNC3(long, db_freadIntCount, DbFile*, file, DWORD*, dest, long, cou
|
||||
WRAP_WATCOM_FUNC2(long, db_fwriteByte, DbFile*, file, long, value)
|
||||
WRAP_WATCOM_FUNC2(long, db_fwriteInt, DbFile*, file, long, value)
|
||||
WRAP_WATCOM_FUNC0(void, display_stats)
|
||||
WRAP_WATCOM_FUNC3(void, display_inventory, long, inventoryOffset, long, visibleOffset, long, mode)
|
||||
WRAP_WATCOM_FUNC4(void, display_target_inventory, long, inventoryOffset, long, visibleOffset, DWORD*, targetInventory, long, mode)
|
||||
// perform combat turn for a given critter
|
||||
WRAP_WATCOM_FUNC2(long, combat_turn, GameObject*, critter, long, isDudeTurn)
|
||||
WRAP_WATCOM_FUNC1(long, critter_is_dead, GameObject*, critter)
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#define FO_VAR_dialogue_switch_mode 0x518718
|
||||
#define FO_VAR_dialog_target 0x518848
|
||||
#define FO_VAR_dialog_target_is_party 0x51884C
|
||||
#define FO_VAR_dropped_explosive 0x5190E0
|
||||
#define FO_VAR_drugInfoList 0x5191CC
|
||||
#define FO_VAR_edit_win 0x57060C
|
||||
#define FO_VAR_Educated 0x57082C
|
||||
@@ -67,6 +68,7 @@
|
||||
#define FO_VAR_gsound_initialized 0x518E30
|
||||
#define FO_VAR_hit_location_penalty 0x510954
|
||||
#define FO_VAR_holo_flag 0x664529
|
||||
#define FO_VAR_holodisk 0x6644F4
|
||||
#define FO_VAR_holopages 0x66445C
|
||||
#define FO_VAR_hot_line_count 0x6644F8
|
||||
#define FO_VAR_i_fid 0x59E95C
|
||||
@@ -150,6 +152,7 @@
|
||||
#define FO_VAR_proto_main_msg_file 0x6647FC
|
||||
#define FO_VAR_ptable 0x59E934
|
||||
#define FO_VAR_pud 0x59E960
|
||||
#define FO_VAR_quest_count 0x51C12C
|
||||
#define FO_VAR_queue 0x6648C0
|
||||
#define FO_VAR_quick_done 0x5193BC
|
||||
#define FO_VAR_read_callback 0x51DEEC
|
||||
|
||||
@@ -37,6 +37,7 @@ VAR_(dialogue_state, DWORD)
|
||||
VAR_(dialogue_switch_mode, DWORD)
|
||||
VAR_(dialog_target, DWORD)
|
||||
VAR_(dialog_target_is_party, DWORD)
|
||||
VAR_(dropped_explosive, DWORD)
|
||||
VAR_(drugInfoList, DWORD)
|
||||
VAR_(edit_win, DWORD)
|
||||
VAR_(Educated, DWORD)
|
||||
|
||||
@@ -49,6 +49,14 @@ static void __declspec(naked) PipAlarm_hack() {
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) PipStatus_hook() {
|
||||
__asm {
|
||||
call fo::funcoffs::ListHoloDiskTitles_;
|
||||
mov dword ptr ds:[FO_VAR_holodisk], ebx;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
// corrects saving script blocks (to *.sav file) by properly accounting for actual number of scripts to be saved
|
||||
static void __declspec(naked) scr_write_ScriptNode_hook() {
|
||||
__asm {
|
||||
@@ -603,7 +611,7 @@ static void __declspec(naked) op_wield_obj_critter_adjust_ac_hook() {
|
||||
// Haenlomal
|
||||
static void __declspec(naked) MultiHexFix() {
|
||||
__asm {
|
||||
xor ecx, ecx; // argument value for make_path_func: ecx=0 (unknown arg)
|
||||
xor ecx, ecx; // argument value for make_path_func: ecx=0 (rotation data arg)
|
||||
test byte ptr ds:[ebx+0x25], 0x08; // is target multihex?
|
||||
mov ebx, dword ptr ds:[ebx+0x4]; // argument value for make_path_func: target's tilenum (end_tile)
|
||||
je end; // skip if not multihex
|
||||
@@ -613,6 +621,42 @@ end:
|
||||
}
|
||||
}
|
||||
|
||||
static const DWORD ai_move_steps_closer_run_object_ret = 0x42A169;
|
||||
static void __declspec(naked) MultiHexCombatRunFix() {
|
||||
__asm {
|
||||
test byte ptr ds:[edi + 0x25], 0x08; // is target multihex?
|
||||
jnz multiHex;
|
||||
test byte ptr ds:[esi + 0x25], 0x08; // is source multihex?
|
||||
jz runTile;
|
||||
multiHex:
|
||||
mov edx, dword ptr ds:[esp + 0x4]; // source's destination tilenum
|
||||
cmp dword ptr ds:[edi + 0x4], edx; // target's tilenum
|
||||
jnz runTile;
|
||||
add esp, 4;
|
||||
jmp ai_move_steps_closer_run_object_ret;
|
||||
runTile:
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
static const DWORD ai_move_steps_closer_move_object_ret = 0x42A192;
|
||||
static void __declspec(naked) MultiHexCombatMoveFix() {
|
||||
__asm {
|
||||
test byte ptr ds:[edi + 0x25], 0x08; // is target multihex?
|
||||
jnz multiHex;
|
||||
test byte ptr ds:[esi + 0x25], 0x08; // is source multihex?
|
||||
jz moveTile;
|
||||
multiHex:
|
||||
mov edx, dword ptr ds:[esp + 0x4]; // source's destination tilenum
|
||||
cmp dword ptr ds:[edi + 0x4], edx; // target's tilenum
|
||||
jnz moveTile;
|
||||
add esp, 4;
|
||||
jmp ai_move_steps_closer_move_object_ret;
|
||||
moveTile:
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
//checks if an attacked object is a critter before attempting dodge animation
|
||||
static void __declspec(naked) action_melee_hack() {
|
||||
__asm {
|
||||
@@ -1121,6 +1165,29 @@ end:
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) op_obj_can_see_obj_hack() {
|
||||
__asm {
|
||||
mov eax, [esp + 0x2C - 0x28 + 4]; // source
|
||||
mov ecx, [eax + 4]; // source.tile
|
||||
cmp ecx, -1;
|
||||
jz end;
|
||||
mov eax, [eax + 0x28]; // source.elev
|
||||
mov edi, [edx + 0x28]; // target.elev
|
||||
cmp eax, edi; // check source.elev == target.elev
|
||||
retn;
|
||||
end:
|
||||
dec ecx; // reset ZF
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) ai_best_weapon_hook() {
|
||||
__asm {
|
||||
mov eax, [esp + 0xF4 - 0x10 + 4]; // prev.item
|
||||
jmp fo::funcoffs::item_w_perk_;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BugFixes::init()
|
||||
{
|
||||
@@ -1137,9 +1204,13 @@ void BugFixes::init()
|
||||
//}
|
||||
|
||||
// Fixes for clickability issue in Pip-Boy and exploit that allows to rest in places where you shouldn't be able to rest
|
||||
dlog("Applying fix for Pip-Boy rest exploit.", DL_INIT);
|
||||
dlog("Applying fix for Pip-Boy clickability issues and rest exploit.", DL_INIT);
|
||||
MakeCall(0x4971C7, pipboy_hack);
|
||||
MakeCall(0x499530, PipAlarm_hack);
|
||||
// Fix for clickability issue of holodisk list
|
||||
HookCall(0x497E9F, PipStatus_hook);
|
||||
SafeWrite16(0x497E8C, 0xD389); // mov ebx, edx
|
||||
SafeWrite32(0x497E8E, 0x90909090);
|
||||
dlogr(" Done", DL_INIT);
|
||||
|
||||
// Fix for "Too Many Items" bug
|
||||
@@ -1299,6 +1370,11 @@ void BugFixes::init()
|
||||
dlog("Applying MultiHex Pathing Fix.", DL_INIT);
|
||||
MakeCall(0x42901F, MultiHexFix);
|
||||
MakeCall(0x429170, MultiHexFix);
|
||||
// Fix for multihex critters moving too close and overlapping their targets in combat
|
||||
MakeCall(0x42A14F, MultiHexCombatRunFix);
|
||||
SafeWrite8(0x42A154, 0x90);
|
||||
MakeCall(0x42A178, MultiHexCombatMoveFix);
|
||||
SafeWrite8(0x42A17D, 0x90);
|
||||
dlogr(" Done", DL_INIT);
|
||||
//}
|
||||
|
||||
@@ -1436,6 +1512,18 @@ void BugFixes::init()
|
||||
// Fix for critters killed in combat by scripting still being able to move in their combat turn if the distance parameter
|
||||
// in their AI packages is set to stay_close/charge, or NPCsTryToSpendExtraAP is enabled
|
||||
HookCall(0x42A1A8, ai_move_steps_closer_hook); // 0x42B24D
|
||||
|
||||
// Fix for obj_can_see_obj not checking if source and target objects are on the same elevation before calling
|
||||
// is_within_perception_
|
||||
MakeCall(0x456B63, op_obj_can_see_obj_hack);
|
||||
SafeWrite16(0x456B76, 0x23EB); // jmp loc_456B9B (skip unused engine code)
|
||||
|
||||
// Fix for critters not checking weapon perks properly when searching for the best weapon
|
||||
if (GetConfigInt("Misc", "AIBestWeaponFix", 0)) {
|
||||
dlog("Applying AI best weapon choice fix.", DL_INIT);
|
||||
HookCall(0x42954B, ai_best_weapon_hook);
|
||||
dlogr(" Done", DL_INIT);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -983,11 +983,7 @@ void Graphics::init() {
|
||||
}
|
||||
if (Graphics::mode == 4 || Graphics::mode == 5) {
|
||||
dlog("Applying dx9 graphics patch.", DL_INIT);
|
||||
#ifdef WIN2K
|
||||
#define _DLL_NAME "d3dx9_42.dll"
|
||||
#else
|
||||
#define _DLL_NAME "d3dx9_43.dll"
|
||||
#endif
|
||||
HMODULE h = LoadLibraryEx(_DLL_NAME, 0, LOAD_LIBRARY_AS_DATAFILE);
|
||||
if (!h) {
|
||||
MessageBoxA(0, "You have selected graphics mode 4 or 5, but " _DLL_NAME " is missing\nSwitch back to mode 0, or install an up to date version of DirectX", "Error", 0);
|
||||
|
||||
@@ -42,6 +42,8 @@ void _stdcall BeginHook();
|
||||
void _stdcall RunHookScript(DWORD hook);
|
||||
void _stdcall EndHook();
|
||||
|
||||
#define HookBegin __asm pushad __asm call BeginHook __asm popad
|
||||
|
||||
#define hookbegin(a) __asm pushad __asm call BeginHook __asm popad __asm mov argCount, a
|
||||
#define hookend __asm pushad __asm call EndHook __asm popad
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ static const DWORD RemoveObjHookRet = 0x477497;
|
||||
static void __declspec(naked) RemoveObjHook() {
|
||||
__asm {
|
||||
mov ecx, [esp + 8]; // call addr
|
||||
HookBegin;
|
||||
mov args[0], eax;
|
||||
mov args[4], edx;
|
||||
mov args[8], ebx;
|
||||
@@ -22,7 +23,6 @@ static void __declspec(naked) RemoveObjHook() {
|
||||
pushad;
|
||||
}
|
||||
|
||||
BeginHook();
|
||||
argCount = 4;
|
||||
RunHookScript(HOOK_REMOVEINVENOBJ);
|
||||
EndHook();
|
||||
@@ -38,6 +38,7 @@ static void __declspec(naked) RemoveObjHook() {
|
||||
|
||||
static void __declspec(naked) MoveCostHook() {
|
||||
__asm {
|
||||
HookBegin;
|
||||
mov args[0], eax;
|
||||
mov args[4], edx;
|
||||
call fo::funcoffs::critter_compute_ap_from_distance_
|
||||
@@ -45,7 +46,6 @@ static void __declspec(naked) MoveCostHook() {
|
||||
pushad;
|
||||
}
|
||||
|
||||
BeginHook();
|
||||
argCount = 3;
|
||||
RunHookScript(HOOK_MOVECOST);
|
||||
EndHook();
|
||||
@@ -53,7 +53,7 @@ static void __declspec(naked) MoveCostHook() {
|
||||
__asm {
|
||||
popad;
|
||||
cmp cRet, 1;
|
||||
cmovge eax, rets[0];
|
||||
cmovge eax, dword ptr rets[0];
|
||||
retn;
|
||||
}
|
||||
}
|
||||
@@ -78,16 +78,19 @@ static int __fastcall SwitchHandHook_Script(fo::GameObject* item, fo::GameObject
|
||||
if (itemReplaced && fo::GetItemType(itemReplaced) == fo::item_type_weapon && fo::GetItemType(item) == fo::item_type_ammo) {
|
||||
return -1; // to prevent inappropriate hook call after dropping ammo on weapon
|
||||
}
|
||||
|
||||
BeginHook();
|
||||
argCount = 3;
|
||||
|
||||
args[0] = (addr < 0x47136D) ? 1 : 2; // slot: 1 - left, 2 - right
|
||||
args[1] = (DWORD)item;
|
||||
args[2] = (DWORD)itemReplaced;
|
||||
|
||||
RunHookScript(HOOK_INVENTORYMOVE);
|
||||
int tmp = PartyControl::SwitchHandHook(item);
|
||||
if (tmp != -1) {
|
||||
int result = PartyControl::SwitchHandHook(item);
|
||||
if (result != -1) {
|
||||
cRetTmp = 0;
|
||||
SetHSReturn(tmp);
|
||||
SetHSReturn(result);
|
||||
}
|
||||
EndHook();
|
||||
|
||||
@@ -162,10 +165,11 @@ skip:
|
||||
// - if 0 is returned while dropping caps, selected amount - 1 will still disappear from inventory (fixed)
|
||||
static DWORD nextHookDropSkip = 0;
|
||||
static int dropResult = -1;
|
||||
static const DWORD InvenActionObjDropRet = 0x473874;
|
||||
static void __declspec(naked) InvenActionCursorObjDropHook() {
|
||||
if (nextHookDropSkip) {
|
||||
nextHookDropSkip = 0;
|
||||
dropResult = -1;
|
||||
goto skipHook;
|
||||
} else {
|
||||
__asm {
|
||||
pushad;
|
||||
@@ -180,6 +184,7 @@ static void __declspec(naked) InvenActionCursorObjDropHook() {
|
||||
}
|
||||
|
||||
if (dropResult == -1) {
|
||||
skipHook:
|
||||
_asm call fo::funcoffs::obj_drop_;
|
||||
}
|
||||
_asm retn;
|
||||
@@ -189,10 +194,28 @@ capsMultiDrop:
|
||||
if (dropResult == -1) {
|
||||
nextHookDropSkip = 1;
|
||||
_asm call fo::funcoffs::item_remove_mult_;
|
||||
} else {
|
||||
_asm mov dword ptr [esp], 0x473874; // no caps drop
|
||||
_asm retn;
|
||||
}
|
||||
_asm add esp, 4;
|
||||
_asm jmp InvenActionObjDropRet; // no caps drop
|
||||
}
|
||||
|
||||
static void __declspec(naked) InvenActionExplosiveDropHack() {
|
||||
__asm {
|
||||
pushad;
|
||||
xor ecx, ecx; // no itemReplace
|
||||
push 6; // event: item drop ground
|
||||
call InventoryMoveHook_Script; // edx - item
|
||||
cmp eax, -1; // ret value
|
||||
popad;
|
||||
jnz noDrop;
|
||||
mov dword ptr ds:[FO_VAR_dropped_explosive], ebp; // overwritten engine code (ebp = 1)
|
||||
mov nextHookDropSkip, ebp;
|
||||
retn;
|
||||
noDrop:
|
||||
add esp, 4;
|
||||
jmp InvenActionObjDropRet; // no drop
|
||||
}
|
||||
_asm retn;
|
||||
}
|
||||
|
||||
static int __fastcall DropIntoContainer(DWORD ptrCont, DWORD item, DWORD addrCall) {
|
||||
@@ -255,7 +278,7 @@ donothing:
|
||||
|
||||
/* Common InvenWield hook */
|
||||
static void InvenWieldHook_Script(int flag) {
|
||||
BeginHook();
|
||||
|
||||
argCount = 4;
|
||||
args[3] = flag; // invenwield flag
|
||||
RunHookScript(HOOK_INVENWIELD);
|
||||
@@ -265,6 +288,7 @@ static void InvenWieldHook_Script(int flag) {
|
||||
static void _declspec(naked) InvenWieldFuncHook() {
|
||||
using namespace fo;
|
||||
__asm {
|
||||
HookBegin;
|
||||
mov args[0], eax; // critter
|
||||
mov args[4], edx; // item
|
||||
mov args[8], ebx; // slot
|
||||
@@ -288,6 +312,7 @@ static void _declspec(naked) InvenWieldFuncHook() {
|
||||
// called when unwielding weapons
|
||||
static void _declspec(naked) InvenUnwieldFuncHook() {
|
||||
__asm {
|
||||
HookBegin;
|
||||
mov args[0], eax; // critter
|
||||
mov args[8], edx; // slot
|
||||
pushad;
|
||||
@@ -310,6 +335,7 @@ static void _declspec(naked) InvenUnwieldFuncHook() {
|
||||
|
||||
static void _declspec(naked) CorrectFidForRemovedItemHook() {
|
||||
__asm {
|
||||
HookBegin;
|
||||
mov args[0], eax; // critter
|
||||
mov args[4], edx; // item
|
||||
mov args[8], ebx; // item flag
|
||||
@@ -367,6 +393,8 @@ void InitInventoryHookScripts() {
|
||||
0x473851, 0x47386F,
|
||||
0x47379A // caps multi drop
|
||||
});
|
||||
MakeCall(0x473807, InvenActionExplosiveDropHack); // drop active explosives
|
||||
SafeWrite8(0x47380C, 0x90);
|
||||
|
||||
LoadHookScript("hs_invenwield", HOOK_INVENWIELD);
|
||||
HookCalls(InvenWieldFuncHook, { 0x47275E, 0x495FDF });
|
||||
|
||||
@@ -66,14 +66,16 @@ char* GetMsg(fo::MessageList *msgList, int msgRef, int msgNum) {
|
||||
void ReadExtraGameMsgFiles() {
|
||||
auto msgFileList = GetConfigList("Misc", "ExtraGameMsgFileList", "", 512);
|
||||
if (msgFileList.size() > 0) {
|
||||
int number = 0;
|
||||
for (auto& msgName : msgFileList) {
|
||||
std::string path = "game\\" + msgName + ".msg";
|
||||
fo::MessageList* list = new fo::MessageList();
|
||||
if (fo::func::message_load(list, (char*)path.data()) == 1) {
|
||||
gExtraGameMsgLists.insert(std::make_pair(0x2000 + gExtraGameMsgLists.size(), list));
|
||||
gExtraGameMsgLists.insert(std::make_pair(0x2000 + number, list));
|
||||
} else {
|
||||
delete list;
|
||||
}
|
||||
number++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,12 +24,40 @@
|
||||
namespace sfall
|
||||
{
|
||||
|
||||
static bool outRangeFlag = false;
|
||||
static DWORD calledflag = 0x0;
|
||||
static DWORD called_quest_number = 0x0;
|
||||
static DWORD total_quests = 0x0;
|
||||
static DWORD curent_quest_page = 0x0;
|
||||
static DWORD wait_flag = 0x0;
|
||||
|
||||
// Fix crash when the quest list is too long
|
||||
static void __declspec(naked) PipStatus_hook_printfix() {
|
||||
__asm {
|
||||
test outRangeFlag, 0xFF;
|
||||
jnz force;
|
||||
call fo::funcoffs::_word_wrap_;
|
||||
push eax;
|
||||
movzx eax, word ptr [esp + 0x49C + 8];
|
||||
dec eax;
|
||||
shl eax, 1;
|
||||
add eax, dword ptr ds:[FO_VAR_cursor_line];
|
||||
cmp eax, dword ptr ds:[FO_VAR_bottom_line]; // check max
|
||||
jb skip;
|
||||
mov eax, dword ptr ds:[FO_VAR_quest_count];
|
||||
sub eax, 2;
|
||||
mov dword ptr [esp + 0x4BC - 0x24 + 8], eax; // set last counter
|
||||
mov outRangeFlag, 1;
|
||||
skip:
|
||||
pop eax;
|
||||
retn;
|
||||
force:
|
||||
or eax, -1; // force log error "out of range"
|
||||
mov outRangeFlag, 0;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) newhookpress() {
|
||||
__asm {
|
||||
push eax;
|
||||
@@ -357,10 +385,12 @@ void QuestListPatch() {
|
||||
}
|
||||
|
||||
void QuestList::init() {
|
||||
if(GetConfigInt("Misc", "UseScrollingQuestsList", 0)) {
|
||||
if (GetConfigInt("Misc", "UseScrollingQuestsList", 0)) {
|
||||
dlog("Applying quests list patch ", DL_INIT);
|
||||
QuestListPatch();
|
||||
dlogr(" Done", DL_INIT);
|
||||
} else {
|
||||
HookCall(0x498186, PipStatus_hook_printfix); // fix "out of range" bug when printing a list of quests
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -460,5 +460,32 @@ void sf_set_iface_tag_text(OpcodeContext& ctx) {
|
||||
}
|
||||
}
|
||||
|
||||
void sf_inventory_redraw(OpcodeContext& ctx) {
|
||||
int mode = -1;
|
||||
DWORD loopFlag = GetLoopFlags();
|
||||
if (loopFlag & INVENTORY) {
|
||||
mode = 0;
|
||||
} else if (loopFlag & INTFACEUSE) {
|
||||
mode = 1;
|
||||
} else if (loopFlag & INTFACELOOT) {
|
||||
mode = 2;
|
||||
} else if (loopFlag & BARTER) {
|
||||
mode = 3;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ctx.arg(0).asBool()) {
|
||||
int* stack_offset = (int*)FO_VAR_stack_offset;
|
||||
stack_offset[fo::var::curr_stack * 4] = 0;
|
||||
fo::func::display_inventory(0, -1, mode);
|
||||
} else if (mode >= 2) {
|
||||
int* target_stack_offset = (int*)FO_VAR_target_stack_offset;
|
||||
target_stack_offset[fo::var::target_curr_stack * 4] = 0;
|
||||
fo::func::display_target_inventory(0, -1, (DWORD*)fo::var::target_pud, mode);
|
||||
fo::func::win_draw(fo::var::i_wid);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,5 +91,7 @@ void sf_display_stats(OpcodeContext&);
|
||||
|
||||
void sf_set_iface_tag_text(OpcodeContext&);
|
||||
|
||||
void sf_inventory_redraw(OpcodeContext&);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,6 +94,7 @@ static const SfallMetarule metarules[] = {
|
||||
{"intface_is_hidden", sf_intface_is_hidden, 0, 0},
|
||||
{"intface_redraw", sf_intface_redraw, 0, 0},
|
||||
{"intface_show", sf_intface_show, 0, 0},
|
||||
{"inventory_redraw", sf_inventory_redraw, 1, 1, {ARG_INT}},
|
||||
{"item_weight", sf_item_weight, 1, 1, {ARG_OBJECT}},
|
||||
{"lock_is_jammed", sf_lock_is_jammed, 1, 1, {ARG_OBJECT}},
|
||||
{"outlined_object", sf_outlined_object, 0, 0},
|
||||
|
||||
+1
-1
@@ -128,8 +128,8 @@ static void InitModules() {
|
||||
auto& manager = ModuleManager::getInstance();
|
||||
|
||||
// initialize all modules
|
||||
manager.add<SpeedPatch>();
|
||||
manager.add<BugFixes>();
|
||||
manager.add<SpeedPatch>();
|
||||
manager.add<Graphics>();
|
||||
manager.add<Input>();
|
||||
manager.add<Movies>();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user