mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Fixed the Jet addiction was not removed when using the antidote (#405)
(BGforgeNet/Fallout2_Restoration_Project#118)
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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);
|
||||
//}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user