diff --git a/artifacts/scripting/headers/sfall.h b/artifacts/scripting/headers/sfall.h index 0ceee529..8189e659 100644 --- a/artifacts/scripting/headers/sfall.h +++ b/artifacts/scripting/headers/sfall.h @@ -224,6 +224,7 @@ #define ADD_PERK_MODE_REMOVE (4) // remove from the list of selectable perks // sfall_funcX macros +#define add_trait(traitId) sfall_func1("add_trait", traitId) #define art_cache_clear sfall_func0("art_cache_clear") #define attack_is_aimed sfall_func0("attack_is_aimed") #define create_win(winName, x, y, w, h) sfall_func5("create_win", winName, x, y, w, h) diff --git a/artifacts/scripting/sfall function notes.txt b/artifacts/scripting/sfall function notes.txt index cc532aa0..7c839dba 100644 --- a/artifacts/scripting/sfall function notes.txt +++ b/artifacts/scripting/sfall function notes.txt @@ -512,6 +512,9 @@ Some utility/math functions are available: - can take off player's equipped item when the inventory is opened, or the player is in the barter screen - slot: 0 - armor slot, 1 - right slot, 2 - left slot (see INVEN_TYPE_* in define.h) +> void sfall_func1("add_trait", int traitId) +- adds the specified trait to the player + ------------------------ ------ MORE INFO ------- ------------------------ diff --git a/sfall/FalloutEngine.cpp b/sfall/FalloutEngine.cpp index 5255e942..dec24ff1 100644 --- a/sfall/FalloutEngine.cpp +++ b/sfall/FalloutEngine.cpp @@ -75,7 +75,7 @@ DWORD* ptr_gdBarterMod = reinterpret_cast(_gdBarterMod); DWORD* ptr_gdNumOptions = reinterpret_cast(_gdNumOptions); DWORD* ptr_gIsSteal = reinterpret_cast(_gIsSteal); DWORD* ptr_glblmode = reinterpret_cast(_glblmode); -DWORD* ptr_gmouse_current_cursor = reinterpret_cast(_gmouse_current_cursor); +long* ptr_gmouse_current_cursor = reinterpret_cast(_gmouse_current_cursor); DWORD* ptr_gmovie_played_list = reinterpret_cast(_gmovie_played_list); BYTE* ptr_GreenColor = reinterpret_cast(_GreenColor); DWORD* ptr_gsound_initialized = reinterpret_cast(_gsound_initialized); diff --git a/sfall/FalloutEngine.h b/sfall/FalloutEngine.h index 9f5c2dd8..897c79e5 100644 --- a/sfall/FalloutEngine.h +++ b/sfall/FalloutEngine.h @@ -317,7 +317,7 @@ extern DWORD* ptr_gdBarterMod; extern DWORD* ptr_gdNumOptions; extern DWORD* ptr_gIsSteal; extern DWORD* ptr_glblmode; -extern DWORD* ptr_gmouse_current_cursor; +extern long* ptr_gmouse_current_cursor; extern DWORD* ptr_gmovie_played_list; extern BYTE* ptr_GreenColor; extern DWORD* ptr_gsound_initialized; diff --git a/sfall/LoadGameHook.cpp b/sfall/LoadGameHook.cpp index 0a4c1f5f..e567a02c 100644 --- a/sfall/LoadGameHook.cpp +++ b/sfall/LoadGameHook.cpp @@ -107,7 +107,7 @@ static void _stdcall ResetState(DWORD onLoad) { } void GetSavePath(char* buf, char* ftype) { - sprintf(buf, "%s\\savegame\\slot%.2d\\sfall%s.sav", *(char**)_patches, *(DWORD*)_slot_cursor + 1 + LSPageOffset, ftype); //add SuperSave Page offset + sprintf(buf, "%s\\savegame\\slot%.2d\\sfall%s.sav", *(char**)_patches, *ptr_slot_cursor + 1 + LSPageOffset, ftype); //add SuperSave Page offset } static char SaveSfallDataFailMsg[128]; diff --git a/sfall/PartyControl.cpp b/sfall/PartyControl.cpp index 6a8b6483..fa62e51c 100644 --- a/sfall/PartyControl.cpp +++ b/sfall/PartyControl.cpp @@ -58,7 +58,7 @@ static DWORD real_perkLevelDataList[PERK_count]; static int real_tag_skill[4]; //static DWORD real_bbox_sneak; -static const DWORD* list_com = (DWORD*)_list_com; +static const DWORD* list_com = ptr_list_com; static bool _stdcall IsInPidList(TGameObj* obj) { int pid = obj->pid & 0xFFFFFF; diff --git a/sfall/Perks.cpp b/sfall/Perks.cpp index 895eaa76..2fd36a36 100644 --- a/sfall/Perks.cpp +++ b/sfall/Perks.cpp @@ -365,10 +365,10 @@ static DWORD _stdcall HandleFakeTraits(int isSelect) { } if (a && !isSelect) { isSelect = 1; - *(DWORD*)_folder_card_fid = fakeTraits[i].Image; - *(DWORD*)_folder_card_title = (DWORD)fakeTraits[i].Name; - *(DWORD*)_folder_card_title2 = 0; - *(DWORD*)_folder_card_desc = (DWORD)fakeTraits[i].Desc; + *ptr_folder_card_fid = fakeTraits[i].Image; + *ptr_folder_card_title = (DWORD)fakeTraits[i].Name; + *ptr_folder_card_title2 = 0; + *ptr_folder_card_desc = (DWORD)fakeTraits[i].Desc; } } return isSelect; diff --git a/sfall/ScriptExtender.cpp b/sfall/ScriptExtender.cpp index d1aa2362..380a788d 100644 --- a/sfall/ScriptExtender.cpp +++ b/sfall/ScriptExtender.cpp @@ -391,6 +391,7 @@ static void OpcodeInvalidArgs(const char* opcodeName) { If you don't include opcode in this array, you should take care of all argument validation inside handler itself. */ static const SfallOpcodeMetadata opcodeMetaArray[] = { + {sf_add_trait, "add_trait", {DATATYPE_MASK_INT}}, {sf_create_win, "create_win", {DATATYPE_MASK_STR, DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT}}, {sf_critter_inven_obj2, "critter_inven_obj2", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT}}, {sf_get_current_inven_size, "get_current_inven_size", {DATATYPE_MASK_VALID_OBJ}}, diff --git a/sfall/ScriptOps/MetaruleOp.hpp b/sfall/ScriptOps/MetaruleOp.hpp index 0d9d740f..9cedd427 100644 --- a/sfall/ScriptOps/MetaruleOp.hpp +++ b/sfall/ScriptOps/MetaruleOp.hpp @@ -118,10 +118,11 @@ static void sf_metarule_exist() { - minArgs/maxArgs - minimum and maximum number of arguments allowed for this function (max 6) */ static const SfallMetarule metaruleArray[] = { + {"add_trait", sf_add_trait, 1, 1}, {"art_cache_clear", sf_art_cache_flush, 0, 0}, {"attack_is_aimed", sf_attack_is_aimed, 0, 0}, - {"critter_inven_obj2", sf_critter_inven_obj2, 2, 2}, {"create_win", sf_create_win, 5, 6}, + {"critter_inven_obj2", sf_critter_inven_obj2, 2, 2}, {"dialog_obj", sf_get_dialog_object, 0, 0}, {"display_stats", sf_display_stats, 0, 0}, // refresh {"exec_map_update_scripts", sf_exec_map_update_scripts, 0, 0}, diff --git a/sfall/ScriptOps/ObjectsOps.hpp b/sfall/ScriptOps/ObjectsOps.hpp index 0488cc8e..0b0a7ee1 100644 --- a/sfall/ScriptOps/ObjectsOps.hpp +++ b/sfall/ScriptOps/ObjectsOps.hpp @@ -462,14 +462,14 @@ static void __declspec(naked) op_tile_get_objects() { } static void _stdcall op_get_party_members2() { - DWORD obj, mode = opHandler.arg(0).asInt(), isDead; - int i, actualCount = *(DWORD*)_partyMemberCount; + DWORD mode = opHandler.arg(0).asInt(), isDead; + int actualCount = *ptr_partyMemberCount; DWORD arrayId = TempArray(0, 4); - DWORD* partyMemberList = *(DWORD**)_partyMemberList; - for (i = 0; i < actualCount; i++) { - obj = partyMemberList[i*4]; + DWORD* partyMemberList = *ptr_partyMemberList; + for (int i = 0; i < actualCount; i++) { + TGameObj* obj = reinterpret_cast(partyMemberList[i * 4]); if (mode == 0) { // mode 0 will act just like op_party_member_count in fallout2 - if ((*(DWORD*)(obj + 100) >> 24) != OBJ_TYPE_CRITTER) // obj type != critter + if (obj->pid >> 24 != OBJ_TYPE_CRITTER) // obj type != critter continue; __asm { mov eax, obj; @@ -478,7 +478,7 @@ static void _stdcall op_get_party_members2() { } if (isDead) continue; - if (*(DWORD*)(obj + 36) & 1) // no idea.. + if (obj->flags & 1) // Mouse_3d flag continue; } arrays[arrayId].push_back((long)obj); @@ -646,7 +646,7 @@ static void sf_get_loot_object() { opHandler.setReturn((GetLoopFlags() & INTFACELOOT) ? LoadGameHook_LootTarget : 0, DATATYPE_INT); } -static const char* failedLoad = "%s() - failed to load a prototype id: %d"; +static const char* failedLoad = "%s() - failed to load a prototype ID: %d"; static bool protoMaxLimitPatch = false; static void _stdcall get_proto_data2() { diff --git a/sfall/ScriptOps/PerksOp.hpp b/sfall/ScriptOps/PerksOp.hpp index 49870a9d..83589947 100644 --- a/sfall/ScriptOps/PerksOp.hpp +++ b/sfall/ScriptOps/PerksOp.hpp @@ -621,7 +621,26 @@ static void __declspec(naked) SetPerkLevelMod() { mov ecx, eax; call SetPerkLevelMod2; end: - pop ecx; + pop ecx; retn; } } + +static void sf_add_trait() { + if (*(DWORD*)(*(DWORD*)_obj_dude + 0x64) != PID_Player) { + opHandler.printOpcodeError("add_trait() - traits can be added only to the player."); + return; + } + long traitId = opHandler.arg(0).rawValue(); + if (traitId >= TRAIT_fast_metabolism && traitId <= TRAIT_gifted) { + if (ptr_pc_traits[0] == -1) { + ptr_pc_traits[0] = traitId; + } else if (ptr_pc_traits[0] != traitId && ptr_pc_traits[1] == -1) { + ptr_pc_traits[1] = traitId; + } else { + opHandler.printOpcodeError("add_trait() - cannot add the trait ID: %d", traitId); + } + } else { + opHandler.printOpcodeError("add_trait() - invalid trait ID."); + } +} diff --git a/sfall/dinput.cpp b/sfall/dinput.cpp index b71b8b10..2a4df31d 100644 --- a/sfall/dinput.cpp +++ b/sfall/dinput.cpp @@ -208,7 +208,7 @@ public: if (UseScrollWheel) { int count = 1; if (MouseState.lZ > 0) { - if (*(DWORD*)_gmouse_current_cursor == 2 || *(DWORD*)_gmouse_current_cursor == 3) { + if (*ptr_gmouse_current_cursor == 2 || *ptr_gmouse_current_cursor == 3) { __asm { call display_scroll_up_; } @@ -218,7 +218,7 @@ public: while (count--) TapKey(DIK_UP); } } else if (MouseState.lZ < 0) { - if (*(DWORD*)_gmouse_current_cursor == 2 || *(DWORD*)_gmouse_current_cursor == 3) { + if (*ptr_gmouse_current_cursor == 2 || *ptr_gmouse_current_cursor == 3) { __asm { call display_scroll_down_; }