mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Added a new hook: HOOK_ADJUSTPOISON
Added a fix to the poison handling in the engine when an NPC is under the player's control.
This commit is contained in:
@@ -69,6 +69,7 @@
|
||||
#define HOOK_STDPROCEDURE_END (41)
|
||||
#define HOOK_TARGETOBJECT (42)
|
||||
#define HOOK_ENCOUNTER (43)
|
||||
#define HOOK_ADJUSTPOISON (44)
|
||||
|
||||
//Valid arguments to list_begin
|
||||
#define LIST_CRITTERS (0)
|
||||
|
||||
@@ -368,7 +368,7 @@ int ret0 - overrides the pressed key (a new key DX scancode or 0 for no over
|
||||
|
||||
HOOK_MOUSECLICK (hs_mouseclick.int)
|
||||
|
||||
Runs once every time when a mouse button was pressed or release.
|
||||
Runs once every time when a mouse button was pressed or released.
|
||||
|
||||
int arg0 - event type: 1 - pressed, 0 - released
|
||||
int arg1 - button number (0 - left, 1 - right, up to 7)
|
||||
@@ -693,3 +693,17 @@ int arg2 - 1 when the encounter occurs is a special encounter, 0 otherwise
|
||||
|
||||
int ret0 - overrides the map ID, or pass -1 for event type 0 to cancel the encounter and continue traveling
|
||||
int ret1 - pass 1 to cancel the encounter and load the specified map from the ret1 (only for event type 0)
|
||||
|
||||
-------------------------------------------
|
||||
|
||||
HOOK_ADJUSTPOISON (hs_adjustpoison.int)
|
||||
|
||||
Runs when a critter's poison level is changed, or when the player takes damage from the poison.
|
||||
|
||||
Critter arg0 - the critter
|
||||
int arg1 - the amount of poison being added/removed
|
||||
int arg2 - the damage value at the time of applying the poison effect
|
||||
(damage from the poison effect is implemented only for the player character; for other critters, this value will always be 0)
|
||||
|
||||
int ret0 - the new amount of poison being added/removed
|
||||
int ret1 - the new damage value, only negative values are allowed (will only be valid at the time of taking damage from the poison)
|
||||
|
||||
@@ -205,6 +205,7 @@ WRAP_WATCOM_FUNC0(void, process_bk)
|
||||
WRAP_WATCOM_FUNC0(void, proto_dude_update_gender)
|
||||
// Places pointer to a prototype structure into ptrPtr and returns 0 on success or -1 on failure
|
||||
WRAP_WATCOM_FUNC2(long, proto_ptr, long, pid, Proto**, ptrPtr)
|
||||
WRAP_WATCOM_FUNC2(void, queue_clear_type, long, qType, void*, func)
|
||||
WRAP_WATCOM_FUNC2(void*, queue_find_first, GameObject*, object, long, qType)
|
||||
WRAP_WATCOM_FUNC2(void*, queue_find_next, GameObject*, object, long, qType)
|
||||
WRAP_WATCOM_FUNC2(void, queue_remove_this, GameObject*, object, long, qType)
|
||||
|
||||
@@ -16,6 +16,6 @@ public:
|
||||
|
||||
extern int tagSkill4LevelBase;
|
||||
|
||||
extern void ResetBodyState();
|
||||
void ResetBodyState();
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* sfall
|
||||
* Copyright (C) 2008-2021 The sfall team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "..\main.h"
|
||||
#include "..\FalloutEngine\Fallout2.h"
|
||||
#include "PartyControl.h"
|
||||
|
||||
#include "CritterPoison.h"
|
||||
|
||||
namespace sfall
|
||||
{
|
||||
|
||||
//static long adjustPoison = -2;
|
||||
|
||||
long CritterPoison::adjustPoisonHP_Default = -1;
|
||||
long CritterPoison::adjustPoisonHP; // default or returned value from HOOK_ADJUSTPOISON
|
||||
|
||||
void CritterPoison::SetDefaultAdjustPoisonHP(long value) {
|
||||
adjustPoisonHP_Default = adjustPoisonHP = value;
|
||||
}
|
||||
|
||||
void __fastcall sf_critter_adjust_poison(fo::GameObject* critter, long amount) {
|
||||
if (amount == 0) return;
|
||||
if (amount > 0) {
|
||||
amount -= fo::func::stat_level(critter, fo::STAT_poison_resist) * amount / 100;
|
||||
} else if (critter->critter.poison == 0) {
|
||||
return;
|
||||
}
|
||||
critter->critter.poison += amount;
|
||||
if (critter->critter.poison < 0) {
|
||||
critter->critter.poison = 0; // level can't be negative
|
||||
} else {
|
||||
// set uID for saving queue
|
||||
//Objects::SetObjectUniqueID(critter);
|
||||
//fo::func::queue_add(10 * (505 - 5 * critter->critter.poison), critter, nullptr, fo::QueueType::poison_event);
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) critter_adjust_poison_hack() {
|
||||
__asm {
|
||||
mov edx, esi;
|
||||
mov ecx, edi;
|
||||
jmp sf_critter_adjust_poison;
|
||||
}
|
||||
}
|
||||
|
||||
void __declspec(naked) critter_check_poison_hack() {
|
||||
__asm {
|
||||
mov eax, CritterPoison::adjustPoisonHP_Default;
|
||||
mov edx, CritterPoison::adjustPoisonHP;
|
||||
mov CritterPoison::adjustPoisonHP, eax;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
void __fastcall critter_check_poison_fix() {
|
||||
if (PartyControl::IsNpcControlled()) {
|
||||
// since another critter is being controlled, we can't apply the poison effect to it
|
||||
// instead, we add the "poison" event to dude again, which will be triggered when dude returns to the player's control
|
||||
fo::func::queue_clear_type(fo::QueueType::poison_event, nullptr);
|
||||
fo::GameObject* dude = PartyControl::RealDudeObject();
|
||||
fo::func::queue_add(10, dude, nullptr, fo::QueueType::poison_event);
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) critter_check_poison_hack_fix() {
|
||||
using namespace fo;
|
||||
using namespace Fields;
|
||||
__asm {
|
||||
mov ecx, [eax + protoId]; // critter.pid
|
||||
cmp ecx, PID_Player;
|
||||
jnz notDude;
|
||||
retn;
|
||||
notDude:
|
||||
call critter_check_poison_fix;
|
||||
or al, 1; // unset ZF (exit from func)
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
void __declspec(naked) critter_adjust_poison_hack_fix() { // can also be called from HOOK_ADJUSTPOISON
|
||||
using namespace fo;
|
||||
using namespace Fields;
|
||||
__asm {
|
||||
mov edx, ds:[FO_VAR_obj_dude];
|
||||
mov ebx, [eax + protoId]; // critter.pid
|
||||
mov ecx, PID_Player;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
void CritterPoison::init() {
|
||||
// Allow changing the poison level for critters
|
||||
MakeCall(0x42D226, critter_adjust_poison_hack);
|
||||
SafeWrite8(0x42D22C, 0xDA); // jmp 0x42D30A
|
||||
|
||||
// Adjust poison damage
|
||||
SetDefaultAdjustPoisonHP(*(DWORD*)0x42D332);
|
||||
MakeCall(0x42D331, critter_check_poison_hack);
|
||||
|
||||
// Fix/tweak for party control
|
||||
MakeCall(0x42D31F, critter_check_poison_hack_fix, 1);
|
||||
MakeCall(0x42D21C, critter_adjust_poison_hack_fix, 1);
|
||||
SafeWrite8(0x42D223, 0xCB); // cmp eax, edx > cmp ebx, ecx
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* sfall
|
||||
* Copyright (C) 2008-2021 The sfall team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Module.h"
|
||||
|
||||
namespace sfall
|
||||
{
|
||||
|
||||
class CritterPoison : public Module {
|
||||
public:
|
||||
const char* name() { return "CritterPoison"; }
|
||||
void init();
|
||||
|
||||
static long adjustPoisonHP_Default;
|
||||
static long adjustPoisonHP; // temp value from HOOK_ADJUSTPOISON
|
||||
|
||||
static void SetDefaultAdjustPoisonHP(long value);
|
||||
};
|
||||
|
||||
void critter_adjust_poison_hack_fix();
|
||||
|
||||
}
|
||||
@@ -103,6 +103,7 @@ static HooksInjectInfo injectHooks[] = {
|
||||
{HOOK_STDPROCEDURE_END, Inject_ScriptProcedureHook2, false},
|
||||
{HOOK_TARGETOBJECT, Inject_TargetObjectHook, false},
|
||||
{HOOK_ENCOUNTER, Inject_EncounterHook, false},
|
||||
{HOOK_ADJUSTPOISON, Inject_AdjustPoisonHook, false},
|
||||
};
|
||||
|
||||
void HookScripts::InjectingHook(int hookId) {
|
||||
|
||||
@@ -70,6 +70,7 @@ enum HookType
|
||||
HOOK_STDPROCEDURE_END = 41,
|
||||
HOOK_TARGETOBJECT = 42,
|
||||
HOOK_ENCOUNTER = 43,
|
||||
HOOK_ADJUSTPOISON = 44,
|
||||
HOOK_COUNT
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "..\..\FalloutEngine\Fallout2.h"
|
||||
#include "..\..\SafeWrite.h"
|
||||
#include "..\HookScripts.h"
|
||||
#include "..\CritterPoison.h"
|
||||
#include "Common.h"
|
||||
|
||||
#include "ObjectHs.h"
|
||||
@@ -302,6 +303,36 @@ skip:
|
||||
}
|
||||
}
|
||||
|
||||
static DWORD __fastcall AdjustPoison_Script(DWORD critter, long amount, DWORD addr) {
|
||||
BeginHook();
|
||||
argCount = 3;
|
||||
|
||||
bool checkPoison = (addr == (0x42D32C + 5)); // from critter_check_poison_
|
||||
|
||||
args[0] = critter;
|
||||
args[1] = amount;
|
||||
args[2] = (checkPoison) ? CritterPoison::adjustPoisonHP_Default : 0;
|
||||
|
||||
RunHookScript(HOOK_ADJUSTPOISON);
|
||||
|
||||
if (cRet > 0) amount = rets[0];
|
||||
if (cRet > 1 && checkPoison && (long)rets[1] < 0) CritterPoison::adjustPoisonHP = rets[1];
|
||||
|
||||
EndHook();
|
||||
return amount;
|
||||
}
|
||||
|
||||
static void __declspec(naked) critter_adjust_poison_hack() {
|
||||
__asm {
|
||||
push [esp + 0x24 + 4]; // called from
|
||||
mov ecx, eax; // critter
|
||||
call AdjustPoison_Script; // edx - amount
|
||||
mov esi, eax; // old/new amount
|
||||
mov eax, edi; // restore eax value
|
||||
jmp critter_adjust_poison_hack_fix; // in CritterPoison
|
||||
}
|
||||
}
|
||||
|
||||
void Inject_UseObjOnHook() {
|
||||
HookCalls(UseObjOnHook, { 0x49C606, 0x473619 });
|
||||
|
||||
@@ -310,7 +341,7 @@ void Inject_UseObjOnHook() {
|
||||
0x4285DF, // ai_check_drugs
|
||||
0x4286F8, // ai_check_drugs
|
||||
0x4287F8, // ai_check_drugs
|
||||
0x473573 // inven_action_cursor
|
||||
0x473573 // inven_action_cursor
|
||||
});
|
||||
}
|
||||
|
||||
@@ -339,6 +370,10 @@ void Inject_ScriptProcedureHook2() {
|
||||
HookCall(0x4A49A7, After_ScriptStdProcedureHook);
|
||||
}
|
||||
|
||||
void Inject_AdjustPoisonHook() {
|
||||
MakeCall(0x42D21C, critter_adjust_poison_hack, 1);
|
||||
}
|
||||
|
||||
void InitObjectHookScripts() {
|
||||
HookScripts::LoadHookScript("hs_useobjon", HOOK_USEOBJON);
|
||||
HookScripts::LoadHookScript("hs_useobj", HOOK_USEOBJ);
|
||||
@@ -347,6 +382,7 @@ void InitObjectHookScripts() {
|
||||
HookScripts::LoadHookScript("hs_setlighting", HOOK_SETLIGHTING);
|
||||
HookScripts::LoadHookScript("hs_stdprocedure", HOOK_STDPROCEDURE); // combo hook
|
||||
HookScripts::LoadHookScript("hs_stdprocedure", HOOK_STDPROCEDURE_END);
|
||||
HookScripts::LoadHookScript("hs_adjustpoison", HOOK_ADJUSTPOISON);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,4 +11,5 @@ namespace sfall
|
||||
void Inject_SetLightingHook();
|
||||
void Inject_ScriptProcedureHook();
|
||||
void Inject_ScriptProcedureHook2();
|
||||
void Inject_AdjustPoisonHook();
|
||||
}
|
||||
|
||||
@@ -916,10 +916,7 @@ static void __fastcall SetPanPosition(fo::ACMSoundData* sound) {
|
||||
if (distance > 5) {
|
||||
long direction = fo::func::tile_dir(fo::var::obj_dude->tile, relativeObject->tile);
|
||||
bool isRightSide = (direction <= 2);
|
||||
|
||||
long panValue = (distance - 5) * 100;
|
||||
if (panValue > 10000) panValue = 10000;
|
||||
|
||||
long panValue = (distance < 55) ? (distance - 5) * 200 : 10000;
|
||||
sound->soundBuffer->SetPan((isRightSide) ? panValue : -panValue); // left mute 10000 ... -10000 right mute
|
||||
}
|
||||
relativeObject = nullptr; // just in case
|
||||
|
||||
@@ -26,17 +26,6 @@
|
||||
namespace sfall
|
||||
{
|
||||
|
||||
void __fastcall sf_critter_adjust_poison(fo::GameObject* critter, long amount) {
|
||||
if (amount == 0) return;
|
||||
if (amount > 0) {
|
||||
amount -= fo::func::stat_level(critter, fo::STAT_poison_resist) * amount / 100;
|
||||
} else if (critter->critter.poison == 0) {
|
||||
return;
|
||||
}
|
||||
critter->critter.poison += amount;
|
||||
if (critter->critter.poison < 0) critter->critter.poison = 0; // level can't be negative
|
||||
}
|
||||
|
||||
static DWORD statMaximumsPC[fo::STAT_max_stat];
|
||||
static DWORD statMinimumsPC[fo::STAT_max_stat];
|
||||
static DWORD statMaximumsNPC[fo::STAT_max_stat];
|
||||
@@ -220,14 +209,6 @@ allow:
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) critter_adjust_poison_hack() {
|
||||
__asm {
|
||||
mov edx, esi;
|
||||
mov ecx, edi;
|
||||
jmp sf_critter_adjust_poison;
|
||||
}
|
||||
}
|
||||
|
||||
static void StatsReset() {
|
||||
for (size_t i = 0; i < fo::STAT_max_stat; i++) {
|
||||
statMaximumsPC[i] = statMaximumsNPC[i] = fo::var::stat_data[i].maxValue;
|
||||
@@ -262,9 +243,6 @@ void Stats::init() {
|
||||
// Allow set_critter_stat function to change STAT_unused and STAT_dmg_* stats for the player
|
||||
MakeCall(0x4AF54E, stat_set_base_hack_allow);
|
||||
MakeCall(0x455D65, op_set_critter_stat_hack); // STAT_unused for other critters
|
||||
// Allow changing the poison level for critters
|
||||
MakeCall(0x42D226, critter_adjust_poison_hack);
|
||||
SafeWrite8(0x42D22C, 0xDA); // jmp 0x42D30A
|
||||
|
||||
auto xpTableList = GetConfigList("Misc", "XPTable", "", 2048);
|
||||
size_t numLevels = xpTableList.size();
|
||||
|
||||
@@ -291,6 +291,7 @@
|
||||
<ClInclude Include="FalloutEngine\Variables.h" />
|
||||
<ClInclude Include="FalloutEngine\Functions.h" />
|
||||
<ClInclude Include="FalloutEngine\Functions_def.h" />
|
||||
<ClInclude Include="Modules\CritterPoison.h" />
|
||||
<ClInclude Include="Modules\CritterStats.h" />
|
||||
<ClInclude Include="Modules\Interface.h" />
|
||||
<ClInclude Include="Modules\Drugs.h" />
|
||||
@@ -388,6 +389,7 @@
|
||||
<ClCompile Include="FalloutEngine\FunctionOffsets.cpp" />
|
||||
<ClCompile Include="FalloutEngine\Variables.cpp" />
|
||||
<ClCompile Include="FalloutEngine\Functions.cpp" />
|
||||
<ClCompile Include="Modules\CritterPoison.cpp" />
|
||||
<ClCompile Include="Modules\CritterStats.cpp" />
|
||||
<ClCompile Include="Modules\Interface.cpp" />
|
||||
<ClCompile Include="Modules\Drugs.cpp" />
|
||||
|
||||
@@ -304,6 +304,9 @@
|
||||
<ClInclude Include="Modules\SubModules\GameRender.h">
|
||||
<Filter>Modules\SubModules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Modules\CritterPoison.h">
|
||||
<Filter>Modules</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp" />
|
||||
@@ -562,6 +565,9 @@
|
||||
<ClCompile Include="Modules\SubModules\GameRender.cpp">
|
||||
<Filter>Modules\SubModules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Modules\CritterPoison.cpp">
|
||||
<Filter>Modules</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="version.rc" />
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "Modules\Credits.h"
|
||||
#include "Modules\Criticals.h"
|
||||
#include "Modules\CritterStats.h"
|
||||
#include "Modules\CritterPoison.h"
|
||||
#include "Modules\DamageMod.h"
|
||||
#include "Modules\DebugEditor.h"
|
||||
#include "Modules\Drugs.h"
|
||||
@@ -185,6 +186,7 @@ static void InitModules() {
|
||||
manager.add<Worldmap>();
|
||||
manager.add<Stats>();
|
||||
manager.add<CritterStats>();
|
||||
manager.add<CritterPoison>();
|
||||
manager.add<Perks>();
|
||||
manager.add<Combat>();
|
||||
manager.add<Skills>();
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@
|
||||
|
||||
#define TARGETVERSION "Fallout 2 v1.02 US"
|
||||
|
||||
#define LEGAL_COPYRIGHT "Copyright (C) 2006-2020, sfall team"
|
||||
#define LEGAL_COPYRIGHT "Copyright (C) 2006-2021, sfall team"
|
||||
|
||||
#define VERSION_MAJOR 4
|
||||
#define VERSION_MINOR 2
|
||||
|
||||
Reference in New Issue
Block a user