From 1db89883687b24c5b7c8ffcc0366863d13620900 Mon Sep 17 00:00:00 2001 From: NovaRain Date: Mon, 29 Jun 2020 11:53:12 +0800 Subject: [PATCH] Added "get_stat_max/min" script functions (#307) Added updating player's stats on the char screen to "display_stats" script function (#314) --- artifacts/scripting/headers/sfall.h | 9 +++++ artifacts/scripting/sfall function notes.txt | 11 +++++- .../Modules/Scripting/Handlers/Interface.cpp | 32 +++++++++------ sfall/Modules/Scripting/Handlers/Metarule.cpp | 3 ++ sfall/Modules/Scripting/Handlers/Stats.cpp | 14 +++++++ sfall/Modules/Scripting/Handlers/Stats.h | 4 ++ sfall/Modules/Stats.cpp | 39 ++++++++++++------- sfall/Modules/Stats.h | 11 ++++-- 8 files changed, 93 insertions(+), 30 deletions(-) diff --git a/artifacts/scripting/headers/sfall.h b/artifacts/scripting/headers/sfall.h index 210a259f..f20a3ca5 100644 --- a/artifacts/scripting/headers/sfall.h +++ b/artifacts/scripting/headers/sfall.h @@ -272,6 +272,11 @@ use_obj_on_obj(item, dude_obj); \ set_self(0) +// returns the corrected tile distance between two objects to the distance variable (return value >= 9996 is an error when getting the distance) +#define distance_objs(distance, obj1, obj2) distance := tile_distance_objs(obj1, obj2) - 1; \ + if (get_flags(obj1) bwand FLAG_MULTIHEX) distance--; \ + if (get_flags(obj2) bwand FLAG_MULTIHEX) distance-- + // sfall_funcX macros #define add_extra_msg_file(name) sfall_func1("add_extra_msg_file", name) #define add_global_timer_event(time, fixedParam) sfall_func2("add_g_timer_event", time, fixedParam) @@ -304,6 +309,10 @@ #define get_object_ai_data(obj, aiParam) sfall_func2("get_object_ai_data", obj, aiParam) #define get_object_data(obj, offset) sfall_func2("get_object_data", obj, offset) #define get_outline(obj) sfall_func1("get_outline", obj) +#define get_pc_stat_max(stat) sfall_func1("get_stat_max", stat) +#define get_pc_stat_min(stat) sfall_func1("get_stat_min", stat) +#define get_npc_stat_max(stat) sfall_func2("get_stat_max", stat, 1) +#define get_npc_stat_min(stat) sfall_func2("get_stat_mix", stat, 1) #define get_sfall_arg_at(argNum) sfall_func1("get_sfall_arg_at", argNum) #define get_string_pointer(text) sfall_func1("get_string_pointer", text) #define get_text_width(text) sfall_func1("get_text_width", text) diff --git a/artifacts/scripting/sfall function notes.txt b/artifacts/scripting/sfall function notes.txt index 12e126e1..20788aa9 100644 --- a/artifacts/scripting/sfall function notes.txt +++ b/artifacts/scripting/sfall function notes.txt @@ -480,8 +480,8 @@ Some utility/math functions are available: - sets the current cursor mode > void sfall_func0("display_stats") -- displays player stats in the inventory screen display window -- works only in opened inventory +- updates player's stats in the inventory display window or on the character screen +- NOTE: works only when the interface window is opened > int sfall_func1("lock_is_jammed", object) - returns 1 if the lock (container or scenery) is currently jammed, 0 otherwise @@ -730,6 +730,13 @@ optional arguments: - flags: mode flags (see MSGBOX_* constants in define_extra.h). Pass -1 to skip setting the flags (default flags are NORMAL and YESNO) - color1/2: the color index in Fallout palette. color1 sets the text color for the first line, and color2 for all subsequent lines of text (default color is 145) +> int sfall_func1("get_stat_min", stat) +> int sfall_func1("get_stat_max", stat) +> int sfall_func2("get_stat_min", stat, bool who) +> int sfall_func2("get_stat_max", stat, bool who) +- returns the maximum or minimum set value of the specified stat (see set_stat_max/min functions) +- who: 0 (false) or omitting the argument - returns the value of the player, 1 (true) - returns the value set for other critters + ------------------------ ------ MORE INFO ------- ------------------------ diff --git a/sfall/Modules/Scripting/Handlers/Interface.cpp b/sfall/Modules/Scripting/Handlers/Interface.cpp index 60eb2d3d..45694912 100644 --- a/sfall/Modules/Scripting/Handlers/Interface.cpp +++ b/sfall/Modules/Scripting/Handlers/Interface.cpp @@ -38,7 +38,6 @@ void __declspec(naked) op_input_funcs_available() { __asm { mov edx, 1; // They're always available from 2.9 on _J_RET_VAL_TYPE(VAR_TYPE_INT); -// retn; } } @@ -67,7 +66,6 @@ void __declspec(naked) op_get_mouse_x() { mov edx, ds:[FO_VAR_mouse_x_]; add edx, ds:[FO_VAR_mouse_hotx]; _J_RET_VAL_TYPE(VAR_TYPE_INT); -// retn; } } @@ -76,7 +74,6 @@ void __declspec(naked) op_get_mouse_y() { mov edx, ds:[FO_VAR_mouse_y_]; add edx, ds:[FO_VAR_mouse_hoty]; _J_RET_VAL_TYPE(VAR_TYPE_INT); -// retn; } } @@ -94,7 +91,6 @@ void __declspec(naked) op_get_window_under_mouse() { __asm { mov edx, ds:[FO_VAR_last_button_winID]; _J_RET_VAL_TYPE(VAR_TYPE_INT); -// retn; } } @@ -104,7 +100,6 @@ void __declspec(naked) op_get_screen_width() { sub edx, ds:[FO_VAR_scr_size]; // _scr_size.x inc edx; _J_RET_VAL_TYPE(VAR_TYPE_INT); -// retn; } } @@ -114,7 +109,6 @@ void __declspec(naked) op_get_screen_height() { sub edx, ds:[FO_VAR_scr_size + 4]; // _scr_size.y inc edx; _J_RET_VAL_TYPE(VAR_TYPE_INT); -// retn; } } @@ -189,7 +183,6 @@ void __declspec(naked) op_get_viewport_x() { __asm { mov edx, ds:[FO_VAR_wmWorldOffsetX]; _J_RET_VAL_TYPE(VAR_TYPE_INT); -// retn; } } @@ -197,7 +190,6 @@ void __declspec(naked) op_get_viewport_y() { __asm { mov edx, ds:[FO_VAR_wmWorldOffsetY]; _J_RET_VAL_TYPE(VAR_TYPE_INT); -// retn; } } @@ -300,9 +292,27 @@ void mf_set_cursor_mode(OpcodeContext& ctx) { } void mf_display_stats(OpcodeContext& ctx) { -// calling the function outside of inventory screen will crash the game - if (GetLoopFlags() & INVENTORY) { - fo::func::display_stats(); + unsigned long flags = GetLoopFlags(); + if (flags & LoopFlag::INVENTORY) { + fo::func::display_stats(); // calling the function outside of inventory screen will crash the game + } else if (flags & LoopFlag::CHARSCREEN) { + __asm { + mov eax, ds:[FO_VAR_obj_dude]; + call fo::funcoffs::stat_recalc_derived_; + mov eax, ds:[FO_VAR_obj_dude]; + call fo::funcoffs::critter_adjust_hits_; + push edx; + push ebx; + mov eax, 7; + call fo::funcoffs::PrintBasicStat_; + xor eax, eax; + call fo::funcoffs::ListSkills_; + call fo::funcoffs::PrintLevelWin_; + call fo::funcoffs::ListDrvdStats_; + pop ebx; + pop edx; + } + fo::func::win_draw(fo::var::edit_win); } } diff --git a/sfall/Modules/Scripting/Handlers/Metarule.cpp b/sfall/Modules/Scripting/Handlers/Metarule.cpp index 41eff975..94c7908e 100644 --- a/sfall/Modules/Scripting/Handlers/Metarule.cpp +++ b/sfall/Modules/Scripting/Handlers/Metarule.cpp @@ -27,6 +27,7 @@ #include "Misc.h" #include "Objects.h" #include "Perks.h" +#include "Stats.h" #include "Utils.h" #include "Worldmap.h" @@ -91,6 +92,8 @@ static const SfallMetarule metarules[] = { {"get_object_data", mf_get_object_data, 2, 2, 0, {ARG_OBJECT, ARG_INT}}, {"get_outline", mf_get_outline, 1, 1, 0, {ARG_OBJECT}}, {"get_sfall_arg_at", mf_get_sfall_arg_at, 1, 1, 0, {ARG_INT}}, + {"get_stat_max", mf_get_stat_max, 1, 2, 0, {ARG_INT, ARG_INT}}, + {"get_stat_min", mf_get_stat_min, 1, 2, 0, {ARG_INT, ARG_INT}}, {"get_string_pointer", mf_get_string_pointer, 1, 1, 0, {ARG_STRING}}, {"get_text_width", mf_get_text_width, 1, 1, 0, {ARG_STRING}}, {"get_window_attribute", mf_get_window_attribute, 1, 2, -1, {ARG_INT, ARG_INT}}, diff --git a/sfall/Modules/Scripting/Handlers/Stats.cpp b/sfall/Modules/Scripting/Handlers/Stats.cpp index ed5c9f0b..c898c6e4 100644 --- a/sfall/Modules/Scripting/Handlers/Stats.cpp +++ b/sfall/Modules/Scripting/Handlers/Stats.cpp @@ -477,6 +477,20 @@ end: } } +void mf_get_stat_max(OpcodeContext& ctx) { + int who = (ctx.numArgs() > 1) ? ctx.arg(1).rawValue() : 0; + ctx.setReturn( + Stats::GetStatMax(ctx.arg(0).rawValue(), who) + ); +} + +void mf_get_stat_min(OpcodeContext& ctx) { + int who = (ctx.numArgs() > 1) ? ctx.arg(1).rawValue() : 0; + ctx.setReturn( + Stats::GetStatMin(ctx.arg(0).rawValue(), who) + ); +} + static void __declspec(naked) statPCAddExperienceCheckPMs_hack() { static DWORD xpTemp; __asm { diff --git a/sfall/Modules/Scripting/Handlers/Stats.h b/sfall/Modules/Scripting/Handlers/Stats.h index 207d87e4..571aae22 100644 --- a/sfall/Modules/Scripting/Handlers/Stats.h +++ b/sfall/Modules/Scripting/Handlers/Stats.h @@ -84,6 +84,10 @@ void __declspec() op_set_npc_stat_max(); void __declspec() op_set_npc_stat_min(); +void mf_get_stat_max(OpcodeContext&); + +void mf_get_stat_min(OpcodeContext&); + void op_set_xp_mod(OpcodeContext&); } diff --git a/sfall/Modules/Stats.cpp b/sfall/Modules/Stats.cpp index 4ecceb81..f51179a5 100644 --- a/sfall/Modules/Stats.cpp +++ b/sfall/Modules/Stats.cpp @@ -46,8 +46,8 @@ static struct StatFormula { static fo::GameObject* cCritter; -static const DWORD StatLevelHack_Ret = 0x4AEF52; static void __declspec(naked) stat_level_hack() { + static const DWORD StatLevelHack_Ret = 0x4AEF52; __asm { mov cCritter, eax; sub esp, 8; @@ -56,7 +56,7 @@ static void __declspec(naked) stat_level_hack() { } } -static int __fastcall check_stat_level(register int value, DWORD stat) { +static int __fastcall check_stat_level(int value, DWORD stat) { int valLimit; if (cCritter == fo::var::obj_dude) { valLimit = statMinimumsPC[stat]; @@ -73,11 +73,10 @@ static int __fastcall check_stat_level(register int value, DWORD stat) { } static void __declspec(naked) stat_level_hack_check() { - static const DWORD StatLevelHackCheck_Ret = 0x4AF3D7; __asm { mov edx, esi; // stat - call check_stat_level; // ecx - value - jmp StatLevelHackCheck_Ret; + push 0x4AF3D7; // return address + jmp check_stat_level; // ecx - value } } @@ -318,27 +317,41 @@ void Stats::init() { } } -void __stdcall SetPCStatMax(int stat, int i) { +long Stats::GetStatMax(int stat, int isNPC) { if (stat >= 0 && stat < fo::STAT_max_stat) { - statMaximumsPC[stat] = i; + return (isNPC) ? statMaximumsNPC[stat] : statMaximumsPC[stat]; + } + return 0; +} + +long Stats::GetStatMin(int stat, int isNPC) { + if (stat >= 0 && stat < fo::STAT_max_stat) { + return (isNPC) ? statMinimumsNPC[stat] : statMinimumsPC[stat]; + } + return 0; +} + +void __stdcall SetPCStatMax(int stat, int value) { + if (stat >= 0 && stat < fo::STAT_max_stat) { + statMaximumsPC[stat] = value; } } -void __stdcall SetPCStatMin(int stat, int i) { +void __stdcall SetPCStatMin(int stat, int value) { if (stat >= 0 && stat < fo::STAT_max_stat) { - statMinimumsPC[stat] = i; + statMinimumsPC[stat] = value; } } -void __stdcall SetNPCStatMax(int stat, int i) { +void __stdcall SetNPCStatMax(int stat, int value) { if (stat >= 0 && stat < fo::STAT_max_stat) { - statMaximumsNPC[stat] = i; + statMaximumsNPC[stat] = value; } } -void __stdcall SetNPCStatMin(int stat, int i) { +void __stdcall SetNPCStatMin(int stat, int value) { if (stat >= 0 && stat < fo::STAT_max_stat) { - statMinimumsNPC[stat] = i; + statMinimumsNPC[stat] = value; } } diff --git a/sfall/Modules/Stats.h b/sfall/Modules/Stats.h index dc4f9193..17f90cf8 100644 --- a/sfall/Modules/Stats.h +++ b/sfall/Modules/Stats.h @@ -31,11 +31,14 @@ public: static float experienceMod; static DWORD standardApAcBonus; static DWORD extraApAcBonus; + + static long GetStatMax(int stat, int isNPC); + static long GetStatMin(int stat, int isNPC); }; -void __stdcall SetPCStatMax(int stat, int i); -void __stdcall SetPCStatMin(int stat, int i); -void __stdcall SetNPCStatMax(int stat, int i); -void __stdcall SetNPCStatMin(int stat, int i); +void __stdcall SetPCStatMax(int stat, int value); +void __stdcall SetPCStatMin(int stat, int value); +void __stdcall SetNPCStatMax(int stat, int value); +void __stdcall SetNPCStatMin(int stat, int value); }