diff --git a/artifacts/scripting/sfall function notes.md b/artifacts/scripting/sfall function notes.md index e7c6ceff..759e987e 100644 --- a/artifacts/scripting/sfall function notes.md +++ b/artifacts/scripting/sfall function notes.md @@ -36,8 +36,6 @@ The `force_graphics_refresh` forces the screen to redraw at times when it normal 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. The `get_world_map_x_pos` and `get_world_map_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 `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. - The `get_critter_current_ap` and `set_critter_current_ap` functions should only be used during the target critters turn while in combat. Calling them outside of combat typically returns the critters max AP, but don't rely on that behaviour. (Specifically, if the critter has never before entered combat, it will probably return the critters base AP ignoring any extra bonuses from perks etc.) The **type** value in the weapon knockback functions can be 0 or 1. If 0, the value becomes an absolute distance that targets will be knocked back. If 1, the value is multiplied by the distance they would normally have been knocked back. Weapon knockback modifiers are applied in the order `weapon -> attacker -> target`, so a x2 weapon wielded by an abs 6 attacker hitting a /2 target will knock the target back 3 squares. The knockback functions will not override the stonewall perk or knockdowns resulting from criticals. knockback values set on weapons or critters are not saved, and must be reset each time the player reloads. @@ -104,6 +102,10 @@ FUNCTION REFERENCE ##### `int game_loaded()` - Returns 1 the first time it is called after a new game or game load, and 0 any time after. It works on an individual basis for each script, so one script wont interfere with others. Its primary use is for global scripts, so that they know when to call `set_global_script_repeat`, but it can be called from normal scripts too. +----- +##### `void set_pipboy_available(int available)` +- Sets the availability of the pipboy in the game. Use 0 to disable the pipboy, and 1 or 2 to enable it (value 2 does not mark the `VSUIT_MOVIE` movie as "played"). + ----- ##### `void inc_npc_level(int pid/string name)` - Takes a party member PID or an NPC name (deprecated, for compatibility with sfall 4.1.5/3.8.15 or earlier) as an argument. The NPC must be in your party. @@ -170,7 +172,7 @@ FUNCTION REFERENCE - Accepts a pointer to an object and will remove the script from that object. ----- -##### `void set_script(object, int scriptid)` +##### `void set_script(object, int scriptID)` - Accepts a pointer to an object and **scriptID**, and applies the given script to an object (scriptID accepts the same values as `create_object_sid`) - If used on an object that is already scripted, it will remove the existing script first; you cannot have multiple scripts attached to a single object. Calling `set_script` on `self_obj` will have all sorts of wacky side effects, and should be avoided. - If you add `0x80000000` to the SID when calling `set_script`, `map_enter_p_proc` will be SKIPPED. The `start` proc will always be run. diff --git a/sfall/Modules/ScriptExtender.cpp b/sfall/Modules/ScriptExtender.cpp index e27da7a0..6becc3b7 100644 --- a/sfall/Modules/ScriptExtender.cpp +++ b/sfall/Modules/ScriptExtender.cpp @@ -33,6 +33,7 @@ #include "Scripting\Opcodes.h" #include "Scripting\OpcodeContext.h" #include "Scripting\Handlers\Anims.h" +#include "Scripting\Handlers\Interface.h" #include "Scripting\Handlers\Worldmap.h" #include "ScriptExtender.h" @@ -1144,6 +1145,7 @@ void ScriptExtender::OnGameLoad() { ClearGlobalScripts(); ClearGlobals(); RegAnimCombatCheck(1); + PipboyAvailableRestore(); ForceEncounterRestore(); // restore if the encounter did not happen ObjectName::Reset(); diff --git a/sfall/Modules/Scripting/Handlers/Interface.cpp b/sfall/Modules/Scripting/Handlers/Interface.cpp index 5f0dd084..0fef9c18 100644 --- a/sfall/Modules/Scripting/Handlers/Interface.cpp +++ b/sfall/Modules/Scripting/Handlers/Interface.cpp @@ -43,16 +43,29 @@ void __declspec(naked) op_input_funcs_available() { } } -void __declspec(naked) op_set_pipboy_available() { - __asm { - _GET_ARG_INT(end); - cmp eax, 0; - jl end; - cmp eax, 1; - jg end; - mov byte ptr ds:[FO_VAR_gmovie_played_list][0x3], al; -end: - retn; +static BYTE pipboyMovieCheck = 0; + +void PipboyAvailableRestore() { + if (pipboyMovieCheck) { + SafeWrite8(0x497011, pipboyMovieCheck); + pipboyMovieCheck = 0; + } +} + +void op_set_pipboy_available(OpcodeContext& ctx) { + if (!pipboyMovieCheck) pipboyMovieCheck = *(BYTE*)0x497011; // should be either jnz or jmp(short) + + switch (ctx.arg(0).rawValue()) { + case 0: + fo::ptr::gmovie_played_list[3] = false; + SafeWrite8(0x497011, CodeType::JumpNZ); // restore the vault suit movie check + break; + case 1: + fo::ptr::gmovie_played_list[3] = true; + break; + case 2: + SafeWrite8(0x497011, CodeType::JumpShort); // skip the vault suit movie check + break; } } diff --git a/sfall/Modules/Scripting/Handlers/Interface.h b/sfall/Modules/Scripting/Handlers/Interface.h index f8e429d9..54d87633 100644 --- a/sfall/Modules/Scripting/Handlers/Interface.h +++ b/sfall/Modules/Scripting/Handlers/Interface.h @@ -30,9 +30,11 @@ class OpcodeContext; // input_functions void __declspec() op_input_funcs_available(); -void __declspec() op_set_pipboy_available(); +void op_set_pipboy_available(OpcodeContext&); -void op_key_pressed(OpcodeContext& ctx); +void PipboyAvailableRestore(); + +void op_key_pressed(OpcodeContext&); void __declspec() op_tap_key(); diff --git a/sfall/Modules/Scripting/Opcodes.cpp b/sfall/Modules/Scripting/Opcodes.cpp index ee6f1c62..8a9ffd70 100644 --- a/sfall/Modules/Scripting/Opcodes.cpp +++ b/sfall/Modules/Scripting/Opcodes.cpp @@ -81,6 +81,7 @@ static SfallOpcodeInfo opcodeInfoArray[] = { {0x189, "set_perk_name", op_set_perk_name, 2, false, 0, {ARG_INT, ARG_STRING}}, {0x18a, "set_perk_desc", op_set_perk_desc, 2, false, 0, {ARG_INT, ARG_STRING}}, + {0x18b, "set_pipboy_available", op_set_pipboy_available, 1, false, 0, {ARG_INT}}, {0x190, "get_perk_available", op_get_perk_available, 1, true, 0, {ARG_INT}}, {0x192, "set_critter_current_ap", op_set_critter_current_ap, 2, false, 0, {ARG_OBJECT, ARG_INT}}, @@ -324,7 +325,6 @@ void Opcodes::InitNew() { for (int i = 0x178; i < 0x189; i++) { opcodes[i] = op_set_perk_value; } - opcodes[0x18b] = op_set_pipboy_available; opcodes[0x18c] = op_get_kill_counter; opcodes[0x18d] = op_mod_kill_counter; opcodes[0x18e] = op_get_perk_owed;