Fallout 2 utility Party Member Script Template

QuantumApprentice

Where'd That 6th Toe Come From?
EDIT2: A few more fixes I found as I was trying to implement other things, and a couple of new optional additions.
EDIT: I've made changes to the script to fix the bugs Lexx pointed out. Keep em coming :)

I've been spending the last few weeks working on a generic script template for new party members in the hopes it assists modders old and new with creating individual party members.

I'd like some feedback if anybody is interested.
I have basic instructions throughout the script, including how to add this character to party.h and party.txt.

To use just open this script in script editor, press CTRL + F to open the find function, and replace 'Character_Name" with your new character's name, then add your character to party.h and party.txt.
There are instructions for each step, but I'm not sure if they're clear or concise enough, so any feedback here is welcome.
In addition, if there are any generic party things that I have missed or that should be added, please let me know :)
https://github.com/QuantumApprentice/Fallout-2-Party-Member-Template
Code:
/*******************************************************************************
        Name:        Fallout 2 Party Member Template
        Location:
        Description: NPC template script

            Created: by sFall Script Editor
            Updated:

*******************************************************************************/

/* Include Files */
#include "..\headers\define.h"
#include "..\headers\command.h"
#include "..\headers\ModReact.h"

// Character_Name
/* Highlight "Character_Name" above and press CTRL+F to activate the Find function.
   Type your new character's name in the replace box, check "Find all matches",
   check "Find in current scripts", fill your character name in the Replace Text box,
   then select "Find & Replace". */


/* Don't forget to change the NAME and TOWN_REP_VAR variables to match your new critter */
#define NAME                    SCRIPT_Character_Name
#define TOWN_REP_VAR            GVAR_TOWN_REP_ARROYO              // Need to specify global.h variable for town rep modifiers if used (replace "GVAR_TOWN_REP_" with actual global variable name)



/* Standard Script Procedures */
procedure start;
procedure critter_p_proc;
procedure pickup_p_proc;
procedure talk_p_proc;
procedure destroy_p_proc;
procedure look_at_p_proc;
procedure description_p_proc;
procedure use_skill_on_p_proc;
procedure damage_p_proc;
procedure map_enter_p_proc;
procedure push_p_proc;

/* Script Specific Procedure Calls */
procedure Node998;                                      // This Node is Always Combat
procedure Node999;                                      // This Node is Always Ending

/*****************************************************************
Party Member pre-requisites
These lines are necessary for the critter to join the player
as a party member.
*****************************************************************/
procedure Node000;
procedure Node001;
procedure Node002;
procedure Join_Party;                                    // Party Join node
procedure Abandon_Party;                                 // Party Abandon node
procedure Node1000;                                      // Main party member node
procedure Node1001;                                      // heal yourself
procedure Node1002;                                      // wait here
procedure Node1003;                                      // put your weapon away
procedure Node1004;                                      // follow close
procedure Node1005;                                      // follow medium
procedure Node1006;                                      // follow far
procedure Node1007;                                      // change distance menu
procedure Node1008;                                      // look at gear menu
procedure Node1009;                                      // remove armor menu
procedure Node1010;                                      // weapon abilities
procedure Node1100;                                      // rejoin party


/* Change "Character_Name" to match the name of your new critter */
#define Character_Name_joins_party             party_add_self;                                                   \
                                               critter_add_trait(self_obj,TRAIT_OBJECT,OBJECT_TEAM_NUM,TEAM_PLAYER)
#define dude_has_free_slot_for_Character_Name  ((dude_at_max_party_size == false) and (Character_Name_In_Party == false))     // Need to declare Character_Name_In_Party in PARTY.H
      /*
      Right click "dude_at_max_party_size" and select "Go to declaration" to open PARTY.H
      Scroll to the top and add lines with this format:
         #define Character_Name_Ptr                             party_member_obj(PID_Character_Name)
      and:
         #define Character_Name_In_Party                        (Character_Name_Ptr != 0)
      You don't have to organize them in the same sections as their counterparts, but it helps :)
      Make sure PID_Character_Name is declared in CRITRPID.H.
      If you used Proto Manager to create your critter then it should have
      automatically added it to this list.

      In order to get Party AI options for combat, open Party.TXT in data\data\ folder
      and add your new party member to the end of the list.
      Simply copy and paste the options for the previous party member, and adjust to your liking.
      Make sure the party_member_PID is pointing to the correct number and is declared in CRITRPID.H
      */

/*****************************************************************
   Local Variables which are saved.
   All Local Variables need to be prepended by LVAR_

      To have LVars work, open scripts.LST, scroll to your character's script name,
      and change the "LVars" setting to at least 8,
      Since there are 8 Local Variables used below.

      (LVAR_ 0 thru 3 are reserved for NPC Reaction Modifiers...
      ...will add more when I learn how they work.)

      If you would rather use the LVAR_Hostile, LVAR_Herebefore, LVAR_Personal_Enemy
      variables instead of LVAR_Flags, uncomment the relevent lines and comment out
      lines with set_herebefore, set_hostile, if (hostile) and (self_can_see_dude).
*****************************************************************/

#define LVAR_Flags                      (4)
#define LVAR_WAITING                    (5)
#define LVAR_FOLLOW_DISTANCE            (6)
#define LVAR_TEAM                       (7)
#define LVAR_Joined_Player              (8)

//#define LVAR_Hostile                    (9)
//#define LVAR_Herebefore                 (10)
//#define LVAR_Personal_Enemy             (11)

#define PARTY_NODE_X                      Node1000

/*******************************************************************
   Imported variables from the Map scripts. These should only be
   pointers and variables that need not be saved. If a variable
   Needs to be saved, make it a map variable (MVAR_)
*******************************************************************/


/*******************************************************************
   Local variables which do not need to be saved between map changes.
*******************************************************************/
variable begin
end

/*******************************************************************
*                           PROCEDURES                             *
*******************************************************************/
procedure start begin

end

procedure map_enter_p_proc begin
   /*  This procedure will get called each time that the map is first entered. It will
       set up the Team number and AI packet for this critter. This will override the
       default from the prototype, and needs to be set in scripts. */

   party_member_map_enter;
   if (Character_Name_In_Party) then begin
      //do nothing
   end

//   critter_add_trait(self_obj, TRAIT_OBJECT, OBJECT_TEAM_NUM,TEAM_);
//   critter_add_trait(self_obj, TRAIT_OBJECT, OBJECT_AI_PACKET,AI_);

end

procedure critter_p_proc begin
   /* Every heartbeat that the critter gets, this procedure will be called. Anything from
      Movement to attacking the player on sight can be placed in here.
      If the critter is mad at the player for any reason, it will attack and remember to attack
      the player should the game be saved and loaded repeatedly. Additionally, if any special
      actions need to be taken by the critter based on previous combat, the critter will remember
      this as well. */

//   if ((local_var(LVAR_Hostile) > 1) and (obj_can_see_obj(self_obj, dude_obj))) then begin
//      set_local_var(LVAR_Hostile,1);
   if (hostile) and (self_can_see_dude) then begin
      self_attack_dude; //Macro made by Tom to keep the critter fleeing.
   end

   /* This next script moves the new party member to follow the player after they've joined and
      when entering new maps. */
   if (Character_Name_In_Party) then begin
      if (party_is_waiting == false) then begin
         party_member_follow_dude
      end
   end

   /*
   -----   These are examples of common Abandon_Party calls, use...or don't...at your discretion   -----

   else if (Character_Name_In_Party) then begin
      if (global_var(GVAR_PLAYER_REPUTATION) < Character_Name_Bad_Karma) then begin
         call Abandon_Party;
         debug_msg("Character_Name Bad Player Rep");
      end
      else if (has_rep_childkiller) then begin
         call Abandon_Party;
         debug_msg("Character_Name: Child Killer");
      end
      else if (has_rep_berserker) then begin
         call Abandon_Party;
         debug_msg("Character_Name: Berserker");
      end
      else if (has_rep_slaver) then begin
         call Abandon_Party;
         debug_msg("Character_Name: Slaver Rep");
      end*/

end

procedure damage_p_proc begin
   /* Whenever the critter takes damage of any type, this procedure will be called. Things
      like setting ENEMY_ and LVAR_Personal_Enemy can be set here.
      If the player causes damage to this critter, then he will instantly consider the player
      his personal enemy. In Critter_Proc or through dialog, actions will be taken against
      the player for his evil acts. */

   if (obj_in_party(source_obj)) then begin
//       set_local_var(LVAR_Personal_Enemy, 1);
      set_personal_enemy;
   end

end

procedure pickup_p_proc begin
   /* Any time that the player is caught stealing from this critter, Pickup_proc will be called.
      In here, various things can happen. The most common response is instant hostility which
      will be remembered. */

   if (source_obj == dude_obj) then begin
//      set_local_var(LVAR_Hostile, 2);
      set_hostile;
   end

end

procedure talk_p_proc begin
   /* These next two scripts are for recruiting a new character to your party,
      Node1000 in particular is necessary to connect to the generic party member inventory
      and combat settings.
      Open Party.h and create a new pointer for your new party member critter at the top of the #defines.
      Replace "Character_Name_Ptr" with the pointer for your new character created in Party.h */

   /* The dialog system is setup and prepares the player to talk to this NPC. Where To Go
      written by designers are placed in here. Additionally, Reactions are generated and
      stored which affects player interactions. */
   Evil_Critter:=0;
   Slavery_Tolerant:=SLAVE_TOLERANT;
   Karma_Perception:=KARMA_PERCEPTION1;

   CheckKarma;

   GetReaction;

start_dialogue(self_obj, neutral_fidget);
gsay_start;
   if ((Character_Name_Ptr != 0) or (party_is_waiting)) then begin      //Character_Name_Ptr needs to be declared in Party.h with your own "Character_Name"
      call Node1000;
      end
   else begin
      call Node001;
   end
gsay_end;
end_dialogue;

end

procedure destroy_p_proc begin
   /* This procedure gets called only on the death of this NPC. Special things like
       incrementing the death count for reputation purposes and Enemy Counters are placed
       in here. */

   /* Increment the aligned critter counter
        This counter affects your karma? */
   //inc_good_critter
   //inc_evil_critter
   inc_neutral_critter

   /* Set global_variable for Enemy status*/

end

procedure look_at_p_proc begin
   /* Look_at_p_proc gets called any time that the player passes the cursor over any object.
       This should only hold the most cursory of glances for the player. */

   script_overrides;
//   if (local_var(LVAR_Herebefore) == 0) then
//      set_local_var(LVAR_Herebefore, 1);
   if not herebefore then begin
      set_herebefore;
      display_mstr(100);
   end else
      display_mstr(101);

end

procedure description_p_proc begin
   /* The player will see more indepth descriptions from this procedure. They are actively
   looking at the critter and want more information. Things like names can be added here
   if the critter is known to the player. */

   script_overrides;
   display_mstr(102);

end

procedure use_skill_on_p_proc begin
   /* Any time a skill is used on a critter this call is made. This can be to give examinations
       for things like Doctor skill or messages for various other skills. */
end

procedure push_p_proc begin

   floater_rand(780, 790);

end

procedure Node001 begin

   Reply(random(750,751));                               // Random dialogue greetings
   if (Character_Name_In_Party == false) then begin
      NLowOption(760, Node002);                          // This NLowOption message(760) is a Low Int request to join the player's party
      NOption(765, Node002, 4);                          // This NOption message(765) is Normal Int request to join the player's party
   end else begin
      call Node1000;
   end

end

procedure Node002 begin
   /* This node checks for stuff before allowing NPC to join party.
       You can add other conditions for joining here. */
   if (dude_charisma <= 1) then begin
     NMessage(800);                                      // This NOption message(800) is a response if player has 1 Charisma or less (can't have party members because too ugly)
end else begin
   if (dude_at_max_party_size) then begin
   Reply(810);                                           // This line is for when the character does NOT join the player's party       (because too many followers)
      NOption(820,Node999,4);                            // This NOption message is Normal Int player response to NOT joining party    (because too many followers)
      NLowOption(825,Node999);                           // This NLowOption message is Low Int player response to NOT joining party    (because too many followers)

   end else if town_rep_is_hated then begin
   Reply(830);                                           // This line is for if the player is hated by the NPC's home town (hates player because TOWN_REPUTATION<=-15)
      NOption(835, Node998, 4);                          // This line is Normal Int response to being hated by the NPC's home town  (default points to combat Node998)
      NLowOption(840, Node998);                          // This line is Low Int response to being hated by town                    (default points to Combat Node998)

   end else begin
   Reply(850);                                           // This line is for when the character agrees to Join the player's party
      NOption(855, Join_Party, 4);                       // This NOption message(855) is Normal Int player response to joining party
      NLowOption(860, Join_Party);                       // This NLowOption message(860) is Low Int player response to joining party
   end
end

end


procedure Node998 begin
   /* Should the Player ever cause the NPC too much discomfort that he desires to attack the player,
       this call will be made. Essentially, it stores the Hostile vaule so that the critter remembers
       he was once hostile towards the player.*/
//   set_local_var(LVAR_Hostile,2);
   set_hostile;

end


procedure Node999 begin
   /* Anytime that there is a need for an ending to dialog, this node is to be called. It will just
       exit from the dialog system without any reprisals from the NPC. */
end


procedure Join_Party begin
   /* This node places the NPC in the player's party.
      Call this node any time you want an action from the player to result in the NPC joining their party. */

   Character_Name_joins_party;
   set_local_var(LVAR_Joined_Player,1);
   float_msg(self_obj, message_str(NAME, 870), FLOAT_COLOR_HIGH);      // Personalize this message or remove if you feel like it

end

procedure Abandon_Party begin

   //set_local_var(LVAR_never_again,1);
   //party_remove(self_obj);
   //leave party
   if (self_visible) then
   set_self_abandon_party;

end


   /* Node1000 and on are default dialogue nodes for a generic NPC joining the player's party. */

procedure Node1000 begin
   Reply(880);                                        // This reply is when the NPC is in your party and you talk to them
   party_member_default_options;
end
procedure Node1001 begin
   // heal yourself
   obj_heal(self_obj)
   if (party_healed_max) then begin
      Reply(random(900,905));                         // This reply is when your party member is healed to max
   end else if (party_healed_good) then begin
     Reply(910);                                      // This reply message is for when the NPC is Barely Hurt (90% health or above)
   end else if (party_healed_hurt) then begin
      Reply(915);                                     // This reply message is for when the NPC is Wounded (70%-90% health?)
   end else begin
      Reply(920);                                     // This reply message is for Failures
   end
   party_member_default_options;
end
procedure Node1002 begin
   // wait here
   set_party_waiting;
   Reply(random(930,931));                            // These reply messages are in response to wait request
   party_member_default_options;
end
procedure Node1003 begin
   // put your weapon away
   inven_unwield(self_obj);
   Reply(940);                                        // Response to removing weapon
   party_member_default_options;
end
procedure Node1004 begin
   // follow close
   set_follow_close;
   Reply(random(950,951));                            // Random responses for distance change
   party_member_default_options;
end
procedure Node1005 begin
   // follow medium
   set_follow_medium;
   Reply(random(960,961));                            // Random responses for distance change
   party_member_default_options;
end
procedure Node1006 begin
   // follow far
   set_follow_far;
   Reply(random(970,975));                            // Random responses for distance change
   party_member_default_options;
end
procedure Node1007 begin
   // distance
   //Reply("TEMP MESSAGE: DISTANCE");
   Reply(980);                                        // Generic response to "Change follow distance" menu
   party_member_def_follow_options;
end
procedure Node1008 begin
   // gear
   //Reply("TEMP MESSAGE: GEAR");
   Reply(985);                                        // Generic response to "Look at your gear"
   party_member_def_gear_options;
end
procedure Node1009 begin
   // remove armor
   //NEED TO FIND OUT WHY THIS DOESNT WORK!!! - NBK
   remove_armor(self_obj)
   //Reply("TEMP MESSAGE: REMOVE ARMOR");
   Reply(990);                                        // Generic response to "Remove armor"
   party_member_default_options;
end
procedure Node1010 begin
   // weapons that can be used
   //Reply("TEMP MESSAGE: CAN USE...");
   Reply(995);                                        // Specific reply, indicating what weapons the NPC can use.
   party_member_default_options;
end
procedure Node1100 begin                              // This node is for when the player is asking the NPC to re-join
   // join me
   if (dude_charisma <= 1) then begin
      set_self_abandon_party;
      Reply(800);                                     // NPC abandons party because Player Character is too ugly
      NOption(g_mstr(10007),Node999,001);             // Predefined generic messages in GENERIC.MSG
   end else if (dude_at_max_party_size) then begin
      set_self_abandon_party;
      Reply(810); //was 2000                          // Generic "Too many followers" reply
      NOption(g_mstr(10007),Node999,001);             // Predefined generic messages in GENERIC.MSG
   end else if (town_rep_is_hated) then begin
      set_self_abandon_party;
      Reply(830);                                     // Will abandon party if Town_Rep becomes Hated
      NOption(g_mstr(10007),Node999,001);             // Predefined generic messages in GENERIC.MSG
   end else begin
      end_party_waiting;
      Reply(random(750,751));                         // Random dialogue greetings
      party_member_default_options;
   end
end
 
Last edited:
Your template is using the bitwise set_hostile macro, which utilizes LVAR_Flags, and at the same time the LVAR_Hostile local variable. This is duplicated - you can (or probably should) only use either of those for clarity. Originally the LVAR_Flags stuff was used to cut down on the amount of local variables in a script, but it seems to not have been used by every Fo2 scripter, or they probably just forgot that this existed in the first place.

For example, right now there will be an issue with your script. If you go into combat with the critter via dialog (Node998), the script will set the hostile bit in LVAR_Flags. However, the critter_p_proc only checks for LVAR_Hostile ... the LVAR_Flags bit is never checked, thus the critter will not go into combat mode.

Oh, and in damage_p_proc is a similar issue ... you are setting LVAR_Personal_Enemy, which is not checked again in critter_p_proc either, so here the critter will also not remember you as an enemy.

The only time the critter will go into combat mode is if you try to steal from him (pickup_p_proc), because here the LVAR_Hostile will be set to 2.
 
Last edited:
Weird...I must have copied that from Vic's code. Thanks for catching it! Which method would you recommend: LVAR_Hostile or LVAR_Flags?
I looked through all the party members I could find and Sulik, Dogmeat, Marcus, Lenny, Goris, Casidy, K9, Cyberdog, and Brainbot all use LVAR_Hostile, while Vic is the only one using "set_hostile" which uses LVAR_Flags.
lol indeed it looks like it got ignored by a lot of scripters.
 
It really depends on what you want to do. Now in 2021, the amount of LVARs doesn't really seem to matter anymore ... even Fixt just went all crowbar on it and increased the LVARs of every single script to minimum 15. Personally I find the way of LVAR_Flags much more elegant, though, especially because all the macros for it are already written and it is used for more than just "check if hostile". But yeah... nobody cares, especially not the generic hobby Fallout modder.

That reminds me of one more issue in your template: LVAR 4 is defined twice. The bit-variable is overwritten by the normal one. This screams for problems down the line.

Also the reason why almost all LVAR defines start at 4 is because 0 - 3 are reserved for the modreact.h macros. So similar to LVAR_Flags, the scripter needs to be aware of that if NPC reaction code is supposed to work.
 
Last edited:
That reminds me of one more issue in your template: LVAR 4 is defined twice. The bit-variable is overwritten by the normal one. This screams for problems down the line.
Awesome thanks! I'll start updating the script.

Also the reason why almost all LVAR defines start at 4 is because 0 - 3 are reserved for the modreact.h macros. So similar to LVAR_Flags, the scripter needs to be aware of that if NPC reaction code is supposed to work.
I have no idea how this works. Can you point me to anything describing modreact.h macros? Or why defining macros as numbers does anything at all?
 
Hard to explain. I think the modreact stuff is mostly used for talking heads (bad mood, neutral, good mood, etc which is modified by the "UpReact", "DownReact" etc. macros in a dialog node). Of course it also works for every other dialog, but afaik it is only really used in Fo1. In Fo2 the dialogues were written in a different style and the whole reaction thing is broken because of that.

Fo1 has much more "random" elements in interactions, while Fo2 is often using fixed values (don't remember if it's all the time or not right now).

Example: In Fo1 you pick a dialog option that will piss off an NPC (DownReact). If you trigger 2 DownReact in the dialog, the critter stops liking you. So the next time when the script checks if the NPC likes you ... it will take that into consideration.

But what most modern games will do: If you pick a dialog option that pisses off an NPC, you will set a variable "I am pissed off" ... and the next time the script checks if the NPC likes you, it will just check if the "I am pissed off" variable is set ..... same result, but no random involved.

/Edit: Check out Aradesh in Fo1. If you are a dick to him, it will trigger a DownReact. If you are nice to him or bring back Tandi, it will trigger an UpReact. This has influence on his face.
I don't have any Fo2 examples for this stuff right now. I tried to find some right now, but it's used almost nowhere.

/Edit2: Oh, here is another one... NOption, BOption, GOption, etc. dialog options in the scripts are also just macros and they also affect the modreact system, which in return has influence on character faces.

Generally I don't know how much of this is hardcoded or not ... thus, I prefer not to touch it and just take it the way it comes.

tl;dr -- it's hard to explain.



About "macros as numbers" - this is not what this is. Every LVAR in the script is just a number... you are giving it a name for readability. Technically you don't have to write "set_local_var(LVAR_Hostile, 1)" ... might as well just write "set_local_var(4, 1)" ... it's exactly the same, but now you won't remember what the fuck is going on if you go back to the script in a few months.
 
Last edited:
Ok the modreact stuff I kind of get, and you gave me a direction to look so I can experiment with it.
Every LVAR in the script is just a number... you are giving it a name for readability. Technically you don't have to write "set_local_var(LVAR_Hostile, 1)" ... might as well just write "set_local_var(4, 1)" ... it's exactly the same, but now you won't remember what the fuck is going on if you go back to the script in a few months.
but this doesn't make much sense. Your explanation is legible, but making the name interchangeable with a number on purpose? Why?

Is every local variable assigned a number by default without user input?

If so, are there more numbers I should avoid because they are pre-assigned to other things?

Why not simply create named variables under the "variable begin" section and let the compiler assign them?

Do the numbers themselves point to other macro's that are built into the engine?

Or is this just some sort of formatting that some scripters used and others didn't?
 
Your explanation is legible, but making the name interchangeable with a number on purpose? Why?
I don't understand what you mean.

Is every local variable assigned a number by default without user input?
You define the amount of LVARs in the scripts.lst file. From that moment on, the script has access to x amount of LVARs.
/Edit: All the variables, GVAR, LVAR, MVAR are just numbers. The compiler doesn't care about the names. What you define them as is just for us to read them better, not much else.

Scripts usually only include modreact.h which already defines LVARs for the 0 - 3 range. Party.h uses defined LVARs, but those are usually defined in the actual party member script itself and not in the .h file, so they can be whatever number (LVAR_WAITING, etc).

Why not simply create named variables under the "variable begin" section and let the compiler assign them?
This part is talking about *temporary variables* which are not the same as LVARs. Temporary variables are cleared on map change / game load while LVARs are always saved.

Do the numbers themselves point to other macro's that are built into the engine?
Usually no. About the macros you will have to check the header files. As far as I am aware right now, there shouldn't be anything else using that, except maybe some exceptions in location related macros.

Macros from header files only work if you actually use them in your script, so I wouldn't worry about that.
 
Last edited:
I don't understand what you mean.
I meant why would you do this operation at all? Seems kind of pointless unless:

This part is talking about *temporary variables* which are not the same as LVARs. Temporary variables are cleared on map change / game load while LVARs are always saved.
So you're saying that defining a variable as a number between 0 and the upper limit set in scripts.lst is how you actually declare an LVAR?
And then the engine takes care of saving the variable itself?
 
Sorry I have no idea how to explain this in other words. :D

If scripts.lst says a script has 15 LVARs, then it has 15 LVARs. 0, 1, 2, 3, ... are all there.

What you do is just giving them names, so you can use them easier.
 
I think I understand.
You declare the number of LVARs you want in scripts.lst.
The LVARs are by default named 1 (or 0?) through the number declared. ie 1 thru 15 (or 0 thru 14?) if 15 is what's declared.
The numbers can be used? but it's easier to read if proper names are defined for them.
And variables declared and defined in this way are stored by the engine in savegames and between maps? whereas simple script variables are not stored at all outside of running.
Declaring two different names for an LVAR is probably ok, but it probably won't work if they are supposed to store different things.

So if I give a script 15 LVARs in scripts.lst, but I don't use all 15, or any, will that have an effect or an impact on the script running?

Oh and...huh...did not know they didn't use "Node000" procedures in the original fallout scripts.
 
In Aradesh's script the LVARs are:
Code:
#define LVAR_Herebefore              (4)
#define LVAR_Invasion                (6)
#define LVAR_Caught_Stealing         (9)
Why did they use 4,6, and 9 instead of 0,1, and 2 if these are the only LVARs in the script?

/Edit: Nevermind I see a lot of LVARs being called by their numbers.
 
Last edited:
Oh and...huh...did not know they didn't use "Node000" procedures in the original fallout scripts.

Procedure names can be whatever. The reason why Fo2 scripts use Node001, 002, etc. is because that's what their dialog tool did.


In Aradesh's script the LVARs are:

Why did they use 4,6, and 9 instead of 0,1, and 2 if these are the only LVARs in the script?
0 to 3 are used by the modreact system. The LVARs are defined in the modreact.h file.
Code:
#define LVAR_reaction                   (0)             // Holds reaction number value.
#define LVAR_reaction_level             (1)             // Holds reaction level: BAD, NEUTRAL, GOOD.
#define LVAR_got_reaction               (2)             // Makes sure to modify reaction only once.
#define LVAR_base_reaction              (3)

Aradesh.ssl is using 10 LVARs in total, but I have only defined 3 which I identified myself. We don't have Fo1 script sources - they were decompiled and thus don't show variable names. This is what I mean with readability .. the numbers are shit, you don't know what they mean and have to guess.
 
The reason why Fo2 scripts use Node001, 002, etc. is because that's what their dialog tool did.
What dialogue tool did they use? Is it similar to the one built into sfall scripter?
We don't have Fo1 script sources
My bad I didn't know that.

Ok so I think the only thing I'm not clear on is the modreact thing. I did a ctrl+f search and couldn't find anything in Aradesh's script that calls local_var(0) or 1,2, or 3 directly. Are they called in the DownReact/UpReact macros (and thus are hidden)?
 
What dialogue tool did they use? Is it similar to the one built into sfall scripter?
We don't know. I think they wrote dialog in MS Word and exported it via macros and shit. At least that's the format the Planescape: Torment dialog examples had. Or was it in Van Buren ... I have no idea, it's too many years since.

Are they called in the DownReact/UpReact macros (and thus are hidden)?
Yes, they are used in the DownReact / UpReact macros. You will have to read modreact.h for that ..

Code:
#define UpReact      set_local_var(LVAR_reaction, local_var(LVAR_reaction) + NORMAL_BOOST); \
                     ReactToLevel

#define DownReact    set_local_var(LVAR_reaction, local_var(LVAR_reaction) - NORMAL_BOOST); \
                     ReactToLevel
 
Dude you have been awesome! Thanks for taking the time to explain everything to me!
I'll have start working on a reaction section now that I have a clue where to start :P
 
One more question that just occurred to me today as I was trying to learn how to script,
If I use a number in a variable or in a command
ie
Code:
tile_num_in_direction(tile_num(self_obj), (cardoor - 2), 2)
and I have LVars declared, is there something to worry about one of the LVars being accidentally used instead of the integer?
 
No, because to access a variable you use
Code:
local_var(x)
map_var(x)
global_var(x)
 
Back
Top