Upgrade system:

  • CardData.upgradeLevel (int, 0/1/2) replaces the binary isUpgraded flag as the source of truth. Legacy bool stays for save-file backwards compatibility.
  • CardUpgrade.CanUpgrade() + MAX_LEVEL = 2 gate repeated upgrades. Rest nodes, event upgrade rewards, victory-screen upgrades, and weapon-rarity-triggered starter bumps all use the gate.
  • CreateUpgraded() now increments upgradeLevel and appends another ”+” so the name progresses Slash -> Slash+ -> Slash++.
  • Shield stat added to upgrade bumps (+3 single-effect, +2 multi), parallel to block. Fixes Barrier / Arcane Shield / Frost Nova / Cleansing Arc / Pulse silently upgrading nothing on the shield stat. Paired with the {shield} placeholder fix in the previous commit.

Save compatibility:

  • SerializableCard gains upgradeLevel int; legacy isUpgraded bool stays for v1 saves. Load path prefers upgradeLevel when present and falls back to promoting isUpgraded=true to level 1. Card names are saved stripped of ALL trailing ’+’ chars so + and ++ both resolve to the same base registry entry.

Gear art:

  • 52 PNGs generated via tools/generate_gear_art.py (Gemini 3 Pro Image), dropped into Assets/Resources/GearArt/. Slug format matches NodeMapUI.SlugifyEventName output so shop / inventory auto-pick them up without code changes.

Card reference Excel:

  • tools/dump_card_reference.py parses CardDatabase.cs with regex, applies the CardUpgrade rules twice, and emits card_reference.xlsx at repo root with Base / + / ++ columns for all 152 cards (28 stat columns × 3 tiers + power fields + flags + description). Rarity-colored rows, frozen header. Regenerate with: python tools/dump_card_reference.py.

Commit 783db18 by astafford8488.