diff --git a/artifacts/config_files/Drugs.ini b/artifacts/config_files/Drugs.ini index 12d47595..d11e9ae7 100644 --- a/artifacts/config_files/Drugs.ini +++ b/artifacts/config_files/Drugs.ini @@ -13,18 +13,25 @@ Count=0 [1] ; drug item PID PID=0 + ; set a limit on the count of first and second delayed effects when using the drug, i.e. if the queue has delayed effects from the drug, ; and their count is greater or equal to NumEffects, it is not possible to obtain new effects from using the drug -; this count is 4 for Buffout/Mentats/Psycho/Jet +; e.g. this count is 4 for Buffout/Mentats/Psycho/Jet ; set -1 to leave this parameter unchanged NumEffects=-1 + ; the duration of the addiction effect in game minutes (i.e. 1440 = 24 game hours) -; set to 0 to use the default time (7 days for all drugs except Jet) +; set to 0 to use the default time of 7 days (as all drugs except Jet) AddictTime=0 + ; the number of the global variable from vault13.gam responsible for displaying addiction in the character screen +; if you set GvarID with numbers: 21-26, 295, 296, or variable numbers that have already been declared in previous sections, +; the TextID and FrmID options in this section will be ignored ; set to 0 if the addiction is not required GvarID=0 + ; the index number from editor.msg to display the title of the addiction (the description uses the index number of TextID + 100) TextID=-1 + ; the line number (0-indexed) of the corresponding FRM in skilldex.lst FrmID=-1 diff --git a/sfall/Modules/BugFixes.cpp b/sfall/Modules/BugFixes.cpp index f512c3fa..225662eb 100644 --- a/sfall/Modules/BugFixes.cpp +++ b/sfall/Modules/BugFixes.cpp @@ -1509,7 +1509,7 @@ static void __declspec(naked) ResetPlayer_hook() { static void __declspec(naked) obj_move_to_tile_hack() { static const DWORD obj_move_to_tile_Ret = 0x48A74E; __asm { - cmp ds:[FO_VAR_loadingGame], 0; // prevents leaving the map after reloading a saved game if the player died + cmp ds:[FO_VAR_loadingGame], 0; // prevents leaving the map after loading a saved game if the player died jnz skip; // on the world map from radiation (or in some cases on another map) cmp dword ptr ds:[FO_VAR_map_state], 0; // map number, -1 exit to worldmap jz mapLeave; diff --git a/sfall/Modules/Drugs.cpp b/sfall/Modules/Drugs.cpp index b71cf0d5..252da488 100644 --- a/sfall/Modules/Drugs.cpp +++ b/sfall/Modules/Drugs.cpp @@ -121,10 +121,29 @@ static void __declspec(naked) perform_withdrawal_start_hack() { } } +static bool IsEngineAddictGvar(long gNum) { + for (size_t i = 0; i < 9; i++) { + if (fo::var::drugInfoList[i].addictGvar == gNum) return true; + } + return false; +} + static long __fastcall PrintAddictionList(long isSeparator) { + std::vector gVars; // gvar list of already displayed addictions long isSelect = 0; + for (int i = 0; i < drugsCount; i++) { - if (drugs[i].gvarID > 0 && fo::var::game_global_vars[drugs[i].gvarID]) { + if (drugs[i].skip) continue; + long gvarID = drugs[i].gvarID; + if (gvarID > 0 && fo::var::game_global_vars[gvarID]) { + + if (IsEngineAddictGvar(gvarID)) { + drugs[i].skip = 1; // skip this element next time + continue; + } + if (std::find(gVars.cbegin(), gVars.cend(), gvarID) != gVars.cend()) continue; + gVars.push_back(gvarID); + if (!isSeparator) { // print separator line isSeparator = 1; const char* message = fo::GetMessageStr(&fo::var::editor_message_file, 4001); diff --git a/sfall/Modules/Drugs.h b/sfall/Modules/Drugs.h index b82666b1..73597e7a 100644 --- a/sfall/Modules/Drugs.h +++ b/sfall/Modules/Drugs.h @@ -39,7 +39,7 @@ public: static long SetDrugAddictTimeOff(long pid, long time); }; -#define SIZE_S_DRUGS (32) +#define SIZE_S_DRUGS (32 + 1) struct sDrugs { DWORD drugPid; // don't move @@ -50,6 +50,8 @@ struct sDrugs { long frmID; long iniNumEffects; long iniAddictTimeOff; + + char skip; }; extern sDrugs *drugs; diff --git a/sfall/Modules/Explosions.cpp b/sfall/Modules/Explosions.cpp index eac6d6fb..b456588a 100644 --- a/sfall/Modules/Explosions.cpp +++ b/sfall/Modules/Explosions.cpp @@ -49,10 +49,9 @@ static bool explosionsMetaruleReset = false; static bool explosionsDamageReset = false; static bool explosionMaxTargetReset = false; -static const DWORD ranged_attack_lighting_fix_back = 0x4118F8; - // enable lighting for flying projectile, based on projectile PID data (light intensity & radius) static void __declspec(naked) ranged_attack_lighting_fix() { + static const DWORD ranged_attack_lighting_fix_back = 0x4118F8; __asm { mov eax, [esp + 40]; // source projectile ptr - 1st arg mov ecx, [eax + lightIntensity]; // check existing light intensity @@ -68,9 +67,9 @@ skip: } } -static const DWORD explosion_effect_hook_back = 0x411AB9; static DWORD explosion_effect_starting_dir = 0; static void __declspec(naked) explosion_effect_hook() { + static const DWORD explosion_effect_hook_back = 0x411AB9; __asm { mov bl, lightingEnabled; test bl, bl; @@ -95,9 +94,9 @@ skiplight: } } -static const DWORD explosion_lighting_fix2_back = 0x412FC7; // enable lighting for central explosion object (action_explode) static void __declspec(naked) explosion_lighting_fix2() { + static const DWORD explosion_lighting_fix2_back = 0x412FC7; __asm { mov eax, [esp + 24]; mov edx, 1; // turn on @@ -122,8 +121,8 @@ static void __declspec(naked) explosion_lighting_fix2() { // return value1; //} -static const DWORD anim_set_check_light_back = 0x415A4C; static void __declspec(naked) anim_set_check_light_fix() { + static const DWORD anim_set_check_light_back = 0x415A4C; __asm { mov eax, [esi + 4]; // object lea ecx, [esp + 16]; // unknown.. something related to next "tile_refresh_rect" call? @@ -143,9 +142,9 @@ end: } } -static const DWORD fire_dance_lighting_back = 0x410A4F; // enable lighting for burning poor guy static void __declspec(naked) fire_dance_lighting_fix1() { + static const DWORD fire_dance_lighting_back = 0x410A4F; __asm { push edx; push ebx; @@ -340,19 +339,6 @@ static DWORD set_expl_radius_grenade = 2; static DWORD set_expl_radius_rocket = 3; static const size_t numArtChecks = sizeof(explosion_art_adr) / sizeof(explosion_art_adr[0]); -static const size_t numDmgChecks = sizeof(explosion_dmg_check_adr) / sizeof(explosion_dmg_check_adr[0]); - -enum MetaruleExplosionsMode { - EXPL_FORCE_EXPLOSION_PATTERN = 1, - EXPL_FORCE_EXPLOSION_ART = 2, - EXPL_FORCE_EXPLOSION_RADIUS = 3, - EXPL_FORCE_EXPLOSION_DMGTYPE = 4, - EXPL_STATIC_EXPLOSION_RADIUS = 5, - EXPL_GET_EXPLOSION_DAMAGE = 6, - EXPL_SET_DYNAMITE_EXPLOSION_DAMAGE = 7, - EXPL_SET_PLASTIC_EXPLOSION_DAMAGE = 8, - EXPL_SET_EXPLOSION_MAX_TARGET = 9, -}; static void SetExplosionRadius(int arg1, int arg2) { SafeWrite32(explosion_radius_grenade, arg1); @@ -395,6 +381,18 @@ static int GetExplosionDamage(int pid) { return arrayId; } +enum MetaruleExplosionsMode { + EXPL_FORCE_EXPLOSION_PATTERN = 1, + EXPL_FORCE_EXPLOSION_ART = 2, + EXPL_FORCE_EXPLOSION_RADIUS = 3, + EXPL_FORCE_EXPLOSION_DMGTYPE = 4, + EXPL_STATIC_EXPLOSION_RADIUS = 5, + EXPL_GET_EXPLOSION_DAMAGE = 6, + EXPL_SET_DYNAMITE_EXPLOSION_DAMAGE = 7, + EXPL_SET_PLASTIC_EXPLOSION_DAMAGE = 8, + EXPL_SET_EXPLOSION_MAX_TARGET = 9, +}; + int _stdcall ExplosionsMetaruleFunc(int mode, int arg1, int arg2) { switch (mode) { case EXPL_FORCE_EXPLOSION_PATTERN: @@ -407,17 +405,13 @@ int _stdcall ExplosionsMetaruleFunc(int mode, int arg1, int arg2) { } break; case EXPL_FORCE_EXPLOSION_ART: - for (int i = 0; i < numArtChecks; i++) { - SafeWrite32(explosion_art_adr[i], (BYTE)arg1); - } + SafeWriteBatch((BYTE)arg1, explosion_art_adr); break; case EXPL_FORCE_EXPLOSION_RADIUS: SetExplosionRadius(arg1, arg1); break; case EXPL_FORCE_EXPLOSION_DMGTYPE: - for (int i = 0; i < numDmgChecks; i++) { - SafeWrite8(explosion_dmg_check_adr[i], (BYTE)arg1); - } + SafeWriteBatch((BYTE)arg1, explosion_dmg_check_adr); break; case EXPL_STATIC_EXPLOSION_RADIUS: if (arg1 > 0) set_expl_radius_grenade = arg1; @@ -459,9 +453,7 @@ void ResetExplosionSettings() { // explosion radiuses SetExplosionRadius(set_expl_radius_grenade, set_expl_radius_rocket); // explosion dmgtype - for (int i = 0; i < numDmgChecks; i++) { - SafeWrite8(explosion_dmg_check_adr[i], fo::DamageType::DMG_explosion); - } + SafeWriteBatch(fo::DamageType::DMG_explosion, explosion_dmg_check_adr); // explosion max target count if (explosionMaxTargetReset) { SafeWrite8(0x423C93, 6); diff --git a/sfall/Modules/Perks.cpp b/sfall/Modules/Perks.cpp index 563d4370..b4896eee 100644 --- a/sfall/Modules/Perks.cpp +++ b/sfall/Modules/Perks.cpp @@ -829,21 +829,31 @@ static void PerkEngineInit() { // GetPlayerAvailablePerks (ListDPerks_) HookCall(0x43D127, GetAvailablePerksHook); - HookCall(0x43D17D, GetPerkSNameHook); - HookCalls(GetPerkSLevelHook, {0x43D25E, 0x43D275}); // ShowPerkBox (perks_dialog_) - HookCalls(GetPerkSLevelHook, {0x43C82E, 0x43C85B}); - HookCalls(GetPerkSDescHook, {0x43C888, 0x43C8D1}); - HookCalls(GetPerkSNameHook, {0x43C8A6, 0x43C8EF}); - HookCall(0x43C90F, GetPerkSImageHook); HookCall(0x43C952, AddPerkHook); // PerkboxSwitchPerk (RedrwDPrks_) - HookCalls(GetPerkSLevelHook, {0x43C3F1, 0x43C41E}); - HookCalls(GetPerkSDescHook, {0x43C44B, 0x43C494}); - HookCalls(GetPerkSNameHook, {0x43C469, 0x43C4B2}); - HookCall(0x43C4D2, GetPerkSImageHook); + + // GetPerkS hooks + HookCalls(GetPerkSLevelHook, { + 0x43D25E, 0x43D275, // ListDPerks_ + 0x43C82E, 0x43C85B, // perks_dialog_ + 0x43C3F1, 0x43C41E // RedrwDPrks_ + }); + HookCalls(GetPerkSNameHook, { + 0x43D17D, // ListDPerks_ + 0x43C8A6, 0x43C8EF, // perks_dialog_ + 0x43C469, 0x43C4B2 // RedrwDPrks_ + }); + HookCalls(GetPerkSDescHook, { + 0x43C888, 0x43C8D1, // perks_dialog_ + 0x43C44B, 0x43C494 // RedrwDPrks_ + }); + HookCalls(GetPerkSImageHook, { + 0x43C90F, // perks_dialog_ + 0x43C4D2 // RedrwDPrks_ + }); // perk_owed hooks MakeCall(0x4AFB2F, LevelUpHack, 1); // replaces 'mov edx, ds:[PlayerLevel]' diff --git a/sfall/Modules/SpeedPatch.cpp b/sfall/Modules/SpeedPatch.cpp index fd429f23..c306d837 100644 --- a/sfall/Modules/SpeedPatch.cpp +++ b/sfall/Modules/SpeedPatch.cpp @@ -170,7 +170,9 @@ void SpeedPatch::init() { int size = sizeof(offsets) / 4; if (GetConfigInt("Speed", "AffectPlayback", 0) == 0) size -= 4; - SafeWriteBatch((DWORD)&sf_GetTickCount, offsets); + for (int i = 0; i < size; i++) { + SafeWrite32(offsets[i], (DWORD)&sf_GetTickCount); + } SafeWrite32(0x4FDF58, (DWORD)&sf_GetLocalTime); HookCall(0x4A433E, scripts_check_state_hook);