Modifying perk effects?

martix

First time out of the vault
Hey there.

I've recently gone into Fallout again, with the intent to run through them all from start to finish.
Since I also like to tinker I've been looking at modding stuff along the way.
I'm on FO2 right now, and there are loads of nice tools for it. Which certainly should help a lot. But I'm a newbie.

One thing I thought might be fun and easy to do is modify/create a perk.
Not as easy as I thought. For one, no idea where perk/trait effect data is stored.
 
AFAIK, perks are divided into several categories:
a) hard-coded effect perks which give you certain bonuses in stats or other aspects of game
b) script-based perks that do nothing on their own, but are checked in different scripts
c) (introduced in sfall), "fake" perks. they effectively the same as (b) but can be added at will using sfall create_fake_perk function (or something like that), you provide perk title, description and image. It stored in save game and can be later checked by get_fake_perk (not exact name) by perk title.

To change hard-coded perks, refer to sfall modders pack (you can get it at sourceforge), there is example perks.ini file. Never tried it myself though.
 
I've been asked for a tutorial for perks before,and I was a jerk(imo) about it,ill try to cover the main points(note : I do everything with fake perks from sfall,even disabling vanilla perks using sfall then writing fake perk scripts)
been a couple years since I modded fo2 but my modding folder has not been altered
*goes to relevent ssl files for reference*
for instance,i wont lie,when I play I cheat,but not with editors or trainers,i mod OP perks and abilities,this is what I did for player carry weight
vanilla(unaltered or un-modded fallout 2) has 2 perks for carry weight,strong back and packrat
these perks are disabled and then re-written with scripting through sfall,several procedures in my custom perks script covers this
multiple conditions to make the perk available in an ini file named customperks.ini,these are the settings :
Code:
;set to 1 to enable this perk,0 to disable(will enable vannilla perk if disabled,this perk enabled also disabled "Pack Rat" perk) : "AKA Mule.  You can carry an additional " + CustomPerksIniSetting:StrongBackAmount + " pounds of equipment for each level of this Perk."
StrongBackEnable=1
;this sets the amount for Strong Back
StrongBackAmount=500
;this sets the player stat amount that is max for this perk to be selectable(ie. if player carry amount is less then CustomPerksIniSetting:StrongBackMax,then this perk is selectable,and this value is used to set the max carry amount for all critters,can lower or raise it)
StrongBackMax=2000
;//*****************************************************Strong Back Requirements*****************************************************;//
;Strong Back Required Strength
StrongBackRequirementStrength=4
;Strong Back Required Perception
StrongBackRequirementPerception=-10
;Strong Back Required Endurance
StrongBackRequirementEndurance=-10
;Strong Back Required Charisma
StrongBackRequirementCharisma=-10
;Strong Back Required Intelligence
StrongBackRequirementIntelligence=-10
;Strong Back Required Agility
StrongBackRequirementAgility=-10
;Strong Back Required Luck
StrongBackRequirementLuck=-10
;Strong Back Required Small Guns
StrongBackRequirementSmallGuns=-10
;Strong Back Required Big Guns
StrongBackRequirementBigGuns=-10
;Strong Back Required Energy Weapons
StrongBackRequirementEnergyWeapons=-10
;Strong Back Required Unarmed
StrongBackRequirementUnarmed=-10
;Strong Back Required Melee
StrongBackRequirementMelee=-10
;Strong Back Required Throwing
StrongBackRequirementThrowing=-10
;Strong Back Required First Aid
StrongBackRequirementFirstAid=-10
;Strong Back Required Doctor
StrongBackRequirementDoctor=-10
;Strong Back Required Sneak
StrongBackRequirementSneak=-10
;Strong Back Required Lockpick
StrongBackRequirementLockpick=-10
;Strong Back Required Steal
StrongBackRequirementSteal=-10
;Strong Back Required Traps
StrongBackRequirementTraps=-10
;Strong Back Required Science
StrongBackRequirementScience=-10
;Strong Back Required Repair
StrongBackRequirementRepair=-10
;Strong Back Required Speech
StrongBackRequirementSpeech=-10
;Strong Back Required Barter
StrongBackRequirementBarter=-10
;Strong Back Required Gambling
StrongBackRequirementGambling=-10
;Strong Back Required Outdoorsman
StrongBackRequirementOutdoorsman=-10
;Strong Back Required Level
StrongBackRequirementLevel=3
all of those settings are set to a sfall global variable on init of fo2(this is done for each perk in my custum perk scripts),handled in the procedure
Code:
procedure Set_Global_Variables
and it contains this code in that procedure(and will be updated on startup of fo2)
Code:
   /* Strong Back*/
   set_sfall_global(38, get_ini_setting("CustomPerks.ini|PERKS|StrongBackMax"));
   //display_msg("Strong Back Max " + get_sfall_global_int(38));
   set_sfall_global(39, get_ini_setting("CustomPerks.ini|PERKS|StrongBackEnable"));
   //display_msg("Strong Back Enable " + get_sfall_global_int(39));
   set_sfall_global(40, get_ini_setting("CustomPerks.ini|PERKS|StrongBackAmount"));
   //display_msg("Strong Back Amount " + get_sfall_global_int(40));
   set_sfall_global(662, get_ini_setting("CustomPerks.ini|PERKS|StrongBackRequirementStrength"));
   //display_msg("Strong Back Requirement Strength " + get_sfall_global_int(662));
   set_sfall_global(663, get_ini_setting("CustomPerks.ini|PERKS|StrongBackRequirementPerception"));
   //display_msg("Strong Back Requirement Perception " + get_sfall_global_int(663));
   set_sfall_global(664, get_ini_setting("CustomPerks.ini|PERKS|StrongBackRequirementEndurance"));
   //display_msg("Strong Back Requirement Endurance " + get_sfall_global_int(664));
   set_sfall_global(665, get_ini_setting("CustomPerks.ini|PERKS|StrongBackRequirementCharisma"));
   //display_msg("Strong Back Requirement Charisma " + get_sfall_global_int(665));
   set_sfall_global(666, get_ini_setting("CustomPerks.ini|PERKS|StrongBackRequirementIntelligence"));
   //display_msg("Strong Back Requirement Intelligence " + get_sfall_global_int(666));
   set_sfall_global(667, get_ini_setting("CustomPerks.ini|PERKS|StrongBackRequirementAgility"));
   //display_msg("Strong Back Requirement Agility " + get_sfall_global_int(667));
   set_sfall_global(668, get_ini_setting("CustomPerks.ini|PERKS|StrongBackRequirementLuck"));
   //display_msg("Strong Back Requirement Luck " + get_sfall_global_int(668));
   set_sfall_global(669, get_ini_setting("CustomPerks.ini|PERKS|StrongBackRequirementSmallGuns"));
   //display_msg("Strong Back Requirement Small Guns " + get_sfall_global_int(669));
   set_sfall_global(670, get_ini_setting("CustomPerks.ini|PERKS|StrongBackRequirementBigGuns"));
   //display_msg("Strong Back Requirement Big Guns " + get_sfall_global_int(670));
   set_sfall_global(671, get_ini_setting("CustomPerks.ini|PERKS|StrongBackRequirementEnergyWeapons"));
   //display_msg("Strong Back Requirement Energy Weapons " + get_sfall_global_int(671));
   set_sfall_global(672, get_ini_setting("CustomPerks.ini|PERKS|StrongBackRequirementUnarmed"));
   //display_msg("Strong Back Requirement Unarmed " + get_sfall_global_int(672));
   set_sfall_global(673, get_ini_setting("CustomPerks.ini|PERKS|StrongBackRequirementMelee"));
   //display_msg("Strong Back Requirement Melee " + get_sfall_global_int(673));
   set_sfall_global(674, get_ini_setting("CustomPerks.ini|PERKS|StrongBackRequirementThrowing"));
   //display_msg("Strong Back Requirement Throwing " + get_sfall_global_int(674));
   set_sfall_global(675, get_ini_setting("CustomPerks.ini|PERKS|StrongBackRequirementFirstAid"));
   //display_msg("Strong Back Requirement First Aid " + get_sfall_global_int(675));
   set_sfall_global(676, get_ini_setting("CustomPerks.ini|PERKS|StrongBackRequirementDoctor"));
   //display_msg("Strong Back Requirement Doctor " + get_sfall_global_int(676));
   set_sfall_global(677, get_ini_setting("CustomPerks.ini|PERKS|StrongBackRequirementSneak"));
   //display_msg("Strong Back Requirement Sneak " + get_sfall_global_int(677));
   set_sfall_global(678, get_ini_setting("CustomPerks.ini|PERKS|StrongBackRequirementLockpick"));
   //display_msg("Strong Back Requirement Lockpick " + get_sfall_global_int(678));
   set_sfall_global(679, get_ini_setting("CustomPerks.ini|PERKS|StrongBackRequirementSteal"));
   //display_msg("Strong Back Requirement Steal " + get_sfall_global_int(679));
   set_sfall_global(680, get_ini_setting("CustomPerks.ini|PERKS|StrongBackRequirementTraps"));
   //display_msg("Strong Back Requirement Traps " + get_sfall_global_int(680));
   set_sfall_global(681, get_ini_setting("CustomPerks.ini|PERKS|StrongBackRequirementScience"));
   //display_msg("Strong Back Requirement Science " + get_sfall_global_int(681));
   set_sfall_global(682, get_ini_setting("CustomPerks.ini|PERKS|StrongBackRequirementRepair"));
   //display_msg("Strong Back Requirement Repair " + get_sfall_global_int(682));
   set_sfall_global(683, get_ini_setting("CustomPerks.ini|PERKS|StrongBackRequirementSpeech"));
   //display_msg("Strong Back Requirement Speech " + get_sfall_global_int(683));
   set_sfall_global(684, get_ini_setting("CustomPerks.ini|PERKS|StrongBackRequirementBarter"));
   //display_msg("Strong Back Requirement Barter " + get_sfall_global_int(684));
   set_sfall_global(685, get_ini_setting("CustomPerks.ini|PERKS|StrongBackRequirementGambling"));
   //display_msg("Strong Back Requirement Gambling " + get_sfall_global_int(685));
   set_sfall_global(686, get_ini_setting("CustomPerks.ini|PERKS|StrongBackRequirementOutdoorsman"));
   //display_msg("Strong Back Requirement Outdoorsman " + get_sfall_global_int(686));
   set_sfall_global(687, get_ini_setting("CustomPerks.ini|PERKS|StrongBackRequirementLevel"));
   //display_msg("Strong Back Requirement Level " + get_sfall_global_int(687));
the commented(lines with ->//<-) I uncomment when making the perk then start fo2 to make sure my settings are registering,convinient to simply copy paste then paste the new perk over the relevant portions
the point of the above is to define what conditions the player must meet to have the perk available,all of it must be tied together with scripting
since the perk is going to be scripted,neccessary to disable the vanilla perks ,as such :
Code:
 if (get_sfall_global_int(39) == 1) then 
 begin
set_perk_name(13, Carry);
set_perk_desc(13, "");
set_perk_ranks(13, 50);
set_perk_level(13, 100);
set_perk_name(100, Carry2);
set_perk_desc(100, "");
set_perk_ranks(100, 50);
set_perk_level(100, 100);
set_stat_max(12, get_sfall_global_int(38));
set_npc_stat_max(12, get_sfall_global_int(38));
set_pc_stat_max(12, get_sfall_global_int(38));
 end
you can see the above code is only called when global 39 is set to 1,signifying strong back custom perk is enabled
in the above code 13 is strong back and 100 is packrat(these vanilla perk numbers are found in data\text\english\game\Perks.msg)
setting perk level to 100(unreachable player level)makes the perk unattainable for selection
also set_stat_max sets maximum carry weight of critters to w/e global 38 is set to(in my case 2000[the sfall max])
these misc strings are in perk_text.h(my perk text file)
Code:
#define Carry                                                                              "Strong Back"
#define Carry2                                                                             "Pack Rat"
next need to make the new perk selectable for the player,i do this in
Code:
procedure Add_Selectable_Fake_Perks
and the relevant code is :
Code:
   if(Req(a19,b19,c19,d19,e19,f19,g19,h19,i19,j19,k19,l19,m19,n19,o19,p19,q19,r19,s19,t19,u19,v19,w19,x19,y19,z19)) and (carry < get_sfall_global_int(38)) and (get_sfall_global_int(39) == 1) then 
      begin
         set_selectable_perk(StrongBack, 1, 85, StrongBackDescription);
      end
   else
      begin
         set_selectable_perk(StrongBack, 0, 85, StrongBackDescription);
      end
gibberish mostly,i'll break it down :
Code:
(Req(a19,b19,c19,d19,e19,f19,g19,h19,i19,j19,k19,l19,m19,n19,o19,p19,q19,r19,s19,t19,u19,v19,w19,x19,y19,z19))
is reading the global variables from the ini file that were set at startup,if you scroll up,you can see what each value signifies with this define list from my perk_globals.h file
Code:
//What these letters mean :
//a = Required Strength
//b = Required Perception
//c = Required Endurance
//d = Required Charisma
//e = Required Intelligence
//f = Required Agility
//g = Required Luck
//h = Required Small Guns
//i = Required Big Guns
//j = Required Energy Weapons
//k = Required Unarmed
//l = Required Melee
//m = Required Throwing
//n = Required First Aid
//o = Required Doctor
//p = Required Sneak
//q = Required Lockpick
//r = Required Steal
//s = Required Traps
//t = Required Science
//u = Required Repair
//v = Required Speech
//w = Required Barter
//x = Required Gambling
//y = Required Outdoorsman
//z = Required Level
the letter is constant,the number is unique to each perk(tho some jump around)
next :
Code:
(carry < get_sfall_global_int(38))
carry is defined as such in Perks_Inc.h:
Code:
#define carry                                                                   (get_critter_stat(dude_obj,STAT_carry_amt))
and if you remember global 38 is the maximum for the strong back perk to be available,in my game this means if my dude has less then 2000 max carry weight this perk is selectable
next is the perk enabled?
Code:
(get_sfall_global_int(39) == 1)
much more conditions can be set,lots of different conditions are avail for view in my custom perks file for inspiration
next :
if conditions are met then :
Code:
set_selectable_perk(StrongBack, 1, 85, StrongBackDescription);
else
Code:
set_selectable_perk(StrongBack, 0, 85, StrongBackDescription);

set_selectable(name,1,85,desc);

name : in game name of the perk
1 : Boolean selectable or not?
85 : the picture of the perk in game,full list found in skilldex.lst(new art is possible, found in data\art\skilldex\skilldex.lst )
desc : description of the perk
these misc strings are in perk_text.h(my perk text file)
Code:
define StrongBack                                                                         "Strong Back"
#define StrongBackDescription                                                              "AKA Mule.  You can carry an additional " + get_sfall_global_int(40) + " pounds of equipment for each level of this Perk."
next procedure called when perk is selected :
Code:
procedure Selected_Perk
and the code itself(applying the perk)
Code:
   if(has_fake_perk(StrongBack) > get_sfall_global_int(2079)) then 
      begin
         set_pc_extra_stat(STAT_carry_amt, get_pc_extra_stat(STAT_carry_amt) + get_sfall_global_int(40));
         set_sfall_global(2079, get_sfall_global_int(2079) + 1);
      end
has_fake_perk returns the amnt of perks of that name the player has,using global 2079 we can keep track of how much has been applied,if has_* is higher,add an additional x carry weight etc etc
this particular perk doesn't require it but some perks will need to be updated each play session,for those I run this procedure :
Code:
procedure Apply_Perks_Repeat
and run any applicable repeating code

and lastly(tho I wrote it first) the procedure that ties it all together :


Code:
procedure start
begin
   if (game_loaded) then begin
      set_global_script_repeat(60);
      call Set_Global_Variables;
      call Configure_Stock_Perks;
   end
   show_real_perks;
   call Add_Selectable_Fake_Perks;
   call Selected_Perk;
   call Apply_Perks_Repeat;
end

hopefully i havent bored you to tears and this is helpfull
the script and files i referenced can be found at the fallout 2 downloads in my sig

Nirran
 
Last edited:
Thanks a lot for this @Nirran! One thing I've been wondering for a while now, what's the reason you do this step:
Code:
 set_sfall_global(663, get_ini_setting("CustomPerks.ini|PERKS|StrongBackRequirementPerception"));

rather than simply calling the ini setting directly in the script (which is what I, probably foolishly, do)? Is it faster for the engine, or is it just a convenience thing?
 
Last edited by a moderator:
Thanks a lot for this @Nirran! One thing I've been wondering for a while now, what's the reason you do this step:
Code:
 set_sfall_global(663, get_ini_setting("CustomPerks.ini|PERKS|StrongBackRequirementPerception"));

rather than simply calling the ini setting directly in the script (which is what I, probably foolishly, do)? Is it faster for the engine, or is it just a convenience thing?


your welcome :D

at first when I wrote the ini settings I had performance issues,some of them were my code,i found it faster for the engine to read the globals,in fact timeslip added int globals around then(they are slightly faster then string globals),previously they were all strings

performance is the only reason

Nirran
 
at first when I wrote the ini settings I had performance issues,some of them were my code,i found it faster for the engine to read the globals,in fact timeslip added int globals around then(they are slightly faster then string globals),previously they were all strings

performance is the only reason

Nirran
I would suggest not abuse sfall global variables for configs when not necessary. For example, if you want to use some INI value several times inside hook script, just define normal variable in global scope of your script and then use it. Like so:
Code:
variable ini_StrongBackRequirementPerception;
...
// init part of script (which called for every hook script only when loading your game):
ini_StrongBackRequirementPerception := get_ini_setting("CustomPerks.ini|PERKS|StrongBackRequirementPerception");
...
// main part of script (called many times):
if (ini_StrongBackRequirementPerception) then .... etc.

Global scope variables retain their values as long as game is running.

On unrelated note, I have a library to work with arrays (safe working with persistent arrays in sfall globals, without worrying of memory/savegame data leaks; associative arrays; sets), can share if someone wants.
 
@phobos2077 you are prolly right,i know how to use sfall arrays and as I am slightly motivated in fo2 modding at the moment,I will do a test with rapid perks mod I wrote,see if I cant make all the ini settings in one array,though some will not be possible

nirran
 
Last edited by a moderator:
Nirran: Speaking of your Rapid Perks, if I wanted to reduce the level requirement between perks, and the number of perks per level, I'd have to just put:

Code:
set_sfall_global(2123, 1)
// [I]to set the levels between perks to 1
[/I]set_sfall_global(2127, 3)
// [I]to set the perks per level to 3 per level[/I]

into a script. Is this right?

I don't know where to find the list of sfall globals, so I had to figure it out from your source code. If this is right, where would I have to put this, in what kind of script? The point would be to have this work all the time, but I'm not sure what else would I have to call in that script to make it work. Would something simple like this work:

Code:
procedure start;

procedure start begin
   if(game_loaded) then 
      begin
         set_global_script_repeat(60);
         set_sfall_global(2123, 1);
         set_sfall_global(2127, 3);
      end
end

And if this bit is enough, how do I get it called by the game? Ty.
 
Nirran: Speaking of your Rapid Perks, if I wanted to reduce the level requirement between perks, and the number of perks per level, I'd have to just put:

Code:
set_sfall_global(2123, 1)
// [I]to set the levels between perks to 1
[/I]set_sfall_global(2127, 3)
// [I]to set the perks per level to 3 per level[/I]

into a script. Is this right?

I don't know where to find the list of sfall globals, so I had to figure it out from your source code. If this is right, where would I have to put this, in what kind of script? The point would be to have this work all the time, but I'm not sure what else would I have to call in that script to make it work. Would something simple like this work:

Code:
procedure start;

procedure start begin
   if(game_loaded) then 
      begin
         set_global_script_repeat(60);
         set_sfall_global(2123, 1);
         set_sfall_global(2127, 3);
      end
end

And if this bit is enough, how do I get it called by the game? Ty.


yes this is what is needed,the only script needed is Perk_Per.int and your code,but set repeat to 0(it will run once then shut off untill you start fo2 again)
Code:
procedure start;

procedure start begin
   if(game_loaded) then begin
         set_global_script_repeat(0);
         set_sfall_global(2123, 1);
         set_sfall_global(2127, 3);
      end
end

Nirran
 
Thank you so much!

Just to confirm I understood you, I put the modified (repeat 0) code into the allready existing Perk_Per.int (from your level per perk mod?) and that's it? :)
 
no,leave GL_Perk_Per as is,create a new script name it GL_whatever and put the repeat 0 code in it,thats it,starting a new game should have 3 perks at lvl 2

Nirran
 
no,leave GL_Perk_Per as is,create a new script name it GL_whatever and put the repeat 0 code in it,thats it,starting a new game should have 3 perks at lvl 2

Nirran

Unfortunately it's not working for some reason. How about I try just splicing the

Code:
set_sfall_global(2123, 1);
set_sfall_global(2127, 3);

part into the GL_Perk_Per somewhere tactfully? (Hmmm, that didn't work either, which is strange since the perks have worked as described for a few years now, but I have to fiddle with the savegame editor to set up every new character that way.).

I am having trouble with compilin stuff, as the sfall script editor doesn't seem to work on my 32bit win XP, so maybe stuff just isn't compiling right or something? Could someone just compile the following with an up-to-date tool? For science?

Code:
#include "C:\Game Files\Fallout 2\HEADERS\Perk_Inc.h"

procedure start;

procedure start begin
    if(game_loaded) then begin
        set_global_script_repeat(0);
        set_sfall_global(2123, 1);
        set_sfall_global(2127, 3);
        end
    end
 
Last edited:
Back
Top