mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Merge pull request #531 from sfall-team/feature/inventory-slot-extensions
Added inventory/barter slot extensions
This commit is contained in:
@@ -133,6 +133,15 @@ WorldMapTravelMarkers=0
|
||||
;Set to 1 to display terrain types when hovering the cursor over the player's marker on the world map
|
||||
WorldMapTerrainInfo=0
|
||||
|
||||
;Set to 1 to enable tall trade/barter window with 4 item slots per table instead of 3
|
||||
;Requires the high-res mode with resolution of at least 640x528
|
||||
;Requires new frm files in art\intrface\: barter_e.frm (640x239), trade_e.frm (640x238) (included in sfall.dat)
|
||||
ExpandedBarter=0
|
||||
|
||||
;Set to 1 to enable tall inventory/loot/item select windows with 8 vertical slots instead of 6
|
||||
;Requires new frm files in art\intrface\: invbox_e.frm (499x467), loot_e.frm (537x464) and use_e.frm (292x464) files (included in sfall.dat)
|
||||
ExpandedInventory=0
|
||||
|
||||
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
[Sound]
|
||||
;Sets the number of allowed simultaneous sound effects
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -409,7 +409,7 @@ fo::GameObject* __fastcall MultiHexMoveIsBlocking(fo::GameObject* source, long d
|
||||
|
||||
// Returns the terrain type of the sub-tile at the specified coordinates on the world map
|
||||
long wmGetTerrainType(long xPos, long yPos) {
|
||||
long* terrainId;
|
||||
long* terrainId{};
|
||||
__asm {
|
||||
lea ebx, terrainId;
|
||||
mov edx, yPos;
|
||||
@@ -667,105 +667,5 @@ void RefreshGNW(bool skipOwner) {
|
||||
fo::var::setInt(FO_VAR_doing_refresh_all) = 0;
|
||||
}
|
||||
|
||||
//////////////////////////// UNLISTED FRM FUNCTIONS ////////////////////////////
|
||||
|
||||
static bool LoadFrmHeader(fo::UnlistedFrm *frmHeader, fo::DbFile* frmStream) {
|
||||
if (fo::func::db_freadInt(frmStream, &frmHeader->version) == -1)
|
||||
return false;
|
||||
else if (fo::func::db_freadShort(frmStream, &frmHeader->FPS) == -1)
|
||||
return false;
|
||||
else if (fo::func::db_freadShort(frmStream, &frmHeader->actionFrame) == -1)
|
||||
return false;
|
||||
else if (fo::func::db_freadShort(frmStream, &frmHeader->numFrames) == -1)
|
||||
return false;
|
||||
else if (fo::func::db_freadShortCount(frmStream, frmHeader->xCentreShift, 6) == -1)
|
||||
return false;
|
||||
else if (fo::func::db_freadShortCount(frmStream, frmHeader->yCentreShift, 6) == -1)
|
||||
return false;
|
||||
else if (fo::func::db_freadIntCount(frmStream, frmHeader->oriOffset, 6) == -1)
|
||||
return false;
|
||||
else if (fo::func::db_freadInt(frmStream, &frmHeader->frameAreaSize) == -1)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool LoadFrmFrame(fo::UnlistedFrm::Frame *frame, fo::DbFile* frmStream) {
|
||||
//FRMframe *frameHeader = (FRMframe*)frameMEM;
|
||||
//BYTE* frameBuff = frame + sizeof(FRMframe);
|
||||
|
||||
if (fo::func::db_freadShort(frmStream, &frame->width) == -1)
|
||||
return false;
|
||||
else if (fo::func::db_freadShort(frmStream, &frame->height) == -1)
|
||||
return false;
|
||||
else if (fo::func::db_freadInt(frmStream, &frame->size) == -1)
|
||||
return false;
|
||||
else if (fo::func::db_freadShort(frmStream, &frame->x) == -1)
|
||||
return false;
|
||||
else if (fo::func::db_freadShort(frmStream, &frame->y) == -1)
|
||||
return false;
|
||||
|
||||
frame->indexBuff = new BYTE[frame->size];
|
||||
if (fo::func::db_fread(frame->indexBuff, 1, frame->size, frmStream) != frame->size)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
fo::UnlistedFrm *LoadUnlistedFrm(char *frmName, unsigned int folderRef) {
|
||||
if (folderRef > fo::OBJ_TYPE_SKILLDEX) return nullptr;
|
||||
|
||||
const char *artfolder = fo::var::art[folderRef].path; // address of art type name
|
||||
char frmPath[MAX_PATH];
|
||||
|
||||
if (fo::var::use_language) {
|
||||
sprintf_s(frmPath, MAX_PATH, "art\\%s\\%s\\%s", (const char*)fo::var::language, artfolder, frmName);
|
||||
} else {
|
||||
sprintf_s(frmPath, MAX_PATH, "art\\%s\\%s", artfolder, frmName);
|
||||
}
|
||||
|
||||
fo::UnlistedFrm *frm = new fo::UnlistedFrm;
|
||||
|
||||
auto frmStream = fo::func::db_fopen(frmPath, "rb");
|
||||
|
||||
if (!frmStream && fo::var::use_language) {
|
||||
sprintf_s(frmPath, MAX_PATH, "art\\%s\\%s", artfolder, frmName);
|
||||
frmStream = fo::func::db_fopen(frmPath, "rb");
|
||||
}
|
||||
|
||||
if (frmStream != nullptr) {
|
||||
if (!LoadFrmHeader(frm, frmStream)) {
|
||||
fo::func::db_fclose(frmStream);
|
||||
delete frm;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DWORD oriOffset_1st = frm->oriOffset[0];
|
||||
DWORD oriOffset_new = 0;
|
||||
frm->frames = new fo::UnlistedFrm::Frame[6 * frm->numFrames];
|
||||
for (int ori = 0; ori < 6; ori++) {
|
||||
if (ori == 0 || frm->oriOffset[ori] != oriOffset_1st) {
|
||||
frm->oriOffset[ori] = oriOffset_new;
|
||||
for (int fNum = 0; fNum < frm->numFrames; fNum++) {
|
||||
if (!LoadFrmFrame(&frm->frames[oriOffset_new + fNum], frmStream)) {
|
||||
fo::func::db_fclose(frmStream);
|
||||
delete frm;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
oriOffset_new += frm->numFrames;
|
||||
} else {
|
||||
frm->oriOffset[ori] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
fo::func::db_fclose(frmStream);
|
||||
} else {
|
||||
delete frm;
|
||||
return nullptr;
|
||||
}
|
||||
return frm;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,20 @@ namespace fo
|
||||
namespace util
|
||||
{
|
||||
|
||||
// To safely unlock cache entries after using art_ptr_lock and similar functions
|
||||
struct ArtCacheLock {
|
||||
DWORD entryPtr = 0;
|
||||
|
||||
ArtCacheLock() { }
|
||||
ArtCacheLock(DWORD _lock) : entryPtr(_lock) { }
|
||||
~ArtCacheLock() {
|
||||
if (entryPtr != 0) {
|
||||
fo::func::art_ptr_unlock(entryPtr);
|
||||
entryPtr = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
__inline void DisplayPrint(const std::string& str) {
|
||||
fo::func::display_print(str.c_str());
|
||||
}
|
||||
@@ -191,7 +205,5 @@ void RedrawObject(fo::GameObject* obj);
|
||||
// Redraws all windows
|
||||
void RefreshGNW(bool skipOwner = false);
|
||||
|
||||
fo::UnlistedFrm *LoadUnlistedFrm(char *frmName, unsigned int folderRef);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -927,4 +927,31 @@ enum DialogOutFlags : long
|
||||
DIALOGOUT_CLEAN = 0x20 // no buttons
|
||||
};
|
||||
|
||||
enum InventoryWindowType : unsigned long
|
||||
{
|
||||
// Normal inventory window with quick character sheet.
|
||||
INVENTORY_WINDOW_TYPE_NORMAL,
|
||||
|
||||
// Narrow inventory window with just an item scroller that's shown when
|
||||
// a "Use item on" is selected from context menu.
|
||||
INVENTORY_WINDOW_TYPE_USE_ITEM_ON,
|
||||
|
||||
// Looting/strealing interface.
|
||||
INVENTORY_WINDOW_TYPE_LOOT,
|
||||
|
||||
// Barter interface.
|
||||
INVENTORY_WINDOW_TYPE_TRADE,
|
||||
|
||||
// Supplementary "Move items" window. Used to set quantity of items when
|
||||
// moving items between inventories.
|
||||
INVENTORY_WINDOW_TYPE_MOVE_ITEMS,
|
||||
|
||||
// Supplementary "Set timer" window. Internally it's implemented as "Move
|
||||
// items" window but with timer overlay and slightly different adjustment
|
||||
// mechanics.
|
||||
INVENTORY_WINDOW_TYPE_SET_TIMER,
|
||||
|
||||
INVENTORY_WINDOW_TYPE_COUNT,
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -29,8 +29,8 @@ namespace sfall
|
||||
struct Rectangle {
|
||||
long x, y, width, height;
|
||||
|
||||
long right() { return x + (width - 1); }
|
||||
long bottom() { return y + (height - 1); }
|
||||
long right() const { return x + (width - 1); }
|
||||
long bottom() const { return y + (height - 1); }
|
||||
};
|
||||
|
||||
}
|
||||
@@ -208,25 +208,25 @@ struct GameObject {
|
||||
long rads;
|
||||
long poison;
|
||||
|
||||
inline bool IsDead() {
|
||||
inline bool IsDead() const {
|
||||
return ((damageFlags & DamageFlag::DAM_DEAD) != 0);
|
||||
}
|
||||
inline bool IsNotDead() {
|
||||
inline bool IsNotDead() const {
|
||||
return ((damageFlags & DamageFlag::DAM_DEAD) == 0);
|
||||
}
|
||||
inline bool IsActive() {
|
||||
inline bool IsActive() const {
|
||||
return ((damageFlags & (DamageFlag::DAM_KNOCKED_OUT | DamageFlag::DAM_LOSE_TURN)) == 0);
|
||||
}
|
||||
inline bool IsNotActive() {
|
||||
inline bool IsNotActive() const {
|
||||
return ((damageFlags & (DamageFlag::DAM_KNOCKED_OUT | DamageFlag::DAM_LOSE_TURN)) != 0);
|
||||
}
|
||||
inline bool IsActiveNotDead() {
|
||||
inline bool IsActiveNotDead() const {
|
||||
return ((damageFlags & (DamageFlag::DAM_DEAD | DamageFlag::DAM_KNOCKED_OUT | DamageFlag::DAM_LOSE_TURN)) == 0);
|
||||
}
|
||||
inline bool IsNotActiveOrDead() {
|
||||
inline bool IsNotActiveOrDead() const {
|
||||
return ((damageFlags & (DamageFlag::DAM_DEAD | DamageFlag::DAM_KNOCKED_OUT | DamageFlag::DAM_LOSE_TURN)) != 0);
|
||||
}
|
||||
inline bool IsFleeing() {
|
||||
inline bool IsFleeing() const {
|
||||
return ((combatState & CombatStateFlag::InFlee) != 0);
|
||||
}
|
||||
|
||||
@@ -255,23 +255,23 @@ struct GameObject {
|
||||
GameObject* owner; // not saved
|
||||
long scriptIndex;
|
||||
|
||||
inline char Type() {
|
||||
inline char Type() const {
|
||||
return (protoId >> 24);
|
||||
}
|
||||
inline char TypeFid() {
|
||||
inline char TypeFid() const {
|
||||
return ((artFid >> 24) & 0x0F);
|
||||
}
|
||||
|
||||
inline bool IsCritter() {
|
||||
inline bool IsCritter() const {
|
||||
return (Type() == fo::ObjType::OBJ_TYPE_CRITTER);
|
||||
}
|
||||
inline bool IsNotCritter() {
|
||||
inline bool IsNotCritter() const {
|
||||
return (Type() != fo::ObjType::OBJ_TYPE_CRITTER);
|
||||
}
|
||||
inline bool IsItem() {
|
||||
inline bool IsItem() const {
|
||||
return (Type() == fo::ObjType::OBJ_TYPE_ITEM);
|
||||
}
|
||||
inline bool IsNotItem() {
|
||||
inline bool IsNotItem() const {
|
||||
return (Type() != fo::ObjType::OBJ_TYPE_ITEM);
|
||||
}
|
||||
};
|
||||
@@ -498,58 +498,6 @@ struct TileFrmFile : public FrmHeaderData {
|
||||
|
||||
static_assert(sizeof(TileFrmFile) == 2954, "Incorrect TileFrmFile definition.");
|
||||
|
||||
// structures for loading unlisted frms
|
||||
struct UnlistedFrm {
|
||||
DWORD version;
|
||||
WORD FPS;
|
||||
WORD actionFrame;
|
||||
WORD numFrames;
|
||||
WORD xCentreShift[6];
|
||||
WORD yCentreShift[6];
|
||||
DWORD oriOffset[6];
|
||||
DWORD frameAreaSize;
|
||||
|
||||
struct Frame {
|
||||
WORD width;
|
||||
WORD height;
|
||||
DWORD size;
|
||||
WORD x;
|
||||
WORD y;
|
||||
BYTE *indexBuff;
|
||||
|
||||
Frame() {
|
||||
width = 0;
|
||||
height = 0;
|
||||
size = 0;
|
||||
x = 0;
|
||||
y = 0;
|
||||
indexBuff = nullptr;
|
||||
}
|
||||
~Frame() {
|
||||
if (indexBuff != nullptr)
|
||||
delete[] indexBuff;
|
||||
}
|
||||
} *frames;
|
||||
|
||||
UnlistedFrm() {
|
||||
version = 0;
|
||||
FPS = 0;
|
||||
actionFrame = 0;
|
||||
numFrames = 0;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
xCentreShift[i] = 0;
|
||||
yCentreShift[i] = 0;
|
||||
oriOffset[i] = 0;
|
||||
}
|
||||
frameAreaSize = 0;
|
||||
frames = nullptr;
|
||||
}
|
||||
|
||||
~UnlistedFrm() {
|
||||
if (frames != nullptr) delete[] frames;
|
||||
}
|
||||
};
|
||||
|
||||
//for holding a message
|
||||
struct MessageNode {
|
||||
long number;
|
||||
|
||||
@@ -169,6 +169,7 @@
|
||||
#define FO_VAR_intface_full_width 0x56FB4C
|
||||
#define FO_VAR_intfaceEnabled 0x518F10
|
||||
#define FO_VAR_intotal 0x43E95C
|
||||
#define FO_VAR_inven_cur_disp 0x519054
|
||||
#define FO_VAR_inven_dude 0x519058
|
||||
#define FO_VAR_inven_pid 0x51905C
|
||||
#define FO_VAR_inven_scroll_dn_bid 0x5190E8
|
||||
|
||||
@@ -18,6 +18,7 @@ VAR_(BlueColor, BYTE)
|
||||
VAR_(bottom_line, DWORD)
|
||||
VAR_(btable, DWORD)
|
||||
VAR_(btncnt, DWORD)
|
||||
VAR_(buf_length_2, long)
|
||||
VARD(cap, fo::AIcap) // dynamic array
|
||||
VAR_(carCurrentArea, DWORD)
|
||||
VAR_(carGasAmount, long) // from 0 to 80000
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "..\main.h"
|
||||
#include "..\FalloutEngine\Fallout2.h"
|
||||
#include "..\Modules\ExtraArt.h"
|
||||
#include "..\Modules\LoadGameHook.h"
|
||||
|
||||
#include "Init.h"
|
||||
@@ -22,7 +23,7 @@ namespace sf = sfall;
|
||||
static const long width = 640; // art
|
||||
static long scr_width = 639;
|
||||
|
||||
static fo::UnlistedFrm* altDialogArt;
|
||||
static fo::FrmFile* altDialogArt;
|
||||
|
||||
bool Dialog::DIALOG_SCRN_ART_FIX = true;
|
||||
bool Dialog::DIALOG_SCRN_BACKGROUND = false;
|
||||
@@ -172,20 +173,16 @@ 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);
|
||||
altDialogArt = sf::LoadUnlistedFrmCached("HR_ALLTLK.frm", fo::ArtType::OBJ_TYPE_INTRFACE);
|
||||
}
|
||||
if (altDialogArt) {
|
||||
src = altDialogArt->frames->indexBuff;
|
||||
srcWidth = altDialogArt->frames->width;
|
||||
src = altDialogArt->frameData[0].data;
|
||||
srcWidth = altDialogArt->frameData[0].width;
|
||||
}
|
||||
fo::func::buf_to_buf(src, w, h, srcWidth, dst, dstWidth);
|
||||
}
|
||||
|
||||
static void UnloadDialogArt() {
|
||||
if (altDialogArt) {
|
||||
delete altDialogArt;
|
||||
altDialogArt = nullptr;
|
||||
}
|
||||
loadAltDialogArt = false;
|
||||
}
|
||||
|
||||
@@ -273,7 +270,7 @@ void Dialog::init() {
|
||||
fo::var::backgrndRects[i].offy += 5;
|
||||
}
|
||||
|
||||
sf::LoadGameHook::OnGameExit() += UnloadDialogArt;
|
||||
sf::LoadGameHook::OnGameReset() += UnloadDialogArt;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+15
-19
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "..\main.h"
|
||||
#include "..\FalloutEngine\Fallout2.h"
|
||||
#include "..\Modules\ExtraArt.h"
|
||||
#include "..\Modules\LoadGameHook.h"
|
||||
|
||||
#include "Init.h"
|
||||
@@ -45,22 +46,20 @@ static class Panels {
|
||||
long rightBarID;
|
||||
|
||||
void LoadFRMImage(char* name, long winId) {
|
||||
auto* frm = fo::util::LoadUnlistedFrm(name, fo::ArtType::OBJ_TYPE_INTRFACE);
|
||||
if (!frm) return;
|
||||
fo::FrmFile* frm = sf::LoadUnlistedFrmCached(name, fo::ArtType::OBJ_TYPE_INTRFACE);
|
||||
if (frm == nullptr) return;
|
||||
|
||||
fo::Window* win = fo::func::GNW_find(winId);
|
||||
|
||||
long width = win->width;
|
||||
if (width > frm->frames->width) width = frm->frames->width;
|
||||
BYTE* scr = frm->frames->indexBuff;
|
||||
if (width > frm->frameData[0].width) width = frm->frameData[0].width;
|
||||
BYTE* scr = frm->frameData[0].data;
|
||||
|
||||
// set the position to the right side
|
||||
if (!IFaceBar::IFACE_BAR_SIDES_ORI && win->wRect.left <= 0) scr += (frm->frames->width - win->width);
|
||||
if (IFaceBar::IFACE_BAR_SIDES_ORI && win->wRect.left > xPosition) scr += (frm->frames->width - win->width);
|
||||
if (!IFaceBar::IFACE_BAR_SIDES_ORI && win->wRect.left <= 0) scr += (frm->frameData[0].width - win->width);
|
||||
if (IFaceBar::IFACE_BAR_SIDES_ORI && win->wRect.left > xPosition) scr += (frm->frameData[0].width - win->width);
|
||||
|
||||
fo::func::cscale(scr, width, frm->frames->height, frm->frames->width, win->surface, win->width, win->height, win->width);
|
||||
|
||||
delete frm;
|
||||
fo::func::cscale(scr, width, frm->frameData[0].height, frm->frameData[0].width, win->surface, win->width, win->height, win->width);
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -205,24 +204,21 @@ static long __cdecl InterfaceArt(BYTE* scr, long w, long h, long srcWidth, BYTE*
|
||||
char file[33];
|
||||
std::sprintf(file, "HR_IFACE_%i%s.frm", IFaceBar::IFACE_BAR_WIDTH, ((expandAPBar) ? "E" : ""));
|
||||
|
||||
auto* frm = fo::util::LoadUnlistedFrm(file, fo::ArtType::OBJ_TYPE_INTRFACE);
|
||||
if (frm && frm->frames->width == IFaceBar::IFACE_BAR_WIDTH) {
|
||||
h = frm->frames->height;
|
||||
fo::FrmFile* frm = sf::LoadUnlistedFrmCached(file, fo::ArtType::OBJ_TYPE_INTRFACE);
|
||||
if (frm != nullptr && frm->frameData[0].width == IFaceBar::IFACE_BAR_WIDTH) {
|
||||
h = frm->frameData[0].height;
|
||||
if (h > 100) h = 100;
|
||||
|
||||
fo::func::buf_to_buf(frm->frames->indexBuff, frm->frames->width, h, frm->frames->width, dst, IFaceBar::IFACE_BAR_WIDTH);
|
||||
|
||||
delete frm;
|
||||
fo::func::buf_to_buf(frm->frameData[0].data, frm->frameData[0].width, h, frm->frameData[0].width, dst, IFaceBar::IFACE_BAR_WIDTH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// no required file, use the default one provided by HRP
|
||||
if (!frm) frm = fo::util::LoadUnlistedFrm(((expandAPBar) ? "HR_IFACE_800E.frm" : "HR_IFACE_800.frm"), fo::ArtType::OBJ_TYPE_INTRFACE);
|
||||
if (frm == nullptr) frm = sf::LoadUnlistedFrmCached(((expandAPBar) ? "HR_IFACE_800E.frm" : "HR_IFACE_800.frm"), fo::ArtType::OBJ_TYPE_INTRFACE);
|
||||
|
||||
if (frm) {
|
||||
if (frm != nullptr) {
|
||||
// scale the 800px wide interface to the width of IFACE_BAR_WIDTH
|
||||
InterfaceArtScale(frm->frames->indexBuff, frm->frames->width, frm->frames->height, dst, h);
|
||||
delete frm;
|
||||
InterfaceArtScale(frm->frameData[0].data, frm->frameData[0].width, frm->frameData[0].height, dst, h);
|
||||
} else {
|
||||
// scale the vanilla interface to 640px wide (640-460=180)
|
||||
InterfaceArtScale(scr, w, h, dst, h);
|
||||
|
||||
@@ -24,7 +24,8 @@ static long __fastcall CreateWin(long height, long yPos, long xPos, long width,
|
||||
if (!setPosition[mode]) {
|
||||
setPosition[mode] = true;
|
||||
long x = (Setting::ScreenWidth() - width) / 2;
|
||||
long y = (fo::var::getInt(FO_VAR_buf_length_2) - height) / 2;
|
||||
long y = (fo::var::buf_length_2 - height) / 2;
|
||||
if (y < 0) y = 0;
|
||||
fo::var::iscr_data[mode].x = x;
|
||||
fo::var::iscr_data[mode].y = y;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user