Guide: Creating a New Skill
Relevant source files
The following files were used as context for generating this wiki page:- src/models/skill_refactoring/SkillSystem.js
- src/config/characterData.js
- src/models/skill_refactoring/SkillCore/Skill.js
- src/models/skill_refactoring/SkillCore/SkillValidator.js
- src/entities/enemies/systems/EnemySkillSystem.js
- src/models/skill_refactoring/SkillHandlers/ChannelingSkillHandler.js
- src/systems/Tutorial.js
This guide provides a comprehensive overview of how to create and configure new skills within the souless game engine. The skill system is designed to be data-driven, meaning most skill definitions and behaviors are controlled through a central configuration file, minimizing the need for new code for each skill.
The process primarily involves defining skill properties in characterData.js. The SkillSystem then interprets this data to handle skill execution, validation, animations, and effects. This document covers the architecture of the skill system and provides a step-by-step guide to adding a new skill.
System Architecture
The skill system is composed of several key classes that work together to manage skill logic. At its core, the SkillSystem orchestrates the entire process, from validating a skill's use to executing its effects.
The following diagram illustrates the main components and their relationships.
SkillSystem: The central class that manages all skills for a character. It initializes skills from configuration, handlesuseSkillrequests, and updates skill states.
Sources: src/models/skill_refactoring/SkillSystem.jsSkill: A class representing a single skill instance. It holds the skill's configuration and its dynamic state, such ascooldownRemainingandisActive.
Sources: src/models/skill_refactoring/SkillCore/Skill.jscharacterData.js: A configuration file containing all character-specific data, including the definitions for all their skills. This is the primary file you will edit.
Sources: src/config/characterData.jsSkillHandlerFactory: A factory responsible for providing the correct skill handler based on the skill'stype(e.g., 'melee', 'channeling'). TheSkillSystemuses this to delegate execution logic.
Sources: src/models/skill_refactoring/SkillSystem.js:40-46BaseSkillHandler/ChannelingSkillHandler: Concrete implementations of skill logic. Each handler is responsible for executing a specific type of skill. For example,ChannelingSkillHandlermanages skills that are held over time.
Sources: src/models/skill_refactoring/SkillHandlers/ChannelingSkillHandler.jsSkillValidator: A static utility class that performs comprehensive checks to determine if a skill can be used. This includes checking for level requirements, mana, character state (e.g., in-air), and resource levels.
Sources: src/models/skill_refactoring/SkillCore/SkillValidator.js
Step 1: Configure the Skill in characterData.js
The first and most important step is to define the skill's properties within the skills object for a character in src/config/characterData.js. Each key in the skills object (e.g., q_skill, attack) corresponds to a skill.
Key Configuration Properties
The behavior of a skill is determined by the properties you define in its configuration object.
| Property | Type | Description |
|---|---|---|
type | string | Determines the execution logic. Examples: instant, melee, movement, channeling. This maps to a SkillHandler. |
icon | string | Path to the skill's UI icon (e.g., assets/skills/monk/q_skill.png). |
animation | string | The key of the animation to play when the skill is used. This must match an animation key in the character's animations array. |
cooldown | number | The skill's cooldown time in milliseconds. |
cost | object | The resource cost to use the skill, e.g., { mana: 20 }. |
hitboxSequence | array | An array of objects defining multi-stage attacks. Each object can have a delay, hitbox definition, damage, and movement. See Advanced: Hitbox Sequences section. |
effects | array | An array of status effects to apply on hit, e.g., ['burn', 'stun']. For channeling skills, can include ['heal', 'mana_regen']. |
knockback | object | The force to apply to a target on hit, e.g., { x: 250, y: -150 }. |
hitstop | string | A preset key for a "hit stop" or "hit pause" effect to add weight to an impact. |
impactEffect | array | An array of visual effect keys to play on hit. |
channeling | object | Configuration for channeling skills, e.g., { type: 'hold', maxDuration: 3000 }. |
Sources: src/config/characterData.js, src/models/skill_refactoring/SkillCore/Skill.js, src/models/skill_refactoring/SkillSystem.js
Example: fireknight's W-Skill
This example shows the configuration for the fireknight's w_skill, which is a three-part combo attack.
// from src/config/characterData.js
w_skill: {
type: 'instant',
damage: 25,
icon: 'assets/skills/fireknight/w_skill.png',
hitboxSequence: [
{
delay: 100,
hitbox: {
width: 120,
height: 40,
offsetX: -30,
offsetY: 120,
effect: '',
duration: 200,
},
damage: 10,
},
{
delay: 300,
hitbox: { width: 40, height: 155, offsetX: 40, offsetY: 60, effect: '', duration: 200 },
damage: 10,
},
{
delay: 500,
hitbox: {
width: 150,
height: 130,
offsetX: 130,
offsetY: 60,
effect: '',
duration: 300,
},
damage: 15,
},
],
hitstop: 'FIREKNIGHT',
animation: 'w_skill',
knockback: { x: 200, y: -100 },
effects: ['stun'],
cooldown: 0, // Example value, likely higher in practice
cost: { mana: 0 }, // Example value
targetType: 'multi',
impactEffect: ['fire_knight_w_skill'], // 타격 시 이펙트
},
Sources: src/config/characterData.js:770-820
Step 2: Define Skill Animations
The animation property in the skill configuration must correspond to an animation defined in the same character's animations array in characterData.js. The SkillSystem will automatically play this animation when the skill is executed.
Example: fireknight's w_skill Animation
// from src/config/characterData.js
animations: [
// ... other animations
{ key: 'w_skill', frames: { start: 270, end: 279 }, frameRate: 12, repeat: 0 },
// ... other animations
],
This defines an animation with the key w_skill that plays frames 270 through 279 from the character's spritesheet at 12 FPS and does not loop (repeat: 0). The skill is considered complete when the animation finishes.
Sources: src/config/characterData.js:847, src/models/skill_refactoring/SkillSystem.js:101-115
Skill Execution Flow
When a player presses a skill key, a sequence of events is triggered, managed by the SkillSystem.
This sequence diagram shows the flow from input to damage application.
useSkill(skillName): The process starts when an input callsSkillSystem.useSkill().- Validation:
SkillSystemcallsSkillValidator.canUseSkill()to check everything from level locks and mana costs to whether the character is in the correct state (e.g., on the ground). - Activation: If valid, the
Skillinstance consumes resources (like mana) and is marked asisActive. The cooldown is not yet started. - Execution:
SkillSystemgets the appropriateSkillHandlerfrom the factory based on the skill'stypeand calls itsexecutemethod. - Effects: The handler plays the associated animation and activates the
SkillHitbox. - Completion: When the skill's animation finishes, it fires an
animationcompleteevent.SkillSystemlistens for this and calls theskill.complete()method, which finally starts the skill's cooldown.
Sources: src/models/skill_refactoring/SkillSystem.js:193-239, src/models/skill_refactoring/SkillCore/Skill.js:48-73, src/models/skill_refactoring/SkillCore/SkillValidator.js:84-104
Skill Types and Handlers
The type property in a skill's configuration is critical, as it dictates which handler will be used to execute the skill's logic. The EnemySkillSystem and characterData.js reveal several available types.
| Type | Handler Logic |
|---|---|
instant | A versatile type that executes immediately. Often used for skills with complex hitboxSequence definitions. |
melee | A standard close-range attack. Typically defines a single hitbox or a simple sequence. |
movement | A skill that moves the character, such as a dash. The configuration includes properties like distance and speed. |
channeling | A skill that is active as long as a key is held or for a set duration. It can apply effects over time, like healing (heal) or mana regeneration (mana_regen). |
projectile | Fires a projectile. The logic for creating the projectile is defined in the skill's configuration. (Seen in EnemySkillSystem). |
aoe | An Area of Effect skill. Typically involves activating a large hitbox or a visual effect at a target location. (Seen in EnemySkillSystem). |
buff | Applies a temporary buff to the character, such as increased speed. (Seen in EnemySkillSystem). |
Sources: src/config/characterData.js, src/entities/enemies/systems/EnemySkillSystem.js:311-325, src/models/skill_refactoring/SkillHandlers/ChannelingSkillHandler.js:6-16
Advanced: Hitbox Sequences
For skills that involve multiple hits, movements, or timed effects, the hitboxSequence property is used. It is an array where each element represents a step in the sequence.
This allows for creating complex combos, where different hitboxes are activated at different times with unique properties.
This diagram shows how the SkillSystem processes a hitboxSequence. For each step, it waits for the specified delay, then activates a hitbox with its own duration, damage, and optional movement.
Sources: src/config/characterData.js:772-811, src/entities/enemies/systems/EnemySkillSystem.js:360-370
Hitbox Sequence Step Properties
| Property | Type | Description |
|---|---|---|
delay | number | Time in milliseconds to wait before this step starts, relative to the beginning of the skill execution. |
hitbox | object | Defines the hitbox for this step (width, height, offsetX, offsetY, duration). |
damage | number | The damage dealt by this specific step's hitbox, overriding the skill's base damage. |
movement | object | An optional movement to apply to the character during this step, e.g., { distanceX: 100, duration: 200 }. |
effect | string | A visual effect key to play when this specific hitbox is activated. |
Sources: src/config/characterData.js:772-811
Conclusion
Creating a new skill in souless is a straightforward, data-driven process. By adding a new entry to a character's skills object in characterData.js and defining its properties, you can introduce complex behaviors without writing extensive new code. The system is flexible enough to support everything from simple melee attacks to multi-stage, movement-based combos by leveraging the hitboxSequence property. Remember to link a corresponding animation to ensure the skill executes and completes correctly.