Repository navigation
Spell04 Dynamic Scaling
← Part 3: Unit Stat Upgrades | Next: Part 5: Card Triggers →
In this lesson, we explore dynamic scaling—effects that calculate their magnitude based on statistics tracked during combat.
We will create Play Other Cards, a 2-Ember spell that grants a target unit +2 Attack for every card played during the current battle. You will learn how CardTraits modify upgrades and how to configure tracked statistics.
Download the custom card art:
- Download Art: PlayOtherCardsSprite.png
-
Save Location: Save it to your mod project under
textures/PlayOtherCardsSprite.png.
In Plugin.cs, add "json/spells/PlayOtherCards.json" to your AddMergedJsonFile call. Then create json/spells/PlayOtherCards.json and add:
{
"$schema": "https://github.com/Monster-Train-2-Modding-Group/Trainworks-Reloaded/releases/latest/download/schema.json",
"cards": [
{
"id": "PlayOthercards",
"cost": 2,
"names": {
"english": "Play Other Cards"
},
"descriptions": {
"english": "Apply +[trait0.power][attack] per card played this battle."
},
"rarity": "rare",
"targets_room": true,
"targetless": false,
"class": "ClassBanished",
"card_art": "@PlayOtherCardsCardArt",
"pools": [
"MegaPool"
],
"traits": [
"@PlayOtherCardsScalingTrait"
],
"effects": [
"@ApplyScaledUpgrade"
]
}
],
"effects": [
{
"id": "ApplyScaledUpgrade",
"name": "CardEffectAddTempCardUpgradeToUnits",
"target_mode": "drop_target_character",
"target_team": "both",
"param_upgrade": "@PlayOtherCardsUpgrade"
}
],
"traits": [
{
"id": "PlayOtherCardsScalingTrait",
"name": "CardTraitScalingUpgradeUnitAttack",
"param_tracked_value": "any_card_played",
"param_entry_duration": "this_battle",
"param_int": 2
}
],
"upgrades": [
{
"id": "PlayOtherCardsUpgrade",
"bonus_damage": 0,
"upgrade_will_be_scaled_by_non_magic_power_trait": true
}
],
"game_objects": [
{
"id": "PlayOtherCardsCardArt",
"type": "card_art",
"extensions": {
"card_art": {
"sprite": "@PlayOtherCardsSprite"
}
}
}
],
"sprites": [
{
"id": "PlayOtherCardsSprite",
"path": "textures/PlayOtherCardsSprite.png"
}
]
}Unlike traits have a keyword (such as CardTraitIgnoreArmor - Piercing), CardTraitScalingUpgradeUnitAttack does not add a Keyword to the card:
- It modifies the upgrade applied by
@ApplyScaledUpgrade. - It reads the tracked in-game statistic and adds
tracked_stat * param_inttobonus_damageof the upgrade.
"traits": [
{
"id": "PlayOtherCardsScalingTrait",
"name": "CardTraitScalingUpgradeUnitAttack",
"param_tracked_value": "any_card_played",
"param_entry_duration": "this_battle",
"param_int": 2
}
]-
param_tracked_value: Specifies the battle statistice to monitor ("any_card_played"increments every time any card is played). -
param_entry_duration: Sets the monitoring time window:-
"this_turn": Gets the value of the statistic as of this turn. The value resets at the start of each new turn. -
"previous_turn": Get the value of the statistic from the previous turn. -
"this_battle": Gets the cumulative count of the statistic for the current battle (used here).
-
-
param_int: The scaling multiplier (adds +2 attack per recorded event).
Important
Scaling traits of this type are specifically built for Spells. Attaching them to Monster cards can cause undefined behavior and bugs.
"upgrades": [
{
"id": "PlayOtherCardsUpgrade",
"bonus_damage": 0,
"upgrade_will_be_scaled_by_non_magic_power_trait": true
}
]-
bonus_damage: 0: The default of any integer property is 0, so this could be left out, here for emphasis. -
upgrade_will_be_scaled_by_non_magic_power_trait: true: A flag for the upgrade that that this upgrade's parameters are modified by a scaling trait. This ensures that other mechanics that add upgrades to cards (like Reform) don't reset the scaled value back to 0.
"descriptions": {
"english": "Apply +[trait0.power][attack] per card played this battle."
}-
[trait0.power]: Dynamically pulls theparam_intvalue (2) from the first trait (trait0) listed on the card. -
[attack]: Replaced by the Attack icon.
- Build your solution and deploy the updated mod files to
BepInEx/plugins/<YourMod>/. - Launch Monster Train 2 and verify no JSON errors appear in the BepInEx console log.
- Start a battle with Play Other Cards in hand or deck:
- Play several other cards first.
- Inspect Play Other Cards: the dynamic description will update to show the current scaled attack buff.
- Play it onto a friendly unit and verify that the attack gained matches
(cards_played * 2).
Now that you can build dynamically scaled spells, continue to Part 5: Card Triggers (Pyre Sharpener) to build cards that activate automatically from hand without being cast.
Need Help? Got Feedback?
We're in the Shiny Shoe Discord Server - #mt2-modding