Logic problem hooking state machine to animation tree

I just finished building a basic state machine to drive the character’s physical behavior in-game. A lot of the character’s action verbs change depending on what he’s doing: hitting “dodge” while standing still executes a roll, “dodge” while moving does acrobatics, “dodge” while falling curls up into a ball to avoid damage, and so forth. I handle this complexity by create an enum to hold values for every possible player state, then running each input through two switch blocks using that enum, like this:


ECharacterState characterState = ECharacterState::Idle; //This variable will always reflect the player's current state

void GetAttackKeyInput(){ //All custom behavior for each key goes in a function like this
SetPlayerState(ECharacterState:Attack); //Try to place the character in the Attack state
switch (characterState){
	case ECharacterState::Locomotion: //If the player is still in the locomotion state...
                //Set the JumpKick bool to true for the animation tree
		break;
	case ECharacterState::Attacking: //If the player successfully switched to the attack state...
                //Set the bGroundKick bool to true for the animation tree
		break;
         default: //We don't have any other states we want you to attack from, so if you aren't moving or attacking...
         //Don't do anything!
                break;
}


}

bool AMBaseCharacter::SetPlayerState(ECharacterState desiredState){
	switch (desiredState){

	case ECharacterState::Locomotion:
		if (TryLocomotion()){
			characterState = ECharacterState::Locomotion;
			return true;
		}
		break;
	case ECharacterState::Attacking:
		if (TryAttack()){
			characterState = ECharacterState::Attacking;
			return true;
		}
		break;
//Logic continues for every possible verb
}

TryAttack(){
bool AMBaseCharacter::TryAttack()
{
	switch (characterState){
        case ECharacterState::Attack: //If the character is idle, moving, or already attacking, they can transition into the attack state
	case ECharacterState::Locomotion: 
	case ECharacterState::Idle:
                return true;
		break;

	default: //Otherwise, they cannot switch to the attack state
                return false;
		break;
	}

}


This almost does everything I need; it keeps the transition logic in one place where I can easily edit it, and maintains a persistent awareness of what the character is doing that can be queried from anywhere else in code. The one problem I’m running into is the logic behind turning this into animation: I can’t just have the animation tree check TryAttack() to see if it should launch into the attack montage, because I want different behavior for different combinations of states. The best solution I’ve come up with thus far is to create a bunch of protected bools, one for each transition, use those bools to cue up different animations, and modify my switch blocks to curate them.

This sounds like it’s veering into spaghetti code territory, though, because suddenly the switch blocks are doing double duty, and I’ve just introduced a boatload of uncomfortable edge cases where I need a bunch of bools to toggle on/off at specific intervals purely to make the animations line up. Is there a better way to handle cuing the animation tree, given that we already know exactly what behavior we want from each and every combination of inputs + player states?