SKILL.md
Adding Abilities to Pokestar
Quick Reference
Files to modify:
src/enums/battleEnums.js- AddabilityIdEnum.YOUR_ABILITYentry (ONLY if not exists)src/battle/data/abilities.js- Add the ability implementation
DO NOT modify other abilities or battleConfig.js unless explicitly asked.
Ability Structure
[abilityIdEnum.ABILITY_NAME]: new Ability({
id: abilityIdEnum.ABILITY_NAME,
name: "Ability Name",
description: "Description of what the ability does",
abilityAdd({ battle, target }) {
// Called when ability is applied (battle start)
return {
// Properties to store for later use in abilityRemove
listenerId: this.registerListenerFunction({...}),
};
},
abilityRemove({ battle, target, properties }) {
// Called when ability is removed
battle.unregisterListener(properties.listenerId);
},
}),
Properties Pattern
Return state from abilityAdd that you'll need in abilityRemove:
abilityAdd({ battle, target }) {
return {
listenerId: this.registerListenerFunction({...}),
originalValue: target.getStat("atk"),
triggered: false,
};
},
abilityRemove({ battle, target, properties }) {
battle.unregisterListener(properties.listenerId);
}
Event Listener Registration
Abilities have a class-level registerListenerFunction method that automatically includes the ability instance:
abilityAdd({ battle, target }) {
return {
listenerId: this.registerListenerFunction({
battle,
target,
eventName: battleEventEnum.AFTER_DAMAGE_DEALT,
callback: ({ damage, abilityInstance }) => {
// abilityInstance.data contains the properties
// Perform ability logic
},
conditionCallback: getIsSourcePokemonCallback(target),
}),
};
},
Common Patterns
Refer to references/pattern-* for common ability implementations.
Common Gotchas
- Always Clean Up Listeners: Failing to unregister listeners causes memory leaks.
- Event Argument Modification: Return modified values from callbacks:
``javascript callback: (args) => { return { damage: Math.floor(args.damage * 0.5) }; }; ``
- abilityInstance: Access stored properties via
abilityInstance.datain callbacks.
- Source vs Target: Use the right condition callback:
- getIsSourcePokemonCallback - when this Pokemon is dealing damage/using moves - getIsTargetPokemonCallback - when this Pokemon is receiving damage/effects
Validation
After implementing an ability, run the ability test suite to validate the implementation:
npm test -- src/battle/data/__tests__/abilities.test.js
This runs an e2e test that verifies all abilities can be applied and removed without throwing errors. If your new ability causes a test failure, fix the implementation and re-run until tests pass.
See the unit-test skill for more details on testing.
References
add-event-listenerskill - Common event types and condition callbacksreferences/pattern-*- Common ability implementation patterns