diff --git a/artifacts/scripting/headers/sfall.h b/artifacts/scripting/headers/sfall.h index 931917bb..6449e32f 100644 --- a/artifacts/scripting/headers/sfall.h +++ b/artifacts/scripting/headers/sfall.h @@ -213,6 +213,11 @@ #define party_member_list_critters party_member_list(0) #define party_member_list_all party_member_list(1) +// fake perks/traits add mode flags +#define ADD_PERK_MODE_TRAIT (1) // add to the player's traits +#define ADD_PERK_MODE_PERK (2) // add to the player's perks +#define ADD_PERK_MODE_REMOVE (4) // remove from the list of selectable perks + // sfall_funcX macros #define art_cache_clear sfall_func0("art_cache_clear") #define attack_is_aimed sfall_func0("attack_is_aimed") diff --git a/artifacts/scripting/sfall function notes.txt b/artifacts/scripting/sfall function notes.txt index 32f7d74c..f3fc401b 100644 --- a/artifacts/scripting/sfall function notes.txt +++ b/artifacts/scripting/sfall function notes.txt @@ -32,7 +32,7 @@ set_shader_mode tells sfall when to use a shader. The parameter is a set of 32 f force_graphics_refresh forces the screen to redraw at times when it normally wouldn't. If you're using animated shader, turning this option on is recommended. -The mapper manual lists the functions 'world_map_x_pos' and 'world_map_y_pos', which supposedly return the players x and y positions on the world map. get_world_map_x/y_pos are included here anyway, because I was unable to get those original functions to work, or even to find any evidence that they existed in game. +The mapper manual lists the functions 'world_map_x_pos' and 'world_map_y_pos', which supposedly return the player's x and y positions on the world map. get_world_map_x/y_pos are included here anyway, because I was unable to get those original functions to work, or even to find any evidence that they existed in game. set_pipboy_available will only accept 0 or 1 as an argument. Using any other value will cause the function to have no effect. Use 0 to disable the pipboy, and 1 to enable it. @@ -42,13 +42,13 @@ The 'type' value in the weapon knockback functions can be 0 or 1. If 0, the valu The get/set_sfall_global functions require an 8 characters long case sensitive string for the variable name. The variables behave the same as normal Fallout globals, except that they don't have to be declared beforehand in vault13.gam. Trying to get a variable which hasn't been set will always return 0. These functions are intended for use when a patch to a mod requires the addition of a new global variable, a case which would otherwise require the player to start a new game. -set_pickpocket_max and set_hit_chance_max effect all critters rather than just the player. set_skill_max can't be used to increase the skill cap above 300. set_perk_level_mod sets a modifier between +25 and -25 that is added/subtracted from the players level for the purposes of deciding which perks can be chosen. +set_pickpocket_max and set_hit_chance_max effect all critters rather than just the player. set_skill_max can't be used to increase the skill cap above 300. set_perk_level_mod sets a modifier between +25 and -25 that is added/subtracted from the player's level for the purposes of deciding which perks can be chosen. set_fake_trait and set_fake_perk can be used to add additional traits and perks to the character screen. They will be saved correctly when the player saves and reloads games, but by themselves they will have no further effect on the character. For perks, the allowed range for levels is between 0 and 100; setting the level to 0 removes that perk. For traits, the level must be 0 or 1. The image is a numeric id that corresponds to an entry in skilldex.lst. The name is limited to 63 characters and the description to 255 characters by sfall, but internal Fallout limits may be lower. has_fake_trait and has_fake_perk return the number of levels the player has of the perks/traits with the given name. -perk_add_mode, set_selectable_perk, set_perkbox_title, hide_real_perks, show_real_perks and clear_selectable_perks control the behaviour of the select a perk box. set_selectable_perk can be used to add additional items by setting the 'active' parameter to 1, and to remove them again by setting it to 0. set_perkbox_title can be used to change the title of the box, or by using "" it will be set back to the default. hide and show_real_perks can be used to prevent the dialog from displaying any of the original 119 perks. perk_add_mode modifies what happens when a fake perk is selected from the perks dialog. It is treated as a set of flags - if bit 1 is set then it is added to the players traits, if bit 2 is set it is added to the players perks, and if bit 3 is set it is removed from the list of selectable perks. The default is 0x2. clear_selectable_perks restores the dialog to its default state. +perk_add_mode, set_selectable_perk, set_perkbox_title, hide_real_perks, show_real_perks and clear_selectable_perks control the behaviour of the select a perk box. set_selectable_perk can be used to add additional items by setting the 'active' parameter to 1, and to remove them again by setting it to 0. set_perkbox_title can be used to change the title of the box, or by using "" it will be set back to the default. hide and show_real_perks can be used to prevent the dialog from displaying any of the original 119 perks. perk_add_mode modifies what happens when a fake perk is selected from the perks dialog. It is treated as a set of flags - if bit 1 is set then it is added to the player's traits, if bit 2 is set it is added to the player's perks, and if bit 3 is set it is removed from the list of selectable perks. The default is 0x2. clear_selectable_perks restores the dialog to its default state. show_iface_tag, hide_iface_tag and is_iface_tag_active relate to the boxes that appear above the interface such as SNEAK and LEVEL. You can use 3 for LEVEL and 4 for ADDICT, or the range from 5 to 9 for custom boxes. Remember to add your messages to intrface.msg and set up the font colours in ddraw.ini if you're going to use custom boxes. Starting from sfall 3.8.12, is_iface_tag_active can also be used to check 0 for SNEAK, 1 for POISONED, and 2 for RADIATED. diff --git a/sfall/Define.h b/sfall/Define.h index 300b556e..2344a621 100644 --- a/sfall/Define.h +++ b/sfall/Define.h @@ -337,7 +337,7 @@ enum AttackType : long ATKTYPE_PIERCINGKICK = 19 }; -#define OBJFLAG_CAN_WEAR_ITEMS (0xf000000) +#define OBJFLAG_CAN_WEAR_ITEMS (0xF000000) #define OBJFLAG_HELD_IN_RIGHT (0x10000) #define OBJFLAG_HELD_IN_LEFT (0x20000) diff --git a/sfall/Perks.cpp b/sfall/Perks.cpp index 1172dd08..5bed91f2 100644 --- a/sfall/Perks.cpp +++ b/sfall/Perks.cpp @@ -135,7 +135,7 @@ static void __declspec(naked) LevelUpHack() { notSkilled: mov ecx, 3; afterSkilled: - mov eax, ds:[_Level_]; // Get players level + mov eax, ds:[_Level_]; // Get player's level inc eax; xor edx, edx; div ecx; @@ -174,8 +174,9 @@ void _stdcall SetPerkboxTitle(char* name) { } } -void _stdcall SetSelectablePerk(char* name, int active, int image, char* desc) { - if (active < 0 || active > 1) return; +void _stdcall SetSelectablePerk(const char* name, int active, int image, const char* desc) { + if (active < 0) return; + if (active > 1) active = 1; size_t size = fakeSelectablePerks.size(); if (active == 0) { for (size_t i = 0; i < size; i++) { @@ -204,12 +205,9 @@ void _stdcall SetSelectablePerk(char* name, int active, int image, char* desc) { } } -void _stdcall SetFakePerk(char* name, int level, int image, char* desc) { - if (level > 100) { - level = 100; - } else if (level < 0 ) { - return; - } +void _stdcall SetFakePerk(const char* name, int level, int image, const char* desc) { + if (level < 0 ) return; + if (level > 100) level = 100; size_t size = fakePerks.size(); if (level == 0) { // remove perk from fakePerks for (size_t i = 0; i < size; i++) { @@ -238,12 +236,9 @@ void _stdcall SetFakePerk(char* name, int level, int image, char* desc) { } } -void _stdcall SetFakeTrait(char* name, int active, int image, char* desc) { - if (active > 1) { - active = 1; - } else if (active < 0) { - return; - } +void _stdcall SetFakeTrait(const char* name, int active, int image, const char* desc) { + if (active < 0) return; + if (active > 1) active = 1; size_t size = fakeTraits.size(); if (active == 0) { for (size_t i = 0; i < size; i++) { @@ -394,10 +389,10 @@ oloop: call HaveFakePerks; test eax, eax; jnz win; - mov eax, 0x434446; + mov eax, 0x434446; // skip print perks jmp eax; win: - mov eax, 0x43438A; + mov eax, 0x43438A; // print perks jmp eax; } } @@ -407,7 +402,7 @@ static void __declspec(naked) PlayerHasTraitHook() { call HaveFakeTraits; test eax, eax; jz end; - mov eax, 0x43425B; + mov eax, 0x43425B; // print traits jmp eax; end: jmp PlayerHasPerkHack; @@ -561,7 +556,7 @@ end: } // Adds the selected perk to the player -static void _stdcall AddFakePerk(DWORD perkID) { +static long _stdcall AddFakePerk(DWORD perkID) { size_t count; bool matched = false; // behavior for fake perk/trait @@ -598,6 +593,7 @@ static void _stdcall AddFakePerk(DWORD perkID) { if (addPerkMode & 4) { // delete from selectable perks RemoveSelectableID.push_back(perkID); //fakeSelectablePerks.remove_at(perkID); } + return 0; } // Adds perk from selection window to player @@ -609,7 +605,6 @@ static void __declspec(naked) AddPerkHook() { push edx; call AddFakePerk; pop ecx; - xor eax, eax; retn; normalPerk: push edx; @@ -1117,7 +1112,7 @@ void _stdcall AddPerkMode(DWORD mode) { addPerkMode = mode; } -DWORD _stdcall HasFakePerk(char* name) { +DWORD _stdcall HasFakePerk(const char* name) { for (DWORD i = 0; i < fakePerks.size(); i++) { if (!strcmp(name, fakePerks[i].Name)) { return fakePerks[i].Level; @@ -1126,7 +1121,7 @@ DWORD _stdcall HasFakePerk(char* name) { return 0; } -DWORD _stdcall HasFakeTrait(char* name) { +DWORD _stdcall HasFakeTrait(const char* name) { for (DWORD i = 0; i < fakeTraits.size(); i++) { if (!strcmp(name, fakeTraits[i].Name)) { return 1; diff --git a/sfall/Perks.h b/sfall/Perks.h index be46ba50..6a581ef8 100644 --- a/sfall/Perks.h +++ b/sfall/Perks.h @@ -34,15 +34,15 @@ void _stdcall SetPerkName(int id, char* value); void _stdcall SetPerkDesc(int id, char* value); void _stdcall SetPerkboxTitle(char* title); -void _stdcall SetSelectablePerk(char* name, int level, int image, char* desc); -void _stdcall SetFakePerk(char* name, int level, int image, char* desc); -void _stdcall SetFakeTrait(char* name, int level, int image, char* desc); +void _stdcall SetSelectablePerk(const char* name, int active, int image, const char* desc); +void _stdcall SetFakePerk(const char* name, int level, int image, const char* desc); +void _stdcall SetFakeTrait(const char* name, int active, int image, const char* desc); void _stdcall IgnoreDefaultPerks(); void _stdcall RestoreDefaultPerks(); void _stdcall AddPerkMode(DWORD mode); -DWORD _stdcall HasFakePerk(char* name); -DWORD _stdcall HasFakeTrait(char* name); +DWORD _stdcall HasFakePerk(const char* name); +DWORD _stdcall HasFakeTrait(const char* name); void _stdcall ClearSelectablePerks(); void _stdcall SetPerkFreq(int i); \ No newline at end of file diff --git a/sfall/ScriptExtender.cpp b/sfall/ScriptExtender.cpp index 18decaa1..7dcdd6b4 100644 --- a/sfall/ScriptExtender.cpp +++ b/sfall/ScriptExtender.cpp @@ -1766,12 +1766,14 @@ void LoadGlobalScripts() { dlogr("Finished loading global scripts.", DL_SCRIPT|DL_INIT); } -static DWORD _stdcall ScriptHasLoaded(DWORD script) { - for (DWORD d = 0; d < checkedScripts.size(); d++) { - if (checkedScripts[d] == script) return 0; +static bool _stdcall ScriptHasLoaded(DWORD script) { + for (size_t d = 0; d < checkedScripts.size(); d++) { + if (checkedScripts[d] == script) { + return false; + } } checkedScripts.push_back(script); - return 1; + return true; } // this runs before actually loading/starting the game diff --git a/sfall/ScriptExtender.h b/sfall/ScriptExtender.h index 51090e55..22a10798 100644 --- a/sfall/ScriptExtender.h +++ b/sfall/ScriptExtender.h @@ -72,7 +72,7 @@ void GetAppearanceGlobals(int *race, int *style); void _stdcall RegAnimCombatCheck(DWORD newValue); -DWORD _stdcall ScriptHasLoaded(DWORD script); +bool _stdcall ScriptHasLoaded(DWORD script); // finds procedure ID for given script program pointer and procedure name DWORD GetScriptProcByName(DWORD scriptPtr, const char* procName); // loads script from .int file into scripting engine, fill scriptPtr and proc table diff --git a/sfall/ScriptOps/PerksOp.hpp b/sfall/ScriptOps/PerksOp.hpp index 12a272bc..f6f1818c 100644 --- a/sfall/ScriptOps/PerksOp.hpp +++ b/sfall/ScriptOps/PerksOp.hpp @@ -411,28 +411,24 @@ static void __declspec(naked) fSetPerkboxTitle() { __asm { push ebx; push ecx; - push edx; - push edi; - mov edi, eax; + mov ecx, eax; call interpretPopShort_; - mov edx, eax; - mov eax, edi; + mov edx, eax; + mov eax, ecx; call interpretPopLong_; - cmp dx, VAR_TYPE_STR2; - jz next; - cmp dx, VAR_TYPE_STR; - jnz end; + cmp dx, VAR_TYPE_STR2; + jz next; + cmp dx, VAR_TYPE_STR; + jnz end; next: - mov ebx, eax; - mov eax, edi; + mov ebx, eax; + mov eax, ecx; call interpretGetString_; push eax; call SetPerkboxTitle; end: - pop edi; - pop edx; - pop ecx; - pop ebx; + pop ecx; + pop ebx; retn; } }