Character "Abilities"

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • Character "Abilities"

      Main question: How is a character ability system handled in a game?


      Two setups I've thought of with examples:
      1) Player Character A activates ability 1 through input. Input system sends out some kind of "ActivatedAbilityOne" Event. StabAbilityComponent is tied to ability slot one and has registered to receive the event (alternatively the component could be tied directly to the slot instead of using events). It sends out a "StabAbility" event.

      GameLogic and AnimationSystem listen for this event. GameLogic finds possible actors in front of Player Character A and checks the event for how much damage is caused. AnimationSystem starts the StabAnimation.

      This seems feasible to me except that the GameLogic and AnimationSystem could be potentially listening to tons of specific "ability" events. Perhaps an AbilitySystem within the GameLogic to handle the events? It could then send the required info along (targets, how much damage, which animation, etc)


      2) The specific ability components do the heavy lifting. Each component finds it's own possible targets and passes along to a corresponding component the needed info. For example using same basic setup as above, StabAbilityComponent is activated. It finds possible targets (in this case an actor in front of the player) and gets their HealthComponent and uses the takeDamage method. The StabAbilityComponent also sends out an animation for the AnimationSystem to play.

      This way seems like it would reduce the number of events, but increase coupling between components.


      Is either of these ways even close to a "correct" or possible way?
    • This really depends on what you're trying to achieve, but I'd lean more towards system two. A game is best thought of in layers. At the lowest level, you completely generic things like utility classes. These are usable everywhere. As you move up, the upper-level systems are allowed to depend on the lower-level systems, but never the other way around.

      In your case, the animation system is a lower-level system that lives on the engine. All games will require this system. The StabAbilityComponent is a gameplay system that lives on a higher level, so allowing it to depend on the animation component is reasonable.

      Furthermore, you don't want the animation system listening for gameplay events. You want it to handle things like "play this animation" rather than "this ability is executing".

      What is it that you're trying to achieve? Are you trying to create a zelda-like game where you can stab someone with a sword? If so, you might want to try a more generic approach. The sword itself should just be an attachment which has collision detection. Anything that collides gets its effect run on it (in this case, damaging the target).

      -Rez
    • Hey Trinak,

      I'd also go with method 2. Include an input state in your update loop, and then inside of your abilities component (or whatever will do the logic of "you used an ability") check the input state and see if it matches whatever your trigger condition is (like "this button is pressed this frame, but wasn't pressed last frame, and cooldown between ability uses is 0"). That's more or less how it works on the game I'm on now. The input system we're using actually builds an input mapping layer on top of the input state, so you can check "Is Fire pressed?" or "Is Right Trigger pressed?", depending on if you want conceptual buttons or actual buttons, all specified by the same enum, consumed by the same methods. You might consider doing something similar if you want data driven input mapping.

      Hope some of that is useful,
      James
    • Hey,

      the input stuff doesn't sound like a good way to go to me and I think it's contrary to gcc architecture amd its separation of concerns, unless I am mistaken.

      But with that aside I would go method 2 as well. I thought of it like this, yes there is coupling, but aren't those components conceptually coupled anyway? I mean the stabby component's aim is to take health away. On the other hand if your health component knows about the stabby one then you've got an issue.

      Cheers.
    • What are your specific concerns?

      Input mapping is very common. The idea is to build a map of hardware keys to game events and save that map in a data file. This allows you to easily let the user remap their keys.

      When the user presses a key, you send an event with the specific data for that key. Various systems catch those events and handle them appropriately. In my engine, I have two types of events: C++ events and Lua function events. C++ events use my event system as you'd expect. Lua events simply call a Lua function.

      One thing that makes this type of system really powerful is that the input system is completely decoupled from the game. Nothing stops me from calling those Lua functions directly or sending those C++ events in circumstances other than an input message. The receiver doesn't care if it's coming from the keyboard or some other trigger, it just responds.

      -Rez
    • Hmm, I'm not sure what's going on, but my main page for this site doesn't show any "new" threads like it usually does. In fact, when I look at the link for this thread it shows 0 replies. I also didn't receive an email for when replies occur (hence why I haven't responded). I'm also getting the mySQL error Quin is getting (at least I assume it's the same) when I respond to posts. Is this something on my end or sites?

      Anyways, back on topic. Essentially the game uses simple shapes for characters (as I'm not much of an artist) which don't really require animation, just moving the shapes. I got stuck when I tried thinking of how to add the abilities to the shapes that animate. The Zelda-like game would probably be accurate. I think I am stuck with the divide between abilities and animations, and their communication with other systems.

      At first I thought of creating a StabComponent for the ability, but then I couldn't think of a way to add in the animation in a way that made sense. StabComponent composed of an AnimationComponent didn't seem right. I suppose the StabComponent could register with an animation system it's animation and owner's ID to get the position, etc for the animation and then just tell the animation system to play it (just thought of this now, not sure how I like it yet).

      My next thought was having the StabComponent be an actor instead with its own AnimationComponent, Physics, etc, but attaching actors to actors appears worse than components to components.
    • Hey Trinak,

      I was advocating something slightly different. Rez brings up a good point about being able to just fire (and fake) input events with doing an event based system. What I was describing was including the state with your update calls. This does couple everything that is on the update loop to whatever interface governs the input state. The actual implementation that grabs input can still exist somewhere else and wouldn't be coupled. Basically along with passing in a delta time, you'd also pass in the current input state, in read only form. So your main loop would essentially be:

      Source Code

      1. while(running)
      2. {
      3. InputState input;
      4. InputSytem::getInputState(input);
      5. foreach(updateable in updateList)
      6. updateable.update(deltaTime, input);
      7. }


      Of course that's very basic and doesn't account for multiple controllers and such, or any sort of input filtering. As per Rez's example, you could have multiple input sources for one player for debugging/scripting purposes, so that getInputState call could be reading the controller, and a Lua virtual controller, etc.

      Anywho, just a suggestion. It is a bit more coupled than the rest of GCC, so feel free to disregard :)

      James

      The post was edited 1 time, last by rickvanprim ().