get_proto_database

JimTheDinosaur

Vault Dweller
Modder
Everybody who's spent more than five minutes modding Fallout knows that editing proto files is a dangerous business. The game hates you for it and tries everything it can to stop you from doing it. It is said that every time someone edits a proto MCA feels a sharp pain in his lower abdomen.

Anyway, Timeslip in his infinite wisdom has given us the get/set_proto_data functions which let us all avoid the horrors of proto editing in favor of harmless scripting. The only problem is that it's never really clear under which value the juicy proto bits are stored, so I thought I might as well do some exploring using a variation of the method described by Nirran here and make a database. I just looked for data I thought could be useful to me, and skipped some other ones, but you pretty easily guess the missing ones by just checking here and comparing with the data listed below (e.g. I didn't check the "number of the list of the critical failures possible for this weapon", but you can deduce from the order that it's 76). The only very slight downside to the scripting approach is that the new data is temporary (reload the game and it's gone), but this can be easily circumvented by just checking for a return to the old value and resetting it in that case.

Proto General

ObjectID: 0 (the numbers in the header files)
TextID: 4 (usually ObjectID * 100)

Items General

Flags Ext: 25 (if not a weapon, it's -16777xxx, with xxx being 040 for items both usable on yourself and others, 048 for only usable on self, 56 for unusable, 200 for chems, 184 for containers, and 216 for what I think are quest related items, but I'm not sure).
Item Type: 32
Material: 108 (I don't think they did this consistently; a first aid book for instance comes up as metal, but I tried it with Leather Armor and sure enough leather pops up)
Size: 112
Cost: 120
Weight: 116

Weapons

Flags Extended: 25 (what I understand so far is that you want -16777xxy, with xx being either 21 or 05 and y being 6 for a onehanded weapon, 4 for a non-biggun twohanded weapon, and 3 for a biggun)
Min Dam: 40
Max Dam: 44
Max Range 1: 52
Max Range 2: 56
Min St: 64
AP cost 1: 68
AP cost 2: 72
Burst Rounds: 84
Magazine Size: 96

Armor

AC: 36
DR Normal: 40
DR Laser: 44
DR Fire: 48
DR Plasma: 52
DR Electrical: 56
DR EMP: 60
DR Explosion: 64
DT Normal: 68
DT Laser: 72
DT Fire: 76
DT Plasma: 80
DT Electrical: 84
DT EMP: 88
DT Explosion: 92

Drugs

Changed Stats Immediate: 36, 40, 44 (look in define.h for the relevant values; e.g. charisma is 3, sequence is 13, etc.)
Changed Amount Immediate: 48, 52, 56
Duration 1: 60 (in minutes)
Changed Amount after first duration: 64, 68, 72
Duration 2: 76 (in minutes)
Changed Amount after second duration: 80, 84, 88
Addiction Rate: 92

Ammunition

Caliber: 36 (check the proto.msg from 300 on for the values)
Mag Size: 40
AC mod: 44
DR Mod: 48
Damage multiplier: 52
Damage divisor: 56

Critters

base stats:
ST: 36
PE: 40
EN: 44
CH: 48
IN: 52
AG: 56
LK: 60
HP: 64
AP: 68
AC: 72
Melee Dam: 80
Carry Weight: 84
Sequence: 88
Heal Rate: 92
Crit Chance: 96

Resistances:
DT Normal: 244
DT Laser: 248
DT Fire: 252
DT Plasma: 256
DT Electrical: 260
DT EMP: 264
DT Explosion: 268
DR Normal: 272
DR Laser: 276
DR Fire: 280
DR Plasma: 284
DR Electrical: 288
DR EMP: 292
DR Explosion: 296

skills extra (so on top of the skill's base value of, for instance, 4*AG in the case of throwing):
Small Guns: 316
Big Guns: 320
Energy Weapons: 324
Unarmed: 328
Melee: 332
Throwing: 336
First aid: 340
Doctor: 344
Sneak: 348
Lockpick: 352
Steal: 356
Traps: 360
Science: 364
Repair: 368
Speech: 372
Barter: 376
Gambling: 380
Outdoorsman:384

misc:
Body Type: 388 (0 for biped, 1 for quadruped, 2 for robotic)
Experience Value: 392
Kill Type: 396 (check define.h for the value)
 
Hm I never experienced bad things when editing protos. I even only use the BIS mapper and despite of it being unhandy at times, it works without problems.
 
Lexx said:
Hm I never experienced bad things when editing protos. I even only use the BIS mapper and despite of it being unhandy at times, it works without problems.
Modifying proto files directly hasn't been an issue for years now, but having those changes take affect without replacing every instance of a proto you modified on every map that contains that proto has been a considerable challenge.

Scripting this allows for all instances of a proto to be affected whenever and however it's used.

Though I would still wonder if critters stamped with a specific armor would adopt a change made to an armor proto or if the critter would have to be modified as well.
 
Glovz said:
Modifying proto files directly hasn't been an issue for years now, but having those changes take affect without replacing every instance of a proto you modified on every map that contains that proto has been a considerable challenge.

Scripting this allows for all instances of a proto to be affected whenever and however it's used.

Though I would still wonder if critters stamped with a specific armor would adopt a change made to an armor proto or if the critter would have to be modified as well.

They would have to be modified as well, which is why it's annoying that I can't find the Damage Resistance/Threshold values, which are the most obvious workarounds for that problem.
 
I know Glovz and me are probably the only ones who recognize the inherent genius of this method, but in case someone's interested, I think I finally have a more or less comprehensive list of the available proto data.
 
2JimTheDinosaur: the description of extended item flags is vague. You might want to check out this awesome wiki page: http://falloutmods.wikia.com/wiki/PRO_File_Format
As prototypes are stored in memory more or less in the same format as in PRO files, you might expect that descriptions to apply here as well.
Actually the correct offset is 24 (first 3 bytes are the flags, and last byte is weapon attack modes compressed into 1 byte (lower octet (4 bits) is attack mode 1 and higher is attack mode 2).

Example usage (hs_itemdamage):
Code:
// get attack types bits from proto
attackModes_8 := get_proto_data(weaponPid, 24) bwand 0x000000FF;
attackModes := temp_array(2, 1);
attackModes[0] := attackModes_8 bwand 0x0F;
attackModes[1] := (attackModes_8 bwand 0xF0) / 16;
// actual weapon attack type
attackMode := attackModes[attackType % 2];

Some of the values in OP in header format:
Code:
// offsets for get_proto_data
#define PRODATA_PID             (1)
#define PRODATA_TEXTID          (4)

// items
#define PRODATA_IT_FLAGS       (24)
#define PRODATA_IT_TYPE        (32)
#define PRODATA_IT_MATERIAL   (108)
#define PRODATA_IT_SIZE       (112)
#define PRODATA_IT_WEIGHT     (116)
#define PRODATA_IT_COST       (120)

// weapons
#define PRODATA_IT_WP_DMG_MIN     (40)
#define PRODATA_IT_WP_DMG_MAX     (44)
#define PRODATA_IT_WP_RANGE_MIN   (52)
#define PRODATA_IT_WP_RANGE_MAX   (56)
#define PRODATA_IT_WP_MIN_ST      (64)
#define PRODATA_IT_WP_APCOST_1    (68)
#define PRODATA_IT_WP_APCOST_2    (72)
#define PRODATA_IT_WP_BURST       (84)
#define PRODATA_IT_WP_MAG_SIZE    (96)
#define PRODATA_IT_WP_ANIM        (36)

// armor
#define PRODATA_IT_AR_AC          (36)
#define PRODATA_IT_AR_DR_NORMAL    (40)
#define PRODATA_IT_AR_DR_LASER     (44)
#define PRODATA_IT_AR_DR_FIRE      (48)
#define PRODATA_IT_AR_DR_PLASMA    (52)
#define PRODATA_IT_AR_DR_ELECTRICAL   (56)
#define PRODATA_IT_AR_DR_EMP       (60)
#define PRODATA_IT_AR_DR_EXPLOSION (64)
#define PRODATA_IT_AR_DT_NORMAL    (68)
#define PRODATA_IT_AR_DT_LASER     (72)
#define PRODATA_IT_AR_DT_FIRE      (76)
#define PRODATA_IT_AR_DT_PLASMA    (80)
#define PRODATA_IT_AR_DT_ELECTRICAL   (84)
#define PRODATA_IT_AR_DT_EMP       (88)
#define PRODATA_IT_AR_DT_EXPLOSION (92)

// ammo
#define PRODATA_IT_AM_CALIBER      (36)
#define PRODATA_IT_AM_MAG_SIZE     (40)
#define PRODATA_IT_AM_AC_MOD       (44)
#define PRODATA_IT_AM_DR_MOD       (48)
#define PRODATA_IT_AM_DMG_MULT     (52)
#define PRODATA_IT_AM_DMG_DIV      (56)

// critters
#define PRODATA_CR_KILL_EXP   (392)
#define PRODATA_CR_KILL_TYPE  (396)
 
Last edited:
Crap, yeah, I should really update these threads once in a while instead of letting them rust with inaccurate data. Nirran has a really neat tool for "unwrapping" the extended item data I've been using a lot, but yours looks a lot more compact, cool!
 
@phobos2077, again, dude, awesome little workaround! @Nirran, if you ever feel like working on your hs_combatdamage again, you can replace the whole mainattack, secondaryattack and convertbitfield procedures with just

Code:
procedure MainAttack(variable value) begin
   attackModes_8 := get_proto_data(value, 24) bwand 0x000000FF;
    value:= (attackModes_8 bwand 0x0F);
   return value;
end
            
procedure SecondaryAttack(variable value) begin
   attackModes_8 := get_proto_data(value, 24) bwand 0x000000FF;
    value:= ((attackModes_8 bwand 0xF0) / 16);
   return value;
end

Probably little more than a convenience thing, but I for one like to have to do less scrolling :).
 
Last edited by a moderator:
One little thing that might be useful for people who want to find the original proto data of an item after having altered it through set_proto_data (e.g. you've set the desert eagle's mag size to 5 momentarily for whatever reason, and want to revert to the original 8 easily). Unless @phobos2077 has already made a more straightforward way of doing this, this might come in handy:

Code:
               proto_dict:=create_array(num_of_protos + 1, 122);	       set_sfall_global("protdict", proto_dict);
               pidcount:=1;
               while pidcount <= num_of_protos do begin
                 proto_dict[pidcount]:=create_array((120/4) + 1, 3);
                 counter:=1;
                 while counter < (120/4) do begin
                    set_array(get_array(proto_dict, pidcount), counter, get_proto_data(pidcount, counter*4));
                    counter+=1;
                 end
                 pidcount+=1;
               end


            //display_msg(" desert eagle ammo " + get_orig_proto(PID_DESERT_EAGLE, PROTO_WP_MAG_SIZE));

Add this to your Define.h:

Code:
#define get_orig_proto(x, y)     get_array(get_array(get_sfall_global_int("protdict"), x), (y/4))

If you let this run once at the beginning of the game, you can then just access it any time you want (e.g. the above message returns the original mag size before you've changed it, i.e. 8). num_of_protos is the number of unique items you have in your mod.

edit: sorry about the crappy formatting, but
Code:
 works even worse in this version of nma than in the previous.
 
Last edited:
You and Glovz aren't the only ones, I love this method and it will save so much time and headaches.

Have you tried it for changing item type completely? i.e. will this let you turn all Flares into Misc instead of Weapon without crashing or causing other weirdness? Currently it is impossible to avoid crashes with such a change unless you replace every instance on every map. Quite a pain in the ass.

P.S. for the OP, Timeslip is a "her", not a "his" :p
 
Last edited:
Have you tried it for changing item type completely? i.e. will this let you turn all Flares into Misc instead of Weapon without crashing or causing other weirdness? Currently it is impossible to avoid crashes with such a change unless you replace every instance on every map. Quite a pain in the ass.

Yeah, I tried doing this a while ago and it worked fine iirc.

Code:
      set_proto_data(PID_FLARE, PROTO_IT_TYPE, item_type_misc_item);
 
You and Glovz aren't the only ones, I love this method and it will save so much time and headaches.

Have you tried it for changing item type completely? i.e. will this let you turn all Flares into Misc instead of Weapon without crashing or causing other weirdness? Currently it is impossible to avoid crashes with such a change unless you replace every instance on every map. Quite a pain in the ass.

P.S. for the OP, Timeslip is a "her", not a "his" :p

I'm curious, why would you possibly need to turn flares into misc?
 
I edited my post to add the proper Define.h entry, so you can make it work instantly. Provided you use the original array settings (I really should start using phobos's arrays, but I'm too accustomed I guess).

I'm guessing for the same reason I did it originally, namely to just turn it into a torch for use in hand. Of course I just did it cause I couldn't get flares to work properly; not sure why Sduibek would.
 
(I really should start using phobos's arrays, but I'm too accustomed I guess).
Man, you are already using them :D in reality, arraysBehavior setting only changes tiny bit of logic which saves all normal arrays by default under the same key (basically create_array(...) in "old" mode is the same as save_array(create_array(...) in "new" mode). Nothing prevents you from using associative arrays, array expressions and foreach loops in old mode. You can switch to new behavior when you have time to change how arrays are created and accessed in your scripts.

I'm guessing for the same reason I did it originally, namely to just turn it into a torch for use in hand. Of course I just did it cause I couldn't get flares to work properly; not sure why Sduibek would.
If it was me, I would just replace Flare PRO file with MISC prototype (different file length) and set all appropriate values for a flare, then script it as I need using hs_useobj hook.
 
Back
Top