Added "draw_image" and "draw_image_scaled" script functions.

This commit is contained in:
NovaRain
2019-05-09 22:22:02 +08:00
parent 4bc1a422c3
commit 02c2df50ac
8 changed files with 94 additions and 6 deletions
+1 -1
View File
@@ -630,7 +630,7 @@ DontTurnOffSneakIfYouRun=0
;Set to 0 to disable switching. (Default is 3)
UseWalkDistance=3
;Set to 1 to fix the bug that unable to sell used geiger counters or stealth boys
;Set to 1 to fix the bug of being unable to sell used geiger counters or stealth boys
CanSellUsedGeiger=1
;Set to 1 to fix the issue with being able to charge the car by using cells on other scenary/critters
+2
View File
@@ -249,6 +249,8 @@
#define dialog_message(text) sfall_func1("dialog_message", text)
#define dialog_obj sfall_func0("dialog_obj")
#define display_stats sfall_func0("display_stats")
#define draw_image(frmFile, frame, x, y, transparent) sfall_func5("draw_image", frmFile, frame, x, y, transparent)
#define draw_image_scaled(frmFile, frame, x, y, w, h) sfall_func6("draw_image_scaled", frmFile, frame, x, y, w, h)
#define exec_map_update_scripts sfall_func0("exec_map_update_scripts")
#define floor2(value) sfall_func1("floor2", value)
#define get_can_rest_on_map(map, elev) sfall_func2("get_can_rest_on_map", map, elev)
@@ -587,6 +587,17 @@ Some utility/math functions are available:
- there is also a unique ID number range for the player and party members from 18000 to 83535
- to assign a new ID number generated by the engine to the object (i.e. unassign a unique ID), call the function with two arguments and pass -1 for the flag argument
> void sfall_func5("draw_image", string/int pathFile/artId, int frame, int x, int y, bool transparent)
> void sfall_func6("draw_image_scaled", string/int pathFile/artId, int frame, int x, int y, int width, int height)
- displays the specified FRM image in the active window created by vanilla CreateWin or sfall's create_win script function
- pathFile/artId: path to the FRM file (e.g. "art\\inven\\5mmap.frm"), or its FRM ID number (e.g. 117440550, see specification of the FID format)
Optional arguments:
- frame: frame number, the first frame starts from zero
- x/y: offset relative to the top-left corner of the window
- width/height: image size, used to scale the image when displaying it
- transparent: pass true to display an image with transparent background
- NOTE: calling the functions without creating a window first will crash the game
------------------------
------ MORE INFO -------
------------------------
+2
View File
@@ -417,6 +417,7 @@ void __fastcall DrawWinLine(int winRef, DWORD startXPos, DWORD endXPos, DWORD st
}
}
// draws an image to the buffer without scaling and with possible transparency
void __fastcall windowDisplayBuf(long x, long width, long y, long height, void* data, long isTrans) {
__asm {
push height;
@@ -430,6 +431,7 @@ void __fastcall windowDisplayBuf(long x, long width, long y, long height, void*
}
}
// draws an image in the window and scales it to fit the window
void __fastcall displayInWindow(long w_here, long width, long height, void* data) {
__asm {
mov ebx, height;
+3 -3
View File
@@ -2320,9 +2320,9 @@ void BugFixes::init()
MakeCall(0x4130E5, action_explode_hack1);
dlogr(" Done", DL_INIT);
// Fix for unable to sell used geiger counters or stealth boys
// Fix for being unable to sell used geiger counters or stealth boys
if (GetConfigInt("Misc", "CanSellUsedGeiger", 1)) {
dlog("Applying fix for unable to sell used geiger counters or stealth boys.", DL_INIT);
dlog("Applying fix for being unable to sell used geiger counters or stealth boys.", DL_INIT);
SafeWrite8(0x478115, 0xBA);
SafeWrite8(0x478138, 0xBA);
MakeJump(0x474D22, barter_attempt_transaction_hack);
@@ -2487,7 +2487,7 @@ void BugFixes::init()
SafeWrite8(0x4C1015, 0x90);
HookCall(0x4C1042, wmSetupRandomEncounter_hook);
// Fix for unable to sell/give items in the barter screen when the player/party member is overloaded
// Fix for being unable to sell/give items in the barter screen when the player/party member is overloaded
HookCalls(barter_attempt_transaction_hook_weight, {0x474C73, 0x474CCA});
// Fix for the underline position in the inventory display window when the item name is longer than one line
@@ -398,5 +398,72 @@ void sf_create_win(OpcodeContext& ctx) {
}
}
static void DrawImage(OpcodeContext& ctx, bool isScaled) {
long rotation = 0;
const char* file = nullptr;
if (ctx.arg(0).isInt()) { // art id
long fid = ctx.arg(0).rawValue();
if (fid == -1) return;
long _fid = fid & 0xFFFFFFF;
file = fo::func::art_get_name(_fid); // .frm
if (_fid >> 24 == fo::OBJ_TYPE_CRITTER) {
rotation = (fid >> 28);
DWORD sz;
if (rotation && fo::func::db_file_exist(file, &sz)) {
file = fo::func::art_get_name(fid); // .fr#
}
}
} else {
file = ctx.arg(0).strValue(); // path to frm file
}
fo::FrmFile* frmPtr = nullptr;
if (fo::func::load_frame(file, &frmPtr)) {
ctx.printOpcodeError("%s() - can't open the file '%s'.", ctx.getMetaruleName(), file);
return;
}
fo::FrmFrameData* framePtr = (fo::FrmFrameData*)&frmPtr->width;
if (rotation > 0 && rotation < 6) {
BYTE* offsOriFrame = (BYTE*)framePtr;
offsOriFrame += frmPtr->oriFrameOffset[rotation];
framePtr = (fo::FrmFrameData*)offsOriFrame;
}
int frameno = ctx.arg(1).rawValue();
if (frameno > 0) {
int maxFrames = frmPtr->frames - 1;
if (frameno > maxFrames) frameno = maxFrames;
while (frameno-- > 0) {
BYTE* offsFrame = (BYTE*)framePtr;
offsFrame += framePtr->size + (sizeof(fo::FrmFrameData) - 1);
framePtr = (fo::FrmFrameData*)offsFrame;
}
}
if (isScaled && ctx.numArgs() < 3) {
fo::func::displayInWindow(framePtr->width, framePtr->width, framePtr->height, framePtr->data); // scaled to window size
} else {
int x = ctx.arg(2).rawValue(), y = ctx.arg(3).rawValue();
if (isScaled) { // draw to scale
long s_width = (ctx.numArgs() > 4) ? ctx.arg(4).rawValue() : framePtr->width;
long s_height = (ctx.numArgs() > 5) ? ctx.arg(5).rawValue() : framePtr->height;
long w_width = fo::func::windowWidth();
long xy_pos = (x * w_width) + y;
fo::func::trans_cscale(framePtr->width, framePtr->height, s_width, s_height, xy_pos, w_width, framePtr->data); // custom scaling
} else {
fo::func::windowDisplayBuf(x + frmPtr->xshift[rotation], framePtr->width, y + frmPtr->yshift[rotation], framePtr->height, framePtr->data, ctx.arg(4).rawValue());
}
}
__asm {
mov eax, frmPtr;
call fo::funcoffs::mem_free_;
}
}
void sf_draw_image(OpcodeContext& ctx) {
DrawImage(ctx, false);
}
void sf_draw_image_scaled(OpcodeContext& ctx) {
DrawImage(ctx, true);
}
}
}
@@ -99,5 +99,9 @@ void sf_dialog_message(OpcodeContext&);
void sf_create_win(OpcodeContext&);
void sf_draw_image(OpcodeContext&);
void sf_draw_image_scaled(OpcodeContext&);
}
}
@@ -54,7 +54,7 @@ static MetaruleTableType metaruleTable;
{ name, handler, minArgs, maxArgs, {arg1, arg2, ...} }
- name - name of function that will be used in scripts,
- handler - pointer to handler function (see examples below),
- minArgs/maxArgs - minimum and maximum number of arguments allowed for this function
- minArgs/maxArgs - minimum and maximum number of arguments allowed for this function (max 6)
- arg1, arg2, ... - argument types for automatic validation
*/
static const SfallMetarule metarules[] = {
@@ -66,7 +66,9 @@ static const SfallMetarule metarules[] = {
{"critter_inven_obj2", sf_critter_inven_obj2, 2, 2, {ARG_OBJECT, ARG_INT}},
{"dialog_message", sf_dialog_message, 1, 1, {ARG_STRING}},
{"dialog_obj", sf_get_dialog_object, 0, 0},
{"display_stats", sf_display_stats, 0, 0},
{"display_stats", sf_display_stats, 0, 0}, // refresh
{"draw_image", sf_draw_image, 1, 5, {ARG_INTSTR, ARG_INT, ARG_INT, ARG_INT, ARG_INT}},
{"draw_image_scaled", sf_draw_image_scaled, 1, 6, {ARG_INTSTR, ARG_INT, ARG_INT, ARG_INT, ARG_INT, ARG_INT}},
{"exec_map_update_scripts", sf_exec_map_update_scripts, 0, 0},
{"floor2", sf_floor2, 1, 1, {ARG_NUMBER}},
{"get_can_rest_on_map", sf_get_rest_on_map, 2, 2, {ARG_INT, ARG_INT}},