Open Animation Replacer v2.0.2
I started working on this plugin while Dynamic Animation Replacer wasn't updated for the most recent Skyrim version, and nobody knew whether it would ever be. Shortly after I started, DAR suddenly received an update, and by that point I've already made significant progress on my plugin as a replacement for DAR. I've decided to continue, focusing on adding new features and ensuring extensibility.
There's been quite a few things that animators wanted from an animation replacer that DAR didn't support. DAR is also closed source, so nobody else can update it when the original author is missing, which has already proven to cause quite a mess when it didn't receive an update to the most recent Skyrim patch for a long time, with people downgrading their game version because they couldn't use some of the amazing animation replacers available. That's most likely going to happen again - for a while now Skyrim has been receiving regular updates on the private development branch on Steam - which means that another (big?) patch is probably on the way, which might require SKSE plugins to get updated. Being closed source also meant that nobody else could contribute to the plugin. Felisky (DAR's author) has stated that they don't have time to mod anymore, so we can't really expect any new features for DAR in the foreseeable future. Dynamic animation replacement is an incredibly powerful concept that enabled so many cool mods, and I believe it deserves to be iterated on and developed further.
This plugin is not a reverse engineered modification of Dynamic Animation Replacer. It does not include any of Dynamic Animation Replacer's code, aside from the parts that interact with the game code itself and can only be done in one way. It is my own work, based mostly on my own research into the game.
In the later stages of development of this plugin, when I was already pretty much done with the core and have been focusing on the in-game editor, DAR has been reverse engineered by someone else and posted on GitHub (and later even ported to CommonLibSSE). You can compare the source with my own and see that everything is pretty much completely different.
Open Animation Replacer has a SKSE plugin API that lets other plugins add new conditions, thus allowing other authors to extend the possibilities without having it all depend on the original author. New features to the plugin itself, done as pull requests on GitHub, are very welcome too.
While this plugin is intended to be a successor of Dynamic Animation Replacer, with full backwards compatibility and new features, please consider downloading and endorsing DAR if you haven't before. The original idea was Felisky's.
I'm very excited about the new possibilities, and look forward to mods utilizing them!
Features
- Dynamic replacement of animations based on configurable conditions.
- Full backward compatibility with Dynamic Animation Replacer based mods.
- Many new conditions as well as improvements to existing ones (e.g. support for keyword EditorIDs).
- Paired animations are supported.
- Non-actor animations are supported.
- Correctly replaces animations on animation loop and echo.
- Filters out duplicated replacer animations that contribute to the animation limit, without affecting the results.
- Animation variants for easy randomization.
- Replacer submods can have additional settings, allowing things such as:
- Constant polling of required conditions while the animation is playing, resulting and immediate replacement when the situation changes, with proper blending between the previous and new animation.
- Keeping the results of random conditions on animation loop, useful for movement mods so the animation isn't replaced every few steps.
- Sharing random results throughout the whole submod, so the whole animation set is randomized together.
- Ignoring the No Triggers animation clip flag which is enabled on some animation clips in vanilla, which normally causes annotated animation events to be ignored.
- Setting a required project name (e.g. so a particular submod only loads for DefaultMale or DefaultFemale etc.)
- Setting the name of the folder that contains animations, so multiple submods can include the same animations without duplicating them.
- In-game editor that lets you inspect and edit conditions, priority and other features of replacer mods while in-game, and immediately see and test the changes.
- Preview any replacer animation in the in-game editor.
- Animation log UI that helps identify the most recently played animations.
- Animations can start preloading while in the main menu.
- A small progress bar that displays animation preloading progress.
- Increased animation limit up to 32767 per project.
- Increased Havok heap size for better stability with lots of animations.
- API for other SKSE plugins to add new custom conditions.
- Everything is done through SKSE and can be installed or uninstalled anytime.
Experimental features include:
- Increased animation limit up to 65534 per project.
A technical description for those interested: A Havok behavior animation clip has a 16-bit signed integer variable (int16) that represents the index of the entry in a huge animation binding array that should be read when the clip is activated. The maximum range of an int16 value is -32768 to 32767. However, almost the entire negative part of the possible values is unused. Only -1 is used as a special value for situations such as when the animation clip is uninitialized. The experimental setting patches all the places in the game code I could find where the value is treated as a signed integer, and changes the instructions so it's treated as an unsigned integer instead (uint16). An unsigned integer can have values from 0 to 65535. The value that was previously -1 is still reserved, hence the maximum of 65534 animations. The setting is considered experimental because I might have missed some places to patch, and not many people will actually reach the 32k limit in the first place. Only enable it if you actually need it, or are curious, though you probably won't see any potential issues if you aren't actually over the limit.
- Disabling preloading animations.
This setting appears to work just fine for me, but some testers have previously reported seeing short T-Poses with it enabled. Consider checking it out, it should have less impact on the memory footprint of the game and there's no animation loading queue at all with this setting enabled.
Structure
The replacer mod structure tries to keep things neatly organized. Since version 2.0.0, the replacer mods will be recognized anywhere inside Data\Meshes. An easy way of figuring out the correct way to place the replacer mod is to think of it as interrupting the original animation path with a block of OpenAnimationReplacer\MyMod\MySubmod\.
This means, for a replacer mod that is supposed to replace an animation originally placed in Data\Meshes\actors\character\animations\male\mt_idle.hkx, the replacer mod should be placed like any of the following examples:
- Data\Meshes\OpenAnimationReplacer\MyMod\MySubmod\actors\character\animations\male\mt_idle.hkx
- Data\Meshes\actors\OpenAnimationReplacer\MyMod\MySubmod\character\animations\male\mt_idle.hkx
- Data\Meshes\actors\character\OpenAnimationReplacer\MyMod\MySubmod\animations\male\mt_idle.hkx
- etc...
The structure is based on the concept of a replacer mod containing multiple submods.
Each replacer mod contains one or more submods, and a configuration .json file that currently just contains the mod name and description. Each submod contains replacer animations and a configuration .json file that contains all the information about the animations contained within, like the submod name, description, priority, conditions and other features.
This replacer 🠚 submods structure exists mostly because that's how most animation replacer mods tend to work - they contain multiple folders, each with different conditions and animations. Now they all their subfolders can be organized into one folder, making the structure cleaner. OpenAnimationReplacer
├── Replacer mod 1
│├── Submod A
││├── [animation files]
││└── config.json<- the submod configuration file
│├── Submod B
││├── [animation files]
││└── config.json
│└── config.json <- the replacer mod configuration file
└── Replacer mod 2
├── Submod C
│├── [animation files]
│└── config.json
└── config.json
Unlike DAR, the priority is not defined by the folder names. They can be named however you want! (although please avoid using non-english characters/symbols because they will probably not be read correctly - pull requests on GitHub from someone that knows what they're doing with Unicode strings and file paths are welcome, I give up).
You do not have to edit the .json files manually in a text editor. While it can be done, the in-game editor lets you do everything and is much easier and safer to use. It's easy to make an accidental mistake when editing configuration files manually.
As for backwards compatibility, every mod placed in the DynamicAnimationReplacer folder is also read and converted to the new structure when loaded into the game. Because they were missing the new features, these new features are all off by default, so they should behave exactly as before, aside from improvements like random condition results being re-rolled on animation loop or echo. There's no concept of a Replacer mod->Submod in DAR, so all DAR mods are treated as submods to one big replacer mod called Legacy in the editor. Their names are just their folder names. That's the best I could do based on the limited information.
You can even edit them ingame and save user configuration. However, I encourage replacer mod authors to provide OAR versions. If not for the new features, then at least for the neater organization.
Please remember that you can't physically add new or remove animation files from a mod, or add/remove mods themselves while the game is running, it will only take effect after you restart. You can however disable animations or submods inside the editor.
Since 1.2.0 a replacement animation can have multiple variants. It's a much more comfortable way of making random animations. Previously, multiple random variants were done by creating multiple submods with the same condition sets, including a random condition. With variants, you only need to create one submod without any random conditions.
To add variants to an animation in a submod, create a subfolder where the animation would normally be placed. Name the subfolder "_variants_[animNameWithoutExtension]" (so, for "mt_idle.hkx", the folder should be named "_variants_mt_idle" and placed in the same location). Put all variants of that animation you want to randomize inside that folder. The filename does not matter. However, I suggest using something short (even 1.hkx, 2.hkx and so on) to avoid potential issues with long paths. (so, instead of "submodFolder/male/mt_idle.hkx", you have "submodFolder/male/_variants_mt_idle/1.hkx" etc.)
That's it. The animations will be picked up by the plugin and randomized when that replacement animation is supposed to play.
The variant randomization will respect the "Keep random results on loop/echo" and "Share random results" submod settings, just like a random condition would.
You can configure the weight used for the randomization for each variant in the in-game editor, inside the submod's replacement animations. For example: setting a weight of 2 on a variant will make it twice as likely to play as variants with a weight of 1.
To make it clear and easier to grasp: don't overthink what this does. It's just an optional step that will run after conditions are evaluated. The only difference is that instead of a single replacement animation being selected and played, one animation is selected from the possible variants.
In-game editor
The in-game UI, accessible by pressing Shift + O by default, lets you inspect and edit all your installed replacer mods.
The editor might look a bit intimidating at first, but I tried to make it pretty user friendly. There are many quality of life features like copy/pasting conditions by right clicking them, or the entire condition sets, and you can drag and drop conditions to reorder them.
You can select an actor in the console, or type their FormID in the editor, in the upper left corner. This will select it as the current evaluation target. When a target is selected, each condition will display an icon indicating whether its requirements are currently met. In certain cases, relevant conditions will also provide an additional field showing the current value that is being checked. This allows for easy identification of the current status and provides insight into any necessary changes.
The editor allows you to switch between three modes: Inspect, User, and Author.
- In Inspect mode, editing functionality is disabled, providing a read-only view.
- In Author mode, changes are saved directly to the config.json file. This file serves as the primary configuration file intended for distribution along with the replacer mod itself.
User
- and
Author
- modes, as their names suggest, are designed for mod users and mod authors, respectively. The main difference lies in the configuration file that is saved when clicking the save button.
- In User mode, a user.json file is created, which overrides everything from the config.json file except for the submod's name and description. This mode enables users to make personalized adjustments to replacer mods, such as changing priorities, modifying conditions, or disabling animations, without affecting the original files. The user config file can be safely deleted, and the original config.json will be used instead.
There is an additional tab that provides a list of all replacements for each animation, sorted by priority. This tab is designed for easy inspection and does not allow direct editing, because all replacer animations within one submod share the same configuration, and the relationship between different animations from the same submod is not clear in this view.
Don't forget about the settings menu. There are a few experimental features that aren't 100% fully known to be flawless, but in my experience work fine.
The editor will display a warning if multiple submods share the same priority, and display an error when a submod has a condition that requires another plugin, or a newer version. You can read detailed information by clicking the error bar at the bottom of the editor.