The normal extension path is data first, then a small action/handler seam when new behavior is required. Avoid putting a custom skill directly into UI or network code.
Skill action contract
using GreenCloakGames.TileTickRPGCore.Animation;
namespace GreenCloakGames.TileTickRPGCore.Skills
{
public interface IPlayerSkillAction
{
bool IsComplete { get; }
InteractionAnimationClass InteractionAnimationClass { get; }
bool LoopsInteractionAnimation { get; }
bool CanStart();
void Start();
void Tick(long tick);
void Cancel();
}
}
A long-running skill action participates in the same tick/cancel/action lifecycle as built-in gathering/production. Use CanStart for prerequisites, Start for initial setup, Tick for deterministic attempts, and Cancel to cleanly stop.
Progression events
unitSkills.OnXpGained += (skill, oldXp, newXp) => { /* UI/presentation */ };
unitSkills.OnLevelGained += (skill, oldLevel, newLevel) => { /* level-up presentation */ };
unitSkills.OnAnySkillChanged += () => { /* generic refresh */ };
Tracked versus implemented skills
SkillType contains more progression identities than the package currently has complete gameplay loops for. Treat an enum entry as a stable stat identity, not proof that gathering/production behavior already exists. The audited complete non-combat actions are Woodcutting, Fishing, Firemaking, and Cooking.
Data-driven content pattern
| Need | Prefer |
|---|---|
| New item | New item ScriptableObject with a stable item ID. |
| New weapon | Weapon/equipment definition using the current equipment authoring path. |
| New spell | Spell data in the Magic Database plus reusable SpellEffect where needed. |
| New quest behavior | Quest requirement/action/reward definition or extension seam, not quest-specific code in UI. |
| New interaction | Stable InteractionActionId plus provider/handler. |
| New persistent feature | Save DTO + IPlayerSaveModule. |
| Repeated designer content | Add editor/database tooling and validation instead of hand-editing scattered assets. |
Identity rule
Do not serialize display names, object references, or array positions as network/save identity when a stable ID exists. IDs should remain immutable after content ships; migrations should translate old IDs when necessary.