Hello! In our last lesson, we built the reward system, ensuring that victory in battle leads to meaningful character progression through experience points and loot. This completed the foundational combat loop: engage, fight, win/lose, and get rewarded.
Now, we'll begin adding the strategic depth that defines the JRPG genre. This lesson fulfills the learning outcome: Design a data structure for skills and magic, including cost, target type, power, and effects. We'll move beyond simple "Attack" and "Defend" commands by architecting the data that will power every spell, special move, and technique in your game. True to your preference, we'll focus on the architectural design first, establishing a robust and flexible data model before we write the code to interpret it.
1. The Anatomy of a Skill
At its core, a skill is a collection of data that tells the game engine what to do when a character uses it. Instead of hard-coding every skill, we'll design a generic structure. This data-driven approach means creating new skills becomes a matter of adding a new data entry, not writing new code—a principle you're very familiar with from modern front-end development.
Every skill needs a few basic properties for identification and display:
id: A unique machine-readable identifier (e.g.,fire_spell_1).name: A human-readable name for the UI (e.g., "Fire").description: Text explaining the skill's effect for menus and tooltips.iconId: An identifier to show a specific icon in the UI.
To see how these fundamental properties and more advanced ones are handled in a professional game-making tool, let's look at RPG Maker.
RPG Maker MZ The Basics How to make Custom Skills
The video 'RPG Maker MZ The Basics How to make Custom Skills' by Driftwood Gaming provides an excellent tour of a skill database. It's a perfect real-world example of the data structure we are about to design.
Please watch these two short segments: Creating a Custom Warrior Skill (01:00 - 03:16): Pay attention to the fields being filled out: Name, Icon, Description, Damage Type, Element, and the Formula. Skill Cost, Type, Scope, and Occasion (03:16 - 05:05): Notice how cost (TP), skill type (a category), scope (the target), and occasion (when it can be used) are defined. These are essential parts of our data model.
2. Structuring the Core Attributes
Based on the video and our requirements, we can start building a JSON object to represent a skill. We'll group related properties into objects for clarity.
Cost, Scope, and Context
First, let's define how a skill is used.
- Cost: What resource does the skill consume? This could be MP, TP (Technique Points), or even HP. Our structure should be flexible enough to handle any of these.
- Scope (Target Type): Who can the skill be used on? This is a critical field for your game's logic. Common scopes include:
- One Enemy / All Enemies
- One Ally / All Allies
- The User (Self)
- One Dead Ally (for revival skills)
- Occasion: Where can the skill be used? Some skills are for battle only, some are for the world map/menu, and some can be used anywhere.
Here's how we can represent this in our data structure:
{
"id": "fire_spell_1",
"name": "Fire",
"description": "Deals minor Fire damage to one enemy.",
"iconId": "icon_fire_1",
"skillType": "black_magic", // For categorization (e.g., Black Magic, White Magic, Tech)
"cost": {
"type": "mp", // 'mp', 'tp', or 'hp'
"value": 5
},
"scope": "one_enemy", // e.g., 'all_enemies', 'one_ally', 'self'
"occasion": "battle_only" // 'menu_only', 'always'
}
3. Defining Power and Damage
A skill's power isn't just a single number; it's part of a system that interacts with character stats. As you saw in the RPG Maker video, a damage formula often looks something like a.atk * 4 - b.def * 2, where a is the attacker and b is the target.
Instead of storing the formula as a string which would require a complex parser, we can define the core components of the skill's damage and let our game engine use a standardized function to calculate the final number. This connects to the concept of derived stats—the final damage is derived from the skill's base power and the stats of the combatants involved.
We can add a damage object to our skill structure:
{
// ... other properties
"damage": {
"type": "hp", // 'hp', 'mp', 'hp_drain', 'mp_drain'
"element": "fire", // 'physical', 'fire', 'ice', 'holy', etc.
"basePower": 50 // A base value used in the damage calculation
}
}
When this skill is used, our battle system would:
- Identify the damage
typeishpand theelementisfire. - Grab the caster's relevant stat (e.g.,
magicAttack). - Grab the target's relevant defense (e.g.,
magicDefenseand fire resistance). - Plug these values, along with the skill's
basePower, into a damage formula. For example:
damage = (skill.basePower + caster.magicAttack) - target.magicDefense
This approach keeps the data clean and centralizes the complex calculation logic within the engine.
4. The Heart of Strategy: Skill Effects
Many skills do more than just deal damage. They can heal, apply status ailments, or grant buffs. This is where the effects property comes in. It should be an array, allowing a single skill to have multiple effects.
To understand the kinds of effects we need to model, and how they work under the hood, it helps to revisit the concept of stat modifiers. A "buff" that raises attack is simply a temporary modifier applied to a character's stats.
The article 'How to Make an RPG: Stats' provides an excellent implementation guide for stat modifiers. While you may have seen it before, the 'Modifiers' section is directly applicable to how we'll structure our skill effects.
Please read the section titled 'Modifiers'. Focus on how it translates concepts like "magic sword" or "curse" into data using add and mult properties. The provided code for AddModifier and Get shows exactly how these data-driven effects can be stacked and calculated. This is the system our skill's effects will interact with.
Drawing from that article and the RPG Maker video, we can see that effects fall into several categories. Our effects array will contain objects, each with a type and associated parameters.
Here are some common effect types:
recover_hp_percent: Heals a percentage of the target's max HP.recover_mp_flat: Restores a flat amount of MP.add_status: Applies a status effect like 'Poison', 'Sleep', or 'Paralysis'. We must include achanceproperty.remove_status: Removes a status effect.apply_modifier: Applies a temporary buff or debuff, using theadd/multstructure from the article. Requires aduration.
Here is how we could structure an effects array for a skill that has a chance to poison the target:
{
// ... other properties
"effects": [
{
"type": "add_status",
"statusId": "poison",
"chance": 0.3 // 30% chance to apply
}
]
}
A self-buff skill like "Focus" might look like this:
{
// ... id, name, cost, etc.
"scope": "self",
"effects": [
{
"type": "apply_modifier",
"modifierId": "focus_buff", // Links to a modifier definition
"duration": 5 // Lasts for 5 turns
}
]
}
And the focus_buff modifier itself would be defined elsewhere in our database, just as the article suggested:focus_buff = { mult: { ["magicAttack"]: 0.25 } } // +25% Magic Attack
This component-based design is incredibly powerful. For a more complex example, consider the Reddit post you reviewed earlier, which described a "Turn Undead" spell. In our system, this could be a skill that targets enemies with the 'Undead' tag, and has two effects: one add_status effect with statusId: 'death' and a high chance, and a secondary damage effect that only triggers if the first one fails.
Test your understanding!
Using the data structure we've designed, how would you model a basic "Cure" spell?
Properties: Costs 4 MP, can be used anytime, restores 30% of an ally's max HP.
Show answer
{
"id": "cure_spell_1",
"name": "Cure",
"description": "Restores a small amount of HP to one ally.",
"iconId": "icon_heal_1",
"skillType": "white_magic",
"cost": {
"type": "mp",
"value": 4
},
"scope": "one_ally",
"occasion": "always",
"damage": null, // Or omit this property entirely
"effects": [
{
"type": "recover_hp_percent",
"value": 0.30 // 30%
}
]
}
5. The Complete Picture
By combining all these pieces, we get a comprehensive data structure for any skill. This single, consistent format can describe everything from a simple fire spell to a complex buff that changes a character's stats.
Let's look at a complete example for a skill called "Armor Break":
{
"id": "armor_break_1",
"name": "Armor Break",
"description": "A powerful strike that also lowers the target's defense.",
"iconId": "icon_shield_break",
"skillType": "tech",
"cost": {
"type": "tp",
"value": 20
},
"scope": "one_enemy",
"occasion": "battle_only",
"damage": {
"type": "hp",
"element": "physical",
"basePower": 80
},
"effects": [
{
"type": "apply_modifier",
"modifierId": "def_down_s", // A small defense down debuff
"duration": 3, // 3 turns
"chance": 1.0 // 100% chance to apply on hit
}
]
}
All the user interfaces in a game, like skill lists and skill trees, are simply visual representations of this underlying data.

Conclusion
You have now designed a flexible and powerful data structure for skills and magic. This architecture is the foundation for all strategic combat in your JRPG.
Key Takeaways:
- Data-Driven Design: Skills are defined as data (JSON objects), not code. This makes creating, balancing, and managing them vastly simpler.
- Composite Structure: A skill is composed of several distinct parts: core properties (ID, name), usage rules (cost, scope, occasion), a damage component, and an array of effects.
- Effects are Modifiers: The most complex part of a skill, its effects (buffs, debuffs, status ailments), can be elegantly handled by a robust stat modifier system that temporarily alters a character's base stats.
- The Engine's Role: The game engine's job is to be an interpreter for this data, applying the costs, damage, and effects as described.
Preview of the next lesson:
With the design complete, we will move on to implementation. In the next lesson, we will focus on the first steps of making these skills usable in battle: implementing logic for MP consumption and target selection for skills. We'll update our battle UI to let the player choose a skill and a target, and then deduct the resource cost.
Can't find a good explanation? Sign up and we'll make it for you
Sign up