Added code for Dialog/Barter interface

Added support for Continuum's dialog graphic.
This commit is contained in:
NovaRain
2021-11-10 10:43:15 +08:00
parent f75214056e
commit 5a61bb8fc3
11 changed files with 330 additions and 16 deletions
+1
View File
@@ -19,6 +19,7 @@
#define FO_VAR_aTextSCutsS 0x503530
#define FO_VAR_aTextSCutsSS 0x50B01C
#define FO_VAR_attack_str 0x56D624
#define FO_VAR_backgrndRects 0x518748
#define FO_VAR_background_fname_requested 0x596FC2
#define FO_VAR_background_volume 0x518E88
#define FO_VAR_bboxslot 0x5970E0
+1
View File
@@ -10,6 +10,7 @@ VARA(art, fo::Art, 11)
VAR_(art_name, DWORD)
VAR_(art_vault_guy_num, DWORD)
VAR_(art_vault_person_nums, DWORD)
VARA(backgrndRects, fo::BoundRect, 8)
VAR_(background_volume, DWORD)
VAR_(bckgnd, BYTE*)
VAR_(black_palette, DWORD)
+270
View File
@@ -0,0 +1,270 @@
/*
* sfall
* Copyright (C) 2008-2021 The sfall team
*
*/
#include "..\main.h"
#include "..\FalloutEngine\Fallout2.h"
#include "..\Modules\LoadGameHook.h"
#include "Init.h"
#include "ViewMap\ViewMap.h"
#include "Dialog.h"
namespace sfall
{
static const long width = 640; // art
static long scr_width = 639;
static fo::UnlistedFrm* altDialogArt;
bool Dialog::DIALOG_SCRN_ART_FIX = true;
bool Dialog::DIALOG_SCRN_BACKGROUND = false;
static long xPosition;
static long yPosition;
static long __fastcall CreateWinDialog(long height, long yPos, long xPos, long color, long flags) {
if (Dialog::DIALOG_SCRN_BACKGROUND) {
fo::func::win_hide(fo::var::getInt(FO_VAR_display_win));
// hide panels
yPos += 50;
}
long mapWinW = fo::var::getInt(FO_VAR_buf_width_2) / 2;
long mapWinH = fo::var::getInt(FO_VAR_buf_length_2) / 2;
yPos += mapWinH - (height / 2); // yPos:0 = 480 - art_frame_length
xPos += mapWinW - (width / 2); // xPos:0
xPosition = xPos;
yPosition = yPos;
return fo::func::win_add(xPos, yPos, width, height, color, flags);
}
static void __declspec(naked) gdCreateHeadWindow_hook_win_add() {
__asm {
pop ebx; // ret addr
push eax; // xPos
push ebx;
jmp CreateWinDialog;
}
}
static void ShowMapWindow() {
fo::func::win_show(fo::var::getInt(FO_VAR_display_win));
fo::func::win_draw(fo::var::getInt(FO_VAR_display_win));
// show panels
}
static void __declspec(naked) gdDestroyHeadWindow_hook_win_delete() {
__asm {
call fo::funcoffs::win_delete_;
jmp ShowMapWindow;
}
}
static void __declspec(naked) GeneralDialogWinAdd() {
__asm {
add eax, xPosition;
add edx, yPosition;
mov ebx, width;
jmp fo::funcoffs::win_add_;
}
}
static void __declspec(naked) gdProcess_hook_win_add() {
__asm {
add edx, yPosition;
add eax, xPosition;
jmp fo::funcoffs::win_add_;
}
}
static void __declspec(naked) setup_inventory_hook_win_add() {
__asm {
add eax, xPosition;
add edx, yPosition;
jmp fo::funcoffs::win_add_;
}
}
static void __declspec(naked) setup_inventory_hack() {
__asm {
mov dword ptr ds:[FO_VAR_i_wid], eax;
add ebx, xPosition;
add ecx, yPosition;
retn;
}
}
static void __declspec(naked) barter_move_hook_mouse_click_in() {
__asm {
add eax, xPosition; // left
add ebx, xPosition; // right
add edx, yPosition; // top
add ecx, yPosition; // bottom
jmp fo::funcoffs::mouse_click_in_;
}
}
static void __declspec(naked) hook_buf_to_buf() {
__asm {
imul eax, yPosition, 640;
add [esp + 4], eax;
jmp fo::funcoffs::buf_to_buf_;
}
}
// Implementation from HRP by Mash
static void __cdecl gdDisplayFrame_hook_buf_to_buf(BYTE* src, long w, long h, long srcWidth, BYTE* dst, long dstWidth) {
long cx, cy;
ViewMap::GetTileCoord(fo::var::getInt(FO_VAR_tile_center_tile), cx, cy);
fo::GameObject* dialog_target = fo::var::dialog_target;
long x, y;
ViewMap::GetTileCoord(dialog_target->tile, x, y);
long xDist = 16 * (cx - x);
long yDist = 12 * (y - cy);
DWORD lockPtr;
auto frm = fo::func::art_ptr_lock(dialog_target->artFid, &lockPtr);
long yOffset = fo::func::art_frame_length(frm, dialog_target->frm, dialog_target->rotation) / 2;
fo::func::art_ptr_unlock(lockPtr);
long mapWinH = fo::var::getInt(FO_VAR_buf_length_2) - h;
y = (mapWinH / 2) + (yDist - yOffset);
if (y < 0) {
y = 0;
} else if (y > mapWinH) {
y = mapWinH;
}
long mapWinW = srcWidth - w; // fo::var::getInt(FO_VAR_buf_width_2);
x = (mapWinW / 2) + xDist;
if (x < 0) {
x = 0;
} else if (x > (mapWinW)) {
x = mapWinW;
}
fo::func::buf_to_buf((BYTE*)fo::var::getInt(FO_VAR_display_buf) + x + (y * srcWidth), w, h, srcWidth, dst, width);
}
static bool loadAltDialogArt = false;
static void __cdecl talk_to_refresh_background_window_hook_buf_to_buf(BYTE* src, long w, long h, long srcWidth, BYTE* dst, long dstWidth) {
if (!loadAltDialogArt) {
loadAltDialogArt = true;
altDialogArt = fo::util::LoadUnlistedFrm("HR_ALLTLK.frm", fo::ArtType::OBJ_TYPE_INTRFACE);
}
if (altDialogArt) {
src = altDialogArt->frames->indexBuff;
srcWidth = altDialogArt->frames->width;
}
fo::func::buf_to_buf(src, w, h, srcWidth, dst, dstWidth);
}
static void UnloadDialogArt() {
if (altDialogArt) {
delete altDialogArt;
altDialogArt = nullptr;
}
loadAltDialogArt = false;
}
void Dialog::init() {
// replace width size for buffers functons
SafeWriteBatch(&scr_width, {
0x447201, 0x447248, //0x44716F, // gdCreateHeadWindow_
0x4459F0, 0x445A0C, //0x44597A, // gdReviewInit_
0x445DA7, 0x445DD1, // gdReviewDisplay_
0x447E43, 0x447E75, 0x447EE2, 0x447EFE, 0x447DB5, // gdialog_scroll_subwin_
0x44A705, //0x44A6C3, // gdialog_window_create_
0x44AA28, // gdialog_window_destroy_
0x448354, //0x448312, // gdialog_barter_create_win_
0x4485AC, // gdialog_barter_destroy_win_
0x4487FF, //0x4487BD, // gdControlCreateWin_
0x448CA0, // gdControlDestroyWin_
0x4497A0, //0x44975E, // gdCustomCreateWin_
0x449AA0, // gdCustomDestroyWin_
0x449C2C, // gdCustomUpdateInfo_
0x44AB4C, 0x44AB6A, // talk_to_refresh_background_window_
0x44AC23, // talkToRefreshDialogWindowRect_
0x44AE4D, 0x44AF94, 0x44AFD5, 0x44B015, 0x44AD7B, 0x44AE88, // gdDisplayFrame_
//0x44AADE, // talk_to_create_background_window_ (unused)
// for barter interface
0x46EE04, // setup_inventory_
0x4753C1, 0x475400, 0x47559F, 0x4755F5, // display_table_inventories_
0x47005A, 0x47008F, // display_inventory_
0x470401, 0x47043E, // display_target_inventory_
0x47080E, // display_body_
0x474E35, 0x474E76, // barter_move_inventory_
0x4750FE, 0x475139, // barter_move_from_table_inventory_
0x4733DF, 0x47343A, // inven_action_cursor_
});
HookCall(0x44718F, gdCreateHeadWindow_hook_win_add);
HookCalls(GeneralDialogWinAdd, {
0x445997, // gdReviewInit_
0x44A6E4, // gdialog_window_create_
0x448333, // gdialog_barter_create_win_
0x4487CE, // gdControlCreateWin_
0x44976F, // gdCustomCreateWin_
});
// gdCustomSelect_
long yoffset = (DIALOG_SCRN_BACKGROUND) ? 100 : 200; // shifted the window up so that the window with the selected parameters was visible
SafeWrite32(0x44A03E, HRP::ScreenHeight() - yoffset);
SafeWrite32(0x44A02A, HRP::ScreenWidth());
HookCall(0x4462A7, gdProcess_hook_win_add);
HookCall(0x446387, gdProcess_hook_win_add);
HookCall(0x447900, hook_buf_to_buf); // demo_copy_options_
HookCall(0x447A46, hook_buf_to_buf); // gDialogRefreshOptionsRect_
HookCall(0x44AF39, gdDisplayFrame_hook_buf_to_buf);
// Barter interface hacks
HookCall(0x46EDC9, setup_inventory_hook_win_add);
MakeCall(0x46EDD8, setup_inventory_hack);
HookCalls(barter_move_hook_mouse_click_in, {
0x474F76, 0x474FF9, // barter_move_inventory_
0x475241, 0x4752C2, // barter_move_from_table_inventory_
0x449661 // gdControl_ (custom disposition button)
});
if (DIALOG_SCRN_BACKGROUND) HookCall(0x4472D8, gdDestroyHeadWindow_hook_win_delete);
if (DIALOG_SCRN_ART_FIX) {
HookCall(0x44AB79, talk_to_refresh_background_window_hook_buf_to_buf);
// gdCreateHeadWindow_
SafeWrite16(0x447255, 0xD269);
SafeWrite32(0x447257, 19); // y
SafeWrite8(0x44725B, 0x90);
SafeWrite16(0x44725C, 0x3EB);
// gdDisplayFrame_
SafeWrite8(0x44AF9D, 20); // 15 to 20
SafeWrite32(0x44AFEB, 219); // 214 to 219
SafeWrite32(0x44AF47, 19); // 14 to 19
SafeWrite32(0x44AF51, 219); // 214 to 219
for (size_t i = 0; i < 8; i++) {
fo::var::backgrndRects[i].y += 5;
fo::var::backgrndRects[i].offy += 5;
}
LoadGameHook::OnGameExit() += UnloadDialogArt;
}
}
}
+20
View File
@@ -0,0 +1,20 @@
/*
* sfall
* Copyright (C) 2008-2021 The sfall team
*
*/
#pragma once
namespace sfall
{
class Dialog {
public:
static void init();
static bool DIALOG_SCRN_ART_FIX;
static bool DIALOG_SCRN_BACKGROUND;
};
}
+12 -1
View File
@@ -15,6 +15,7 @@
#include "SplashScreen.h"
#include "MainMenu.h"
#include "InterfaceBar.h"
#include "Dialog.h"
#include "Init.h"
@@ -102,10 +103,19 @@ void HRP::init() {
ViewMap::IGNORE_MAP_EDGES = (IniReader::GetInt("MAPS", "IGNORE_MAP_EDGES", 0, f2ResIni) != 0);
ViewMap::EDGE_CLIPPING_ON = (IniReader::GetInt("MAPS", "EDGE_CLIPPING_ON", 1, f2ResIni) != 0);
Dialog::DIALOG_SCRN_ART_FIX = (IniReader::GetInt("OTHER_SETTINGS", "DIALOG_SCRN_ART_FIX", 1, f2ResIni) != 0);
Dialog::DIALOG_SCRN_BACKGROUND = (IniReader::GetInt("OTHER_SETTINGS", "DIALOG_SCRN_BACKGROUND", 0, f2ResIni) != 0);
if (IniReader::GetInt("OTHER_SETTINGS", "BARTER_PC_INV_DROP_FIX", 1, f2ResIni)) {
// barter_move_from_table_inventory_
if (fo::var::getInt(0x47523D) == 80) SafeWrite32(0x47523D, 100); // x_start
if (fo::var::getInt(0x475231) == 144) SafeWrite32(0x475231, 164); // x_end
}
// add before sfall.dat and after critter.dat
LoadOrder::AddResourcePatches(
IniReader::GetString("Main", "f2_res_dat", "f2_res.dat", MAX_PATH, f2ResIni),
IniReader::GetString("Main", "f2_res_patches", "data", MAX_PATH, f2ResIni)
IniReader::GetString("Main", "f2_res_patches", "", MAX_PATH, f2ResIni)
);
/* Inject hacks */
@@ -135,6 +145,7 @@ void HRP::init() {
MainMenuScreen::init();
ViewMap::init();
IFaceBar::init();
Dialog::init();
}
}
+4 -4
View File
@@ -113,7 +113,7 @@ static void SetDefaultEdgeData() {
edge->squareRect.right = 0;
edge->squareRect.bottom = 99;
edge->field_48 = 0;
edge->clipData = 0;
edge->prevEdgeData = nullptr;
edge->nextEdgeData = nullptr;
}
@@ -168,7 +168,7 @@ static fo::DbFile* LoadMapEdgeFileSub(char* mapName) {
if (edgeVersion) {
// load rectangle data (version 2)
if (fo::func::db_freadIntCount(file, (DWORD*)&edgeData->squareRect, 4) || fo::func::db_freadInt(file, (DWORD*)&edgeData->field_48)) {
if (fo::func::db_freadIntCount(file, (DWORD*)&edgeData->squareRect, 4) || fo::func::db_freadInt(file, (DWORD*)&edgeData->clipData)) {
return file; // read error
}
} else {
@@ -176,7 +176,7 @@ static fo::DbFile* LoadMapEdgeFileSub(char* mapName) {
edgeData->squareRect.top = 0;
edgeData->squareRect.right = 0;
edgeData->squareRect.bottom = 99;
edgeData->field_48 = 0;
edgeData->clipData = 0;
}
if (getValue == mapLevel) {
@@ -229,7 +229,7 @@ long EdgeBorder::GetCenterTile(long tile, long mapLevel) {
Edge* edgeData = &MapEdgeData[mapLevel];
currentMapEdge = edgeData;
// clear unreconstructed areas when EDGE_CLIPPING is enabled (maybe there is another way to do this, and not every time)
// clear unreferenced areas when EDGE_CLIPPING is enabled (maybe there is another way to do this, and not every time)
std::memset((void*)fo::var::getInt(FO_VAR_display_buf), 0, fo::var::getInt(FO_VAR_buf_size));
//fo::func::win_draw(fo::var::getInt(FO_VAR_display_win)); // for test
+2 -2
View File
@@ -16,8 +16,8 @@ public:
RECT borderRect; // right is less than left
RECT rect_2;
RECT tileRect;
RECT squareRect;
long field_48; // unknown
RECT squareRect; // angel clipping
long clipData; // angel clip type
Edge* prevEdgeData; // unused (used in 3.06)
Edge* nextEdgeData;
+10 -7
View File
@@ -164,6 +164,7 @@ static void __declspec(naked) tile_scroll_to_hack_replacement() {
}
}
// Implementation from HRP 3.0.6 by Mash
static long __fastcall square_rect_render_floor(long y, long id, long x) {
if (x < 0 || x >= square_width || y < 0 || y >= square_length) return -1;
@@ -192,6 +193,7 @@ skipDraw:
}
}
// Implementation from HRP 3.0.6 by Mash
static long __fastcall square_rect_render_roof(long y, long id, long x) {
if (x < 0 || x >= square_width || y < 0 || y >= square_length) return -1;
@@ -243,6 +245,7 @@ skipDraw:
}
}
// Implementation from HRP 3.0.6 by Mash
static void __fastcall square_obj_render(fo::BoundRect* rect, long tag) {
if (EdgeBorder::EdgeVersion() == 0) return;
@@ -267,10 +270,10 @@ static void __fastcall square_obj_render(fo::BoundRect* rect, long tag) {
do {
long X = x2;
do {
if (X > edge->squareRect.left && ((edge->field_48 >> 24) & 1) == tag ||
Y < edge->squareRect.top && ((edge->field_48 >> 16) & 1) == tag ||
X < edge->squareRect.right && ((edge->field_48 >> 8) & 1) == tag ||
Y > edge->squareRect.bottom && (edge->field_48 & 1) == tag)
if (X > edge->squareRect.left && ((edge->clipData >> 24) & 1) == tag ||
Y < edge->squareRect.top && ((edge->clipData >> 16) & 1) == tag ||
X < edge->squareRect.right && ((edge->clipData >> 8) & 1) == tag ||
Y > edge->squareRect.bottom && (edge->clipData & 1) == tag)
{
long s_x, s_y;
fo::func::square_coord(X + sY, &s_x, &s_y);
@@ -282,7 +285,7 @@ static void __fastcall square_obj_render(fo::BoundRect* rect, long tag) {
call fo::funcoffs::floor_draw_;
}
}
} while (++X < x0);
} while (++X < x0); // x < right
sY += square_width;
} while (++Y < y3); // y < bottom
@@ -290,8 +293,8 @@ static void __fastcall square_obj_render(fo::BoundRect* rect, long tag) {
static void __declspec(naked) obj_render_pre_roof_hack_0() {
__asm {
lea ecx, [esp + 4];
mov edx, 0;
lea ecx, [esp + 4];
call square_obj_render;
mov edi, [esp + 0x2C + 4];
test edi, edi;
@@ -301,8 +304,8 @@ static void __declspec(naked) obj_render_pre_roof_hack_0() {
static void __declspec(naked) obj_render_pre_roof_hack_1() {
__asm {
lea ecx, [esp + 4];
mov edx, 1;
lea ecx, [esp + 4];
call square_obj_render;
pop eax; // ret addr
add esp, 0x44;
+2 -2
View File
@@ -488,8 +488,8 @@ static void SfallResourceFile() {
// last: master.dat < critter.dat < [add here] < sfall.dat < patchXXX.dat
void LoadOrder::AddResourcePatches(std::string &dat, std::string &patches) {
patchFiles.push_back(std::move(dat));
patchFiles.push_back(std::move(patches));
if (!dat.empty()) patchFiles.push_back(std::move(dat));
if (!patches.empty()) patchFiles.push_back(std::move(patches));
}
void LoadOrder::init() {
+2
View File
@@ -309,6 +309,7 @@
<ClInclude Include="Game\skills.h" />
<ClInclude Include="Game\stats.h" />
<ClInclude Include="Game\tilemap.h" />
<ClInclude Include="HRP\Dialog.h" />
<ClInclude Include="HRP\Image.h" />
<ClInclude Include="HRP\Init.h" />
<ClInclude Include="HRP\InterfaceBar.h" />
@@ -435,6 +436,7 @@
<ClCompile Include="Game\skills.cpp" />
<ClCompile Include="Game\stats.cpp" />
<ClCompile Include="Game\tilemap.cpp" />
<ClCompile Include="HRP\Dialog.cpp" />
<ClCompile Include="HRP\Image.cpp" />
<ClCompile Include="HRP\Init.cpp" />
<ClCompile Include="HRP\InterfaceBar.cpp" />
+6
View File
@@ -401,6 +401,9 @@
<ClInclude Include="HRP\ViewMap\EdgeClipping.h">
<Filter>HRP\ViewMap</Filter>
</ClInclude>
<ClInclude Include="HRP\Dialog.h">
<Filter>HRP</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
@@ -737,6 +740,9 @@
<ClCompile Include="HRP\ViewMap\EdgeClipping.cpp">
<Filter>HRP\ViewMap</Filter>
</ClCompile>
<ClCompile Include="HRP\Dialog.cpp">
<Filter>HRP</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="version.rc" />