Added a fix to the weapon check in the Fast Shot trait (#335)

* changed range check to type+range check, the same fix is also applied
to FastShotTraitFix.

Added more info to the description of FastShotFix option.
This commit is contained in:
NovaRain
2020-09-05 10:39:22 +08:00
parent 282a491718
commit 2badb5fdd2
3 changed files with 56 additions and 28 deletions
+6 -6
View File
@@ -534,10 +534,10 @@ RemoveCriticalTimelimits=0
;Change the colour of the font used on the main menu for the button text
;MainMenuBigFontColour=0x3C
;Two alternate fixes to the interaction between HtH attacks and the fast shot trait
;0 - Fallout 2 original behaviour
;1 - Haenlomal's fix, called shots are enabled for HtH attacks
;2 - Restoring the -1 AP bonus for HtH attacks (i.e. Fallout 1 behaviour)
;Alternative behaviors to the Fast Shot trait
;0 - Fallout 2 original behavior: -1 AP cost for ranged weapons; no aimed shots for all attacks
;1 - Haenlomal's fix: aimed shots are enabled for melee/unarmed weapons and HtH attacks
;2 - Alternative behavior: apply -1 AP cost to melee/unarmed weapons and HtH attacks
FastShotFix=1
;Set to 1 to boost the maximum number of script names from 1450 to 10000
@@ -557,9 +557,9 @@ CritterInvSizeLimit=100
MotionScannerFlags=1
;Set a value greater than 40 to change the maximum encounter table size (enc_## in worldmap.txt)
;Note: Setting this greater than 50 requires renumbering all message lines for the encounter tables in worldmap.msg
;so that the message numbers for each table will start from (3000 + table number * 100)
;Default is 40, and the maximum is 100
;Note: Setting this greater than 50 requires renumbering all message lines for the encounter tables in worldmap.msg
;The messages for each table must be numbered from (3000 + table number * 100) to (3099 + table number * 100)
EncounterTableSize=0
;Set to 1 to disable the pipboy alarm button
+2 -1
View File
@@ -467,7 +467,8 @@
#define Stereo16bit (soundstereo bwor sound16bit)
#define Stereo16bitLoop (soundstereo bwor sound16bit bwor soundloop)
// Adjust/reduce volume: 0x0000XXXX - max volume, 0x7FFFXXXX - mute
// Adjust (reduce) volume for soundplay and play_sfall_sound
// range: 0x0000XXXX (max volume) - 0x7FFFXXXX (mute)
#define SoundVolume25 (0x20000000)
#define SoundVolumeHalf (0x40000000)
#define SoundVolume75 (0x60000000)
+48 -21
View File
@@ -1232,39 +1232,66 @@ dlgExit:
}
}
static void __declspec(naked) item_w_called_shot_hack() {
static const DWORD FastShotTraitFixEnd1 = 0x478E7F;
static const DWORD FastShotTraitFixEnd2 = 0x478E7B;
static void __declspec(naked) item_w_mp_cost_hook() {
__asm {
test eax, eax; // does player have Fast Shot trait?
je ajmp; // skip ahead if no
mov edx, ecx; // argument for item_w_range_: hit_mode
mov eax, ebx; // argument for item_w_range_: pointer to source_obj (always dude_obj due to code path)
call fo::funcoffs::item_w_range_; // get weapon's range
cmp eax, 0x2; // is weapon range less than or equal 2 (i.e. melee/unarmed attack)?
jle ajmp; // skip ahead if yes
xor eax, eax; // otherwise, disallow called shot attempt
jmp bjmp;
ajmp:
jmp FastShotTraitFixEnd1; // continue processing called shot attempt
bjmp:
jmp FastShotTraitFixEnd2; // clean up and exit function item_w_called_shot
call fo::funcoffs::item_w_range_;
cmp eax, 2;
jge checkType; // is weapon range less than 2?
retn; // yes, skip -1 AP cost (0x478CA2)
checkType:
mov eax, edi; // source
mov edx, ecx; // hit_mode
call fo::funcoffs::item_hit_with_; // get pointer to weapon
mov edx, ecx; // hit_mode
jmp fo::funcoffs::item_w_subtype_; // eax - item
}
}
// Haenlomal's fix
static void __declspec(naked) item_w_called_shot_hack() {
static const DWORD FastShotTraitFix_End = 0x478E7F;
__asm {
mov edx, ecx; // argument for item_hit_with_: hit_mode
mov eax, ebx; // argument for item_hit_with_: pointer to source_obj (always dude_obj due to code path)
call fo::funcoffs::item_hit_with_; // get pointer to weapon
mov edx, ecx;
call fo::funcoffs::item_w_subtype_;
cmp eax, THROWING; // is weapon type GUNS or THROWING?
jge checkRange; // yes
jmp FastShotTraitFix_End; // continue processing called shot attempt
checkRange:
mov edx, ecx; // argument for item_w_range_: hit_mode
mov eax, ebx; // argument for item_w_range_: pointer to source_obj (always dude_obj due to code path)
call fo::funcoffs::item_w_range_; // get weapon's range
cmp eax, 2; // is weapon range greater than or equal to 2 (i.e. ranged attack)?
jge cantUse; // yes, disallow called shot attempt
jmp FastShotTraitFix_End; // continue processing called shot attempt
cantUse:
xor eax, eax; // clean up and exit function item_w_called_shot
pop esi;
pop ecx;
pop ebx;
retn;
}
}
static void FastShotTraitFix() {
switch (GetConfigInt("Misc", "FastShotFix", 1)) {
case 1:
dlog("Applying Fast Shot Trait Fix.", DL_INIT);
MakeJump(0x478E75, item_w_called_shot_hack);
goto done;
dlog("Applying Fast Shot trait patch. (Haenlomal's fix)", DL_INIT);
MakeJump(0x478E79, item_w_called_shot_hack);
goto fix;
case 2:
dlog("Applying Fast Shot Trait Fix. (Fallout 1 version)", DL_INIT);
dlog("Applying Fast Shot trait patch. (Alternative behavior)", DL_INIT);
SafeWrite16(0x478C9F, 0x9090);
HookCalls((void*)0x478C7D, {0x478BB8, 0x478BC7, 0x478BD6, 0x478BEA, 0x478BF9, 0x478C08, 0x478C2F});
goto done;
default:
dlog("Applying Fast Shot trait fix.", DL_INIT);
fix:
HookCall(0x478C97, item_w_mp_cost_hook);
done:
dlogr(" Done", DL_INIT);
break;
}
}