===================================================================================================
Consistent Two-Handed Bash Timing
AUTHOR: Lord Zapharos (www.lordzapharos.com)
DATE: 29 May 2024
===================================================================================================


LICENSE AND CREDITS:
===================================================================================================
Creative Commons Attribution 4.0 International (https://creativecommons.org/licenses/by/4.0/)

You are free to share and transform this work (commercially or otherwise) provided you give proper
credit to Lord Zapharos, provide a link to this license, and indicate if changes were made.


DESCRIPTION:
===================================================================================================

In vanilla Skyrim, you can "counter" attacks (power or otherwise) by blocking with your weapon or
shield, then bashing right as the enemy attacks you. This underutilized mechanic briefly stumbles
your enemy and can prove a vital skill in any mod introducing harsher combat.

But if you enjoy using two-handed weapons, you may have noticed that countering with greatswords is
far easier than with battleaxes or warhammers. In fact, you may have found it almost impossible to
counter anything other than slow power attacks with the latter weapon types. The issue also applies
to any weapon using the battleaxe or warhammer animation set, such as Requiem's battlestaves.

Don't worry; the problem is NOT with your reflexes!

Two-handed weapons use two different sets of animation timings: one for greatswords (2HM), and the
other for all other types (2HW). When you counter an enemy's attack with a greatsword, you have an
extra 0.2 seconds to react. But with battleaxes and warhammers, you don't have those extra seconds.
Strangely, one-handed weapons don't have this issue, and all use identical animation timings.

This mod fixes the problem by adjusting both the animation speed and hitframe of all 2HM weapons to
match that of greatswords, *exactly*. The animations themselves are not changed; only their timing.

Both first-person and third-person timings are fixed (you can choose one or the other if you like).
This mod is NOT compatible with any other mod that changes two-handed bash animations. However, you
can still apply the fix yourself (see NOTES below).


REQUIREMENTS:
===================================================================================================

Skyrim Legendary Edition


INSTALLATION:
===================================================================================================

1. Copy the "Data" folder from this directory to your main Skyrim directory (this is usually found
   in "C:\Program Files (x86)\Steam\steamapps\Skyrim").
2. IF YOU ARE ASKED TO REPLACE ANY FILES, STOP and check the section NOTES below.

To uninstall, just remove the files added by this mod.

All first-person animation files are stored in the "_1stperson" folder; if you only want the fix
for one perspective, you can choose which files to copy or remove accordingly.


SKYRIM SPECIAL EDITION USERS:
===================================================================================================

This mod was designed in Skyrim Legendary Edition and WILL NOT WORK with Skyrim Special Edition. If
you decide to convert this mod to work in Skyrim Special Edition, I would be happy to bundle your
converted version with this mod and give you due credit -- just send me your conversion.


NOTES:
===================================================================================================

Some mods, such as FNIS, may overwrite the bashbehavior.hkx file in particular. This mod is not
compatible with any such mod by default, nor is it compatible with any mod that changes the default
bash animations. However, you can make the needed changes yourself (it's easy, if a bit tedious).
To do this, you will need a copy of ConvertUI (https://www.nexusmods.com/skyrim/mods/17109). You
may also need a BSA extraction tool (see below).

Start by taking the *.hkx files that conflict (i.e. those already in your data folder e.g. after
running FNIS or installing another animation mod). There are three files to consider; not all may
conflict:

    2hw_blockbashintro.hkx  - controls the delay before the 2HW weapon bash starts
    2hw_blockbash.hkx       - the actual bashing animation for 2HW weapon types
    bashbehavior.hkx        - controls all bash animations for all weapon types

You may also need a copy of 2hm_blockbashintro.hkx and 2hm_blockbash.hkx for comparison. If you do
not see these files in your data folder, you should extract them from Skyrim - Animations.bsa. Some
mods may pack custom animations in their own BSA file; in this case, you should extract the files
from your mod's BSA instead.

Use ConvertUI to extract all .hkx files to XML. All you need to do here is place the files in your
"infolder", select the "hkx to xml" tab, and click Convert. The files you need to edit will then be
in your "outfolder". You can open them with any text editor.

The changes you need to make are threefold.

First, in 2hm_blockbashintro.hkx (2HM weapons), there is a field like this:

    <hkparam name="duration">0.666667</hkparam>

The time shown above (0.666667) may be different for you. Whatever this value shows, copy it into
the same field in 2hw_blockbashintro.hkx (for me, this field's original value was set to 0.833333).
This will force 2HW weapons to use the same intro timings as 2HM weapons. Save the file.

Second, in 2hm_blockbash.hkx, you will see a very similar field e.g.

    <hkparam name="duration">0.500000</hkparam>

Copy this value (e.g. 0.500000) into 2hw_blockbash.hkx (for me, the latter file was originally set
to 0.633333). This will force 2HW weapons to use the same bash animation timings as 2HM weapons.
Save the file.

Now comes the tedious part! Open bashbehavior.hkx and search for the following:

    2HM_BlockBash.hkx

Above the found item, you will see an XML segment something like this (your values may not match
exactly):

    <hkobject name="#0161" class="hkbClipTriggerArray" signature="0x59c23a0f">
        <!-- memSizeAndFlags SERIALIZE_IGNORED -->
        <!-- referenceCount SERIALIZE_IGNORED -->
        <hkparam name="triggers" numelements="6">
            <hkobject>
                <hkparam name="localTime">0.000000</hkparam>
                <hkparam name="event">
                    <hkobject>
                        <hkparam name="id">10</hkparam>
                        <hkparam name="payload">null</hkparam>
                    </hkobject>
                </hkparam>
                <hkparam name="relativeToEndOfClip">false</hkparam>
                <hkparam name="acyclic">false</hkparam>
                <hkparam name="isAnnotation">false</hkparam>
            </hkobject>
            <hkobject>
                <hkparam name="localTime">0.000000</hkparam>
                <hkparam name="event">
                    <hkobject>
                        <hkparam name="id">1</hkparam>
                        <hkparam name="payload">null</hkparam>
                    </hkobject>
                </hkparam>
                <hkparam name="relativeToEndOfClip">true</hkparam>
                <hkparam name="acyclic">false</hkparam>
                <hkparam name="isAnnotation">false</hkparam>
            </hkobject>
            <hkobject>
                <hkparam name="localTime">0.033000</hkparam>
                <hkparam name="event">
                    <hkobject>
                        <hkparam name="id">3</hkparam>
                        <hkparam name="payload">null</hkparam>
                    </hkobject>
                </hkparam>
                <hkparam name="relativeToEndOfClip">false</hkparam>
                <hkparam name="acyclic">false</hkparam>
                <hkparam name="isAnnotation">false</hkparam>
            </hkobject>
            <hkobject>
                <hkparam name="localTime">0.099000</hkparam>
                <hkparam name="event">
                    <hkobject>
                        <hkparam name="id">4</hkparam>
                        <hkparam name="payload">null</hkparam>
                    </hkobject>
                </hkparam>
                <hkparam name="relativeToEndOfClip">false</hkparam>
                <hkparam name="acyclic">false</hkparam>
                <hkparam name="isAnnotation">false</hkparam>
            </hkobject>
            <hkobject>
                <hkparam name="localTime">0.133000</hkparam>
                <hkparam name="event">
                    <hkobject>
                        <hkparam name="id">8</hkparam>
                        <hkparam name="payload">null</hkparam>
                    </hkobject>
                </hkparam>
                <hkparam name="relativeToEndOfClip">false</hkparam>
                <hkparam name="acyclic">false</hkparam>
                <hkparam name="isAnnotation">false</hkparam>
            </hkobject>
            <hkobject>
                <hkparam name="localTime">0.500000</hkparam>
                <hkparam name="event">
                    <hkobject>
                        <hkparam name="id">9</hkparam>
                        <hkparam name="payload">null</hkparam>
                    </hkobject>
                </hkparam>
                <hkparam name="relativeToEndOfClip">false</hkparam>
                <hkparam name="acyclic">false</hkparam>
                <hkparam name="isAnnotation">false</hkparam>
            </hkobject>
        </hkparam>
    </hkobject>

The only thing you need to pay attention to here are two sets of fields:

    "localTime" - the time, in seconds, at which an animation event occurs
    "id"        - the animation event occurring at the localTime IMMEDIATELY ABOVE this field in
                  the file

Now search for 2HW_BlockBash.hkx. You will see a very similar segment above it, but its timings and
IDs will be a bit different:

    <hkobject name="#0159" class="hkbClipTriggerArray" signature="0x59c23a0f">
        <!-- memSizeAndFlags SERIALIZE_IGNORED -->
        <!-- referenceCount SERIALIZE_IGNORED -->
        <hkparam name="triggers" numelements="5">
            <hkobject>
                <hkparam name="localTime">0.000000</hkparam>
                <hkparam name="event">
                    <hkobject>
                        <hkparam name="id">1</hkparam>
                        <hkparam name="payload">null</hkparam>
                    </hkobject>
                </hkparam>
                <hkparam name="relativeToEndOfClip">true</hkparam>
                <hkparam name="acyclic">false</hkparam>
                <hkparam name="isAnnotation">false</hkparam>
            </hkobject>
            <hkobject>
                <hkparam name="localTime">0.099000</hkparam>
                <hkparam name="event">
                    <hkobject>
                        <hkparam name="id">10</hkparam>
                        <hkparam name="payload">null</hkparam>
                    </hkobject>
                </hkparam>
                <hkparam name="relativeToEndOfClip">false</hkparam>
                <hkparam name="acyclic">false</hkparam>
                <hkparam name="isAnnotation">false</hkparam>
            </hkobject>
            <hkobject>
                <hkparam name="localTime">0.198000</hkparam>
                <hkparam name="event">
                    <hkobject>
                        <hkparam name="id">4</hkparam>
                        <hkparam name="payload">null</hkparam>
                    </hkobject>
                </hkparam>
                <hkparam name="relativeToEndOfClip">false</hkparam>
                <hkparam name="acyclic">false</hkparam>
                <hkparam name="isAnnotation">false</hkparam>
            </hkobject>
            <hkobject>
                <hkparam name="localTime">0.233000</hkparam>
                <hkparam name="event">
                    <hkobject>
                        <hkparam name="id">8</hkparam>
                        <hkparam name="payload">null</hkparam>
                    </hkobject>
                </hkparam>
                <hkparam name="relativeToEndOfClip">false</hkparam>
                <hkparam name="acyclic">false</hkparam>
                <hkparam name="isAnnotation">false</hkparam>
            </hkobject>
            <hkobject>
                <hkparam name="localTime">0.633000</hkparam>
                <hkparam name="event">
                    <hkobject>
                        <hkparam name="id">9</hkparam>
                        <hkparam name="payload">null</hkparam>
                    </hkobject>
                </hkparam>
                <hkparam name="relativeToEndOfClip">false</hkparam>
                <hkparam name="acyclic">false</hkparam>
                <hkparam name="isAnnotation">false</hkparam>
            </hkobject>
        </hkparam>
    </hkobject>

Now, all you need to do is the following:

    1. For 2HW_BlockBash.hkx, set the localTime field ABOVE id 1 to 0.000000, replacing its
       original value.
    2. For 2HW_BlockBash.hkx, set the localTime field ABOVE id 10 to 0.000000, replacing its
       original value.
    3. Ignore the localTime field ABOVE id 3.
    4. Copy every other localTime field from 2HM_BlockBash to the same localTime in 2HW_BlockBash.
       For example, the localTime ABOVE ID 9 in the 2HM_BlockBash section (here, 0.500000) should
       be copied to the localTime ABOVE ID 9 in the 2HW_BlockBash section (here, 0.633000), thereby
       setting 2HW to use the same animation timing as 2HM.
    5. DO NOT mix up the localTime/id fields, or you will break the animation! Including steps 1/2,
       there are FIVE total values to be changed in this file.

When you are done, save the file. Delete the contents of your infolder, and move the files you just
saved from outfolder to infolder. Then, in ConvertUI select the "xml to hkx" tab and click Convert
(leave the "filename" section blank).

Your files are now patched; place them in the same location as you would the files from this mod.
If necessary, repeat these steps for first-/third-person.

Please note that if the incompatible files were caused by FNIS, you will need to restore them every
time you re-run FNIS, as the latter may regenerate bashbehavior.hkx. It is a good idea to store a
backup of your patched files, just in case.
