Balancing steal skill

Discussion in 'Fallout General Modding' started by Daemonjax, Jul 10, 2016.

  1. Daemonjax

    Daemonjax First time out of the vault

    Jul 5, 2016
    So, as far as I can tell, there's really no real practical difference between 30 steal and 300 steal.

    This bothered me for two reasons:

    1) All of my characters end up being master pickpockets, even if I didn't build them that way
    2) It makes the game easier than it should be, despite using mods that increase difficulty.

    So, I did some fiddling, and realized a simple way to balance it (balanced insofar you have to invest into it to use it).

    A) Increase the size of all items significantly (I used weight as a general guide and used f2wedit)
    1. All items with 0 weight: size = 5
    2. All items with 1 - 4 weight: size = weight * 15
    3. All items with 5+ weight: size = 100 (just to keep things simple because there's a lot of items to edit)
    4. Some items with 0 weight, I changed to have a weight of 1 (like drugs)
    5. Some items with a weight of 1, changed to 0 (pieces of paper and keys).
    6. Increase the max size of most containers by a factor of 2 to 15 (depending on how I felt about it).
    B) Reduced the level requirement of the Pickpocketing perk to level 3 (using sfall):
    [37] ;Pickpocket

    So... pickpocketing is now pretty much impossible unless you put points into the skill and get the perk, which can be done at level 3 if you tag the skill.

    I haven't seen this approach posted anywhere, so I thought I'd share the info. The edits took me about 35 minutes.

    I started a new fallout 2 game and the change really hit home when my non-stealing character was rescuing smiley. Usually, the smart thing to do is to pickpocket the 10 gecko hides off him, rescue him for the exp, get the gecko skinning perk, and choose Sulik as the reward. Win, win, win, and win.. But now I couldn't exploit this encounter (well, I could have if I invested in steal)... I had to choose. Which was cool. What I ended up doing was something I never tried before: I brought him to the entrance of the toxic caves, where he proceeded to thank me and tell me he's got it from here. And then I turned around and nailed him with a plant spike aimed at his balls. Crit knockdown (thanks to finesse). Then another aimed at his head (another crit) knocking him unconscious. I looted him and left him on the cave floor naked at the entrance. I then went back to Klamath in my new leather armor to get my reward for rescuing Smiley. He was there, none too pleased, but won't attack as long as I never talk to him again. So, no gecko skinning perk or 1-6% outdoorsman for me, but it's a fair trade for the 10 golden hides and the leather armor... and sulik takes care of outdoorsman anyways.
    Last edited: Jul 10, 2016
  2. Darek

    Darek is currently unavailable

    Jan 7, 2008
    While I like the idea, I think you've made it too tough if the player is "forced" to take the pickpocketing perk. Also, doesn't the car trunk check for size? If so, hasn't your changes drastically reduced the amount you can place in it?
  3. Daemonjax

    Daemonjax First time out of the vault

    Jul 5, 2016
    Well, that's why I also changed the pickpocketing perk to be a level 3 perk, since that's where the least powerful ones are so it's not so great a sacrifice (it's usually quickpockets or maybe toughness) . Being able to pickpocket anything is pretty powerful (at least in my game, with how the economy is modded), and that's fine, as long as the character is built that way... is the player "forced" to tag and increase small guns or take any number of perks if he wants to be good at shooting small guns? Basically, yeah... and that's OK, too.

    I agree it's not a perfect solution (perfect would be implementing something like Divinity Original Sin's pickpocketing system since it isn't chance based), but it's the only one I'm aware of that's currently doable.

    Yeah, max size for all containers needed to be increased. Personally, I multiplied the trunk size by 15. But you're right, it's possible the size increases for items needs to be more granular (but I just wanted to keep it simple enough to get through all the manual edits quickly). I guess I could have written a java program to modify all the proto files directly because then it could have a more complicated formula. I just don't feel like studying the hex code of the proto files to do that. The trunk will definitely not be able to hold so many guns and armor... but maybe that's a good thing. I'm going to see how it plays out with the way I have it now, but so far so good.

    EDIT: It would probably be better to use the sfall hook script to make stealing non-chance based, but I'm not sure how it works yet or how to get the size/weight of an item, but I imagine it's possible and I'll figure it out eventually.
    Last edited: Jul 12, 2016
  4. burn

    burn A Smooth-Skin

    Apr 22, 2012
    I stopped stealing since switching to no-reload runs. It's just not worth it.
    Now, if it could be modified so that the whole town doesn't turn on you upon a failed attempt, that would be interesting.

    PRO file format is described pretty well, so no research is really needed. An example how I make unlimited trunk.
  5. Daemonjax

    Daemonjax First time out of the vault

    Jul 5, 2016
    I agree that a steal system that doesn't promote save scumming would be best.

    I was looking into what's possible using sfall hook scripts, and I think it's possible to implement something like divinity original sins. The only part I'm not sure about would be how best to prevent the player from pickpocketing the same person more than once (otherwise they'd be able to circumvent the whole system by stealing one item at a time) without touching every script for every npc. If I could somehow get and store a unique identifier for each npc, that would solve it.

    I imagine a GUI popup showing the current value/weight/size/whatever stolen and the max allowed (based on skill and perks) could be made in a similar to the Mr. Fixit mod, I just don't know if that popup window can exist while mouse focus is maintained on the item transfer window. It may be possible.

    EDIT: I think it would be a simple matter to use the sfall script hook hs_steal to force a success for every steal attempt if certain conditions are met (e.g. tagged steal skill + skill at 100 + pickpocket perk + thief perk + master thief perk), but I'm not sure it would be so easy to remove the experience bonus when successful. Maybe the thief perk allows 2 successful attempts, and master thief allows 3. After that, the person can't be pickpocketed anymore, which would means I could leave the exp bonus. Would have to auto close the item transfer window after the last successful attempt, and I don't know how to do that... hmm... tap_key(DIK_ESCAPE); might work. Would still need to figure out how to store the number of successful pickpockets for each npc, and that would only really work well if each npc has a unique identifier that remains unchanged between sessions. Can I store an array of object pointers?

    According to that, yes, and I could also use a map (use the npc object pointer as a key and the value is the number of successful steal attempts for them) instead... and they can be saved between sessions. I don't know if the object pointers change between sessions, though. If they do (and they very well might), then that approach won't work. In that case, I'd have to try and build some unique identifier string for each npc, like name + something else. No idea what the something else would be... my first thought would be map name/number + orignal starting xy coordinate on the map, but there's no way to get that afaik, so it's not a very good idea. If I'm willing to touch all npc scripts, then there are multiple approaches that could work.
    Last edited: Jul 15, 2016
  6. burn

    burn A Smooth-Skin

    Apr 22, 2012
    Not sure about pointers. I guess you'll just have to test.
    I'd avoid touching all scripts, because then either the mod will have very limited compatibility, or they'll have to be re-built at install time, which is an effort on its own.
  7. Daemonjax

    Daemonjax First time out of the vault

    Jul 5, 2016
    I did some testing on object pointers on another mod I'm working on, and when converted to a string, the string changes between sessions. At least for items, but it would make sense if that's also true for all object pointers. So that won't work as a unique identifier. EDIT: Verified critter object pointers don't persist between sessions (tested by converting them to a string).

    I thought of another way: I can use a random number as a unique identifier, as long as I can store it on the npc itself.

    Specifically, I can randomize some useless non-combat skills on npcs (first aid, etc.) the first time you steal from them -- I would imagine that these changes persist between sessions.

    0x815e - void set_critter_base_stat(CritterPtr, int StatID, int value)
    0x815f - void set_critter_extra_stat(CritterPtr, int StatID, int value)
    0x8160 - int get_critter_base_stat(CritterPtr, int StatID)
    0x8161 - int get_critter_extra_stat(CritterPtr, int StatID)

    Even if I just end up using a handful of skills (I may luck out and age can be 32bit number, but I doubt it), a range of 0 - 300 is more than 8 bits of information. String 4 of them together, and you get something atleast as good as a 32bit random number (critter PID + current map + random 32 bit number should suffice as hash key for the map data structure). I image a hash collision would prevent you from stealing from the npc erroneously (it says I stole from this other raider too after I stole from one of his buddies), but it should be so rare it'll never happen... and I could hide it behind a fluff string of text so you'd just shrug and move on to the next target anyways. Good enough for a game, anyways.

    Assuming modified npc stats persist across sessions (do they?), and that the savegame bloat from the map array isn't insane (I guess that's relative, and it would only increase linearly), then I wouldn't need to touch npc scripts.

    Hell, I wouldn't even need a map array at all. If npc stat changes persist, I could just use the npc's age (or whatever useless stat) as a bit flag! 8bits would be more than enough. I could probably get away just using 2 or 3 bits. Wouldn't get any simpler than that.

    Update: Tested and it doesn't work. Two problems with it really, and either would be enough to kill that idea:

    1) When I increase the age of an Addict in the Den, all Addicts' ages increase by the same amount. So it increases the proto's age, and since they share the proto, they get all the effects of the change.
    2) The change doesn't persist across sessions (it does for companions, though, but that's not useful).

    So the last idea I have is to add a number of unstealable/weightless objects to their inventory upon the first steal attempt (let's call them tokens). The tokens would represent the number of successful steal attempts, and using other token types I could track other things. AFAIK, their inventories persist across sessions, so it should work (unless it doesn't). I don't know how to do this, but I'll look into it. I'm concerned I won't be able to make something unstealable via scripting in a way that's invisible to the player.

    So, it looks like it's not currently possible to set the hide/unhide flag on inventory items via sfall -- according to NovaRain in this thread: Furthermore, if it was made possible, it's likely that once hidden the item(s) would no longer be able to be affected by scripting -- but maybe unhiding the object and then rehiding after you're done may work around that.

    As a solution, I considered remove the tokens from the npc's inventory just before the first steal attempt, but I don't think there is a way to reliably determine when the player is done stealing in order to know when to add them back.

    The closest thing I've thought of that may be a working solutions are:

    A) Leave the tokens in their inventories, but try and make them as close to invisible to the player as possible. Also prevent the player from stealing them (somehow, but I think I can) via the hs_steal hook, so that if you try, exactly nothing seems to happen (I'd have to figure out some way to reverse/prevent the exp gain). To make them unobtrusive to the player, I could set the inventory icon for them to look exactly like background of the transaction window and maybe somehow blank out the tooltip when you hover your mouse over it (give them no names).

    B) Leave the tokens in their inventories for the player to see, but make them humorous. This has the advantage over A in that it would take a lot less effort and would definitely work. I could name them "Private Parts" and the icon looks like male genitals, boobs, or a weird green thing (depending on whether the target is male, female, or a mutant) and I set it up so the player is always caught if he tries to steal them. It kinda fits with Fallout 2's brand of humor, I'm just not so sure we need more of it.

    C) Leave the tokens in their inventories for the player to see, but make them provide some kind of gameplay function during pickpocketing. Like a meter (a poor man's GUI -- when Suspicion reaches 100, you get caught). Something like that anyways. Again, trying to steal them would result in failure, so you just don't try. This has the advantage over A and B in that it won't offend anyone and is still a lot less effort than A. It would also definitely work. On the other hand, I was kinda planning to make an actual graphical overlay for player feedback (kinda like in the Mr Fixit mod) during stealing... but maybe that turns out to be impossible (I don't know if I can create a window without the mouse needing to focus on it) or too hard (I doubt it).

    What do you guys think? I still have to test to verify that objects added to inventories persist (I believe they do, except possibly shopkeepers, but they are all unique npcs, so I can use another approach with them).
    Last edited: Jul 16, 2016
  8. bratmanntoffel

    bratmanntoffel First time out of the vault

    Nov 17, 2015
    Sorry for gravedigging an old thread but it appears like this is the only one for that topic to fix the broken steal system.
    And I must say I quite like your first attempt. Sure fiddling with tokens and deep scripting could find a more smooth solution (@Daemonjax, keep it up if you're still on this) but as a first fix, editing the item sizes can produce quite good results.
    But your numbers should be corrected.
    Acording to the steal formula @falltergeist posted here:
    the size modifier is 4 * item_size(item).
    So, with an item_size of 5 for example, stealing chance would start with 1% at skill=21.
    With item_size = 10, 1% chance starts at 41.
    With item_size = 20, 1% chance starts at 81.
    And so on. This even creates sth. of a hard limit for stealing.
    If it fails it does a roll_vs_skill(catch_chance, 0) with
    catch_chance = steal_skill(mark). So the critter's steal skill is basicly the chance to get caught.

    Therefore I suggest following edits:

    0) think about what range you want for stealing
    1) edit item_size according to that range
    2) increase the size of containers
    3) edit pickpocket_perk to higher skill and/or
    level requirement
    4) change steal skill of critters to 0 for no
    hostility and end of safescumming or a bit higher for
    some hostility

    My suggestion would be like this:
    0) success beginning from 20% up to 120% steal skill, depending on item size (equals difficulty)
    1) item_size = 5 (20% steal) up to 30 (120% steal)
    smallest (fruits,...) =5, start at 21 steal
    stims/ammo =8 to 10, start at 33 to 41 steal
    pistols =10 to 15, start at 41 to 61 steal
    rifles =13 to 20, start at 53 to 81 steal
    bigger guns =20 to 30, start at 81 to 121 steal
    2) increase container size * 5
    3) change pickpocket to require steal=100, lvl=18
    4) regular townspeople: steal=0,
    guys w/ weapons: steal=1 to 10
    soldiers like ncr police: steal=20
    tough soldiers like enclave: steal=30

    Numbers may vary :)

    With this you have something like a hard border for success, forcing the player to actually invest in steal.
    Moving the pickpocket perk to higher skill and/or level will leave it in the game, making it a convenience choice or high reward and still forces investing in skill.
    Editing critter steal skill to 0 would prevent annoying town hostility and savescumming.
    Choosing higher numbers for tough guys preserves the danger aspect and would simulate more realistic behavior, as guys like Metzger won't tolerate f*gging with them.

    I, for one, will implement these in my personal WIP-mod to see how it works out.
    Last edited: Oct 3, 2020