Two (now four) sfall scripting questions

Discussion in 'Fallout General Modding' started by Ardent, Nov 1, 2010.

  1. Ardent

    Ardent A Smooth-Skin

    Jul 24, 2009
    Hello, everyone!

    I'd like to ask two questions about using sfall functions in an NPC script.


    The question is about drug items in Fallout 2. I'd like to read the value representing the time that a drug item lasts on the player. I read sfall's functions and found this:

    Would that be the right function to do it? If yes, what offset should I provide and where/how to find it? Unfortunately, I know nothing about offsets, HEX and all that :/

    What do I need it for: I'd like to set an event that will happen when a drug wears off. For example:

    1. Dude uses a drug on themselves. The drug lasts for 60 minutes.
    2. I set a local_var to game_time + 60 minutes (this value - 60 minutes - should be read from the drug proto).
    3. When the drug expires, the game_time > local_var and something happens (e.g. global_var + 1)


    The other question is about lists (I think). I'd like an NPC to perform a sneak roll for every weapon item found in Dude's inventory. I believe I should make a list of all dude's weapons, then cycle through them and check Sneak, right?

    Problem is, I only found list functions for cycling through items/scenery pieces/critters on a map. Is there any way I could check dude's weapons without having to check for every single weapon pid in the game?


    I'll be extremely grateful for any insight you could share on these matters. Thank you very much in advance!
  2. pelicano

    pelicano It Wandered In From the Wastes

    Jun 14, 2008

    Yes, that would the functions. As for the offsets, you don't have to know how to hex edit but probably you'll have to half-guess the right offsets. You can check these here:

    Have in mind the bold part. This is not entirely true for all proto types. The fallout engine changes the offset slightly in the memory depending on the item type, but the basic structure pointed out in the proto file format document is accurate.


    To check dude's items you can use from DEFINE.H:
    #define INVEN_TYPE_INV_COUNT   (-2) 
    #define inven_count(WHO)       critter_inven_obj(WHO, INVEN_TYPE_INV_COUNT) 
    // Inven Cmd defines // 
    #define INVEN_CMD_INDEX_PTR  (13) 
    #define inven_ptr(WHO,WHERE)     inven_cmds(WHO,INVEN_CMD_INDEX_PTR,WHERE)
    One is the number of items in the inventory and the other is a pointer to each of them. Make a loop from 0 to inven_cout -1 and use the pointer to check each item if it's a weapon type. For reference you can search these functions in killap's unofficial patch scripts. I'm positive I saw a script there using that. Extreme Caution Advised when using loops in fallout. ;)
  3. Nirran

    Nirran Vault Senior Citizen

    Apr 15, 2007
    pelicano is right,this is what i do for determing offsets,these numbers for critters range from 0 to 500ish

    procedure Check_Proto_Data
       display_msg("1 " + get_proto_data(obj_pid(dude_obj), 1));
       display_msg("2 " + get_proto_data(obj_pid(dude_obj), 2));
       display_msg("3 " + get_proto_data(obj_pid(dude_obj), 3));
       display_msg("4 " + get_proto_data(obj_pid(dude_obj), 4));
       display_msg("5 " + get_proto_data(obj_pid(dude_obj), 5));
       display_msg("6 " + get_proto_data(obj_pid(dude_obj), 6));
       display_msg("7 " + get_proto_data(obj_pid(dude_obj), 7));
       display_msg("8 " + get_proto_data(obj_pid(dude_obj), 8));
       display_msg("9 " + get_proto_data(obj_pid(dude_obj), 9));
       display_msg("10 " + get_proto_data(obj_pid(dude_obj), 10));
       display_msg("11 " + get_proto_data(obj_pid(dude_obj), 11));
       display_msg("12 " + get_proto_data(obj_pid(dude_obj), 12));
       display_msg("13 " + get_proto_data(obj_pid(dude_obj), 13));
       display_msg("14 " + get_proto_data(obj_pid(dude_obj), 14));
       display_msg("15 " + get_proto_data(obj_pid(dude_obj), 15));
       display_msg("16 " + get_proto_data(obj_pid(dude_obj), 16));
       display_msg("17 " + get_proto_data(obj_pid(dude_obj), 17));
       display_msg("18 " + get_proto_data(obj_pid(dude_obj), 18));
       display_msg("19 " + get_proto_data(obj_pid(dude_obj), 19));
       display_msg("20 " + get_proto_data(obj_pid(dude_obj), 20));
       display_msg("21 " + get_proto_data(obj_pid(dude_obj), 21));
       display_msg("22 " + get_proto_data(obj_pid(dude_obj), 22));
       display_msg("23 " + get_proto_data(obj_pid(dude_obj), 23));
       display_msg("24 " + get_proto_data(obj_pid(dude_obj), 24));
       display_msg("25 " + get_proto_data(obj_pid(dude_obj), 25));
       display_msg("26 " + get_proto_data(obj_pid(dude_obj), 26));
       display_msg("27 " + get_proto_data(obj_pid(dude_obj), 27));
       display_msg("28 " + get_proto_data(obj_pid(dude_obj), 28));
       display_msg("29 " + get_proto_data(obj_pid(dude_obj), 29));
       display_msg("30 " + get_proto_data(obj_pid(dude_obj), 30));
       display_msg("31 " + get_proto_data(obj_pid(dude_obj), 31));
       display_msg("32 " + get_proto_data(obj_pid(dude_obj), 32));
       display_msg("33 " + get_proto_data(obj_pid(dude_obj), 33));
       display_msg("34 " + get_proto_data(obj_pid(dude_obj), 34));
       display_msg("35 " + get_proto_data(obj_pid(dude_obj), 35));
       display_msg("36 " + get_proto_data(obj_pid(dude_obj), 36));
       display_msg("37 " + get_proto_data(obj_pid(dude_obj), 37));
       display_msg("38 " + get_proto_data(obj_pid(dude_obj), 38));
       display_msg("39 " + get_proto_data(obj_pid(dude_obj), 39));
       display_msg("40 " + get_proto_data(obj_pid(dude_obj), 40));
       display_msg("41 " + get_proto_data(obj_pid(dude_obj), 41));
       display_msg("42 " + get_proto_data(obj_pid(dude_obj), 42));
       display_msg("43 " + get_proto_data(obj_pid(dude_obj), 43));
       display_msg("44 " + get_proto_data(obj_pid(dude_obj), 44));
       display_msg("45 " + get_proto_data(obj_pid(dude_obj), 45));
       display_msg("46 " + get_proto_data(obj_pid(dude_obj), 46));
       display_msg("47 " + get_proto_data(obj_pid(dude_obj), 47));
       display_msg("48 " + get_proto_data(obj_pid(dude_obj), 48));
       display_msg("49 " + get_proto_data(obj_pid(dude_obj), 49));
       display_msg("50 " + get_proto_data(obj_pid(dude_obj), 50));
       display_msg("51 " + get_proto_data(obj_pid(dude_obj), 51));
       display_msg("52 " + get_proto_data(obj_pid(dude_obj), 52));
       display_msg("53 " + get_proto_data(obj_pid(dude_obj), 53));
       display_msg("54 " + get_proto_data(obj_pid(dude_obj), 54));
       display_msg("55 " + get_proto_data(obj_pid(dude_obj), 55));
       display_msg("56 " + get_proto_data(obj_pid(dude_obj), 56));
       display_msg("57 " + get_proto_data(obj_pid(dude_obj), 57));
       display_msg("58 " + get_proto_data(obj_pid(dude_obj), 58));
       display_msg("59 " + get_proto_data(obj_pid(dude_obj), 59));
       display_msg("60 " + get_proto_data(obj_pid(dude_obj), 60));
       display_msg("61 " + get_proto_data(obj_pid(dude_obj), 61));
       display_msg("62 " + get_proto_data(obj_pid(dude_obj), 62));
       display_msg("63 " + get_proto_data(obj_pid(dude_obj), 63));
       display_msg("64 " + get_proto_data(obj_pid(dude_obj), 64));
       display_msg("65 " + get_proto_data(obj_pid(dude_obj), 65));
       display_msg("66 " + get_proto_data(obj_pid(dude_obj), 66));
       display_msg("67 " + get_proto_data(obj_pid(dude_obj), 67));
       display_msg("68 " + get_proto_data(obj_pid(dude_obj), 68));
       display_msg("69 " + get_proto_data(obj_pid(dude_obj), 69));
       display_msg("70 " + get_proto_data(obj_pid(dude_obj), 70));
       display_msg("71 " + get_proto_data(obj_pid(dude_obj), 71));
       display_msg("72 " + get_proto_data(obj_pid(dude_obj), 72));
       display_msg("73 " + get_proto_data(obj_pid(dude_obj), 73));
       display_msg("74 " + get_proto_data(obj_pid(dude_obj), 74));
       display_msg("75 " + get_proto_data(obj_pid(dude_obj), 75));
       display_msg("76 " + get_proto_data(obj_pid(dude_obj), 76));
       display_msg("77 " + get_proto_data(obj_pid(dude_obj), 77));
       display_msg("78 " + get_proto_data(obj_pid(dude_obj), 78));
       display_msg("79 " + get_proto_data(obj_pid(dude_obj), 79));
       display_msg("80 " + get_proto_data(obj_pid(dude_obj), 80));
       display_msg("81 " + get_proto_data(obj_pid(dude_obj), 81));
       display_msg("82 " + get_proto_data(obj_pid(dude_obj), 82));
       display_msg("83 " + get_proto_data(obj_pid(dude_obj), 83));
       display_msg("84 " + get_proto_data(obj_pid(dude_obj), 84));
       display_msg("85 " + get_proto_data(obj_pid(dude_obj), 85));
       display_msg("86 " + get_proto_data(obj_pid(dude_obj), 86));
       display_msg("87 " + get_proto_data(obj_pid(dude_obj), 87));
       display_msg("88 " + get_proto_data(obj_pid(dude_obj), 88));
       display_msg("89 " + get_proto_data(obj_pid(dude_obj), 89));
       display_msg("90 " + get_proto_data(obj_pid(dude_obj), 90));
       display_msg("91 " + get_proto_data(obj_pid(dude_obj), 91));
       display_msg("92 " + get_proto_data(obj_pid(dude_obj), 92));
       display_msg("93 " + get_proto_data(obj_pid(dude_obj), 93));
       display_msg("94 " + get_proto_data(obj_pid(dude_obj), 94));
       display_msg("95 " + get_proto_data(obj_pid(dude_obj), 95));
       display_msg("96 " + get_proto_data(obj_pid(dude_obj), 96));
       display_msg("97 " + get_proto_data(obj_pid(dude_obj), 97));
       display_msg("98 " + get_proto_data(obj_pid(dude_obj), 98));
       display_msg("99 " + get_proto_data(obj_pid(dude_obj), 99));
       display_msg("100 " + get_proto_data(obj_pid(dude_obj), 100));
    change the pointers and numbers to determine(make the target offset at about half off the 100 range)the offset,keep in mind that numbers on that table are in hex(the link he posted),use windows calculater and check scientific,input the hex and then click decimal,that is what sfall needs,the decimal

    use this script and add the above code

    procedure start;
    procedure start
       if (game_loaded) then begin
       else begin
          call Check_Proto_Data;
    in ddraw.ini,add this(with the path to your fo2 folder)

    ;Set this to a valid path to save a copy of the console contents
    ConsoleOutputPath="C:\Game Files\Fallout 2\console.txt"
    the load fo2,do the testing(messege box will spam),once you do what you need,exit fo2 and look at the logg file

    little complicated but it works

  4. Ardent

    Ardent A Smooth-Skin

    Jul 24, 2009
    Thanks guys! I think I learned something new :wink: I'll let you know if I have any further problems.
  5. Ardent

    Ardent A Smooth-Skin

    Jul 24, 2009
    I have another question related to sfall:

    I want to change dude's appearance in the game, i.e. to imitate the effect of changing from a tribal warrior to a jumpsuit dude after obtaining the PipBoy (so not the appearance style/race as seen in Appearance Mod). I can't use the settings in ddraw.ini for that.

    How can I do it via script? I tried using the following function, but it didn't seem to have any effect:
    set_dm_model(char* name)
    Is it the right function in the first place? (I assume it should change the default appearance of a male dude, right?)

    Sorry if the question is dumb, but I suck everytime I try to script anything with sfall, and this is just another such occasion. Thanks in advance for any help.
  6. Timeslip

    Timeslip Water Chip? Been There, Done That

    Aug 15, 2007
    I can't quite remember how that works off the top of my head. iirc it changes the jumpsuit model, and you need to do a map change before it takes effect. (Or wear/remove armour? Something like that.)
  7. Ardent

    Ardent A Smooth-Skin

    Jul 24, 2009
    I'm actually doing just that:

       if (dude_is_male) then begin
    and the character stays the same. Thanks for looking into this.
  8. Timeslip

    Timeslip Water Chip? Been There, Done That

    Aug 15, 2007
    Try and wear/remove some armour, and see if that helps. I can't remember under what conditions fallout rereads that variable.
  9. Ardent

    Ardent A Smooth-Skin

    Jul 24, 2009
    OK, I've made a lot of testing and it seems the function works a little different than I expected:

    1. I didn't use sfall's option to modify the starting and default look of the PC. I started off with the tribal costume.
    2. I put on some armor.
    3. I called the discussed function and was teleported to another map.
    4. The armor was removed via script
    5. I had the look of the V13 suit.

    So it seems the function did change my appearance, but to the default look, from the starting look. It didn't apply the look I called in the set_dm_model function. So maybe this is only used to revert from the starting look to the default look, that you can set up in ddraw.ini?

    If that's the case, how can I change dude's look after the default look has been obtained? In this case, I want the dude to look different during a boxing fight, and then revert to the default look again.

    Thanks for help!


    Scratch that. Due to the armor worn, I didn't see that the game flipped to my default look, because I had the "PipBoy available at start game" function set to 1.

    Now I'm still testing, but it doesn't look, like it works.


    Ran some more tests. The function doesn't seem to have any effect, whether I wear, change, remove the armor or whatever, nor change maps. I tried calling the function when I had both the starting and the default look, it had no effect too. I suppose I must be doing something wrong.

    * Is it OK that I call this function from a critter script, and not a global script or anything?
    * Is it OK that I call this function from dialogue?
    * Am I putting the name correctly in the function? My present code looks like that:
       if (dude_is_male) then begin
    The msg is of course to see if the code was called or not (it is). hmmetl is one of the models from the vanilla game.
    * I'm compiling scripts in the sfall script editor.
  10. Timeslip

    Timeslip Water Chip? Been There, Done That

    Aug 15, 2007
    Your usage of it looks correct to me. I guess that the answer to the question of when fallout rechecks that variable is 'never'.

    Well, it certainly does at game load, but that's a bit useless because it's before any scripts run. Perhaps I should make a pre-load hookscript. Edit: Although that's still useless for your case. I don't think that script function is suitable for your purposes, sorry. You'll need something that changes appearance in a different way.
  11. Ardent

    Ardent A Smooth-Skin

    Jul 24, 2009
    Well, it was just for flavour purposes, so even if I don't manage to circumnavigate this, it won't be much of a problem. Thanks for your time, Timeslip! :)
  12. Darek

    Darek is currently unavailable

    Jan 7, 2008
    If you just want to change the look of your character, can't you use this code?
    metarule3(107, self_obj, 16777232, 0);
    Where '16777232' is the fid number (change to whatever it is you need), and self_ob might need to be changed to dude_obj depending on where the script is run from of course.
  13. Ardent

    Ardent A Smooth-Skin

    Jul 24, 2009
    Thanks for the tip, I'll definitely try that. (I actually solved the problem, but it's not a neat solution)
  14. Ardent

    Ardent A Smooth-Skin

    Jul 24, 2009
    EDIT: Disregard what below, I seem to have already gotten it working as intended.

    I have a new question, please:

    I'd like to check whether the blow that just hit the player character is a critical hit. I suppose I should use a hook script for that? I was looking through Timeslip's notes and found this:

    Runs after fallout has decided if an attack will hit or miss
    int     arg1 - If the attack will hit. (0 - critical miss, 1 - miss, 2 - hit, 3 - critical hit)
    critter arg2 - The attacker
    critter arg3 - The target of the attack
    int     arg4 - The bodypart
    int     arg5 - The hit chance
    int     ret1 - Override the hit/miss
    int     ret2 - Override the targeted bodypart
    critter ret3 - Override the target of the attack
    I'm guessing that I should ask for arg1, and if the value is 3, then add the effects, is that correct?

    Thank you in advance for any help.
  15. killap

    killap Bear Dude Moderator Modder

    May 16, 2005
    What was your solution for this? Using the metarule Darek mentioned doesn't fully work since bringing up the inventory window sets the player's model back to the default state. I'm just temporarily trying to change the look of the player.
  16. Ardent

    Ardent A Smooth-Skin

    Jul 24, 2009
    So far, we haven't managed to solve this issue. The player character changes appearance to the Vault suit when you open the inventory. I tried disabling PipBoy, as it only happens after getting the pipboy from the Temple of Trials (when I tested this with the tribal look, there was no such issue). Unfortunately, it didn't work.

    There's an ugly solution to this, if you want, though:

    1) Make an armor item that will change Dude's appearance to the boxer one.
    2) Put it in the player's inventory when the fight starts.
    3) In critter_p_proc put code that checks whether the player is wearing this armor. If not, force wield_obj.

    You will have the boxer look, and even if the player takes the armor off, it will immediately pop back again, so technically, you will still look like the boxer. But obviously, this is a very dodgy and ugly solution.

    In any case, I think we need to ask Timeslip for some more tweaks to the change appearance function (there is one in sfall, but it only works on map change, or doesn't work at all, IIRC).
  17. killap

    killap Bear Dude Moderator Modder

    May 16, 2005
    Yeah, I feared that was the only way. I think I'll still take this route though.

    I'll even have to add some code to check whether the player drops the armor and if so to just shove it back into the inventory (like is done with the GECK) and then wield it again.

    However, you claim that doing a check in critter_p_proc will immediately pop the armor back on. Does this actually happen for you? It seems that critter_p_proc is not run in combat mode, or at least is run extremely infrequent. I had to do a check in combat_p_proc but even that isn't good because the armor will only be reequipped once it's my next turn.

    In the end though why would someone try and look at/move/drop a non-visible item from their armor slot? During the fights the inventory is empty anyway, so if they do look the average person would just assume nothing is there. But of course, if years of coding have taught me anything, it is to never underestimate the user. ;)
  18. Ardent

    Ardent A Smooth-Skin

    Jul 24, 2009
    You're right, I forgot about the combat mode. So far, we only used this dirty trick to change Dude's appearance when out of combat, so it never really came up. Also, good point about dropping the armor.

    Users will always find a way to break things, but in this case - this is ultimately the user's choice to fuck up their own game :P Choice & consequence is a staple of Fallout, right? :lol:

    Regardless, I think I'll still ask Timeslip whether a neater script-based solution can be found.
  19. killap

    killap Bear Dude Moderator Modder

    May 16, 2005
    When I last spoke to Timeslip I believe she said that she's booked with other things until Feb/March. Seeing how I want to release the RP very soon, that's not going to work for me.

    Eh, don't know. This is a nice addition to the game and I highly doubt anyone would notice the armor hack, but it feels dirty and I know inevitably I'll get someone asking about why they temporarily have this invisible armor. :|
  20. Ardent

    Ardent A Smooth-Skin

    Jul 24, 2009
    Yeah, that's not an overnight solution, sadly.

    Maybe put that in the readme? Then you can brush them off with a RTFM or something :P
    Seriously though, if I were you, I think I'd still go with the armor hack. And when Timeslip has time to do something about it, I'd release a small patch fixing it.