This is a scripting tutorial originally authored by Lisac2k.
It is strongly recommended that you read the Scripting Tutorial by Jargo before continuing with this tutorial.
"I'll write this tutorial the way I see things. I'm not a programmer, so my words here are not the standard programming synthax, but in the end all I want to do is to write down my experiences with the script. I hope you'll find it useful." -- Lisac2k.
Ok, now we start learning important things! The basic of the Fallout2 scripting system are:
As I've said before, the list of all commands can be found in your FO2 Mapper directory (file "Fallout_Editor.doc" - I suggest taking some time and read the file!) Some of them are easy to understand, others looks chaotic. "What does this do?" you might ask yourself reading the list... Don't forget! We have a bunch of original FO2 scripts to learn from, so most of the commands will be more clear... Later.
One thing you've probably already noticed is that most of the commands are long, not easy to write or understand. However, there is a solution for this problem, and in our case it's called "creating macros"!
I guess we don't need to create our own macros, 'cause BIS guys did it for us. MACRO is a short version of a command. Let's see how it works!
Example: according "Fallout_Editor.doc" to this command "reads (checks)" a critters' STAT - I hope you know what a STAT is, if not then get the hell outta here!
get_critter_stat int Critter who (ObjectPtr) stat (int)
So, let's imagine we want to check critters' current hit points (they're recognised as stats by the game engine), the command should look like this:
(get_critter_stat(self_obj,STAT_current_hp)) (command(critter(variable "self_obj" points to a specific critter),stat itself (integer numbers!!!))
Now, I bet this looks confusing all the way. I'll expalin it later, but first let's see how to make this command shorter!
There is THE LIST of already PREMADE MACROS from BIS. It's in “yourFO2mapper_dir\scripts\headers\command.h” Almost any command or its' variety are “macroed” in this file!!!
So, if you try to search through the file, you'll find this line:
#define self_cur_hits (get_critter_stat(self_obj,STAT_current_hp))
DEFINE is used to define a thing ONLY IF IT IS NOT ALREADY DEFINED, in other words if it's unknown thing to engine. It's often used in the scripts, so remember what is written here!
This macro allows us to write simply self_cur_hits in our scripts instead of typing looooong and complicated commands. Nice, ain't it?
It's very important to manipulate with macros, since the original FO2 scripts are full of'em! Most of the macros can be found in header files (see the end of this tutorial).
Now, the macros would be lost in your script, if there wasn't any controlling and organizing structures. They'd crawl around like a bunch of deathclaws without Gruthar and the Mother. Fortunately, there are procedures!
PROCEDURES ARE SMALL STEPS IN SCRIPTS WHICH DO SOMETHING.
EVERY PROCEDURE MUST HAVE A NAME, example: procedure Kick_ass
Some names are RESERVED, like these:
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 map_exit_p_proc; procedure timed_event_p_proc;
These procedures do specific stuff in game. Example: “procedure talk_p_proc” ALWAYS starts a dialogue, in other words it brings on the dialogue window.
PROCEDURES ARE BEING USED FOR BUILDING DIALOGUE TREES, TOO!
They're named like this:
procedure Node001; procedure Node002; procedure Node003; ... procedure NodeXYZ;
These procedures are being called from other procedures and represent nodes in the dialogue tree.
Example (Eldridge, weapons dealer in New Reno):
procedure talk_p_proc begin if (eldridge_bed_time) then begin //If Eldridge sleeps, go to Node 30! call Node030; end else begin //In any other case, go this way prev_node := 0; //Simple variable, forget it for now give_eldridge_box(new_reno_eldridge_box) //Gives Eldridge inventory from his box start_gdialog(NAME,self_obj,4,-1,-1); //NAME == Eldridge, self_obj == player, mood, head art, background picture gSay_Start; //Starts a new dialog sequence. etc...
I guess you already noticed all commands usually finish with “;” character. Remember it! It might cause a lot of problems while compiling (errors)!!!
Other thing: comments are written as “//text” or “/*text*/”. Remember it, it's important! Comment every step you make, since it makes sense to you and (more important) to others!
EVERY PROCEDURE SHOULD BE DECLARED ON THE SCRIPTS' START! Look in the original FO2 scripts for it!
PROCEDURES ARE STARTED (CALLED) WITH “CALL” COMMAND! Look in the original FO2 scripts for it!
PROCEDURES MUST BEGIN WITH “BEGIN” AND END WITH “END” COMMAND! Example:
procedure look_at_p_proc begin script_overrides; display_mstr(100); end
Working with procedures and debugging of them is job which demands dedication, but the results are worth it. There's a bunch of procedures in original scripts, study them carefully and learn! Of course, simple copy&paste is always welcome, and if you do some editing you might make a script in no time... Maybe not yet, but over time for sure!
VARIABLES ARE “CARRIERS” WHICH HAVE A VALUE OF SOME SORT AND CAN CARRY IT AROUND AND BRING IT SOMEWHERE AND GIVE ITS' VALUE TO OTHERS. Example:
lisacs_inventory; temp; prev_node; etc...
So we can set some values to varibles. Like this:
temp := 8
Or like this:
temp := lisacs_inventory
(More about operators further in the text!)
However, these are only temporary vars for a script. They're recognised by script, but not saved . Other, more important variables, which are saved (probably into a savegame file) are:
a) GVARs (Global VARiables) which are recognized by engine in the WHOLE GAME.
b) LVARs (Local VARiables) which are recognized by specific SCRIPTS ONLY.
c) MVARs (Map VARiables) which are recognized by specific MAPS ONLY.
As far as I know, all vars (variables shortly) can have an integer number or a string as value. We should stick to integers, since it can do everythig we need
All variables are listed in these files: GLOBAL.H (for gvars) and MAPNAME.H (for mvars). Mapname = name of the specific map, e.g. “ARBRIDGE” for “ARBRIDGE.H”
Local varibles are located and defined inside the scripts. Gvars and mvars are defined in the files I mentioned above, sometimes in other “.H” (header) files.
All vars needs to be DEFINED on the start of a script, so the game/script knows about it! Example:
#define LVAR_Herebefore (4)
Definition of temp vars is even simpler, example:
variable starttile := 0;
Now, this is a no brainer
> (greater than) < (lesser than) >= (greater than or equal to) <= (lesser than or equal to) == (equals) != (does not equal)
Sometimes, you'll see this operator ":=" It's used by temporary variables as an equation sign.
HEADERS are files with “.H” extension in “yourFO2mapper\scripts\headers” directory. They contain bunch of useful informations and refferences for the game itself, but for us (modders) too. Example:
AIPACKET.H contains informations about artificial inteligence of the game critters, CARAVAN.H about caravans gvars, and ITEMPID.H about items' personal ID's (it's easier to work with names than with numbers).
It's strongly recommended to check all header files at least once in order to see what's where, why and how.
If you plan to use something from the headers files, you'll have to say it to your script. It can be done using “#include” comand, like this:
#include "..\headers\define.h" #include "..\headers\v15ent.h"
Typical headers included in the original scripts are “command.h” and “define.h”, they're the most important things. Compiling errors can be caused by not including a header(s), so be absolutely sure you've included everything you plan to use in your script.