reznok/gmcabilitysystem/gmas-ability

Claude Code and agent skill by reznok/gmcabilitysystem

Trust tier 3
  • community
  • ext:[{"type":"hook","description":"Pre/post lifecycle hooks"}]
Source check pending

Checking that the SKILL.md file is still in the repository.

Use when creating or modifying a UGMCAbility - lifecycle hooks, cost and cooldown, activation tags, chains, tasks, input, and its visuals and sounds on every machine.

Install

npx vskill@latest install reznok/gmcabilitysystem/gmas-ability

Semi-extensibleMentions customization, but needs skill-specific knowledge. Read the extensible skills standard

SKILL.md

Behavior below was verified against GMC 2.3.x and GMAS 1.4. Confirm signatures in this project's own headers (paths are relative to each plugin's root, e.g. Source/GMCCore/Public/Components/GMCReplicationComponent.h); GMC's source is not part of this plugin.

A UGMCAbility (Public/Ability/GMCAbility.h) is a UObject the UGMC_AbilitySystemComponent ("the ASC") instantiates per activation and ticks from inside the pawn's GMC move: on the owning client (predicted, replayed) and on the server (re-executed). It owns no replicated state; what it changes lives in bound attributes and tags (gmas:gmas-rules), through effects (gmas:gmas-effect). The first ability and the movement-component wiring are in gmas:gmas-setup; GMC's move cycle in gmas:gmc-prediction; task authoring in gmas:gmas-task. Six worked abilities: references/recipes.md; the cosmetics API: references/cosmetics.md. GMAS paths below are relative to Source/GMCAbilitySystem/.

Anatomy

Identity and cost:

PropertyDefaultMeaning
AbilityTagnoneAbility.*; the key for cooldowns, EndAbilitiesByTag / CancelAbilitiesByTag (1.4.1+), the cancel/block containers and OnAbilityActivated. Not the activation tag: abilities are activated by the Input.* key of the ability map
AbilityCostnonean effect class (normally Instant, one modifier per attribute); checked at activation (1.4.1+, below), applied by CommitAbilityCost. The attributes it reads and spends should be GMC-bound: the gate runs on both sides, and an unbound cost attribute logs one Warning per ability class
CooldownTime0seconds; 0 = none. Needs AbilityTag. Stored on the ASC as an absolute expiry in ActionTimer units (ActiveCooldowns, not bound)
bApplyCooldownAtAbilityBegintruecommit the cooldown in BeginAbility, before your event; false = you call CommitAbilityCooldown()
bAllowMultipleInstancesfalsefalse: a second activation while an instance is alive is refused (silently at default verbosity; [AbilityGate] warning once the blocker is older than 2 s)
AbilityDefinitionemptydescriptive tags matched by the *Query fields of other abilities and of effects (EndAbilityOnActivationQuery)
GetAbilityCostValues() (1.4+)–attribute tag → the cost's change, for UI. 1.4.1+: summed per attribute; on an instance with an owner the projected change (attribute-sourced values and Conditions resolved, a Set as target − current); on a class default object the raw AMT_Value amounts summed (other sources count 0). 1.4.0: only AMT_Value resolved and the last modifier per attribute won

Activation gates, evaluated on the class default object before an instance exists:

GateWhereFails how
bAllowMultipleInstancesTryActivateAbilityreturns false: the next candidate on the input tag is tried
ActivationRequiredTags, ActivationBlockedTagsCheckActivationTags, with HasActiveTag (the union of bound and client-auth tags, 1.4+)returns false: next candidate
ActivationQuerysame, against the bound ActiveTags onlyreturns false: next candidate
cooldown (IsOnCooldown()), cost (CanAffordAbilityCost(), 1.4.1+), PreExecuteCheckEvent(), BlockedByOtherAbility, IsAbilityTagBlockedPreBeginAbility, on the instancethe activation is refused: the press is consumed, no other candidate runs, the instance is Ended and purged next tick. A refused instance never began: no CancelAbilityEvent, no OnAbilityCancelled, no ApplyEffectOnEnd / RemoveEffectOnEnd (1.4.1+)

Blocking and cancelling (all hierarchical on the other ability's AbilityTag):

PropertyEffect
BlockedByOtherAbilitythis ability is refused while any active ability's tag matches
BlockOtherAbilitywhile this ability is active, candidates whose tag matches are refused (IsAbilityTagBlocked); ModifyBlockOtherAbility(Add, Remove), ResetBlockOtherAbility() edit it live
bBlockAllOtherAbilities + BlockAllAllowedTags (1.4+)while active, every candidate is refused unless its tag matches the allow-list; SetBlockAllOtherAbilities(bool) toggles it (open the gate for a recovery phase)
CancelAbilitiesWithTagat BeginAbility, active abilities with matching tags are cancelled (CancelAbilitiesByTag, 1.4.1+: no end event, no chain window). On 1.4.0 they got EndAbility(), a natural end
EndOtherAbilitiesQuery, BlockOtherAbilitiesQueryat BeginAbility, active abilities whose AbilityDefinition matches are flagged and cancelled on their next prediction tick (1.4.1+; EndAbility() on 1.4.0). The second query blocks nothing despite its name; its editor name is End Other Abilities On Begin (Definition Query) (1.4.1+)

Chains and end hooks (1.4+, category Chain):

PropertyEffect
ChainWindowTag, ChainWindowDuration (0)on a natural EndAbility (never on CancelAbility) the ASC applies an internal Persistent effect, EffectTag = GrantedTags = the window tag, Duration = the window, bUniqueByEffectTag; the next stage lists the tag in ActivationRequiredTags
ChainConsumeWindowTagsremoved (RemoveEffectByTagSafe, all instances) in BeginAbility after every gate passed: a refused press leaves the window open
ApplyEffectOnEnd, RemoveEffectOnEndat any end of an ability that began, cancel included (1.4.1+: not for a refused activation): ApplyAbilityEffectShort per class, RemoveEffectByTagSafe(Tag, -1) per tag; Predicted inside a GMC tick or standalone, otherwise PredictedQueued

Ticking and network:

Property / accessorDefaultMeaning
bActivateOnMovementTicktrue (1.4+; false before)which tick activates the ability and dispatches its task payloads: the prediction tick (replayed) or the ancillary tick (never replayed, for what must happen once: firing a weapon). Every active ability still gets Tick in the prediction tick and AncillaryTick in the ancillary tick. The first granted candidate on an input tag decides for the batch; mixing values on one tag is an Error
ServerConfirmTimeout (protected, class defaults)2 s (1.4+; 1 s before)a client instance the server has not confirmed (RPCConfirmAbilityActivation) within this much ActionTimer is cancelled (1.4.1+; ended on 1.4.0) with an [AbilityCut] error
AbilityInputActionthe action passed to QueueAbilityread by the input tasks
AbilityState (EAbilityState)PreExecution → Initialized → EndedRunning and Waiting are never set (hidden in the editor, 1.4.1+); IsActive(), AbilityEnded()
OwnerAbilityComponent, GetOwnerMovementComponent()set by Executethe ASC and its UGMC_MovementUtilityCmp: every bound value the ability reads or writes lives on the latter
GetOwnerPawn(), GetOwningPlayerController()–the AGMC_Pawn; its AGMC_PlayerController, null for AI and on machines that do not control the pawn
GetOwnerAttributeValueByTag(Tag)–the attribute's Value (modifiers included) on the owner
GetAbilityID(), IsServerConfirmed() (1.4+), GetClientStartTime() (1.4+; double on 1.4.1+)–the activation id (operation-derived on 1.4+, identical on both sides), whether the server confirmed it, the ActionTimer at activation; diagnostics

Lifecycle

  1. Activation (TryActivateAbility, ASC): instance gate, tag gates, NewObject from the class, Execute(ASC, AbilityID, InputAction) sets the owner, AbilityInputAction, ClientStartTime = ActionTimer and calls PreBeginAbility(). The instance is added to ActiveAbilities even when it already ended; the server confirms the client only when it did not.
  2. `PreBeginAbility()`: cooldown → cost (CanAffordAbilityCost(), 1.4.1+) → PreExecuteCheckEvent() → BlockedByOtherAbility → IsAbilityTagBlocked. Each refusal logs at Verbose (Ability Activation for Ability.Dash Stopped By Cooldown / Stopped By Cost / ...) and refuses the activation (the press is consumed). Then (1.4.1+) AbilityState = Initialized, the OnAbilityActivated broadcast (the listener sees IsActive() true; a listener that calls CancelAbility() on it refuses the activation there: no cooldown, no BeginAbilityEvent, the cancel hooks fire), then BeginAbility(). On 1.4.0 cost was not checked and OnAbilityActivated fired from BeginAbility before Initialized. Keep PreExecuteCheckEvent cheap and pure: it runs on both sides inside the move.
  3. `BeginAbility()`: BlockOtherAbilitiesQuery, chain consume, cooldown commit (bApplyCooldownAtAbilityBegin), CancelConflictingAbilities(), then `BeginAbilityEvent()`: your code. Override the events, not PreBeginAbility / BeginAbility / EndAbility, so the bookkeeping stays. An override of BeginAbility whose work after Super creates tasks, declares effects or commits a cost must stop when the ability ended inside Super: Super::BeginAbility(); if (AbilityState == EAbilityState::Ended) { return; }.
  4. `Tick(DeltaTime)` (prediction tick, after the ASC processed the move's operation and before effects tick and attributes recalculate): confirm timeout (client), pending cancel or end, TickTasks, then `TickEvent`. `AncillaryTick` (ancillary tick, after cooldown expiry and task-payload dispatch): AncillaryTickTasks, then `AncillaryTickEvent`. Predicted movement goes in TickEvent; once-only work in AncillaryTickEvent or behind the live-move guard below.
  5. `EndAbility()` is the natural end: chain window applied, FinishEndAbility(), `EndAbilityEvent()`, OnAbilityEnded. `CancelAbility()` is the abnormal end: FinishEndAbility(), then (1.4.1+) `CancelAbilityEvent()` (BlueprintNativeEvent) and the ASC's OnAbilityCancelled; no end event, no OnAbilityEnded, no chain window. Cleanup that must run on both paths (stop a loop, hide a cosmetic) implements both events. First end wins (1.4.1+): the two share one latch, so a CancelAbility() during a natural end, or an EndAbility() during a cancel, is ignored and exactly one hook set fires.
  6. `FinishEndAbility()` (both paths, once): [AbilityCut] warning if tasks are unfinished, every task ended (EndTaskGMAS), every declared effect removed (by id, or by cached EffectTag if a replay renumbered it, [EffectLeak]), ApplyEffectOnEnd / RemoveEffectOnEnd (only for an ability that began, 1.4.1+), AbilityState = Ended. The ASC purges ended instances at the end of its next prediction tick (CleanupStaleAbilities; the server also sends RPCClientEndAbility).
  7. Ending from outside (1.4.1+): every abnormal or external end cancels. CancelAbilitiesByTag(Tag) and CancelAbilitiesByQuery(Query) (pending cancel, next tick), CancelAbilitiesWithTag, EndOtherAbilitiesQuery, BlockOtherAbilitiesQuery, an effect's CancelAbilityOnActivation / CancelAbilityOnEnd and EndAbilityOn*Query, the client confirm timeout, the server's RPCClientEndAbility ([AbilityCut] warning) and the task heartbeat watchdog (server, 3 s without a client heartbeat) all call CancelAbility(). EndAbilitiesByTag(Tag), EndAbilitiesByClass(Class) and EndAbilitiesByQuery(Query) (pending end) keep the natural end for callers that mean it (a death handler ending a held ability). The By* calls return how many live instances they reached (already-ended, unpurged ones are skipped). On 1.4.0 every one of these paths was a natural end; an ability that must not open its window on interruption detected it itself and called CancelAbility().

Cost and cooldown calls:

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 95 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

7-day trend score
0

Not refreshed yet.

Extension points

  • hookPre/post lifecycle hooks

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/reznok/gmcabilitysystem/gmas-ability/badge)](https://verified-skill.com/skills/reznok/gmcabilitysystem/gmas-ability)

Something wrong with this skill or its page? Tell us.