Fallout 2 mod Scripting Help Needed - object can't read inventory of another object?

Stuporstar

First time out of the vault
Hi there. I'm pretty new to Fallout 2 modding, but I've been modding Morrowind for almost two decades (and am well familiar with how finicky C-based scripting can be). I've managed to figure out most of the tools and basic syntax already, as well as working with the various header macros. Anyway, I've been working on a mini-mod to extend the timer for Arroyo, using the RPU as a base. I've got the basic mini quests and dialogue all working, but after weeks of figuring out this stuff myself, I'm completely stumped on this problem.

Specifically, this line is returning 0 when it shouldn't be:
Code:
Item_Added:=(obj_is_carrying_obj_pid(PID_ARROYO_ELDER,PID_GOLDEN_GECKO_PELT));

I'll add some context. This is the whole bit (everything I'm not currently testing commented out), inside procedure map_update_p_proc:
Code:
   variable Item_Count;
   variable Item_Adjust;
   variable Item_Added;

   if (map_var(MVAR_Hides_Given) > 0) then begin // this is working in the elder's script
//      Item_Count:=self_item_count(PID_GOLDEN_GECKO_PELT);
      Item_Added:=(obj_is_carrying_obj_pid(PID_ARROYO_ELDER,PID_GOLDEN_GECKO_PELT)); // BROKEN!
      give_xp(Item_Added); // using as a temporary debug message I can see in the message box
      set_map_var(MVAR_Hides_Given, 0); // so it doesn't spam
    
//      if (map_var(MVAR_Hides_Given) > Item_Count) then begin // hides have either been given or stolen
//         Item_Added := obj_is_carrying_obj_pid(PID_ARROYO_ELDER,PID_GOLDEN_GECKO_PELT);
//         if (Item_Added > 0) then begin
//            Item_Adjust := rm_mult_objs_from_inven(PID_ARROYO_ELDER, PID_GOLDEN_GECKO_PELT, Item_Added);
//            add_mult_objs_to_inven(self_obj, PID_GOLDEN_GECKO_PELT, Item_Adjust);
//            Number_Days := (Item_Added * 30);
//            inc_global_var_amt(GVAR_ARROYO_RELIEF, Number_Days);
//         end
//         else begin  // hides likely stolen from chest - but it's triggering every time
//            Amount_Stolen := (map_var(MVAR_Hides_Given) - Item_Count);
//            Number_Days := (Amount_Stolen * 30);
//            set_map_var(MVAR_Hides_Given,Item_Count);
//            dec_global_var_amt(GVAR_ARROYO_RELIEF, Number_Days);
//            call stolen_from;
//         end
//      end
   end

What happens is I get a "0 exp" message after I give the pelts to the Elder. I've tried all sorts of things, like making a #define for that variable instead, but it just doesn't work.

I tried testing with this instead:
Code:
   if (map_var(MVAR_Hides_Given) > 0) then begin // this is working in the elder's script
      Item_Count:=self_item_count(PID_GOLDEN_GECKO_PELT);
//      Item_Added:=(obj_is_carrying_obj_pid(PID_ARROYO_ELDER,PID_GOLDEN_GECKO_PELT)); // BROKEN!
      give_xp(Item_Count); // using as a temporary debug message I can see in the message box
      set_map_var(MVAR_Hides_Given, 0); // so it doesn't spam
end

Then in-game I pick the lock, stick some hides in the chest, and then give one to the elder to trigger the map var. I get the right number in the chest in the "x exp" message. So it seems the chest can read its own inventory just fine -- it just refuses to do so with the elder.

I've thought of a few workarounds that involve moving the elder's whole inventory back and forth (and dealing with the UP's anti-stealing bit), which I can try. But would that require making a chest with a unique PID like the trader chests? I'd also just like to know if this (reading other object's inventory) is just something the scripts can't handle or if I'm missing something here.
 
It's "obj_is_carrying_obj_pid(object obj, int pid)" and you passed a PID as an object pointer.
And if you want to see a (debug) message in the message box, just use display_msg(), like
Code:
display_msg("obj_is_carrying_obj_pid: " + Item_Added);
 
Last edited:
Oh, I see! So I use the object_ptr instead of its PID. That's what I was missing. I'd also wrongly assumed you needed to reference a .msg file to use display_msg().

Thanks!

I have another question regarding this mod I'm working on. I noticed the ddraw.ini has lines to change the time for the dream sequences, so is it impossible to change the actual time limit for Arroyo inside the game via. script? I have the sinking sense that all I'm doing by adjusting the game time limit in command.h and global.h is for role-playing flavor and I have to adjust the .ini outside the game.
 
Huh, I'm still doing something ridiculously wrong. I've tried making an object pointer to the Elder using variables and defines in a variety of ways and it's not working.

So I have to ask the very rudimentary question -- how do I make a simple object pointer? All I can find in any scripts are self_obj, dude_obj, party_member_obj, and even prize_figher_obj, but nothing that just says "this critter with this PID."

Looking at merchant box scripts, it looks like I do need to use a workaround by importing an exported variable like a box_obj, because they all use the self_obj pointer with generic_temp_box as a go-between instead of passing inventory directly back and forth.

Edit: I guess maybe it does need the temp box, because just exporting the variable Elder_Ptr from the map script, importing it and having the elder define it in her script, and then closing the dialogue and letting the box directly yank the items out of her inventory freezes the game. Whoops
 
Last edited:
Ok I'm really stumped now. I've been trying to use an exported variable for the container just like the merchant scripts, but the variable keeps returning 0 and not working. I keep getting results like this.
Screenshot (3).png

Here is the simplified script bits on the box:
Code:
export variable Elder_box_obj;
procedure start begin
   variable Elder_box_obj := self_obj;
   display_msg("object is " + Elder_box_obj);
end

And the elder:
Code:
import variable Elder_box_obj;
procedure look_at_p_proc begin
display_msg("object is " + Elder_box_obj);
end

It makes no difference whether I export the variable from the map script instead. This is just me trying to figure out the simplest chain of events, where I export the variable from the box and have it defined as the box at start. Then import it into the Elder's script and have it return the variable number again when you look at her. When called from her script it's always 0, only returning correctly when calling from the box.

I did a second test where I defined the elder in a variable as well, and when called from the container's script it always returns correctly. So this seems to be a script load order problem, with the Elder always loading first.

Edit: Working with that in mind, I decided to try pulling the items from the elder's inventory using the box's script again and finally got it to work without crashing with this:
Code:
if (map_var(MVAR_Hides_Given) > 0) then begin // triggered in Elder's script
      if (map_var(MVAR_Hides_Given) > Item_Adjust) then begin
         Item := obj_carrying_pid_obj(Elder_Ptr,PID_GOLDEN_GECKO_PELT);
         Item_Count := obj_is_carrying_obj_pid(Elder_Ptr,PID_GOLDEN_GECKO_PELT);
         Item_Adjust += rm_mult_objs_from_inven(Elder_Ptr, item, item_count);
         add_mult_objs_to_inven(Elder_box_obj, item, item_count);
   end
Nice and clean, only one imported variable necessary, and no temp box needed. I think I want to save Item_Adjust though, or a separate LVAR to track how many are in the container to detect if the player steals them back? I dunno I'll figure it out.

Edit 2: Working 100% now, with added checks for player sticking the hides in her chest, stealing them back, and so on:
Code:
item_added := obj_is_carrying_obj_pid(Elder_Ptr,PID_GOLDEN_GECKO_PELT);
   item_count := self_item_count(PID_GOLDEN_GECKO_PELT);
   if (item_added) then // item given to elder
      inc_map_var_amt(MVAR_Hides_Given, item_added);
   if (map_var(MVAR_Hides_Given) < item_count) then // item added to chest
      set_map_var(MVAR_Hides_Given, item_count);
   else if ((map_var(MVAR_Hides_Given)) > (local_var(LVAR_Hide_Count))) then begin // hides given
      if (item_added > 0) then begin // given to elder
         item := obj_carrying_pid_obj(Elder_Ptr,PID_GOLDEN_GECKO_PELT);
         item_adjust := rm_mult_objs_from_inven(Elder_Ptr, item, item_added);
         add_mult_objs_to_inven(self_obj, item, item_added);
      end
      else // added to chest
         item_added := (item_count - (local_var(LVAR_Hide_Count)));
      inc_local_var_amt(LVAR_Hide_Count, item_added);
      item_adjust := (item_added * 15);
      inc_global_var_amt(GVAR_ARROYO_RELIEF, item_adjust);
      display_msg("Added to chest " + item_added);
   end
   else if (local_var(LVAR_Hide_Count) > item_count) then begin  // hides likely stolen from chest
      item_adjust := (local_var(LVAR_Hide_Count) - item_count);
      dec_local_var_amt(LVAR_Hide_Count, item_adjust);
      item_adjust := (item_adjust * 15);
      dec_global_var_amt(GVAR_ARROYO_RELIEF, item_adjust);
      set_map_var(MVAR_Hides_Given, item_count); // gecko pelts left in chest
      call stolen_from;
   end
 
Last edited:
I have another basic syntax question I can't find an answer to (probably because it's "no" lol). Can variables handle integer ranges (when not random)? Or do I always have to do something like this?
Code:
if ((global_var(GVAR_Var_Name) > 0) and (global_var(GVAR_Var_Name) < 3)) then
 
You export the variable from the map script and import them into your box script and into the character script. Look again at how Fo2 scripts are doing it and do exactly the same.
 
Hmm, that's the first thing I did though, and it had the script load order problem, which is why I tried simplifying everything. I got it working by making it point to the Elder and having the container do the work. Probably the better way to go anyway since the Elder gets transported to the Enclave. This way there's nothing in Arroyo being called on in her script.

Would exporting the variable from the map script cause trouble when she's moved? Because it's exported from her script right now, since she always seems to load first.

I've got almost everything working in this Arroyo mod now except for being able to alter the times of the Hakunin dream sequences from a script inside the game. Is that even possible?
 
Last edited:
Exporting/importing temp variables only works on the map with the attached map script. If you want the variable to work on the enclave map as well, you will have to export it from that map script as well.
 
Back
Top