diff --git a/artifacts/scripting/headers/sfall.h b/artifacts/scripting/headers/sfall.h index 173da3d1..8af61cfa 100644 --- a/artifacts/scripting/headers/sfall.h +++ b/artifacts/scripting/headers/sfall.h @@ -64,6 +64,7 @@ #define HOOK_SNEAK (39) #define HOOK_STDPROCEDURE (40) #define HOOK_STDPROCEDURE_END (41) +#define HOOK_TARGETOBJECT (42) //Valid arguments to list_begin #define LIST_CRITTERS (0) @@ -296,6 +297,7 @@ #define metarule_exist(metaruleName) sfall_func1("metarule_exist", metaruleName) #define npc_engine_level_up(toggle) sfall_func1("npc_engine_level_up", toggle) #define obj_under_cursor(onlyCritter, includeDude) sfall_func2("obj_under_cursor", onlyCritter, includeDude) +#define objects_in_radius(tile, radius, elev, type) sfall_func4("objects_in_radius", tile, radius, elev, type) #define outlined_object sfall_func0("outlined_object") #define real_dude_obj sfall_func0("real_dude_obj") #define remove_all_timer_events sfall_func0("remove_timer_event") @@ -321,6 +323,7 @@ #define string_compare(str1, str2) sfall_func2("string_compare", str1, str2) #define string_compare_locale(str1, str2, codePage) sfall_func3("string_compare", str1, str2, codePage) #define string_format(format, a1, a2) sfall_func3("string_format", format, a1, a2) +#define tile_by_position(x, y) sfall_func2("tile_by_position", x, y) #define tile_refresh_display sfall_func0("tile_refresh_display") #define unjam_lock(obj) sfall_func1("unjam_lock", obj) #define unset_unique_id(obj) sfall_func2("set_unique_id", obj, -1) diff --git a/artifacts/scripting/hookscripts.txt b/artifacts/scripting/hookscripts.txt index da2ce2ef..05187799 100644 --- a/artifacts/scripting/hookscripts.txt +++ b/artifacts/scripting/hookscripts.txt @@ -648,3 +648,15 @@ Obj arg3 - the object that called this handler (source_obj, can be 0) int arg4 - 1 after procedure execution (for HOOK_STDPROCEDURE_END), 0 otherwise int ret1 - pass -1 to cancel the execution of the handler (only for HOOK_STDPROCEDURE) + +------------------------------------------- + +HOOK_TARGETOBJECT (hs_targetobject.int) + +Runs whenever the targeting cursor hovers over something. + +int arg1 - event type: 0 - when hovering over the target, 1 - when clicking on the target +int arg2 - 1 if the target is a valid object, 0 otherwise +Obj arg3 - the target object + +int ret1 - overrides the target object diff --git a/artifacts/scripting/sfall function notes.txt b/artifacts/scripting/sfall function notes.txt index 0c705c98..01ca2330 100644 --- a/artifacts/scripting/sfall function notes.txt +++ b/artifacts/scripting/sfall function notes.txt @@ -685,7 +685,17 @@ optional argument: > string sfall_func3("string_format", string format, any val1, any val2, ...) - formats given value using standard syntax of C printf function (google "printf" for format details). However it is limited to formatting up to 4 values -- formatting is only supported for %s and %d. The format string is limited to 1024 characters +- formatting is only supported for %s and %d, and the format string is limited to 1024 characters + +> array sfall_func3("objects_in_radius", int tile, int radius, int elevation) +> array sfall_func4("objects_in_radius", int tile, int radius, int elevation, int type) +- returns an array of objects of a type (see OBJ_TYPE_* constants in define_extra.h) within the specified radius from the given tile +- The radius is limited to 50 hexes +- passing -1 to the type argument or not specifying it will return all types of objects + +> int sfall_func2("tile_by_position", int x, int y) +- returns the tile number at the x/y position relative to the top-left corner of the screen +- returns -1 if the position is outside of the screen ------------------------ ------ MORE INFO ------- diff --git a/sfall/FalloutEngine/EngineUtils.cpp b/sfall/FalloutEngine/EngineUtils.cpp index 37c7c4b2..c27a79c8 100644 --- a/sfall/FalloutEngine/EngineUtils.cpp +++ b/sfall/FalloutEngine/EngineUtils.cpp @@ -196,16 +196,18 @@ long __fastcall GetTopWindowID(long xPos, long yPos) { return win->wID; } -// Returns an array of objects within the specified tile radius, objects at the source tile will not be included in the array -void GetObjectsTileRadius(std::vector &objs, long tile, long radius, long elev, long type = -1) { - for (; radius > 0; radius--) { - for (long rotation = 0; rotation < 6; rotation++) { - long _tile = fo::func::tile_num_in_direction(tile, rotation, radius); - fo::GameObject* obj = fo::func::obj_find_first_at_tile(elev, _tile); - while (obj) { - if (type == -1 || type == obj->Type()) objs.push_back(obj); - obj = fo::func::obj_find_next_at_tile(); +// Returns an array of objects within the specified radius from the source tile +void GetObjectsTileRadius(std::vector &objs, long sourceTile, long radius, long elev, long type = -1) { + for (long tile = 0; tile < 40000; tile++) { + fo::GameObject* obj = fo::func::obj_find_first_at_tile(elev, tile); + while (obj) { + if (type == -1 || type == obj->Type()) { + bool multiHex = (obj->flags & fo::ObjectFlag::MultiHex) ? true : false; + if (fo::func::tile_dist(sourceTile, obj->tile) <= (radius + multiHex)) { + objs.push_back(obj); + } } + obj = fo::func::obj_find_next_at_tile(); } } } diff --git a/sfall/FalloutEngine/EngineUtils.h b/sfall/FalloutEngine/EngineUtils.h index 72c94a39..f9a3c812 100644 --- a/sfall/FalloutEngine/EngineUtils.h +++ b/sfall/FalloutEngine/EngineUtils.h @@ -78,7 +78,7 @@ long GetScriptLocalVars(long sid); long __fastcall GetTopWindowID(long xPos, long yPos); -void GetObjectsTileRadius(std::vector &objs, long tile, long radius, long elev, long type); +void GetObjectsTileRadius(std::vector &objs, long sourceTile, long radius, long elev, long type); // Print text to surface void PrintText(char *displayText, BYTE colorIndex, DWORD x, DWORD y, DWORD textWidth, DWORD destWidth, BYTE *surface); diff --git a/sfall/Modules/HookScripts.cpp b/sfall/Modules/HookScripts.cpp index c331985c..2775a29f 100644 --- a/sfall/Modules/HookScripts.cpp +++ b/sfall/Modules/HookScripts.cpp @@ -92,7 +92,7 @@ static HooksInjectInfo injectHooks[] = { {HOOK_SNEAK, Inject_SneakCheckHook, false}, {HOOK_STDPROCEDURE, Inject_ScriptProcedureHook, false}, {HOOK_STDPROCEDURE_END, Inject_ScriptProcedureHook2, false}, - {HOOK_TARGETOBJ, Inject_TargetObjectHook, false}, + {HOOK_TARGETOBJECT, Inject_TargetObjectHook, false}, }; bool HookScripts::injectAllHooks; diff --git a/sfall/Modules/HookScripts.h b/sfall/Modules/HookScripts.h index 4b140449..be0a9bc9 100644 --- a/sfall/Modules/HookScripts.h +++ b/sfall/Modules/HookScripts.h @@ -68,7 +68,7 @@ enum HookType HOOK_SNEAK = 39, HOOK_STDPROCEDURE = 40, HOOK_STDPROCEDURE_END = 41, - HOOK_TARGETOBJ = 42, + HOOK_TARGETOBJECT = 42, HOOK_COUNT }; diff --git a/sfall/Modules/HookScripts/CombatHs.cpp b/sfall/Modules/HookScripts/CombatHs.cpp index 08068757..c8e2c39a 100644 --- a/sfall/Modules/HookScripts/CombatHs.cpp +++ b/sfall/Modules/HookScripts/CombatHs.cpp @@ -491,34 +491,30 @@ static long __fastcall TargetObjectHook(DWORD isValid, DWORD object, long type) BeginHook(); argCount = 3; - args[0] = type; // 0 - mouse hover on target, 1 - mouse click target + args[0] = type; // 0 - mouse hovering over target, 1 - mouse clicking on target args[1] = isValid; // 1 - target is valid args[2] = object; // target object - if (isValid == 0) object = 0; + if (isValid == 0) object = 0; // ??? + if (type == 0) targetRet = 0; // unset ret from the previous execution of the hook - RunHookScript(HOOK_TARGETOBJ); + RunHookScript(HOOK_TARGETOBJECT); - if (type == 0) { - targetRet = 0; - if (cRet > 0) { - targetRet = (rets[0] != 0) ? rets[0] : object; // 0 - default object, -1 - invalid target, or object override - object = (targetRet != -1) ? targetRet : 0; // object can't be -1 - } - } else if (targetRet) { - if (targetRet != -1) object = targetRet; - targetRet = 0; + if (cRet > 0) { + targetRet = (rets[0] != 0) ? rets[0] : object; // 0 - default object, -1 - invalid target, or object override + object = (targetRet != -1) ? targetRet : 0; // object can't be -1 + } else if (type == 1 && targetRet != -1) { + object = targetRet; } EndHook(); - return object; // null or object } static void __declspec(naked) gmouse_bk_process_hook() { __asm { push 0; // type - mov ecx, eax; // valid or object - mov edx, edi; // object + mov ecx, eax; // 1 - valid (object) or 0 - invalid + mov edx, edi; // object under mouse call TargetObjectHook; mov edi, eax; retn; @@ -527,15 +523,16 @@ static void __declspec(naked) gmouse_bk_process_hook() { static void __declspec(naked) gmouse_handle_event_hook() { __asm { - push 1; // type - mov ecx, eax; + push 1; // type + mov ecx, eax; // 1 - valid (object) or 0 - invalid cmp dword ptr ds:[targetRet], 0; je default; // override - xor edx, edx; + mov ecx, 1; + xor eax, eax; cmp dword ptr ds:[targetRet], -1; - cmovne edx, targetRet; // 0 or object - mov ecx, edx; // set valid + cmove ecx, eax; // if true - set invalid + cmovne edx, targetRet; // if false - set override object default: call TargetObjectHook; mov edx, eax; @@ -637,7 +634,7 @@ void InitCombatHookScripts() { LoadHookScript("hs_combatturn", HOOK_COMBATTURN); LoadHookScript("hs_onexplosion", HOOK_ONEXPLOSION); LoadHookScript("hs_subcombatdmg", HOOK_SUBCOMBATDAMAGE); - LoadHookScript("hs_targetobj", HOOK_TARGETOBJ); + LoadHookScript("hs_targetobject", HOOK_TARGETOBJECT); } } diff --git a/sfall/Modules/Scripting/Handlers/Metarule.cpp b/sfall/Modules/Scripting/Handlers/Metarule.cpp index 3aa21e19..7ed9ed44 100644 --- a/sfall/Modules/Scripting/Handlers/Metarule.cpp +++ b/sfall/Modules/Scripting/Handlers/Metarule.cpp @@ -88,12 +88,10 @@ static const SfallMetarule metarules[] = { {"get_metarule_table", sf_get_metarule_table, 0, 0}, {"get_object_ai_data", sf_get_object_ai_data, 2, 2, -1, {ARG_OBJECT, ARG_INT}}, {"get_object_data", sf_get_object_data, 2, 2, 0, {ARG_OBJECT, ARG_INT}}, - {"get_objects_at_radius", sf_get_objects_at_radius, 3, 4, 0, {ARG_INT, ARG_INT, ARG_INT, ARG_INT}}, {"get_outline", sf_get_outline, 1, 1, 0, {ARG_OBJECT}}, {"get_sfall_arg_at", sf_get_sfall_arg_at, 1, 1, 0, {ARG_INT}}, {"get_string_pointer", sf_get_string_pointer, 1, 1, 0, {ARG_STRING}}, {"get_text_width", sf_get_text_width, 1, 1, 0, {ARG_STRING}}, - {"get_tile", sf_get_tile, 2, 2, -1, {ARG_INT, ARG_INT}}, {"has_fake_perk_npc", sf_has_fake_perk_npc, 2, 2, 0, {ARG_OBJECT, ARG_STRING}}, {"has_fake_trait_npc", sf_has_fake_trait_npc, 2, 2, 0, {ARG_OBJECT, ARG_STRING}}, {"hide_window", sf_hide_window, 0, 1, -1, {ARG_STRING}}, @@ -108,7 +106,8 @@ static const SfallMetarule metarules[] = { {"loot_obj", sf_get_loot_object, 0, 0}, {"metarule_exist", sf_metarule_exist, 1, 1}, // no arg check {"npc_engine_level_up", sf_npc_engine_level_up, 1, 1}, - {"obj_under_cursor", sf_get_obj_under_cursor, 2, 2, 0, {ARG_INT, ARG_INT}}, + {"obj_under_cursor", sf_obj_under_cursor, 2, 2, 0, {ARG_INT, ARG_INT}}, + {"objects_in_radius", sf_objects_in_radius, 3, 4, 0, {ARG_INT, ARG_INT, ARG_INT, ARG_INT}}, {"outlined_object", sf_outlined_object, 0, 0}, {"real_dude_obj", sf_real_dude_obj, 0, 0}, {"remove_timer_event", sf_remove_timer_event, 0, 1, -1, {ARG_INT}}, @@ -135,6 +134,7 @@ static const SfallMetarule metarules[] = { {"spatial_radius", sf_spatial_radius, 1, 1, 0, {ARG_OBJECT}}, {"string_compare", sf_string_compare, 2, 3, 0, {ARG_STRING, ARG_STRING, ARG_INT}}, {"string_format", sf_string_format, 2, 5, 0, {ARG_STRING, ARG_ANY, ARG_ANY, ARG_ANY, ARG_ANY}}, + {"tile_by_position", sf_tile_by_position, 2, 2, -1, {ARG_INT, ARG_INT}}, {"tile_refresh_display", sf_tile_refresh_display, 0, 0}, {"unjam_lock", sf_unjam_lock, 1, 1, -1, {ARG_OBJECT}}, {"unwield_slot", sf_unwield_slot, 2, 2, -1, {ARG_OBJECT, ARG_INT}}, diff --git a/sfall/Modules/Scripting/Handlers/Objects.cpp b/sfall/Modules/Scripting/Handlers/Objects.cpp index 65310156..e3fb6eb0 100644 --- a/sfall/Modules/Scripting/Handlers/Objects.cpp +++ b/sfall/Modules/Scripting/Handlers/Objects.cpp @@ -371,7 +371,7 @@ void sf_get_dialog_object(OpcodeContext& ctx) { ctx.setReturn(InDialog() ? fo::var::dialog_target : 0); } -void sf_get_obj_under_cursor(OpcodeContext& ctx) { +void sf_obj_under_cursor(OpcodeContext& ctx) { ctx.setReturn(fo::func::object_under_mouse(ctx.arg(0).asBool() ? 1 : -1, ctx.arg(1).rawValue(), fo::var::map_elevation)); } @@ -520,14 +520,15 @@ void sf_set_unique_id(OpcodeContext& ctx) { ctx.setReturn(id); } -void sf_get_objects_at_radius(OpcodeContext& ctx) { +void sf_objects_in_radius(OpcodeContext& ctx) { long radius = ctx.arg(1).rawValue(); - if (radius <= 0) radius = 1; + if (radius <= 0) radius = 1; else if (radius > 50) radius = 50; long elev = ctx.arg(2).rawValue(); if (elev < 0) elev = 0; else if (elev > 2) elev = 2; long type = (ctx.numArgs() > 3) ? ctx.arg(3).rawValue() : -1; std::vector objects; + objects.reserve(25); fo::GetObjectsTileRadius(objects, ctx.arg(0).rawValue(), radius, elev, type); size_t sz = objects.size(); DWORD id = TempArray(sz, 0); diff --git a/sfall/Modules/Scripting/Handlers/Objects.h b/sfall/Modules/Scripting/Handlers/Objects.h index afd4f946..47b4f22c 100644 --- a/sfall/Modules/Scripting/Handlers/Objects.h +++ b/sfall/Modules/Scripting/Handlers/Objects.h @@ -93,7 +93,7 @@ void sf_get_current_inven_size(OpcodeContext&); void sf_get_dialog_object(OpcodeContext&); -void sf_get_obj_under_cursor(OpcodeContext&); +void sf_obj_under_cursor(OpcodeContext&); void sf_get_loot_object(OpcodeContext&); @@ -111,7 +111,7 @@ void sf_set_drugs_data(OpcodeContext&); void sf_set_unique_id(OpcodeContext&); -void sf_get_objects_at_radius(OpcodeContext&); +void sf_objects_in_radius(OpcodeContext&); } } diff --git a/sfall/Modules/Scripting/Handlers/Worldmap.cpp b/sfall/Modules/Scripting/Handlers/Worldmap.cpp index 353da54d..8b44a11d 100644 --- a/sfall/Modules/Scripting/Handlers/Worldmap.cpp +++ b/sfall/Modules/Scripting/Handlers/Worldmap.cpp @@ -253,7 +253,7 @@ void sf_get_rest_on_map(OpcodeContext& ctx) { ctx.setReturn(result); } -void sf_get_tile(OpcodeContext& ctx) { +void sf_tile_by_position(OpcodeContext& ctx) { ctx.setReturn(fo::func::tile_num(ctx.arg(0).rawValue(), ctx.arg(1).rawValue())); } diff --git a/sfall/Modules/Scripting/Handlers/Worldmap.h b/sfall/Modules/Scripting/Handlers/Worldmap.h index 1d2a7c1f..ed506622 100644 --- a/sfall/Modules/Scripting/Handlers/Worldmap.h +++ b/sfall/Modules/Scripting/Handlers/Worldmap.h @@ -56,7 +56,7 @@ void sf_set_rest_on_map(OpcodeContext&); void sf_get_rest_on_map(OpcodeContext&); -void sf_get_tile(OpcodeContext&); +void sf_tile_by_position(OpcodeContext&); } }