Able Ability System Info and Support Thread

Able v3.55 submitted. Notes below:

I seem to have run into a problem. I made a new ability and put in a animation task. However, the ability goes on forever.

Probably can’t figure out what your animation length is for some reason. I’d check that animation clip.

It might just be me, but this happens for any animation I use. To fix this, I mess with the ability properties ability length and then set it back to the default.

Hmm, can’t say I’ve ever seen that happen locally, but I’ll look and see if something broke.

I had an issue with channeled conditions that required me to modify the Able code. Pretty sure I mentioned it before in the past. I’m not sure why the fix has yet to make an appearance in the main code. The problem is some conditions are only checkable on the client side, and not the server side, such as the input conditionals, and the logic for branch and channeled conditions doesn’t account for that entirely.

But since functions like UAblChannelingBase::GetConditionResult and the FAblAbilityInstance::CheckChannelConditions that calls it only operate on bools which can be inverted to true when it wasn’t able to properly check input.

In reality, there are 3 states that need to be accounted for by all the condition checking code, branch conditionals and channel conditionals. It needs to make a distinction between explicit success and failure and a condition that cannot be checked, so it really needs to be treated as a tri-state check against the activation logic. Where the logic breaks as-is is given the fact that the results can be inverted, such as “input not pressed”. GetConditionResult returns false in that situation when it can’t properly check, but because the caller lacks the context that the false is due to the inability to check, if the result is inverted, it gets turned into a success and you have the server making branch of channeling decisions based on information it doesn’t have. A tri-state would only invert the explicit states, and not the ignored state.

Here are select bits of how I fixed these issues, by changing these bools into a tri-state enumerator, and handling them accordingly.

Note how the input conditional returns an ignored state, distinct from the true/false success/failure it returned before. This represents a distinct state that won’t be mistaken for an explicit success/failure state

By handling these distinct states properly, you ensure that anything involving input conditionals, or any user added realm specific conditionals, can ONLY drive state changes from the appropriate realm(client/server)

Ah, that does ring a bell. Not sure why it got missed either. Thanks @JSwigart

Just a heads up, I’m in Austin and just got back to my place after 5 days without power / water. Power is back but still waiting on water. I’m safe and have supplies, but be patient as I get settled back in and try to get back into a normal flow. Hope everyone else is staying safe out there.

Hi .

First off great plugin and glad to hear you’re getting back to normal and safe.

Quick question, If I need my character to instantly rotate to where the camera is facing on ability cast, fully networked, what would be the best way to go about that?

I suggest adding a m_TargetRotation or something that can be set on the context before being sent to the server, then use that to set context owner’s rotation on all the clients. The TurnTo Task doesn’t work here because there isn’t a target, and the TurnTo Camera wouldn’t work in a networked environment if I’m not mistaken.

Thanks again for the great plugin

Sorry I’m just getting to this. Like I said, it’s been a crazy few weeks.

TurnTo should work in the network environment even if you use Camera (but I haven’t verified that). Effectively what you want is to turn towards the Camera, which modifies the Player Yaw, which gets replicated to the Server since Client movement is authoritative (to a point). I’d just try that - if it doesn’t work, you could also create a location just infront of your player, set that as the Target Location (which will get replicated up with the Ability call to the server), and you can just set your TurnTo Task Target to Location.

Able v3.56 has been submitted, notes below:

Able v3.57 has been submitted, notes below:

If you aren’t on our Discord, I’d definitely encourage you to swing by. Community is super helpful and you can directly suggest features / reports any issues (like this Initial Stacks concept). You can get a link by opening up the Ability Editor and using “Community -> Discord”.

Able v3.58 submitted, notes below:

As always, please let me know if you run into any issues!

I see the Able system is 50% off until today, and I’m considering purchasing the product, so I want to ask a quick question: does Able still have conflicts with ALSv4? (I’m using the C++ version, if that’s of any relevance.) I was reading through some pages of this thread, but then I realized there are 116 pages. I apologize if this question has already been asked and answered.

That issue is with ALS, not Able unfortunately. I know the fix amounts to basically a nullptr check within ALS’s tick method - but I’m unsure if the author of ALS is aware of the issue or has put in a fix.

Able v3.60 submitted, notes below:

Hey , how are you?

I can’t describe how impressed our team is with Able. I mean, it is everything we’ve asked for – thank you so much for putting your time into creating this great piece of software!

Anyways, I’ve been playing with Able this last weekend and compiled a list of questions that I wish you could respond.

  1. Is there any way to access Blueprint Function Libraries through an Ability’s Graph? It seems we don’t have the WorldContext in there, so I’m currently not able to access my so precious functions.
  2. How do I set default Tags at Actors that expose the AblAbilityComponent? Like, I have this Actor called AWall and I’d like it to start with the tag Wall. I believe the only way I found so far is by calling the AddTags at the BeginPlay event. Of course, I can always create a Tag system myself but well…
  3. Is there a way for me to prevent an Ability to be activated using Tags as filters, pretty similar to what GAS does? I don’t want Players with the Dead tag to activate abilities around.
  4. Oftentimes I don’t know the length of my ability. I mean, that’s way too obscure to me. I want this ability to consider itself done as soon as all the tasks are done. In this case, all I have to do is to mark Finish All Tasks, right? Sorry, I’m a little confused because it seems the Timeline still persists against the Length set at the AbilityProperties.
  5. Let’s say I want to create a Passive Ability called “RegenHP”. How do I add this Ability to all characters by default? I mean, should I really Activate the ability manually through BeginPlay or something, or is there any other, correct way?
  6. I have this Ability “Revive”. When a Character dies, we trigger an animation and hide the UI. Turns out the UI is client/local-only, but the animation must be run at every connected client in the server. How would you create this Ability? One Task for the UI, and one for the Animation? Would you mind elaborating your approach here?

Now, let me jump into a more complex “question”. Pretty much, sometimes I’m struggling to differentiate a Task from an Ability; that said, given the following scenario…

So, a few questions around this, especially regarding good practices.

  • Would you recommend creating an Ability “Die”, that does things, and Activate it when I see the Health reached 0? Or…
  • Would you recommend creating a Passive Ability that monitors the Character’s Health, and when it reaches 0, we activate this other Ability called “Die”? Or…
  • Would you recommend creating a Task “Kill”, that is called from a “Die” Ability that is activated when the Health reached 0? Or…
  • Something else?

I mean, I feel that I am always struggling when making decisions. I don’t know what kind of logic I should keep at my own scripts and what logic belongs to Able Abilities. Could you reference any documents that get deeper into the theoretical/conceptual nuances of your system? Or perhaps mentioning some broad Good Practices around the core concepts of Able?

So far I believe that’s all. Thank you so much for your time and I look forward to your answer!

Cheers,
Gui.

Hey Gui, posting your answers here for posterity.

  1. Some BP Libraries work fine (Oculus for example), others don’t. No idea why. There is obviously some bit that needs to be twiddled - but I haven’t found it yet.
  2. Using the Begin Play is currently the only way, I can likely expose that Tag container. So I’ll look at that for the next update - I can’t think of any reason why not off the top of my head.
  3. There is a “CanAbilityActivate” check that you can have look at Tags and have all your other Abilities inherit from that so that BP call gets hit.
  4. The timeline has to be set to some value so you can drag and drop things, but yes, you could just set it to 1 second and as long as you have “Must Finish All Tasks” - the Ability will take as long as the Task requires. There’s just no way for me to know what that time may be to show in the Editor.
  5. Yes, manually adding things in BeginPlay is the best way. I do that in my own projects. Just make a quick system that takes a list of Abilities to auto apply.
  6. You can put both Client / Server / Client And Server tasks in the same Ability. The server just won’t execute the Client only tasks, and vice-versa. So make a simple Custom Task that hides your UI if you’re the local player and toss the animation and stuff in there as well.
  • A death ability is what I do in my own projects. Basically just loops a dead animation, set some material parameters to fade the model out, and then, once the Ability is done playing, clean up the Actor. If you wanted corpses, you could just spawn in a corpse and do some pose copy - but it all begins with that Death ability.
  • No, Damage is an event. There is a OnDamaged Event on the Actor itself, so you know when the Actor’s health is changing and possibly goes to 0. No reason to constantly check.
  • Not sure what a Kill Task would do (unless maybe you mean mark the Actor as destroyed or something).

The basic questions I ask myself when deciding how to split logic is:

  • Is the logic something simple and holistic that I want to expose to designers? Then it’s probably good for a Task. Doing a collision query, playing an Animation, playing a Particle effect. All simple tools that make for great Tasks. Tasks are your wood, hammer, nails, screws, etc. They are simple things that do one thing only but are fairly useless by themselves.
  • Is the logic something I can see building from those pieces and may re-use? Then it’s probably good for an Ability. Abilities are your chairs, tables, etc - all made using using Tasks. Can you have a one-off Ability? Absolutely. If I want to have a background NPC play some animation to act as if he’s talking to another NPC and the other NPC just laughs - I can set that up with Able pretty easily (two abilities - same length, one plays the “talking animation” the other is timed to play the laugh when the talking ends and both Abilities are just auto applied when the game starts to their appropriate actors). That’s entirely fine. You don’t need to do a whole sequencer movie for something like that.

Able is pretty cheap in the grand scheme of things. The network bandwidth is super small, the CPU over head is relative to the number of Tasks you have running in an Ability so tiny Abilities don’t take much time. Odds are Physics, Rendering and Character Movement will be your high nails of performance or bandwidth long before Able is. So just do what is works and is easiest - you can always go back and refactor things as needed.

Thank you so much for such a thorough answer, .

I mean, I couldn’t be happier with what you wrote. Allow me to contextualize.

Before Able, we created our own AbilitySystem. We don’t have an Ability Editor as Able offers, but in terms of Developer Experience, it is awesome. Our pain points were in the semantics: replication, overall performance, etc etc. So we checked GAS out. Unfortunately, GAS is quite imperative and doesn’t easily integrate with the thing we created - and, for what it’s worth, if we had to migrate everything from our system to GAS, I’m talking about months of work (which is the reason we decided to avoid it).

Then we found Able. And it seemed to us that, by design, it’s smaller than GAS and less opinionated. Since it was on sale last week, we decided to give it a go. And after some exploration this weekend, as I mentioned, I stumbled upon all the questions I wrote above.

Now, after reading your answer, I must say that this is the perfect world. Able is almost non-opinionated, giving us the flexibility to use it in pair with the system we created, without having the fatigue of migrating all the things to a brand new system.

I believe the only thing left now is for me to debug further how I can expose BP Function Libraries to Able consistently, b/c I personally adore stateless functions - it’s just a time saver when you gotta refactor something. Oh, and by the way, perhaps 4.27 might be our solution. Check this out. Fingers crossed!

Last but not least, thank you again. That was quick and on point!

Take care my friend,
Gui.

Able v3.61 submitted, notes below:

I bought the plug in today, was really excited to make the switch from GAS for an easier to use solution. I must add that I am trying to do multiplayer abilities and GAS worked fine for that except when It came to lag.

After setting up a simple ability from the tutorials page in the Documentation I tried to run the ability on a client and I keep getting the same crash error no matter if I do an authority check or locally controlled player. Haven’t tried server call because I was under the impression that this was networked out of the box. If thats not the case then I really regret spending the 100$… Heres the error log and the code I’m trying to run on my character

When running as the listen server My print strings work and no crash. Running on a client instantly crashes the editor.

(Greggory is on the Discord where we’re helping him).

For posterity, Able is networked outside of the box. There is no need to do anything fancy - this looks like just a bad Ability somehow getting passed into the Context.

EDIT: The crash was caused by a trying to use a latent call with a stale context it looks like.