Compare commits

...
58 Commits
Author SHA1 Message Date
NovaRain 63606b96d7 Updated version number and changelog
Minor code edits to BugFixes.cpp.
2026-06-03 19:17:48 +08:00
NovaRain d6946c8b65 Re-added NumberPatchLoop option to ddraw.ini 2026-06-01 13:29:39 +08:00
NovaRain 96eab6efff Tweaked obj distance check in action_* engine functions
* use path length instead of tile distance to determine whether to walk
or run to interact with objects.

(ref. fallout2-ce/fallout2-ce#248)
2026-05-31 21:13:26 +08:00
NovaRain e277bbbe9a Reordered functions in MiscPatches.cpp & Worldmap.cpp
* grouping patch functions and their ASM hacks together for easier
checking.
2026-05-29 22:38:06 +08:00
NovaRain 1f18d06f9b Reduced the number of trailing NOPs for MakeCall/Jump
* when the trailing length is longer than 4 bytes, it will use a mix of
5-byte long NOPs and single-byte NOPs.
2026-05-29 09:18:23 +08:00
NovaRain 9f0a3e43de Fixed typo in sound debug output 2026-05-28 13:15:23 +08:00
NovaRain 1e1eeda287 Corrected the object ID range for party members 2026-05-27 09:52:31 +08:00
NovaRain 17383dbd64 Fixed set_unique_id script function
* it unassigned unique ID even when the object doesn't have one.
* it didn't sync the attached script's owner id after unassignment.

Added a safeguard to prevent item_identical function returning false
when comparing a unique_id item to itself.

(ref. fallout2-ce/fallout2-ce#466)
2026-05-25 14:42:38 +08:00
NovaRain d74ec5f4fa Removed ExtraSaveSlots from ddraw.ini (always enabled)
Changed the maximum number of save slots to 1000 (10k was overkill).
2026-05-23 00:12:57 +08:00
NovaRainandGitHub 45b1cce949 Merge pull request #626 from sfall-team/dependabot/bundler/docs/faraday-2.14.2
Bump faraday from 2.14.1 to 2.14.2 in /docs
2026-05-19 00:12:03 +08:00
dependabot[bot]andGitHub 5ffa2e1f79 Bump faraday from 2.14.1 to 2.14.2 in /docs
Bumps [faraday](https://github.com/lostisland/faraday) from 2.14.1 to 2.14.2.
- [Release notes](https://github.com/lostisland/faraday/releases)
- [Changelog](https://github.com/lostisland/faraday/blob/main/CHANGELOG.md)
- [Commits](https://github.com/lostisland/faraday/compare/v2.14.1...v2.14.2)

---
updated-dependencies:
- dependency-name: faraday
  dependency-version: 2.14.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-18 15:11:58 +00:00
NovaRain d9ee190435 Added a new value to InstantWeaponEquip
Tweaked the animation sequence when interacting with scenery or using
an item on an object.
2026-05-18 14:02:10 +08:00
NovaRain b4495f01e9 Changed the character portrait on the char screen
* now it's always in ANIM_stand instead of current action frame.
2026-05-17 16:57:30 +08:00
NovaRain d8ae063298 Fixed the morning start time while traveling on the world map
* it starts at 6:01 instead of 6:00, inconsistent with afternoon (12:00)
and night (18:00).

Fixed potential index out of bounds error in wmMapIdxToName_.

(ref. fallout2-ce/fallout2-ce#453)
2026-05-13 10:05:46 +08:00
NovaRain 9b92adfa51 Disallowed negative cost for set/get_inven_ap_cost 2026-05-11 13:34:18 +08:00
NovaRainandGitHub 67c6ee6245 Merge pull request #625 from sfall-team/dependabot/bundler/docs/nokogiri-1.19.3
Bump nokogiri from 1.19.1 to 1.19.3 in /docs
2026-05-09 00:14:55 +08:00
dependabot[bot]andGitHub 55e61c54d2 Bump nokogiri from 1.19.1 to 1.19.3 in /docs
Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.19.1 to 1.19.3.
- [Release notes](https://github.com/sparklemotion/nokogiri/releases)
- [Changelog](https://github.com/sparklemotion/nokogiri/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.19.1...v1.19.3)

---
updated-dependencies:
- dependency-name: nokogiri
  dependency-version: 1.19.3
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-08 16:11:57 +00:00
NovaRain 06c5779475 Code edits to ApplyInvenApCostPatch 2026-05-08 14:40:42 +08:00
NovaRain 53a2a11521 Tweaked the position of item counter/timer window
* now they are centered in the game view (CE style) except when in
dialog screen with DIALOG_SCRN_BACKGROUND=0.
2026-05-06 21:18:53 +08:00
NovaRain c3dae6db57 Increased decompression buffer size to 4KB
(ref. fallout2-ce/fallout2-ce#439)
2026-05-05 21:11:12 +08:00
NovaRain 86e1425044 Added a tweak to center inventory windows when not using HRP
Shorten inventory window enum names.
2026-05-04 11:02:44 +08:00
NovaRain b54b86b33c Cosmetic edits: remove unnecessary size directives
* verified the compiled binary is still the same.
2026-05-03 09:31:51 +08:00
NovaRain f4eaaccc57 Added a file size check for scripts
* this is for filtering out some clearly defective (or not even valid)
scripts.
2026-04-24 21:37:46 +08:00
NovaRain fb47779d4c Fixed set/remove_script script functions
* they didn't set the script index number on non-critter objects.

Changed objects_in_radius to accept a radius of 0.

Edits to scripting documents.
2026-04-23 22:24:37 +08:00
NovaRain 91cc37dc17 Fixed HOOK_REMOVEINVENOBJ not being triggered
* when using drug/misc item from active item slots (closes #623)
2026-04-21 21:25:53 +08:00
NovaRain 9c6d7bfdd2 Moved HP/flag setting earlier in critter_kill_ engine function
(mainly for HOOK_ONDEATH, ref. fallout2-ce/fallout2-ce#384)
2026-04-20 09:52:01 +08:00
NovaRain 3b836fdf73 Replaced serial single-byte NOPs with long NOPs
(the sequence is 5-byte long NOPs with trailing single-byte NOPs)
2026-04-19 20:38:10 +08:00
NovaRain e3a133e3aa Fixed ONDEATH hook being incorrectly triggered by non-critter objects
(when calling kill_critter on a non-critter obj)
2026-04-17 23:05:56 +08:00
NovaRain 81e612f383 Added object type validation to item_weight metarule
Fixed set_critter_current_ap and set_combat_free_move to update
player's AP lights only in combat

Edits to scripting documents.

(ref. fallout2-ce/fallout2-ce#380)
2026-04-17 11:54:35 +08:00
NovaRain 490934bb3c Fixed AP cost display on game load when using CALCAPCOST hook
(ref. fallout2-ce/fallout2-ce#376)
2026-04-16 10:29:46 +08:00
NovaRain 68d721773e Simplified the code in commit db4f0cb8 2026-04-14 21:59:10 +08:00
NovaRain 31df2d5c98 Added #pragma sce to all scripts that require -s option 2026-04-14 11:27:22 +08:00
NovaRain db4f0cb8d5 Fixed garbled colors when SkipOpeningMovies=1
(ref. fallout2-ce/fallout2-ce#372)
2026-04-14 11:03:39 +08:00
NovaRain 67c74888b4 Fixed a visual glitch on the char screen when selecting gain xxx perks
(ref. fallout2-ce/fallout2-ce#367)
2026-04-11 21:33:33 +08:00
NovaRain 1ee135611d Increased the maximum party member level from 6 to 10 (closes #621)
Updated scripting documents.

* the game reserves 10 level-up messages for each party member. More
level-ups require either more hacks or renumbering all level-up messages
in misc.msg. Otherwise, one will start using others' lines (e.g. Sulik
says Lenny's lines after lv10).
2026-04-11 00:01:25 +08:00
NovaRain bfbdea7e83 Removed GlobalScriptPaths option
* storing global scripts across multiple paths is almost never needed,
and no publicly available mod really uses the option. If one doesn't
want to put their global scripts in the main folder, they can always
package the scripts in a mod dat file/folder instead.
2026-04-10 08:54:46 +08:00
NovaRainandGitHub 802a49b627 Merge pull request #620 from sfall-team/dependabot/bundler/docs/addressable-2.9.0
Bump addressable from 2.8.9 to 2.9.0 in /docs
2026-04-08 18:17:27 +08:00
dependabot[bot]andGitHub d619c01d81 Bump addressable from 2.8.9 to 2.9.0 in /docs
Bumps [addressable](https://github.com/sporkmonger/addressable) from 2.8.9 to 2.9.0.
- [Changelog](https://github.com/sporkmonger/addressable/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sporkmonger/addressable/compare/addressable-2.8.9...addressable-2.9.0)

---
updated-dependencies:
- dependency-name: addressable
  dependency-version: 2.9.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-08 09:45:13 +00:00
NovaRain a273969756 Fixed crash when calling proto_data with invalid data member
(ref. BGforgeNet/Fallout2_Restoration_Project#381)
2026-04-05 08:29:20 +08:00
NovaRain a14f3d14a3 Updated resource files for the previous commit 2026-04-02 13:39:59 +08:00
NovaRain cc61526f69 Removed AllowLargeTiles option
* Originally, its goal was to bypass the tile FRM limit and save
people's time from splitting tiles. But no one has really used this
option since sfall 2.0 (no bug reports about being broken for many
years). And boosting the limit to 16383 should practically solve the
first goal.

* In the end the option doesn't really do what its name suggests and is
completely unused. Its tile auto-splitting function is also not very
practical.
2026-04-02 11:47:12 +08:00
NovaRain 5c4b1ffea1 Updated nokogiri version in Gemfile.lock 2026-04-01 22:31:35 +08:00
NovaRain 4e9eb06988 Try updating some components in Gemfile 2026-04-01 22:27:49 +08:00
NovaRain 7cd30956a7 Edited the description of inc_npc_level in scripting docs
Cosmetic edits: removed trailing spaces in some source files.
2026-04-01 22:24:53 +08:00
NovaRain c28d8c0d2b Deprecated two-argument form of add_extra_msg_file
Edits to scripting documents.
2026-03-26 12:09:32 +08:00
NovaRain 7b3f69f496 Fixed glitched map when the encounter table has no available entries
(ref. fallout2-ce/fallout2-ce#313)

Updated sslc document.
2026-03-20 11:18:45 +08:00
NovaRainandGitHub 6d6d6a40f9 Merge pull request #619 from sfall-team/dependabot/bundler/docs/json-2.19.2
Bump json from 2.18.1 to 2.19.2 in /docs
2026-03-19 20:53:07 +08:00
dependabot[bot]andGitHub 5e8c376ecf Bump json from 2.18.1 to 2.19.2 in /docs
Bumps [json](https://github.com/ruby/json) from 2.18.1 to 2.19.2.
- [Release notes](https://github.com/ruby/json/releases)
- [Changelog](https://github.com/ruby/json/blob/master/CHANGES.md)
- [Commits](https://github.com/ruby/json/compare/v2.18.1...v2.19.2)

---
updated-dependencies:
- dependency-name: json
  dependency-version: 2.19.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-19 12:51:56 +00:00
Vlad KandGitHub 90e18faefc Merge pull request #617 from sfall-team/feature/nested-array-expressions
Support for nested array expressions (#616)
2026-03-15 13:47:33 +01:00
phobos2077 9cdbc01728 Add script procs for creating permanent arrays from nested expressions, add arrays testcase script, fix load_array not accepting float as array key 2026-03-15 13:41:38 +01:00
phobos2077 168687c9ee Support for nested expressions (#616)
- Doesn't require any new opcode
- temp_array is repurposed as sub-expression terminator
- Accompanied by sslc update
- Backwards compatible with old scripts using single-layer expressions
2026-03-15 12:47:12 +01:00
NovaRain 41fd1e3495 Fixed +/- not updating brightness slider when used on the Pref screen
(ref. fallout2-ce/fallout2-ce#298)
2026-03-15 07:55:23 +08:00
NovaRain a8490f1913 Changed the timing of setting OPTIONS game mode flag
* now it is toggled when creating/deleting the Preferences window.
2026-03-14 20:20:33 +08:00
NovaRain f5bc53d780 Fixed the root cause of crash in PrepareGlobalScriptsListByMask
* Calling convention violation - v141_xp uses ebx to store reference,
but db_get_file_list does not preserve it.
* v140_xp uses esi instead, which is preserved by the engine function.
* Reverted some code changes in ScriptExtender.cpp.
2026-03-12 21:32:04 +08:00
NovaRainandGitHub 2db7492648 Merge pull request #618 from sfall-team/dependabot/github_actions/actions/upload-artifact-7
Bump actions/upload-artifact from 6 to 7
2026-03-01 09:37:10 +08:00
dependabot[bot]andGitHub bf4b50d549 Bump actions/upload-artifact from 6 to 7
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 6 to 7.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-01 01:14:17 +00:00
phobos2077 fe24221456 Cleanup debugging leftovers 2026-02-28 15:58:57 +01:00
phobos2077 b58c26a401 Fixed crash in PrepareGlobalScriptsListByMask in ReleaseXP build when using v141_xp toolset
- Passing a raw pointer to fileMask's char array to db_get_file_list seemed to be the main cause
- I've also replaced the use of _strlwr with ToLowerCase on the string copy, to avoiding editing strings returned from engine function in-place
- Clarified the constness of file list variable used by db_*_file_list for the same reason
2026-02-28 15:54:28 +01:00
95 changed files with 1937 additions and 1275 deletions
+1 -1
View File
@@ -55,7 +55,7 @@ jobs:
shell: bash
- name: Upload artifacts
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: sfall-build
path: sfall-build
+32 -2
View File
@@ -1,7 +1,37 @@
# Changelog
## 4.5
* Fixed garbled colors during the fade to the main menu on startup when **SkipOpeningMovies** is enabled
* Fixed the AP cost display not updating on game load when using `HOOK_CALCAPCOST` hook script
* Fixed `load_array` script function not accepting floats as array keys
* Fixed a crash when calling `proto_data` with an invalid data member value
* Fixed `set_critter_current_ap` and `set_combat_free_move` script functions to update the player's AP lights only in combat
* Fixed `set/remove_script` script functions not setting the script index number on an object properly
* Fixed `set_unique_id` script function to prevent it from reassigning an object ID when unnecessary
* Fixed `ONDEATH` hook to prevent it from being triggered by non-critter objects
* Fixed `REMOVEINVENOBJ` hook not being triggered when using an item from active item slots while in the inventory screen
* Changed `add_extra_msg_file` script function to mark the two-argument form as deprecated
* Changed `objects_in_radius` script function to accept a radius of 0
* Changed the character portrait on the character screen (from the **hero appearance mod**) to always show the standing pose
* Re-added **NumberPatchLoop** option from older versions to `ddraw.ini`
* Removed **AllowLargeTiles** option because its functionality is impractical and has never been used
* Removed **GlobalScriptPaths** option because storing global scripts across multiple paths is almost never needed
* Removed **ExtraSaveSlots** option from `ddraw.ini`. Now additional pages of save slots are always available, up to a maximum of **1000** slots
* Added a fix for the `+/-` keys not updating the brightness slider when used on the preferences screen
* Added a fix for getting stuck on an empty map when the encounter table has no available entries
* Added a fix for a visual glitch on the character screen when selecting perks that modify SPECIAL stats
* Added a fix for the morning start time used to determine random encounter frequency
* Added a tweak to center inventory windows horizontally when not using the hi-res patch
* Added a tweak to the animation sequence when interacting with scenery or using an item on an object
* Added a tweak to use path length instead of tile distance to determine whether to walk or run to interact with objects
* Added a new value to **InstantWeaponEquip** to skip weapon equip/unequip animations only when interacting with objects
* Added object type validation to `item_weight` script function to prevent potential issues
* Added a file size check for scripts to filter out clearly defective ones
* Added support for nested array expressions (`compile.exe` in the **modders pack** is also updated)
* Increased the maximum party member level from 6 to 10
## 4.4.9.1
* Fixed a crash bug introduced in 4.4.6 when the player is hit and combat starts at the same time
* Fixed a crash bug introduced in 4.4.6 when a critter is hit and combat starts at the same time
## 4.4.9
* Fixed the edge-scrolling speed when using the game speed tweak
@@ -1070,7 +1100,7 @@ Original engine bug fixes and various features based on the work by Crafty:
Original engine bug fixes and various features based on the work by Crafty:
* Fixed a crash bug introduced with the inventory drag and drop fix
* Added a new value to **SpeedInterfaceCounterAnims** to update the HP/AC counters instantly when the number is not negative
* Added an option to skip weapon equip/unequip animations when performing various actions
* Added an option to skip weapon equip/unequip animations during various actions
* Added an option to control the speed of pipboy alarm clock animations
* Added an option to change the carry weight limit
+13 -19
View File
@@ -1,5 +1,5 @@
;sfall configuration settings
;v4.4.9.1
;v4.5
[Main]
;Set to 1 to enable the built-in High Resolution Patch mode that is similar to the hi-res patch by Mash
@@ -309,8 +309,10 @@ WorldMapSlots=0
UseFileSystemOverride=0
;To use a patch file other than patch000.dat, uncomment the next line and add your new file name
;If you want to load multiple patch files (up to 1000) at once, you can include a %d in the file name (sprintf syntax)
;If you want to load multiple patch files at once, you can include a %d in the file name (sprintf syntax)
;PatchFile=patch%03d.dat
;Uncomment the next line to change the number of patch files to load (valid range: 1..1000; default is 100)
;NumberPatchLoop=100
;Set to 1 to change the order of how the engine loads game data
;Old: patchXXX.dat > critter_patches > critter_dat > f2_res_patches > f2_res_dat > master_patches > master_dat
@@ -477,11 +479,6 @@ SkipOpeningMovies=0
;Set to 0 to disable
NPCsTryToSpendExtraAP=0
;Allows the use of tiles over 80x36 in size. sfall will just split and resave them to art\tiles\zzz####.frm at startup
;Set to 1 to check all tiles on started (slow, but can also be useful for checking the correct size of your new tiles)
;Set to 2 if you provide a XLtiles.lst file in art\tiles\ containing a list of the tile indexes that need checking
AllowLargeTiles=0
;Set to 1 to boost the maximum number of tile FRMs from 4096 to 16383
;This option is always enabled in 4.3.7/3.8.37 or later and cannot be disabled (kept for reference only)
MoreTiles=1
@@ -519,14 +516,15 @@ UseScrollingQuestsList=1
;ConsoleOutputPath=console.txt
;Set to 1 to add additional pages of save slots
ExtraSaveSlots=0
;This option is always enabled in 4.5/3.8.50 or later and cannot be disabled (kept for reference only)
ExtraSaveSlots=1
;To use more than one save slot for quick saving (F6 key) without picking a slot beforehand, set the next two lines
;To use more than one save slot for quick saving (F6 key) without picking a slot beforehand, set the next two options
;Quick save will cyclically overwrite saves from the first slot on the specified page to the last slot on the n-th page
;AutoQuickSave sets how many pages you want to use for quick saving (valid range: 1..10)
;AutoQuickSave sets the number of pages used for quick saving (valid range: 1..10)
;Set to 0 to disable
AutoQuickSave=0
;AutoQuickSavePage is the page number to start at if ExtraSaveSlots is enabled (valid range: 0..999)
;AutoQuickSavePage sets the starting page number for quick saving (valid range: 0..99)
;Set to -1 to use the current selected page (not recommended)
AutoQuickSavePage=1
@@ -694,7 +692,8 @@ ActiveGeigerMsgs=1
;Set to 1 to fix the bug of being unable to sell used geiger counters or stealth boys
CanSellUsedGeiger=1
;Set to 1 to skip weapon equip/unequip animations when performing various actions
;Set to 1 to skip weapon equip/unequip animations during various actions
;Set to 2 to skip these animations only when interacting with objects
InstantWeaponEquip=0
;To add additional game msg files, uncomment the next line and set a comma-delimited list of filenames without .msg extension
@@ -846,11 +845,6 @@ DivisionOperatorFix=1
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
[Scripts]
;Comma-separated list of masked paths to load global scripts from
;Only use single backslash \ as the directory separator
;Paths outside of scripts folder are supported
GlobalScriptPaths=scripts\gl*.int,scripts\sfall\gl*.int
;Uncomment the option to specify an additional directory for ini files used by scripts
;The game will search for ini files first relative to this directory and then relative to the root directory if not found
;The path length is limited to 61 characters
@@ -890,8 +884,8 @@ SkipCompatModeCheck=0
;show_script_messages=1
;show_tile_num=1
;[sound]
;debug=0
;debug_sfxc=0
;debug=1
;debug_sfxc=1
;-------
DebugMode=0
@@ -7,10 +7,13 @@ Auto Doors mod v1.2 for Fallout 2 by Mr.Stalin
Requires sfall 3.7b or higher
NOTE: this script requires compiler from sfall modderspack with -s option (short circuit evaluation)
NOTE: this script requires compiler from sfall modderspack with -s option
(short circuit evaluation)
*/
#pragma sce
/* Include Files */
#include "..\headers\define.h"
//#include "..\headers\command.h"
@@ -13,14 +13,15 @@ NOTE: this script requires compiler from sfall modderspack with -s option
*/
procedure start;
procedure afterhitroll_handler;
#pragma sce
#include "..\headers\define.h"
#include "..\headers\sfall\sfall.h"
#include "..\headers\sfall\define_extra.h"
procedure start;
procedure afterhitroll_handler;
procedure start begin
if game_loaded then begin
register_hook_proc(HOOK_AFTERHITROLL, afterhitroll_handler);
+2
View File
@@ -19,6 +19,8 @@
**/
#pragma sce
#include "main.h"
//#include "..\..\..\!SRC\headers\define.h"
+2
View File
@@ -13,6 +13,8 @@
*/
#pragma sce
#include "main.h"
#define IS_ARMOR(item) (obj_type(item) == OBJ_TYPE_ITEM and obj_item_subtype(item) == item_type_armor)
+2
View File
@@ -16,6 +16,8 @@
*/
#pragma sce
#include "..\headers\global.h"
#include "..\headers\critrpid.h"
#include "main.h"
+13 -13
View File
@@ -164,23 +164,23 @@ ___
_*mixed means any type_
#### `int create_array(int size, int flags)`
- creates permanent array (but not "saved")
- if `size >= 0`, creates list with given size
- if `size == -1`, creates map (associative array)
- creates a permanent array (but not "saved")
- if `size >= 0`, creates a list with the given size
- if `size == -1`, creates a map (associative array)
- if `size == -1` and `flags == 2`, creates a "lookup" map (associative array) 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) key value
* NOTE: in earlier versions (up to 4.1.3/3.8.13) the second argument is not used, just use 0
- returns array ID (valid until array is deleted)
#### `int temp_array(int size, int flags)`
- works exactly like `create_array`, only created array becomes "temporary"
- works exactly like `create_array`, only the created array becomes "temporary"
#### `void fix_array(int arrayID)`
- changes "temporary" array into "permanent" ("permanent" arrays are not automatically saved into savegames)
- changes a "temporary" array into "permanent" ("permanent" arrays are not automatically saved into savegames)
#### `void set_array(int arrayID, mixed key, mixed value)`
- sets array value
- if used on list, "key" must be numeric and within valid index range (0..size-1)
- if used on map, key can be of any type
- if used on lists, "key" must be numeric and within valid index range (0..size-1)
- if used on maps, "key" can be of any type
- to "unset" a value from map, just set it to zero (0)
* NOTE: to add a value of 0 for the key, use the float value of 0.0
- this works exactly like statement: `arrayID[key] := value;`
@@ -200,17 +200,17 @@ _*mixed means any type_
- if array was "saved", it will be removed from a savegame
#### `mixed scan_array(int arrayID, mixed value)`
- searches for a first occurrence of given value inside given array
- searches for the first occurrence of the given value inside the given array
- if value is found, returns its index (for lists) or key (for maps)
- if value is not found, returns -1 (be careful, as -1 can be a valid key for a map)
#### `int len_array(int arrayID)`
- returns number of elements or key=>value pairs in a given array
- if array is not found, returns -1 (can be used to check if given array exist)
- returns number of elements or key=>value pairs in the given array
- if array is not found, returns -1 (can be used to check if the given array exist)
#### `void save_array(mixed key, int arrayID)`
- makes the array saveable; it will be saved in **sfallgv.sav** file when saving the game
- array ID is associated with given "key"
- array ID is associated with the given "key"
- array becomes permanent (if it was temporary) and "saved"
- key can be of any type (int, float or string)
- if you specify 0 as the key for the array ID, it will make the array "unsaved"
@@ -223,11 +223,11 @@ _*mixed means any type_
- don't use it directly; it is generated by the compiler in foreach loops
- for lists, returns index back (no change)
- for maps, returns a key at the specified numeric index (don't rely on the order in which keys are stored though)
- can be checked if given array is associative or not, by using index (-1): 0 - array is list, 1 - array is map
- can be checked if the given array is associative or not, by using index (-1): 0 - array is a list, 1 - array is a map
#### `int arrayexpr(mixed key, mixed value)`
- don't use it directly; it is used by compiler to create array expressions
- assigns value to a given key in an array, created by last `create_array` or `temp_array` call
- assigns value to the given key in an array, created by last `create_array` or `temp_array` call
- always returns 0
@@ -323,6 +323,8 @@ Syntax which requires sfall for compiled scripts to be interpreted is marked by
__NOTE:__ Just like `for` loop, `continue` statement will respect increments of a hidden counter variable, so you can safely use it inside `foreach`.
- `#pragma sce` directive. If present anywhere in the script source, it will enable short-circuit evaluation for all the logical `AND` and `OR` operators, even if the command line option `-s` is not used.
---
### Fixes
@@ -348,6 +350,10 @@ There are several changes in this version of sslc which may result in problems f
### Changelog
**sfall 4.4.10:**
- added `#pragma sce` directive
- added support for nested array expressions
**sfall 4.4.7:**
- fixed leftover stack data caused by the `break` statement
- added Linux & WebAssembly builds
+58 -37
View File
@@ -565,7 +565,7 @@
doc: |
Used to play `mp3/wav/wma` files. The path given is relative to the Fallout folder. Specify mode as 1 to loop the file continuously, 2 to replace the current background game music with playing the specified file in loop mode, or 0 to play the file once. If you don't wish to loop, `play_sfall_sound` returns 0. If you do loop, it returns an ID which can be passed back to `stop_sfall_sound` when you want to stop the effect. All sounds effects will be stopped on game reload, looping or not. Does not require `AllowDShowSound` to be set to 1 in `ddraw.ini`.
Starting from sfall 4.2.8/3.8.28, you can pass a value in the `mode` argument for a reduced sound volume. To set the volume, you need to convert the number to hexadecimal and use the argument format `0xZZZZ000Y`, where `ZZZZ` is the volume reduction value in range from 0 to 32767 (the value 32767 is mute), and `Y` is the playback mode.
Starting from sfall 4.2.8/3.8.28, you can pass a value in the `mode` argument for a reduced sound volume. To set the volume, you need to convert the number to hexadecimal and use the argument format `0xZZZZ000Y`, where `ZZZZ` is the volume reduction value in the range of 0 to 32767 (the value 32767 is mute), and `Y` is the playback mode.
- name: stop_sfall_sound
detail: void stop_sfall_sound(int soundID)
opcode: 0x822c
@@ -763,7 +763,7 @@
- makes the specified item (pid) an explosive item like Dynamite or Plastic Explosives
- `maxDamage` is optional
- `activePid` is for an item with an active timer, can be the same as the `pid` argument
- the item proto must be the **Misc Item** type and have the **Use** action flag
- the item proto must be of the **Misc Item** type and have the **Use** action flag
- minDamage/maxDamage are the minimum and maximum explosion damage
- using the function on an item that is already set as an explosive will override its previous settings
- NOTE: this function does not work for pids of Dynamite and Plastic Explosives
@@ -794,12 +794,14 @@
doc: Should work like `art_change_fid_num` but in `reg_anim` sequence.
opcode: 0x825e
- name: reg_anim_take_out
detail: void reg_anim_take_out(ObjectPtr, holdFrameID, delay)
doc: Plays "take out weapon" animation for given `holdFrameID`. It is not required to have such weapon in critter's inventory.
detail: void reg_anim_take_out(ObjectPtr, int weaponCode, int delay)
doc: |
Plays "take out weapon" animation for the given `weaponCode` (see `WPN_ANIM_*` constants in **define_extra.h**).
- It is not required for the critter to have this type of weapon in its inventory.
opcode: 0x825f
- name: reg_anim_turn_towards
detail: void reg_anim_turn_towards(ObjectPtr, int tile/target, delay)
doc: Makes object change its direction to face given tile number or target object.
doc: Makes object change its direction to face the given tile number or target object.
opcode: 0x8260
- name: reg_anim_callback
detail: void reg_anim_callback(procedure proc)
@@ -816,7 +818,9 @@
items:
- name: art_exists
detail: int art_exists(int artFID)
doc: 'checks if given artFID exists in the game. Useful when you want to check if critter can use specific weapon: `art_exists((artFid bwand 0xffff0fff) bwor (weaponAnim * 0x1000))`.'
doc: |
Checks if the given `artFID` exists in the game.
- Useful when you want to check if critter can use specific weapon: `art_exists((artFid bwand 0xffff0fff) bwor (weaponAnim * 0x1000))`.
opcode: 0x8274
- name: refresh_pc_art
detail: void refresh_pc_art
@@ -848,18 +852,20 @@
opcode: 0x824b
- name: tile_light
detail: int tile_light(int elevation, int tileNum)
doc: Returns light intensity at the given tile in range from 0 to 65535.
doc: Returns light intensity at the given tile in the range of 0 to 65536.
opcode: 0x826d
- name: tile_get_objs
detail: array tile_get_objs(int tileNum, int elevation)
doc: Returns an array of all objects at given tile. It will include any hidden, dead or system objects (like cursor), so make sure to check properly when iterating.
doc: |
Returns an array of all objects at the given tile.
- It will include any hidden, dead or system objects (like cursor), so make sure to check properly when iterating.
opcode: 0x8270
- name: tile_refresh_display
detail: void tile_refresh_display
doc: Redraws the game scene (tiles, walls, objects, etc.).
- name: obj_blocking_tile
detail: ObjectPtr obj_blocking_tile(int tileNum, int elevation, int blockingType)
doc: Returns first object blocking given tile using given blocking function or 0 if tile is clear.
doc: Returns the first object blocking the given tile using the given blocking function, or 0 if the tile is clear.
opcode: 0x826f
- name: tile_by_position
@@ -870,20 +876,26 @@
macro: sfall.h
- name: get_tile_ground_fid
detail: int get_tile_ground_fid(int tileNum, int elevation)
doc: Returns FID of a ground tile at given tile number and elevation.
doc: Returns FID of a ground tile at the given tile number and elevation.
macro: sfall.h
- name: get_tile_roof_fid
detail: int get_tile_roof_fid(int tileNum, int elevation)
doc: Returns FID of a roof tile at given tile number and elevation. Note that FID of 1 is used when there is no actual roof.
doc: Returns FID of a roof tile at the given tile number and elevation. Note that FID of 1 is used when there is no actual roof.
macro: sfall.h
- name: obj_blocking_line
detail: ObjectPtr obj_blocking_line(ObjectPtr objFrom, int tileTo, int blockingType)
doc: Returns first object which blocks direct linear path from `objFrom` to `tileTo` using selected blocking function (see `BLOCKING_TYPE_*` constants in **sfall.h**). If path is clear (no blocker was encountered by selected function) - returns 0. `objFrom` is always excluded from calculations, but is required to be a valid object.
doc: |
Returns the first object which blocks direct linear path from `objFrom` to `tileTo` using selected blocking function (see `BLOCKING_TYPE_*` constants in **sfall.h**).
- If path is clear (no blocker was encountered by selected function) - returns 0.
- `objFrom` is always excluded from calculations, but is required to be a valid object.
opcode: 0x826e
- name: path_find_to
detail: array path_find_to(ObjectPtr objFrom, int tileTo, int blockingType)
doc: Returns the shortest path to a given tile using given blocking function as an array of tile directions (0..5) to move on each step. Array length equals to a number of steps. Empty array means that specified target cannot be reached.
doc: |
Returns the shortest path to a given tile using the given blocking function as an array of tile directions (0..5) to move on each step.
- Array length equals to a number of steps.
- Empty array means that specified target cannot be reached.
opcode: 0x8272
- name: Other
@@ -926,11 +938,11 @@
- name: set_pickpocket_max
detail: void set_pickpocket_max(int percentage)
opcode: 0x81a0
doc: Effects all critters rather than just the player and can set the maximum in range from 0 to 999.
doc: Effects all critters rather than just the player and can set the maximum in the range of 0 to 999.
- name: set_hit_chance_max
detail: void set_hit_chance_max(int percentage)
opcode: 0x81a1
doc: Effects all critters rather than just the player and can set the maximum in range from 0 to 999.
doc: Effects all critters rather than just the player and can set the maximum in the range of 0 to 999.
- name: set_xp_mod
detail: void set_xp_mod(int percentage)
opcode: 0x81aa
@@ -943,7 +955,10 @@
- name: inc_npc_level
detail: void inc_npc_level(int party_member_pid)
opcode: 0x81a5
doc: 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. This function ignores player level requirements and the minimum 3 player level delay between NPC level gains. It also ignores the random element, regardless of sfall's `NPCAutoLevel` or `PartyMemberNonRandomLevelUp` setting.
doc: |
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.
- This function ignores the player's minimum level and the required number of level-ups between NPC level gains. It also ignores the random element, regardless of sfall's `NPCAutoLevel` or `PartyMemberNonRandomLevelUp` setting.
- Starting from sfall 4.5/3.8.50, the maximum possible NPC level is 10.
- name: get_npc_level
detail: int get_npc_level(string npc)
opcode: 0x8241
@@ -970,7 +985,7 @@
doc: Alters the AC bonus you receive per unused action point at the end of your turn in combat. To allow for fractional values, the value given if divided by 4. (Hence the default value is 4 and not 1.)
- name: get_unspent_ap_bonus
detail: int get_unspent_ap_bonus
doc: Gets the AC bonus you receive per unused action point at the end of your turn in combat. To allow for fractional values, the value given if divided by 4. (Hence the default value is 4 and not 1.)
doc: Returns the AC bonus you receive per unused action point at the end of your turn in combat. To allow for fractional values, the value given if divided by 4. (Hence the default value is 4 and not 1.)
opcode: 0x81e7
- name: set_unspent_ap_perk_bonus
detail: void set_unspent_ap_perk_bonus(int multiplier)
@@ -1010,7 +1025,7 @@
- name: get_light_level
detail: int get_light_level
opcode: 0x8226
doc: Returns ambient light level in range 0..65536. The value returned by get_light_level may not exactly match that set by `set_light_level`, as `set_light_level` applies modifiers from the Night Vision perk.
doc: Returns ambient light level in the range of 0 to 65536. The value returned by get_light_level may not exactly match that set by `set_light_level`, as `set_light_level` applies modifiers from the Night Vision perk.
- name: mark_movie_played
detail: void mark_movie_played(int id)
@@ -1059,7 +1074,7 @@
- name: create_spatial
detail: ObjectPtr create_spatial(int scriptID, int tile, int elevation, int radius)
doc: Creates new spatial script with given SID, at given tile, and radius.
doc: Creates new spatial script with the given scriptID at the given tile and radius.
opcode: 0x8273
- name: unwield_slot
@@ -1092,8 +1107,8 @@
- name: sprintf
detail: string sprintf(string format, any value)
doc: |
Formats given value using standart syntax of C `printf` function (google "printf" for format details). However, it is limited to formatting only 1 value.
- Can be used to get character by ASCII code ("%c").
Formats the given value using standard syntax of C `printf` function (google "printf" for format details). However, it is limited to formatting only 1 value.
- Can be used to get character by ASCII code (`%c`).
opcode: 0x8250
- name: typeof
detail: int typeof(any value)
@@ -1127,7 +1142,7 @@
opcode: 0x824f
- name: charcode
detail: int charcode(string text)
doc: Returns ASCII code for the first character in given string.
doc: Returns ASCII code for the first character in the given string.
opcode: 0x8251
- name: get_string_pointer
detail: int get_string_pointer(string text)
@@ -1223,7 +1238,7 @@
opcode: 0x823c
- name: get_sfall_arg_at
detail: mixed get_sfall_arg_at(int argNum)
doc: Gets the value of hook argument with the specified argument number (first argument of hook starts from 0)
doc: Returns the value of hook argument with the specified argument number (first argument of hook starts from 0)
macro: sfall.h
- name: set_sfall_return
detail: void set_sfall_return(any value)
@@ -1419,12 +1434,12 @@
macro: sfall.h
- name: item_weight
detail: int item_weight(ObjectPtr obj)
doc: Gets the current weight of an object.
doc: Returns the weight of an item object.
macro: sfall.h
- name: spatial_radius
detail: int spatial_radius(ObjectPtr obj)
doc: Returns radius of spatial script, associated with given dummy-object (returned by `create_spatial`).
doc: Returns radius of spatial script, associated with the given dummy object (returned by `create_spatial`).
macro: sfall.h
- name: set_rest_heal_time
detail: void set_rest_heal_time(int time)
@@ -1483,12 +1498,12 @@
- name: add_extra_msg_file
detail: int add_extra_msg_file(string fileName)
doc: |
Loads the custom message file, and returns the file ID number assigned to it in range from 0x3000 to 0x3FFF for the `message_str_game` function to get messages from the file.
Loads a custom message file and returns the file ID number assigned to it, in the range of 0x3000 to 0x3FFF, for use with the `message_str_game` function.
- `fileName`: the name of the custom message file (including the .msg extension) in `text\<language>\game\` directory.
- __NOTE:__ if the msg file does not exist in the current language directory, the function will try to load it from the `text\English\game\` directory.
Alternative form: `int add_extra_msg_file(string fileName, int fileNumber)`
- `fileNumber`: the file ID number for the `message_str_game` function. The available range is from 0x2000 to 0x2FFF (see `ExtraGameMsgFileList` setting in `ddraw.ini`)
Use `fileNumber` only if you want to add a message file without editing `ddraw.ini` or existing scripts to support the old way.
Alternative form: `int add_extra_msg_file(string fileName, int fileNumber)` **[DEPRECATED]**
- __Deprecation notice:__ Starting from sfall 4.5/3.8.50, the two-argument form is deprecated. The `fileNumber` argument is ignored, and the function behaves the same as the one-argument form.
macro: sfall.h
- name: void sfall_func0("remove_timer_event")
@@ -1609,7 +1624,7 @@
- name: get_bodypart_hit_modifier
detail: int get_bodypart_hit_modifier(int bodypart)
opcode: 0x81df
doc: Gets the hit percentage modifiers for aiming at specific bodyparts. Valid bodypart id's are from 0 to 8.
doc: Returns the hit percentage modifiers for aiming at specific bodyparts. Valid bodypart id's are from 0 to 8.
- name: combat_data
detail: mixed combat_data
doc: |
@@ -1628,7 +1643,7 @@
- name: get_critical_table
detail: int get_critical_table(int crittertype, int bodypart, int level, int valuetype)
opcode: 0x81e2
doc: Gets current critical table. For details see [critical hit tables](http://falloutmods.wikia.com/wiki/Critical_hit_tables). Requires `OverrideCriticalTable` to be enabled in `ddraw.ini` (already enabled by default).
doc: Returns the current critical table. For details see [critical hit tables](http://falloutmods.wikia.com/wiki/Critical_hit_tables). Requires `OverrideCriticalTable` to be enabled in `ddraw.ini` (already enabled by default).
- name: reset_critical_table
detail: void reset_critical_table(int crittertype, int bodypart, int level, int valuetype)
opcode: 0x81e3
@@ -1843,7 +1858,7 @@
macro: sfall.h
- name: get_outline
detail: int get_outline(ObjectPtr obj)
doc: Gets the current outline color for an object.
doc: Returns the current outline color of an object.
macro: sfall.h
- name: set_outline
detail: void set_outline(ObjectPtr obj, int color)
@@ -2007,12 +2022,16 @@
- name: set_script
detail: void set_script(ObjectPtr obj, int scriptID)
opcode: 0x81f4
doc: Accepts a pointer to an object and scriptID, and applies the given script to an object (scriptID accept the same values as `create_object_sid `from sfall 3.6). 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.
doc: |
Accepts a pointer to an object and scriptID, and applies the given script to an object (scriptID accept the same values as `create_object_sid` from sfall 3.6).
- 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 scriptID when calling `set_script`, `map_enter_p_proc` will be SKIPPED. The `start` proc will always be run.
- name: get_script
detail: int get_script(ObjectPtr obj)
opcode: 0x81f5
doc: |
- accepts a pointer to an object and returns its scriptID (line number in `scripts.lst`), or 0 if the object is unscripted.
Accepts a pointer to an object and returns its `scriptID` (line number in `scripts.lst`), or 0 if the object is unscripted.
- returns -1 on argument error.
- name: obj_is_carrying_obj
@@ -2051,11 +2070,13 @@
- name: get_flags
detail: int get_flags(ObjectPtr obj)
doc: Gets the current value of object flags (see **define_extra.h** for available flags).
doc: Returns the current value of object flags (see **define_extra.h** for available flags).
macro: sfall.h
- name: set_flags
detail: void set_flags(ObjectPtr obj, int flags)
doc: Sets the current flags of an object. All flags are rewritten with given integer, so first get current flags with `get_flags` and use `bwor/bwand` to set/remove specific flag.
doc: |
Sets the current flags of an object.
- All flags are rewritten with the given `flags` integer, so first get the current flags with `get_flags` and use `bwor`/`bwand` to set/remove specific flags.
macro: sfall.h
- name: set_unique_id
@@ -2065,7 +2086,7 @@
- items with unique IDs will not stack with other items of the same type in the inventory
- to just get the current ID number of an object, use `get_object_data(object, OBJ_DATA_ID)`
- unique ID numbers are saved in your savegame, and have a range from 0x10000000 to 0x7FFFFFFF
- there is also a unique ID number range for the player and party members from 18000 to 83535
- there is also a unique ID number range for the player and party members from 18000 to 16795215
- to assign a new ID number generated by the engine to the object (i.e. unassign a unique ID), call the function with two arguments and pass -1 for the flag argument
macro: sfall.h
@@ -475,6 +475,7 @@
#define OBJ_DATA_DAMAGE_FLAGS (0x44)
#define OBJ_DATA_DAMAGE_LAST_TURN (0x48)
#define OBJ_DATA_WHO_HIT_ME (0x54) // current target of the critter
#define OBJ_DATA_CRITTER_HP (0x58)
// compute attack result data offsets
#define C_ATTACK_SOURCE (0x00)
+22 -5
View File
@@ -35,8 +35,11 @@ procedure array_keys(variable array);
// list of array values (useful for maps)
procedure array_values(variable array);
// fix_array for multi-dimensional arrays
procedure fix_array_deep(variable array, variable levels := 1);
// makes given array permanent and returns it
procedure array_fixed(variable array);
procedure array_fixed(variable array, variable levels := 1);
// returns temp array containing a subarray starting from $index with $count elements
// negative $index means index from the end of array
@@ -246,13 +249,28 @@ end
/**
* Sets given array as permanent and returns it.
* @arg {array} array
* @arg {int} levels - Number of depth levels for a multi-dimensional array
* @ret {array}
*/
procedure array_fixed(variable array) begin
fix_array(array);
procedure array_fixed(variable array, variable levels) begin
call fix_array_deep(array, levels);
return array;
end
/**
* Makes a multi-dimensional temp array permenant.
* @arg {array} array
* @arg {int} levels - Number of depth levels for a multi-dimensional array
*/
procedure fix_array_deep(variable array, variable levels) begin
fix_array(array);
if (levels > 1) then begin
foreach (variable subArray in array) begin
call fix_array_deep(subArray, levels - 1);
end
end
end
/**
* Returns a slice of a given list array as a new temp array.
* @arg {list} array
@@ -757,7 +775,7 @@ end
procedure debug_array_str_deep(variable arr, variable levels, variable prefix := false) begin
#define _newline if (levels > 1) then s += "\n";
#define _indent ii := 0; while (ii < levels - 1) do begin s += " "; ii++; end
#define _value(v) (v if (levels <= 1 or not array_exists(v)) else debug_array_str_deep(v, levels - 1))
#define _value(v) (v if (levels <= 1 or typeof(v) != VALTYPE_INT or not array_exists(v)) else debug_array_str_deep(v, levels - 1))
variable i := 0, ii, k, v, s, len;
len := len_array(arr);
if (array_is_map(arr)) then begin // print assoc array
@@ -776,7 +794,6 @@ procedure debug_array_str_deep(variable arr, variable levels, variable prefix :=
s += "}";
end else begin // print list
s := ("List("+len+"): [") if prefix else "[";
_newline
while i < len do begin
_newline
v := get_array(arr, i);
+41 -40
View File
@@ -41,7 +41,7 @@ The **type** value in the weapon knockback functions can be 0 or 1. If 0, the va
The `get_sfall_global` and `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.
The `set_pickpocket_max` and `set_hit_chance_max` affect all critters rather than just the player and can set the maximum in range from 0 to 999.
The `set_pickpocket_max` and `set_hit_chance_max` affect all critters rather than just the player and can set the maximum in the range of 0 to 999.
The `set_skill_max` can't be used to increase the skill cap above 300. The `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.
@@ -66,7 +66,7 @@ The `get_proto_data` and `set_proto_data` are used to manipulate the in memory c
The `list_xxx` functions can be used to loop over all items on a map. `list_begin` takes an argument telling sfall what you want to list (defined in **sfall.h**). It returns a list pointer, which you iterate through with `list_next`. Finally, when you've finished with the list use `list_end` on it. Not calling `list_end` will result in a memory leak. Alternatively, use `list_as_array` to get the whole list at once as a temp array variable, which can be looped over using `len_array` and which you don't need to remember to free afterwards.
The `play_sfall_sound` and `stop_sfall_sound` are used to play **mp3/wav/wma** files. The path given is relative to the Fallout folder. Specify mode as 1 to loop the file continuously, 2 to replace the current background game music with playing the specified file in loop mode, or 0 to play the file once. If you don't wish to loop, `play_sfall_sound` returns 0. If you do loop, it returns an ID which can be passed back to `stop_sfall_sound` when you want to stop the effect. All sounds effects will be stopped on game reload, looping or not. These functions do not require **AllowDShowSound** to be set to 1 in **ddraw.ini**.
Starting from sfall 4.2.8/3.8.28, you can pass a value in the **mode** argument for a reduced sound volume. To set the volume, you need to convert the number to hexadecimal and use the argument format `0xZZZZ000Y`, where `ZZZZ` is the volume reduction value in range from 0 to 32767 (the value 32767 is muted), and `Y` is the playback mode.
Starting from sfall 4.2.8/3.8.28, you can pass a value in the **mode** argument for a reduced sound volume. To set the volume, you need to convert the number to hexadecimal and use the argument format `0xZZZZ000Y`, where `ZZZZ` is the volume reduction value in the range of 0 to 32767 (the value 32767 is mute), and `Y` is the playback mode.
Arrays are created and manipulated with the `xxx_array` functions. An array must first be created with `create_array` or `temp_array`, specifying how many data elements the array can hold. You can store any of ints, floats and strings in an array, and can mix all 3 in a single array. The ID returned by `create_array` or `temp_array` can then be used with the other array functions. Arrays are shared between all scripts. (i.e. you can call `create_array` from one script, and then use the returned ID from another script.) They are also saved across savegames. Arrays created with `temp_array` will be automatically freed at the end of the frame. These functions are safe, in that supplying a bad ID or trying to access out of range elements will not crash the script. `create_array` is the only function that returns a permanent array, all other functions which return arrays (`string_split`, `list_as_array`, etc,) all return temp arrays. You can use `fix_array` to make a temp array permanent.\
__NOTE:__ refer to **arrays.md** for detailed description of the array behavior and function usage.
@@ -119,7 +119,8 @@ FUNCTION REFERENCE
-----
#### `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.
- This function ignores player level requirements and the minimum 3 player level delay between NPC level gains. It also ignores the random element, regardless of sfall's **NPCAutoLevel** or **PartyMemberNonRandomLevelUp** setting.
- This function ignores the player's minimum level and the required number of level-ups between NPC level gains. It also ignores the random element, regardless of sfall's **NPCAutoLevel** or **PartyMemberNonRandomLevelUp** setting.
- Starting from sfall 4.5/3.8.50, the maximum possible NPC level is 10.
-----
#### `int get_npc_level(int pid/string name)`
@@ -172,7 +173,7 @@ FUNCTION REFERENCE
-----
#### `int get_light_level`
- Ambient light level in range 0..65536
- Returns ambient light level in the range of 0 to 65536.
- The value returned by `get_light_level` may not exactly match that set by `set_light_level`, as `set_light_level` applies modifiers from the night vision perk.
-----
@@ -181,19 +182,20 @@ FUNCTION REFERENCE
- This function works in addition to the **WorldMapTimeMod** setting in **ddraw.ini** and the Pathfinder perk, rather than overriding it, so calling `set_map_time_multi(0.5)` when the player has 2 levels of pathfinder would result in time passing at 25% the normal speed on the world map.
-----
#### `void remove_script(object obj)`
- Accepts a pointer to an object and will remove the script from that object.
#### `int get_script(object obj)`
- Accepts a pointer to an object and returns its `scriptID` (line number in **scripts.lst**), or 0 if the object is unscripted.
- Returns -1 on argument error.
-----
#### `void set_script(object obj, 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.
- 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 **scriptID** when calling `set_script`, `map_enter_p_proc` will be SKIPPED. The `start` proc will always be run.
-----
#### `int get_script(object obj)`
- Accepts a pointer to an object and returns its scriptID (line number in **scripts.lst**), or 0 if the object is unscripted.
- Returns -1 on argument error.
#### `void remove_script(object obj)`
- Accepts a pointer to an object and will remove the script from that object.
-----
#### `void set_self(object setObj)`
@@ -245,11 +247,11 @@ FUNCTION REFERENCE
-----
#### `int get_tile_ground_fid(int tileNum, int elevation)`
- Returns FID of a ground tile at given tile number and elevation.
- Returns FID of a ground tile at the given tile number and elevation.
-----
#### `int get_tile_roof_fid(int tileNum, int elevation)`
- Returns FID of a roof tile at given tile number and elevation. Note that FID of 1 is used when there is no actual roof.
- Returns FID of a roof tile at the given tile number and elevation. Note that FID of 1 is used when there is no actual roof.
-----
#### `void reg_anim_combat_check(int enable)`
@@ -274,12 +276,13 @@ FUNCTION REFERENCE
- Should work like `art_change_fid_num` but in `reg_anim` sequence.
-----
#### `void reg_anim_take_out(object obj, holdFrameID, int delay)`
- Plays "take out weapon" animation for given **holdFrameID**. It is not required to have such weapon in critter's inventory.
#### `void reg_anim_take_out(object obj, int weaponCode, int delay)`
- Plays "take out weapon" animation for the given `weaponCode` (see `WPN_ANIM_*` constants in **define_extra.h**).
- It is not required for the critter to have this type of weapon in its inventory.
-----
#### `void reg_anim_turn_towards(object obj, int/object tile/target, int delay)`
- Makes object change its direction to face given tile number or target object.
- Makes object change its direction to face the given tile number or target object.
-----
#### `void reg_anim_callback(procedure proc)`
@@ -348,7 +351,7 @@ FUNCTION REFERENCE
-----
#### `string sprintf(string format, any value)`
- Formats given value using standard syntax of C `printf` function (google "printf" for format details). However, it is limited to formatting only 1 value.
- Formats the given value using standard syntax of C `printf` function (google "printf" for format details). However, it is limited to formatting only 1 value.
- Can be used to get character by ASCII code (`%c`).
-----
@@ -357,7 +360,7 @@ FUNCTION REFERENCE
-----
#### `int charcode(string text)`
- Returns ASCII code for the first character in given string.
- Returns ASCII code for the first character in the given string.
-----
#### `div` operator (unsigned integer division)
@@ -414,7 +417,7 @@ FUNCTION REFERENCE
-----
#### `void register_hook_proc(int hookID, procedure proc)`
- Works just like `register_hook`, but allows to specify which procedure to use for given hook script (instead of `start`).
- Works just like `register_hook`, but allows to specify which procedure to use for the given hook script (instead of `start`).
- Use zero (0) as second argument to unregister hook script from current global script.
- Only use in global scripts.
- Second argument should be passed just like you pass procedures to functions like `gsay_option`, `giq_option`, etc. (name without quotes).
@@ -439,21 +442,21 @@ FUNCTION REFERENCE
-----
#### `int tile_light(int elevation, int tileNum)`
- Returns light intensity at the given tile in range from 0 to 65536.
- Returns light intensity at the given tile in the range of 0 to 65536.
-----
#### `object obj_blocking_line(object objFrom, int tileTo, int blockingType)`
- Returns first object which blocks direct linear path from objFrom to tileTo using selected blocking function (see `BLOCKING_TYPE_*` constants in **sfall.h**).
- Returns the first object which blocks direct linear path from `objFrom` to `tileTo` using selected blocking function (see `BLOCKING_TYPE_*` constants in **sfall.h**).
- If path is clear (no blocker was encountered by selected function) - returns 0.
- `objFrom` is always excluded from calculations, but is required to be a valid object.
-----
#### `object obj_blocking_tile(int tileNum, int elevation, int blockingType)`
- Returns first object blocking given tile using given blocking function or 0 if tile is clear.
- Returns the first object blocking the given tile using the given blocking function, or 0 if the tile is clear.
-----
#### `array tile_get_objs(int tileNum, int elevation)`
- Returns an array of all objects at given tile.
- Returns an array of all objects at the given tile.
- It will include any hidden, dead or system objects (like cursor), so make sure to check properly when iterating.
-----
@@ -462,17 +465,17 @@ FUNCTION REFERENCE
-----
#### `array path_find_to(object objFrom, int tileTo, int blockingType)`
- Returns the shortest path to a given tile using given blocking function as an array of tile directions (0..5) to move on each step.
- Returns the shortest path to a given tile using the given blocking function as an array of tile directions (0..5) to move on each step.
- Array length equals to a number of steps.
- Empty array means that specified target cannot be reached.
-----
#### `object create_spatial(int scriptID, int tile, int elevation, int radius)`
- Creates new spatial script with given SID, at given tile, and radius.
- Creates new spatial script with the given scriptID at the given tile and radius.
-----
#### `int art_exists(int artFID)`
- Checks if given **artFID** exists in the game.
- Checks if the given `artFID` exists in the game.
- Useful when you want to check if critter can use specific weapon: `art_exists((artFid bwand 0xFFFF0FFF) bwor (weaponAnim * 0x1000))`
-----
@@ -504,7 +507,7 @@ sfall_funcX metarule functions
----
#### spatial_radius
`int sfall_func1("spatial_radius", object obj)`
- Returns radius of spatial script, associated with given dummy-object (returned by `create_spatial`)
- Returns radius of spatial script, associated with the given dummy object (returned by `create_spatial`)
----
#### critter_inven_obj2
@@ -555,12 +558,12 @@ sfall_funcX metarule functions
----
#### item_weight
`int sfall_func1("item_weight", object obj)`
- Gets the current weight of an object
- Returns the weight of an item object
----
#### get_outline
`int sfall_func1("get_outline", object obj)`
- Gets the current outline color for an object
- Returns the current outline color of an object
----
#### set_outline
@@ -573,13 +576,13 @@ sfall_funcX metarule functions
----
#### get_flags
`int sfall_func1("get_flags", object obj)`
- Gets the current value of object flags (see **define_extra.h** for available flags)
- Returns the current value of object flags (see **define_extra.h** for available flags)
-----
#### set_flags
`void sfall_func2("set_flags", object obj, int flags)`
- Sets the current flags of an object
- All flags are rewritten with given integer, so first get current flags with `get_flags` and use `bwor`/`bwand` to set/remove specific flag
- All flags are rewritten with the given `flags` integer, so first get the current flags with `get_flags` and use `bwor`/`bwand` to set/remove specific flags
----
#### tile_refresh_display
@@ -722,7 +725,7 @@ sfall_funcX metarule functions
`void sfall_func4("item_make_explosive", int pid, int activePid, int min, int max)`
- Makes the specified item (pid) an explosive item like Dynamite or Plastic Explosives
- `activePid` is for an item with an active timer, can be the same as the `pid` argument
- The item proto must be the **Misc Item** type and have the **Use** action flag
- The item proto must be of the **Misc Item** type and have the **Use** action flag
- `min` and `max` are the minimum and maximum explosion damage
- Using the function on an item that is already set as an explosive will override its previous settings
- __NOTE:__ this function does not work for pid's of Dynamite and Plastic Explosives
@@ -828,7 +831,7 @@ sfall_funcX metarule functions
- Items with unique IDs will not stack with other items of the same type in the inventory
- To just get the current ID number of an object, use `sfall_func2("get_object_data", object, OBJ_DATA_ID)`
- Unique ID numbers are saved in your savegame, and have a range from `0x10000000` to `0x7FFFFFFF`
- There is also a unique ID number range for the player and party members from 18000 to 83535
- There is also a unique ID number range for the player and party members from 18000 to 16795215
- To assign a new ID number generated by the engine to the object (i.e. unassign a unique ID), call the function with two arguments and pass -1 for the flag argument
----
@@ -858,13 +861,11 @@ sfall_funcX metarule functions
----
#### add_extra_msg_file
`int sfall_func1("add_extra_msg_file", string fileName)`\
`int sfall_func2("add_extra_msg_file", string fileName, int fileNumber)`
- Loads the custom message file, and returns the file ID number assigned to it in range from `0x3000` to `0x3FFF` for the `message_str_game` function to get messages from the file
`int sfall_func2("add_extra_msg_file", string fileName, int fileNumber)` **[DEPRECATED]**
- Loads a custom message file and returns the file ID number assigned to it, in the range of `0x3000` to `0x3FFF`, for use with the `message_str_game` function
- `fileName`: the name of the custom message file (including the **.msg** extension) in the `text\<language>\game\` directory
- __NOTE:__ if the msg file does not exist in the current language directory, the function will try to load it from the `text\English\game\` directory
**Optional argument:**
- `fileNumber`: the file ID number for the `message_str_game` function. The available range is from `0x2000` to `0x2FFF` (see **ExtraGameMsgFileList** setting in **ddraw.ini**). Use **fileNumber** only if you want to add a message file without editing **ddraw.ini** or existing scripts to support the old way
- __Deprecation notice:__ Starting from sfall 4.5/3.8.50, the two-argument form is deprecated. The `fileNumber` argument is ignored, and the function behaves the same as the one-argument form.
----
#### unwield_slot
@@ -900,7 +901,7 @@ sfall_funcX metarule functions
----
#### get_sfall_arg_at
`mixed sfall_func1("get_sfall_arg_at", int argNum)`
- Gets the value of hook argument with the specified argument number (*first argument of hook starts from 0*)
- Returns the value of hook argument with the specified argument number (*first argument of hook starts from 0*)
----
#### hide_window
@@ -0,0 +1,211 @@
#include "../headers/sfall.h"
#include "../headers/lib.arrays.h"
#include "../headers/lib.strings.h"
variable test_suite_errors := 0;
variable test_suite_verbose := true;
#ifndef assertEquals
procedure assertEquals(variable desc, variable a, variable b) begin
if (a != b or typeof(a) != typeof(b)) then begin
display_msg("Assertion failed \""+desc+"\": "+a+" != "+b);
test_suite_errors ++;
end else if (test_suite_verbose) then begin
display_msg("Assert \""+desc+"\" ok");
end
end
procedure assertNotEquals(variable desc, variable a, variable b) begin
if (a == b) then begin
display_msg("Assertion failed \""+desc+"\": "+a+" == "+b);
test_suite_errors ++;
end else if (test_suite_verbose) then begin
display_msg("Assert \""+desc+"\" ok");
end
end
#endif
#define ARRAY_MAX_STRING (1024)
#define ARRAY_MAX_SIZE (100000)
procedure array_test_suite begin
variable arr, i, arr2, map, k, v, s;
test_suite_errors := 0;
display_msg("Testing utility functions...");
call assertEquals("strlen", strlen("testing"), 7);
call assertEquals("substr 1", substr("testing", 4, 2), "in");
call assertEquals("substr 2", substr("testing", 1, -1), "estin");
call assertEquals("substr 3", substr("testing", -5, 5), "sting");
call assertEquals("typeof 1", typeof(1), VALTYPE_INT);
call assertEquals("typeof 2", typeof(1.0), VALTYPE_FLOAT);
call assertEquals("typeof 3", typeof("1.0"), VALTYPE_STR);
// Basic array functionality
display_msg("Testing basic arrays functionality...");
arr := create_array(5,0);
call assertEquals("array size", len_array(arr), 5);
arr[0]:=100;
call assertEquals("get array", get_array(arr, 0), 100);
arr[1]:=5.555;
call assertEquals("get array float", get_array(arr, 1), 5.555);
arr[2]:="hello";
call assertEquals("get array str", get_array(arr, 2), "hello");
call assertEquals("get array invalid index", get_array(arr, -1), 0);
call assertEquals("get array invalid index", get_array(arr, 6), 0);
resize_array(arr, 77);
call assertEquals("list resize", len_array(arr), 77);
resize_array(arr, ARRAY_MAX_SIZE + 100);
call assertEquals("resize max", len_array(arr), ARRAY_MAX_SIZE);
free_array(arr);
call assertEquals("not exists check", len_array(arr), -1);
arr := create_array(ARRAY_MAX_SIZE + 100, 0);
call assertEquals("create max", len_array(arr), ARRAY_MAX_SIZE);
free_array(arr);
arr := [6, 1, 10, "one", 10, "two", 5, "three"];
arr[0] := "wtf";
//display_msg(debug_array_str(arr));
call assertEquals("scan list", scan_array(arr, 10), 2);
call assertEquals("scan list 2", scan_array(arr, "two"), 5);
call assertEquals("array_key", array_key(arr, 5), 5);
call assertEquals("array_key out of range", array_key(arr, 9), 0);
call assertEquals("is list", array_key(arr, -1), 0);
call assertEquals("get array as substr", get_array("NiCe", 1), "i");
arr := [78, 12, 99, 1, -5];
sort_array(arr);
call assertEquals("sort ASC", arrays_equal(arr, [-5, 1, 12, 78, 99]), true);
arr := ["Albert", "John", "Mike", "David"];
sort_array_reverse(arr);
call assertEquals("sort DESC", arrays_equal(arr, ["Mike", "John", "David", "Albert"]), true);
reverse_array(arr);
call assertEquals("reverse list", arrays_equal(arr, ["Albert", "David", "John", "Mike"]), true);
shuffle_array(arr);
call assertEquals("shuffle list 1", arrays_equal(arr, ["Albert", "David", "John", "Mike"]), false);
call assertEquals("shuffle list 2", len_array(arr), 4);
if (test_suite_verbose) then display_array(arr);
// some additional stuff
call assertEquals("string_split", get_array(string_split("this+is+good", "+"), 2), "good");
call assertEquals("string_split 2", len_array(string_split("advice", "")), 6);
s := "";
for (i := 0; i < ARRAY_MAX_STRING+30; i+=10) begin
s += "Verbosity.";
end
arr[0] := s;
call assertEquals("array max string", strlen(arr[0]), ARRAY_MAX_STRING-1);
// ASSOC ARRAYS TEST
display_msg("Testing associative arrays...");
arr := create_array(-1,0);
call assertEquals("is map", array_key(arr, -1), 1);
call assertEquals("exists check", len_array(arr), 0);
arr["123"] := 100;
call assertEquals("set/get str=>int", arr["123"], 100);
arr["123"] := 50;
call assertEquals("overwrite 1", arr["123"], 50);
call assertEquals("overwrite 2", len_array(arr), 1);
arr[-1] := "wtf";
call assertEquals("set/get int=>str", arr[-1], "wtf");
arr[3.14] := 0.00001;
call assertEquals("set/get float=>float", arr[3.14], 0.00001);
arr["fourth"] := "elem";
call assertEquals("map size", len_array(arr), 4);
arr[-1] := 0;
call assertEquals("unset key: length", len_array(arr), 3);
call assertEquals("unset key: hashmap", arr[3.14], 0.00001);
call assertEquals("key not exist", arr[777], 0);
free_array(arr);
call assertEquals("not exists check", len_array(arr), -1);
arr := {6:5, 1.001:0.5, 10:"A", 5:0, "wtf":1.1, 10:0.0001, "some":"What"}; // 7 here
// 10:"A" will be overwritten by 10:0.0001
call assertEquals("assoc array expr", len_array(arr), 6); // 6 actual
call assertEquals("scan map 1", scan_array(arr, 1.1), "wtf");
call assertEquals("scan map 2", scan_array(arr, 5), 6);
call assertEquals("scan map 3", scan_array(arr, "What"), "some");
call assertEquals("array_key 1", array_key(arr, 0), 6);
call assertEquals("array_key 2", array_key(arr, 4), "wtf");
call assertEquals("array_key 3", array_key(arr, 1), 1.001);
resize_array(arr, 2);
call assertEquals("map resize 1", len_array(arr), 2);
call assertEquals("map resize 2", arrays_equal(arr, {6:5, 1.001:0.5}), true);
resize_array(arr, 0);
call assertEquals("map clear", len_array(arr), 0);
display_msg("Testing foreach...");
s := "ar";
arr := [6, 10, 0.5, "wtf"];
foreach v in arr begin
s += v;
end
call assertEquals("foreach 1", s, "ar6100.50000wtf");
s := "ar2=";
arr := {"name": "John", "hp": 25, 0: 5.5};
foreach k: v in arr begin
s += k+":"+v+";";
end
call assertEquals("foreach 2", s, "ar2=name:John;hp:25;0:5.50000;");
display_msg("Testing save/load...");
arr := [2,1];
arr2 := {1:2};
s := "wtf";
k := 1;
if (arr and arr2[k]) then s := "ok";
call assertEquals("bracket syntax", s, "ok");
save_array("myarray", arr);
call assertEquals("load 1", load_array("myarray"), arr);
save_array("myarray", arr2);
call assertEquals("load 2", load_array("myarray"), arr2);
free_array(arr2);
call assertEquals("not exists check", len_array(arr2), -1);
call assertEquals("load fail", load_array("myarray"), 0);
save_array(0.1, arr);
call assertEquals("save as float", load_array(0.1), arr);
arr2 := list_saved_arrays; // list of array names
//display_msg(debug_array_str(arr2));
call assertNotEquals("saved arrays 1", scan_array(arr2, 0.1), -1);
call assertEquals("saved arrays 2", scan_array(arr2, "myarray"), -1);
save_array(0, arr);
call assertEquals("unsave array 1", load_array(0.1), 0);
call assertEquals("unsave array 2", len_array(arr), 2);
call assertEquals("saved arrays 3", len_array(list_saved_arrays), len_array(arr2) - 1);
display_msg("Testing nested expressions...");
arr := [["one", "two"], {"three": "four"}];
call assertEquals("nested 1", arr[0][1], "two");
call assertEquals("nested 2", arr[1].three, "four");
display_msg("All tests finished with "+test_suite_errors+" errors.");
end
procedure arrays_lib_tests begin
variable arr, i, arr2, map, k, v, s;
test_suite_errors := 0;
call assertEquals("array_equals 1", arrays_equal([9, 7, 2, 1], [9, 7, 2, 1]), true);
call assertEquals("array_equals 2", arrays_equal([9, 7, 0, 1], [9, 7, 2, 1]), false);
call assertEquals("array_equals 3", arrays_equal([1, 1, 1, 1], [1, 1, 1]), false);
call assertEquals("array_equals 4", arrays_equal([], []), true);
call assertEquals("array_equals 5", arrays_equal({}, []), false);
call assertEquals("array_equals 6", arrays_equal({1: 1.0, 2: 2.0}, {1: 1.000, 2: 2.000}), true);
call assertEquals("array_equals 7", arrays_equal({"name": "John", "dept": 15.20}, {"name": "John"}), false);
arr := array_transform(array_filter(string_split(",23,1,ghh 6 6,77.1 ", ","), @string_null_or_empty, true), @string_to_float);
call assertEquals("array_filter 1", arrays_equal(arr, [23.0,1.0,0.0,77.1]), true);
display_msg("All tests finished with "+test_suite_errors+" errors.");
end
procedure start begin
if not game_loaded then return;
call array_test_suite;
call arrays_lib_tests;
end
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More