mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Modified some of the mechanics of "interface_overlay" function
Changed "intface_redraw" with one argument to redraw the specified interface window.
This commit is contained in:
@@ -338,7 +338,8 @@
|
||||
#define interface_art_draw_ex(winID, artID, x, y, frame, param) sfall_func6("interface_art_draw", winID, artID, x, y, frame, param)
|
||||
#define interface_print(text, winType, x, y, color) sfall_func5("interface_print", text, winType, x, y, color)
|
||||
#define interface_print_width(text, winType, x, y, color, w) sfall_func6("interface_print", text, winType, x, y, color, w)
|
||||
#define interface_redraw_all sfall_func1("intface_redraw", 1)
|
||||
#define interface_redraw_all sfall_func1("intface_redraw", -1)
|
||||
#define interface_redraw_win(winType) sfall_func1("intface_redraw", winType)
|
||||
#define intface_hide sfall_func0("intface_hide")
|
||||
#define intface_is_hidden sfall_func0("intface_is_hidden")
|
||||
#define intface_is_shown(winType) sfall_func1("get_window_attribute", winType)
|
||||
@@ -358,6 +359,7 @@
|
||||
#define overlay_create(winType) sfall_func2("interface_overlay", winType, 1)
|
||||
#define overlay_clear(winType) sfall_func2("interface_overlay", winType, 2)
|
||||
#define overlay_clear_rectangle(winType, x, y, w, h) sfall_func6("interface_overlay", winType, 2, x, y, w, h)
|
||||
#define overlay_destroy(winType) sfall_func2("interface_overlay", winType, 0)
|
||||
#define real_dude_obj sfall_func0("real_dude_obj")
|
||||
#define remove_all_timer_events sfall_func0("remove_timer_event")
|
||||
#define remove_timer_event(fixedParam) sfall_func1("remove_timer_event", fixedParam)
|
||||
|
||||
@@ -402,9 +402,9 @@ Some utility/math functions are available:
|
||||
- works just like vanilla critter_inven_obj, but correctly reports item in player's inactive hand slot
|
||||
|
||||
> void sfall_func0("intface_redraw")
|
||||
> void sfall_func1("intface_redraw", bool eachWin)
|
||||
> void sfall_func1("intface_redraw", int winType)
|
||||
- redraws main game interface, useful to reflect changes after directly changing current player weapons or stats
|
||||
- eachWin: pass True to redraw all interface windows
|
||||
- winType: the type number of the interface window (see WINTYPE_* constants in sfall.h). Pass -1 to redraw all interface windows
|
||||
|
||||
> void sfall_func0("intface_hide")
|
||||
- hides main interface
|
||||
@@ -782,6 +782,14 @@ optional arguments:
|
||||
- fills the rectangle area of the currently selected script window with the specified color, or clears the window with transparent (index 0) color (call the function without arguments)
|
||||
- color: the color index in the game palette (from 0 to 255)
|
||||
|
||||
> int sfall_func2("interface_overlay", int winType, int mode)
|
||||
> int sfall_func6("interface_overlay", int winType, 2, int x, int y, int width, int height)
|
||||
- creates an additional drawing surface above the graphic layer of the specified interface window. All subsequent calls of interface_art_draw and interface_print functions will draw on it
|
||||
- winType: the type number of the interface window (see WINTYPE_* constants in sfall.h)
|
||||
- mode: 1 - creates a new overlay surface
|
||||
2 - clears the overlay area or the specified rectangle defined by the x, y, width, height arguments
|
||||
0 - destroys the created overlay surface (frees up the memory allocated to the surface)
|
||||
|
||||
------------------------
|
||||
------ MORE INFO -------
|
||||
------------------------
|
||||
|
||||
@@ -365,6 +365,4 @@
|
||||
0x8280 - any sfall_func7(string funcName, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
|
||||
0x8281 - any sfall_func8(string funcName, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
|
||||
|
||||
|
||||
* These functions require AllowUnsafeScripting to be enabled in ddraw.ini
|
||||
|
||||
|
||||
@@ -499,10 +499,11 @@ void RedrawObject(GameObject* obj) {
|
||||
func::tile_refresh_rect(&rect, obj->elevation);
|
||||
}
|
||||
|
||||
// Redraws all interface windows
|
||||
void RefreshGNW(size_t from) {
|
||||
// Redraws all windows
|
||||
void RefreshGNW(bool skipOwner) {
|
||||
*(DWORD*)FO_VAR_doing_refresh_all = 1;
|
||||
for (size_t i = from; i < fo::var::num_windows; i++) {
|
||||
for (size_t i = 0; i < fo::var::num_windows; i++) {
|
||||
if (skipOwner && fo::var::window[i]->flags & fo::WinFlags::OwnerFlag) continue;
|
||||
fo::func::GNW_win_refresh(fo::var::window[i], &fo::var::scr_size, 0);
|
||||
}
|
||||
*(DWORD*)FO_VAR_doing_refresh_all = 0;
|
||||
|
||||
@@ -148,8 +148,8 @@ DWORD GetMaxCharWidth();
|
||||
// Redraw the given object on screen (does not always redraws the whole object)
|
||||
void RedrawObject(GameObject* obj);
|
||||
|
||||
// Redraws all interface windows
|
||||
void RefreshGNW(size_t from = 0);
|
||||
// Redraws all windows
|
||||
void RefreshGNW(bool skipOwner = false);
|
||||
|
||||
UnlistedFrm *LoadUnlistedFrm(char *frmName, unsigned int folderRef);
|
||||
|
||||
|
||||
+10
-10
@@ -789,16 +789,16 @@ namespace Fields {
|
||||
namespace WinFlags {
|
||||
enum WinButtonFlags : long
|
||||
{
|
||||
OwnerFlag = 0x1,
|
||||
DontMoveTop = 0x2,
|
||||
MoveOnTop = 0x4,
|
||||
Hidden = 0x8,
|
||||
Exclusive = 0x10,
|
||||
Transparent = 0x20,
|
||||
UnknownFlag40 = 0x40,
|
||||
UnknownFlag80 = 0x80,
|
||||
ScriptWindow = 0x100,
|
||||
itsButton = 0x10000,
|
||||
OwnerFlag = 0x000001, // sfall Render flag, indicates that the window surface is used for rendering the game scene
|
||||
DontMoveTop = 0x000002, // does not move the window to top when the mouse is clicked in the window area or when it is showing
|
||||
MoveOnTop = 0x000004, // places the window on top when it is created
|
||||
Hidden = 0x000008,
|
||||
Exclusive = 0x000010,
|
||||
Transparent = 0x000020,
|
||||
UnknownFlag40 = 0x000040,
|
||||
UnknownFlag80 = 0x000080,
|
||||
ScriptWindow = 0x000100,
|
||||
itsButton = 0x010000,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,18 @@
|
||||
|
||||
#include "Enums.h"
|
||||
|
||||
namespace sfall
|
||||
{
|
||||
|
||||
struct Rectangle {
|
||||
long x, y, width, height;
|
||||
|
||||
long right() { return x + (width - 1); }
|
||||
long bottom() { return y + (height - 1); }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace fo
|
||||
{
|
||||
|
||||
@@ -74,6 +86,22 @@ struct BoundRect {
|
||||
long y;
|
||||
long offx; // right
|
||||
long offy; // bottom
|
||||
|
||||
BoundRect() {};
|
||||
|
||||
BoundRect(sfall::Rectangle rect) {
|
||||
x = rect.x;
|
||||
y = rect.y;
|
||||
offx = rect.right();
|
||||
offy = rect.bottom();
|
||||
}
|
||||
|
||||
BoundRect(RECT* rect) {
|
||||
x = rect->left;
|
||||
y = rect->top;
|
||||
offx = rect->right;
|
||||
offy = rect->bottom;
|
||||
}
|
||||
};
|
||||
|
||||
struct RectList {
|
||||
|
||||
@@ -572,11 +572,32 @@ static void AlwaysReloadMsgs() {
|
||||
}
|
||||
}
|
||||
|
||||
static void RemoveWindowRoundingPatch() {
|
||||
static void InterfaceWindowPatch() {
|
||||
if (GetConfigInt("Misc", "RemoveWindowRounding", 1)) {
|
||||
SafeWriteBatch<BYTE>(CodeType::JumpShort, {0x4D6EDD, 0x4D6F12});
|
||||
//SafeWrite16(0x4B8090, 0x04EB); // jmps 0x4B8096 (old)
|
||||
}
|
||||
|
||||
dlog("Applying flags patch for interface windows.", DL_INIT);
|
||||
|
||||
// Remove MoveOnTop flag for interfaces
|
||||
SafeWrite8(0x46ECE9, (*(BYTE*)0x46ECE9) ^ fo::WinFlags::MoveOnTop); // Player Inventory/Loot/UseOn
|
||||
SafeWrite8(0x41B966, (*(BYTE*)0x41B966) ^ fo::WinFlags::MoveOnTop); // Automap
|
||||
|
||||
// Set OwnerFlag flag
|
||||
SafeWrite8(0x481CEC, (*(BYTE*)0x481CEC) | fo::WinFlags::OwnerFlag); // _display_win (map win)
|
||||
SafeWrite8(0x44E7D2, (*(BYTE*)0x44E7D2) | fo::WinFlags::OwnerFlag); // gmovie_play_ (movie win)
|
||||
|
||||
// Remove OwnerFlag flag
|
||||
SafeWrite8(0x4B801B, (*(BYTE*)0x4B801B) ^ fo::WinFlags::OwnerFlag); // createWindow_
|
||||
// Remove OwnerFlag and Transparent flags
|
||||
SafeWrite8(0x42F869, (*(BYTE*)0x42F869) ^ (fo::WinFlags::Transparent | fo::WinFlags::OwnerFlag)); // addWindow_
|
||||
|
||||
dlogr(" Done", DL_INIT);
|
||||
|
||||
// Disable unused code for the RandX and RandY window structure fields (these fields can now be used for other purposes)
|
||||
SafeWrite32(0x4D630C, 0x9090C031); // xor eax, eax
|
||||
SafeWrite8(0x4D6310, 0x90);
|
||||
BlockCall(0x4D6319);
|
||||
}
|
||||
|
||||
static void InventoryCharacterRotationSpeedPatch() {
|
||||
@@ -685,15 +706,6 @@ static void SkipLoadingGameSettingsPatch() {
|
||||
}
|
||||
}
|
||||
|
||||
static void InterfaceDontMoveOnTopPatch() {
|
||||
//if (GetConfigInt("Misc", "InterfaceDontMoveOnTop", 0)) {
|
||||
dlog("Applying no MoveOnTop flag for interface patch.", DL_INIT);
|
||||
SafeWrite8(0x46ECE9, fo::WinFlags::Exclusive); // Player Inventory/Loot/UseOn
|
||||
SafeWrite8(0x41B966, fo::WinFlags::Exclusive); // Automap
|
||||
dlogr(" Done", DL_INIT);
|
||||
//}
|
||||
}
|
||||
|
||||
static void UseWalkDistancePatch() {
|
||||
int distance = GetConfigInt("Misc", "UseWalkDistance", 3) + 2;
|
||||
if (distance > 1 && distance < 5) {
|
||||
@@ -834,7 +846,7 @@ void MiscPatches::init() {
|
||||
PlayIdleAnimOnReloadPatch();
|
||||
|
||||
SkilldexImagesPatch();
|
||||
RemoveWindowRoundingPatch();
|
||||
InterfaceWindowPatch();
|
||||
|
||||
ScienceOnCrittersPatch();
|
||||
InventoryCharacterRotationSpeedPatch();
|
||||
@@ -862,7 +874,6 @@ void MiscPatches::init() {
|
||||
PartyMemberSkillPatch();
|
||||
|
||||
SkipLoadingGameSettingsPatch();
|
||||
InterfaceDontMoveOnTopPatch();
|
||||
|
||||
UseWalkDistancePatch();
|
||||
}
|
||||
|
||||
@@ -268,10 +268,17 @@ void op_is_iface_tag_active(OpcodeContext &ctx) {
|
||||
}
|
||||
|
||||
void mf_intface_redraw(OpcodeContext& ctx) {
|
||||
if (ctx.arg(0).rawValue() == 0) {
|
||||
if (ctx.numArgs() == 0) {
|
||||
fo::func::intface_redraw();
|
||||
} else {
|
||||
fo::func::RefreshGNW(2); // fake redraw all interfaces (TODO: need a real redraw of interfaces)
|
||||
// fake redraw interfaces (TODO: need a real redraw of interface?)
|
||||
long winType = ctx.arg(0).rawValue();
|
||||
if (winType == -1) {
|
||||
fo::func::RefreshGNW(true);
|
||||
} else {
|
||||
fo::Window* win = Interface::GetWindow(winType);
|
||||
if (win && (int)win != -1) fo::func::GNW_win_refresh(win, &win->rect, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -636,7 +643,7 @@ static long InterfaceDrawImage(OpcodeContext& ctx, fo::Window* ifaceWin) {
|
||||
surface + (y * ifaceWin->width) + x, width, height, ifaceWin->width
|
||||
);
|
||||
|
||||
if (!(ctx.arg(0).rawValue() & 0x1000000)) {
|
||||
if (!(ctx.arg(0).rawValue() & 0x1000000)) { // is set to "Don't redraw"
|
||||
fo::func::GNW_win_refresh(ifaceWin, &ifaceWin->rect, 0);
|
||||
}
|
||||
|
||||
@@ -828,15 +835,15 @@ void mf_win_fill_color(OpcodeContext& ctx) {
|
||||
}
|
||||
|
||||
void mf_interface_overlay(OpcodeContext& ctx) {
|
||||
fo::Window* win = nullptr;
|
||||
long winType = ctx.arg(0).rawValue();
|
||||
|
||||
if (ctx.arg(1).rawValue()) {
|
||||
win = Interface::GetWindow(winType);
|
||||
fo::Window* win = Interface::GetWindow(winType);
|
||||
if (!win || (int)win == -1) return;
|
||||
}
|
||||
|
||||
switch (ctx.arg(1).rawValue()) {
|
||||
case 0:
|
||||
GameRender::DestroyOverlaySurface(win);
|
||||
break;
|
||||
case 1:
|
||||
GameRender::CreateOverlaySurface(win, winType);
|
||||
break;
|
||||
@@ -856,8 +863,6 @@ void mf_interface_overlay(OpcodeContext& ctx) {
|
||||
GameRender::ClearOverlay(win);
|
||||
}
|
||||
break;
|
||||
//case 0: // unused (reserved)
|
||||
// GameRender::DestroyOverlaySurface(winType);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
namespace sfall
|
||||
{
|
||||
|
||||
static void __fastcall sf_GNW_win_refresh(fo::Window* win, RECT* updateRect, BYTE* toBuffer);
|
||||
|
||||
class OverlaySurface
|
||||
{
|
||||
private:
|
||||
@@ -34,12 +36,12 @@ private:
|
||||
BYTE* surface = nullptr;
|
||||
|
||||
public:
|
||||
//long winType = -1;
|
||||
long winType = -1;
|
||||
|
||||
BYTE* Surface() { return surface; }
|
||||
|
||||
void CreateSurface(fo::Window* win, long winType) {
|
||||
//this->winType = winType;
|
||||
this->winType = winType;
|
||||
this->surfWidth = win->width;
|
||||
this->size = win->height * win->width;
|
||||
|
||||
@@ -66,26 +68,28 @@ public:
|
||||
|
||||
size_t sizeD = rect.width >> 2;
|
||||
size_t sizeB = rect.width & 3;
|
||||
size_t stride = sizeD << 2;
|
||||
size_t strideD = sizeD << 2;
|
||||
size_t stride = surfWidth - rect.width;
|
||||
|
||||
long height = rect.height;
|
||||
while (height--) {
|
||||
if (sizeD) {
|
||||
__stosd((DWORD*)surf, 0, sizeD);
|
||||
surf += stride;
|
||||
surf += strideD;
|
||||
}
|
||||
if (sizeB) {
|
||||
__stosb(surf, 0, sizeB);
|
||||
surf += sizeB;
|
||||
}
|
||||
surf += stride;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/*void DestroySurface() {
|
||||
void DestroySurface() {
|
||||
delete[] surface;
|
||||
surface = nullptr;
|
||||
}*/
|
||||
}
|
||||
|
||||
~OverlaySurface() {
|
||||
delete[] surface;
|
||||
@@ -95,32 +99,45 @@ public:
|
||||
static long indexPosition = 0;
|
||||
|
||||
void GameRender::CreateOverlaySurface(fo::Window* win, long winType) {
|
||||
overlaySurfaces[indexPosition].CreateSurface(win, winType);
|
||||
win->randY = reinterpret_cast<long*>(&overlaySurfaces[indexPosition]);
|
||||
if (win->randY) return;
|
||||
if (overlaySurfaces[indexPosition].winType == winType) {
|
||||
overlaySurfaces[indexPosition].ClearSurface();
|
||||
} else {
|
||||
if (++indexPosition == 5) indexPosition = 0;
|
||||
};
|
||||
overlaySurfaces[indexPosition].CreateSurface(win, winType);
|
||||
}
|
||||
win->randY = reinterpret_cast<long*>(&overlaySurfaces[indexPosition]);
|
||||
}
|
||||
|
||||
BYTE* GameRender::GetOverlaySurface(fo::Window* win) {
|
||||
return reinterpret_cast<OverlaySurface*>(win->randY)->Surface();
|
||||
};
|
||||
}
|
||||
|
||||
void GameRender::ClearOverlay(fo::Window* win) {
|
||||
if (win->randY) reinterpret_cast<OverlaySurface*>(win->randY)->ClearSurface();
|
||||
};
|
||||
}
|
||||
|
||||
void GameRender::ClearOverlay(fo::Window* win, Rectangle &rect) {
|
||||
if (win->randY) reinterpret_cast<OverlaySurface*>(win->randY)->ClearSurface(rect);
|
||||
};
|
||||
if (win->randY) {
|
||||
reinterpret_cast<OverlaySurface*>(win->randY)->ClearSurface(rect);
|
||||
fo::BoundRect updateRect = rect;
|
||||
updateRect.x += win->rect.x;
|
||||
updateRect.y += win->rect.y;
|
||||
updateRect.offx += win->rect.x;
|
||||
updateRect.offy += win->rect.y;
|
||||
sf_GNW_win_refresh(win, reinterpret_cast<RECT*>(&updateRect), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*void GameRender::DestroyOverlaySurface(long winType) {
|
||||
for (size_t i = 0; i < 5; i++) {
|
||||
if (overlaySurfaces[i].winType == winType) {
|
||||
overlaySurfaces[i].DestroySurface();
|
||||
overlaySurfaces[i].winType = -1;
|
||||
//break;
|
||||
void GameRender::DestroyOverlaySurface(fo::Window* win) {
|
||||
if (win->randY) {
|
||||
auto overlay = reinterpret_cast<OverlaySurface*>(win->randY);
|
||||
win->randY = nullptr;
|
||||
overlay->winType = -1;
|
||||
overlay->DestroySurface();
|
||||
sf_GNW_win_refresh(win, &win->wRect, 0);
|
||||
}
|
||||
}
|
||||
};*/
|
||||
|
||||
static BYTE* GetBuffer() {
|
||||
return (BYTE*)*(DWORD*)FO_VAR_screen_buffer;
|
||||
@@ -202,7 +219,7 @@ static void __fastcall sf_GNW_win_refresh(fo::Window* win, RECT* updateRect, BYT
|
||||
__asm mov rects, eax;
|
||||
if (!rects) return;
|
||||
|
||||
rects->rect = { updateRect->left, updateRect->top, updateRect->right, updateRect->bottom };
|
||||
rects->rect = updateRect;
|
||||
rects->nextRect = nullptr;
|
||||
|
||||
/*
|
||||
@@ -312,17 +329,11 @@ void GameRender::init() {
|
||||
0x4D5D46, // win_init_ (create screen_buffer)
|
||||
0x4D75E6 // win_clip_ (remove _buffering checking)
|
||||
});
|
||||
SafeWrite8(0x42F869, fo::WinFlags::MoveOnTop | fo::WinFlags::OwnerFlag); // addWindow_ (remove Transparent flag)
|
||||
|
||||
// Custom implementation of the GNW_win_refresh function
|
||||
MakeJump(0x4D6FD9, GNW_win_refresh_hack, 1);
|
||||
// Replace _screendump_buf with _screen_buffer for creating screenshots
|
||||
SafeWriteBatch<DWORD>(FO_VAR_screen_buffer, {0x4C8FD1, 0x4C900D});
|
||||
|
||||
// Disable unused code for the RandX and RandY window structure fields (these fields can now be used for other purposes)
|
||||
SafeWrite32(0x4D630C, 0x9090C031); // xor eax, eax
|
||||
SafeWrite8(0x4D6310, 0x90);
|
||||
BlockCall(0x4D6319);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ public:
|
||||
static void init();
|
||||
|
||||
static void CreateOverlaySurface(fo::Window* win, long winType);
|
||||
// static void DestroyOverlaySurface(long winType);
|
||||
static void DestroyOverlaySurface(fo::Window* win);
|
||||
static void ClearOverlay(fo::Window* win);
|
||||
static void ClearOverlay(fo::Window* win, Rectangle &rect);
|
||||
static BYTE* GetOverlaySurface(fo::Window* win);
|
||||
|
||||
@@ -80,13 +80,6 @@ namespace sfall
|
||||
#define pushadc __asm push eax __asm push edx __asm push ecx
|
||||
#define popadc __asm pop ecx __asm pop edx __asm pop eax
|
||||
|
||||
struct Rectangle {
|
||||
long x, y, width, height;
|
||||
|
||||
long right() { return x + width; }
|
||||
long bottom() { return y + height; }
|
||||
};
|
||||
|
||||
// Gets the integer value from given INI file.
|
||||
int iniGetInt(const char* section, const char* setting, int defaultValue, const char* iniFile);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user