Fixed and improved AllowLargeTiles option (#367)

Removed the unspent skill points limit.
This commit is contained in:
NovaRain
2021-04-18 20:17:24 +08:00
parent e9aa1f1762
commit 0731325585
12 changed files with 163 additions and 106 deletions
+5 -5
View File
@@ -121,7 +121,7 @@ OverrideMusicDir=1
UseScrollWheel=1
;The mouse Z position is divided by this modifier to calculate the number of inventory
;slots to scroll. My mouse moves 120 pixel in the z direction for one click of the mouse
;slots to scroll. My mouse moves 120 pixels in the z direction for one click of the mouse
;wheel, but this may vary depending on your mouse manufacturer and windows settings.
;Set to 0 to only ever scroll 1 click
ScrollMod=0
@@ -429,13 +429,13 @@ AIBestWeaponFix=0
;Set to 1 to fix NPCs not taking chem_primary_desire in AI.txt as drug use preference when using drugs in their inventory
;Set to 2 to allow NPCs to use only the drugs listed in chem_primary_desire and healing drugs (stimpaks and healing powder)
;Note: chem_primary_desire w/o fixes prevents the specified item PID from being consumed if all three PIDs in the list are the same
;Note: chem_primary_desire w/o fixes prevents the specified item PID from being consumed if all three values in the list are the same PID
;chem_primary_desire also works as a priority list of drug items the NPC will try to pick up in combat when they are on the ground
AIDrugUsePerfFix=0
;Allows the use of tiles over 80x36 in size. sfall will just split and resave them at startup
;Set to 1 to check all tiles on started (slow)
;Set to 2 if you provide a XLtiles.lst file in art\tiles\ containing a list of the tile IDs that need checking
;Allows the use of tiles over 80x36 in size. sfall will just split and resave them to art\tiles\zzz####.frm at startup
;Set to 1 to check all tiles on started (slow, but can also be useful for checking the correct size of your new tiles)
;Set to 2 if you provide a XLtiles.lst file in art\tiles\ containing a list of the tile indexes that need checking
AllowLargeTiles=0
;Set to 1 to boost the maximum number of tile FRMs from 4096 to 16383
+1 -1
View File
@@ -972,7 +972,7 @@ static bool LoadFrmFrame(UNLSTDfrm::Frame *frame, DbFile* frmStream) {
return false;
frame->indexBuff = new BYTE[frame->size];
if (fo_db_fread(frame->indexBuff, frame->size, 1, frmStream) != 1)
if (fo_db_fread(frame->indexBuff, 1, frame->size, frmStream) != frame->size)
return false;
return true;
+30 -27
View File
@@ -78,32 +78,6 @@ WRAP_WATCOM_FUNC1(long, critter_is_dead, TGameObj*, critter)
WRAP_WATCOM_FUNC1(const char*, critter_name, TGameObj*, critter) // Returns the name of the critter
WRAP_WATCOM_FUNC1(void, critter_pc_set_name, const char*, newName) // Change the name of playable character
WRAP_WATCOM_FUNC1(long, critterIsOverloaded, TGameObj*, critter)
/* Database functions */
WRAP_WATCOM_FUNC1(bool, db_access, const char*, fileName) // Checks if given file exists in DB
WRAP_WATCOM_FUNC1(long, db_fclose, DbFile*, file)
WRAP_WATCOM_FUNC2(DbFile*, db_fopen, const char*, path, const char*, mode)
WRAP_WATCOM_FUNC1(long, db_fgetc, DbFile*, file)
WRAP_WATCOM_FUNC3(char*, db_fgets, char*, buf, long, max_count, DbFile*, file)
WRAP_WATCOM_FUNC4(long, db_fread, void*, buf, long, elsize, long, count, DbFile*, file)
WRAP_WATCOM_FUNC3(long, db_fseek, DbFile*, file, long, pos, long, origin)
WRAP_WATCOM_FUNC2(void, db_free_file_list, char***, fileList, DWORD, arg2) // Destroys filelist array created by db_get_file_list
WRAP_WATCOM_FUNC2(long, db_freadByte, DbFile*, file, BYTE*, _out)
WRAP_WATCOM_FUNC2(long, db_freadShort, DbFile*, file, WORD*, _out)
WRAP_WATCOM_FUNC2(long, db_freadInt, DbFile*, file, DWORD*, _out)
WRAP_WATCOM_FUNC3(long, db_freadByteCount, DbFile*, file, BYTE*, cptr, long, count)
WRAP_WATCOM_FUNC3(long, db_freadShortCount, DbFile*, file, WORD*, dest, long, count)
WRAP_WATCOM_FUNC3(long, db_freadIntCount, DbFile*, file, DWORD*, dest, long, count)
WRAP_WATCOM_FUNC2(long, db_fwriteByte, DbFile*, file, long, value)
WRAP_WATCOM_FUNC2(long, db_fwriteInt, DbFile*, file, long, value)
WRAP_WATCOM_FUNC3(long, db_fwriteByteCount, DbFile*, file, const BYTE*, cptr, long, count)
WRAP_WATCOM_FUNC2(long, db_dir_entry, const char*, fileName, DWORD*, sizeOut) // Check fallout file and get file size (result 0 - file exists)
// Searches files in DB by given path/filename mask and stores result in fileList
// fileList is a pointer to a variable, that will be assigned with an address of an array of char* strings
WRAP_WATCOM_FUNC2(long, db_get_file_list, const char*, searchMask, char***, fileList) // Returns number of elements in *fileList
WRAP_WATCOM_FUNC2(long, db_init, const char*, path_dat, const char*, path_patches)
WRAP_WATCOM_FUNC1(void*, dbase_open, const char*, fileName)
WRAP_WATCOM_FUNC1(void, dbase_close, void*, dbPtr)
////////////////////////
WRAP_WATCOM_FUNC1(void, display_print, const char*, msg) // Displays message in main UI console window
WRAP_WATCOM_FUNC0(void, display_stats)
// Execute script proc by internal proc number (from script's proc table, basically a sequential number of a procedure as defined in code, starting from 1)
@@ -235,5 +209,34 @@ WRAP_WATCOM_FUNC2(void, win_draw_rect, DWORD, winRef, RECT*, rect)
WRAP_WATCOM_FUNC1(void, win_delete, DWORD, winRef)
WRAP_WATCOM_FUNC0(long, windowWidth)
WRAP_WATCOM_FUNC1(void, wmRefreshInterfaceOverlay, long, isRedraw)
/* Database functions */
WRAP_WATCOM_FUNC1(bool, db_access, const char*, fileName) // Checks if given file exists in DB
WRAP_WATCOM_FUNC1(long, db_fclose, DbFile*, file)
WRAP_WATCOM_FUNC2(DbFile*, db_fopen, const char*, path, const char*, mode)
//WRAP_WATCOM_FUNC1(long, db_fgetc, DbFile*, file)
WRAP_WATCOM_FUNC3(char*, db_fgets, char*, buf, long, max_count, DbFile*, file)
WRAP_WATCOM_FFUNC4(long, db_fread, void*, buf, long, elsize, long, count, DbFile*, file)
WRAP_WATCOM_FFUNC3(long, db_fseek, DbFile*, file, long, pos, long, origin)
WRAP_WATCOM_FUNC2(void, db_free_file_list, char***, fileList, DWORD, arg2) // Destroys filelist array created by db_get_file_list
WRAP_WATCOM_FUNC2(long, db_freadByte, DbFile*, file, BYTE*, _out)
WRAP_WATCOM_FUNC2(long, db_freadShort, DbFile*, file, WORD*, _out)
WRAP_WATCOM_FUNC2(long, db_freadInt, DbFile*, file, DWORD*, _out)
WRAP_WATCOM_FFUNC3(long, db_freadByteCount, DbFile*, file, BYTE*, cptr, long, count)
WRAP_WATCOM_FFUNC3(long, db_freadShortCount, DbFile*, file, WORD*, dest, long, count)
WRAP_WATCOM_FFUNC3(long, db_freadIntCount, DbFile*, file, DWORD*, dest, long, count)
//WRAP_WATCOM_FFUNC3(long, db_freadLongCount, DbFile*, file, DWORD*, dest, long, count)
WRAP_WATCOM_FUNC2(long, db_fwriteByte, DbFile*, file, long, value)
WRAP_WATCOM_FUNC2(long, db_fwriteInt, DbFile*, file, long, value)
WRAP_WATCOM_FFUNC3(long, db_fwriteByteCount, DbFile*, file, const BYTE*, cptr, long, count)
//WRAP_WATCOM_FFUNC3(long, db_fwriteLongCount, DbFile*, file, DWORD*, dest, long, count)
WRAP_WATCOM_FUNC2(long, db_dir_entry, const char*, fileName, DWORD*, sizeOut) // Check fallout file and get file size (result 0 - file exists)
// Searches files in DB by given path/filename mask and stores result in fileList
// fileList is a pointer to a variable, that will be assigned with an address of an array of char* strings
WRAP_WATCOM_FUNC2(long, db_get_file_list, const char*, searchMask, char***, fileList) // Returns number of elements in *fileList
WRAP_WATCOM_FUNC2(long, db_init, const char*, path_dat, const char*, path_patches)
WRAP_WATCOM_FUNC1(void*, dbase_open, const char*, fileName)
WRAP_WATCOM_FUNC1(void, dbase_close, void*, dbPtr)
WRAP_WATCOM_FUNC2(DbFile*, xfopen, const char*, fileName, const char*, flags)
WRAP_WATCOM_FUNC3(long, xfseek, DbFile*, file, long, fOffset, long, origin)
WRAP_WATCOM_FFUNC3(long, xfseek, DbFile*, file, long, fOffset, long, origin)
+2
View File
@@ -408,6 +408,8 @@ struct FrmFile { // sizeof 2954
BYTE pixels[80 * 36]; // for tiles FRM
};
FrmFile() {};
// Returns a pointer to the data of the frame in the direction
FrmFrameData* GetFrameData(long dir, long frame) {
BYTE* offsDirectionFrame = (BYTE*)&frameData;
+1 -1
View File
@@ -544,7 +544,7 @@ DWORD __stdcall FScopy(const char* path, const char* source) {
DWORD fsize;
sFile* file;
const char* mode = "r";
const char* mode = "rb"; // was 'r'
__asm {
mov eax, source;
mov edx, mode;
+1 -1
View File
@@ -20,8 +20,8 @@
#include "main.h"
#include "FalloutEngine.h"
#include "LoadGameHook.h"
#include "Utils.h"
#include "LoadGameHook.h"
#include "Worldmap.h"
long Interface_ActiveInterfaceWID() {
+3
View File
@@ -325,6 +325,9 @@ void Skills_Init() {
SafeWrite8(0x4ABC67, 0x89); // mov [esp + 0x54], eax
SafeWrite32(0x4ABC6B, 0x90909090);
// Remove the unspent skill points limit
SafeWrite8(0x43C2B9, CODETYPE_JumpShort); // UpdateLevel_
// Add an additional 'Energy Weapon' flag to the weapon flags (offset 0x0018)
// Weapon Flags:
// 0x00000400 - Energy Weapon (forces weapon to use Energy Weapons skill)
+107 -71
View File
@@ -21,7 +21,8 @@
#include "main.h"
#include "FalloutEngine.h"
#include "FileSystem.h"
#include "Utils.h"
//#include "FileSystem.h"
typedef int (__stdcall *functype)();
@@ -53,114 +54,141 @@ struct TilesData {
#pragma pack(pop)
struct OverrideEntry {
DWORD xtiles;
DWORD ytiles;
DWORD replacementid;
DWORD xTiles;
DWORD yTiles;
DWORD replacementID;
OverrideEntry(DWORD _xtiles, DWORD _ytiles, DWORD _repid)
: xtiles(_xtiles), ytiles(_ytiles), replacementid(_repid) {
OverrideEntry(DWORD xtiles, DWORD ytiles, DWORD repid)
: xTiles(xtiles), yTiles(ytiles), replacementID(repid) {
}
};
static OverrideEntry** overrides;
static OverrideEntry** overrides = nullptr;
static DWORD origTileCount = 0;
static DWORD tileMode;
static BYTE* mask;
static void CreateMask() {
// emulation of std::lroundf in C++11
static long lroundf(float x) {
if (x < 0)
return static_cast<long>(x - 0.5f);
else
return static_cast<long>(x + 0.5f);
}
static bool LoadMask() {
DbFile* file = fo_db_fopen("art\\tiles\\gridmask.frm", "rb"); // same as grid000.frm from HRP
if (!file) {
dlogr("AllowLargeTiles: Unable to open art\\tiles\\gridmask.frm file.", DL_INIT);
return false;
}
mask = new BYTE[80 * 36];
DbFile* file = fo_db_fopen("art\\tiles\\grid000.frm", "r");
fo_db_fseek(file, 0x4A, 0);
fo_db_fseek(file, 0x4A, SEEK_SET);
fo_db_freadByteCount(file, mask, 80 * 36);
fo_db_fclose(file);
return true;
}
static WORD ByteSwapW(WORD w) {
return ((w & 0xFF) << 8) | ((w & 0xFF00) >> 8);
}
static int __stdcall ProcessTile(sArt* tiles, int tile, int listPos) {
char buf[32] = "art\\tiles\\";
strncpy_s(&buf[10], 22, &tiles->names[13 * tile], _TRUNCATE);
static DWORD ByteSwapD(DWORD w) {
return ((w & 0xFF) << 24) | ((w & 0xFF00) << 8) | ((w & 0xFF0000) >> 8) | ((w & 0xFF000000) >> 24);
}
DbFile* artFile = fo_db_fopen(buf, "rb");
if (!artFile) return 0;
static int ProcessTile(sArt* tiles, int tile, int listpos) {
char buf[32];
//sprintf_s(buf, "art\\tiles\\%s", &tiles->names[13*tile]);
strcpy_s(buf, "art\\tiles\\");
strcat_s(buf, &tiles->names[13 * tile]);
fo_db_fseek(artFile, 0x3E, SEEK_SET); // frameData
DbFile* art = fo_db_fopen(buf, "r");
if (!art) return 0;
fo_db_fseek(art, 0x3E, 0);
WORD width;
fo_db_freadShort(art, &width); //80;
if (width == 80) {
fo_db_fclose(art);
fo_db_freadShort(artFile, &width);
if (width < 80) goto exit;
WORD height;
fo_db_freadShort(artFile, &height);
if (height < 36) goto exit;
float newWidth = (float)(width - (width % 8));
float newHeight = (float)(height - (height % 12));
// Number of tiles horizontally and vertically
// the calculation is unstable if the large tile is not proportional to the size of 80x36 (aspect ratio)
int xSize = lroundf(((newWidth / 32.0f) - (newHeight / 24.0f)) - 0.01f);
int ySize = lroundf(((newHeight / 16.0f) - (newWidth / 64.0f)) - 0.01f);
if (xSize <= 0 || ySize <= 0) goto exit;
long bytes = width * height;
BYTE* pixelData = new BYTE[bytes];
// Read pixels data
if (fo_db_fseek(artFile, 0x4A, SEEK_SET) ||
fo_db_fread(pixelData, 1, bytes, artFile) != bytes)
{
delete[] pixelData;
exit:
fo_db_fclose(artFile);
return 0;
}
WORD height;
fo_db_freadShort(art, &height); //36
fo_db_fseek(art, 0x4A, 0);
BYTE* pixeldata = new BYTE[width * height];
fo_db_freadByteCount(art, pixeldata, width * height);
DWORD listid = listpos - tiles->total;
float newwidth = (float)(width - width % 8);
float newheight = (float)(height - height % 12);
int xsize = (int)floor(newwidth / 32.0f - newheight / 24.0f);
int ysize = (int)floor(newheight / 16.0f - newwidth / 64.0f);
for (int y = 0; y < ysize; y++) {
for (int x = 0; x < xsize; x++) {
FrmFile frame;
fo_db_fseek(art, 0, 0);
fo_db_freadByteCount(art, (BYTE*)&frame, 0x4a);
frame.height = ByteSwapW(36);
frame.width = ByteSwapW(80);
frame.frameSize = ByteSwapD(80 * 36);
frame.frameAreaSize = ByteSwapD(80 * 36 + 12);
int xoffset = x * 48 + (ysize - (y + 1)) * 32;
int yoffset = height - (36 + x * 12 + y * 24);
for (int y2 = 0; y2 < 36; y2++) {
for (int x2 = 0; x2 < 80; x2++) {
if (mask[y2 * 80 + x2]) {
frame.pixels[y2 * 80 + x2] = pixeldata[(yoffset + y2) * width + xoffset + x2];
long listID = listPos - tiles->total;
FrmFile frame;
fo_db_fseek(artFile, 0, SEEK_SET);
fo_db_freadByteCount(artFile, (BYTE*)&frame, 74);
frame.height = ByteSwapW(36);
frame.width = ByteSwapW(80);
frame.frameSize = ByteSwapD(80 * 36);
frame.frameAreaSize = ByteSwapD(80 * 36 + 12);
for (int y = 0; y < ySize; y++) {
for (int x = 0; x < xSize; x++) {
// offset relative to the top-left corner
int xOffset = x * 48 + (ySize - (y + 1)) * 32;
int yOffset = height - (36 + x * 12 + y * 24);
for (int pY = 0; pY < 36; pY++) {
for (int pX = 0; pX < 80; pX++) {
int point = (80 * pY) + pX;
if (mask[point]) {
frame.pixels[point] = pixelData[(width * (yOffset + pY)) + xOffset + pX];
} else {
frame.pixels[y2 * 80 + x2] = 0;
frame.pixels[point] = 0;
}
}
}
sprintf_s(buf, 32, "art\\tiles\\zzz%04d.frm", listid++);
sprintf_s(&buf[10], 22, "zzz%04d.frm", listID++);
//FScreateFromData(buf, &frame, sizeof(frame));
DbFile* file = fo_db_fopen(buf, "w");
DbFile* file = fo_db_fopen(buf, "wb");
fo_db_fwriteByteCount(file, (BYTE*)&frame, sizeof(frame));
fo_db_fclose(file);
}
}
overrides[tile] = new OverrideEntry(xsize, ysize, listpos);
fo_db_fclose(art);
delete[] pixeldata;
return xsize * ysize;
overrides[tile] = new OverrideEntry(xSize, ySize, listPos);
fo_db_fclose(artFile);
delete[] pixelData;
return xSize * ySize; // number of tiles added
}
static const functype art_init = (functype)art_init_;
static int __stdcall ArtInitHook() {
if (art_init()) return -1;
CreateMask();
if (!LoadMask()) return 0;
sArt* tiles = &ptr_art[4];
char buf[32];
DWORD listpos = tiles->total;
origTileCount = listpos;
overrides = new OverrideEntry*[listpos];
ZeroMemory(overrides, 4 * (listpos - 1));
long listpos = origTileCount = tiles->total;
overrides = new OverrideEntry*[listpos]();
if (tileMode == 2) {
DbFile* file = fo_db_fopen("art\\tiles\\xltiles.lst", "rt");
if (!file) return 0;
char buf[32];
DWORD id;
char* comment;
while (fo_db_fgets(buf, 31, file) > 0) {
if (comment = strchr(buf, ';')) *comment = 0;
id = atoi(buf);
@@ -172,7 +200,7 @@ static int __stdcall ArtInitHook() {
}
if (listpos != tiles->total) {
tiles->names = (char*)fo_mem_realloc(tiles->names, listpos * 13);
for (DWORD i = tiles->total; i < listpos; i++) {
for (long i = tiles->total; i < listpos; i++) {
sprintf_s(&tiles->names[i * 13], 12, "zzz%04d.frm", i - tiles->total);
}
tiles->total = listpos;
@@ -194,14 +222,15 @@ static void __declspec(naked) iso_init_hook() {
}
static long __fastcall SquareLoadCheck(TilesData* data) {
if (!overrides) return 0;
for (DWORD y = 0; y < 100; y++) {
for (DWORD x = 0; x < 100; x++) {
for (DWORD z = 0; z < 2; z++) {
DWORD tile = data[y * 100 + x].tile[z];
if (tile > 1 && tile < origTileCount && overrides[tile]) {
DWORD newtile = overrides[tile]->replacementid - 1;
for (DWORD y2 = 0; y2 < overrides[tile]->ytiles; y2++) {
for (DWORD x2 = 0; x2 < overrides[tile]->xtiles; x2++) {
DWORD newtile = overrides[tile]->replacementID - 1;
for (DWORD y2 = 0; y2 < overrides[tile]->yTiles; y2++) {
for (DWORD x2 = 0; x2 < overrides[tile]->xTiles; x2++) {
newtile++;
if (x - x2 < 0 || y - y2 < 0) continue;
data[(y - y2) * 100 + x - x2].tile[z] = (short)newtile;
@@ -277,3 +306,10 @@ void Tiles_Init() {
dlogr(" Done", DL_INIT);
}
}
void Tiles_Exit() {
if (overrides) {
for (size_t i = 0; i < origTileCount; i++) delete overrides[i]; // free OverrideEntry
delete[] overrides;
}
}
+1
View File
@@ -19,3 +19,4 @@
#pragma once
void Tiles_Init();
void Tiles_Exit();
+8
View File
@@ -3,6 +3,14 @@
#include "Utils.h"
WORD ByteSwapW(WORD w) {
return ((w & 0xFF) << 8) | ((w & 0xFF00) >> 8);
}
DWORD ByteSwapD(DWORD dw) {
return ((dw & 0xFF) << 24) | ((dw & 0xFF00) << 8) | ((dw & 0xFF0000) >> 8) | ((dw & 0xFF000000) >> 24);
}
std::vector<std::string> split(const std::string &s, char delim) {
std::vector<std::string> elems;
split(s, delim, std::back_inserter(elems));
+3
View File
@@ -18,6 +18,9 @@ void split(const std::string &s, char delim, T result, size_t limit = -1) {
}
}
WORD ByteSwapW(WORD w);
DWORD ByteSwapD(DWORD dw);
// Splits a string by given delimiter
std::vector<std::string> split(const std::string &s, char delim);
+1
View File
@@ -238,6 +238,7 @@ static void __stdcall OnExit() {
Interface_Exit();
SpeedPatch_Exit();
Skills_Exit();
Tiles_Exit();
Sound_Exit();
Reputations_Exit();
Console_Exit();