diff --git a/artifacts/config_files/elevators.ini b/artifacts/config_files/elevators.ini index 31842637..b33863e9 100644 --- a/artifacts/config_files/elevators.ini +++ b/artifacts/config_files/elevators.ini @@ -1,5 +1,5 @@ ;Controls the elevators -;Image must match up with the image of an existing elevator (can be overrided in sfall 4.1.4 or newer) +;Image must match up with the image of an existing elevator (can be overrided in sfall 4.1.4/3.8.14 or newer) ;Make sure you specify the correct number of exit targets ;The maximum number of elevators is currently capped at 50 ;Use the line number (0-indexed) of the corresponding FRM in intrface.lst to set the appearance of the elevator diff --git a/artifacts/scripting/arrays.txt b/artifacts/scripting/arrays.txt index 5b5ef0d0..14542a0e 100644 --- a/artifacts/scripting/arrays.txt +++ b/artifacts/scripting/arrays.txt @@ -156,7 +156,7 @@ Example: - if size is >= 0, creates list with given size - if size == -1, creates map (associative array) - if size == -1 and flags == 2, creates a "lookup" map in which the values of existing keys are read-only and can't be updated. -This type of array allows you to store a zero (0) value for a key +This type of array allows you to store a zero (0) key value - NOTE: in earlier versions (up to 4.1.3/3.8.13) the second argument is not used, just use 0 - returns arrayID (valid until array is deleted) diff --git a/sfall/FalloutEngine/Functions.cpp b/sfall/FalloutEngine/Functions.cpp index 6a3959fc..316e654b 100644 --- a/sfall/FalloutEngine/Functions.cpp +++ b/sfall/FalloutEngine/Functions.cpp @@ -44,7 +44,7 @@ namespace func WRAP_WATCOM_CALL2(offs, arg1, arg2) #define WRAP_WATCOM_CALL4(offs, arg1, arg2, arg3, arg4) \ - __asm mov ecx, arg4 \ + __asm mov ecx, arg4 \ WRAP_WATCOM_CALL3(offs, arg1, arg2, arg3) #define WRAP_WATCOM_CALL5(offs, arg1, arg2, arg3, arg4, arg5) \ @@ -59,19 +59,41 @@ namespace func __asm push arg7 \ WRAP_WATCOM_CALL6(offs, arg1, arg2, arg3, arg4, arg5, arg6) +// defines wrappers for __fastcall +#define WRAP_WATCOM_FCALL1(offs, arg1) \ + __asm mov eax, ecx \ + WRAP_WATCOM_CALL0(offs) + +#define WRAP_WATCOM_FCALL2(offs, arg1, arg2) \ + WRAP_WATCOM_FCALL1(offs, arg1) + +#define WRAP_WATCOM_FCALL3(offs, arg1, arg2, arg3) \ + __asm mov ebx, arg3 \ + WRAP_WATCOM_FCALL1(offs, arg1) + +#define WRAP_WATCOM_FCALL4(offs, arg1, arg2, arg3, arg4) \ + __asm mov eax, ecx \ + __asm mov ebx, arg3 \ + __asm mov ecx, arg4 \ + WRAP_WATCOM_CALL0(offs) + +#define WRAP_WATCOM_FCALL5(offs, arg1, arg2, arg3, arg4, arg5) \ + __asm push arg5 \ + WRAP_WATCOM_FCALL4(offs, arg1, arg2, arg3, arg4) + +#define WRAP_WATCOM_FCALL6(offs, arg1, arg2, arg3, arg4, arg5, arg6) \ + __asm push arg6 \ + WRAP_WATCOM_FCALL5(offs, arg1, arg2, arg3, arg4, arg5) + +#define WRAP_WATCOM_FCALL7(offs, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \ + __asm push arg7 \ + WRAP_WATCOM_FCALL6(offs, arg1, arg2, arg3, arg4, arg5, arg6) + + bool __stdcall art_exists(long artFid) { WRAP_WATCOM_CALL1(art_exists_, artFid) } -long __fastcall _word_wrap(const char* text, int maxWidth, DWORD* buf, BYTE* count) { - __asm { - mov eax, ecx; - mov ecx, count; - mov ebx, buf; - call fo::funcoffs::_word_wrap_; - } -} - // Returns the name of the critter const char* __stdcall critter_name(GameObject* critter) { WRAP_WATCOM_CALL1(critter_name_, critter) @@ -284,6 +306,14 @@ long __stdcall message_exit(MessageList *msgList) { WRAP_WATCOM_CALL1(message_exit_, msgList) } +GameObject* __fastcall obj_blocking_at_wrapper(GameObject* obj, DWORD tile, DWORD elevation, void* func) { + __asm { + mov eax, ecx; + mov ebx, elevation; + call func; + } +} + GameObject* __stdcall obj_find_first_at_tile(long elevation, long tileNum) { WRAP_WATCOM_CALL2(obj_find_first_at_tile_, elevation, tileNum) } @@ -424,9 +454,40 @@ void __fastcall DrawWinLine(int winRef, DWORD startXPos, DWORD endXPos, DWORD st WRAP_WATCOM_CALL6(name##_, arg1, arg2, arg3, arg4, arg5, arg6) \ } -#define WRAP_WATCOM_FUNC7(retType, name, arg1t, arg1, arg2t, arg2, arg3t, arg3, arg4t, arg4, arg5t, arg5, arg6t, arg6, arg7t, arg7) \ - retType __stdcall name(arg1t arg1, arg2t arg2, arg3t arg3, arg4t arg4, arg5t arg5, arg6t arg6, arg7t arg7) { \ - WRAP_WATCOM_CALL7(name##_, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \ + +#define WRAP_WATCOM_FFUNC1(retType, name, arg1t, arg1) \ + retType __fastcall name(arg1t arg1) { \ + WRAP_WATCOM_FCALL1(name##_, arg1) \ + } + +#define WRAP_WATCOM_FFUNC2(retType, name, arg1t, arg1, arg2t, arg2) \ + retType __fastcall name(arg1t arg1, arg2t arg2) { \ + WRAP_WATCOM_FCALL2(name##_, arg1, arg2) \ + } + +#define WRAP_WATCOM_FFUNC3(retType, name, arg1t, arg1, arg2t, arg2, arg3t, arg3) \ + retType __fastcall name(arg1t arg1, arg2t arg2, arg3t arg3) { \ + WRAP_WATCOM_FCALL3(name##_, arg1, arg2, arg3) \ + } + +#define WRAP_WATCOM_FFUNC4(retType, name, arg1t, arg1, arg2t, arg2, arg3t, arg3, arg4t, arg4) \ + retType __fastcall name(arg1t arg1, arg2t arg2, arg3t arg3, arg4t arg4) { \ + WRAP_WATCOM_FCALL4(name##_, arg1, arg2, arg3, arg4) \ + } + +#define WRAP_WATCOM_FFUNC5(retType, name, arg1t, arg1, arg2t, arg2, arg3t, arg3, arg4t, arg4, arg5t, arg5) \ + retType __fastcall name(arg1t arg1, arg2t arg2, arg3t arg3, arg4t arg4, arg5t arg5) { \ + WRAP_WATCOM_FCALL5(name##_, arg1, arg2, arg3, arg4, arg5) \ + } + +#define WRAP_WATCOM_FFUNC6(retType, name, arg1t, arg1, arg2t, arg2, arg3t, arg3, arg4t, arg4, arg5t, arg5, arg6t, arg6) \ + retType __fastcall name(arg1t arg1, arg2t arg2, arg3t arg3, arg4t arg4, arg5t arg5, arg6t arg6) { \ + WRAP_WATCOM_FCALL6(name##_, arg1, arg2, arg3, arg4, arg5, arg6) \ + } + +#define WRAP_WATCOM_FFUNC7(retType, name, arg1t, arg1, arg2t, arg2, arg3t, arg3, arg4t, arg4, arg5t, arg5, arg6t, arg6, arg7t, arg7) \ + retType __fastcall name(arg1t arg1, arg2t arg2, arg3t arg3, arg4t arg4, arg5t arg5, arg6t arg6, arg7t arg7) { \ + WRAP_WATCOM_FCALL7(name##_, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \ } #include "Functions_def.h" diff --git a/sfall/FalloutEngine/Functions.h b/sfall/FalloutEngine/Functions.h index 7829352a..91f0e9be 100644 --- a/sfall/FalloutEngine/Functions.h +++ b/sfall/FalloutEngine/Functions.h @@ -36,8 +36,6 @@ namespace func bool __stdcall art_exists(long artFid); -long __fastcall _word_wrap(const char* text, int maxWidth, DWORD* buf, BYTE* count); - // Returns the name of the critter const char* __stdcall critter_name(GameObject* critter); @@ -162,6 +160,8 @@ long __stdcall message_load(MessageList *msgList, const char *msgFilePath); // destroys message list long __stdcall message_exit(MessageList *msgList); +GameObject* __fastcall obj_blocking_at_wrapper(GameObject* obj, DWORD tile, DWORD elevation, void* func); + GameObject* __stdcall obj_find_first_at_tile(long elevation, long tileNum); GameObject* __stdcall obj_find_next_at_tile(); @@ -221,8 +221,27 @@ void __stdcall DialogOut(const char* text); #define WRAP_WATCOM_FUNC6(retType, name, arg1t, arg1, arg2t, arg2, arg3t, arg3, arg4t, arg4, arg5t, arg5, arg6t, arg6) \ retType __stdcall name(arg1t arg1, arg2t arg2, arg3t arg3, arg4t arg4, arg5t arg5, arg6t arg6); -#define WRAP_WATCOM_FUNC7(retType, name, arg1t, arg1, arg2t, arg2, arg3t, arg3, arg4t, arg4, arg5t, arg5, arg6t, arg6, arg7t, arg7) \ - retType __stdcall name(arg1t arg1, arg2t arg2, arg3t arg3, arg4t arg4, arg5t arg5, arg6t arg6, arg7t arg7); + +#define WRAP_WATCOM_FFUNC1(retType, name, arg1t, arg1) \ + retType __fastcall name(arg1t arg1); + +#define WRAP_WATCOM_FFUNC2(retType, name, arg1t, arg1, arg2t, arg2) \ + retType __fastcall name(arg1t arg1, arg2t arg2); + +#define WRAP_WATCOM_FFUNC3(retType, name, arg1t, arg1, arg2t, arg2, arg3t, arg3) \ + retType __fastcall name(arg1t arg1, arg2t arg2, arg3t arg3); + +#define WRAP_WATCOM_FFUNC4(retType, name, arg1t, arg1, arg2t, arg2, arg3t, arg3, arg4t, arg4) \ + retType __fastcall name(arg1t arg1, arg2t arg2, arg3t arg3, arg4t arg4); + +#define WRAP_WATCOM_FFUNC5(retType, name, arg1t, arg1, arg2t, arg2, arg3t, arg3, arg4t, arg4, arg5t, arg5) \ + retType __fastcall name(arg1t arg1, arg2t arg2, arg3t arg3, arg4t arg4, arg5t arg5); + +#define WRAP_WATCOM_FFUNC6(retType, name, arg1t, arg1, arg2t, arg2, arg3t, arg3, arg4t, arg4, arg5t, arg5, arg6t, arg6) \ + retType __fastcall name(arg1t arg1, arg2t arg2, arg3t arg3, arg4t arg4, arg5t arg5, arg6t arg6); + +#define WRAP_WATCOM_FFUNC7(retType, name, arg1t, arg1, arg2t, arg2, arg3t, arg3, arg4t, arg4, arg5t, arg5, arg6t, arg6, arg7t, arg7) \ + retType __fastcall name(arg1t arg1, arg2t arg2, arg3t arg3, arg4t arg4, arg5t arg5, arg6t arg6, arg7t arg7); #include "Functions_def.h" @@ -233,7 +252,15 @@ void __stdcall DialogOut(const char* text); #undef WRAP_WATCOM_FUNC4 #undef WRAP_WATCOM_FUNC5 #undef WRAP_WATCOM_FUNC6 -#undef WRAP_WATCOM_FUNC7 +//#undef WRAP_WATCOM_FUNC7 + +#undef WRAP_WATCOM_FFUNC1 +#undef WRAP_WATCOM_FFUNC2 +#undef WRAP_WATCOM_FFUNC3 +#undef WRAP_WATCOM_FFUNC4 +#undef WRAP_WATCOM_FFUNC5 +#undef WRAP_WATCOM_FFUNC6 +#undef WRAP_WATCOM_FFUNC7 } } diff --git a/sfall/FalloutEngine/Functions_def.h b/sfall/FalloutEngine/Functions_def.h index c7dfcb78..9738254d 100644 --- a/sfall/FalloutEngine/Functions_def.h +++ b/sfall/FalloutEngine/Functions_def.h @@ -14,6 +14,14 @@ NOTES: be careful not to use reserved words, including ASM instructions (push, pop, mov, div, etc.) */ +// For functions that have 3 or more arguments, it is preferable to use the fastcall calling convention +// because the compiler builds the better/optimized code when calling the engine functions +WRAP_WATCOM_FFUNC4(long, _word_wrap, const char*, text, int, maxWidth, DWORD*, buf, BYTE*, count) +WRAP_WATCOM_FFUNC7(long, createWindow, const char*, winName, long, x, long, y, long, width, long, height, long, bgColorIndex, long, flags) +WRAP_WATCOM_FFUNC7(void, make_straight_path_func, fo::GameObject*, objFrom, DWORD, tileFrom, DWORD, tileTo, void*, rotationPtr, DWORD*, result, long, flags, void*, func) +WRAP_WATCOM_FFUNC3(long, object_under_mouse, long, crSwitch, long, inclDude, long, elevation) + +// stdcall WRAP_WATCOM_FUNC1(AIcap*, ai_cap, GameObject*, critter) WRAP_WATCOM_FUNC1(Program*, allocateProgram, const char*, filePath) WRAP_WATCOM_FUNC0(void, art_flush) @@ -26,7 +34,6 @@ WRAP_WATCOM_FUNC4(BYTE*, art_ptr_lock_data, long, frmId, long, frameNum, long, r WRAP_WATCOM_FUNC4(BYTE*, art_lock, long, frmId, DWORD*, lockPtr, long*, widthOut, long*, heightOut) WRAP_WATCOM_FUNC1(long, art_ptr_unlock, DWORD, lockId) WRAP_WATCOM_FUNC2(long, barter_compute_value, GameObject*, source, GameObject*, target) -WRAP_WATCOM_FUNC7(long, createWindow, const char*, winName, long, x, long, y, long, width, long, height, long, bgColorIndex, long, flags) WRAP_WATCOM_FUNC1(void*, dbase_open, const char*, fileName) WRAP_WATCOM_FUNC1(void, dbase_close, void*, dbPtr) WRAP_WATCOM_FUNC3(long, db_freadShortCount, DbFile*, file, WORD*, dest, long, count) @@ -79,7 +86,6 @@ WRAP_WATCOM_FUNC2(long, obj_pid_new, fo::GameObject*, object, long, pid) // checks/unjams jammed locks WRAP_WATCOM_FUNC1(long, obj_lock_is_jammed, GameObject*, object) WRAP_WATCOM_FUNC1(void, obj_unjam_lock, GameObject*, object) -WRAP_WATCOM_FUNC3(long, object_under_mouse, long, crSwitch, long, inclDude, long, elevation) WRAP_WATCOM_FUNC6(long, pick_death, GameObject*, attacker, GameObject*, target, GameObject*, weapon, long, amount, long, anim, long, hitFromBack) WRAP_WATCOM_FUNC0(void, proto_dude_update_gender) WRAP_WATCOM_FUNC2(long, queue_find_first, GameObject*, object, long, qType) diff --git a/sfall/Modules/Karma.cpp b/sfall/Modules/Karma.cpp index 92cb47d2..2dcbc874 100644 --- a/sfall/Modules/Karma.cpp +++ b/sfall/Modules/Karma.cpp @@ -41,7 +41,7 @@ static std::string karmaGainMsg; static std::string karmaLossMsg; bool displayKarmaChanges; -static DWORD _stdcall DrawCardHook2() { +static DWORD _stdcall DrawCard() { int reputation = fo::var::game_global_vars[fo::GVAR_PLAYER_REPUTATION]; for (auto& info : karmaFrms) { if (reputation < info.points) { @@ -51,19 +51,19 @@ static DWORD _stdcall DrawCardHook2() { return karmaFrms.end()->frm; } -static void __declspec(naked) DrawCardHook() { +static void __declspec(naked) DrawInfoWin_hook() { __asm { - cmp ds : [FO_VAR_info_line], 10; - jne skip; - cmp eax, 0x30; - jne skip; + cmp ds:[FO_VAR_info_line], 10; + jne skip; + cmp eax, 0x30; + jne skip; push ecx; push edx; - call DrawCardHook2; - pop edx; - pop ecx; + call DrawCard; + pop edx; + pop ecx; skip: - jmp fo::funcoffs::DrawCard_; + jmp fo::funcoffs::DrawCard_; } } @@ -101,7 +101,7 @@ void ApplyKarmaFRMsPatch() { ? atoi(karmaPointsList[i].c_str()) : INT_MAX; } - HookCall(0x4367A9, DrawCardHook); + HookCall(0x4367A9, DrawInfoWin_hook); dlogr(" Done", DL_INIT); } diff --git a/sfall/Modules/ScriptExtender.cpp b/sfall/Modules/ScriptExtender.cpp index 01805b19..4e518158 100644 --- a/sfall/Modules/ScriptExtender.cpp +++ b/sfall/Modules/ScriptExtender.cpp @@ -549,7 +549,7 @@ static void RunScript(GlobalScript* script) { */ static void ResetStateAfterFrame() { if (tempArrays.size()) { - for (std::set::iterator it = tempArrays.begin(); it != tempArrays.end(); ++it) + for (std::set::iterator it = tempArrays.begin(); it != tempArrays.end(); ++it) FreeArray(*it); tempArrays.clear(); } diff --git a/sfall/Modules/Scripting/Arrays.cpp b/sfall/Modules/Scripting/Arrays.cpp index d510b218..6df24ceb 100644 --- a/sfall/Modules/Scripting/Arrays.cpp +++ b/sfall/Modules/Scripting/Arrays.cpp @@ -495,6 +495,8 @@ static void ListSort(std::vector &arr, int type) { static void MapSort(sArrayVar& arr, int type) { std::vector> map; + map.reserve(arr.val.size()); + bool sortByValue = false; if (type < ARRAY_ACTION_SHUFFLE) { type += 4; diff --git a/sfall/Modules/Scripting/Handlers/Metarule.cpp b/sfall/Modules/Scripting/Handlers/Metarule.cpp index cdd8adc9..59712045 100644 --- a/sfall/Modules/Scripting/Handlers/Metarule.cpp +++ b/sfall/Modules/Scripting/Handlers/Metarule.cpp @@ -107,7 +107,7 @@ static const SfallMetarule metarules[] = { {"item_weight", sf_item_weight, 1, 1, {ARG_OBJECT}}, {"lock_is_jammed", sf_lock_is_jammed, 1, 1, {ARG_OBJECT}}, {"loot_obj", sf_get_loot_object, 0, 0}, - {"obj_under_cursor", sf_obj_under_cursor, 2, 2, {ARG_INT, ARG_INT}}, + {"obj_under_cursor", sf_get_obj_under_cursor, 2, 2, {ARG_INT, ARG_INT}}, {"outlined_object", sf_outlined_object, 0, 0}, {"real_dude_obj", sf_real_dude_obj, 0, 0}, {"set_can_rest_on_map", sf_set_rest_on_map, 3, 3, {ARG_INT, ARG_INT, ARG_INT}}, diff --git a/sfall/Modules/Scripting/Handlers/Misc.cpp b/sfall/Modules/Scripting/Handlers/Misc.cpp index e03837b9..56c3ff36 100644 --- a/sfall/Modules/Scripting/Handlers/Misc.cpp +++ b/sfall/Modules/Scripting/Handlers/Misc.cpp @@ -1722,9 +1722,5 @@ void sf_get_ini_section(OpcodeContext& ctx) { ctx.setReturn(arrayId); } -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)); -} - } } diff --git a/sfall/Modules/Scripting/Handlers/Misc.h b/sfall/Modules/Scripting/Handlers/Misc.h index 3a34f1a7..500f76ea 100644 --- a/sfall/Modules/Scripting/Handlers/Misc.h +++ b/sfall/Modules/Scripting/Handlers/Misc.h @@ -165,7 +165,5 @@ void sf_get_ini_sections(OpcodeContext&); void sf_get_ini_section(OpcodeContext&); -void sf_obj_under_cursor(OpcodeContext&); - } } diff --git a/sfall/Modules/Scripting/Handlers/Objects.cpp b/sfall/Modules/Scripting/Handlers/Objects.cpp index 11415cce..9b524f6f 100644 --- a/sfall/Modules/Scripting/Handlers/Objects.cpp +++ b/sfall/Modules/Scripting/Handlers/Objects.cpp @@ -212,28 +212,6 @@ void sf_set_weapon_ammo_count(OpcodeContext& ctx) { obj->item.charges = ctx.arg(1).asInt(); } -static DWORD _stdcall obj_blocking_at_wrapper(DWORD obj, DWORD tile, DWORD elevation, DWORD func) { - __asm { - mov eax, obj; - mov edx, tile; - mov ebx, elevation; - call func; - } -} - -static DWORD _stdcall make_straight_path_func_wrapper(fo::GameObject* obj, DWORD tileFrom, DWORD a3, DWORD tileTo, DWORD* result, DWORD a6, DWORD func) { - __asm { - mov eax, obj; - mov edx, tileFrom; - mov ecx, a3; - mov ebx, tileTo; - push func; - push a6; - push result; - call fo::funcoffs::make_straight_path_func_; - } -} - #define BLOCKING_TYPE_BLOCK (0) #define BLOCKING_TYPE_SHOOT (1) #define BLOCKING_TYPE_AI (2) @@ -259,21 +237,25 @@ static DWORD getBlockingFunc(DWORD type) { void sf_make_straight_path(OpcodeContext& ctx) { auto objFrom = ctx.arg(0).asObject(); DWORD tileTo = ctx.arg(1).asInt(), - type = ctx.arg(2).asInt(), - resultObj, arg6; - arg6 = (type == BLOCKING_TYPE_SHOOT) ? 32 : 0; - make_straight_path_func_wrapper(objFrom, objFrom->tile, 0, tileTo, &resultObj, arg6, getBlockingFunc(type)); + type = ctx.arg(2).asInt(); + + long flag = (type == BLOCKING_TYPE_SHOOT) ? 32 : 0; + DWORD resultObj = 0; + fo::func::make_straight_path_func(objFrom, objFrom->tile, tileTo, 0, &resultObj, flag, (void*)getBlockingFunc(type)); ctx.setReturn(resultObj, DataType::INT); } void sf_make_path(OpcodeContext& ctx) { auto objFrom = ctx.arg(0).asObject(); auto tileTo = ctx.arg(1).asInt(), - type = ctx.arg(2).asInt(); + type = ctx.arg(2).asInt(); auto func = getBlockingFunc(type); - long pathLength, a5 = 1; + + // if the object is not a critter, then there is no need to check tile (tileTo) for blocking + long checkFlag = (objFrom->type() == fo::OBJ_TYPE_CRITTER); + char pathData[800]; - pathLength = fo::func::make_path_func(objFrom, objFrom->tile, tileTo, pathData, a5, (void*)func); + long pathLength = fo::func::make_path_func(objFrom, objFrom->tile, tileTo, pathData, checkFlag, (void*)func); auto arrayId = TempArray(pathLength, 0); for (int i = 0; i < pathLength; i++) { arrays[arrayId].val[i].set((long)pathData[i]); @@ -283,15 +265,15 @@ void sf_make_path(OpcodeContext& ctx) { void sf_obj_blocking_at(OpcodeContext& ctx) { DWORD tile = ctx.arg(0).asInt(), - elevation = ctx.arg(1).asInt(), - type = ctx.arg(2).asInt(), - resultObj; - resultObj = obj_blocking_at_wrapper(0, tile, elevation, getBlockingFunc(type)); - if (resultObj && type == BLOCKING_TYPE_SHOOT && (*(DWORD*)(resultObj + 39) & 0x80)) { // don't know what this flag means, copy-pasted from the engine code + elevation = ctx.arg(1).asInt(), + type = ctx.arg(2).asInt(); + + fo::GameObject* resultObj = fo::func::obj_blocking_at_wrapper(0, tile, elevation, (void*)getBlockingFunc(type)); + if (resultObj && type == BLOCKING_TYPE_SHOOT && (resultObj->flags & fo::ObjectFlag::ShootThru)) { // don't know what this flag means, copy-pasted from the engine code // this check was added because the engine always does exactly this when using shoot blocking checks - resultObj = 0; + resultObj = nullptr; } - ctx.setReturn(resultObj, DataType::INT); + ctx.setReturn((DWORD)resultObj, DataType::INT); } void sf_tile_get_objects(OpcodeContext& ctx) { @@ -456,6 +438,10 @@ void sf_get_dialog_object(OpcodeContext& ctx) { ctx.setReturn(InDialog() ? fo::var::dialog_target : 0); } +void sf_get_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)); +} + void sf_get_loot_object(OpcodeContext& ctx) { ctx.setReturn((GetLoopFlags() & INTFACELOOT) ? LoadGameHook::LootTarget : 0); } diff --git a/sfall/Modules/Scripting/Handlers/Objects.h b/sfall/Modules/Scripting/Handlers/Objects.h index 7ffc3251..df882b22 100644 --- a/sfall/Modules/Scripting/Handlers/Objects.h +++ b/sfall/Modules/Scripting/Handlers/Objects.h @@ -97,6 +97,8 @@ void sf_get_current_inven_size(OpcodeContext&); void sf_get_dialog_object(OpcodeContext&); +void sf_get_obj_under_cursor(OpcodeContext&); + void sf_get_loot_object(OpcodeContext&); void sf_get_object_data(OpcodeContext&); diff --git a/sfall/Modules/Sound.cpp b/sfall/Modules/Sound.cpp index 4cc3b2f0..5ec64e89 100644 --- a/sfall/Modules/Sound.cpp +++ b/sfall/Modules/Sound.cpp @@ -6,62 +6,67 @@ namespace sfall { -static char attackerSnd[8]; -static char targetSnd[8]; +static char attackerSnd[9] = {0}; +static char targetSnd[9] = {0}; -static void __declspec(naked) MsgCopy() { +static void __declspec(naked) combatai_msg_hook() { __asm { - mov edi, [esp+0xc]; - pushad; - cmp eax, FO_VAR_target_str; - jne attacker; - lea eax, targetSnd; - jmp end; + mov edi, [esp + 0xC]; // lip file from msg + push eax; + cmp eax, FO_VAR_target_str; + jne attacker; + lea eax, targetSnd; + jmp skip; attacker: - lea eax, attackerSnd; -end: - mov edx, edi; - mov ebx, 8; + lea eax, attackerSnd; +skip: + push edx; + push ebx; + mov edx, edi; + mov ebx, 8; call fo::funcoffs::strncpy_; - popad; - jmp fo::funcoffs::strncpy_; + pop ebx; + pop edx; + pop eax; + jmp fo::funcoffs::strncpy_; } } -static void __declspec(naked) DisplayMsg() { +static void __declspec(naked) ai_print_msg_hook() { __asm { - pushad; - cmp edx, FO_VAR_target_str; - jne attacker; - lea eax, targetSnd; - jmp end; + push eax; + cmp edx, FO_VAR_target_str; + jne attacker; + lea eax, targetSnd; + jmp skip; attacker: - lea eax, attackerSnd; -end: - mov ebx, [eax]; - test bl, bl; - jz skip; - call fo::funcoffs::gsound_play_sfx_file_; + lea eax, attackerSnd; skip: - popad; - jmp fo::funcoffs::text_object_create_; + push ecx; + mov ecx, [eax]; + test cl, cl; + jz end; + call fo::funcoffs::gsound_play_sfx_file_; +end: + pop ecx; + pop eax; + jmp fo::funcoffs::text_object_create_; } } void Sound::init() { - int tmp; - if (tmp = GetConfigInt("Sound", "NumSoundBuffers", 0)) { - SafeWrite8(0x451129, (BYTE)tmp); + if (int sBuff = GetConfigInt("Sound", "NumSoundBuffers", 0)) { + SafeWrite8(0x451129, (BYTE)sBuff); } if (GetConfigInt("Sound", "AllowSoundForFloats", 0)) { - HookCall(0x42B7C7, MsgCopy); - HookCall(0x42B849, DisplayMsg); - } + HookCall(0x42B7C7, combatai_msg_hook); // copy msg + HookCall(0x42B849, ai_print_msg_hook); - //Yes, I did leave this in on purpose. Will be of use to anyone trying to add in the sound effects - if (GetConfigInt("Sound", "Test_ForceFloats", 0)) { - SafeWrite8(0x42B772, 0xeb); + //Yes, I did leave this in on purpose. Will be of use to anyone trying to add in the sound effects + if (isDebug && GetConfigInt("Sound", "Test_ForceFloats", 0)) { + SafeWrite8(0x42B6F5, 0xEB); // bypass chance + } } } diff --git a/sfall/Modules/Worldmap.cpp b/sfall/Modules/Worldmap.cpp index 826530b0..b3298748 100644 --- a/sfall/Modules/Worldmap.cpp +++ b/sfall/Modules/Worldmap.cpp @@ -48,15 +48,15 @@ static __declspec(naked) void GetDateWrapper() { push esi; push ebx; call fo::funcoffs::game_time_date_; - mov ecx, ds:[FO_VAR_pc_proto + 0x4C]; - pop esi; + mov ecx, ds:[FO_VAR_pc_proto + 0x4C]; + pop esi; test esi, esi; - jz end; - add ecx, [esi]; - mov[esi], ecx; + jz end; + add ecx, [esi]; + mov [esi], ecx; end: - pop esi; - pop ecx; + pop esi; + pop ecx; retn; } } @@ -71,19 +71,19 @@ static int mapSlotsScrollMax = 27 * (17 - 7); static __declspec(naked) void ScrollCityListHook() { __asm { push ebx; - mov ebx, ds:[0x672F10]; + mov ebx, ds:[0x672F10]; test eax, eax; - jl up; - cmp ebx, mapSlotsScrollMax; - je end; - jmp run; + jl up; + cmp ebx, mapSlotsScrollMax; + je end; + jmp run; up: test ebx, ebx; - jz end; + jz end; run: call fo::funcoffs::wmInterfaceScrollTabsStart_; end: - pop ebx; + pop ebx; retn; } } @@ -95,28 +95,28 @@ static void __stdcall WorldmapLoopHook() { static DWORD worldMapDelay; static void __declspec(naked) WorldMapFpsPatch() { __asm { - pushad; + pushadc; call WorldmapLoopHook; - mov ecx, worldMapDelay; + mov ecx, worldMapDelay; tck: - mov eax, ds : [0x50fb08]; + mov eax, ds:[0x50fb08]; call fo::funcoffs::elapsed_time_; - cmp eax, ecx; - jl tck; + cmp eax, ecx; + jl tck; call fo::funcoffs::get_time_; - mov ds : [0x50fb08], eax; - popad; - jmp fo::funcoffs::get_input_; + mov ds:[0x50fb08], eax; + popadc; + jmp fo::funcoffs::get_input_; } } //Only used if the world map speed patch is disabled, so that world map scripts are still run static void __declspec(naked) WorldMapHook() { __asm { - pushad; + pushadc; call WorldmapLoopHook; - popad; - jmp fo::funcoffs::get_input_; + popadc; + jmp fo::funcoffs::get_input_; } } @@ -139,36 +139,36 @@ static void __declspec(naked) wmRndEncounterOccurred_hack() { static void __declspec(naked) ViewportHook() { __asm { call fo::funcoffs::wmWorldMapLoadTempData_; - mov eax, ViewportX; - mov ds : [FO_VAR_wmWorldOffsetX], eax - mov eax, ViewportY; - mov ds : [FO_VAR_wmWorldOffsetY], eax; + mov eax, ViewportX; + mov ds:[FO_VAR_wmWorldOffsetX], eax; + mov eax, ViewportY; + mov ds:[FO_VAR_wmWorldOffsetY], eax; retn; } } static void __declspec(naked) wmTownMapFunc_hack() { __asm { - cmp edx, 0x31 - jl end - cmp edx, ecx - jge end - push edx - sub edx, 0x31 - lea eax, ds:0[edx*8] - sub eax, edx - pop edx - cmp dword ptr [edi+eax*4+0x0], 0 // Visited - je end - cmp dword ptr [edi+eax*4+0x4], -1 // Xpos - je end - cmp dword ptr [edi+eax*4+0x8], -1 // Ypos - je end - retn + cmp edx, 0x31; + jl end; + cmp edx, ecx; + jge end; + push edx; + sub edx, 0x31; + lea eax, ds:0[edx*8]; + sub eax, edx; + pop edx; + cmp dword ptr [edi+eax*4+0x0], 0; // Visited + je end; + cmp dword ptr [edi+eax*4+0x4], -1; // Xpos + je end; + cmp dword ptr [edi+eax*4+0x8], -1; // Ypos + je end; + retn; end: - add esp, 4 // Destroy the return address - push 0x4C4976 - retn + add esp, 4; // destroy the return address + push 0x4C4976; + retn; } } @@ -187,7 +187,7 @@ static __declspec(naked) void PathfinderFix3() { } static DWORD _stdcall PathfinderFix2(DWORD perkLevel, DWORD ticks) { - double d = MapMulti*MapMulti2; + double d = MapMulti * MapMulti2; if (perkLevel == 1) d *= 0.75; else if (perkLevel == 2) d *= 0.5; else if (perkLevel == 3) d *= 0.25; @@ -426,7 +426,7 @@ void StartingStatePatches() { if (ViewportY != -1) { dlog("Applying starting y view patch.", DL_INIT); SafeWrite32(FO_VAR_wmWorldOffsetY, ViewportY); - HookCall(0x4BCF07, &ViewportHook); + if (ViewportX == -1) HookCall(0x4BCF07, &ViewportHook); dlogr(" Done", DL_INIT); } } @@ -509,7 +509,7 @@ void Worldmap::SetRestMode(DWORD mode) { } if (mode & 2) { // bit2 - disable resting on maps with "can_rest_here=No" in Maps.txt, even if there are no other critters SafeWrite8(0x42E587, 0xE9); - SafeWrite32(0x42E588, 0x00000094); // jmp 0x42E620 + SafeWrite32(0x42E588, 0x94); // jmp 0x42E620 } if (mode & 4) { // bit3 - disable healing during resting SafeWrite16(0x499FD4, 0x9090);