diff --git a/sfall/DebugEditor.cpp b/sfall/DebugEditor.cpp index a237836c..099a923d 100644 --- a/sfall/DebugEditor.cpp +++ b/sfall/DebugEditor.cpp @@ -97,21 +97,12 @@ static void RunEditorInternal(SOCKET &s) { std::vector vec = std::vector(); for (int elv = 0; elv < 3; elv++) { for (int tile = 0; tile < 40000; tile++) { - DWORD* obj; - __asm { - mov edx, tile; - mov eax, elv; - call obj_find_first_at_tile_; - mov obj, eax; - } + TGameObj* obj = ObjFindFirstAtTile(elv, tile); while (obj) { - DWORD otype = obj[25]; - otype = (otype & 0xFF000000) >> 24; - if (otype == 1) vec.push_back(obj); - __asm { - call obj_find_next_at_tile_; - mov obj, eax; + if (obj->pid >> 24 == OBJ_TYPE_CRITTER) { + vec.push_back(reinterpret_cast(obj)); } + obj = ObjFindNextAtTile(); } } } diff --git a/sfall/FalloutEngine.cpp b/sfall/FalloutEngine.cpp index 7e2d52ca..5255e942 100644 --- a/sfall/FalloutEngine.cpp +++ b/sfall/FalloutEngine.cpp @@ -1083,10 +1083,22 @@ TGameObj* __stdcall ObjFindFirst() { __asm call obj_find_first_; } +TGameObj* __stdcall ObjFindFirstAtTile(long elevation, long tileNum) { + __asm { + mov edx, tileNum; + mov eax, elevation; + call obj_find_first_at_tile_; + } +} + TGameObj* __stdcall ObjFindNext() { __asm call obj_find_next_; } +TGameObj* __stdcall ObjFindNextAtTile() { + __asm call obj_find_next_at_tile_; +} + long __stdcall NewObjId() { __asm call new_obj_id_; } diff --git a/sfall/FalloutEngine.h b/sfall/FalloutEngine.h index 6d7e69c8..9f5c2dd8 100644 --- a/sfall/FalloutEngine.h +++ b/sfall/FalloutEngine.h @@ -1073,8 +1073,12 @@ long __stdcall QueueFindFirst(TGameObj* object, long qType); TGameObj* __stdcall ObjFindFirst(); +TGameObj* __stdcall ObjFindFirstAtTile(long elevation, long tileNum); + TGameObj* __stdcall ObjFindNext(); +TGameObj* __stdcall ObjFindNextAtTile(); + long __stdcall NewObjId(); FrmFrameData* __fastcall FramePtr(FrmHeaderData* frm, long frame, long direction); diff --git a/sfall/Karma.cpp b/sfall/Karma.cpp new file mode 100644 index 00000000..14f151d3 --- /dev/null +++ b/sfall/Karma.cpp @@ -0,0 +1,121 @@ +/* + * sfall + * Copyright (C) 2008-2017 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 +#include +#include +#include + +#include "main.h" +#include "FalloutEngine.h" + +struct KarmaFrmSetting { + DWORD frm; + int points; +}; + +static std::vector karmaFrms; + +static char KarmaGainMsg[128]; +static char KarmaLossMsg[128]; + +static DWORD _stdcall DrawCard() { + int reputation = **(int**)_game_global_vars; + for (std::vector::const_iterator it = karmaFrms.begin(); it != karmaFrms.end(); ++it) { + if (reputation < it->points) { + return it->frm; + } + } + return karmaFrms.end()->frm; +} + +static void __declspec(naked) DrawInfoWin_hook() { + __asm { + cmp ds:[_info_line], 10; + jne skip; + cmp eax, 0x30; + jne skip; + push ecx; + push edx; + call DrawCard; + pop edx; + pop ecx; +skip: + jmp DrawCard_; + } +} + +static void _stdcall SetKarma(int value) { + int old; + __asm { + xor eax, eax; + call game_get_global_var_; + mov old, eax; + } + old = value - old; + char buf[128]; + if (old == 0) return; + if (old > 0) { + sprintf_s(buf, KarmaGainMsg, old); + } else { + sprintf_s(buf, KarmaLossMsg, -old); + } + DisplayConsoleMessage(buf); +} + +static void __declspec(naked) SetGlobalVarWrapper() { + __asm { + test eax, eax; // GVar number + jnz end; + pushadc; + push edx; + call SetKarma; + popadc; +end: + jmp game_set_global_var_; + } +} + +void KarmaInit() { + if (GetConfigInt("Misc", "DisplayKarmaChanges", 0)) { + dlog("Applying display karma changes patch.", DL_INIT); + Translate("sfall", "KarmaGain", "You gained %d karma.", KarmaGainMsg); + Translate("sfall", "KarmaLoss", "You lost %d karma.", KarmaLossMsg); + HookCall(0x455A6D, SetGlobalVarWrapper); + dlogr(" Done", DL_INIT); + } + + std::vector karmaFrmList = GetConfigList("Misc", "KarmaFRMs", "", 512); + size_t countFrm = karmaFrmList.size(); + if (countFrm) { + dlog("Applying karma FRM patch.", DL_INIT); + std::vector karmaPointsList = GetConfigList("Misc", "KarmaPoints", "", 512); + + karmaFrms.resize(countFrm); + size_t countPoints = karmaPointsList.size(); + for (size_t i = 0; i < countFrm; i++) { + karmaFrms[i].frm = atoi(karmaFrmList[i].c_str()); + karmaFrms[i].points = (countPoints > i) + ? atoi(karmaPointsList[i].c_str()) + : INT_MAX; + } + HookCall(0x4367A9, DrawInfoWin_hook); + + dlogr(" Done", DL_INIT); + } +} diff --git a/sfall/Karma.h b/sfall/Karma.h new file mode 100644 index 00000000..b8ce0bd0 --- /dev/null +++ b/sfall/Karma.h @@ -0,0 +1,21 @@ +/* + * sfall + * Copyright (C) 2008-2017 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 KarmaInit(); diff --git a/sfall/LoadGameHook.cpp b/sfall/LoadGameHook.cpp index 1d9622b0..0a4c1f5f 100644 --- a/sfall/LoadGameHook.cpp +++ b/sfall/LoadGameHook.cpp @@ -33,15 +33,16 @@ #include "input.h" #include "Inventory.h" #include "LoadGameHook.h" +#include "LoadOrder.h" #include "Logging.h" #include "Message.h" -#include "movies.h" +#include "Movies.h" #include "Objects.h" #include "PartyControl.h" -#include "perks.h" +#include "Perks.h" #include "ScriptExtender.h" -#include "skills.h" -#include "sound.h" +#include "Skills.h" +#include "Sound.h" #include "SuperSave.h" #include "TalkingHeads.h" #include "version.h" diff --git a/sfall/LoadOrder.cpp b/sfall/LoadOrder.cpp new file mode 100644 index 00000000..7d105597 --- /dev/null +++ b/sfall/LoadOrder.cpp @@ -0,0 +1,253 @@ +/* + * sfall + * Copyright (C) 2008-2017 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" + +static std::vector savPrototypes; + +static void __declspec(naked) RemoveDatabase() { + __asm { + cmp eax, -1; + je end; + mov ebx, ds:[_paths]; + mov ecx, ebx; +nextPath: + mov edx, [esp + 0x104 + 4 + 4]; // path_patches + mov eax, [ebx]; // database.path + call stricmp_; + test eax, eax; // found path? + jz skip; // Yes + mov ecx, ebx; + mov ebx, [ebx + 0xC]; // database.next + jmp nextPath; +skip: + mov eax, [ebx + 0xC]; // database.next + mov [ecx + 0xC], eax; // database.next + xchg ebx, eax; + cmp eax, ecx; + jne end; + mov ds:[_paths], ebx; +end: + retn; + } +} + +// Remove master_patches from the chain +static void __declspec(naked) game_init_databases_hack1() { + __asm { + call RemoveDatabase; + mov ds:[_master_db_handle], eax; // the pointer of master_patches node will be saved here + retn; + } +} + +// Remove critter_patches from the chain +static void __declspec(naked) game_init_databases_hack2() { + __asm { + cmp eax, -1; + je end; + mov eax, ds:[_master_db_handle]; // pointer to master_patches node + mov eax, [eax]; // eax = master_patches.path + call xremovepath_; + dec eax; // remove path (critter_patches == master_patches)? + jz end; // Yes (jump if 0) + inc eax; + call RemoveDatabase; +end: + mov ds:[_critter_db_handle], eax; // the pointer of critter_patches node will be saved here + retn; + } +} + +static void __declspec(naked) game_init_databases_hook() { + // eax = _master_db_handle + __asm { + mov ecx, ds:[_critter_db_handle]; + mov edx, ds:[_paths]; + test ecx, ecx; + jz skip; + mov [ecx + 0xC], edx; // critter_patches.next->_paths + mov edx, ecx; +skip: + mov [eax + 0xC], edx; // master_patches.next + mov ds:[_paths], eax; + retn; + } +} + +////////////////////////////// SAVE PARTY MEMBER PROTOTYPES ////////////////////////////// + +static void __fastcall AddSavPrototype(long pid) { + for (std::vector::const_iterator it = savPrototypes.begin(); it != savPrototypes.end(); ++it) { + if (*it == pid) return; + } + savPrototypes.push_back(pid); +} + +static long ChangePrototypeExt(char* path) { + long len = strlen(path); + if (len) { + len -= 4; + if (path[len] == '.') { + path[++len] = 's'; + path[++len] = 'a'; + path[++len] = 'v'; + } else { + len = 0; + } + } + return len; +} + +static void __fastcall ExistSavPrototype(long pid, char* path) { + if (savPrototypes.empty()) return; + for (std::vector::const_iterator it = savPrototypes.begin(); it != savPrototypes.end(); ++it) { + if (*it == pid) { + ChangePrototypeExt(path); + break; + } + } +} + +static long __fastcall CheckProtoType(long pid, char* path) { + if (pid >> 24 != OBJ_TYPE_CRITTER) return 0; + return ChangePrototypeExt(path); +} + +// saves prototypes (all party members) before saving game or exiting the map +static void __declspec(naked) proto_save_pid_hook() { + __asm { + push ecx; + call proto_list_str_; + test eax, eax; + jnz end; + mov ecx, ebx; // party pid + mov edx, edi; // path buffer + call CheckProtoType; + test eax, eax; + jz end; + mov ecx, ebx; // party pid + call AddSavPrototype; +end: + pop ecx; + retn; + } +} + +#define _F_PATHFILE 0x6143F4 +static void __declspec(naked) GameMap2Slot_hack() { // save party pids + __asm { + push ecx; + mov edx, _F_PATHFILE; // path buffer + call CheckProtoType; // ecx - party pid + pop ecx; + lea eax, [esp + 0x14 + 4]; + retn 0x14; + } +} + +static void __declspec(naked) SlotMap2Game_hack() { // load party pids + __asm { + push edx; + mov ecx, edi; // party pid + mov edx, _F_PATHFILE; // path buffer + call CheckProtoType; + test eax, eax; + jz end; + mov ecx, edi; + call AddSavPrototype; +end: + pop edx; + lea eax, [esp + 0x14 + 4]; + retn 0x14; + } +} + +static void __declspec(naked) proto_load_pid_hook() { + __asm { // eax - party pid + push ecx; + mov ecx, eax; + call proto_list_str_; + test eax, eax; + jnz end; + // check pid type + mov edx, ecx; + shr edx, 24; + cmp edx, OBJ_TYPE_CRITTER; + jnz end; + mov edx, edi; // path buffer + call ExistSavPrototype; // ecx - party pid + xor eax, eax; +end: + pop ecx; + retn; + } +} + +static void ResetReadOnlyAttr() { + DWORD attr = GetFileAttributesA((const char*)_F_PATHFILE); + if (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_READONLY)) { + SetFileAttributesA((const char*)_F_PATHFILE, (attr & ~FILE_ATTRIBUTE_READONLY)); + } +} + +static void __declspec(naked) SlotMap2Game_hack_attr() { + __asm { + cmp eax, -1; + je end; + cmp ebx, OBJ_TYPE_CRITTER; + jne end; + call ResetReadOnlyAttr; + or eax, 1; // reset ZF +end: + retn 0x8; + } +} + +#define _F_SAV (const char*)0x50A480 +#define _F_PROTO_CRITTERS (const char*)0x50A490 + +void RemoveSavFiles() { + MapDirErase(_F_PROTO_CRITTERS, _F_SAV); +} + +void ClearSavPrototypes() { + savPrototypes.clear(); + RemoveSavFiles(); +} + +void LoadOrderInit() { + if (GetConfigInt("Misc", "DataLoadOrderPatch", 1)) { + dlog("Applying data load order patch.", DL_INIT); + MakeCall(0x444259, game_init_databases_hack1); + MakeCall(0x4442F1, game_init_databases_hack2); + HookCall(0x44436D, game_init_databases_hook); + SafeWrite8(0x4DFAEC, 0x1D); // error correction (ecx > ebx) + dlogr(" Done", DL_INIT); + } + + dlog("Applying party member protos save/load patch.", DL_INIT); + savPrototypes.reserve(25); + HookCall(0x4A1CF2, proto_load_pid_hook); + HookCall(0x4A1BEE, proto_save_pid_hook); + MakeCall(0x47F5A5, GameMap2Slot_hack); // save game + MakeCall(0x47FB80, SlotMap2Game_hack); // load game + MakeCall(0x47FBBF, SlotMap2Game_hack_attr, 1); + dlogr(" Done", DL_INIT); +} diff --git a/sfall/LoadOrder.h b/sfall/LoadOrder.h new file mode 100644 index 00000000..4bef86a0 --- /dev/null +++ b/sfall/LoadOrder.h @@ -0,0 +1,23 @@ +/* + * sfall + * Copyright (C) 2008-2017 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 LoadOrderInit(); +void RemoveSavFiles(); +void ClearSavPrototypes(); diff --git a/sfall/movies.cpp b/sfall/Movies.cpp similarity index 99% rename from sfall/movies.cpp rename to sfall/Movies.cpp index 1b1dfbfb..1dcc928f 100644 --- a/sfall/movies.cpp +++ b/sfall/Movies.cpp @@ -27,7 +27,7 @@ #include "Graphics.h" #include "Logging.h" -#include "movies.h" +#include "Movies.h" static DWORD MoviePtrs[MaxMovies]; char MoviePaths[MaxMovies * 65]; diff --git a/sfall/movies.h b/sfall/Movies.h similarity index 100% rename from sfall/movies.h rename to sfall/Movies.h diff --git a/sfall/ScriptExtender.cpp b/sfall/ScriptExtender.cpp index 55ca2680..d1aa2362 100644 --- a/sfall/ScriptExtender.cpp +++ b/sfall/ScriptExtender.cpp @@ -1205,7 +1205,7 @@ static void _stdcall ClearEventsOnMapExit() { } } -void ScriptExtenderSetup() { +void ScriptExtenderInit() { toggleHighlightsKey = GetConfigInt("Input", "ToggleItemHighlightsKey", 0); if (toggleHighlightsKey) { MotionSensorMode = GetConfigInt("Misc", "MotionScannerFlags", 1); diff --git a/sfall/ScriptExtender.h b/sfall/ScriptExtender.h index 91a30d03..f4751fc4 100644 --- a/sfall/ScriptExtender.h +++ b/sfall/ScriptExtender.h @@ -43,7 +43,7 @@ typedef struct { char initialized; } sScriptProgram; -void ScriptExtenderSetup(); +void ScriptExtenderInit(); bool _stdcall IsGameScript(const char* filename); void LoadGlobalScripts(); void ClearGlobalScripts(); diff --git a/sfall/ScriptOps/MiscOps.hpp b/sfall/ScriptOps/MiscOps.hpp index 85334d22..78eecd38 100644 --- a/sfall/ScriptOps/MiscOps.hpp +++ b/sfall/ScriptOps/MiscOps.hpp @@ -24,7 +24,7 @@ #include "Combat.h" #include "HeroAppearance.h" #include "KillCounter.h" -#include "movies.h" +#include "Movies.h" #include "PartyControl.h" #include "ScriptExtender.h" diff --git a/sfall/ScriptOps/ObjectsOps.hpp b/sfall/ScriptOps/ObjectsOps.hpp index abe67c13..0488cc8e 100644 --- a/sfall/ScriptOps/ObjectsOps.hpp +++ b/sfall/ScriptOps/ObjectsOps.hpp @@ -447,21 +447,12 @@ static void __declspec(naked) op_obj_blocking_at() { static void _stdcall op_tile_get_objects2() { DWORD tile = opHandler.arg(0).asInt(), - elevation = opHandler.arg(1).asInt(), - obj; + elevation = opHandler.arg(1).asInt(); DWORD arrayId = TempArray(0, 4); - __asm { - mov eax, elevation; - mov edx, tile; - call obj_find_first_at_tile_; - mov obj, eax; - } + TGameObj* obj = ObjFindFirstAtTile(elevation, tile); while (obj) { - arrays[arrayId].push_back((long)obj); - __asm { - call obj_find_next_at_tile_; - mov obj, eax; - } + arrays[arrayId].push_back(reinterpret_cast(obj)); + obj = ObjFindNextAtTile(); } opHandler.setReturn(arrayId, DATATYPE_INT); } diff --git a/sfall/ScriptOps/ScriptArrays.hpp b/sfall/ScriptOps/ScriptArrays.hpp index eadab031..e4f84eca 100644 --- a/sfall/ScriptOps/ScriptArrays.hpp +++ b/sfall/ScriptOps/ScriptArrays.hpp @@ -482,6 +482,18 @@ struct sList { } }; +static DWORD listID = 0xCCCCCC; + +struct ListId { + sList* list; + DWORD id; + + ListId(sList* lst) : list(lst) { + id = ++listID; + } +}; +static std::vector mList; + static void FillListVector(DWORD type, std::vector& vec) { vec.reserve(100); if (type == 6) { @@ -522,36 +534,28 @@ static void FillListVector(DWORD type, std::vector& vec) { } else if (type != 4) { for (int elv = 0; elv < 3; elv++) { for (int tile = 0; tile < 40000; tile++) { - TGameObj* obj; - __asm { - mov edx, tile; - mov eax, elv; - call obj_find_first_at_tile_; - mov obj, eax; - } + TGameObj* obj = ObjFindFirstAtTile(elv, tile); while (obj) { DWORD otype = obj->pid >> 24; if (type == 9 || (type == 0 && otype == 1) || (type == 1 && otype == 0) || (type >= 2 && type <= 5 && type == otype)) { vec.push_back(obj); } - __asm { - call obj_find_next_at_tile_; - mov obj, eax; - } + obj = ObjFindNextAtTile(); } } } } } -static void* _stdcall list_begin2(DWORD type) { +static DWORD _stdcall ListBegin(DWORD type) { std::vector vec = std::vector(); FillListVector(type, vec); sList* list = new sList(&vec); - return list; + mList.push_back(list); + return listID; } -static DWORD _stdcall list_as_array2(DWORD type) { +static DWORD _stdcall ListAsArray(DWORD type) { std::vector vec = std::vector(); FillListVector(type, vec); size_t sz = vec.size(); @@ -562,14 +566,20 @@ static DWORD _stdcall list_as_array2(DWORD type) { return id; } -static TGameObj* _stdcall list_next2(sList* list) { +static TGameObj* _stdcall ListNext(sList* list) { if (!list || list->pos == list->len) return 0; else return list->obj[list->pos++]; } -static void _stdcall list_end2(sList* list) { - delete[] list->obj; - delete list; +static void _stdcall ListEnd(DWORD id) { + for (std::vector::const_iterator it = mList.cbegin(), it_end = mList.cend(); it != it_end; ++it) { + if (it->id == id) { + delete[] it->list->obj; + delete it->list; + mList.erase(it); + break; + } + } } static void __declspec(naked) list_begin() { @@ -583,7 +593,7 @@ static void __declspec(naked) list_begin() { cmp di, VAR_TYPE_INT; jnz fail; push eax; - call list_begin2; + call ListBegin; mov edx, eax; jmp end; fail: @@ -599,6 +609,7 @@ end: retn; } } + static void __declspec(naked) list_as_array() { __asm { pushad; @@ -610,7 +621,7 @@ static void __declspec(naked) list_as_array() { cmp di, VAR_TYPE_INT; jnz fail; push eax; - call list_as_array2; + call ListAsArray; mov edx, eax; jmp end; fail: @@ -626,33 +637,29 @@ end: retn; } } + +static void _stdcall list_next2() { + const ScriptValue &idArg = opHandler.arg(0); + if (idArg.isInt()) { + DWORD id = idArg.rawValue(); + sList* list = nullptr; + for (std::vector::const_iterator it = mList.cbegin(), it_end = mList.cend(); it != it_end; ++it) { + if (it->id == id) { + list = it->list; + break; + } + } + opHandler.setReturn(ListNext(list)); + } else { + OpcodeInvalidArgs("list_next"); + opHandler.setReturn(-1); + } +} + static void __declspec(naked) list_next() { - __asm { - pushad; - mov ebp, eax; - call interpretPopShort_; - mov edi, eax; - mov eax, ebp; - call interpretPopLong_; - cmp di, VAR_TYPE_INT; - jnz fail; - push eax; - call list_next2; - mov edx, eax; - jmp end; -fail: - xor edx, edx; - dec edx; -end: - mov eax, ebp; - call interpretPushLong_; - mov eax, ebp; - mov edx, VAR_TYPE_INT; - call interpretPushShort_; - popad; - retn; - } + _WRAP_OPCODE(list_next2, 1, 1) } + static void __declspec(naked) list_end() { __asm { pushad; @@ -664,7 +671,7 @@ static void __declspec(naked) list_end() { cmp di, VAR_TYPE_INT; jnz end; push eax; - call list_end2; + call ListEnd; end: popad; retn; diff --git a/sfall/ScriptOps/StatsOp.hpp b/sfall/ScriptOps/StatsOp.hpp index 21afc2a3..6881fdfd 100644 --- a/sfall/ScriptOps/StatsOp.hpp +++ b/sfall/ScriptOps/StatsOp.hpp @@ -23,7 +23,7 @@ #include "Combat.h" #include "Criticals.h" #include "ScriptExtender.h" -#include "skills.h" +#include "Skills.h" #include "Stats.h" const char* invalidStat = "%s() - stat number out of range."; diff --git a/sfall/skills.cpp b/sfall/Skills.cpp similarity index 100% rename from sfall/skills.cpp rename to sfall/Skills.cpp diff --git a/sfall/skills.h b/sfall/Skills.h similarity index 100% rename from sfall/skills.h rename to sfall/Skills.h diff --git a/sfall/sound.cpp b/sfall/Sound.cpp similarity index 100% rename from sfall/sound.cpp rename to sfall/Sound.cpp diff --git a/sfall/sound.h b/sfall/Sound.h similarity index 100% rename from sfall/sound.h rename to sfall/Sound.h diff --git a/sfall/ddraw.vcxproj b/sfall/ddraw.vcxproj index 3e7103a6..66de461d 100644 --- a/sfall/ddraw.vcxproj +++ b/sfall/ddraw.vcxproj @@ -290,6 +290,8 @@ + + @@ -300,7 +302,7 @@ - + @@ -324,8 +326,8 @@ - - + + @@ -358,6 +360,8 @@ + + @@ -368,7 +372,7 @@ - + @@ -377,8 +381,8 @@ - - + + Create diff --git a/sfall/ddraw.vcxproj.filters b/sfall/ddraw.vcxproj.filters index 06603b0d..1d6639f8 100644 --- a/sfall/ddraw.vcxproj.filters +++ b/sfall/ddraw.vcxproj.filters @@ -57,7 +57,7 @@ Headers - + Headers @@ -78,7 +78,7 @@ Headers - + Headers @@ -109,7 +109,7 @@ Headers - + Headers @@ -205,6 +205,12 @@ Headers + + Headers + + + Headers + Headers @@ -252,7 +258,7 @@ Source - + Source @@ -273,7 +279,7 @@ Source - + Source @@ -298,7 +304,7 @@ Source - + Source @@ -352,6 +358,12 @@ Source + + Source + + + Source + Source diff --git a/sfall/dinput.cpp b/sfall/dinput.cpp index 25f463a3..b71b8b10 100644 --- a/sfall/dinput.cpp +++ b/sfall/dinput.cpp @@ -24,7 +24,7 @@ #include "main.h" #include "FalloutEngine.h" -#include "graphics.h" +#include "Graphics.h" #include "ScriptExtender.h" #include "HookScripts.h" #include "input.h" diff --git a/sfall/main.cpp b/sfall/main.cpp index 5775cd1a..685f5505 100644 --- a/sfall/main.cpp +++ b/sfall/main.cpp @@ -31,7 +31,7 @@ #include "BugFixes.h" #include "BurstMods.h" #include "Combat.h" -#include "console.h" +#include "Console.h" #include "CRC.h" #include "Credits.h" #include "Criticals.h" @@ -43,23 +43,25 @@ #include "Graphics.h" #include "HeroAppearance.h" #include "Inventory.h" +#include "Karma.h" #include "KillCounter.h" #include "LoadGameHook.h" +#include "LoadOrder.h" #include "Logging.h" #include "MainMenu.h" #include "Message.h" -#include "movies.h" +#include "Movies.h" #include "Objects.h" #include "PartyControl.h" -#include "perks.h" +#include "Perks.h" #include "Premade.h" #include "QuestList.h" #include "Reputations.h" #include "ScriptExtender.h" -#include "skills.h" -#include "sound.h" +#include "Skills.h" +#include "Sound.h" #include "SpeedPatch.h" -#include "stats.h" +#include "Stats.h" #include "SuperSave.h" #include "TalkingHeads.h" #include "Tiles.h" @@ -134,15 +136,6 @@ size_t Translate(const char* section, const char* setting, const char* defaultVa return iniGetString(section, setting, defaultValue, buffer, bufSize, translationIni); } -static std::vector savPrototypes; - -struct KarmaFrmSetting { - DWORD frm; - int points; -}; - -static std::vector karmaFrms; - static char mapName[65]; static char configName[65]; static char patchName[65]; @@ -178,219 +171,6 @@ static const DWORD WalkDistanceAddr[] = { 0x411FF0, 0x4121C4, 0x412475, 0x412906, }; -static void __declspec(naked) RemoveDatabase() { - __asm { - cmp eax, -1; - je end; - mov ebx, ds:[_paths]; - mov ecx, ebx; -nextPath: - mov edx, [esp + 0x104 + 4 + 4]; // path_patches - mov eax, [ebx]; // database.path - call stricmp_; - test eax, eax; // found path? - jz skip; // Yes - mov ecx, ebx; - mov ebx, [ebx + 0xC]; // database.next - jmp nextPath; -skip: - mov eax, [ebx + 0xC]; // database.next - mov [ecx + 0xC], eax; // database.next - xchg ebx, eax; - cmp eax, ecx; - jne end; - mov ds:[_paths], ebx; -end: - retn; - } -} - -// Remove master_patches from the chain of paths -static void __declspec(naked) game_init_databases_hack1() { - __asm { - call RemoveDatabase; - mov ds:[_master_db_handle], eax; // the pointer of master_patches node will be saved here - retn; - } -} - -// Remove critter_patches from the chain of paths -static void __declspec(naked) game_init_databases_hack2() { - __asm { - cmp eax, -1; - je end; - mov eax, ds:[_master_db_handle]; // pointer to master_patches node - mov eax, [eax]; // eax = master_patches.path - call xremovepath_; - dec eax; // remove path (critter_patches == master_patches)? - jz end; // Yes (jump if 0) - inc eax; - call RemoveDatabase; -end: - mov ds:[_critter_db_handle], eax; // the pointer of critter_patches node will be saved here - retn; - } -} - -static void __declspec(naked) game_init_databases_hook() { - // eax = _master_db_handle - __asm { - mov ecx, ds:[_critter_db_handle]; - mov edx, ds:[_paths]; - test ecx, ecx; - jz skip; - mov [ecx + 0xC], edx; // critter_patches.next->_paths - mov edx, ecx; -skip: - mov [eax + 0xC], edx; // master_patches.next - mov ds:[_paths], eax; - retn; - } -} - -///////////////////////// SAVE PARTY MEMBER PROTOTYPES ///////////////////////// - -static void __fastcall AddSavPrototype(long pid) { - for (std::vector::const_iterator it = savPrototypes.begin(); it != savPrototypes.end(); ++it) { - if (*it == pid) return; - } - savPrototypes.push_back(pid); -} - -static long ChangePrototypeExt(char* path) { - long len = strlen(path); - if (len) { - len -= 4; - if (path[len] == '.') { - path[++len] = 's'; - path[++len] = 'a'; - path[++len] = 'v'; - } else { - len = 0; - } - } - return len; -} - -static void __fastcall ExistSavPrototype(long pid, char* path) { - if (savPrototypes.empty()) return; - for (std::vector::const_iterator it = savPrototypes.begin(); it != savPrototypes.end(); ++it) { - if (*it == pid) { - ChangePrototypeExt(path); - break; - } - } -} - -static long __fastcall CheckProtoType(long pid, char* path) { - if (pid >> 24 != OBJ_TYPE_CRITTER) return 0; - return ChangePrototypeExt(path); -} - -// saves prototypes (all party members) before saving game or exiting the map -static void __declspec(naked) proto_save_pid_hook() { - __asm { - push ecx; - call proto_list_str_; - test eax, eax; - jnz end; - mov ecx, ebx; // party pid - mov edx, edi; // path buffer - call CheckProtoType; - test eax, eax; - jz end; - mov ecx, ebx; // party pid - call AddSavPrototype; -end: - pop ecx; - retn; - } -} - -#define _F_PATHFILE 0x6143F4 -static void __declspec(naked) GameMap2Slot_hack() { // save party pids - __asm { - push ecx; - mov edx, _F_PATHFILE; // path buffer - call CheckProtoType; // ecx - party pid - pop ecx; - lea eax, [esp + 0x14 + 4]; - retn 0x14; - } -} - -static void __declspec(naked) SlotMap2Game_hack() { // load party pids - __asm { - push edx; - mov ecx, edi; // party pid - mov edx, _F_PATHFILE; // path buffer - call CheckProtoType; - test eax, eax; - jz end; - mov ecx, edi; - call AddSavPrototype; -end: - pop edx; - lea eax, [esp + 0x14 + 4]; - retn 0x14; - } -} - -static void __declspec(naked) proto_load_pid_hook() { - __asm { // eax - party pid - push ecx; - mov ecx, eax; - call proto_list_str_; - test eax, eax; - jnz end; - // check pid type - mov edx, ecx; - shr edx, 24; - cmp edx, OBJ_TYPE_CRITTER; - jnz end; - mov edx, edi; // path buffer - call ExistSavPrototype; // ecx - party pid - xor eax, eax; -end: - pop ecx; - retn; - } -} - -static void ResetReadOnlyAttr() { - DWORD attr = GetFileAttributesA((const char*)_F_PATHFILE); - if (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_READONLY)) { - SetFileAttributesA((const char*)_F_PATHFILE, (attr & ~FILE_ATTRIBUTE_READONLY)); - } -} - -static void __declspec(naked) SlotMap2Game_hack_attr() { - __asm { - cmp eax, -1; - je end; - cmp ebx, OBJ_TYPE_CRITTER; - jne end; - call ResetReadOnlyAttr; - or eax, 1; // reset ZF -end: - retn 0x8; - } -} - -#define _F_SAV (const char*)0x50A480 -#define _F_PROTO_CRITTERS (const char*)0x50A490 - -void RemoveSavFiles() { - MapDirErase(_F_PROTO_CRITTERS, _F_SAV); -} - -void ClearSavPrototypes() { - savPrototypes.clear(); - RemoveSavFiles(); -} - -//////////////////////////////////////////////////////////////////////////////// - static void __declspec(naked) WeaponAnimHook() { __asm { cmp edx, 11; @@ -407,39 +187,6 @@ c15: } } -static char KarmaGainMsg[128]; -static char KarmaLossMsg[128]; -static void _stdcall SetKarma(int value) { - int old; - __asm { - xor eax, eax; - call game_get_global_var_; - mov old, eax; - } - old = value - old; - char buf[128]; - if (old == 0) return; - if (old > 0) { - sprintf_s(buf, KarmaGainMsg, old); - } else { - sprintf_s(buf, KarmaLossMsg, -old); - } - DisplayConsoleMessage(buf); -} - -static void __declspec(naked) SetGlobalVarWrapper() { - __asm { - test eax, eax; // GVar number - jnz end; - pushadc; - push edx; - call SetKarma; - popadc; -end: - jmp game_set_global_var_; - } -} - static void __declspec(naked) ReloadHook() { __asm { push eax; @@ -529,32 +276,6 @@ end: } } -static DWORD _stdcall DrawCard() { - int reputation = **(int**)_game_global_vars; - for (std::vector::const_iterator it = karmaFrms.begin(); it != karmaFrms.end(); ++it) { - if (reputation < it->points) { - return it->frm; - } - } - return karmaFrms.end()->frm; -} - -static void __declspec(naked) DrawInfoWin_hook() { - __asm { - cmp ds:[_info_line], 10; - jne skip; - cmp eax, 0x30; - jne skip; - push ecx; - push edx; - call DrawCard; - pop edx; - pop ecx; -skip: - jmp DrawCard_; - } -} - static void __declspec(naked) ScienceCritterCheckHook() { __asm { cmp esi, ds:[_obj_dude]; @@ -661,15 +382,9 @@ static void DllMain2() { dlogr("Running BugFixesInit().", DL_INIT); BugFixesInit(); - dlogr("Running SpeedPatchInit().", DL_INIT); - SpeedPatchInit(); - dlogr("Running GraphicsInit().", DL_INIT); GraphicsInit(); - dlogr("Running TalkingHeadsInit().", DL_INIT); - TalkingHeadsInit(); - //if (GetConfigInt("Input", "Enable", 0)) { dlog("Applying input patch.", DL_INIT); SafeWriteStr(0x50FB70, "ddraw.dll"); @@ -677,26 +392,11 @@ static void DllMain2() { dlogr(" Done", DL_INIT); //} - if (GetConfigInt("Misc", "DataLoadOrderPatch", 1)) { - dlog("Applying data load order patch.", DL_INIT); - MakeCall(0x444259, game_init_databases_hack1); - MakeCall(0x4442F1, game_init_databases_hack2); - HookCall(0x44436D, game_init_databases_hook); - SafeWrite8(0x4DFAEC, 0x1D); // error correction (ecx > ebx) - dlogr(" Done", DL_INIT); - } + dlogr("Running LoadOrderInit().", DL_INIT); + LoadOrderInit(); - dlog("Applying party member protos save/load patch.", DL_INIT); - savPrototypes.reserve(25); - HookCall(0x4A1CF2, proto_load_pid_hook); - HookCall(0x4A1BEE, proto_save_pid_hook); - MakeCall(0x47F5A5, GameMap2Slot_hack); // save game - MakeCall(0x47FB80, SlotMap2Game_hack); // load game - MakeCall(0x47FBBF, SlotMap2Game_hack_attr, 1); - dlogr(" Done", DL_INIT); - - dlogr("Running DamageModInit().", DL_INIT); - DamageModInit(); + dlogr("Running LoadGameHookInit().", DL_INIT); + LoadGameHookInit(); dlogr("Running MoviesInit().", DL_INIT); MoviesInit(); @@ -708,34 +408,8 @@ static void DllMain2() { dlogr("Running ObjectsInit().", DL_INIT); ObjectsInit(); - mapName[64] = 0; - if (GetConfigString("Misc", "StartingMap", "", mapName, 64)) { - dlog("Applying starting map patch.", DL_INIT); - SafeWrite32(0x480AAA, (DWORD)&mapName); - dlogr(" Done", DL_INIT); - } - - versionString[64] = 0; - if (GetConfigString("Misc", "VersionString", "", versionString, 64)) { - dlog("Applying version string patch.", DL_INIT); - SafeWrite32(0x4B4588, (DWORD)&versionString); - dlogr(" Done", DL_INIT); - } - - configName[64] = 0; - if (GetConfigString("Misc", "ConfigFile", "", configName, 64)) { - dlog("Applying config file patch.", DL_INIT); - SafeWrite32(0x444BA5, (DWORD)&configName); - SafeWrite32(0x444BCA, (DWORD)&configName); - dlogr(" Done", DL_INIT); - } - - patchName[64] = 0; - if (GetConfigString("Misc", "PatchFile", "", patchName, 64)) { - dlog("Applying patch file patch.", DL_INIT); - SafeWrite32(0x444323, (DWORD)&patchName); - dlogr(" Done", DL_INIT); - } + dlogr("Running SpeedPatchInit().", DL_INIT); + SpeedPatchInit(); startMaleModelName[64] = 0; if (GetConfigString("Misc", "MaleStartModel", "", startMaleModelName, 64)) { @@ -766,41 +440,125 @@ static void DllMain2() { dlogr("Running WorldmapInit().", DL_INIT); WorldmapInit(); - if (GetConfigInt("Misc", "DialogueFix", 1)) { - dlog("Applying dialogue patch.", DL_INIT); - SafeWrite8(0x446848, 0x31); - dlogr(" Done", DL_INIT); - } + dlogr("Running StatsInit().", DL_INIT); + StatsInit(); + + dlogr("Running PerksInit().", DL_INIT); + PerksInit(); + + dlogr("Running CombatInit().", DL_INIT); + CombatInit(); + + dlogr("Running SkillsInit().", DL_INIT); + SkillsInit(); + + dlogr("Running FileSystemInit().", DL_INIT); + FileSystemInit(); dlogr("Running CriticalsInit().", DL_INIT); CriticalsInit(); + dlogr("Running KarmaInit().", DL_INIT); + KarmaInit(); + + dlogr("Running TilesInit().", DL_INIT); + TilesInit(); + + dlogr("Running CreditsInit().", DL_INIT); + CreditsInit(); + + dlogr("Running QuestListInit().", DL_INIT); + QuestListInit(); + + dlogr("Running PremadeInit().", DL_INIT); + PremadeInit(); + + dlogr("Running SoundInit().", DL_INIT); + SoundInit(); + + dlogr("Running ReputationsInit().", DL_INIT); + ReputationsInit(); + + dlogr("Running ConsoleInit().", DL_INIT); + ConsoleInit(); + + if (GetConfigInt("Misc", "ExtraSaveSlots", 0)) { + dlogr("Running EnableSuperSaving().", DL_INIT); + EnableSuperSaving(); + } + + dlogr("Running InventoryInit().", DL_INIT); + InventoryInit(); + + dlogr("Initializing party control...", DL_INIT); + PartyControlInit(); + + dlogr("Running ComputeSprayModInit().", DL_INIT); + ComputeSprayModInit(); + + dlogr("Running BooksInit().", DL_INIT); + BooksInit(); + + dlogr("Running ExplosionInit().", DL_INIT); + ExplosionInit(); + + std::string elevPath = GetConfigString("Misc", "ElevatorsFile", "", MAX_PATH); + if (!elevPath.empty()) { + dlog("Applying elevator patch.", DL_INIT); + ElevatorsInit(); + LoadElevators(elevPath.insert(0, ".\\").c_str()); + dlogr(" Done", DL_INIT); + } + if (GetConfigInt("Misc", "ExtraKillTypes", 0)) { dlog("Applying extra kill types patch.", DL_INIT); KillCounterInit(); dlogr(" Done", DL_INIT); } - //if (GetConfigInt("Misc", "ScriptExtender", 0)) { - dlogr("Running StatsInit().", DL_INIT); - StatsInit(); - dlogr("Running ScriptExtenderSetup().", DL_INIT); - ScriptExtenderSetup(); - dlogr("Running LoadGameHookInit().", DL_INIT); - LoadGameHookInit(); - dlogr("Running PerksInit().", DL_INIT); - PerksInit(); - dlogr("Running CombatInit().", DL_INIT); - CombatInit(); - dlogr("Running SkillsInit().", DL_INIT); - SkillsInit(); - //} + dlogr("Running AIInit().", DL_INIT); + AIInit(); - dlogr("Running FileSystemInit().", DL_INIT); - FileSystemInit(); + dlogr("Running DamageModInit().", DL_INIT); + DamageModInit(); - dlogr("Running DebugEditorInit().", DL_INIT); - DebugEditorInit(); + dlogr("Running AnimationsAtOnceInit().", DL_INIT); + AnimationsAtOnceInit(); + + dlogr("Running BarBoxesInit().", DL_INIT); + BarBoxesInit(); + + dlogr("Running HeroAppearanceModInit().", DL_INIT); + HeroAppearanceModInit(); + + mapName[64] = 0; + if (GetConfigString("Misc", "StartingMap", "", mapName, 64)) { + dlog("Applying starting map patch.", DL_INIT); + SafeWrite32(0x480AAA, (DWORD)&mapName); + dlogr(" Done", DL_INIT); + } + + versionString[64] = 0; + if (GetConfigString("Misc", "VersionString", "", versionString, 64)) { + dlog("Applying version string patch.", DL_INIT); + SafeWrite32(0x4B4588, (DWORD)&versionString); + dlogr(" Done", DL_INIT); + } + + configName[64] = 0; + if (GetConfigString("Misc", "ConfigFile", "", configName, 64)) { + dlog("Applying config file patch.", DL_INIT); + SafeWrite32(0x444BA5, (DWORD)&configName); + SafeWrite32(0x444BCA, (DWORD)&configName); + dlogr(" Done", DL_INIT); + } + + patchName[64] = 0; + if (GetConfigString("Misc", "PatchFile", "", patchName, 64)) { + dlog("Applying patch file patch.", DL_INIT); + SafeWrite32(0x444323, (DWORD)&patchName); + dlogr(" Done", DL_INIT); + } if (GetConfigInt("Misc", "SingleCore", 1)) { dlog("Applying single core patch.", DL_INIT); @@ -817,11 +575,16 @@ static void DllMain2() { dlogr(" Done", DL_INIT); } - std::string elevPath = GetConfigString("Misc", "ElevatorsFile", "", MAX_PATH); - if (!elevPath.empty()) { - dlog("Applying elevator patch.", DL_INIT); - ElevatorsInit(); - LoadElevators(elevPath.insert(0, ".\\").c_str()); + if (GetConfigInt("Misc", "Fallout1Behavior", 0)) { + dlog("Applying Fallout 1 engine behavior patch.", DL_INIT); + BlockCall(0x4A4343); // disable playing the final movie/credits after the endgame slideshow + SafeWrite8(0x477C71, 0xEB); // disable halving the weight for power armor items + dlogr(" Done", DL_INIT); + } + + if (GetConfigInt("Misc", "DialogueFix", 1)) { + dlog("Applying dialogue patch.", DL_INIT); + SafeWrite8(0x446848, 0x31); dlogr(" Done", DL_INIT); } @@ -841,14 +604,6 @@ static void DllMain2() { dlogr(" Done", DL_INIT); //} - if (GetConfigInt("Misc", "DisplayKarmaChanges", 0)) { - dlog("Applying display karma changes patch.", DL_INIT); - Translate("sfall", "KarmaGain", "You gained %d karma.", KarmaGainMsg); - Translate("sfall", "KarmaLoss", "You lost %d karma.", KarmaLossMsg); - HookCall(0x455A6D, SetGlobalVarWrapper); - dlogr(" Done", DL_INIT); - } - if (GetConfigInt("Misc", "AlwaysReloadMsgs", 0)) { dlog("Applying always reload messages patch.", DL_INIT); SafeWrite8(0x4A6B8D, 0x0); @@ -885,35 +640,6 @@ static void DllMain2() { if (tmp != 293) SafeWrite32(0x518D64, tmp); dlogr(" Done", DL_INIT); - dlogr("Running HeroAppearanceModInit().", DL_INIT); - HeroAppearanceModInit(); - - dlogr("Running TilesInit().", DL_INIT); - TilesInit(); - - dlogr("Running CreditsInit().", DL_INIT); - CreditsInit(); - - dlogr("Running QuestListInit().", DL_INIT); - QuestListInit(); - - dlogr("Running PremadeInit().", DL_INIT); - PremadeInit(); - - dlogr("Running SoundInit().", DL_INIT); - SoundInit(); - - dlogr("Running ReputationsInit().", DL_INIT); - ReputationsInit(); - - dlogr("Running ConsoleInit().", DL_INIT); - ConsoleInit(); - - if (GetConfigInt("Misc", "ExtraSaveSlots", 0)) { - dlogr("Running EnableSuperSaving().", DL_INIT); - EnableSuperSaving(); - } - switch (GetConfigInt("Misc", "SpeedInterfaceCounterAnims", 0)) { case 1: dlog("Applying SpeedInterfaceCounterAnims patch.", DL_INIT); @@ -927,25 +653,6 @@ static void DllMain2() { break; } - std::vector karmaFrmList = GetConfigList("Misc", "KarmaFRMs", "", 512); - size_t countFrm = karmaFrmList.size(); - if (countFrm) { - dlog("Applying karma FRM patch.", DL_INIT); - std::vector karmaPointsList = GetConfigList("Misc", "KarmaPoints", "", 512); - - karmaFrms.resize(countFrm); - size_t countPoints = karmaPointsList.size(); - for (size_t i = 0; i < countFrm; i++) { - karmaFrms[i].frm = atoi(karmaFrmList[i].c_str()); - karmaFrms[i].points = (countPoints > i) - ? atoi(karmaPointsList[i].c_str()) - : INT_MAX; - } - HookCall(0x4367A9, DrawInfoWin_hook); - - dlogr(" Done", DL_INIT); - } - switch (GetConfigInt("Misc", "ScienceOnCritters", 0)) { case 1: HookCall(0x41276E, ScienceCritterCheckHook); @@ -962,15 +669,9 @@ static void DllMain2() { dlogr(" Done", DL_INIT); } - dlogr("Running BarBoxesInit().", DL_INIT); - BarBoxesInit(); - dlogr("Patching out ereg call.", DL_INIT); BlockCall(0x4425E6); - dlogr("Running AnimationsAtOnceInit().", DL_INIT); - AnimationsAtOnceInit(); - if (tmp = GetConfigInt("Sound", "OverrideMusicDir", 0)) { SafeWrite32(0x4449C2, (DWORD)musicOverridePath); SafeWrite32(0x4449DB, (DWORD)musicOverridePath); @@ -993,9 +694,6 @@ static void DllMain2() { dlogr(" Done", DL_INIT); } - dlogr("Running InventoryInit().", DL_INIT); - InventoryInit(); - if (tmp = GetConfigInt("Misc", "MotionScannerFlags", 1)) { dlog("Applying MotionScannerFlags patch.", DL_INIT); if (tmp & 1) MakeJump(0x41BBE9, ScannerAutomapHook); @@ -1027,12 +725,6 @@ static void DllMain2() { dlogr(" Done", DL_INIT); } - dlogr("Running AIInit().", DL_INIT); - AIInit(); - - dlogr("Initializing party control...", DL_INIT); - PartyControlInit(); - if (GetConfigInt("Misc", "ObjCanSeeObj_ShootThru_Fix", 0)) { dlog("Applying ObjCanSeeObj ShootThru Fix.", DL_INIT); HookCall(0x456BC6, op_obj_can_see_obj_hook); @@ -1040,12 +732,6 @@ static void DllMain2() { } // phobos2077: - dlogr("Running ComputeSprayModInit().", DL_INIT); - ComputeSprayModInit(); - dlogr("Running ExplosionInit().", DL_INIT); - ExplosionInit(); - dlogr("Running BooksInit().", DL_INIT); - BooksInit(); DWORD addrs[2] = {0x45F9DE, 0x45FB33}; SimplePatch(addrs, 2, "Misc", "CombatPanelAnimDelay", 1000, 0, 65535); addrs[0] = 0x447DF4; addrs[1] = 0x447EB6; @@ -1142,12 +828,15 @@ static void DllMain2() { SafeWrite8(0x43ACD5, 144); // 136 SafeWrite8(0x43DD37, 144); // 133 - if (GetConfigInt("Misc", "Fallout1Behavior", 0)) { - dlog("Applying Fallout 1 engine behavior patch.", DL_INIT); - BlockCall(0x4A4343); // disable playing the final movie/credits after the endgame slideshow - SafeWrite8(0x477C71, 0xEB); // disable halving the weight for power armor items - dlogr(" Done", DL_INIT); - } + dlogr("Running TalkingHeadsInit().", DL_INIT); + TalkingHeadsInit(); + + // most of modules should be initialized before running the script handlers + dlogr("Running ScriptExtenderInit().", DL_INIT); + ScriptExtenderInit(); + + dlogr("Running DebugEditorInit().", DL_INIT); + DebugEditorInit(); dlogr("Leave DllMain2", DL_MAIN); } @@ -1156,17 +845,17 @@ static void _stdcall OnExit() { if (scriptDialog != nullptr) { delete[] scriptDialog; } - SpeedPatchExit(); GraphicsExit(); - TalkingHeadsExit(); MoviesExit(); - ClearReadExtraGameMsgFiles(); + SpeedPatchExit(); SkillsExit(); - HeroAppearanceModExit(); ReputationsExit(); ConsoleExit(); - AnimationsAtOnceExit(); BooksExit(); + ClearReadExtraGameMsgFiles(); + AnimationsAtOnceExit(); + HeroAppearanceModExit(); + TalkingHeadsExit(); } static void __declspec(naked) OnExitFunc() { diff --git a/sfall/main.h b/sfall/main.h index caf1ac96..1a00763f 100644 --- a/sfall/main.h +++ b/sfall/main.h @@ -111,9 +111,6 @@ extern bool hrpVersionValid; extern char defaultMaleModelName[65]; extern char defaultFemaleModelName[65]; -void RemoveSavFiles(); -void ClearSavPrototypes(); - template T SimplePatch(DWORD addr, const char* iniSection, const char* iniKey, T defaultValue, T minValue = 0, T maxValue = INT_MAX) {