Log 19: My Ultimate Super Special Move!
- Bruce McCormack

- Aug 22, 2024
- 6 min read
The next thing I wanted to work on is what I'm calling the Linked Ability mechanic. In its most basic form when two or more characters are close to the player, and they have the Power for it, when the player activates an ability the computer controlled characters activate the same ability.
For example: If the player is standing near to another ranger and both have adequate Power, when the player activates their Ultimate, the other ranger will activate theirs as well. Ideally targeting the same area/individual as the player.
But, before I worked on the Linked Ability mechanic, I had to actually have the Ultimate attack to do it with. At first I tried making my own custom animation so that it could be as fancy as I wanted. But then I ran into the problem that while I enjoy animation, I'm a more talented programmer. The animation was taking too long for something that only had to be in place for mechanical testing and not final production. So this is as far as I got before I tried something else:

The next thing I tried was to create an animation montage from several animation clips that came in one of the animation packs I bought. After I got the inputs hooked up between the "Player Controller" (actually pressing the button) and the [Attack Controller] (the code to respond to the button press) I got it to play...with some issues:

The first issue is that when I let go of the trigger, the weapon disappears, which I don't want until the attack is done. I want the player to be able to release both the trigger and some tension with this attack. And second is during the final stage of the attack (when the character raises their hand) they snap back to their starting position from the position that the swing moved them into.
The positioning was easy enough, all I had to do was enable Root Motion on the animation sequence that moves the character forward. Easy-peasy.

When I went to work on the sword disappearing, I had thought to merely adapt how I solved the same problem with normal sword attacks. Only then did I realize that I never fixed the same issue with regular Empowered attacks, so I had more work to fix it than originally conceived.
The first thing I did was put a bool into "BP_Visible_Weapon" called "CanUnsummon", and if this bool is true then the weapon can disappear as normal. But if it is false an event is bound to a new dispatcher that is called during Tick (I'm not a huge fan of this, but there won't be many of these objects in the game and if it does cause problems down the line I'll shift it into a macro). This event also checks "CanUnsummon", calling the function to unsummon the weapon when it is true and unbinding the event from the dispatcher. Next I created a function that will set the value of "CanUnsummon" which I bound to a new dispatcher in the [Attack Controller] that gets called when certain animation events get called. My first attempt at testing this yielded....interesting results.

The particles kept being restarted because I actually forgot to unbind from the dispatcher at first. But I got it working after I fixed that.

The fun part is that I stumbled onto a couple of bugs. Two graphical and one major that I will have to fix once I'm done here:
Two are graphical bugs with the weapon trail that in the first it just stays on and follows where the sword should be. The second (last pic) it just stays in space independent of the character and weapon. These should (hopefully) be relatively easy. The fun one that I can already tell is going to give me a headache is the one where summoning the mount causes the character to go flying off into space, and (not pictured here) gives an error in the console where I'm trying to access the "Player Controller".
The bugs needed to wait, though; I was still working on the Ultimate.
The Ultimate Attack being a multi-hit attack highlights something I was wrestling with before with the regular attack combos. I want all the hits before the final one to drag the hit enemies together and, in the case that the attack animation moves the character, drag the enemies with them. This way it is easier to rack up large hit numbers and overall make the gameplay more manageable for the player.
After researching the various physics components in Unreal, I decided to try using the [Physics Constraint] component to try and pull the enemy characters into place. I started by adding two new components to the basic character template: a blank sphere to act as an anchor point and the [Physics Constraint] component itself. Because I want one character to be able to pull multiple others they all need to have their own constraint component so I'm not constantly spawning in dozens of them. Because I'm already doing my hit tracing in the [Attack Controller] I needed a new dispatcher to send out the hit character to the [Controller] owner. Once the owner knows about it, it calls a new interface function and passes its own anchor and adds the character to an array for later. The interface function activates the physics simulation on the hit character's root as well as linking the passed anchor and root in the [Physics Constraint].

Turns out the camera bug was because several of the components were set to block camera collision, so once I set them to ignore it instead the bug went away.
Next I made a dispatcher in the [Attack Controller] that fires when it receives the "Combo Ended" animNotify, this causes the [Physics Constraint]s to break from each other and if there is sufficient knockback force causes the enemies to get launched away.
Because of the fact that the Ultimate attack is a multi-hit attack, and contains hitboxes with different properties, I wound up having to do some light re-doing on how creating hit detection works. Originally the shape and size of hit detection was all part of an ever-growing "Attack" struct. Now the struct only contains the animation montage for the attack and the Power cost of the attack. Instead I created a new "Detect Hit" struct that contains the relevant info for hit detection. I then create and store this struct data in an AnimNotify kept on the montage itself and is then passed to the character and [Attack Controller] through an interface message. Other than that, hit detection and damage calculation and application are all the same.
I also made an "FX Info" struct for use with a new AnimNotify that spawns a Niagara object based on an animation. This will allow me to have various VFX go off for the Ultimate attack, like an explosion at the end, because who doesn't love a good explosion?
While working on the VFX for the Ultimate move, I noticed that it was using the wrong trail for the sword.

Looking into it, despite putting the animation/unsummoning on hold that only applies to the actual weapon object. It is still considered "unsummoned" by the character blueprint. Thus, when the AnimState calls for the "Right Hand" trail object the character blueprint returns the one for the fist. So I put in a couple of dispatchers into the weapon blueprint that fire off when the animations finish one way or the other. The character blueprint subscribes the summon and unsummon function to those dispatcher so it can take care of what it needs to when the animations finish.
After cannibalizing a couple of other Niagara systems (re-using and modifying the explosion from the morph, and stripping some pieces out of another purchased Niagara) I have a workable Ultimate:

Post script:
While editing this I realized that the character is supposed to be invulnerable during their Ultimate attack, and I had forgotten to make it so. I quickly added a boolean called "Invulnerable" to the [Health Component] on the Basic Character. This bool gets toggled on when the attack starts (and when dodging) and toggled off when done. As long as the bool is true, the [Health Component] won't accept the damage.








Comments