I swear I have never met another more frustrating issue while modding a Bethesda game.
So, I had the idea to add in dimmable headlamps for Power Armor helmets. Not too hard of a problem: add a new craftable OMOD for each helmet, then write a bunch of Papyrus that will swap that headlamp with other OMODs of varying brightness levels when an aid item/hotkey is used.
Straightforward enough, until I found that there's an engine bug where the game only properly loads the first headlamp spotlight you equip after entering a suit of Power Armor. All headlamps lights after the first one don't load the gobo (the texture the light filters through to project an image), and the color of the light is not loaded properly either (it'll be tinted purple for some reason).
Simple reproduction steps to see this bug in a vanilla game:
Anyway, not totally insurmountable: forcing an exit/reentry of the PA frame will reload the light and make it display properly. Here is where the real problem starts.
Turns out that getting the player out and back into their PA quickly is almost possible, but every avenue I've tried has been a dead end:
- The first thing I tried was to simply wearer.SwitchToPowerArmor(None), wearer.SwitchToPowerArmor(PAFrame).
(Skimming over the boring bits, like finding the PA frame furniture object--also, wearer is my local variable for the actor currently wearing the helmet with an adjustable headlamp)
So, just kick the player out of their frame, then immediately force them back into it. Was a decent idea, but the second SwitchToPowerArmor() call won't work while the player is playing the exit animation, which is like 3.5 seconds. Adding a wait works, but feels absolutely horrible, because switching from the lowest to highest lamp setting takes up to 15 seconds of watching that damn animation.
- Next I thought to do wearer.SwitchToPowerArmor(None), wearer.MoveTo(wearer), wearer.SwitchToPowerArmor(PAFrame).
The first time I tried this it worked fine, the wearer.MoveTo(wearer) call would cancel the exit animation, allowing us to complete the whole cycle in just a few frames. A little clunky, but it works...or, it did, until I relaunched the game. After that, moving the player to themselves now always triggers a loading screen. I have no idea why this started, but I cannot get this method to work anymore, even in an unmodded game. I also tried placing something at the player's feet and then MoveTo()ing them to that, or MoveTo()ing to the PA frame, but these also trigger loading screens. I also tried fiddling with the fMinPlayerMoveToDistForLoadScreen ini setting, but it seems to do nothing.
I have no explanation for why this worked in the first place. Moving on...
- Next I attempted to find some way to cancel an ongoing animation, like playing a different idle with a script, and trying every Papyrus function I could think of that might also interrupt animations. No dice here, nothing seems to be able to do this except for MoveTo().
- Right, so, maybe there's some way to artificially unequip a PA frame without SwitchToPowerArmor(None)? Maybe...wearer.UnequipAll()? Uh, no, oh god no, now my player character requires an SCP designation. Moving on...
- Okay, so what if I make the animation shorter? Easy enough, I just have to find the animation files (in Meshes\Actors\Character\Animations\Furniture\PowerArmor\Neutral: ExitToStand.hkx, ExitToStandCombat.hkx, and QuickExitToStand.hkx), unpack them, hack the duration value to 0, repack and replace. Hacky, but works great as a proof of concept: moving the player out of and then back into their PA is back to only taking a few frames, which is kludgy, but workable.
But, obviously, this creates a new problem: since this is an animation replacer, the PA exit animation is always instant. Not a good side-effect.
- After a little research, it's pretty simple to conditionally use different sets of animations, based on actor keywords, by setting up an animation subgraph. Perfect! Right?
The process doesn't seem too difficult: in this case, all I (apparently) need to do is:
- Make a new keyword
- Duplicate HumanRaceSubGraphData
- Set it to be Additive to HumanRaceSubGraphData
- Make a (near) duplicate of the already-existing subgraph entry for Meshes\Actors\Character\Behavoirs\FurnitureNoMirrorBehavior.hkx with a target keyword of FurnitureTypePowerArmor, with some slight modifications: add my new keyword into the Actor Keywords filter, and add a new path pointing to where I've put my custom ExitToStand.hkx/etc animations--like so [image]
- Confirm that the entry does, in fact, add (the UI is dodgy)
- Run the CK with these arguments to build anim text data:
CreationKit.exe -GenerateAnimInfo:IDEK_ExitAnimTest.esp .\Data .\Data
Unfortunately, though, this doesn't seem to work, at all. Instead of using a different animation set, this prevents the actor from playing any PA furniture-related animations. If the player character is already in a suit of PA, attempting to exit shows the message You can't exit your armor here. Attempting to get into a PA frame shows You cannot use this at this time. Removing the keyword for the new subgraph returns things to normal.
Thinking that this might be because of my crappy hacked animations, I tried setting the animation paths up as an exact duplicate of the vanilla one, except with my actor keyword, and rebuilt anim text data again. Theoretically, then, actors with my keyword should use my new subgraph, but they'll use the exact same animation set as the vanilla subgraph. Same issue. Removing my additive subgraph Race record and moving the (still near-duplicate) subgraph entry as a direct edit into HumanRaceSubGraphData also does not work. #[email protected]%!#?!
So, here's where I'm at. I cannot find an adequate solution to any of these problems:
- Lights and their gobos not loading properly
- Reloading an incorrectly loaded spotlight without restarting the game, or exiting and reentering the PA frame
- Removing an actor from their Power Armor without having to watch the exit animation
- Cancelling or interrupting a PA exit animation
- Conditionally replacing the PA exit animations
Since the last one is the most complicated, but also the most promising, I made a little test mod here in case anyone would be willing to experiment with it. It adds an additive subgraph that's active when an actor has a particular keyword, which can be toggled by the Aid item that the mod also adds to your inventory on install. Theoretically, using the item should allow you to instantly exit a PA frame. Using the item again should restore the normal animation. In practice, using the item prevents PA animations from working at all.
Hopefully someone with more knowledge on how subgraphs work can educate me on what I'm doing wrong.
Or, if anyone can think of a solution to any of the other problems I just listed, any one of those would work too, and I would be greatly appreciative.
If nothing else, maybe future generations will find this post and save themselves the bother of attempting such an undertaking.
Thanks for reading my dissertation about an exercise in frustration.