Fallout 2 mod FO2 Engine Tweaks (Sfall)

Discussion in 'Fallout General Modding' started by Dude101, Jul 30, 2007.

  1. JimTheDinosaur

    JimTheDinosaur Vault Dweller
    Modder

    736
    Mar 17, 2013
    You know what would be really awesome (annoying JtD request #4995 incoming), an roll_vs_skill/do_check hook; imagine it, overriding all those annoying random stat/skill checks in one fell swoop. Especially when the Fallout 1 conversion is done, this could produce miracles (the Fallout 2 devs were a bit more reasonable and made stat checks a bit less random). You could change every random skill roll into a threshold purely based on the modifier alone (e.g. roll vs. skill with -20 modifier could become 50 - -20*3 = 110 skill threshold), but more refined possibilities based on a critter's stats if what calls the hook is a critter, or an area's "difficulty" if it's not a critter (e.g. a door).

    edit: ideally this would even allow you to make the reaction system actually matter: change the speech skill success condition based on LVAR_reaction. Of course, this would presume being able to tap into local vars from hookscripts.

    I actually originally considered the advantages of being able to tap into local variables in the case of LVAR_Hostile: there's no reliable way to make an enemy surrender or flee in Fallout because their critter_proc will keep telling them to initiate combat. Unfortunately, the devs didn't consistently use the same lvar for hostility; however, LVAR_reaction is used consistently.

    Anyway, long story short: a man can dream :P. Wish I were a programmer and not a total amateur and I'd try and figure it out myself instead of whining to phobos, heh (might still give it a try at some point all the same though, being a masochist).
     
    Last edited: Feb 27, 2015
  2. phobos2077

    phobos2077 Vault Dweller
    Modder

    708
    Apr 24, 2010
    You can do that:
    Code:
    set_self(otherDude);
    set_local_var(4 /* or whatever the number is */, 0);
    
     
    • [Like] [Like] x 1
  3. JimTheDinosaur

    JimTheDinosaur Vault Dweller
    Modder

    736
    Mar 17, 2013
    Weird, thought I'd already tested that... that's very interesting; if only the devs had used a more consistent lvar numbering system for things other than reactions.

    edit: ah well, this is probably more an ingredient for mass compile anyway; messing with lvars from outside would be just asking for crazy bugs all over the place. Might as well do the same with skill rolls I suppose.

    maybe instead of individualized hostility, team based hostility could be the best approach; replace all instances of LVAR_Hostile and and calls for hostile in LVAR_Flags with a reference to an array storing the varying degrees of hostility in a team hostility array; this'd finally ensure that terminate_combat can be used safely...
     
    Last edited: Feb 27, 2015
  4. phobos2077

    phobos2077 Vault Dweller
    Modder

    708
    Apr 24, 2010
    An update. CorpseLineOfFireFix was rewritten. Now it has only 2 states (enabled/disabled) and prevents corpses from blocking fire altogether at low level (they will act like bushes or other scenery - completely irrelevant to burst fire logic).
    Also added hotkey (configurable) to reload current weapon.
     
    • [Like] [Like] x 1
  5. NovaRain

    NovaRain Casual Modder Modder Moderator

    Mar 10, 2007
    sfall 3.6 is released on SourceForge, along with the modders pack and win2k version.

    EDIT: re-uploaded modders pack because the previously included int2ssl requires MinGW libraries.
     
    Last edited: Mar 5, 2015
    • [Like] [Like] x 4
  6. JimTheDinosaur

    JimTheDinosaur Vault Dweller
    Modder

    736
    Mar 17, 2013
    In array.txt it says:

    I guess this can't be used to check anything for being an array, right?

    Code:
    
      nougat:=1;
      debug_msg("len_array(1) " + len_array(1));
      debug_msg("len_array(nougat:=1) " + len_array(nougat));
      nougat:=create_array(1,0);
      debug_msg("len_array(nougat[0]) " + len_array(get_array(nougat, 0)));
      nougat[0]:=1;
      debug_msg("len_array(nougat[0]:=1) " + len_array(get_array(nougat, 0)));
    
    returns this:

    Code:
    len_array(1) 0
    len_array(nougat:=1) 0
    len_array(nougat[0]) -1
    len_array(nougat[0]:=1) 0
    Is there a way to find out whether or not something is an array regardless of whether it ever was (as obviously something with len 0 could just be an array without size)?
     
    Last edited: Mar 5, 2015
  7. phobos2077

    phobos2077 Vault Dweller
    Modder

    708
    Apr 24, 2010
    Well this works like that because you don't have separate data type for arrays. As you know there are 3 data types in fallout scripts: Integer, Float and String. Array references are integer values, so there is no reliable way to check if some value is an array reference and not just some number. This also depends on what exactly you want to achieve. If you want to make recursive debug_array_str function then I guess you will have to go for some other approach, like if you have a proper multi-dimensional array, you can pass number of dimensions (nesting depth) as a procedure argument.

    I actually thought about using specially crafted strings (with non-character bytes) as array references, but dropped this idea eventually for the sake of simplicity. The downside was that if at some point this string would be printed somewhere in the game (could happen very easily during debugging), it will crash the game. And you can't introduce another data type to the engine, as you will have to modify a lot of vanilla opcode handlers (using ASM hacks) - too much work and risk.
    This could be done easily with new engine, however. Wait a few years :P
     
    Last edited: Mar 6, 2015
    • [Like] [Like] x 2
  8. JimTheDinosaur

    JimTheDinosaur Vault Dweller
    Modder

    736
    Mar 17, 2013
    I just changed it so that only len_array's > 0 get debugged as arrays. Makes it confusing when you don't know it's empty beforehand, but I should be able to piece it together heh.

    Another thing I just can't seem to figure out is your description of return arguments in registered hooks:

    Code:
    
    NOTE: you can hook several scripts to a single hook point, for example if it's different mods from different authors or just some different aspects of one larger mod. In this case scripts are executed in reverse order of how they were registered. When one of the scripts in a chain returns value with "set_sfall_return", the next script may override this value if calls "set_sfall_return" again. Sometimes you need to multiply certain value in a chain of hook scripts.
    Example: let's say we have a Mod A which reduces all "to hit" chances by 50%. The code might look like this:
    
    
        original_chance = get_sfall_arg;
        set_sfall_return(original_chance / 2);
    
    
    Mod B also want to affect hit chances globally, by increasing them by 50%. Now in order for both mods to work well together, we need to add this line to Mod A hook script:
    
    
        set_sfall_arg(original_chance / 2);
    
    
    This basically changes hook argument for the next script. Mod B code:
    
    
        original_chance = get_sfall_arg;
        set_sfall_return(original_chance * 1.5);
        set_sfall_arg(original_chance * 1.5);
    
    
    So if you combine both mods together, they will run in chain and the end result will be a 75% from original hit chance (hook register order doesn't matter in this case, if you use "set_sfall_arg" in both hooks).
    What decides which of these two is MOD A and MOD B? From the description they seem identical, and you say register order doesn't matter (I don't even know what you meant by that tbh), so what does matter then to decide in what order the sfall return is modified (i.e. first /2 then *1.5, rather than first *1.5 and only afterwards /2)?
     
  9. phobos2077

    phobos2077 Vault Dweller
    Modder

    708
    Apr 24, 2010
    That's because A*B == B*A (first grade math :D). When first hook returns multiplied value it also modifies the argument to the same value, so the next hook will start it's modifications from that value.

    Not sure what exactly you are asking :)
     
  10. JimTheDinosaur

    JimTheDinosaur Vault Dweller
    Modder

    736
    Mar 17, 2013
    Haha, oh right, ok then different example: Mod A does (original_chance + 20), while Mod B does (original_chance * 1.5). What decides which of these operations is carried out first (e.g. if original_chance is 40, what decides whether the outcome is 90 or 80)?
     
  11. phobos2077

    phobos2077 Vault Dweller
    Modder

    708
    Apr 24, 2010
    Well not all mods can be combined. In docs I just pointed out that you CAN make some mods inter-compatible with each other.
    In your example the outcome is undefined so you shouldn't use those mods together :)
     
    Last edited: Mar 5, 2015
    • [Like] [Like] x 1
  12. JimTheDinosaur

    JimTheDinosaur Vault Dweller
    Modder

    736
    Mar 17, 2013
    Just a little note: apparently when you set the global script type to 1 (or, less surprisingly, 2), the generic procedures (map_enter, map_exit) no longer hook. Not a big problem of course, but took me a while to figure out :P.
     
  13. Lexx

    Lexx Testament to the ghoul lifespan
    Moderator Modder

    Apr 24, 2005
    So with all of that new Sfall stuff and stuff I wonder one thing.... Can we get back the little red dots while traveling on the worldmap? It's one of the few Fo1 features that I really want to see in Fo2 again.
     
  14. JimTheDinosaur

    JimTheDinosaur Vault Dweller
    Modder

    736
    Mar 17, 2013
    I'm getting a lot of errors in the script editor when performing actions that would also crash it in older version:

    Code:
    ************** Exception Text **************System.IO.IOException: The process cannot access the file 'C:\GOG.com\Fallout 2 Mapper\modderspack 3.6.7\ScriptEditor\errors.txt' because it is being used by another process.
       at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
       at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy)
       at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options)
       at System.IO.StreamReader..ctor(String path, Encoding encoding, Boolean detectEncodingFromByteOrderMarks, Int32 bufferSize)
       at System.IO.StreamReader..ctor(String path, Encoding encoding)
       at System.IO.File.ReadAllText(String path, Encoding encoding)
       at ScriptEditor.TextEditor.bwSyntaxParser_RunWorkerCompleted(Object sender, RunWorkerCompletedEventArgs e)
       at System.ComponentModel.BackgroundWorker.OnRunWorkerCompleted(RunWorkerCompletedEventArgs e)
       at System.ComponentModel.BackgroundWorker.AsyncOperationCompleted(Object arg)
    It usually happens when I try changing the amount of variables carried over to a procedure without first changing that in the declaration. E.g. going from

    Code:
    procedure herp;
    procedure herp begin
    end
    to

    Code:
    procedure herp;
    procedure herp(variable derp) begin
    end
    Needless to say I don't have a single clue what "other process" could be using error.txt...
     
  15. phobos2077

    phobos2077 Vault Dweller
    Modder

    708
    Apr 24, 2010
    Looks like that's an oversight on my part. Other process is most likely the Parser which is running in another thread...

    I suggest discussing Script Editor and other scripting tools here (to make this thread cleaner).
     
    • [Like] [Like] x 1
  16. JimTheDinosaur

    JimTheDinosaur Vault Dweller
    Modder

    736
    Mar 17, 2013
    I was wondering, is there a way to use art_exists to find out whether a certain critter can perform a certain animation? E.g. whether obj_art_fid(dude_obj) can perform ANIM_burned_to_nothing?

    I managed to get it to work for weapon animations per your instructions, which is already very helpful, but no clue how to address other types of art...
     
  17. phobos2077

    phobos2077 Vault Dweller
    Modder

    708
    Apr 24, 2010
    Yeah, sure. The third byte of FID is most likely the animation. Try art_exists((artFid bwand 0xff000fff) bwor (animId * 0x10000))
     
  18. JimTheDinosaur

    JimTheDinosaur Vault Dweller
    Modder

    736
    Mar 17, 2013
    Hmm, doesn't seem to work:

    Code:
    
        display_msg("exist tribal " + art_exists((FID_HMWARR bwand 0xff000fff) bwor (ANIM_sliced_in_half * 0x10000)) );
        display_msg("exist jmps " + art_exists((FID_HMJMPS bwand 0xff000fff) bwor (ANIM_sliced_in_half * 0x10000)) );
    both return 0 where the second one should return 1.
     
  19. JimTheDinosaur

    JimTheDinosaur Vault Dweller
    Modder

    736
    Mar 17, 2013
    @phobos2077, I looked all around, and the only way to set or read a object's flags (e.g. the "trans steam" flag that creates the ghost/stealth boy effect for critters) on an individual basis is with the mapper, right? If so, could there perhaps be added some script functions to accomplish this (e.g. get_obj_flags(obj) and set_obj_flags(obj, value))?

    edit: then again, maybe these values are just hidden in has_trait already, but just not added to define.h?
    edit2: guess not, at least I tested it for every has_trait(TRAIT_OBJECT, etc.) between 0 and 1000 and nothing turned up :p.
     
    Last edited: Apr 1, 2015
  20. Lexx

    Lexx Testament to the ghoul lifespan
    Moderator Modder

    Apr 24, 2005
    I'll just quote myself in this thread:

    Fo2 runs in dx9 mode with Sfall, but the mapper doesn't have such a feature, therefore I can't use it anymore. Anyone got any idea or solution for my problem? If I can't fix this, I will be out of Fo2 modding officially from now on.