diff --git a/artifacts/ddraw.ini b/artifacts/ddraw.ini index 0591d684..52eaa3b6 100644 --- a/artifacts/ddraw.ini +++ b/artifacts/ddraw.ini @@ -215,7 +215,7 @@ HighlightCorpses=0 ;16 - bright yellow ;32 - dark yellow ;64 - purple -;You can set a custom color from the game palette by multiplying the color index value by 256 (available since sfall 3.8.27) +;You can set a custom color from the game palette by multiplying the color index value by 256 (in 3.8.27 or later) OutlineColor=16 ;A key to press to reload your currently equipped weapon or use the active item @@ -298,8 +298,7 @@ DataLoadOrderPatch=1 ;Set to 2 to also load subtitle files from text\\cuts_female\ for female PC FemaleDialogMsgs=0 -;Set to 1 to allow using the special '^' character in dialog msg files to specify the alternative text -;that will be displayed in the dialogue based on the player's gender +;Set to 1 to allow using the caret character '^' in dialog msg files to specify the alternative text based on the player's gender ;The text must be enclosed in angle brackets (example: ) DialogGenderWords=0 @@ -641,14 +640,10 @@ DialogPanelAnimDelay=33 ;Controls the speed of pipboy alarm clock animations (lower - faster; valid range: 0..127) PipboyTimeAnimDelay=50 -;Allows you to directly control other critters in combat -;Set to 0 to disable -;Set to 1 to control all critters in combat (allowed only in sfall debugging mode) -;Set to 2 to control all party members -;Set to 3 to let you order party members to attack specified targets after your first attack instead of controlling them directly -ControlCombat=0 -;If you want to control only specific critters, uncomment the ControlCombatPIDList line and set a comma delimited list of PIDs -;ControlCombatPIDList=62,89,97,107,160,161 +;Set to 1 to let you use the command cursor to specify targets for party members to attack in combat +;Note: The old built-in ControlCombat option is removed in 3.8.39 +;See the example mods in the modders pack for a script-based NPC combat control mod +PartyOrderToAttack=0 ;Changes the way weapon reloading works when you drag ammo onto a weapon in the inventory ;Set to -1 to disable (vanilla behavior with the 'Move Items' window) diff --git a/artifacts/scripting/headers/command_extra.h b/artifacts/scripting/headers/command_extra.h index 85cf6c9d..f1375daf 100644 --- a/artifacts/scripting/headers/command_extra.h +++ b/artifacts/scripting/headers/command_extra.h @@ -1,6 +1,10 @@ #ifndef COMMAND_EXTRA_H #define COMMAND_EXTRA_H +#include "define_lite.h" +#include "define_extra.h" + + #define ammo_caliber(ammoPid) get_proto_data(ammoPid, PROTO_AM_CALIBER) #define obj_name_safe(obj) (obj_name(obj) if obj else "(null)") #define get_active_weapon(critter) critter_inven_obj(critter, (2 - active_hand) if critter == dude_obj else INVEN_TYPE_RIGHT_HAND) diff --git a/artifacts/scripting/headers/lib.strings.h b/artifacts/scripting/headers/lib.strings.h index d2790b9f..942bb3b0 100644 --- a/artifacts/scripting/headers/lib.strings.h +++ b/artifacts/scripting/headers/lib.strings.h @@ -9,6 +9,8 @@ #ifndef LIB_STRINGS_H #define LIB_STRINGS_H +#include "sfall.h" + #define is_in_string(str, sub) (string_pos(str, sub) != -1) #define string_starts_with(str, sub) (substr(str, 0, strlen(sub)) == sub) @@ -166,14 +168,22 @@ end * Useful in cunjunction with is_in_array() */ procedure string_split_ints(variable str, variable split) begin - variable i := 0; - variable list; + variable n := 0; + variable list, result, val; + + if (str == "" or typeof(str) != VALTYPE_STR) then + return temp_array_list(0); + list := string_split(str, split); - while (i < len_array(list)) do begin - list[i] := atoi(list[i]); - i++; + result := temp_array_list(0); + foreach (val in list) begin + if (val != "") then begin + resize_array(result, n + 1); + result[n] := atoi(val); + n++; + end end - return list; + return result; end diff --git a/artifacts/scripting/headers/sfall.h b/artifacts/scripting/headers/sfall.h index b162d18a..989a59fd 100644 --- a/artifacts/scripting/headers/sfall.h +++ b/artifacts/scripting/headers/sfall.h @@ -298,6 +298,7 @@ #define exec_map_update_scripts sfall_func0("exec_map_update_scripts") #define floor2(value) sfall_func1("floor2", value) #define get_can_rest_on_map(map, elev) sfall_func2("get_can_rest_on_map", map, elev) +#define get_combat_free_move sfall_func0("get_combat_free_move") #define get_current_inven_size(obj) sfall_func1("get_current_inven_size", obj) #define get_current_terrain_name sfall_func0("get_terrain_name") #define get_cursor_mode sfall_func0("get_cursor_mode") diff --git a/artifacts/scripting/sfall function notes.md b/artifacts/scripting/sfall function notes.md index 72efa512..9e2b4315 100644 --- a/artifacts/scripting/sfall function notes.md +++ b/artifacts/scripting/sfall function notes.md @@ -1048,11 +1048,18 @@ sfall_funcX metarule functions - `centerMult/targetMult`: multiplier values are capped at divisor values - __NOTE:__ refer to the description of **ComputeSpray_\*** settings in ddraw.ini for details of the bullet distribution of burst attacks +---- +##### get_combat_free_move +`int sfall_func0("get_combat_free_move")` + +- Returns available "bonus move" points of the current critter's turn. For NPCs, this is always 0 unless changed by `set_combat_free_move`. + ---- ##### set_combat_free_move `void sfall_func1("set_combat_free_move", int value)` - Allows changing "bonus move" points (yellow lights on the interface bar) that can only be used for movement, not attacking +- Can be called from `HOOK_COMBATTURN` at the start of the turn (will not work on `dude_obj`) - Can be called from `HOOK_STDPROCEDURE` with `combat_proc` event (will work on both NPCs and `dude_obj`) diff --git a/sfall/Modules/PartyControl.cpp b/sfall/Modules/PartyControl.cpp index 1fae8f99..352df371 100644 --- a/sfall/Modules/PartyControl.cpp +++ b/sfall/Modules/PartyControl.cpp @@ -728,7 +728,7 @@ void PartyControl::init() { // Display party member's current level & AC & addict flag if (IniReader::GetConfigInt("Misc", "PartyMemberExtraInfo", 0)) { - dlogr("Applying display NPC extra info patch.", DL_INIT); + dlogr("Applying display extra info patch for party members.", DL_INIT); HookCall(0x44926F, gdControlUpdateInfo_hook); Translate::Get("sfall", "PartyLvlMsg", "Lvl:", levelMsg, 12); Translate::Get("sfall", "PartyACMsg", "AC:", armorClassMsg, 12); diff --git a/sfall/Modules/Scripting/Handlers/Combat.cpp b/sfall/Modules/Scripting/Handlers/Combat.cpp index 23077750..e9d7ff24 100644 --- a/sfall/Modules/Scripting/Handlers/Combat.cpp +++ b/sfall/Modules/Scripting/Handlers/Combat.cpp @@ -265,6 +265,10 @@ void mf_set_spray_settings(OpcodeContext& ctx) { BurstMods::SetComputeSpraySettings(centerMult, centerDiv, targetMult, targetDiv); } +void mf_get_combat_free_move(OpcodeContext& ctx) { + ctx.setReturn(*fo::ptr::combat_free_move); +} + void mf_set_combat_free_move(OpcodeContext& ctx) { long value = ctx.arg(0).rawValue(); if (value < 0) value = 0; diff --git a/sfall/Modules/Scripting/Handlers/Combat.h b/sfall/Modules/Scripting/Handlers/Combat.h index 9ccee2a6..7ed5aae5 100644 --- a/sfall/Modules/Scripting/Handlers/Combat.h +++ b/sfall/Modules/Scripting/Handlers/Combat.h @@ -58,6 +58,8 @@ void mf_combat_data(OpcodeContext&); void mf_set_spray_settings(OpcodeContext&); +void mf_get_combat_free_move(OpcodeContext&); + void mf_set_combat_free_move(OpcodeContext&); } diff --git a/sfall/Modules/Scripting/Handlers/Metarule.cpp b/sfall/Modules/Scripting/Handlers/Metarule.cpp index 2f8acf1e..729a713e 100644 --- a/sfall/Modules/Scripting/Handlers/Metarule.cpp +++ b/sfall/Modules/Scripting/Handlers/Metarule.cpp @@ -83,6 +83,7 @@ static const SfallMetarule metarules[] = { {"exec_map_update_scripts", mf_exec_map_update_scripts, 0, 0}, {"floor2", mf_floor2, 1, 1, 0, {ARG_NUMBER}}, {"get_can_rest_on_map", mf_get_rest_on_map, 2, 2, -1, {ARG_INT, ARG_INT}}, + {"get_combat_free_move", mf_get_combat_free_move, 0, 0}, {"get_current_inven_size", mf_get_current_inven_size, 1, 1, 0, {ARG_OBJECT}}, {"get_cursor_mode", mf_get_cursor_mode, 0, 0}, {"get_flags", mf_get_flags, 1, 1, 0, {ARG_OBJECT}},