mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
ActionPointsBar: language agnostic FRM
- Use one small FRM with just AP bar background instead of having 2 big FRMs per language (for HRP and not) - It works by simply writing into iface window buffer right after it was written with iface.frm contents - Uses position relative to right edge of the iface panel
This commit is contained in:
+1
-1
@@ -110,7 +110,7 @@ FadeMultiplier=100
|
|||||||
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||||
[Interface]
|
[Interface]
|
||||||
;Set to 1 to expand the number of action points displayed on the interface bar
|
;Set to 1 to expand the number of action points displayed on the interface bar
|
||||||
;Requires new IFACE_E.frm and HR_IFACE_<res>E.frm files in art\intrface\ (included in sfall.dat) to display correctly
|
;Requires new iface_apbar_e.frm in art\intrface\ (included in sfall.dat) to display correctly
|
||||||
;The minimum supported version of the hi-res patch is v4.1.8
|
;The minimum supported version of the hi-res patch is v4.1.8
|
||||||
ActionPointsBar=0
|
ActionPointsBar=0
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
@@ -165,6 +165,7 @@
|
|||||||
#define FO_VAR_idle_func 0x51E234
|
#define FO_VAR_idle_func 0x51E234
|
||||||
#define FO_VAR_In_WorldMap 0x672E1C
|
#define FO_VAR_In_WorldMap 0x672E1C
|
||||||
#define FO_VAR_info_line 0x5707D0
|
#define FO_VAR_info_line 0x5707D0
|
||||||
|
#define FO_VAR_interfaceBuffer 0x59D3F4
|
||||||
#define FO_VAR_interfaceWindow 0x519024
|
#define FO_VAR_interfaceWindow 0x519024
|
||||||
#define FO_VAR_intface_full_width 0x56FB4C
|
#define FO_VAR_intface_full_width 0x56FB4C
|
||||||
#define FO_VAR_intfaceEnabled 0x518F10
|
#define FO_VAR_intfaceEnabled 0x518F10
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ VAR_(i_worn, fo::GameObject*)
|
|||||||
VAR_(idle_func, void*)
|
VAR_(idle_func, void*)
|
||||||
VAR_(In_WorldMap, DWORD) // moving on WorldMap
|
VAR_(In_WorldMap, DWORD) // moving on WorldMap
|
||||||
VAR_(info_line, DWORD)
|
VAR_(info_line, DWORD)
|
||||||
|
VAR_(interfaceBuffer, BYTE*)
|
||||||
VARC(interfaceWindow, DWORD)
|
VARC(interfaceWindow, DWORD)
|
||||||
VAR_(intfaceEnabled, DWORD)
|
VAR_(intfaceEnabled, DWORD)
|
||||||
VAR_(intotal, DWORD)
|
VAR_(intotal, DWORD)
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ static long yPosition;
|
|||||||
static long xOffset;
|
static long xOffset;
|
||||||
static long xyOffsetCBtn;
|
static long xyOffsetCBtn;
|
||||||
static long xyOffsetAP;
|
static long xyOffsetAP;
|
||||||
static bool expandAPBar = false;
|
|
||||||
|
|
||||||
long IFaceBar::display_width = 0; // width of the area for text output
|
long IFaceBar::display_width = 0; // width of the area for text output
|
||||||
char* IFaceBar::display_string_buf = (char*)FO_VAR_display_string_buf;
|
char* IFaceBar::display_string_buf = (char*)FO_VAR_display_string_buf;
|
||||||
@@ -202,7 +201,7 @@ static long __cdecl InterfaceArt(BYTE* scr, long w, long h, long srcWidth, BYTE*
|
|||||||
fo::var::itemButtonRect.offx += xOffset;
|
fo::var::itemButtonRect.offx += xOffset;
|
||||||
|
|
||||||
char file[33];
|
char file[33];
|
||||||
std::sprintf(file, "HR_IFACE_%i%s.frm", IFaceBar::IFACE_BAR_WIDTH, ((expandAPBar) ? "E" : ""));
|
std::sprintf(file, "HR_IFACE_%i.frm", IFaceBar::IFACE_BAR_WIDTH);
|
||||||
|
|
||||||
fo::FrmFile* frm = sf::LoadUnlistedFrmCached(file, fo::ArtType::OBJ_TYPE_INTRFACE);
|
fo::FrmFile* frm = sf::LoadUnlistedFrmCached(file, fo::ArtType::OBJ_TYPE_INTRFACE);
|
||||||
if (frm != nullptr && frm->frameData[0].width == IFaceBar::IFACE_BAR_WIDTH) {
|
if (frm != nullptr && frm->frameData[0].width == IFaceBar::IFACE_BAR_WIDTH) {
|
||||||
@@ -214,7 +213,7 @@ static long __cdecl InterfaceArt(BYTE* scr, long w, long h, long srcWidth, BYTE*
|
|||||||
}
|
}
|
||||||
|
|
||||||
// no required file, use the default one provided by HRP
|
// no required file, use the default one provided by HRP
|
||||||
if (frm == nullptr) frm = sf::LoadUnlistedFrmCached(((expandAPBar) ? "HR_IFACE_800E.frm" : "HR_IFACE_800.frm"), fo::ArtType::OBJ_TYPE_INTRFACE);
|
if (frm == nullptr) frm = sf::LoadUnlistedFrmCached("HR_IFACE_800.frm", fo::ArtType::OBJ_TYPE_INTRFACE);
|
||||||
|
|
||||||
if (frm != nullptr) {
|
if (frm != nullptr) {
|
||||||
// scale the 800px wide interface to the width of IFACE_BAR_WIDTH
|
// scale the 800px wide interface to the width of IFACE_BAR_WIDTH
|
||||||
@@ -466,10 +465,6 @@ static void __declspec(naked) intface_update_ammo_lights_hook() {
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void IFaceBar::SetExpandAPBar() {
|
|
||||||
expandAPBar = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IFaceBar::Hide() {
|
void IFaceBar::Hide() {
|
||||||
InterfaceHide(fo::var::getInt(FO_VAR_interfaceWindow));
|
InterfaceHide(fo::var::getInt(FO_VAR_interfaceWindow));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,8 +25,6 @@ public:
|
|||||||
static long display_width;
|
static long display_width;
|
||||||
static char* display_string_buf;
|
static char* display_string_buf;
|
||||||
|
|
||||||
static void SetExpandAPBar();
|
|
||||||
|
|
||||||
static void Hide();
|
static void Hide();
|
||||||
static void Show();
|
static void Show();
|
||||||
};
|
};
|
||||||
|
|||||||
+49
-17
@@ -41,15 +41,25 @@ static PcxFile LoadPcxFile(const char* file) {
|
|||||||
return pcx;
|
return pcx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static fo::FrmFile* LoadFrmFile(const char* file) {
|
||||||
|
fo::FrmFile* frmPtr = nullptr;
|
||||||
|
if (fo::func::load_frame(file, &frmPtr)) {
|
||||||
|
frmPtr = nullptr;
|
||||||
|
}
|
||||||
|
return frmPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnloadFrmFile(fo::FrmFile* frm) {
|
||||||
|
fo::func::mem_free(frm);
|
||||||
|
}
|
||||||
|
|
||||||
fo::FrmFile* LoadFrmFileCached(const char* file) {
|
fo::FrmFile* LoadFrmFileCached(const char* file) {
|
||||||
fo::FrmFile* frmPtr = nullptr;
|
fo::FrmFile* frmPtr = nullptr;
|
||||||
auto cacheHit = frmFileCache.find(file);
|
auto cacheHit = frmFileCache.find(file);
|
||||||
if (cacheHit != frmFileCache.end()) {
|
if (cacheHit != frmFileCache.end()) {
|
||||||
frmPtr = cacheHit->second;
|
frmPtr = cacheHit->second;
|
||||||
} else {
|
} else {
|
||||||
if (fo::func::load_frame(file, &frmPtr)) {
|
frmPtr = LoadFrmFile(file);
|
||||||
frmPtr = nullptr;
|
|
||||||
}
|
|
||||||
frmFileCache.emplace(file, frmPtr);
|
frmFileCache.emplace(file, frmPtr);
|
||||||
}
|
}
|
||||||
return frmPtr;
|
return frmPtr;
|
||||||
@@ -64,7 +74,6 @@ PcxFile LoadPcxFileCached(const char* file) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void GetUnlistedFrmPath(const char* frmName, unsigned int folderRef, bool useLanguage, char* pathBuf) {
|
static void GetUnlistedFrmPath(const char* frmName, unsigned int folderRef, bool useLanguage, char* pathBuf) {
|
||||||
|
|
||||||
const char* artfolder = fo::var::art[folderRef].path; // address of art type name
|
const char* artfolder = fo::var::art[folderRef].path; // address of art type name
|
||||||
if (useLanguage) {
|
if (useLanguage) {
|
||||||
sprintf_s(pathBuf, MAX_PATH, "art\\%s\\%s\\%s", (const char*)fo::var::language, artfolder, frmName);
|
sprintf_s(pathBuf, MAX_PATH, "art\\%s\\%s\\%s", (const char*)fo::var::language, artfolder, frmName);
|
||||||
@@ -73,10 +82,9 @@ static void GetUnlistedFrmPath(const char* frmName, unsigned int folderRef, bool
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UnlistedFrmExists(const char* frmName, unsigned int folderRef) {
|
static bool CheckUnlistedFrm(const char* frmName, unsigned int folderRef, char* frmPath) {
|
||||||
if (folderRef > fo::OBJ_TYPE_SKILLDEX) return nullptr;
|
if (folderRef > fo::OBJ_TYPE_SKILLDEX) return nullptr;
|
||||||
|
|
||||||
char frmPath[MAX_PATH];
|
|
||||||
GetUnlistedFrmPath(frmName, folderRef, fo::var::use_language != 0, frmPath);
|
GetUnlistedFrmPath(frmName, folderRef, fo::var::use_language != 0, frmPath);
|
||||||
|
|
||||||
bool exists = fo::func::db_access(frmPath);
|
bool exists = fo::func::db_access(frmPath);
|
||||||
@@ -87,19 +95,21 @@ bool UnlistedFrmExists(const char* frmName, unsigned int folderRef) {
|
|||||||
return exists;
|
return exists;
|
||||||
}
|
}
|
||||||
|
|
||||||
fo::FrmFile* LoadUnlistedFrmCached(const char* frmName, unsigned int folderRef) {
|
bool UnlistedFrmExists(const char* frmName, unsigned int folderRef) {
|
||||||
if (folderRef > fo::OBJ_TYPE_SKILLDEX) return nullptr;
|
|
||||||
|
|
||||||
char frmPath[MAX_PATH];
|
char frmPath[MAX_PATH];
|
||||||
|
return CheckUnlistedFrm(frmName, folderRef, frmPath);
|
||||||
|
}
|
||||||
|
|
||||||
GetUnlistedFrmPath(frmName, folderRef, fo::var::use_language != 0, frmPath);
|
fo::FrmFile* LoadUnlistedFrm(const char* frmName, unsigned int folderRef) {
|
||||||
|
char frmPath[MAX_PATH];
|
||||||
|
if (!CheckUnlistedFrm(frmName, folderRef, frmPath)) return nullptr;
|
||||||
|
return LoadFrmFile(frmPath);
|
||||||
|
}
|
||||||
|
|
||||||
fo::FrmFile* frm = LoadFrmFileCached(frmPath);
|
fo::FrmFile* LoadUnlistedFrmCached(const char* frmName, unsigned int folderRef) {
|
||||||
if (frm == nullptr && fo::var::use_language) {
|
char frmPath[MAX_PATH];
|
||||||
GetUnlistedFrmPath(frmName, folderRef, false, frmPath);
|
if (!CheckUnlistedFrm(frmName, folderRef, frmPath)) return nullptr;
|
||||||
frm = LoadFrmFileCached(frmPath);
|
return LoadFrmFileCached(frmPath);
|
||||||
}
|
|
||||||
return frm;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ClearInterfaceArtCache() {
|
static void ClearInterfaceArtCache() {
|
||||||
@@ -109,11 +119,33 @@ static void ClearInterfaceArtCache() {
|
|||||||
pcxFileCache.clear();
|
pcxFileCache.clear();
|
||||||
|
|
||||||
for (auto &pair : frmFileCache) {
|
for (auto &pair : frmFileCache) {
|
||||||
fo::func::mem_free(pair.second);
|
UnloadFrmFile(pair.second);
|
||||||
}
|
}
|
||||||
frmFileCache.clear();
|
frmFileCache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TempFrmHandle::TempFrmHandle(fo::FrmFile* frm) : _frm(frm) {
|
||||||
|
}
|
||||||
|
|
||||||
|
TempFrmHandle::TempFrmHandle(TempFrmHandle&& other) : _frm(other._frm) {
|
||||||
|
other._frm = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
TempFrmHandle::~TempFrmHandle() {
|
||||||
|
if (_frm == nullptr) return;
|
||||||
|
UnloadFrmFile(_frm);
|
||||||
|
_frm = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TempFrmHandle::IsValid() {
|
||||||
|
return _frm != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fo::FrmFile& TempFrmHandle::Frm() const {
|
||||||
|
assert(_frm != nullptr);
|
||||||
|
return *_frm;
|
||||||
|
}
|
||||||
|
|
||||||
void ExtraArt::init() {
|
void ExtraArt::init() {
|
||||||
LoadGameHook::OnGameReset() += []() {
|
LoadGameHook::OnGameReset() += []() {
|
||||||
ClearInterfaceArtCache();
|
ClearInterfaceArtCache();
|
||||||
|
|||||||
@@ -36,16 +36,33 @@ struct PcxFile {
|
|||||||
PcxFile() : pixelData(nullptr), width(0), height(0) {}
|
PcxFile() : pixelData(nullptr), width(0), height(0) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class TempFrmHandle {
|
||||||
|
public:
|
||||||
|
TempFrmHandle(fo::FrmFile* frm);
|
||||||
|
TempFrmHandle(const TempFrmHandle&) = delete;
|
||||||
|
TempFrmHandle(TempFrmHandle&&);
|
||||||
|
TempFrmHandle& operator=(TempFrmHandle) = delete;
|
||||||
|
~TempFrmHandle();
|
||||||
|
|
||||||
|
bool IsValid();
|
||||||
|
const fo::FrmFile& Frm() const;
|
||||||
|
private:
|
||||||
|
fo::FrmFile* _frm;
|
||||||
|
};
|
||||||
|
|
||||||
class ExtraArt : public Module {
|
class ExtraArt : public Module {
|
||||||
public:
|
public:
|
||||||
const char* name() { return "ExtraArt"; }
|
const char* name() { return "ExtraArt"; }
|
||||||
void init();
|
void init();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: more robust caching, similar to how art_ptr_lock works.
|
||||||
fo::FrmFile* LoadFrmFileCached(const char* file);
|
fo::FrmFile* LoadFrmFileCached(const char* file);
|
||||||
PcxFile LoadPcxFileCached(const char* file);
|
PcxFile LoadPcxFileCached(const char* file);
|
||||||
|
|
||||||
bool UnlistedFrmExists(const char* frmName, unsigned int folderRef);
|
bool UnlistedFrmExists(const char* frmName, unsigned int folderRef);
|
||||||
|
fo::FrmFile* LoadUnlistedFrm(const char* frmName, unsigned int folderRef);
|
||||||
fo::FrmFile* LoadUnlistedFrmCached(const char* file, unsigned int folderRef);
|
fo::FrmFile* LoadUnlistedFrmCached(const char* file, unsigned int folderRef);
|
||||||
|
void UnloadFrmFile(fo::FrmFile* frm);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-20
@@ -126,25 +126,29 @@ struct InterfaceCustomFrm {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static BYTE movePointBackground[16 * 9 * 5];
|
static BYTE movePointBackground[16 * 9 * 5];
|
||||||
static InterfaceCustomFrm ifaceFrm{ "IFACE_E.frm" };
|
|
||||||
|
|
||||||
static void* LoadIfaceFrm() {
|
static void DrawExtendedApBar() {
|
||||||
return ifaceFrm.LoadFrmData();
|
const char* const ifaceApBarFrm = "iface_apbar_e.frm"; // 183x13 at 266,10 (x = width - 374)
|
||||||
|
TempFrmHandle frmHandle{ LoadUnlistedFrm(ifaceApBarFrm, fo::ArtType::OBJ_TYPE_INTRFACE) };
|
||||||
|
if (!frmHandle.IsValid()) return;
|
||||||
|
|
||||||
|
DWORD ifaceWin = fo::var::interfaceWindow;
|
||||||
|
fo::Window* win = fo::func::GNW_find(ifaceWin);
|
||||||
|
if (win == nullptr) return;
|
||||||
|
|
||||||
|
constexpr int destOffsetRight = 374;
|
||||||
|
constexpr int destOffsetTop = 10;
|
||||||
|
const fo::FrmFrameData& srcFrame = frmHandle.Frm().frameData[0];
|
||||||
|
BYTE* dest = fo::var::interfaceBuffer + (win->width * (destOffsetTop + 1)) - destOffsetRight;
|
||||||
|
fo::func::buf_to_buf((BYTE*)srcFrame.data, srcFrame.width, srcFrame.height, srcFrame.width, dest, win->width);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __declspec(naked) intface_init_hook_lock() {
|
static void __declspec(naked) intface_init_hook_unlock_iface_frm() {
|
||||||
__asm {
|
__asm {
|
||||||
pushadc;
|
pushadc;
|
||||||
call LoadIfaceFrm;
|
call DrawExtendedApBar;
|
||||||
test eax, eax;
|
|
||||||
jz skip;
|
|
||||||
pop ecx;
|
|
||||||
add esp, 8;
|
|
||||||
mov dword ptr [ecx], 0;
|
|
||||||
retn;
|
|
||||||
skip:
|
|
||||||
popadc;
|
popadc;
|
||||||
jmp fo::funcoffs::art_ptr_lock_data_;
|
jmp fo::funcoffs::art_ptr_unlock_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,14 +179,10 @@ static void APBarRectPatch() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void ActionPointsBarPatch() {
|
static void ActionPointsBarPatch() {
|
||||||
HRP::IFaceBar::SetExpandAPBar();
|
|
||||||
|
|
||||||
dlog("Applying expanded action points bar patch.", DL_INIT);
|
dlog("Applying expanded action points bar patch.", DL_INIT);
|
||||||
if (HRP::Setting::ExternalEnabled()) {
|
if (HRP::Setting::ExternalEnabled()) {
|
||||||
// check valid data
|
// check valid data
|
||||||
if (HRP::Setting::VersionIsValid && !_stricmp((const char*)HRP::Setting::GetAddress(HRP_VAR_HR_IFACE_FRM_STR), "HR_IFACE_%i.frm")) {
|
if (!HRP::Setting::VersionIsValid) {
|
||||||
SafeWriteStr(HRP::Setting::GetAddress(HRP_VAR_HR_IFACE_FRM_STR + 11), "E.frm"); // patching HRP
|
|
||||||
} else {
|
|
||||||
dlogr(" Incorrect HRP version!", DL_INIT);
|
dlogr(" Incorrect HRP version!", DL_INIT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -190,13 +190,14 @@ static void ActionPointsBarPatch() {
|
|||||||
} else {
|
} else {
|
||||||
APBarRectPatch();
|
APBarRectPatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
// intface_init_
|
// intface_init_
|
||||||
SafeWriteBatch<DWORD>((DWORD)&movePointBackground, {0x45E343, 0x45EE3F});
|
SafeWriteBatch<DWORD>((DWORD)&movePointBackground, {0x45E343, 0x45EE3F});
|
||||||
// intface_update_move_points_
|
// intface_update_move_points_
|
||||||
SafeWriteBatch<BYTE>(16, {0x45EE55, 0x45EE7B, 0x45EE82, 0x45EE9C, 0x45EEA0});
|
SafeWriteBatch<BYTE>(16, {0x45EE55, 0x45EE7B, 0x45EE82, 0x45EE9C, 0x45EEA0});
|
||||||
SafeWriteBatch<DWORD>(9276 - (54 / 2), {0x45EE33, 0x45EEC8, 0x45EF16});
|
SafeWriteBatch<DWORD>(9276 - (54 / 2), {0x45EE33, 0x45EEC8, 0x45EF16});
|
||||||
|
|
||||||
HookCall(0x45D918, intface_init_hook_lock);
|
HookCall(0x45D962, intface_init_hook_unlock_iface_frm);
|
||||||
MakeCall(0x45E356, intface_init_hack);
|
MakeCall(0x45E356, intface_init_hack);
|
||||||
MakeJump(0x45EE38, intface_update_move_points_hack, 1);
|
MakeJump(0x45EE38, intface_update_move_points_hack, 1);
|
||||||
dlogr(" Done", DL_INIT);
|
dlogr(" Done", DL_INIT);
|
||||||
@@ -1412,7 +1413,6 @@ void Interface::init() {
|
|||||||
ExpandedInventoryPatch();
|
ExpandedInventoryPatch();
|
||||||
};
|
};
|
||||||
LoadGameHook::OnGameReset() += []() {
|
LoadGameHook::OnGameReset() += []() {
|
||||||
ifaceFrm.Reset();
|
|
||||||
barterTallFrm.Reset();
|
barterTallFrm.Reset();
|
||||||
tradeTallFrm.Reset();
|
tradeTallFrm.Reset();
|
||||||
for (size_t i = 0; i < inventoryTallFrms.size(); ++i) {
|
for (size_t i = 0; i < inventoryTallFrms.size(); ++i) {
|
||||||
|
|||||||
Reference in New Issue
Block a user