diff --git a/artifacts/scripting/headers/sfall.h b/artifacts/scripting/headers/sfall.h index 818095e6..65b8839c 100644 --- a/artifacts/scripting/headers/sfall.h +++ b/artifacts/scripting/headers/sfall.h @@ -234,8 +234,8 @@ #define party_member_list_all party_member_list(1) // fake perks/traits add mode flags -#define ADD_PERK_MODE_TRAIT (1) // add to the player's traits -#define ADD_PERK_MODE_PERK (2) // add to the player's perks +#define ADD_PERK_MODE_TRAIT (1) // add to the player's traits list +#define ADD_PERK_MODE_PERK (2) // add to the player's perks list #define ADD_PERK_MODE_REMOVE (4) // remove from the list of selectable perks (after added to the player) // instantly apply the item to dude_obj (w/o animation) @@ -249,7 +249,15 @@ if (get_flags(obj1) bwand FLAG_MULTIHEX) distance--; \ if (get_flags(obj2) bwand FLAG_MULTIHEX) distance-- -// sfall_funcX macros + +/* sfall metalure3 function macros */ +#define SET_HORRIGAN_ENCOUNTER (200) + +// sets the number of days (range 1...127) for the Frank Horrigan encounter, or disable the encounter if days is set to 0 +#define set_horrigan_days(day) metarule3(SET_HORRIGAN_ENCOUNTER, day, 0, 0) + + +/* sfall_funcX macros */ #define add_global_timer_event(time, fixedParam) sfall_func2("add_g_timer_event", time, fixedParam) #define add_iface_tag sfall_func0("add_iface_tag") #define add_trait(traitID) sfall_func1("add_trait", traitID) diff --git a/artifacts/translations/german.ini b/artifacts/translations/german.ini index cc32d9ab..3a940056 100644 --- a/artifacts/translations/german.ini +++ b/artifacts/translations/german.ini @@ -1,6 +1,6 @@ [sfall] SaveInCombat=Momentan kein Speichern möglich. -KarmaGain=Du gewinnst %d Karma. +KarmaGain=Du erhältst %d Karma. KarmaLoss=Du verlierst %d Karma. HighlightFail1=Du trägst keinen Bewegungssensor. HighlightFail2=Dein Bewegungssensor ist entladen. diff --git a/sfall/FalloutEngine.cpp b/sfall/FalloutEngine.cpp index 97dbbb85..10bd2191 100644 --- a/sfall/FalloutEngine.cpp +++ b/sfall/FalloutEngine.cpp @@ -52,6 +52,7 @@ DWORD* ptr_crnt_func = reinterpret_cast(_crnt_func); DWORD* ptr_curr_font_num = reinterpret_cast(_curr_font_num); DWORD* ptr_curr_pc_stat = reinterpret_cast(_curr_pc_stat); DWORD* ptr_curr_stack = reinterpret_cast(_curr_stack); +TProgram** ptr_currentProgram = reinterpret_cast(_currentProgram); DWORD* ptr_cursor_line = reinterpret_cast(_cursor_line); BYTE* ptr_DARK_GREY_Color = reinterpret_cast(_DARK_GREY_Color); BYTE* ptr_DarkGreenColor = reinterpret_cast(_DarkGreenColor); diff --git a/sfall/FalloutEngine.h b/sfall/FalloutEngine.h index af3bfacd..dabe831d 100644 --- a/sfall/FalloutEngine.h +++ b/sfall/FalloutEngine.h @@ -68,6 +68,7 @@ #define _curr_font_num 0x51E3B0 #define _curr_pc_stat 0x6681AC #define _curr_stack 0x59E96C +#define _currentProgram 0x59E78C #define _currentWindow 0x51DCB8 #define _cursor_line 0x664514 #define _debug_func 0x51DF04 @@ -337,6 +338,7 @@ extern DWORD* ptr_crnt_func; extern DWORD* ptr_curr_font_num; extern DWORD* ptr_curr_pc_stat; extern DWORD* ptr_curr_stack; +extern TProgram** ptr_currentProgram; extern DWORD* ptr_cursor_line; extern BYTE* ptr_DARK_GREY_Color; extern BYTE* ptr_DarkGreenColor; diff --git a/sfall/LoadGameHook.cpp b/sfall/LoadGameHook.cpp index 260df6d4..d0fa7c33 100644 --- a/sfall/LoadGameHook.cpp +++ b/sfall/LoadGameHook.cpp @@ -37,6 +37,7 @@ #include "LoadOrder.h" #include "Logging.h" #include "Message.h" +#include "MetaruleExtender.h" #include "Movies.h" #include "Objects.h" #include "PartyControl.h" @@ -103,6 +104,7 @@ static void __stdcall ResetState(DWORD onLoad) { // OnGameReset & OnBeforeGameSt PartyControl_OnGameLoad(); ResetExplosionRadius(); BarBoxes_OnGameLoad(); + MetaruleExtenderReset(); ScriptExtender_OnGameLoad(); if (isDebug) { char* str = (onLoad) ? "on Load" : "on Exit"; diff --git a/sfall/MetaruleExtender.cpp b/sfall/MetaruleExtender.cpp new file mode 100644 index 00000000..5b4feaa1 --- /dev/null +++ b/sfall/MetaruleExtender.cpp @@ -0,0 +1,96 @@ +/* + * sfall + * Copyright (C) 2008-2020 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 . + */ + +#include "main.h" +#include "FalloutEngine.h" + +#define HorriganEncounterDays (0x4C06EA) +#define HorriganEncounterCheck (0x4C06D8) + +static signed char HorriganEncounterDefaultDays = 35; +static signed char HorriganEncounterSetDays = 35; +static bool HorriganEncounterDisabled = false; + +enum MetaruleFunction : long { + SET_HORRIGAN_ENCOUNTER = 200, // sets the number of days for the Frank Horrigan encounter or disable encounter +}; + +/* + args - contains a pointer to an array (size of 3) of arguments for the metarule3 function [located on the stack] +*/ +static long __fastcall op_metarule3_ext(long metafunc, long* args) { + long result = 0; + + switch (static_cast(metafunc)) { + case SET_HORRIGAN_ENCOUNTER: { + long argValue = args[0]; // arg1 + if (argValue <= 0) { // disable Horrigan encounter + if (*(BYTE*)HorriganEncounterCheck == CODETYPE_JumpNZ) { + SafeWrite8(HorriganEncounterCheck, CODETYPE_JumpShort); // skip the Horrigan encounter check + HorriganEncounterDisabled = true; + } + } else { + if (argValue > 127) argValue = 127; + SafeWrite8(HorriganEncounterDays, static_cast(argValue)); + HorriganEncounterSetDays = static_cast(argValue); + } + break; + } + default: + DebugPrintf("\nOPCODE ERROR: metarule3(%d, ...) - metarule function number does not exist.\n > Script: %s, procedure %s.", + metafunc, (*ptr_currentProgram)->fileName, FindCurrentProc(*ptr_currentProgram)); + break; + } + return result; +} + +static void __declspec(naked) op_metarule3_hack() { + static const DWORD op_metarule3_hack_Ret = 0x45732C; + __asm { + cmp ecx, 111; + jnz extended; + retn; +extended: + lea edx, [esp + 0x4C - 0x4C + 4]; // pointer to args + // swap arg1 <> arg3 + mov eax, [edx]; // get: arg3 + xchg eax, [edx + 2*4]; // get: arg1, set: arg3 > arg1 + mov [edx], eax; // set: arg1 > arg3 + // + call op_metarule3_ext; // ecx - metafunc arg + add esp, 4; + jmp op_metarule3_hack_Ret; + } +} + +void MetaruleExtenderReset() { + if (HorriganEncounterSetDays != HorriganEncounterDefaultDays) { + SafeWrite8(HorriganEncounterDays, HorriganEncounterDefaultDays); + } + if (HorriganEncounterDisabled) { + HorriganEncounterDisabled = false; + SafeWrite8(HorriganEncounterCheck, CODETYPE_JumpNZ); // enable + } +} + +void MetaruleExtenderInit() { + // Keep default value + HorriganEncounterDefaultDays = *(BYTE*)HorriganEncounterDays; + + MakeCall(0x457322, op_metarule3_hack); +} diff --git a/sfall/MetaruleExtender.h b/sfall/MetaruleExtender.h new file mode 100644 index 00000000..b18808d7 --- /dev/null +++ b/sfall/MetaruleExtender.h @@ -0,0 +1,22 @@ +/* + * sfall + * Copyright (C) 2008-2020 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 . + */ + +#pragma once + +void MetaruleExtenderInit(); +void MetaruleExtenderReset(); diff --git a/sfall/ddraw.vcxproj b/sfall/ddraw.vcxproj index 2eb68729..70c2975b 100644 --- a/sfall/ddraw.vcxproj +++ b/sfall/ddraw.vcxproj @@ -297,6 +297,7 @@ + @@ -371,6 +372,7 @@ + diff --git a/sfall/ddraw.vcxproj.filters b/sfall/ddraw.vcxproj.filters index 34bfcec4..a9d2a91d 100644 --- a/sfall/ddraw.vcxproj.filters +++ b/sfall/ddraw.vcxproj.filters @@ -223,6 +223,9 @@ Headers + + Headers + Headers @@ -385,6 +388,9 @@ Source + + Source + Source diff --git a/sfall/main.cpp b/sfall/main.cpp index 5f53ce89..eb0f0ffb 100644 --- a/sfall/main.cpp +++ b/sfall/main.cpp @@ -54,6 +54,7 @@ #include "Logging.h" #include "MainMenu.h" #include "Message.h" +#include "MetaruleExtender.h" #include "MiscPatches.h" #include "Movies.h" #include "Objects.h" @@ -281,6 +282,9 @@ static void DllMain2() { TalkingHeadsInit(); // most of modules should be initialized before running the script handlers + dlogr("Running MetaruleExtenderInit().", DL_INIT); + MetaruleExtenderInit(); + dlogr("Running ScriptExtenderInit().", DL_INIT); ScriptExtenderInit();