Two (now four) sfall scripting questions

Ardent

A Smooth-Skin
Modder
Hello, everyone!

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

Q1:

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:

sfall function notes said:
get/set_proto_data are used to manipulate the in memory copies of the .pro files fallout makes when they are loaded. The offset refers to the offset in memory from the start of the proto to the element you are reading, and is equal to the file offset minus 12.

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)

Q2:

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!
 
a1:

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: http://falloutmods.wikia.com/wiki/PRO_File_Format#Drugs

sfall function notes said:
get/set_proto_data are used to manipulate the in memory copies of the .pro files fallout makes when they are loaded. The offset refers to the offset in memory from the start of the proto to the element you are reading, and is equal to the file offset minus 12.

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.


a2:

To check dude's items you can use from DEFINE.H:
Code:
#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. ;)
 
pelicano is right,this is what i do for determing offsets,these numbers for critters range from 0 to 500ish

Code:
procedure Check_Proto_Data
begin
   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));
end

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

Code:
procedure start;

procedure start
begin
   if (game_loaded) then begin
      set_global_script_repeat(200);
   end
   else begin
      call Check_Proto_Data;
   end
end

in ddraw.ini,add this(with the path to your fo2 folder)

Code:
;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

Nirran
 
Thanks guys! I think I learned something new :wink: I'll let you know if I have any further problems.
 
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:
Code:
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.
 
Ardent said:
How can I do it via script? I tried using the following function, but it didn't seem to have any effect:
Code:
set_dm_model(char* name)
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.)
 
Timeslip said:
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.)

I'm actually doing just that:

Code:
   if (dude_is_male) then begin
	  set_dm_model("hmboxs");
   end
   load_map(23,1);

and the character stays the same. Thanks for looking into this.
 
Try and wear/remove some armour, and see if that helps. I can't remember under what conditions fallout rereads that variable.
 
Timeslip said:
Try and wear/remove some armour, and see if that helps. I can't remember under what conditions fallout rereads that variable.

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!

EDIT--------------

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.

EDIT2--------------

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:
Code:
   if (dude_is_male) then begin
   	  set_dm_model("hmmetl");
   	  display_msg("changed");
   end
   load_map(23,0);
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.
 
Ardent said:
I suppose I must be doing something wrong.
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.
 
Timeslip said:
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.

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! :)
 
If you just want to change the look of your character, can't you use this code?
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.
 
Darek said:
If you just want to change the look of your character, can't you use this code?
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.

Thanks for the tip, I'll definitely try that. (I actually solved the problem, but it's not a neat solution)
 
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:

Code:
hs_afterhitroll.int

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.
 
Ardent said:
Darek said:
If you just want to change the look of your character, can't you use this code?
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.

Thanks for the tip, I'll definitely try that. (I actually solved the problem, but it's not a neat solution)
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.
 
killap said:
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.

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).
 
Ardent said:
There's an ugly solution to this, if you want, though:
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. ;)
 
killap said:
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.

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.

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. ;)

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.
 
Ardent said:
Regardless, I think I'll still ask Timeslip whether a neater script-based solution can be found.
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. :|
 
killap said:
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.

Yeah, that's not an overnight solution, sadly.

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 have this invisible armor. :|

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.
 
Back
Top