Fixed the Jet addiction was not removed when using the antidote (#405)

(BGforgeNet/Fallout2_Restoration_Project#118)
This commit is contained in:
NovaRain
2021-08-29 10:20:01 +08:00
parent d9b7a714ec
commit dfd810c9e4
4 changed files with 48 additions and 28 deletions
+2 -2
View File
@@ -212,10 +212,10 @@ long CheckAddictByPid(fo::GameObject* critter, long pid) {
// Checks whether the player is under the influence of negative effects of radiation
long __fastcall IsRadInfluence() {
fo::QueueRadiation* queue = (fo::QueueRadiation*)fo::func::queue_find_first(fo::var::obj_dude, fo::radiation_event);
fo::QueueRadiationData* queue = (fo::QueueRadiationData*)fo::func::queue_find_first(fo::var::obj_dude, fo::radiation_event);
while (queue) {
if (queue->init && queue->level >= 2) return 1;
queue = (fo::QueueRadiation*)fo::func::queue_find_next(fo::var::obj_dude, fo::radiation_event);
queue = (fo::QueueRadiationData*)fo::func::queue_find_next(fo::var::obj_dude, fo::radiation_event);
}
return 0;
}
+4 -4
View File
@@ -993,12 +993,12 @@ struct Queue {
Queue* next;
};
struct QueueRadiation {
struct QueueRadiationData {
long level;
long init; // 1 - for removing effect
};
struct QueueDrug {
struct QueueDrugData {
DWORD pid;
fo::Stat stat0;
fo::Stat stat1;
@@ -1008,8 +1008,8 @@ struct QueueDrug {
long amount2;
};
struct QueueAddict {
long init; // 1 - perk is not active yet
struct QueueAddictData {
long wait; // 1 - waiting for applying the addiction effects (perk is not active yet)
DWORD drugPid;
fo::Perk perkId; // effect of addiction
};
+40 -20
View File
@@ -264,29 +264,49 @@ skip:
}
}
static void __declspec(naked) item_d_check_addict_hack() { // replace engine function
static void __declspec(naked) item_wd_process_hack() {
__asm {
push 0x47A6A1; // return addr
mov edx, 2; // type = addiction
cmp esi, PERK_add_jet; // esi - queue_addict.perk
je jetAddict;
retn;
jetAddict:
push ecx;
xor edx, edx; // init (0 - effects of addiction have already been applied)
mov eax, ecx; // critter (any party members or dude)
push [ebx + 0x4]; // queue_addict.drugPid (PID_JET)
mov ebx, 10080; // time (7 days)
mov ecx, esi; // addict perk (PERK_add_jet)
call fo::funcoffs::insert_withdrawal_;
pop ecx;
mov [esp], 0x47A3FB; // return addr
retn;
}
}
// replaces the item_d_check_addict_ function in item_d_take_drug_ with an alternative implementation
static void __declspec(naked) item_d_take_drug_hook() { // eax - pid, esi - critter
__asm {
mov edx, addict_event; // type = addiction
cmp eax, -1; // Has drug_pid?
jne skip; // No
mov eax, dword ptr ds:[FO_VAR_obj_dude];
jmp fo::funcoffs::queue_find_first_; // return player addiction
jmp fo::funcoffs::queue_find_first_; // return queue of player addiction
skip:
mov ebx, eax; // ebx = drug_pid
mov eax, esi; // eax = who
call fo::funcoffs::queue_find_first_;
loopQueue:
test eax, eax; // Has something in the list?
jz end; // No
loopQueue:
cmp ebx, dword ptr [eax + 0x4]; // drug_pid == queue_addict.drug_pid?
je end; // Has specific addiction
mov eax, esi; // eax = who
mov edx, 2; // type = addiction
mov edx, addict_event; // type = addiction
call fo::funcoffs::queue_find_next_;
jmp loopQueue;
test eax, eax; // Has something in the list?
jnz loopQueue;
end:
retn;
retn; // return null or pointer to queue_addict
}
}
@@ -304,18 +324,15 @@ end:
static void __declspec(naked) item_d_take_drug_hack() {
__asm {
cmp dword ptr [eax], 0; // queue_addict.init
cmp dword ptr [eax], 0; // queue_addict.wait (queue returned from item_d_take_drug_hook)
jne skip; // Addiction is not active yet
mov edx, PERK_add_jet;
mov eax, esi;
call fo::funcoffs::perform_withdrawal_end_;
skip:
skip: // remove event from queue
mov dword ptr ds:[FO_VAR_wd_obj], esi;
mov eax, 2; // type = addiction
mov eax, addict_event; // type = addiction
mov edx, offset RemoveJetAddictFunc;
call fo::funcoffs::queue_clear_type_;
push 0x479FD1;
retn;
jmp fo::funcoffs::queue_clear_type_;
}
}
@@ -535,7 +552,7 @@ loopAddict:
call fo::funcoffs::item_d_check_addict_;
test eax, eax; // Has addiction?
jz noAddict; // No
cmp dword ptr [eax], 0; // queue_addict.init
cmp dword ptr [eax], 0; // queue_addict.wait
jne noAddict; // Addiction is not active yet
mov edx, dword ptr [eax + 0x8]; // queue_addict.perk
mov eax, ebx;
@@ -3326,16 +3343,19 @@ void BugFixes::init()
//if (IniReader::GetConfigInt("Misc", "JetAntidoteFix", 1)) {
dlog("Applying Jet Antidote fix.", DL_FIX);
// the original jet antidote fix
MakeJump(0x47A013, (void*)0x47A168);
// Fix for Jet antidote not being removed after removing the addiction effect (when using the item)
MakeJump(0x47A013, (void*)0x47A168); // item_d_take_drug_
dlogr(" Done", DL_FIX);
//}
//if (IniReader::GetConfigInt("Misc", "NPCDrugAddictionFix", 1)) {
dlog("Applying NPC's drug addiction fix.", DL_FIX);
// proper checks for NPC's addiction instead of always using global vars
MakeJump(0x47A644, item_d_check_addict_hack);
MakeJump(0x479FC5, item_d_take_drug_hack);
HookCalls(item_d_take_drug_hook, {0x479FBC, 0x47A0AE});
MakeCall(0x479FCA, item_d_take_drug_hack, 2);
// just add a new "addict" event every 7 days (the previous one is deleted) until the Jet addiction is removed by the antidote
// Note: for critters who are not party members, any addiction is removed after leaving the map
MakeCall(0x47A3A4, item_wd_process_hack);
dlogr(" Done", DL_FIX);
//}
+2 -2
View File
@@ -68,11 +68,11 @@ static long __fastcall AllowUseDrug(fo::GameObject* critter, DWORD pid) {
if (drugs[i].drugPid == pid) {
if (drugs[i].numEffects == -1) break; // use NumEffects value from engine
if (drugs[i].numEffects == 0) return 1;
auto queue = (fo::QueueDrug*)fo::func::queue_find_first(critter, 0);
auto queue = (fo::QueueDrugData*)fo::func::queue_find_first(critter, 0);
if (!queue) return 1;
int num = 0;
while (queue->pid != pid || ++num < drugs[i].numEffects) {
queue = (fo::QueueDrug*)fo::func::queue_find_next(critter, 0);
queue = (fo::QueueDrugData*)fo::func::queue_find_next(critter, 0);
if (!queue) return 1;
}
return 0; // not allow