Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
NovaRain committed Jul 3, 2020
2 parents ea921aa + 586d41c commit e10b7ca
Show file tree
Hide file tree
Showing 30 changed files with 428 additions and 195 deletions.
63 changes: 28 additions & 35 deletions artifacts/config_files/Perks.ini
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
;This file handles modifications to perks and traits
;When adding extra perks to a mod, it's advisable to use
; the fake perk scripting functions rather than make modifications
; in this file, as some perks have hardcoded effects which may
; catch you out
;Since traits need to be picked before any scripts run, they
; have an additional NoHardcode option in this file which can

;When adding extra perks to a mod, it's advisable to use the fake perk scripting functions rather than make modifications
; in this file, as some perks have hardcoded effects which may catch you out

;Since traits need to be picked before any scripts run, they have an additional NoHardcode option in this file which can
; be used to remove their hardcoded effects, and add new stat/skill effects

[PerksTweak]
Expand All @@ -31,41 +30,35 @@ WeaponHandlingBonus=3
;Set to 1 to enable the modifications for perks
Enable=0

;Name=The name of the perk (max 63 characters)
;Desc=The description of the perk (max 255 characters)
;Image=The line number (0-indexed) of the corresponding FRM in skilldex.lst
;Ranks=The number of perk levels
;Level=The minimum required level
;Type=If 0, the perk checks only Skill1 for skill requirements; if 1, it checks
; Skill1 or Skill2; if 2, it checks both Skill1 and Skill2
;Stat=The modified stat or -1 if you don't want to change any stats
;StatMag=The increased/decreased value to the modified stat
;Skill1=The first skill (or -1 for none) to check, but if you set a specific bit
; (67108864 or 0x4000000), it checks GVAR. For example, if Skill1=67108864, then
; the perk will check GVAR_PLAYER_REPUTATION (67108864 + 0) on Skill1Mag value
;Skill1Mag=Positive value is used as the minimum requirements of the first
; skill/GVAR, and a negative value is interpreted as the maximum requirement.
; For example, with Skill1=0 and Skill1Mag=100, if player has small guns skill
; >= 100 and meets all other requirements, the perk will be available in the
; selection window; with Skill1=1 and Skill1Mag=-120, the perk will not be
; available if player has big guns skill >= 120
;Skill2=The second skill/GVAR (or -1 for none) to check
;Skill2Mag=Same as Skill1Mag, but for Skill2
;STR-LCK=Positive values are used as minimum requirements of SPECIAL stats, and
; negative values are interpreted as maximum requirements. For some special
; perks processed by the engine (e.g. PERK_armor_powered and PERK_armor_combat),
; the values are not used as requirements but to add to corresponding SPECIAL
; stats
;Name: The name of the perk (max 63 characters)
;Desc: The description of the perk (max 255 characters)
;Image: The line number (0-indexed) of the corresponding FRM in skilldex.lst
;Ranks: The number of perk levels
;Level: The minimum required level
;Type: If 0, the perk checks only Skill1 for skill requirements; if 1, it checks Skill1 or Skill2; if 2, it checks both Skill1 and Skill2
;Stat: The modified stat or -1 if you don't want to change any stats
;StatMag: The increased/decreased value to the modified stat

;Skill1/Skill2: The first/second skill (or -1 for none) to check, but if you set a specific bit 0x4000000 (67108864), it checks GVAR.
; For example, if Skill1=0x4000004, then the perk will check GVAR_BAD_MONSTER (0x4000000 + 4) on Skill1Mag value

;Skill1Mag/Skill2Mag: Positive value is used as the minimum requirements of the first/second skill/GVAR, and a negative value is interpreted as the maximum requirement.
; For example, with Skill1=0 and Skill1Mag=100, if player has small guns skill >= 100 and meets all other requirements, the perk will be available in the
; selection window; with Skill1=1 and Skill1Mag=-120, the perk will not be available if player has big guns skill >= 120

;STR-LCK: Positive values are used as minimum requirements of SPECIAL stats, and negative values are interpreted as maximum requirements.
; For some special perks processed by the engine (e.g. PERK_armor_powered and PERK_armor_combat), the values are not used as requirements
; but to add to corresponding SPECIAL stats

;If the value is set to -99999, the variable will be ignored (similar to comment out that line)

;You can add simple extra perks with ID numbers from 119 to 255
; that do not require using scripting functions to change player stats, and can also be used for Armor perks
;These parameters are only for extra perks
;Stat1-Stat2 = same as Stat
;Stat1Mag-Stat2Mag = same as StatMag
;Skill3-Skill5 = The skill to be modified (or -1 for none)
;Skill3Mod-Skill5Mod = The increased/decreased value to the modified skill
;Stat1/Stat2: same as Stat
;Stat1Mag/Stat2Mag: same as StatMag
;Skill3-Skill5: The skill to be modified (or -1 for none)
;Skill3Mod-Skill5Mod: The increased/decreased value to the modified skill

;##############################################################################
;This is a modification to vanilla perk 0
Expand Down
4 changes: 2 additions & 2 deletions artifacts/ddraw.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
;sfall configuration settings
;v4.2.5
;v4.2.6

[Main]
;Change to 1 if you want to use command line args to tell sfall to use another ini file.
Expand All @@ -21,7 +21,7 @@ UseCommandLine=0
;Path to the folder in which the game will automatically search and load custom files (by *.dat mask, including folders)
;The data load order of the files in the folder will be in reverse alphabetical order of the filenames
;The files placed in this folder will have higher priority than the PatchFileXX options
;Uncomment the option to specify a different folder path. The default path is <GameRoot>\mods\
;This option has no effect in v4.2.6 or later. The default path is <GameRoot>\mods\
;AutoSearchPath=mods

;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Expand Down
Binary file modified artifacts/example_mods/AutoDoors/gl_autodoors.int
Binary file not shown.
44 changes: 22 additions & 22 deletions artifacts/example_mods/AutoDoors/gl_autodoors.ssl
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
/*

Auto Doors mod v1.1 for Fallout 2 by Mr.Stalin
Auto Doors mod v1.2 for Fallout 2 by Mr.Stalin
----------------------------------------------

- allows the player to automatically open/walk through unlocked doors when not in combat

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)

*/

Expand All @@ -30,8 +29,8 @@ procedure combatturn_handler;
#define PORTAL (0)
#define DOOR_FLAGS (0x24)

variable only_once := 0;
variable arrayPid;
variable onlyOnce := 0;
variable pidDoors;

procedure start begin
if game_loaded then begin
Expand All @@ -41,61 +40,62 @@ procedure start begin
set_global_script_repeat(40); // for sfall 3.x
call map_enter_p_proc;
end else begin
if (only_once == 1 and combat_is_initialized) then begin
only_once := 2;
if (onlyOnce == 1 and combat_is_initialized) then begin
onlyOnce := 2;
call set_door_flag(0); // reset flag when entering combat mode
end else if (only_once == 2 and not(combat_is_initialized)) then begin
only_once := 1;
end else if (onlyOnce == 2 and not(combat_is_initialized)) then begin
onlyOnce := 1;
if (sfall_ver_major >= 4) then set_global_script_repeat(0);
call set_door_flag(FLAG_WALKTHRU); // set flag after combat mode ends
end
end
end

procedure map_enter_p_proc begin
if (arrayPid) then begin
// when changing maps, delete the current array to create a new one
free_array(arrayPid);
arrayPid := 0;
if (pidDoors) then begin
// when changing the map, delete the current array to create a new one
free_array(pidDoors);
pidDoors := 0;
end
only_once := 1;
onlyOnce := 1;
call set_door_flag(FLAG_WALKTHRU); // set flag when entering the map
end

procedure set_door_flag(variable state) begin
variable objectMap, obj, objPid, i;

if (arrayPid) then begin
if (pidDoors) then begin
call set_door_flag_array(state);
return;
end

objectMap := list_as_array(LIST_SCENERY);
arrayPid := create_array(0, 0);
pidDoors := create_array(0, 0);

foreach (obj in objectMap) begin
objPid := obj_pid(obj);

if (proto_data(objPid, sc_type) != PORTAL) or is_in_array(objPid, arrayPid) then
if (proto_data(objPid, sc_type) != PORTAL or get_proto_data(objPid, DOOR_FLAGS) or is_in_array(objPid, pidDoors)) then begin
continue; // next object
end

resize_array(arrayPid, i + 1);
arrayPid[i] := objPid;
resize_array(pidDoors, i + 1);
pidDoors[i] := objPid; // add pid to array
i++;
set_proto_data(objPid, DOOR_FLAGS, state);
end
end

procedure set_door_flag_array(variable state) begin
variable objPid;
foreach (objPid in arrayPid) begin
foreach (objPid in pidDoors) begin
set_proto_data(objPid, DOOR_FLAGS, state);
end
end

procedure combatturn_handler begin
if (only_once == 1) then begin
only_once := 2;
if (onlyOnce == 1) then begin
onlyOnce := 2;
call set_door_flag_array(0);
set_global_script_repeat(60);
end
Expand Down
9 changes: 9 additions & 0 deletions artifacts/scripting/headers/sfall.h
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,11 @@
use_obj_on_obj(item, dude_obj); \
set_self(0)

// returns the corrected tile distance between two objects to the distance variable (return value >= 9996 is an error when getting the distance)
#define distance_objs(distance, obj1, obj2) distance := tile_distance_objs(obj1, obj2) - 1; \
if (get_flags(obj1) bwand FLAG_MULTIHEX) distance--; \
if (get_flags(obj2) bwand FLAG_MULTIHEX) distance--

// sfall_funcX macros
#define add_extra_msg_file(name) sfall_func1("add_extra_msg_file", name)
#define add_global_timer_event(time, fixedParam) sfall_func2("add_g_timer_event", time, fixedParam)
Expand Down Expand Up @@ -304,6 +309,10 @@
#define get_object_ai_data(obj, aiParam) sfall_func2("get_object_ai_data", obj, aiParam)
#define get_object_data(obj, offset) sfall_func2("get_object_data", obj, offset)
#define get_outline(obj) sfall_func1("get_outline", obj)
#define get_pc_stat_max(stat) sfall_func1("get_stat_max", stat)
#define get_pc_stat_min(stat) sfall_func1("get_stat_min", stat)
#define get_npc_stat_max(stat) sfall_func2("get_stat_max", stat, 1)
#define get_npc_stat_min(stat) sfall_func2("get_stat_mix", stat, 1)
#define get_sfall_arg_at(argNum) sfall_func1("get_sfall_arg_at", argNum)
#define get_string_pointer(text) sfall_func1("get_string_pointer", text)
#define get_text_width(text) sfall_func1("get_text_width", text)
Expand Down
13 changes: 10 additions & 3 deletions artifacts/scripting/sfall function notes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ The read_xxx functions take a memory address as the parameter and can read arbit

The get/set_pc_base/extra_stat functions are equivalent to calling get/set_critter_base/extra_stat with dude_obj as the critter pointer. None of these stat functions take perks into account, and neither do they do range clamping to make sure the stats are valid. Use the normal get_critter_stat function to get a correctly perk adjusted and range clamped value for a stat.

The set_stat_max/min functions can be used to set the valid ranges on on stats. Values returned by get_current_stat will be clamped to this range. The set_pc_ function only effect the player, the set_npc_ functions only effect other critters, and the set_ functions effect both.
The set_stat_max/min functions can be used to set the valid ranges on stats. Values returned by get_current_stat will be clamped to this range. The set_pc_ function only effect the player, the set_npc_ functions only effect other critters, and the set_ functions effect both.

The input functions are only available if the user has the input hook turned on in ddraw.ini. Use input_funcs_available to check.

Expand Down Expand Up @@ -480,8 +480,8 @@ Some utility/math functions are available:
- sets the current cursor mode

> void sfall_func0("display_stats")
- displays player stats in the inventory screen display window
- works only in opened inventory
- updates player's stats in the inventory display window or on the character screen
- NOTE: works only when the interface window is opened

> int sfall_func1("lock_is_jammed", object)
- returns 1 if the lock (container or scenery) is currently jammed, 0 otherwise
Expand Down Expand Up @@ -730,6 +730,13 @@ optional arguments:
- flags: mode flags (see MSGBOX_* constants in define_extra.h). Pass -1 to skip setting the flags (default flags are NORMAL and YESNO)
- color1/2: the color index in Fallout palette. color1 sets the text color for the first line, and color2 for all subsequent lines of text (default color is 145)

> int sfall_func1("get_stat_min", stat)
> int sfall_func1("get_stat_max", stat)
> int sfall_func2("get_stat_min", stat, bool who)
> int sfall_func2("get_stat_max", stat, bool who)
- returns the maximum or minimum set value of the specified stat (see set_stat_max/min functions)
- who: 0 (false) or omitting the argument - returns the value of the player, 1 (true) - returns the value set for other critters

------------------------
------ MORE INFO -------
------------------------
Expand Down
14 changes: 10 additions & 4 deletions sfall/CheckAddress.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@ namespace sfall

std::multimap<long, long> writeAddress;

static std::vector<long> excludeAddr = {
static std::vector<long> excludeWarning = {
0x44E949, 0x44E94A, 0x44E937, 0x4F5F40, 0x4CB850, // from movies.cpp
};

static std::vector<long> excludeConflict = {
0x42A0F8, // bugfixes.cpp
};

struct HackPair {
long addr;
long len;
Expand Down Expand Up @@ -135,8 +139,10 @@ void PrintAddrList() {
if (diff == 0) {
dlog_f("0x%x L:%d [Overwriting]\n", DL_MAIN, el.addr, el.len);
} else if (diff < pl) {
dlog_f("0x%x L:%d [Conflict] with 0x%x L:%d\n", DL_MAIN, el.addr, el.len, pa, pl);
MessageBoxA(0, "Conflict detected!", "", MB_TASKMODAL);
if (std::find(excludeConflict.cbegin(), excludeConflict.cend(), el.addr) == excludeConflict.cend()) {
dlog_f("0x%x L:%d [Conflict] with 0x%x L:%d\n", DL_MAIN, el.addr, el.len, pa, pl);
MessageBoxA(0, "Conflict detected!", "", MB_TASKMODAL);
}
} else if (level >= 11 && diff == pl) {
dlog_f("0x%x L:%d [Warning] Hacking near:0x%x\n", DL_MAIN, el.addr, el.len, pa);
} else if (level >= 12) {
Expand All @@ -149,7 +155,7 @@ void PrintAddrList() {

void CheckConflict(DWORD addr, long len) {
if (writeAddress.find(addr) != writeAddress.cend()) {
if (std::find(excludeAddr.cbegin(), excludeAddr.cend(), addr) != excludeAddr.cend()) return;
if (std::find(excludeWarning.cbegin(), excludeWarning.cend(), addr) != excludeWarning.cend()) return;
char buf[64];
sprintf_s(buf, "Memory overwriting at address 0x%x", addr);
MessageBoxA(0, buf, "", MB_TASKMODAL);
Expand Down
53 changes: 51 additions & 2 deletions sfall/FalloutEngine/EngineUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -246,14 +246,25 @@ fo::Window* GetWindow(long winType) {
winID = fo::var::optnwin;
break;
default:
return (fo::Window*)-1;
return (fo::Window*)(-1);
}
return (winID > 0) ? fo::func::GNW_find(winID) : nullptr;
}

static long GetRangeTileNumbers(long sourceTile, long radius, long &outEnd) {
long hexRadius = 200 * (radius + 1);

outEnd = sourceTile + hexRadius;
if (outEnd > 40000) outEnd = 40000;

long startTile = sourceTile - hexRadius;
return (startTile < 0) ? 0 : startTile;
}

// Returns an array of objects within the specified radius from the source tile
void GetObjectsTileRadius(std::vector<fo::GameObject*> &objs, long sourceTile, long radius, long elev, long type) {
for (long tile = 0; tile < 40000; tile++) {
long endTile;
for (long tile = GetRangeTileNumbers(sourceTile, radius, endTile); tile < endTile; tile++) {
fo::GameObject* obj = fo::func::obj_find_first_at_tile(elev, tile);
while (obj) {
if (type == -1 || type == obj->Type()) {
Expand All @@ -267,6 +278,44 @@ void GetObjectsTileRadius(std::vector<fo::GameObject*> &objs, long sourceTile, l
}
}

// Checks the blocking tiles and returns the first blocking object
fo::GameObject* CheckAroundBlockingTiles(fo::GameObject* source, long dstTile) {
long rotation = 5;
do {
long chkTile = fo::func::tile_num_in_direction(dstTile, rotation, 1);
fo::GameObject* obj = fo::func::obj_blocking_at(source, chkTile, source->elevation);
if (obj) return obj;
} while (--rotation >= 0);

return nullptr;
}

fo::GameObject* __fastcall MultiHexMoveIsBlocking(fo::GameObject* source, long dstTile) {
if (fo::func::tile_dist(source->tile, dstTile) > 1) {
return CheckAroundBlockingTiles(source, dstTile);
}
// Checks the blocking arc of adjacent tiles
long dir = fo::func::tile_dir(source->tile, dstTile);

long chkTile = fo::func::tile_num_in_direction(dstTile, dir, 1);
fo::GameObject* obj = fo::func::obj_blocking_at(source, chkTile, source->elevation);
if (obj) return obj;

// +1 direction
long rotation = (dir + 1) % 6;
chkTile = fo::func::tile_num_in_direction(dstTile, rotation, 1);
obj = fo::func::obj_blocking_at(source, chkTile, source->elevation);
if (obj) return obj;

// -1 direction
rotation = (dir + 5) % 6;
chkTile = fo::func::tile_num_in_direction(dstTile, rotation, 1);
obj = fo::func::obj_blocking_at(source, chkTile, source->elevation);
if (obj) return obj;

return nullptr;
}

// Returns the type of the terrain sub tile at the the player's position on the world map
long wmGetCurrentTerrainType() {
long* terrainId = *(long**)FO_VAR_world_subtile;
Expand Down
6 changes: 6 additions & 0 deletions sfall/FalloutEngine/EngineUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,14 @@ long __fastcall GetTopWindowID(long xPos, long yPos);

fo::Window* GetWindow(long winType);

// Returns an array of objects within the specified radius from the source tile
void GetObjectsTileRadius(std::vector<fo::GameObject*> &objs, long sourceTile, long radius, long elev, long type = -1);

// Checks the blocking tiles and returns the first blocking object
fo::GameObject* CheckAroundBlockingTiles(fo::GameObject* source, long dstTile);

fo::GameObject* __fastcall MultiHexMoveIsBlocking(fo::GameObject* source, long dstTile);

long wmGetCurrentTerrainType();

void SurfaceCopyToMem(long fromX, long fromY, long width, long height, long fromWidth, BYTE* fromSurface, BYTE* toMem);
Expand Down
1 change: 1 addition & 0 deletions sfall/FalloutEngine/VariableOffsets.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#define FO_VAR_aiInfoList 0x510948
#define FO_VAR_ambient_light 0x51923C
#define FO_VAR_anim_set 0x54CC14
#define FO_VAR_anon_alias 0x56CAEC
#define FO_VAR_art 0x510738
#define FO_VAR_art_name 0x56C9E4
#define FO_VAR_art_vault_guy_num 0x5108A4
Expand Down
Loading

0 comments on commit e10b7ca

Please sign in to comment.