Skip to content

Legends of Runeterra card data ​

Ruleset and calculator scripts get Legends of Runeterra cards as plain objects straight from the card catalog. This page lists every field on those objects and in the catalog globals, with a real example and a few recipes.

Where the cards show up:

  • Card rules receive one card as their first argument.
  • Deck and deck set rules receive cardsById, an object keyed by card ref that holds every card in the deck (it can hold more).
  • Calculators receive cardsById as their second argument.

See the ruleset script API and the calculator script API for the full function signatures.

Card keys and deck refs ​

Every Legends of Runeterra card is keyed by its card code, the same code the game client and deck codes use:

  • 01DE012 is set 01, region DE (Demacia), card 012.
  • Tokens and level-ups add a suffix: 01DE012T1 is Garen's level-up.

A deck is a map of card code to copies ({ "01DE012": 3 }), and cardsById uses the same card codes as keys, so cardsById[ref] is always the card for a deck entry. Legends of Runeterra has no reprints, so cards have no printings list.

Guard against a missing card before reading from it: cardsById[ref] can be undefined when the catalog doesn't know a ref.

Card fields ​

Every card, in every game, has these top-level fields:

PropertyTypeDescription
idstringCatalog id of the card identity ("01DE012" in LoR, "pikachu-ex--1f29b66b68bc" in Pokémon).
namestringDisplay name in the catalog locale.
setCodestringSet of the card, or of its default printing ("set1", "sv2", "OGN").
collectible?booleanFalse for cards that can't go in a deck (LoR tokens and level-ups).
assets?CardCatalogCardAssetContract[]Images of the card's default printing.
printings?CardPrintingContract[]Every printing of the identity, default printing first. Absent in LoR.
hasImage?booleanFalse when none of the card's printings has an image in this language. Absent means it has one.
game?TGameDataGame-specific fields; see the per-game *CardGameData type.

Game fields (card.game) ​

Everything specific to Legends of Runeterra lives on card.game. Text fields and type / supertype are in the viewer's language, so compare the *Ref fields in logic: typeRef is "Unit" in every language, while type is "Einheit" in German.

PropertyTypeDescription
associatedCardRefs?string[]Card codes of related cards: level-ups, spawned tokens, spells a champion creates (["01DE012T1"]).
formatRefs?string[]Formats the card is legal in, as globals.formats keys ("client_Formats_Standard_name").
keywordRefs?string[]Keywords on the card, as globals.keywords keys ("QuickStrike", "Regeneration").
rarityRef?stringRarity key into globals.rarities: "Common", "Rare", "Epic", "Champion" or "None" (tokens, spells a card creates).
regionRefs?string[]Regions, as globals.regions keys ("Demacia", "PiltoverZaun"). A Runeterra champion's own cards also carry its card code ("06RU001"), matching a globals.runeterraChampions key.
spellSpeedRef?stringSpell speed key into globals.spellSpeeds ("Burst", "Fast", "Slow"); spells only.
vocabTerms?string[]Glossary terms linked from the card text, as globals.vocabTerms keys ("Strike", "Allegiance").
supertype?stringLocalized supertype; "Champion" on champions, absent otherwise. Use supertypeRef in logic.
type?stringLocalized card type ("Unit", "Einheit" in German). Use typeRef in logic.
typeRef?stringEnglish card type in every locale: "Unit", "Spell", "Landmark", "Equipment", "Ability" or "Trap".
supertypeRef?stringEnglish supertype in every locale: "Champion" on champions, absent otherwise.
cost?numberMana cost.
attack?numberPower (attack); usually 0 on non-units.
health?numberHealth; usually 0 on non-units.
description?stringRules text with the game client's inline markup (<link=…>, <style=…> tags).
descriptionRaw?stringRules text as plain text, markup removed.
levelupDescription?stringChampion level-up condition, with inline markup.
levelupDescriptionRaw?stringChampion level-up condition as plain text.
flavorText?stringFlavor text.
subtypes?string[]Unit subtypes in upper case (["ELITE"], ["YETI"]).
artistName?stringCard artist's name.

Globals (ctx.globals) ​

The catalog's globals are lookup tables that turn the refs on a card into display names, icons and descriptions: regionRefs: ["Demacia"] resolves through ctx.globals.regions.Demacia.

When globals are available

Globals are passed to ruleset scripts as ctx.globals (the last argument). Calculators may not receive ctx at all, and a ruleset can run without it too. Always check ctx && ctx.globals before using them and fall back to the raw ref.

PropertyTypeDescription
formats?Record<string, LorCatalogFormatLookupEntry>Formats by formatRefs key ("client_Formats_Standard_name" → Standard).
keywords?Record<string, LorCatalogKeywordLookupEntry>Keywords by keywordRefs key ("QuickStrike" → Quick Attack), with reminder text.
rarities?Record<string, LorCatalogRarityLookupEntry>Rarities by rarityRef key ("Common", "Rare", "Epic", "Champion", "None").
regions?Record<string, LorCatalogRegionLookupEntry>Regions by regionRefs key ("Demacia", "PiltoverZaun", "Runeterra").
runeterraChampions?Record<string, LorCatalogRuneterraChampionLookupEntry>Runeterra champions by card code ("06RU001"): the champion refs that can appear in regionRefs.
sets?Record<string, LorCatalogSetLookupEntry>Sets by the card's setCode ("set1", "set7b", "setevent").
spellSpeeds?Record<string, LorCatalogSpellSpeedLookupEntry>Spell speeds by spellSpeedRef key ("Burst", "Fast", "Slow").
types?Record<string, LorCatalogTypeLookupEntry>Card types by English type ("Unit", "Spell", "Champion", "Follower", …).
vocabTerms?Record<string, LorCatalogVocabTermLookupEntry>Glossary terms by vocabTerms key ("Allegiance"), with descriptions.

Lookup entries ​

Every globals table maps a key to an entry with these fields:

PropertyTypeDescription
color?stringDisplay color: a hex value ("#10C26E") or a CSS variable name ("--color-Demacia").
icon?string | nullIcon image URL; empty or null when there is none.
labelstringDisplay name in the catalog locale ("Piltover & Zaun").
metadataRef?LorCatalogMetadataReferenceAnchor an operator override is matched on.
order?numberSort position in filters and lists, lowest first.
showInFilter?booleanWhether the entry is offered as a filter option in the card browser.

Keyword and vocab term entries ​

keywords and vocabTerms entries also have:

PropertyTypeDescription
description?stringReminder text for the keyword, in the catalog locale.

Runeterra champion entries ​

runeterraChampions entries also have:

PropertyTypeDescription
cardCodestringThe champion's card code ("06RU001" for Bard), also its key in runeterraChampions.

Example card ​

Garen (01DE012), trimmed to one image:

json
{
  "id": "01DE012",
  "name": "Garen",
  "setCode": "set1",
  "collectible": true,
  "assets": [
    {
      "kind": "card",
      "url": "https://cdn.turny.gg/cards/lor/assets/01DE012-card-8a863d8a21d1029ab31bd8454e9456e89c2de96072d27705e2f11883752034f5.webp"
    }
  ],
  "game": {
    "associatedCardRefs": ["01DE012T1", "01DE012T2"],
    "formatRefs": [
      "client_Formats_Eternal_name",
      "client_Formats_Standard_name"
    ],
    "keywordRefs": ["Regeneration"],
    "rarityRef": "Champion",
    "regionRefs": ["Demacia"],
    "vocabTerms": ["Strike"],
    "supertype": "Champion",
    "supertypeRef": "Champion",
    "type": "Unit",
    "typeRef": "Unit",
    "cost": 5,
    "attack": 5,
    "health": 5,
    "description": "When I'm summoned, give other allies +1|+1 this round.",
    "descriptionRaw": "When I'm summoned, give other allies +1|+1 this round.",
    "levelupDescription": "I've <link=vocab.Strike><style=Vocab>struck</style></link> twice.<style=Variable></style>",
    "levelupDescriptionRaw": "I've struck twice.",
    "flavorText": "Training and resilience are the way of a soldier. Even in the face of great peril, we will not falter.",
    "subtypes": ["ELITE"],
    "artistName": "SIXMOREVODKA"
  }
}

Common recipes ​

js
// Calculator: cards per type, with champions split out.
export default function compute(pile, cardsById) {
  const counts = {};

  Object.keys(pile).forEach((ref) => {
    const game = (cardsById[ref] && cardsById[ref].game) || {};
    const type =
      game.supertypeRef === "Champion" ? "Champion" : game.typeRef || "Other";

    counts[type] = (counts[type] || 0) + pile[ref];
  });

  return {
    widgets: [
      {
        kind: "donut",
        label: "Card types",
        segments: Object.keys(counts).map((type) => ({
          label: type,
          value: counts[type],
        })),
      },
    ],
  };
}
js
// Card rule: commons only, plus champions.
export default function validateCard(card) {
  const rarity = card.game && card.game.rarityRef;

  if (rarity === "Common" || rarity === "Champion") {
    return true;
  }

  return {
    valid: false,
    issues: [{ message: card.name + " is not a common." }],
  };
}
js
// Card rule: Demacia only. Uses the region's display name when globals exist.
export default function validateCard(card, ctx) {
  const regions = (card.game && card.game.regionRefs) || [];

  if (regions.indexOf("Demacia") !== -1) {
    return true;
  }

  const globals = ctx && ctx.globals;
  const region =
    globals && globals.regions && globals.regions.Demacia
      ? globals.regions.Demacia.label
      : "Demacia";

  return {
    valid: false,
    issues: [{ message: card.name + " is not from " + region + "." }],
  };
}
js
// Calculator: copies at each mana cost, 7+ grouped.
export default function compute(pile, cardsById) {
  const buckets = [0, 0, 0, 0, 0, 0, 0, 0];

  Object.keys(pile).forEach((ref) => {
    const game = (cardsById[ref] && cardsById[ref].game) || {};
    const cost = Math.min(Math.max(game.cost || 0, 0), 7);

    buckets[cost] += pile[ref];
  });

  return {
    widgets: [
      {
        kind: "histogram",
        label: "Mana curve",
        buckets: buckets,
        labels: ["0", "1", "2", "3", "4", "5", "6", "7+"],
      },
    ],
  };
}

Turny.gg documentation