Legends of Runeterra

Overview

This document will provide you with a basic understanding of the Legends of Runeterra developer resources. It is designed to help you begin exploring and developing your own tools and products for Legends of Runeterra.

Getting Started

Before starting on a product for Legends of Runeterra, there are two requirements every developer must complete:

  1. Read the general policies
  2. Register your product

Only after developers have read the policies and registered their product on the Developer Portal, are they granted a limited license to use Riot Games' intellectual property (IP) outlined in the Legal Jibber Jabber.

After you've read the policies and registered your product, it's smooth sailing from there. We suggest following our Twitter and checking our blog to receive updates and joining the Developer Discord for help from the community. The Developer Discord is full of super talented and passionate developers that often run into the same issues you have. When you ask questions in the Discord you'll likely get more people helping you and your question will help others that joined after you. We hold office hours every other Friday where members of the Discord can ask questions related to developer tools or their projects. Beyond that gl and hf. Send us an app note if you run into issues that the community couldn't help you with.

Changelog

As Legends of Runeterra's approaches release, changes have been made to the resources being made available to developers. Below is a list of changes that have been made for each milestone and will be maintained until Legends of Runeterra reaches open access.

Announce Preview Patch (Oct 15-20)

The initial release of Data Dragon for Legends of Runeterra, the deck code library, and game client APIs which include the active deck, in-game card positions, and game result endpoints.

Expeditions Preview Patch (Nov 14-19)

Data Dragon for Legends of Runeterra

  • New level up description fields have been added for champion cards.
  • The content of both the set and core bundles has been updated.

Card positions endpoint

  • Card positions are now reported for the collection, deck builder, and Expeditions screens.
  • A boolean field has been added to the card object indicating whether the card belongs to the local player.

Expeditions endpoint

  • This is a new client endpoint that can be used to determine the cards a player drafts during an Expedition.

Data Dragon

Legends of Runeterra Data Dragon (not to be confused with League of Legends Data Dragon) is the name of the static data product that will host both game assets and data for community use in media or product development. Assets and data are made available over the internet in the format described below, and are updated in tandem with game releases so the community can update their products with the latest and greatest data. Legends of Runeterra static data is split into two bundles; core bundles and set bundles.

Core Bundles

The core bundles contain foundational assets and data that are shared across cards in all sets. This includes information like factions, icons, queues, rules, etc. Core bundles are available over the internet at the following url:

https://dd.b.pvp.net/datadragon-core-en_us.zip

The core bundle once extracted will have the following structure:

core-{locale}/
├─ COPYRIGHT
├─ README.md
├─ metadata.json
└─ {locale}/
   ├─ data/
   │  └─ globals-{locale}.json
   └─ img/
      └─ regions/
         └─ icon_demacia.png

metadata.json
The metadata.json file contains data related to the locale and version of the bundle.

globals.json
The global.json file contains sets of values that are reused throughout various cards. This includes keywords, rarities, regions (otherwise known as factions), spell speeds, and card types. There are two fields are paired with each other; name and nameRef. The name field will return a localized value, while the nameRef field will return a reference value that remains consistent across every locale.

{
  "keywords": [
    {
      "name": "Frostbite", // localized
      "nameRef": "Frostbite",
      ...
    },
    ...
  ],
  "rarities": [...],
  "regions": [...],
  "spellSpeeds": [...],
  "types": [...]
}

Set Bundles

The set bundles contain assets and data for cards released in a specific set. Set bundles are available in two versions; full and lite. The full set bundle contains the card art, alternative art, and full size illustrations for each card. The lite version only contains the card art and the alternative art making the lite version significantly smaller in size. Set bundles are available over the internet at the following urls:

https://dd.b.pvp.net/datadragon-set1-en_us.zip
https://dd.b.pvp.net/datadragon-set1-lite-en_us.zip

The set bundle once extracted will have the structure below.

set1-{locale}/
├── COPYRIGHT
├── README.md
├── metadata.json
└── {locale}/
    ├── data/
    │   └── set1-{locale}.json
    └── img/
        └── cards/
            ├── 01DE001.png
            ├── 01DE001-full.png (not included in lite bundles)
            ├── 01DE001-alt.png
            └── 01DE001-alt-full.png (not included in lite bundles)

metadata.json
The metadata.json file contains data related to the locale and version of the bundle.

set.json
The set.json file contains data related to cards in the specific set. For each card, information is provided on the card's assets, associated cards, attack, health, cost, description, flavor text, name, code, keywords, rarity, type, and subtype.

[
  {
    "associatedCards": [],
    "associatedCardRefs": [
      "01FR009T1",
      "01FR009T2",
      "01FR053"
    ],
    "assets": [
      {
        "gameAbsolutePath": "http://dd.b.pvp.net/Set1/en_us/img/cards/01FR009.png",
        "fullAbsolutePath": "http://dd.b.pvp.net/Set1/en_us/img/cards/01FR009-full.png"
      }
    ],
    "region": "Freljord",
    "regionRef": "Freljord",
    "attack": 0,
    "cost": 3,
    "health": 5,
    "description": "",
    "descriptionRaw": "",
    "levelupDescription": "I've survived 10 total damage<style=Variable></style>.",
    "levelupDescriptionRaw": "I've survived 10 total damage.",
    "flavorText": "“Papa, tell the one about Braum and his door!”\n\"Or when his fall split a mountain in two!\"\n\"Oh! Whattabout when he saved the tavern from the rampaging yeti?!\"",
    "artistName": "SIXMOREVODKA",
    "name": "Braum",
    "cardCode": "01FR009",
    "keywords": [
      "Challenger",
      "Regeneration"
    ],
    "keywordRefs": [
      "Challenger",
      "Regeneration"
    ],
    "spellSpeed": "",
    "spellSpeedRef": "",
    "rarity": "Champion",
    "rarityRef": "Champion",
    "subtype": "",
    "supertype": "Champion",
    "type": "Unit",
    "collectible": true
  },
  ...
]

Paired Fields
Fields are often paired with a reference field, similar to those in the global.json in the core bundle. As an example, the keywords field is paired with a keywordsRef field. The keywords field will return localized values, while the keywordsRef field will return reference values that remains consistent across every locale. Some of these fields contain lists of values and while these lists are not ordered the position in the list should remain consistent with the paired field (i.e., the first element in the keywords field will be paired with the first element in they keywordsRef field).

Card Images
Each card in the full set bundle has at least two image files:

  • The card render (e.g., 01DE001.png) is an image of the full card including its stats and text and frame, in the relevant locale. These images are 768x1024 pixels.
  • The card illustration (e.g., 01DE001-full.png) is the full card art, without stats or text or a card frame. These images are 1024x1024 pixels for spells, and 2048x1024 pixels for all other cards.

In some cases, cards may have an alternative version of card art available in addition:

  • The card alt render (e.g., 01DE001-alt.png) is an image of the full card as described above, but with the alternative art.
  • The card alt illustration (e.g., 01DE001-alt-full.png) is the full card art as described above, but with the alternative art.

Languages

There are separate core and set bundles for each supported language meaning these bundles will need to be fetched separately for each language you wish to support in your product. Below is a list of the supported languages.

Code Language
de_de German (Germany)
en_us English (United States)
es_es Spanish (Spain)
fr_fr French (France)
it_it Italian (Italy)
ja_jp Japanese (Japan)
ko_kr Korean (Korea)

Deck Codes

The Legends of Runeterra game client allows for players to encode/decode Legends of Runeterra deck to/from a simple string so that decks can be shared between players. Below is an example of a code for an Demacia/Freljord deck.

CEAAEBYBAEDRMGREFYZDKCABAABQMCYSCQNB2JYCAQAQABYMFIWAMAIBBEKCAIRHFE

We have a public C# library on GitHub to demonstrate how to generate and parse a deck codes and will be reviewing pull requests if community would like to contribute. If members of the community would like to create implementations in other languages, we'd be happy to reference those implementations in the README.

Game Client API

The Legends of Runeterra game client exposes a collection of endpoints that can be used to describe the deck being used by the player in an active game, the positions of the cards on the board, and the result of the player's most recently completed game.

The game client API is enabled locally on the player's computer via port 21337 by default. If the player chooses, this API can be disabled and the port may be adjusted in the settings menu.

Active Deck

The static-decklist endpoint can be used to describe the player's current deck in an active game. The request returns the deck code and a map of each card in the form of a card code and the count of each card in the deck. As the name of the endpoint suggests, this response remains static even after cards in the deck have been played. Below is an example of a response from this endpoint.

GET http://localhost:{port}/static-decklist

{
  "DeckCode": "DECKCODE",
  "CardsInDeck": {
    "01DE000": 1,
    "01DE001": 2,
    ...
  }
}

If a request is made to the static-decklist endpoint while the player is not in an active game, the endpoint will return null values, seen below.

{
  "DeckCode": null,
  "CardsInDeck": null
}

Card Positions

The positional-rectangles endpoint can be used to determine the position of the cards in the collection, deck builder, Expedition drafts, and active games. Unlike the static-decklist endpoint, the positional-rectangles endpoint will return the position of the cards at the time of the request. The response time of this endpoint will vary by computer, however we suggest polling this endpoint no more than once per second. Below is an example of a response from this endpoint.

GET http://localhost:{port}/positional-rectangles

{
  "PlayerName": "Riot Tuxedo",
  "OpponentName": "Riot Gene",
  "GameState": "InProgress",
  "Screen": {
    "ScreenWidth": 1920,
    "ScreenHeight": 1200
  },
  "Rectangles": [
    {
      "CardID": 0,
      "CardCode": "01DE001",
      "TopLeftX": 800,
      "TopLeftY": 900,
      "Width": 252,
      "Height": 373,
      "LocalPlayer": true
    },
    ...
  ]
}

GameState
As mentioned before, the positional-rectangles endpoint can be used in the collection, deck builder, Expedition drafts, and active games. In the collection view, deck builder, and Expedition drafts the GameState will return Menus. If an active game is in progress, the GameState will return InProgress. If a request is made to the positional-rectangles endpoint while no cards visible, Rectangles will return an empty list, seen below.

{
  "PlayerName": null,
  "OpponentName": null,
  "GameState": "Menus",
  "Screen": {
    "ScreenWidth": 1,
    "ScreenHeight": 1
  },
  "Rectangles": []
}

Rectangles
The TopLeftX and TopLeftY fields indicate the position of the top left corner of the card relative to the bottom left corner of the game client. In the example above, the top left corner of the card would be 900 pixels from the bottom edge of the client and 800 pixels from the left edge of the client.
The Width and Height fields indicate the dimensions of the card itself.
LocalPlayer is a boolean field which returns true if the particular card belongs to the local player and false if the card belongs to an opponent in-game.

Expeditions

The expeditions-state endpoint can be used to determine the cards a player drafts during an Expedition. The request returns a number of fields including the current state of the Expedition and a list of card codes that have been drafted. Below is an example of a response from this endpoint.

GET http://localhost:{port}/expeditions-state

{
  "IsActive": true,
  "State": "Picking",
  "Record": [
    "win",
    "loss"
  ],
  "DraftPicks": [], // Coming soon
  "Deck": [
    "01SI052",
    "01SI001",
    "01SI034",
    ...
  ],
  "Games": 2,
  "Wins": 1,
  "Losses": 1
}

IsActive is a boolean field that indicates whether the player has an active Expedition.
State is an enumerated field that is used to indicate the current state of the Expedition.

  • Inactive indicates the player doesn't have an active Expedition.
  • Offscreen indicates the player has an active Expedition, but they're elsewhere in the client including when the player is playing their drafted deck.
  • Picking indicates the player is being presented with potential cards to draft.
  • Swapping indicates the player is being presented with potential card swaps.
  • Other indicates the player is viewing one of the interstitial screens within Expeditions.

Record returns a list of of win or loss strings based on the results of the player's Expedition.

Game Result

A request to the game-result endpoint can be made to determine the result of the player's most recently completed game. The request returns an int for GameID and a boolean for LocalPlayerWon. The GameID resets every time the client restarts and is incremented after a game is completed. The GameID isn't associated with any other source of data. Below is an example of a response from this endpoint.

GET http://localhost:{port}/game-result

{
    "GameID": 0,
    "LocalPlayerWon": true
}