commit 9e5f83df370119ea131fdfc8d661090826c75662 Author: Sylver Date: Thu Nov 2 02:02:29 2023 +0100 Large initial push 7 factions already implemented: - Norther Realms - Nilfgaard Empire - Scoia'Tael - Monsters - Skellige - Redenia - Toussaint In progress: - Velen To do: - Witchers - Wild Hunt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8a30d25 --- /dev/null +++ b/.gitignore @@ -0,0 +1,398 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..bbc11f3 --- /dev/null +++ b/LICENSE @@ -0,0 +1,11 @@ +“Commons Clause” License Condition v1.0 + +The Software is provided to you by the Licensor under the License, as defined below, subject to the following condition. + +Without limiting other conditions in the License, the grant of rights under the License will not include, and the License does not grant to you, right to Sell the Software. + +For purposes of the foregoing, “Sell” means practicing any or all of the rights granted to you under the License to provide to third parties, for a fee or other consideration (including without limitation fees for hosting or consulting/ support services related to the Software), a product or service whose value derives, entirely or substantially, from the functionality of the Software. Any license notice or attribution required by the License must also include this Commons Cause License Condition notice. + +Software: Gwent Classic +License: MIT +Licensor: Arun Sundaram diff --git a/README.md b/README.md new file mode 100644 index 0000000..db8ce94 --- /dev/null +++ b/README.md @@ -0,0 +1,31 @@ +# gwent-classic-v4.0 +![cover](https://user-images.githubusercontent.com/26311830/116256903-f1599b00-a7b6-11eb-84a1-16dcb5c9bfc6.jpg) + +**WORK IN PROGRESS** + +A browser remake of the original Gwent minigame from The Witcher 3: Wild Hunt.
Click [here](https://romain-durban.github.io/gwent-classic-v4.0/) to play. + +Unlike v3.0 remake, this one is a much deeper redesign, addressing further balance issues. Number of cards is drastically reduced and abilities have been tweaked (and made more complex). +This is based on the huge work from [Novigrad Tavern](https://www.ebay.com/usr/novigrad_tavern), this remake is an attempt to implement the cards they have designed (there are some minor differences though). + +## Improvements + +Are listed here only the modifications done in this present fork, more were done before by other developers. + +TBA + +#### Changes + +Are listed here only the modifications done in this present fork, more were done before by other developers. + +TBA + + +### Operations included with the keyboard: + +**"E"** starts the game
+**"X"** uses or modifies the leader card
+**"Q"** closes the card explanation windows
+**"Space"** passes the round
+**"Enter"** plays the cards
+**Arrows** select cards on the carousel diff --git a/abilities.js b/abilities.js new file mode 100644 index 0000000..fd3592b --- /dev/null +++ b/abilities.js @@ -0,0 +1,2074 @@ +"use strict" + +var ability_dict = { + clear: { + name: "Clear Weather", + description: "Removes all Weather Cards (Biting Frost, Impenetrable Fog and Torrential Rain) effects. ", + placed: async (card, row) => { + // If ability carried by a unit/hero card, draw the weather card from the deck + if (card.isUnit() || card.hero) { + let wCard = card.holder.deck.findCard(c => c.row === "weather" && c.abilities.includes("clear")); + if (wCard) { + await wCard.autoplay(card.holder.deck); + } + } + } + }, + frost: { + name: "Biting Frost", + description: "Sets the strength of all Close Combat cards to 1 for both players. ", + placed: async (card, row) => { + // If ability carried by a unit/hero card, draw the weather card from the deck + if (card.isUnit() || card.hero) { + let wCard = card.holder.deck.findCard(c => c.row === "weather" && c.abilities.includes("frost")); + if (wCard) { + await wCard.autoplay(card.holder.deck); + } + } + } + }, + fog: { + name: "Impenetrable Fog", + description: "Sets the strength of all Ranged Combat cards to 1 for both players. ", + placed: async (card, row) => { + // If ability carried by a unit/hero card, draw the weather card from the deck + if (card.isUnit() || card.hero) { + let wCard = card.holder.deck.findCard(c => c.row === "weather" && c.abilities.includes("fog")); + if (wCard) { + await wCard.autoplay(card.holder.deck); + } + } + player_me.deck.cards.filter(c => c.abilities.includes("fog_summoning")).map(c => c.autoplay(player_me.deck)); + player_me.grave.cards.filter(c => c.abilities.includes("fog_summoning")).map(c => c.autoplay(player_me.grave)); + player_op.deck.cards.filter(c => c.abilities.includes("fog_summoning")).map(c => c.autoplay(player_op.deck)); + player_op.grave.cards.filter(c => c.abilities.includes("fog_summoning")).map(c => c.autoplay(player_op.grave)); + } + }, + fog_summoning: { + name: "Impenetrable Fog Summoning", + description: "When Impenetrable Fog is played by any player, draw this card from your deck or discard pile and play it. Fog does not affect this unit." + }, + rain: { + name: "Torrential Rain", + description: "Sets the strength of all Siege Combat cards to 1 for both players. ", + placed: async (card, row) => { + // If ability carried by a unit/hero card, draw the weather card from the deck + if (card.isUnit() || card.hero) { + let wCard = card.holder.deck.findCard(c => c.row === "weather" && c.abilities.includes("rain")); + if (wCard) { + await wCard.autoplay(card.holder.deck); + } + } + } + }, + storm: { + name: "Skellige Storm", + description: "Reduces to 1 the strength of all units either in Close/Ranged rows, or Siege/Ranged rows.", + placed: async (card, row) => { + if (!(card.holder.controller instanceof ControllerAI)) { + let c = await ui.popup("Close + Ranged [E]", (p) => p.choice = "frost", "Ranged + Siege [Q]", (p) => p.choice = "rain", "Which rows to target", "Skellige Storm can either target Close/Ranged rows or Ranged/Siege rows, which one to target?"); + card.abilities = [c, "fog"]; + } else { + if (card.holder.controller.weightWeather({ key: "spe_storm", abilities: ["frost", "fog"] }) >= card.holder.controller.weightWeather({ key: "spe_storm", abilities: ["rain", "fog"] })) { + card.abilities = ["frost", "fog"]; + } else { + card.abilities = ["rain", "fog"]; + } + } + // If ability carried by a unit/hero card, draw the weather card from the deck + if (card.isUnit() || card.hero) { + let wCard = card.holder.deck.findCard(c => c.row === "weather" && c.abilities.includes("storm")); + if (wCard) { + await wCard.autoplay(card.holder.deck); + } + } + } + }, + hero: { + name: "Hero", + description: "Not affected by any Special Cards or abilities. " + }, + decoy: { + name: "Decoy", + description: "Swap with a card on the battlefield to return it to your hand. " + }, + horn: { + name: "Commander's Horn", + description: "Doubles the strength of all unit cards in that row. Limited to 1 per row. ", + placed: async card => await card.animate("horn"), + effectAfterMove: true + }, + mardroeme: { + name: "Mardroeme", + description: "Triggers transformation of all Berserker cards on the same row. ", + placed: async (card, row) => { + if (card.isLocked()) + return; + let berserkers = row.findCards(c => c.abilities.includes("berserker")); + await Promise.all(berserkers.map(async c => await ability_dict["berserker"].placed(c, row))); + } + }, + berserker: { + name: "Berserker", + description: "Transforms into a bear when a Mardroeme card is on its row. ", + placed: async (card, row) => { + if (row.effects.mardroeme === 0 || card.isLocked()) + return; + await card.animate("mardroeme"); + row.removeCard(card); + await row.addCard(new Card(card.target, card_dict[card.target], card.holder)); + } + }, + scorch: { + name: "Scorch", + description: "Discard after playing. Kills the strongest card(s) on the battlefield. ", + activated: async card => { + await ability_dict["scorch"].placed(card); + await board.toGrave(card, card.holder.hand); + }, + placed: async (card, row) => { + if (card.isLocked() || game.scorchCancelled) + return; + if (row !== undefined) + row.cards.splice(row.cards.indexOf(card), 1); + let maxUnits = board.row.map(r => [r, r.maxUnits()]).filter(p => p[1].length > 0).filter(p => !p[0].isShielded()); + if (row !== undefined) + row.cards.push(card); + let maxPower = maxUnits.reduce((a, p) => Math.max(a, p[1][0].power), 0); + let scorched = maxUnits.filter(p => p[1][0].power === maxPower); + let cards = scorched.reduce((a, p) => a.concat(p[1].map(u => [p[0], u])), []); + + await Promise.all(cards.map(async u => await u[1].animate("scorch", true, false))); + await Promise.all(cards.map(async u => await board.toGrave(u[1], u[0]))); + } + }, + scorch_c: { + name: "Scorch - Close Combat", + description: "Destroy your enemy's strongest Close Combat unit(s) if the combined strength of all his or her Close Combat units is 10 or more. ", + placed: async (card) => await board.getRow(card, "close", card.holder.opponent()).scorch() + }, + scorch_r: { + name: "Scorch - Ranged", + description: "Destroy your enemy's strongest Ranged Combat unit(s) if the combined strength of all his or her Ranged Combat units is 10 or more. ", + placed: async (card) => await board.getRow(card, "ranged", card.holder.opponent()).scorch() + }, + scorch_s: { + name: "Scorch - Siege", + description: "Destroys your enemy's strongest Siege Combat unit(s) if the combined strength of all his or her Siege Combat units is 10 or more. ", + placed: async (card) => await board.getRow(card, "siege", card.holder.opponent()).scorch() + }, + agile: { + name: "Agile", + description: "Can be placed in either the Close Combat or the Ranged Combat row. Cannot be moved once placed. " + }, + agile_cr: { + name: "Agile Close/Ranged", + description: "Can be placed in either the Close Combat or the Ranged Combat row. Cannot be moved once placed. " + }, + agile_cs: { + name: "Agile Close/Siege", + description: "Can be placed in either the Close Combat or the Siege Combat row. Cannot be moved once placed. " + }, + agile_rs: { + name: "Agile Ranged/Siege", + description: "Can be placed in either the Ranged Combat or the Siege Combat row. Cannot be moved once placed. " + }, + agile_crs: { + name: "Agile Close/Ranged/Siege", + description: "Can be placed in any combat row. Cannot be moved once placed. " + }, + muster: { + name: "Muster", + description: "Find any cards with the same name in your deck and play them instantly. ", + placed: async (card) => { + if (card.isLocked()) + return; + let pred = c => c.target === card.target; + let units = card.holder.hand.getCards(pred).map(x => [card.holder.hand, x]) + .concat(card.holder.deck.getCards(pred).map(x => [card.holder.deck, x])); + if (units.length === 0) + return; + await card.animate("muster"); + if (card.row.includes("agile")) { + await Promise.all(units.map(async p => await board.addCardToRow(p[1], card.currentLocation, p[1].holder, p[0]))); + } else { + await Promise.all(units.map(async p => await board.addCardToRow(p[1], p[1].row, p[1].holder, p[0]))); + } + } + }, + spy: { + name: "Spy", + description: "Place on your opponent's battlefield (counts towards your opponent's total) and draw 2 cards from your deck.", + description_toussaint: "Place on your opponent's battlefield. Draw 3 cards from your deck. Keep one of them in your hand and shuffle the other two into the deck.", + placed: async (card) => { + if (card.isLocked()) + return; + await card.animate("spy"); + // Toussaint spies have a different behaviour + if (card.faction === "toussaint") { + let cards = { cards: card.holder.deck.cards.slice(0, 3) }; + let targetCard = null; + if (card.holder.controller instanceof ControllerAI) { + targetCard = card.holder.controller.getHighestWeightCard(cards.cards); + } else { + try { + Carousel.curr.cancel(); + } catch (err) { } + await ui.queueCarousel(cards, 1, (c, i) => targetCard = c.cards[i], c => true, true, false, "Choose the card to draw and play keep"); + } + cards.cards.forEach(c => { + if (c === targetCard) { + board.toHand(c, card.holder.deck); + } else { + // Remove to shuffle back at a random place (default behaviour on addCard in deck) + card.holder.deck.removeCard(c); + card.holder.deck.addCard(c); + } + }); + } else { + for (let i = 0; i < 2; i++) { + if (card.holder.deck.cards.length > 0) { + // If can draw from opponent's deck and not AI + if (card.holder.capabilities["drawOPdeck"] > 0 && !(card.holder.controller instanceof ControllerAI)) { + let d = await ui.popup("Own deck [E]", (p) => p.choice = card.holder.deck, "Opponent's deck [Q]", (p) => { + p.choice = card.holder.opponent().deck; + card.holder.capabilities["drawOPdeck"] -= 1; + }, "Choose deck to draw from", "From which deck to draw the next card, your own or the opponent's deck (" + card.holder.capabilities["drawOPdeck"] + " left in this battle)?"); + await d.draw(card.holder.hand); + } else { + await card.holder.deck.draw(card.holder.hand); + } + } + } + } + card.holder = card.holder.opponent(); + } + }, + medic: { + name: "Medic", + description: "Choose one card from your discard pile and play it instantly (no Heroes or Special Cards). ", + placed: async (card) => { + if (card.isLocked() || (card.holder.grave.findCards(c => c.isUnit()) <= 0)) + return; + let grave = board.getRow(card, "grave", card.holder); + let respawns = []; + if (game.randomRespawn) { + for (var i = 0; i < game.medicCount; i++) { + if (card.holder.grave.findCards(c => c.isUnit()).length > 0) { + let res = grave.findCardsRandom(c => c.isUnit())[0]; + grave.removeCard(res); + grave.addCard(res); + await res.animate("medic"); + await res.autoplay(grave); + } + } + return; + } else if (card.holder.controller instanceof ControllerAI) { + for (var i = 0; i < game.medicCount; i++) { + if (card.holder.grave.findCards(c => c.isUnit()).length > 0) { + let res = card.holder.controller.medic(card, grave); + grave.removeCard(res); + grave.addCard(res); + await res.animate("medic"); + await res.autoplay(grave); + } + } + return; + } + + //Player can't pick more cards than what's actually available in the graveyard + let cardPicks = Math.min(game.medicCount, card.holder.grave.findCards(c => c.isUnit()).length); + await ui.queueCarousel(card.holder.grave, cardPicks, (c, i) => respawns.push({ + card: c.cards[i] + }), c => c.isUnit(), true); + await Promise.all(respawns.map(async wrapper => { + let res = wrapper.card; + grave.removeCard(res); + grave.addCard(res); + await res.animate("medic"); + await res.autoplay(grave); + })); + } + }, + morale: { + name: "Morale Boost", + description: "Adds +1 to all units in the row (excluding itself). ", + placed: async card => await card.animate("morale"), + effectAfterMove: true + }, + bond: { + name: "Tight Bond", + description: "Place next to a card with the same name to double the strength of both cards. ", + placed: async card => { + if (card.isLocked()) + return; + let bonds = card.currentLocation.findCards(c => c.target === card.target).filter(c => c.abilities.includes("bond")).filter(c => !c.isLocked()); + if (bonds.length > 1) + await Promise.all(bonds.map(c => c.animate("bond"))); + }, + effectAfterMove: true + }, + avenger: { + name: "Avenger", + description: "When this card is removed from the battlefield, it summons a powerful new Unit Card to take its place. ", + removed: async (card) => { + if (game.over || game.roundHistory.length > 2 || card.isLocked()) + return; + // Some avengers are related to muster and should trigger it, if not already in deck + if (card_dict[card.target]["ability"].includes("muster") && (card.holder.deck.findCards(c => c.key === card.target).length === 0 && card.holder.hand.findCards(c => c.key === card.target).length === 0)) { + for (let i = 0; i < card_dict[card.target]["count"]; i++) { + let avenger = new Card(card.target, card_dict[card.target], card.holder); + avenger.removed.push(() => setTimeout(() => avenger.holder.grave.removeCard(avenger), 2000)); + if (card.target != card.key) + await board.addCardToRow(avenger, avenger.row, card.holder); + } + } else if (card.target === card.key) { + await board.moveTo(card, card.row, card.holder.grave); + } else { + let avenger; + // If one copy at least in hand or deck, use it instead of creating a duplicate + if (card.holder.deck.findCards(c => c.key === card.target).length) { + avenger = card.holder.deck.findCard(c => c.key === card.target); + await board.moveTo(avenger, avenger.row, card.holder.deck); + } else if (card.holder.hand.findCards(c => c.key === card.target).length) { + avenger = card.holder.hand.findCard(c => c.key === card.target); + await board.moveTo(avenger, avenger.row, card.holder.hand); + } else { + avenger = new Card(card.target, card_dict[card.target], card.holder); + await board.addCardToRow(avenger, avenger.row, card.holder); + if (card.target != card.key) + avenger.removed.push(() => setTimeout(() => avenger.holder.grave.removeCard(avenger), 2000)); + } + } + + }, + weight: (card) => { + if (game.roundHistory.length > 2) + return 1; + return Number(card_dict[card.target]["strength"]); + } + }, + cintra_slaughter: { + name: "Slaughter of Cintra", + description: "When using the Slaugther of Cintra special card, destroy all units on your side of the board having the Slaughter of Cintra ability then draw as many cards as units destroyed.", + activated: async card => { + let targets = board.row.map(r => [r, r.findCards(c => c.abilities.includes("cintra_slaughter")).filter(c => c.holder === card.holder).filter(c => !c.isLocked())]); + let cards = targets.reduce((a, p) => a.concat(p[1].map(u => [p[0], u])), []); + let nb_draw = cards.length; + await Promise.all(cards.map(async u => await u[1].animate("scorch", true, false))); + await Promise.all(cards.map(async u => await board.toGrave(u[1], u[0]))); + await board.toGrave(card, card.holder.hand); + + for (let i = 0; i < nb_draw; i++) { + if (card.holder.deck.cards.length > 0) + await card.holder.deck.draw(card.holder.hand); + } + }, + weight: (card) => 30 + }, + foltest_king: { + description: "Pick an Impenetrable Fog or Torrential Rain card from your deck and play it instantly.", + activated: async card => { + let fog = card.holder.deck.findCard(c => c.key === "spe_fog"); + let rain = card.holder.deck.findCard(c => c.key === "spe_rain"); + let c = null; + if (fog && !rain) { + c = fog; + } else if (rain && !fog) { + c = rain; + } else if (rain && fog) { + // If both weather cards are available, let the user choose + if (!(card.holder.controller instanceof ControllerAI)) { + c = await ui.popup("Impenetrable Fog [E]", (p) => p.choice = fog, "Torrential Rain [Q]", (p) => p.choice = rain, "Choose a weather card to play", "Which weather card to play? Impenetrable Fog or Torrential Rain?"); + } else { + if (card.holder.controller.weightWeatherFromDeck(card, "fog") >= card.holder.controller.weightWeatherFromDeck(card, "rain")) { + c = fog; + } else { + c = rain; + } + } + } + if (c) + await c.autoplay(card.holder.deck); + }, + weight: (card, ai) => Math.max(ai.weightWeatherFromDeck(card, "fog"), ai.weightWeatherFromDeck(card, "rain")) + }, + foltest_steelforged: { + description: "Clear any weather effects (resulting from Biting Frost, Torrential Rain or Impenetrable Fog cards) in play.", + activated: async () => { + tocar("clear", false); + await weather.clearWeather() + }, + weight: (card, ai) => ai.weightCard(card_dict["spe_clear"]) + }, + foltest_siegemaster: { + description: "Doubles the strength of all your Siege units (unless a Commander's Horn is also present on that row).", + activated: async card => await board.getRow(card, "siege", card.holder).leaderHorn(card), + weight: (card, ai) => ai.weightHornRow(card, board.getRow(card, "siege", card.holder)) + }, + foltest_lord: { + description: "Choose one unit card that lies on your battlefield and draw from your deck or grave one unit card with the same name and play it.", + activated: async card => { + // Get all cards on the board for the player + let cards = { + cards: card.holder.getAllRowCards().filter(c => c.isUnit()) + }; + // If AI, look for the most beneficial card to copy + if (card.holder.controller instanceof ControllerAI) { + let candidates = card.holder.controller.bestSimilarCards(card); + if (candidates.length > 0) { + await card.holder.playCardAction(candidates[0][1], async () => await board.moveTo(candidates[0][1], candidates[0][2], null)); + } + return true; + } + let srcCard; + try { + Carousel.curr.cancel(); + } catch (err) { } + // Let the player choose which card on the board to try to copy + await ui.queueCarousel(cards, 1, (c, i) => srcCard = c.cards[i], c => c.isUnit(), true, false, "Which unit to copy?"); + if (srcCard) { + // Look for other similar card than the selected one and let the player choose one + let copycards = { + cards: srcCard.holder.grave.cards.concat(srcCard.holder.deck.cards).filter((c => c.name === srcCard.name || ("target" in srcCard && c.target === srcCard.target))) + }; + if (copycards.length == 0) { + return false; + } + let newCard = null; + try { + Carousel.curr.cancel(); + } catch (err) { } + await ui.queueCarousel(copycards, 1, (c, i) => newCard = c.cards[i], c => c.isUnit(), true, false, "Which unit to summon?"); + if (newCard) { + await newCard.autoplay(); + } + } + + }, + weight: (card, ai, max) => { + let candidates = ai.bestSimilarCards(card); + if (candidates.length > 0) { + return candidates[0][3]; + } + return 0; + } + }, + foltest_son: { + description: "Destroy your enemy's strongest Ranged Combat unit(s) if the combined strength of all his or her Ranged Combat units is 10 or more.", + activated: async card => await ability_dict["scorch_r"].placed(card), + weight: (card, ai, max) => ai.weightScorchRow(card, max, "ranged") + }, + emhyr_imperial: { + description: "Draw from opponent's discard pile one unit card (not hero) into your hand. Then choose any one card from your hand and place it at the bottom of your deck.", + activated: async card => { + let opcards = { cards: card.holder.opponent().grave.cards.filter(c => c.isUnit()) }; + let owncards = { cards: card.holder.hand.cards }; + let drawCard = null, targetCard = null; + + if (opcards.cards.length > 0 && owncards.cards.length > 0) { + if (card.holder.controller instanceof ControllerAI) { + let drawCard = card.holder.controller.medic(card, card.holder.opponent().grave); + // Draw card from OP grave + drawCard.holder = card.holder; + await board.toHand(drawCard, card.holder.opponent().grave); + // Pick lowest card and put it back in the deck + targetCard = card.holder.controller.getLowestWeightCard(owncards.cards); + await board.toDeck(targetCard, card.holder.hand); + } else { + await ui.queueCarousel(opcards, 1, (c, i) => drawCard = c.cards[i], c => c.isUnit(), true, false, "Which card to draw?"); + // Draw card from OP grave + drawCard.holder = card.holder; + await board.toHand(drawCard, card.holder.opponent().grave); + // Pick card to put back into deck + await ui.queueCarousel(owncards, 1, (c, i) => targetCard = c.cards[i], c => true, true, false, "Which card to put back into the deck?"); + await board.toDeck(targetCard, card.holder.hand); + } + } else { + return false; + } + }, + weight: (card, ai) => { + let data = ai.countCards(card.holder.opponent().grave); + let bestCard = card.holder.opponent().grave.cards.filter(c => c.isUnit()).sort((a, b) => b.power - a.power)[0]; + + return !bestCard ? 0 : (data.spy.length ? 50 : data.medic.length ? 15 : bestCard.power); + } + }, + emhyr_emperor: { + description: "Look at 4 random cards in your opponent's hand. Choose one. Opponent must play this card on his next turn (if he does not fold).", + activated: async card => { + let container = new CardContainer(); + container.cards = card.holder.opponent().hand.findCardsRandom(() => true, 4); + try { + Carousel.curr.cancel(); + } catch (err) { } + let targetCard = null; + // AI choses card with lowest weight + if (card.holder.controller instanceof ControllerAI) { + targetCard = card.holder.opponent().getAIController().getLowestWeightCard(container.cards); + } else { + await ui.queueCarousel(container, 1, (c, i) => targetCard = c.cards[i], c => true, true, false, "Which card should your opponent play on the next round?"); + } + // Can't force an action if the opponent has already passed + if (!card.holder.opponent().passed) { + card.holder.opponent().forcedActions.push(targetCard); + } + }, + weight: card => { + if (card.holder.opponent().hand.cards.length > 6 || card.holder.opponent().hand.cards.length < 4) { + return 10; + } + return 20; + } + }, + emhyr_whiteflame: { + description: "Passive: When you use Spies and Emissaries, you (but don't have to) draw cards from your opponent's deck instead of your own. In this way you can draw no more than three cards for the entire battle.", + placed: card => { + card.holder.disableLeader(); + card.holder.capabilities["drawOPdeck"] = 3; + } + }, + emhyr_relentless: { + description: "Destroy one unit or hero card on your battlefield. Then draw any one Spy or Emissary card from your deck into your hand.", + activated: async card => { + // Select own cards on the board + let owncards = { + cards: card.holder.getAllRowCards().filter(c => c.isUnit() || c.hero) + }; + let spyCards = { + cards: card.holder.deck.cards.filter(c => c.abilities.includes("spy") || c.abilities.includes("emissary")) + }; + if (owncards.cards.length === 0 || spyCards.cards.length === 0) + return false; + + let targetCard = null; + let drawCard = null; + if (card.holder.controller instanceof ControllerAI) { + targetCard = owncards.cards.sort((a, b) => a.power - b.power)[0]; // AI takes weakest card + drawCard = spyCards.cards.sort((a, b) => a.power - b.power)[0]; // AI takes weakest spy card + } else { + try { + Carousel.curr.cancel(); + } catch (err) { } + await ui.queueCarousel(owncards, 1, (c, i) => targetCard = c.cards[i], c => true, true, false, "Which card to destroy?"); + await ui.queueCarousel(spyCards, 1, (c, i) => drawCard = c.cards[i], c => true, true, false, "Which Spy/Emissary card to draw?"); + } + + + await board.toGrave(targetCard, board.getRow(targetCard, targetCard.row, targetCard.holder)); + await board.toHand(drawCard, card.holder.deck); + }, + weight: (card, ai, max, data) => { + let owncards = { + cards: card.holder.getAllRowCards().filter(c => c.isUnit() || c.hero) + }; + let spyCards = { + cards: card.holder.deck.cards.filter(c => c.abilities.includes("spy") || c.abilities.includes("emissary")) + }; + if (owncards.cards.length === 0 || spyCards.cards.length === 0) + return 0; + let weakestCard = owncards.cards.sort((a, b) => a.power - b.power)[0]; + if (weakestCard.power <= 7) { + return 15; + } + return 0; + } + }, + emhyr_invader: { + description: "Draw 1 unit or hero card from your opponent's discard pile and play it immediatly in opponent's favour at your discretion. Then draw one unit or hero card from your own discard pile and play it immediatly in your favour.", + activated: async card => { + let opcards = { cards: card.holder.opponent().grave.cards.filter(c => c.isUnit() || c.hero) }; + let owncards = { cards: card.holder.grave.cards.filter(c => c.isUnit() || c.hero) }; + + if (opcards.cards.length > 0) { + if (card.holder.controller instanceof ControllerAI) { + // Pick weakest card from OP grave and play it + let c = card.holder.opponent().getAIController().getLowestWeightCard(opcards.cards); + card.holder.opponent().grave.removeCard(c); + card.holder.opponent().grave.addCard(c); + await c.autoplay(card.holder.opponent().grave); + if (owncards.cards.length > 0) { + // Pick best card from own grave and play it + c = card.holder.controller.getHighestWeightCard(owncards.cards); + card.holder.grave.removeCard(c); + card.holder.grave.addCard(c); + await c.autoplay(card.holder.grave); + } + } else { + let op_card = null, own_card = null; + let backup_mode = game.mode; + game.mode = 3; // Briefly set as PvP to be able to intereact with the opponent's board + await ui.queueCarousel(opcards, 1, (c, i) => op_card = c.cards[i], c => true, true, false, "Which opponent card to restore from the grave?"); + // Move from grave to hand + card.holder.opponent().grave.removeCard(op_card); + card.holder.opponent().hand.addCard(op_card); + // Enable board interaction - Force to select a destination + ui.showPreviewVisuals(op_card); + document.getElementById("click-background").classList.add("noclick"); + card.holder.hand.cards.forEach(c => c.elem.classList.add("noclick")); + ui.setSelectable(op_card, true); + game.mode = backup_mode; + // When play OP card, don't end the turn but switch to the other card selection + if (owncards.cards.length > 0) { + card.holder.opponent().endturn_action = async () => { + card.holder.opponent().endturn_action = null; + await ui.queueCarousel(owncards, 1, (c, i) => own_card = c.cards[i], c => true, true, false, "Which card to restore from your grave?"); + // Move from grave to hand + card.holder.grave.removeCard(own_card); + card.holder.hand.addCard(own_card); + // Enable board interaction - Force to select a destination + ui.showPreviewVisuals(own_card); + document.getElementById("click-background").classList.add("noclick"); + card.holder.hand.cards.forEach(c => c.elem.classList.add("noclick")); + ui.setSelectable(own_card, true); + ui.enablePlayer(true); + }; + } + // Prevent the end of turn while selecting cards + card.holder.endturn_action = async () => { + card.holder.endturn_action = null; + } + ui.enablePlayer(true); + } + } + }, + weight: (card, ai, max, data) => { + let opcards = { cards: card.holder.opponent().grave.cards.filter(c => c.isUnit() || c.hero) }; + let owncards = { cards: card.holder.grave.cards.filter(c => c.isUnit() || c.hero) }; + + if (opcards.cards.length == 0 || owncards.cards.length == 0) + return 0; + return Math.max(0, card.holder.controller.getHighestWeightCard(owncards.cards).power - card.holder.opponent().getAIController().getLowestWeightCard(opcards.cards).power) + + } + }, + eredin_commander: { + description: "Double the strength of all your Close Combat units (unless a Commander's horn is also present on that row).", + activated: async card => await board.getRow(card, "close", card.holder).leaderHorn(card), + weight: (card, ai) => ai.weightHornRow(card, board.getRow(card, "close", card.holder)) + }, + eredin_bringer_of_death: { + name: "Eredin : Bringer of Death", + description: "Restore a unit card from your discard pile to your hand.", + activated: async card => { + let newCard; + if (card.holder.controller instanceof ControllerAI) { + newCard = card.holder.controller.medic(card, card.holder.grave); + } else { + try { + Carousel.curr.exit(); + } catch (err) { } + await ui.queueCarousel(card.holder.grave, 1, (c, i) => newCard = c.cards[i], c => c.isUnit(), false, false); + } + if (newCard) + await board.toHand(newCard, card.holder.grave); + }, + weight: (card, ai, max, data) => ai.weightMedic(data, 0, card.holder) + }, + eredin_destroyer: { + description: "Discard 2 cards and draw 1 card of your choice from your deck.", + activated: async (card) => { + let hand = board.getRow(card, "hand", card.holder); + let deck = board.getRow(card, "deck", card.holder); + if (card.holder.controller instanceof ControllerAI) { + let cards = card.holder.controller.discardOrder(card, card.holder.hand, true).splice(0, 2).filter(c => c.basePower < 7); + await Promise.all(cards.map(async c => await board.toGrave(c, card.holder.hand))); + card.holder.deck.draw(card.holder.hand); + return; + } else { + try { + Carousel.curr.exit(); + } catch (err) { } + } + await ui.queueCarousel(hand, 2, (c, i) => board.toGrave(c.cards[i], c), () => true); + await ui.queueCarousel(deck, 1, (c, i) => board.toHand(c.cards[i], deck), () => true, true); + }, + weight: (card, ai) => { + let cards = ai.discardOrder(card, card.holder.hand, true).splice(0, 2).filter(c => c.basePower < 7); + if (cards.length < 2) + return 0; + return cards[0].abilities.includes("muster") ? 50 : 25; + } + }, + eredin_king: { + description: "Pick any weather card from your deck and play it instantly.", + activated: async card => { + let deck = board.getRow(card, "deck", card.holder); + if (card.holder.controller instanceof ControllerAI) { + await ability_dict["eredin_king"].helper(card).card.autoplay(card.holder.deck); + } else { + try { + Carousel.curr.cancel(); + } catch (err) { } + await ui.queueCarousel(deck, 1, (c, i) => board.toWeather(c.cards[i], deck), c => c.faction === "weather", true); + } + }, + weight: (card, ai, max) => ability_dict["eredin_king"].helper(card).weight, + helper: card => { + let weather = card.holder.deck.cards.filter(c => c.row === "weather").reduce((a, c) => a.map(c => c.name).includes(c.name) ? a : a.concat([c]), []); + + let out, weight = -1; + weather.forEach(c => { + let w = card.holder.controller.weightWeatherFromDeck(c, c.abilities[0]); + if (w > weight) { + weight = w; + out = c; + } + }); + return { + card: out, + weight: weight + }; + } + }, + eredin_treacherous: { + description: "Doubles the strength of all spy cards (affects both players).", + gameStart: () => game.spyPowerMult = 2 + }, + francesca_queen: { + description: "Destroy your enemy's strongest Close Combat unit(s) if the combined strength of all his or her Close Combat units is 10 or more.", + activated: async card => await ability_dict["scorch_c"].placed(card), + weight: (card, ai, max) => ai.weightScorchRow(card, max, "close") + }, + francesca_beautiful: { + description: "Doubles the strength of all your Ranged Combat units (unless a Commander's Horn is also present on that row).", + activated: async card => await board.getRow(card, "ranged", card.holder).leaderHorn(card), + weight: (card, ai) => ai.weightHornRow(card, board.getRow(card, "ranged", card.holder)) + }, + francesca_daisy: { + description: "At the beginning of the game, draw from your deck 13 cards instead of 10. Choose 2 of them and shuffle them back into the deck and start the round with these 11 cards.", + placed: card => game.gameStart.push(() => { + card.holder.disableLeader(); + for (var i = 0; i < 3; i++) { + card.holder.deck.draw(card.holder.hand); + } + return true; + }) + }, + francesca_pureblood: { + description: "Choose 3 or less unit and/or hero cards, which lie on the opponent's battlefield. Move these cards to any other opponent's row (rows).", + activated: async card => { + if (card.holder.controller instanceof ControllerAI) { + // We proceed iteratively because a same card might come up several times with a high weight, but we choose only 1 option + // Also each change can affect the effect of later changes + for (var i = 0; i < 3; i++) { + let action = card.holder.controller.weightAllCardsRowChanges(card.holder.opponent(), false)[0]; + await board.moveToNoEffects(action.card, action.row, action.card.currentLocation ); + } + } else { + card.holder.endTurnAfterAbilityUse = false; + ui.enableBoardRearrangement(card.holder.opponent(), 3); + } + }, + weight: (card, ai) => { + if (card.holder.opponent().getAllRowCards().length < 3) + return 0; + // It's not very accurate since a same card might come up several times in top results, might be counted several times + return ai.weightAllCardsRowChanges(card.holder.opponent(), false).slice(0, 3).reduce((t, v) => t - v.score,0); + } + }, + francesca_hope: { + description: "Choose 4 or less unit and/or hero cards, which lie on your battlefield. Move these cards to your any other row (rows).", + activated: async card => { + if (card.holder.controller instanceof ControllerAI) { + // We proceed iteratively because a same card might come up several times with a high weight, but we choose only 1 option + // Also each change can affect the effect of later changes + for (var i = 0; i < 4; i++) { + let action = card.holder.controller.weightAllCardsRowChanges(card.holder, true)[0]; + await board.moveToNoEffects(action.card, action.row, action.card.currentLocation); + } + } else { + card.holder.endTurnAfterAbilityUse = false; + ui.enableBoardRearrangement(card.holder, 4); + } + }, + weight: (card, ai) => { + if (card.holder.getAllRowCards().length < 4) + return 0; + // It's not very accurate since a same card might come up several times in top results, might be counted several times + return ai.weightAllCardsRowChanges(card.holder, true).slice(0, 4).reduce((t, v) => t + v.score,0); + } + }, + crach_an_craite: { + description: "Shuffle all cards from each player's graveyard back into their decks. You can keep one of the cards in the graveyard.", + activated: async card => { + let targetCard = null; + if (card.holder.controller instanceof ControllerAI) { + let medics = card.holder.hand.findCard(c => c.abilities.includes("medic")); + if (medics !== undefined) { + let spies = card.holder.grave.findCard(c => c.abilities.includes("spy")); + if (spies !== undefined) { + targetCard = spies; + } else { + targetCard = card.holder.controller.getHighestWeightCard(card.holder.grave.cards); + } + } + } else { + let c = await ui.popup("Keep a card [E]", (p) => p.choice = true, "Shuffle them all [Q]", (p) => p.choice = false, "Keep one card in the grave?", "Would you like to select a card to keep in your graveyard?"); + if (c) { + try { + Carousel.curr.cancel(); + } catch (err) { } + await ui.queueCarousel(card.holder.grave, 1, (c, i) => targetCard = c.cards[i], c => true, true); + } + } + + Promise.all(card.holder.grave.cards.filter(c => c !== targetCard).map(c => board.toDeck(c, card.holder.grave))); + await Promise.all(card.holder.opponent().grave.cards.map(c => board.toDeck(c, card.holder.opponent().grave))); + }, + weight: (card, ai, max, data) => { + if (game.roundCount < 2) + return 0; + let medics = card.holder.hand.findCard(c => c.abilities.includes("medic")); + if (medics !== undefined) + return 0; + let spies = card.holder.hand.findCard(c => c.abilities.includes("spy")); + if (spies !== undefined) + return 0; + if (card.holder.hand.findCard(c => c.abilities.includes("decoy")) !== undefined && (data.medic.length || data.spy.length && card.holder.deck.findCard(c => c.abilities.includes("medic")) !== undefined)) + return 0; + return 15; + } + }, + king_bran: { + description: "Once per game at the beginning of any round draw a Skellige Storm from your deck. In this round, all your cards will lose only half of their weather.", + placed: card => { + card.holder.disableLeader(); + game.roundStart.push(async () => { + let activate = false; + if (card.holder.controller instanceof ControllerAI) { + let rand = randomInt(1); + if (rand > 0 || game.roundCount > 2) { + activate = true; + } + } else { + activate = await ui.popup("Bring the Storm [E]", (p) => p.choice = true, "Maybe later [Q]", (p) => p.choice = false, "Bring the Skellige Storm?", "Would you like to draw a Skellige Storm card from your deck and halve weather effects over your units?"); + } + if (activate) { + // Set half weather effect + card.holder.getAllRows().forEach(r => r.halfWeather = true); + game.roundStart.push(async () => { + card.holder.getAllRows().forEach(r => r.halfWeather = false); + return true; + }); + // Now draw the card + let targetCard = card.holder.deck.findCard(c => c.key == "spe_storm"); + if (targetCard) { + await board.toHand(targetCard, card.holder.deck); + } + return true; + } + return false; + }); + } + }, + birna: { + description: "Draw from your deck any card with Mardroeme or Werewolf ability and play it immediatly.", + activated: async card => { + let targetCard = null; + if (card.holder.controller instanceof ControllerAI) { + let berserkers = card.holder.deck.cards.filter(c => c.abilities.includes("berserker")); + let mard = card.holder.deck.cards.filter(c => c.abilities.includes("mardroeme")); + let ownedberserkers = card.holder.hand.cards.filter(c => c.abilities.includes("berserker")).concat(card.holder.getAllRowCards().filter(c => c.abilities.includes("berserker"))); + let ownedmard = card.holder.hand.cards.filter(c => c.abilities.includes("mardroeme")) + .concat(card.holder.getAllRowCards().filter(c => c.abilities.includes("mardroeme"))) + .concat(card.holder.getAllSpecialRowCards().filter(c => c.abilities.includes("mardroeme"))); + // We try to pick a card we are missing + if (ownedberserkers.length > 0 && ownedmard.length == 0 && mard.length > 0) { + targetCard = mard[0]; + } else if (ownedberserkers.length == 0 && ownedmard.length > 0 && berserkers.length > 0) { + targetCard = berserkers.sort((a,b) => b.basePower - a.basePower)[0]; + } else if (berserkers.length > 0) { + targetCard = berserkers.sort((a, b) => b.basePower - a.basePower)[0]; + } else { + targetCard = mard[0]; + } + if (targetCard) { + // Move from deck to hand + card.holder.deck.removeCard(targetCard); + card.holder.hand.addCard(targetCard); + let rows = targetCard.getPlayableRows(); + // Lazy approach, can be improved + await card.holder.playCardToRow(targetCard, rows[0], false); + } + } else { + try { + Carousel.curr.cancel(); + } catch (err) { } + await ui.queueCarousel(card.holder.deck, 1, (c, i) => targetCard = c.cards[i], c => c.abilities.includes("berserker") || c.abilities.includes("mardroeme"), true); + // let player select where to play the card + card.holder.selectCardDestination(targetCard, card.holder.deck); + } + }, + weight: (card, ai) => { + return 10; + } + }, + madman_lugos: { + description: "Once per game at the beginning of any round your opponent must show you 2 random cards in his hand. Pick one of them and discard it.", + placed: card => { + card.holder.disableLeader(); + game.roundStart.push(async () => { + let activate = false; + if (card.holder.controller instanceof ControllerAI) { + let rand = randomInt(1); + if (rand > 0 || game.roundCount > 2) { + activate = true; + } + } else { + activate = await ui.popup("Discard a card [E]", (p) => p.choice = true, "Maybe later [Q]", (p) => p.choice = false, "Discard a card from the hand of the opponent?", "Would you like to see 2 random cards from the hand of your opponent and discard one of them?"); + } + if (activate) { + // Get 2 random cards + let candidates = { cards: card.holder.opponent().hand.findCardsRandom(c => true, 2) }; + let targetCard = null; + if (card.holder.controller instanceof ControllerAI) { + // Lazy approach, not weighting the cards + if (candidates.cards.length > 0) + targetCard = candidates.cards[0]; + } else { + await ui.queueCarousel(candidates, 1, (c, i) => targetCard = c.cards[i], c => true, true, false, "Which card to discard?"); + } + if (targetCard) { + await board.toGrave(targetCard, card.holder.opponent().hand); + } + return true; + } + return false; + }); + }, + weight: (card, ai) => { + if (card.holder.opponent().hand.cards.length < 2 || card.holder.opponent().hand.cards.length > 5) + return 8; + return 12; + } + }, + holger_blakhand: { + description: "After one of your turn you can select a card and change its strength to any other. Effect will last until the end of round scoring when strength returns to the previous value. This ability can be used twice per battle.", + placed: card => { + card.holder.disableLeader(); + card.holder.capabilities["cardEdit"] = 2; + + game.turnEnd.push(async () => { + if (card.holder.passed || game.currPlayer !== card.holder || card.holder.getAllRowCards().length == 0) + return false; + if (card.holder.capabilities["cardEdit"] < 1) + return true; + let activate = false; + if (card.holder.controller instanceof ControllerAI) { + if (card.holder.opponent().passed) + return false; + let targetCard = null; + let targetValue = 0; + let avengers = card.holder.getAllRowCards().filter(c => c.abilities.includes("avenger")); + if (avengers.length > 0) { + targetCard = avengers[0]; + targetValue = 40; + } + // If we have a summon avenger, let's try to have it killed + let maxCards = card.holder.getAllRowCards().filter(c => c.isUnit()).reduce((a, c) => (!a.length || a[0].power < c.power) ? [c] : a[0].power === c.power ? a.concat([c]) : a, []); + if (!targetCard && maxCards.length > 0) { + // If several cards with max value and sum higher than 9 => easy target for scorch, protect with another weaker card set to a high value + if (maxCards.length > 1 && maxCards.reduce((a, c) => a += c.power, 0) > 9) { + targetCard = card.holder.getAllRowCards().filter(c => c.isUnit()).sort((a, b) => a.power - b.power)[0]; + targetValue = 4 * maxCards[0].power; + // If 1 very strong card, protect with another weaker card set to a high value OR lower the stronger card + } else if (maxCards.length == 1 && maxCards[0].power > 9) { + targetCard = card.holder.getAllRowCards().filter(c => c.isUnit()).sort((a, b) => a.power - b.power)[0]; + if (targetCard.power < 6) { + targetValue = 3 * maxCards[0].power; + } else { + targetCard = maxCards[0]; + targetValue = 0; + } + } + } + if (targetCard) { + if (!targetCard.originalBasePower) + targetCard.originalBasePower = targetCard.basePower; + targetCard.basePower = targetValue; + targetCard.temporaryPower = true; + card.holder.capabilities["cardEdit"] -= 1; + } + if (card.holder.capabilities["cardEdit"] < 1) + return true; + } else { + activate = await ui.popup("Change a card's strength [E]", (p) => p.choice = true, "Maybe later [Q]", (p) => p.choice = false, "Change the strengh of a card?", "Would you like to change the strengh of a card? It will be reset at the end of the rounf before scoring."); + } + if (activate && !card.holder.controller instanceof ControllerAI) { + ui.enableCardPowerEdit(card.holder); + } + return false; + }); + }, + weight: (card, ai) => { + let maxCards = card.holder.getAllRowCards().filter(c => c.isUnit()).reduce((a, c) => (!a.length || a[0].power < c.power) ? [c] : a[0].power === c.power ? a.concat([c]) : a, []); + let sum = maxCards.reduce((a, c) => a += c.power, 0); + if (sum > 9) + return sum; + return 0; + } + }, + radovid_king_redania: { + description: "Draw three cards from your deck. Play one of them immediatly, shuffle the other two back into the deck.", + activated: async card => { + let cards = { cards: card.holder.deck.cards.slice(0, 3) }; + let targetCard = null; + if (card.holder.controller instanceof ControllerAI) { + targetCard = card.holder.controller.getHighestWeightCard(cards.cards); + } else { + try { + Carousel.curr.cancel(); + } catch (err) { } + await ui.queueCarousel(cards, 1, (c, i) => targetCard = c.cards[i], c => true, true, false, "Choose the card to draw and play immediatly"); + } + cards.cards.forEach(c => { + if (c === targetCard) { + if (card.holder.controller instanceof ControllerAI) { + targetCard.autoplay(card.holder.deck); + } else { + // let player select where to play the card + card.holder.selectCardDestination(targetCard, card.holder.deck); + } + } else { + // Remove to shuffle back at a random place (default behaviour on addCard in deck) + card.holder.deck.removeCard(c); + card.holder.deck.addCard(c); + } + }); + }, + weight: (card, ai) => { + let musters = card.holder.hand.cards.filter(c => c.abilities.includes("muster")); + // It's not as beneficial to draw when we have muster cards in hand (since we might draw one of the related muster card) + if (musters && musters.length > 0) { + return 5; + } + return 15; + } + }, + radovid_mad_king: { + description: "Destroy the strongest card on the battlefield (it must be a unit or a hero). If there are several strongest cards, choose and destroy only one of them.", + activated: async card => { + let maxCards = card.holder.getAllRowCards().filter(c => c.hero || c.isUnit()) + .concat(card.holder.opponent().getAllRowCards().filter(c => c.hero || c.isUnit())) + .reduce((a, c) => (!a.length || a[0].power < c.power) ? [c] : a[0].power === c.power ? a.concat([c]) : a, []); + if (maxCards.length == 0) + return false; + let targetCard = null; + if (card.holder.controller instanceof ControllerAI) { + let opMax = maxCards.filter(c => c.holder === card.holder.opponent()); + if (opMax.length == 0) + return false; + targetCard = opMax[0]; + } else { + if (maxCards.length == 1) { + targetCard = maxCards[0]; + } else { + try { + Carousel.curr.cancel(); + } catch (err) { } + await ui.queueCarousel({ cards: maxCards }, 1, (c, i) => targetCard = c.cards[i], c => true, true, false, "Choose the card to destroy"); + } + } + if (targetCard) { + await targetCard.animate("scorch", true, false); + await board.toGrave(targetCard, targetCard.currentLocation); + } + }, + weight: (card, ai) => { + let maxCards = card.holder.getAllRowCards().filter(c => c.hero || c.isUnit()) + .concat(card.holder.opponent().getAllRowCards().filter(c => c.hero || c.isUnit())) + .reduce((a, c) => (!a.length || a[0].power < c.power) ? [c] : a[0].power === c.power ? a.concat([c]) : a, []); + if (maxCards.length < 1) + return 0; + for (var i = 0; i < maxCards.length; i++) { + if (maxCards[i].holder === card.holder.opponent()) + return maxCards[i].power; + } + return 0; + } + }, + radovid_strategist: { + description: "Choose one hero card on your battlefield. Take it back to your hand.", + activated: async card => { + let heros = { cards: card.holder.getAllRowCards().filter(c => c.hero) }; + if (heros.cards.length == 0) + return false; + let targetCard = null; + if (card.holder.controller instanceof ControllerAI) { + targetCard = heros.cards[0]; + } else { + try { + Carousel.curr.cancel(); + } catch (err) { } + await ui.queueCarousel(heros, 1, (c, i) => targetCard = c.cards[i], c => true, true,false, "Choose the hero to take back into your hand"); + } + if (targetCard) { + board.toHand(targetCard, targetCard.currentLocation); + } + return true; + }, + weight: (card, ai) => { + let heros = card.holder.getAllRowCards().filter(c => c.hero); + if (heros.length < 1) + return 0; + return 5; + } + }, + anna_henrietta_duchess: { + description: "Pick one hero card from your grave and play it immediatly.", + activated: async card => { + let heros = card.holder.grave.cards.filter(c => c.hero).sort((a,b) => b.power - a.power); + if (heros.length == 0) + return false; + let targetCard = null; + if (card.holder.controller instanceof ControllerAI) { + targetCard = heros[0]; // Strongest should be first + targetCard.autoplay(card.holder.grave); + } else { + await ui.queueCarousel({ cards: heros }, 1, (c, i) => targetCard = c.cards[i], c => true, true, false, "Choose the hero to play"); + if (targetCard) { + // let player select where to play the card + card.holder.selectCardDestination(targetCard, card.holder.grave); + } + } + return true; + }, + weight: (card, ai) => { + return 10; + } + }, + anna_henrietta_ladyship: { + description: "Pick any second form of Monster of Toussaint, which already lies on the battlefield. Remove it from the game then play immediatly its weaker form. Later, you can turn the first form into the second again.", + activated: async card => { + let l2monsters = card.holder.getAllRowCards().filter(c => c.meta.includes("toussaint_monster_level_2")); + if (l2monsters.length == 0) + return false; + let targetCard = null; + if (card.holder.controller instanceof ControllerAI) { + targetCard = l2monsters[0]; + } else { + await ui.queueCarousel({ cards: l2monsters }, 1, (c, i) => targetCard = c.cards[i], c => true, true, false, "Choose the monster to revert to its primal form."); + } + if (targetCard) { + let newCard = new Card(targetCard.target, card_dict[targetCard.target], card.holder); + targetCard.currentLocation.removeCard(targetCard); + card.holder.deck.addCard(newCard); + if (card.holder.controller instanceof ControllerAI) { + newCard.autoplay(card.holder.deck); + } else { + // let player select where to play the card + card.holder.selectCardDestination(newCard, card.holder.deck); + } + return true; + } + return false; + }, + weight: (card, ai) => { + let l2monsters = card.holder.getAllRowCards().filter(c => c.meta.includes("toussaint_monster_level_2")); + if (l2monsters.length == 0) + return 0; + return 10; + } + }, + anna_henrietta_little_weasel: { + description: "Choose an enemy hero card and remove its Hero status.", + activated: async card => { + let heros = card.holder.opponent().getAllRowCards().filter(c => c.hero).sort((a, b) => b.power - a.power); + if (heros.length == 0) + return false; + let targetCard = null; + if (card.holder.controller instanceof ControllerAI) { + targetCard = heros[0]; // should be the strongest + } else { + await ui.queueCarousel({ cards: heros }, 1, (c, i) => targetCard = c.cards[i], c => true, true, false, "Choose the enemy hero to demote."); + } + if (targetCard) { + targetCard.hero = false; + let el = targetCard.createCardElem(targetCard); + targetCard.elem.replaceWith(el); + targetCard.elem = el; + } + return true; + }, + weight: (card, ai) => { + return 8; + } + }, + lady_wood_brewess: { + description: "Each time when your faction ability triggers, draw two cards instead of one. Play one of them, another one shuffle back into your deck.", + placed: card => card.holder.velenCardDraw = 2 + }, + lady_wood_weavess: { + description: "Draw a Curse card from your deck and play it immediatly.", + gameStart: () => game.spyPowerMult = 1 + }, + lady_wood_whispess: { + description: "Take from your discard pile in your hand 3 or less unit cards, that died in the current round.", + gameStart: () => game.spyPowerMult = 1 + }, + ghost_tree: { + description: "Destroy the weakest unit card on the battlefield (any player). If there are several, choose one.", + gameStart: () => game.spyPowerMult = 1 + }, + queen_calanthe: { + description: "Play a unit then draw a card from you deck.", + activated: async card => { + let units = card.holder.hand.cards.filter(c => c.isUnit()); + if (units.length === 0) + return; + let wrapper = { + card: null + }; + if (card.holder.controller instanceof ControllerAI) { + wrapper.card = units[randomInt(units.length)]; + } else { + await ui.queueCarousel(board.getRow(card, "hand", card.holder), 1, (c, i) => wrapper.card = c.cards[i], c => c.isUnit(), true); + } + wrapper.card.autoplay(); + card.holder.hand.removeCard(wrapper.card); + if (card.holder.deck.cards.length > 0) + await card.holder.deck.draw(card.holder.hand); + }, + weight: (card, ai) => { + let units = card.holder.hand.cards.filter(c => c.isUnit()); + if (units.length === 0) + return 0; + return 15; + } + }, + fake_ciri: { + description: "Discard a card from your hand and then draw two cards from your deck.", + activated: async card => { + if (card.holder.hand.cards.length === 0) + return; + let hand = board.getRow(card, "hand", card.holder); + if (card.holder.controller instanceof ControllerAI) { + let cards = card.holder.controller.discardOrder(card, card.holder.hand, true).splice(0, 1).filter(c => c.basePower < 7); + await Promise.all(cards.map(async c => await board.toGrave(c, card.holder.hand))); + } else { + try { + Carousel.curr.exit(); + } catch (err) { } + await ui.queueCarousel(hand, 1, (c, i) => board.toGrave(c.cards[i], c), () => true); + } + + for (let i = 0; i < 2; i++) { + if (card.holder.deck.cards.length > 0) + await card.holder.deck.draw(card.holder.hand); + } + }, + weight: (card, ai) => { + if (card.holder.hand.cards.length === 0) + return 0; + return 15; + } + }, + radovid_stern: { + description: "Discard 2 cards and draw 1 card of your choice from your deck.", + activated: async (card) => { + let hand = board.getRow(card, "hand", card.holder); + let deck = board.getRow(card, "deck", card.holder); + if (card.holder.controller instanceof ControllerAI) { + let cards = card.holder.controller.discardOrder(card, card.holder.hand, true).splice(0, 2).filter(c => c.basePower < 7); + await Promise.all(cards.map(async c => await board.toGrave(c, card.holder.hand))); + card.holder.deck.draw(card.holder.hand); + return; + } else { + try { + Carousel.curr.exit(); + } catch (err) { } + } + await ui.queueCarousel(hand, 2, (c, i) => board.toGrave(c.cards[i], c), () => true); + await ui.queueCarousel(deck, 1, (c, i) => board.toHand(c.cards[i], deck), () => true, true); + }, + weight: (card, ai) => { + let cards = ai.discardOrder(card, card.holder.hand, true).splice(0, 2).filter(c => c.basePower < 7); + if (cards.length < 2) + return 0; + return cards[0].abilities.includes("muster") ? 50 : 25; + } + }, + radovid_ruthless: { + description: "Cancel the scorch ability for one round", + activated: async card => { + game.scorchCancelled = true; + await ui.notification("north-scorch-cancelled", 1200); + game.roundStart.push(async () => { + game.scorchCancelled = false; + return true; + }); + } + }, + vilgefortz_magician_kovir: { + description: "Halves the strength of all spy cards (affects both players).", + gameStart: () => game.spyPowerMult = 0.5 + }, + cosimo_malaspina: { + description: "Destroy your enemy's strongest Melee unit(s) if the combined strength of all his or her Melee units is 10 or more.", + activated: async card => await ability_dict["scorch_c"].placed(card), + weight: (card, ai, max) => ai.weightScorchRow(card, max, "close") + }, + resilience: { + name: "Resilience", + description: "Remains on the board for the following round if another unit on your side of the board had an ability in common.", + placed: async card => { + game.roundEnd.push(async () => { + if (card.isLocked()) + return; + let units = card.holder.getAllRowCards().filter(c => c.abilities.includes(card.abilities.at(-1))); + if (units.length < 2) + return; + card.noRemove = true; + await card.animate("resilience"); + game.roundStart.push(async () => { + delete card.noRemove; + let school = card.abilities.at(-1); + if (!card.holder.effects["witchers"][school]) + card.holder.effects["witchers"][school] = 0 + card.holder.effects["witchers"][school]++; + return true; + }); + }); + } + }, + witcher_wolf_school: { + name: "Wolf School of Witchers", + description: "Each unit of this witcher school is boosted by 2 for each card of this given school.", + placed: async card => { + let school = card.abilities.at(-1); + if (!card.holder.effects["witchers"][school]) + card.holder.effects["witchers"][school] = 0 + card.holder.effects["witchers"][school]++; + }, + removed: async card => { + let school = card.abilities.at(-1); + card.holder.effects["witchers"][school]--; + } + }, + witcher_viper_school: { + name: "Viper School of Witchers", + description: "Each unit of this witcher school is boosted by 2 for each card of this given school.", + placed: async card => { + let school = card.abilities.at(-1); + if (!card.holder.effects["witchers"][school]) + card.holder.effects["witchers"][school] = 0 + card.holder.effects["witchers"][school]++; + }, + removed: async card => { + let school = card.abilities.at(-1); + card.holder.effects["witchers"][school]--; + } + }, + witcher_bear_school: { + name: "Bear School of Witchers", + description: "Each unit of this witcher school is boosted by 2 for each card of this given school.", + placed: async card => { + let school = card.abilities.at(-1); + if (!card.holder.effects["witchers"][school]) + card.holder.effects["witchers"][school] = 0 + card.holder.effects["witchers"][school]++; + }, + removed: async card => { + let school = card.abilities.at(-1); + card.holder.effects["witchers"][school]--; + } + }, + witcher_cat_school: { + name: "Cat School of Witchers", + description: "Each unit of this witcher school is boosted by 2 for each card of this given school.", + placed: async card => { + let school = card.abilities.at(-1); + if (!card.holder.effects["witchers"][school]) + card.holder.effects["witchers"][school] = 0 + card.holder.effects["witchers"][school]++; + }, + removed: async card => { + let school = card.abilities.at(-1); + card.holder.effects["witchers"][school]--; + } + }, + witcher_griffin_school: { + name: "Griffin School of Witchers", + description: "Each unit of this witcher school is boosted by 2 for each card of this given school.", + placed: async card => { + let school = card.abilities.at(-1); + if (!card.holder.effects["witchers"][school]) + card.holder.effects["witchers"][school] = 0 + card.holder.effects["witchers"][school]++; + }, + removed: async card => { + let school = card.abilities.at(-1); + card.holder.effects["witchers"][school]--; + } + }, + shield: { + name: "Shield", + description: "Protects units in the row from all abilities except weather effects.", + weight: (card) => 30 + }, + seize: { + name: "Seize", + description: "Move the Melee unit(s) with the lowest strength on your side of the board/ Their abilities won't work anymore.", + activated: async card => { + let opCloseRow = board.getRow(card, "close", card.holder.opponent()); + let meCloseRow = board.getRow(card, "close", card.holder); + if (opCloseRow.isShielded()) + return; + let units = opCloseRow.minUnits(); + if (units.length === 0) + return; + await Promise.all(units.map(async c => await c.animate("seize"))); + units.forEach(async c => { + c.holder = card.holder; + await board.moveToNoEffects(c, meCloseRow, opCloseRow); + }); + await board.toGrave(card, card.holder.hand); + }, + weight: (card) => { + if (card.holder.opponent().getAllRows()[0].isShielded()) + return 0; + return card.holder.opponent().getAllRows()[0].minUnits().reduce((a, c) => a + c.power, 0) * 2 + } + }, + lock: { + name: "Lock", + description: "Lock/cancels the ability of the next unit played in that row (ignores units without abilities and heroes).", + weight: (card) => 20 + }, + knockback: { + name: "Knockback", + description: "Pushes all units of the selected row (Melee or Ranged) or row back towards the Siege row, ignores shields.", + activated: async (card, row) => { + let units = row.findCards(c => c.isUnit()); + if (units.length > 0) { + let targetRow; + for (var i = 0; i < board.row.length; i++) { + if (board.row[i] === row) { + if (i < 3) + targetRow = board.row[Math.max(0, i - 1)]; + else + targetRow = board.row[Math.min(5, i + 1)]; + } + } + await Promise.all(units.map(async c => await c.animate("knockback"))); + units.map(async c => { + if (c.abilities.includes("bond") || c.abilities.includes("morale") || c.abilities.includes("horn")) // Exception for bond cards, these abilities should continue to work after + await board.moveTo(c, targetRow, row); + else + await board.moveToNoEffects(c, targetRow, row); + }); + + + } + await board.toGrave(card, card.holder.hand); + }, + weight: (card) => { + if (board.getRow(card, "close", card.holder.opponent()).cards.length + board.getRow(card, "ranged", card.holder.opponent()).cards.length === 0) + return 0; + let score = 0; + if (board.getRow(card, "close", card.holder.opponent()).cards.length > 0 && (board.getRow(card, "close", card.holder.opponent()).effects.horn > 0 || board.getRow(card, "ranged", card.holder.opponent()).effects.weather || Object.keys(board.getRow(card, "close", card.holder.opponent()).effects.bond).length > 1 || board.getRow(card, "close", card.holder.opponent()).isShielded())) + score = Math.floor(board.getRow(card, "close", card.holder.opponent()).cards.filter(c => c.isUnit()).reduce((a, c) => a + c.power, 0) * 0.5); + if (board.getRow(card, "ranged", card.holder.opponent()).cards.length > 0 && (board.getRow(card, "ranged", card.holder.opponent()).effects.horn > 0 || board.getRow(card, "siege", card.holder.opponent()).effects.weather || Object.keys(board.getRow(card, "ranged", card.holder.opponent()).effects.bond).length > 1 || board.getRow(card, "ranged", card.holder.opponent()).isShielded())) + score = Math.floor(board.getRow(card, "close", card.holder.opponent()).cards.filter(c => c.isUnit()).reduce((a, c) => a + c.power, 0) * 0.5); + return Math.max(1, score); + } + }, + alzur_maker: { + description: "Destroy one of your units on the board and summon a Koshchey.", + activated: (card, player) => { + player.endTurnAfterAbilityUse = false; + ui.showPreviewVisuals(card); + ui.enablePlayer(true); + if (!(player.controller instanceof ControllerAI)) + ui.setSelectable(card, true); + }, + target: "wu_koshchey", + weight: (card, ai, max) => { + if (ai.player.getAllRowCards().filter(c => c.isUnit()).length === 0) + return 0; + return ai.weightScorchRow(card, max, "close"); + } + }, + vilgefortz_sorcerer: { + description: "Clear all weather effects in play.", + activated: async () => { + tocar("clear", false); + await weather.clearWeather() + }, + weight: (card, ai) => ai.weightCard(card_dict["spe_clear"]) + }, + toussaint_wine: { + name: "Toussaint Wine", + description: "Placed on Melee or Ranged row, boosts all units of the selected row by two. Limited to one per row.", + placed: async card => await card.animate("morale") + }, + meve_princess: { + description: "If the opponent has a total of 10 or higher on one row, destroy that row's strongest card(s) (affects only the opponent's side of the battle field).", + activated: async (card, player) => { + player.endTurnAfterAbilityUse = false; + ui.showPreviewVisuals(card); + ui.enablePlayer(true); + if (!(player.controller instanceof ControllerAI)) + ui.setSelectable(card, true); + }, + weight: (card, ai, max) => { + return Math.max(ai.weightScorchRow(card, max, "close"), ai.weightScorchRow(card, max, "ranged"), ai.weightScorchRow(card, max, "siege")); + } + }, + shield_c: { + name: "Melee Shield", + description: "Protects units in the Melee row from all abilities except weather effects.", + weight: (card) => 20 + }, + shield_r: { + name: "Ranged Shield", + description: "Protects units in the Ranged row from all abilities except weather effects.", + weight: (card) => 20 + }, + shield_s: { + name: "Siege Shield", + description: "Protects units in the Siege row from all abilities except weather effects.", + weight: (card) => 20 + }, + meve_white_queen: { + description: "All medic cards can choose two unit cards from the discard pile (affects both players).", + gameStart: () => game.medicCount = 2 + }, + carlo_varese: { + description: "If the opponent has a total of 10 or higher on one row, destroy that row's strongest card(s) (affects only the opponent's side of the battle field).", + activated: async (card, player) => { + player.endTurnAfterAbilityUse = false; + ui.showPreviewVisuals(card); + ui.enablePlayer(true); + if (!(player.controller instanceof ControllerAI)) + ui.setSelectable(card, true); + }, + weight: (card, ai, max) => { + return Math.max(ai.weightScorchRow(card, max, "close"), ai.weightScorchRow(card, max, "ranged"), ai.weightScorchRow(card, max, "siege")); + } + }, + francis_bedlam: { + description: "Send all spy unit cards to the grave of the side they are on.", + activated: async (card, player) => { + let op_spies = card.holder.opponent().getAllRowCards().filter(c => c.isUnit() && c.abilities.includes("spy")); + let me_spies = card.holder.getAllRowCards().filter(c => c.isUnit() && c.abilities.includes("spy")); + await op_spies.map(async c => await board.toGrave(c, c.currentLocation)); + await me_spies.map(async c => await board.toGrave(c, c.currentLocation)); + }, + weight: (card, ai, max) => { + let op_spies = card.holder.opponent().getAllRowCards().filter(c => c.isUnit() && c.abilities.includes("spy")).reduce((a, c) => a + c.power, 0); + let me_spies = card.holder.getAllRowCards().filter(c => c.isUnit() && c.abilities.includes("spy")).reduce((a, c) => a + c.power, 0); + return Math.max(0, op_spies - me_spies); + } + }, + cyprian_wiley: { + description: "Seize the unit(s) with the lowest strength of the opponents melee row.", + activated: async card => { + let opCloseRow = board.getRow(card, "close", card.holder.opponent()); + let meCloseRow = board.getRow(card, "close", card.holder); + if (opCloseRow.isShielded()) + return; + let units = opCloseRow.minUnits(); + if (units.length === 0) + return; + await Promise.all(units.map(async c => await c.animate("seize"))); + units.forEach(async c => { + c.holder = card.holder; + await board.moveToNoEffects(c, meCloseRow, opCloseRow); + }); + }, + weight: (card) => { + if (card.holder.opponent().getAllRows()[0].isShielded()) + return 0; + return card.holder.opponent().getAllRows()[0].minUnits().reduce((a, c) => a + c.power, 0) * 2 + } + }, + gudrun_bjornsdottir: { + description: "Summon Flyndr's Crew", + activated: async (card, player) => { + let new_card = new Card("sy_flyndr_crew", card_dict["sy_flyndr_crew"], player); + await board.addCardToRow(new_card, new_card.row, card.holder); + }, + weight: (card, ai, max) => { + return card.holder.getAllRows()[0].cards.length + Number(card_dict["sy_flyndr_crew"]["strength"]); + } + }, + cyrus_hemmelfart: { + description: "Play a Dimeritum Shackles card in any of the opponent's row.", + activated: async (card, player) => { + player.endTurnAfterAbilityUse = false; + ui.showPreviewVisuals(card); + ui.enablePlayer(true); + if (!(player.controller instanceof ControllerAI)) + ui.setSelectable(card, true); + }, + weight: (card) => 20 + }, + azar_javed: { + description: "Destroy the enemy's weakest hero card (max 1 card).", + activated: async (card, player) => { + let heroes = player.opponent().getAllRowCards().filter(c => c.hero); + if (heroes.length === 0) + return; + let target = heroes.sort((a, b) => a.power - b.power)[0]; + await target.animate("scorch", true, false) + await board.toGrave(target, target.currentLocation); + }, + weight: (card, ai, max) => { + let heroes = card.holder.opponent().getAllRowCards().filter(c => c.hero); + if (heroes.length === 0) + return 0; + return heroes.sort((a, b) => a.power - b.power)[0].power; + } + }, + bank: { + name: "Bank", + description: "Draw a card from your deck.", + activated: async card => { + card.holder.deck.draw(card.holder.hand); + await board.toGrave(card, card.holder.hand); + }, + weight: (card) => 20 + }, + witch_hunt: { + name: "Witch Hunt", + description: "Destroy the weakest unit on the opposite row. If there are several, choose one.", + placed: async card => { + let row = card.currentLocation.getOppositeRow(); + if (row.isShielded() || game.scorchCancelled) + return; + let units = row.minUnits(); + let targetCard = null; + if (units.length > 0) { + if (units.length == 1 || card.holder.controller instanceof ControllerAI) { + targetCard = units[0]; + } else { + try { + Carousel.curr.exit(); + } catch (err) { } + await ui.queueCarousel({ cards: units }, 1, (c, i) => targetCard = c.cards[i], () => true, true, false, "Choose which enemy card to destroy"); + } + } + if (targetCard) { + await targetCard.animate("scorch", true, false); + await board.toGrave(targetCard, row) + } + } + }, + zerrikanterment: { + description: "Amount of worshippers boost is doubled.", + gameStart: () => game.whorshipBoost *= 2 + }, + baal_zebuth: { + description: "Select 2 cards from your opponent's discard pile and shuffle them back into his/her deck.", + activated: async (card) => { + let grave = card.holder.opponent().grave; + if (card.holder.controller instanceof ControllerAI) { + let cards = grave.findCardsRandom(false, 2); + await Promise.all(cards.map(async c => await board.toDeck(c, c.holder.grave))); + return; + } else { + try { + Carousel.curr.exit(); + } catch (err) { } + await ui.queueCarousel(grave, 2, (c, i) => board.toDeck(c.cards[i], c), () => true); + } + + }, + weight: (card) => { + if (card.holder.opponent().grave.cards.length < 5) + return 0; + else + return 20; + } + }, + rarog: { + description: "Draw a random card from the discard pile to your hand (any card) and then shuffle the rest back into the deck.", + activated: async (card) => { + if (card.holder.grave.cards.length === 0) + return; + let grave = card.holder.grave; + let c = grave.findCardsRandom(false, 1)[0]; + await board.toHand(c, c.holder.grave); + Promise.all(card.holder.grave.cards.map(c => board.toDeck(c, card.holder.grave))); + }, + weight: (card) => { + let medics = card.holder.hand.cards.filter(c => c.abilities.includes("medic")); + if (medics.length > 0 || card.holder.grave.cards.length == 0) + return 0; + else + return 15; + } + }, + whorshipper: { + name: "Whorshipper", + description: "Boost by 1 all whorshipped units on your side of the board.", + placed: async card => { + if (card.isLocked()) + return; + card.holder.effects["whorshippers"]++; + }, + removed: async card => { + if (card.isLocked()) + return; + card.holder.effects["whorshippers"]--; + }, + weight: (card) => { + let wcards = card.holder.getAllRowCards().filter(c => c.abilities.includes("whorshipped")); + return wcards.length * game.whorshipBoost; + } + }, + whorshipped: { + name: "Whorshipped", + description: "Boosted by 1 by all whorshippers present on your side of the board.", + }, + inspire: { + name: "Inspire", + description: "All units with Inspire ability take the highest base strength of the Inspire units on your side of the board. Still affected by weather.", + }, + comrade: { + name: "Comrade", + description: "Once per round, this card can prevent the destruction of another card on its side of the board, including itself.", + placed: async card => { + if (card.isLocked()) + return; + card.protects = true; + return card; + } + }, + invoke: { + name: "Invoke", + description: "Invokes one of the available associated cards from the deck.", + placed: async (card) => { + if (card.isLocked()) + return; + let units = card.holder.deck.findCards(c => c.target === card.target && c.key !== card.key); + if (units.length === 0) + return; + await card.animate("invoke"); + await units[0].autoplay(card.holder.deck); + } + }, + emissary: { + name: "Emissary", + description: "Place on your opponent's battlefield (counts towards your opponent's total), either draw one card or look first 4 and put them back in order of choice, Once per round, some of these can be placed at the bottom.", + placed: async card => { + if (card.isLocked()) + return; + let c = 1; // AI choses 1 + if (!(card.holder.controller instanceof ControllerAI)) { + c = await ui.popup("Draw 1 card [E]", (p) => p.choice = 1, "Look first 4 cards [Q]", (p) => p.choice = 2, "Choose the effect of the emissary", "Either draw the first card of the deck or look the first 4 and order them back as you wish at the top or bottom of the deck."); + } + + await card.animate("emissary"); + if (c == 1) { + // Option 1 - Draw 1 card + if (card.holder.deck.cards.length > 0) { + // If can draw from opponent's deck and not AI + if (card.holder.capabilities["drawOPdeck"] > 0 && !(card.holder.controller instanceof ControllerAI)) { + let d = await ui.popup("Own deck [E]", (p) => p.choice = card.holder.deck, "Opponent's deck [Q]", (p) => { + p.choice = card.holder.opponent().deck; + card.holder.capabilities["drawOPdeck"] -= 1; + }, "Choose deck to draw from", "From which deck to draw the next card, your own or the opponent's deck (" + card.holder.capabilities["drawOPdeck"] + " left in this battle)?"); + await d.draw(card.holder.hand); + } else { + await card.holder.deck.draw(card.holder.hand); + } + } + } else { + if (card.holder.deck.cards.length > 0) { + await ui.startDeckSorter(card.holder.deck.cards.slice(0, Math.min(4, card.holder.deck.cards.length)), card.holder, null, "Re-order the cards back into the deck", true); + } + } + card.holder = card.holder.opponent(); + } + }, + necrophage: { + name: "Necrophage", + description: "Choose up to 2 unit cards from your discard pile and shuffle them back into your deck.", + placed: async card => { + if (card.isLocked()) + return; + let grave_units = { cards: card.holder.grave.cards.filter(c => c.isUnit()) }; + if (grave_units.cards.length == 0) + return; + if (card.holder.controller instanceof ControllerAI) { + let musters = grave_units.cards.filter(c => c.abilities.includes("muster")); + if (musters.length > 1) { + let groups = {}; + // Grouping Musters together + musters.forEach(curr => { + let name = curr.target; + if (!groups[name]) + groups[name] = []; + groups[name].push(curr); + }); + //Pick the strongest muster group with at least 3 cards (1 to keep in grave, 2 to send to deck) + let candidates = Object.keys(groups).filter(n => groups[n].length > 2).sort((a, b) => groups[b][0].power - groups[a][0].power); + if (candidates.length > 0) { + await card.animate("necrophage"); + board.toDeck(groups[candidates[0]][0], card.holder.grave); + board.toDeck(groups[candidates[0]][1], card.holder.grave); + } + } + + } else { + let c = await ui.popup("Yes [E]", (p) => p.choice = true, "No [Q]", (p) => p.choice = false, "Put unit cards from grave back to deck?", "Do you want to put up to 2 cards from your grave back to your deck?"); + if (c) { + await card.animate("necrophage"); + await ui.queueCarousel(grave_units, 2, async (c, i) => await board.toDeck(c.cards[i], card.holder.grave), c => true, true, true, "Choose up to 2 cards to take from your grave back to your deck."); + } + } + }, + // TODO: Make weightCard function call this + weight: (card) => { + let musters = card.holder.grave.cards.filter(c => c.isUnit() && c.abilities.includes("muster")); + if (musters.length > 2) + return 5; + return 0; + } + }, + goetia: { + name: "Goetia", + description: "Place on your battlefield and take 1 card from your deck to your hand, then choose any 1 card from your hand and shuffle it into your deck.", + placed: async card => { + if (card.isLocked()) + return; + if (card.holder.deck.cards.length > 0) { + if (card.holder.controller instanceof ControllerAI) { + card.holder.deck.draw(card.holder.hand); + let targetCard = card.holder.controller.discardOrder(card, card.holder.hand, true)[0]; + if (!targetCard) { + targetCard = card.holder.controller.getLowestWeightCard(card.holder.hand.cards); + } + board.toDeck(targetCard, card.holder.hand); + } else { + await ui.queueCarousel(card.holder.deck, 1, async (c, i) => await board.toHand(c.cards[i], card.holder.deck), () => true, true, false, "Choose a card to draw from your deck."); + await ui.queueCarousel(card.holder.hand, 1, async (c, i) => await board.toDeck(c.cards[i], card.holder.hand), () => true, true, false, "Which card to put back into your deck?"); + } + + } + }, + weight: (card) => { + if (card.holder.deck.cards.length > 0) + return 5; + return 0; + } + }, + ambush: { + name: "Ambush", + description: "Place on your or opponent's battlefield (on any row). If opponent plays a unit or hero card on this row, you will instantly draw 2 cards from your deck into your hand. Remove the ambush to the discard pile when it has happened.", + placed: async card => { + if (card.isLocked()) + return; + card.currentLocation.effects.ambush = true; + }, + weight: (card) => { + if (card.holder.passed) + return 0; + return 10; + } + }, + skellige_fleet: { + name: "Skellige Fleet", + description: "Place on your battlefield and either draw from your deck 1 top card instantly OR draw 2 top cards at the end of this round. In one round you can draw by Skellige Fleet no more than 3 cards.", + activated: async card => { + let c = 0; + if (!(card.holder.controller instanceof ControllerAI)) { + c = await ui.popup("Draw 1 now [E]", (p) => p.choice = 0, "Draw 2 later [Q]", (p) => p.choice = 1, "Draw now or more later?", "Either draw the first card of the deck now or first 2 at the end of the round."); + } else { + c = randomInt(1); + } + if (c == 0) { + if (card.holder.deck.cards.length > 0) { + card.holder.deck.draw(card.holder.hand); + } + } else { + game.roundEnd.push(async () => { + for (var i = 0; i < 2; i++) { + if (card.holder.deck.cards.length > 0) { + card.holder.deck.draw(card.holder.hand); + } + } + return true; + }); + } + await board.toGrave(card, card.holder.hand); + }, + weight: (card) => 20 + }, + royal_decree: { + name: "Royal Decree", + description: "Use your leader's ability", + activated: async card => { + let leaderEnabled = card.holder.leaderAvailable; + if (!card.holder.leaderAvailable) + card.holder.leaderAvailable = true; + await card.holder.activateLeader(false,false); // do not end turn and disable leader now + card.holder.leaderAvailable = leaderEnabled; + await board.toGrave(card, card.holder.hand); + }, + weight: (card) => { + let data_max = card.holder.controller.getMaximums(); + let data_board = card.holder.controller.getBoardData(); + return card.holder.controller.weightLeader(card.holder.leader, data_max, data_board); + } + }, + summon_one_of: { + name: "Summon One Of", + description: "Summons from anywhere (deck, grave or hand) one of the associated card of choice", + placed: async card => { + let targets = []; + if (card.isLocked()) + return; + if (card.target) { + if (Array.isArray(card.target)) + targets = card.target; + else + targets = card.target.split(" "); + } + let cards = card.holder.deck.cards.filter(c => targets.includes(c.key)) + .concat(card.holder.hand.cards.filter(c => targets.includes(c.key))) + .concat(card.holder.grave.cards.filter(c => targets.includes(c.key))); + if (cards.length > 0) { + let targetCard = null; + if (cards.length > 1) { + if (card.holder.controller instanceof ControllerAI) { + targetCard = card.holder.controller.getHighestWeightCard(cards); + } else { + await ui.queueCarousel({ cards: cards }, 1, async (c, i) => targetCard = c.cards[i], () => true, true, false, "Choose one card to play."); + } + } else { + targetCard = cards[0]; + } + if (targetCard) { + await targetCard.autoplay(targetCard.currentLocation); + } + } + }, + weight: (card) => { + let targets = []; + if (card.target) { + if (Array.isArray(card.target)) + targets = card.target; + else + targets = card.target.split(" "); + } + let cards = card.holder.deck.cards.filter(c => targets.includes(c.key)) + .concat(card.holder.hand.cards.filter(c => targets.includes(c.key))) + .concat(card.holder.grave.cards.filter(c => targets.includes(c.key))); + if (cards.length > 0) + return 10; + return 0; + } + }, + immortal: { + name: "Immortal", + description: "Card stays on the battlefield for 2 rounds and cannot be destroyed by another ability", + placed: async card => { + if (card.isLocked()) + return; + game.roundEnd.push(async () => { + card.noRemove = true; + await card.animate("immortal"); + game.roundStart.push(async () => { + delete card.noRemove; + return true; + }); + return true; + }); + }, + weight: (card) => { + return card.basePower; + } + }, + monster_toussaint: { + name: "Monster of Toussaint", + description: "In any round turn, starting from the next, instead of playing a card from your hand you can remove this card from the game and instantly play its second strongest form.", + placed: async card => { + }, + weight: (card) => { + return 5; + } + }, + aerondight: { + name: "Aerondight", + description: "Place on your battlefield than take the unit card with highest original strength and move it to the siege row. While it lies in the siege row, its strength is tripled.", + placed: async card => { + if (card.isLocked()) + return; + let maxCards = card.holder.getAllRowCards().filter(c => c.isUnit()) + .reduce((a, c) => (!a.length || a[0].basePower < c.basePower) ? [c] : a[0].basePower === c.basePower ? a.concat([c]) : a, []); + if (maxCards.length > 0) { + let targetCard = null; + if (maxCards.length == 1 || card.holder.controller instanceof ControllerAI) { + targetCard = maxCards[0]; + } else { + await ui.queueCarousel({ cards: maxCards }, 1, async (c, i) => targetCard = c.cards[i], () => true, true, false, "Choose which card to equip with Aerondight."); + } + if (targetCard) { + let targetRow = board.getRow(card, "siege", card.holder); + if (targetCard.currentLocation !== targetRow) { + await board.moveToNoEffects(targetCard, targetRow, targetCard.currentLocation); + } + targetCard.multiplier = 3; + targetRow.updateScore(); + await targetCard.animate("aerondight"); + } + } + }, + weight: (card) => { + let maxCards = card.holder.getAllRowCards().filter(c => c.isUnit()) + .reduce((a, c) => (!a.length || a[0].basePower < c.basePower) ? [c] : a[0].basePower === c.basePower ? a.concat([c]) : a, []); + if (maxCards.length == 0) + return 0; + return 3 * maxCards[0].basePower; + } + }, + bait: { + name: "Bait", + description: "Place on your battlefield and draw from your deck one card with Tight Bond ability. Play it immediatly.", + placed: async card => { + if (card.isLocked()) + return; + let cards = card.holder.deck.cards.filter(c => c.abilities.includes("bond")); + if (cards.length > 0) { + let targetCard = null; + if (cards.length > 1) { + if (card.holder.controller instanceof ControllerAI) { + targetCard = card.holder.controller.getHighestWeightCard(cards); + } else { + await ui.queueCarousel({ cards: cards }, 1, async (c, i) => targetCard = c.cards[i], () => true, true, false, "Choose one card to play."); + } + } else { + targetCard = cards[0]; + } + if (targetCard) { + if (card.holder.controller instanceof ControllerAI) { + targetCard.autoplay(card.holder.deck); + } else { + // let player select where to play the card + card.holder.selectCardDestination(targetCard, card.holder.deck); + } + } + } + }, + weight: (card) => { + return 10; + } + }, + soothsayer: { + name: "Soothsayer", + description: "Place on your battlefield. For each soothsayer card on your side of the battlefield, you can draw one more card to choose from.", + weight: (card) => { + return 10; + } + }, + curse: { + name: "Curse", + description: "Place on your or opponent's battlefield on any row. Next unit card (not hero) that will be placed on this row will be destroyed and it's abilities will not work", + weight: (card) => 20 + }, +}; diff --git a/cards.js b/cards.js new file mode 100644 index 0000000..756cef4 --- /dev/null +++ b/cards.js @@ -0,0 +1,6796 @@ +/* + * Original cards from The Witcher 3 + */ +var default_cards = { + "spe_decoy": { + "name": "Decoy", + "deck": "special", + "row": "", + "strength": "", + "ability": "decoy", + "filename": "decoy", + "count": "3", + "quote": "When you run out of peasants, decoys also make decent arrow fodder." + }, + "spe_frost": { + "name": "Biting Frost", + "deck": "weather", + "row": "", + "strength": "", + "ability": "frost", + "filename": "frost", + "count": "2", + "quote": "Best part about frost - bodies of the fallen don't rot so quickly." + }, + + "spe_clear": { + "name": "Clear Weather", + "deck": "weather", + "row": "", + "strength": "", + "ability": "clear", + "filename": "clear", + "count": "2", + "quote": "The sun' shinin', Dromle! The sun's shinin'! Maybe there's hope left after all..." + }, + "spe_horn": { + "name": "Commander's Horn", + "deck": "special", + "row": "", + "strength": "", + "ability": "horn", + "filename": "horn", + "count": "3", + "quote": "Plus one to morale, minus three to hearing." + }, + "spe_fog": { + "name": "Impenetrable Fog", + "deck": "weather", + "row": "", + "strength": "", + "ability": "fog", + "filename": "fog", + "count": "2", + "quote": "A good commander's dream... a bad one's horror." + }, + "spe_scorch": { + "name": "Scorch", + "deck": "special", + "row": "", + "strength": "", + "ability": "scorch", + "filename": "scorch", + "count": "3", + "quote": "Pillars of flame turn the mightiest to ash. All others tremble in shock and awe." + }, + "spe_rain": { + "name": "Torrential Rain", + "deck": "weather", + "row": "", + "strength": "", + "ability": "rain", + "filename": "rain", + "count": "2", + "quote": "Even the rain in this land smells like piss." + } +}; + +/* + * Custom new cards + */ + + +var ext_nr_cards = { + "nr_dandelion": { + "name": "Dandelion", + "deck": "realms", + "row": "close", + "strength": "2", + "ability": "horn", + "filename": "dandelion", + "count": "1", + "quote": "Dandelion, you're a cynic, a lecher, a whoremonger, a liar - and my best friend." + }, + "nr_geralt": { + "name": "Geralt of Rivia", + "deck": "realms", + "row": "close", + "strength": "12", + "ability": "hero", + "filename": "geralt", + "count": "1", + "quote": "If that's what it takes to save the world, it's better to let that world die." + }, + "nr_ciri": { + "name": "Cirilla Fiona Elen Riannon", + "deck": "realms", + "row": "close", + "strength": "12", + "ability": "hero", + "filename": "ciri", + "count": "1", + "quote": "Know when fairy tales cease to be tales? When people start believing in them." + }, + "nr_triss": { + "name": "Triss Merigold", + "deck": "realms", + "row": "close", + "strength": "7", + "ability": "hero medic", + "filename": "triss", + "count": "1", + "quote": "I can take care of myself. Trust me." + }, + "nr_villen": { + "name": "Villentretenmerth", + "deck": "realms", + "row": "close", + "strength": "5", + "ability": "scorch_c", + "filename": "villen", + "count": "1", + "quote": "Also calls himself Borkh Three Jackdaws... he's not the best at names." + }, + "nr_yennefer": { + "name": "Yennefer of Vengerberg", + "deck": "realms", + "row": "ranged", + "strength": "7", + "ability": "hero medic", + "filename": "yennefer", + "count": "1", + "quote": "Magic is Chaos, Art and Science. It is a curse, a blessing and a progression." + }, + "nr_zoltan": { + "name": "Zoltan Chivay", + "deck": "realms", + "row": "close", + "strength": "4", + "ability": "comrade", + "filename": "zoltan", + "count": "1", + "quote": "Life without old mates and booze is like a woman without a rump." + }, + "nr_olgierd": { + "name": "Olgierd von Everec", + "deck": "realms", + "row": "agile_cr", + "strength": "6", + "ability": "morale", + "filename": "olgierd", + "count": "1", + "quote": "At least you now know I don't easily lose my head." + }, + "nr_foltest_king": { + "name": "Foltest - King of Temeria", + "deck": "realms", + "row": "leader", + "strength": "", + "ability": "foltest_king", + "filename": "foltest_king", + "count": "1", + "quote": "It is natural and beautiful that a man should love his sister." + }, + "nr_foltest_lord": { + "name": "Foltest - Lord Commander of the North", + "deck": "realms", + "row": "leader", + "strength": "", + "ability": "foltest_lord", + "filename": "foltest_lord", + "count": "1", + "quote": "Sod advisors and their schemes. I place my trust in my soldiers' blades." + }, + "nr_foltest_siegemaster": { + "name": "Foltest - The Siegemaster", + "deck": "realms", + "row": "leader", + "strength": "", + "ability": "foltest_siegemaster", + "filename": "foltest_siegemaster", + "count": "1", + "quote": "A well-aimed ballista razes not just the enemy's wall, but his morale as well." + }, + "nr_foltest_steelforged": { + "name": "Foltest - The Steel-Forged", + "deck": "realms", + "row": "leader", + "strength": "", + "ability": "foltest_steelforged", + "filename": "foltest_steelforged", + "count": "1", + "quote": "A beautiful day for battle" + }, + "nr_foltest_son_of_medell": { + "name": "Foltest - Son of Medell", + "deck": "realms", + "row": "leader", + "strength": "", + "ability": "foltest_son", + "filename": "foltest_son_of_medell", + "count": "1", + "quote": "Dammit, I rule this land and I refuse to creep around its corners." + }, + "nr_blue_stripes_1": { + "name": "Blue Stripes Commando", + "id": 1, + "deck": "realms", + "row": "close", + "strength": "4", + "ability": "bond", + "filename": "blue_stripes_1", + "count": "1", + "target": "nr_blue_stripes", + "quote": "I'd do anything for Temeria. Mostly, though, I kill for her." + }, + "nr_blue_stripes_2": { + "name": "Blue Stripes Commando", + "id": 2, + "deck": "realms", + "row": "close", + "strength": "4", + "ability": "bond", + "filename": "blue_stripes_2", + "count": "1", + "target": "nr_blue_stripes", + "quote": "I'd do anything for Temeria. Mostly, though, I kill for her." + }, + "nr_blue_stripes_3": { + "name": "Blue Stripes Commando", + "id": 3, + "deck": "realms", + "row": "close", + "strength": "4", + "ability": "bond", + "filename": "blue_stripes_3", + "count": "1", + "target": "nr_blue_stripes", + "quote": "I'd do anything for Temeria. Mostly, though, I kill for her." + }, + "nr_catapult_1": { + "name": "Catapult", + "id": 1, + "deck": "realms", + "row": "siege", + "strength": "5", + "ability": "bond", + "filename": "catapult_1", + "count": "1", + "target": "nr_catapult", + "quote": "The gods help those who have better catapults." + }, + "nr_catapult_2": { + "name": "Catapult", + "id": 2, + "deck": "realms", + "row": "siege", + "strength": "5", + "ability": "bond", + "filename": "catapult_2", + "count": "1", + "target": "nr_catapult", + "quote": "The gods help those who have better catapults." + }, + "nr_crinfrid_1": { + "name": "Crinfrid Reavers Dragon Hunter", + "id": 1, + "deck": "realms", + "row": "ranged", + "strength": "5", + "ability": "bond", + "filename": "crinfrid_1", + "count": "1", + "target": "nr_crinfrid", + "quote": "Haven't had much luck with monsters of late, so we enlisted." + }, + "nr_crinfrid_2": { + "name": "Crinfrid Reavers Dragon Hunter", + "id": 2, + "deck": "realms", + "row": "ranged", + "strength": "5", + "ability": "bond", + "filename": "crinfrid_2", + "count": "1", + "target": "nr_crinfrid", + "quote": "Haven't had much luck with monsters of late, so we enlisted." + }, + "nr_crinfrid_3": { + "name": "Crinfrid Reavers Dragon Hunter", + "id": 3, + "deck": "realms", + "row": "ranged", + "strength": "5", + "ability": "bond", + "filename": "crinfrid_3", + "count": "1", + "target": "nr_crinfrid", + "quote": "Haven't had much luck with monsters of late, so we enlisted." + }, + "nr_ballista_1": { + "name": "Ballista", + "id": 1, + "deck": "realms", + "row": "siege", + "strength": "5", + "ability": "bond", + "filename": "ballista_1", + "count": "1", + "target": "nr_ballista", + "quote": "Never manages to hit the same place twice, which might constitute a real problem." + }, + "nr_ballista_2": { + "name": "Ballista", + "id": 2, + "deck": "realms", + "row": "siege", + "strength": "5", + "ability": "bond", + "filename": "ballista_2", + "count": "1", + "target": "nr_ballista", + "quote": "Never manages to hit the same place twice, which might constitute a real problem." + }, + "nr_banner_nurse": { + "name": "Dun Banner Medic", + "deck": "realms", + "row": "siege", + "strength": "2", + "ability": "medic", + "filename": "banner_nurse", + "count": "1", + "quote": "Stitch red to red, white to white, and everything will be all right." + }, + "nr_esterad": { + "name": "Esterad Thyssen", + "deck": "realms", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "esterad", + "count": "1", + "quote": "Like all Thyssen men, he was tall, powerfully built and criminally handsome" + }, + "nr_natalis": { + "name": "John Natalis", + "deck": "realms", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "natalis", + "count": "1", + "quote": "That square should bear the names of my soldiers, of the dead. Not mine." + }, + "nr_kaedwen_siege_1": { + "name": "Kaedweni Siege Expert", + "deck": "realms", + "row": "siege", + "strength": "5", + "ability": "morale", + "filename": "kaedwen_siege_1", + "count": "1", + "quote": "'You gotta recalibrate the arm by five degrees.' 'Do what by the what now?'" + }, + "nr_kaedwen_siege_2": { + "name": "Kaedweni Siege Expert", + "deck": "realms", + "row": "siege", + "strength": "5", + "ability": "morale", + "filename": "kaedwen_siege_2", + "count": "1", + "quote": "'You gotta recalibrate the arm by five degrees.' 'Do what by the what now?'" + }, + "nr_keira": { + "name": "Keira Metz", + "deck": "realms", + "row": "ranged", + "strength": "8", + "ability": "", + "filename": "keira", + "count": "1", + "quote": "If I'm to die today, I wish to look smashing for the occasion." + }, + "nr_philippa": { + "name": "Philippa Eilhart", + "deck": "realms", + "row": "ranged", + "strength": "10", + "ability": "hero", + "filename": "philippa", + "count": "1", + "quote": "Soon the power of kings will wither, and the Lodge shall seize its rightful place." + }, + "nr_poor_infantry_1": { + "name": "Poor Fucking Infantry", + "id": 1, + "deck": "realms", + "row": "close", + "strength": "4", + "ability": "muster", + "filename": "poor_infantry_1", + "count": "1", + "target": "nr_poor_infantry", + "quote": "I's a war veteran! ... spare me a crown?" + }, + "nr_poor_infantry_2": { + "name": "Poor Fucking Infantry", + "id": 2, + "deck": "realms", + "row": "close", + "strength": "4", + "ability": "muster", + "filename": "poor_infantry_2", + "count": "1", + "target": "nr_poor_infantry", + "quote": "I's a war veteran! ... spare me a crown?" + }, + "nr_poor_infantry_3": { + "name": "Poor Fucking Infantry", + "id": 3, + "deck": "realms", + "row": "close", + "strength": "4", + "ability": "muster", + "filename": "poor_infantry_3", + "count": "1", + "target": "nr_poor_infantry", + "quote": "I's a war veteran! ... spare me a crown?" + }, + "nr_stennis": { + "name": "Prince Stennis", + "deck": "realms", + "row": "close", + "strength": "9", + "ability": "spy", + "filename": "stennis", + "count": "1", + "quote": "He ploughin' wears the golden armor. Golden. 'Course he's an arsehole." + }, + "nr_sheldon": { + "name": "Sheldon Skaggs", + "deck": "realms", + "row": "ranged", + "strength": "4", + "ability": "comrade", + "filename": "sheldon", + "count": "1", + "quote": "I was there, on the front lines! Right where the fightin' was the thickest!" + }, + "nr_siege_tower": { + "name": "Siege Tower", + "deck": "realms", + "row": "siege", + "strength": "7", + "ability": "", + "filename": "siege_tower", + "count": "1", + "quote": "I love the clamor of siege towers in the morning. Sounds like victory." + }, + "nr_dijkstra": { + "name": "Sigismund Dijkstra", + "deck": "realms", + "row": "close", + "strength": "8", + "ability": "spy", + "filename": "dijkstra", + "count": "1", + "quote": "Gwent's like politics, just more honest." + }, + "nr_sheala": { + "name": "Síle de Tansarville", + "deck": "realms", + "row": "ranged", + "strength": "8", + "ability": "", + "filename": "sheala", + "count": "1", + "quote": "The Lodge lacks humility. Our lust for power may yet be our undoing." + }, + "nr_thaler": { + "name": "Thaler", + "deck": "realms", + "row": "siege", + "strength": "7", + "ability": "spy", + "filename": "thaler", + "count": "1", + "quote": "Fuck off! We aren't all ploughin' philanderers. Some of us have depth..." + }, + "nr_vernon": { + "name": "Vernon Roche", + "deck": "realms", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "vernon", + "count": "1", + "quote": "A partiot... and a real son of a bitch." + }, + "nr_ves": { + "name": "Ves", + "deck": "realms", + "row": "close", + "strength": "7", + "ability": "agile_cr", + "filename": "ves", + "count": "1", + "quote": "Better to live one day as a king than a whole life as a beggar." + }, + "nr_trebuchet": { + "name": "Trebuchet", + "deck": "realms", + "row": "siege", + "strength": "6", + "ability": "", + "filename": "trebuchet", + "count": "1", + "quote": "Castle won't batter itself down, now will it? Get them trebuchets rollin'!" + } +}; + +var ext_ne_cards = { + "ne_emhyr_imperial": { + "name": "Emhyr var Emreis - His Imperial Majesty", + "deck": "nilfgaard", + "row": "leader", + "strength": "", + "ability": "emhyr_imperial", + "filename": "emhyr_imperial", + "count": "1", + "quote": "The skies wept when my Pavetta died. They will not weep for me." + }, + "ne_emhyr_emperor": { + "name": "Emhyr var Emreis - Emperor of Nilfgaard", + "deck": "nilfgaard", + "row": "leader", + "strength": "", + "ability": "emhyr_emperor", + "filename": "emhyr_emperor", + "count": "1", + "quote": "Your motives do not interest me. Only results." + }, + "ne_emhyr_whiteflame": { + "name": "Emhyr var Emreis - the White Flame", + "deck": "nilfgaard", + "row": "leader", + "strength": "", + "ability": "emhyr_whiteflame", + "filename": "emhyr_whiteflame", + "count": "1", + "quote": "A sword is but one of many tools at a ruler's disposal." + }, + "ne_emhyr_relentless": { + "name": "Emhyr var Emreis - The Relentless", + "deck": "nilfgaard", + "row": "leader", + "strength": "", + "ability": "emhyr_relentless", + "filename": "emhyr_relentless", + "count": "1", + "quote": "They do not call me the Patient. Take care they do not call you the Headless." + }, + "ne_emhyr_invader_of_the_north": { + "name": "Emhyr var Emreis - Invader of the North", + "deck": "nilfgaard", + "row": "leader", + "strength": "", + "ability": "emhyr_invader", + "filename": "emhyr_invader_of_the_north", + "count": "1", + "quote": "Emperors command multitudes, yet cannot control two things: their time and their hearts." + }, + "ne_cahir": { + "name": "Cahir Mawr Dyffryn aep Ceallach", + "deck": "nilfgaard", + "row": "close", + "strength": "7", + "ability": "", + "filename": "cahir", + "count": "1", + "quote": "His eyes flashed under his winged helmet. Fire gleamed from his sword's blade." + }, + "ne_shilard": { + "name": "Shilard Fitz-Oesterlen", + "deck": "nilfgaard", + "row": "close", + "strength": "8", + "ability": "spy", + "filename": "shilard", + "count": "1", + "quote": "Warfare is mere sound and fury - diplomacy is what truly shapes history." + }, + "ne_renuald": { + "name": "Renuald aep Matsen", + "deck": "nilfgaard", + "row": "close", + "strength": "2", + "ability": "invoke", + "filename": "renuald", + "count": "1", + "target": "ne_impera_brigade", + "quote": "They say the Impera fear nothing. Untrue. Renuald scares them shitless." + }, + "ne_impera_brigade_1": { + "name": "Impera Brigade Guard", + "id": 1, + "deck": "nilfgaard", + "row": "close", + "strength": "3", + "ability": "bond", + "filename": "impera_brigade_1", + "count": "1", + "target": "ne_impera_brigade", + "quote": "The Impera Brigade never surrenders. Ever." + }, + "ne_impera_brigade_2": { + "name": "Impera Brigade Guard", + "id": 2, + "deck": "nilfgaard", + "row": "close", + "strength": "3", + "ability": "bond", + "filename": "impera_brigade_2", + "count": "1", + "target": "ne_impera_brigade", + "quote": "The Impera Brigade never surrenders. Ever." + }, + "ne_impera_brigade_3": { + "name": "Impera Brigade Guard", + "id": 3, + "deck": "nilfgaard", + "row": "close", + "strength": "3", + "ability": "bond", + "filename": "impera_brigade_3", + "count": "1", + "target": "ne_impera_brigade", + "quote": "The Impera Brigade never surrenders. Ever." + }, + "ne_impera_brigade_4": { + "name": "Impera Brigade Guard", + "id": 4, + "deck": "nilfgaard", + "row": "close", + "strength": "3", + "ability": "bond", + "filename": "impera_brigade_4", + "count": "1", + "target": "ne_impera_brigade", + "quote": "The Impera Brigade never surrenders. Ever." + }, + "ne_nauzicaa_1": { + "name": "Nausicaa Cavalry Rider", + "id": 1, + "deck": "nilfgaard", + "row": "close", + "strength": "4", + "ability": "bond", + "filename": "nauzicaa_1", + "count": "1", + "target": "ne_nauzicaa", + "quote": "The Emperor will teach the North discipline." + }, + "ne_nauzicaa_2": { + "name": "Nausicaa Cavalry Rider", + "id": 2, + "deck": "nilfgaard", + "row": "close", + "strength": "4", + "ability": "bond", + "filename": "nauzicaa_2", + "count": "1", + "target": "ne_nauzicaa", + "quote": "The Emperor will teach the North discipline." + }, + "ne_nauzicaa_3": { + "name": "Nausicaa Cavalry Rider", + "id": 3, + "deck": "nilfgaard", + "row": "close", + "strength": "4", + "ability": "bond", + "filename": "nauzicaa_3", + "count": "1", + "target": "ne_nauzicaa", + "quote": "The Emperor will teach the North discipline." + }, + "ne_stefan": { + "name": "Stefan Skellen", + "deck": "nilfgaard", + "row": "close", + "strength": "9", + "ability": "spy", + "filename": "stefan", + "count": "1", + "quote": "My mark scards the face of our future empress. That is my proudest achievement." + }, + "ne_vreemde": { + "name": "Vreemde", + "deck": "nilfgaard", + "row": "agile_cr", + "strength": "6", + "ability": "", + "filename": "vreemde", + "count": "1", + "quote": "Discipline is the Empire's deadliest weapon." + }, + "ne_morteisen": { + "name": "Morteisen", + "deck": "nilfgaard", + "row": "agile_cr", + "strength": "5", + "ability": "emissary", + "filename": "morteisen", + "count": "1", + "quote": "No Nordling pikemen or dwarven spearbearers can hope to best trained cavalary." + }, + "ne_letho": { + "name": "Letho of Gulet", + "deck": "nilfgaard", + "row": "close", + "strength": "8", + "ability": "hero scorch_c", + "filename": "letho", + "count": "1", + "quote": "Witchers never die in the beds." + }, + "ne_menno": { + "name": "Menno Coehoorn", + "deck": "nilfgaard", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "menno", + "count": "1", + "quote": "I'll take an attentive reconnaissance unit over a fine cavalry brigade any day." + }, + "ne_vattier": { + "name": "Vattier de Rideaux", + "deck": "nilfgaard", + "row": "close", + "strength": "8", + "ability": "hero spy", + "filename": "vattier", + "count": "1", + "quote": "There's never been a problem a well-planned assassination couldn't solve." + }, + "ne_geralt": { + "name": "Geralt of Rivia", + "deck": "nilfgaard", + "row": "close", + "strength": "12", + "ability": "hero", + "filename": "geralt", + "count": "1", + "quote": "If that's what it takes to save the world, it's better to let that world die." + }, + "ne_ciri": { + "name": "Cirilla Fiona Elen Riannon", + "deck": "nilfgaard", + "row": "close", + "strength": "12", + "ability": "hero", + "filename": "ciri", + "count": "1", + "quote": "Know when fairy tales cease to be tales? When people start believing in them." + }, + "ne_yennefer": { + "name": "Yennefer of Vengerberg", + "deck": "nilfgaard", + "row": "ranged", + "strength": "7", + "ability": "hero medic", + "filename": "yennefer", + "count": "1", + "quote": "Magic is Chaos, Art and Science. It is a curse, a blessing and a progression." + }, + "ne_tibor": { + "name": "Tibor Eggebracht", + "deck": "nilfgaard", + "row": "ranged", + "strength": "7", + "ability": "hero morale", + "filename": "tibor", + "count": "1", + "quote": "Albaaaa! Forward!! Alba! Long live the Emperor!" + }, + "ne_assire": { + "name": "Sorceress: Assire var Anahid", + "deck": "nilfgaard", + "row": "ranged", + "strength": "4", + "ability": "bond", + "filename": "assire", + "count": "1", + "target": "ne_sorceress", + "quote": "Nilfgaardian mages do have a choice, servile submission, or the gallows." + }, + "ne_cynthia": { + "name": "Sorceress: Cynthia", + "deck": "nilfgaard", + "row": "ranged", + "strength": "4", + "ability": "bond", + "filename": "cynthia", + "count": "1", + "target": "ne_sorceress", + "quote": "Cynthia's talents can be deadly. She needs a tight leash." + }, + "ne_fringilla": { + "name": "Sorceress: Fringilla Vigo", + "deck": "nilfgaard", + "row": "ranged", + "strength": "4", + "ability": "bond", + "filename": "fringilla", + "count": "1", + "target": "ne_sorceress", + "quote": "Magic is the highest good. It transcends all borders and divisions." + }, + "ne_black_archer": { + "name": "Black Infantry Archer", + "deck": "nilfgaard", + "row": "ranged", + "strength": "7", + "ability": "", + "filename": "black_archer", + "count": "1", + "quote": "I aim for the knee. Always." + }, + "ne_black_archer_1": { + "name": "Black Infantry Archer", + "deck": "nilfgaard", + "row": "ranged", + "strength": "7", + "ability": "", + "filename": "black_archer_1", + "count": "1", + "quote": "I aim for the knee. Always." + }, + "ne_albrich": { + "name": "Albrich", + "deck": "nilfgaard", + "row": "ranged", + "strength": "3", + "ability": "medic", + "filename": "albrich", + "count": "1", + "quote": "A fireball? Of course. Whatever Your Imperial Majesty whishes." + }, + "ne_young_emissary_1": { + "name": "Young Emissary", + "id": 1, + "deck": "nilfgaard", + "row": "close", + "strength": "4", + "ability": "emissary", + "filename": "young_emissary_1", + "count": "1", + "quote": "If I acquit myself well, perhaps next they'll post me somewhere more civilized." + }, + "ne_young_emissary_2": { + "name": "Young Emissary", + "id": 2, + "deck": "nilfgaard", + "row": "close", + "strength": "4", + "ability": "emissary", + "filename": "young_emissary_2", + "count": "1", + "quote": "If I acquit myself well, perhaps next they'll post me somewhere more civilized." + }, + "ne_puttkammer": { + "name": "Puttkammer", + "deck": "nilfgaard", + "row": "ranged", + "strength": "2", + "ability": "horn", + "filename": "puttkammer", + "count": "1", + "quote": "Learned a lot at Braibant Military Academy. How to scrub potatoes, for instance." + }, + "ne_archer_support": { + "name": "Etolian Auxiliary Archers", + "deck": "nilfgaard", + "row": "ranged", + "strength": "5", + "ability": "morale", + "filename": "archer_support", + "count": "1", + "quote": "Double or nothing, aim for his cock" + }, + "ne_archer_support_1": { + "name": "Etolian Auxiliary Archers", + "deck": "nilfgaard", + "row": "ranged", + "strength": "5", + "ability": "morale", + "filename": "archer_support_1", + "count": "1", + "quote": "Double or nothing, aim for his cock" + }, + "ne_moorvran": { + "name": "Morvran Voorhis", + "deck": "nilfgaard", + "row": "siege", + "strength": "10", + "ability": "hero", + "filename": "moorvran", + "count": "1", + "quote": "Summer sun reflecting in the quiet waters of Alba - that's Nilfgaard to me." + } +}; + +var ext_mo_cards = { + "mo_eredin_commander": { + "name": "Eredin - Commander of the Red Riders", + "deck": "monsters", + "row": "leader", + "strength": "", + "ability": "eredin_commander", + "filename": "eredin_commander", + "count": "1", + "quote": "Go on. Show me your spins, pirouettes and feints. I want to watch." + }, + "mo_eredin_bringer_of_death": { + "name": "Eredin - Bringer of Death", + "deck": "monsters", + "row": "leader", + "strength": "", + "ability": "eredin_bringer_of_death", + "filename": "eredin_bringer_of_death", + "count": "1", + "quote": "It is unavoidable." + }, + "mo_eredin_destroyer": { + "name": "Eredin - Destroyer of Worlds", + "deck": "monsters", + "row": "leader", + "strength": "", + "ability": "eredin_destroyer", + "filename": "eredin_destroyer", + "count": "1", + "quote": "I've long awaited this..." + }, + "mo_eredin_king": { + "name": "Eredin - King of the Wild Hunt", + "deck": "monsters", + "row": "leader", + "strength": "", + "ability": "eredin_king", + "filename": "eredin_king", + "count": "1", + "quote": "Have some dignity. You know how this will end." + }, + "mo_eredin_the_treacherous": { + "name": "Eredin Bréacc Glas - The Treacherous", + "deck": "monsters", + "row": "leader", + "strength": "", + "ability": "eredin_treacherous", + "filename": "eredin_the_treacherous", + "count": "1", + "quote": "I'm enjoying this. You are my toy." + }, + "mo_ghoul": { + "name": "Ghoul", + "deck": "monsters", + "row": "close", + "strength": "4", + "ability": "necrophage", + "filename": "ghoul", + "count": "1", + "quote": "If ghouls are part of the Circle of Life... then it's a damn vicious circle." + }, + "mo_cow": { + "name": "Cow", + "deck": "monsters", + "row": "ranged", + "strength": "0", + "ability": "avenger", + "filename": "cow", + "count": "1", + "target": "mo_bovine_defense", + "quote": "Mooo!" + }, + "mo_bovine_defense": { + "name": "Bovine Defense Force", + "deck": "monsters", + "row": "close", + "strength": "7", + "ability": "", + "filename": "chort", + "count": "0", + "quote": "Grrrrr!" + }, + "mo_forktail": { + "name": "Forktail", + "deck": "monsters", + "row": "close", + "strength": "3", + "ability": "scorch_c", + "filename": "forktail", + "count": "1", + "quote": "Fork tail.. Bah! Fuckers' tails're more like cleavers." + }, + "mo_werewolf": { + "name": "Werewolf", + "deck": "monsters", + "row": "close", + "strength": "8", + "ability": "", + "filename": "werewolf", + "count": "1", + "quote": "Wolves aren't as bad as they say. Werewolves, though - they're worse." + }, + "mo_witch_velen": { + "name": "Crone - Brewess", + "id": 1, + "deck": "monsters", + "row": "close", + "strength": "6", + "ability": "muster", + "filename": "witch_velen", + "count": "1", + "target": "mo_witch_velen", + "quote": "We'll cut you up, boy. A fina broth you will make." + }, + "mo_witch_velen_1": { + "name": "Crone - Weavess", + "id": 2, + "deck": "monsters", + "row": "close", + "strength": "6", + "ability": "muster", + "filename": "witch_velen_1", + "count": "1", + "target": "mo_witch_velen", + "quote": "I sense your pain. I see your fear..." + }, + "mo_witch_velen_2": { + "name": "Crone - Whispess", + "id": 3, + "deck": "monsters", + "row": "close", + "strength": "6", + "ability": "muster", + "filename": "witch_velen_2", + "count": "1", + "target": "mo_witch_velen", + "quote": "I'l be your best - and last." + }, + "mo_bruxa": { + "name": "Vampire - Bruxa", + "id": 1, + "deck": "monsters", + "row": "close", + "strength": "4", + "ability": "muster", + "filename": "bruxa", + "count": "1", + "target": "mo_vampire", + "quote": "A vile, bloodthirsty, man-eating hag. Kind of like my mother-in-law." + }, + "mo_ekkima": { + "name": "Vampire - Ekimmara", + "id": 2, + "deck": "monsters", + "row": "close", + "strength": "4", + "ability": "muster", + "filename": "ekkima", + "count": "1", + "target": "mo_vampire", + "quote": "Who would think overgrown bats would have a taste for gaudy jewelry?" + }, + "mo_fleder": { + "name": "Vampire - Fleder", + "id": 3, + "deck": "monsters", + "row": "close", + "strength": "4", + "ability": "muster", + "filename": "fleder", + "count": "1", + "target": "mo_vampire", + "quote": "Higher vampieres embrace their victims. Fleders rim them to shreds." + }, + "mo_garkain": { + "name": "Vampire - Garkain", + "id": 4, + "deck": "monsters", + "row": "close", + "strength": "4", + "ability": "muster", + "filename": "garkain", + "count": "1", + "target": "mo_vampire", + "quote": "Blood-drinkers and corpse-eaters so foul their very ugliness paralyses foes." + }, + "mo_katakan": { + "name": "Vampire - Katakan", + "id": 5, + "deck": "monsters", + "row": "close", + "strength": "5", + "ability": "muster", + "filename": "katakan", + "count": "1", + "target": "mo_vampire", + "quote": "Drinking the blood of the Continent since the Conjunction." + }, + "mo_imlerith": { + "name": "Imlerith", + "deck": "monsters", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "imlerith", + "count": "1", + "quote": "Ladd nahw! Kill them! Litter the earth with their entrails!" + }, + "mo_celaeno_harpy": { + "name": "Celaeno Harpy", + "deck": "monsters", + "row": "close", + "strength": "8", + "ability": "hero spy", + "filename": "celaeno_harpy", + "count": "1", + "quote": "Common harpies feed on carrion. Calaeno harpies... they feed on dreams." + }, + "mo_kayran": { + "name": "Kayran", + "deck": "monsters", + "row": "agile_cr", + "strength": "8", + "ability": "hero morale", + "filename": "kayran", + "count": "1", + "quote": "Kill a kayran? Simple. Take your best sword... then sell it and hire a witcher." + }, + "mo_gaunter_odimm": { + "name": "Gaunter O'Dimm", + "deck": "monsters", + "row": "siege", + "strength": "8", + "ability": "hero goetia", + "filename": "gaunter_odimm", + "count": "1", + "quote": "He always grants exactly what you wish for. That's the problem." + }, + "mo_gaunter_odimm_darkness": { + "name": "Gaunter O'Dimm - Darkness", + "deck": "monsters", + "row": "agile_crs", + "strength": "5", + "ability": "goetia", + "filename": "gaunter_odimm_darkness", + "count": 1, + "quote": "Fear not the shadows, but the light." + }, + "mo_nekker": { + "name": "Nekker", + "id": 1, + "deck": "monsters", + "row": "ranged", + "strength": "5", + "ability": "muster", + "filename": "nekker", + "count": "1", + "target": "mo_nekker", + "quote": "Damn things are almost cute, if you ignore the whole vicious killer aspect." + }, + "mo_nekker_1": { + "name": "Nekker", + "id": 1, + "deck": "monsters", + "row": "ranged", + "strength": "5", + "ability": "muster", + "filename": "nekker_1", + "count": "1", + "target": "mo_nekker", + "quote": "Damn things are almost cute, if you ignore the whole vicious killer aspect." + }, + "mo_nekker_2": { + "name": "Nekker", + "id": 3, + "deck": "monsters", + "row": "ranged", + "strength": "5", + "ability": "muster", + "filename": "nekker_2", + "count": "1", + "target": "mo_nekker", + "quote": "Damn things are almost cute, if you ignore the whole vicious killer aspect." + }, + "mo_foglet": { + "name": "Foglet", + "deck": "monsters", + "row": "ranged", + "strength": "6", + "ability": "fog_summoning", + "filename": "foglet", + "count": "1", + "quote": "Fog creeps on little cat feet. Foglets creep over the bodies of their victims." + }, + "mo_plague_maiden": { + "name": "Plague Maiden", + "deck": "monsters", + "row": "ranged", + "strength": "4", + "ability": "medic", + "filename": "plague_maiden", + "count": "1", + "quote": "The sick rave about a boil-pocked woman surrounded by herds of rabid rats..." + }, + "mo_toad": { + "name": "Toad", + "deck": "monsters", + "row": "ranged", + "strength": "5", + "ability": "scorch_r", + "filename": "toad", + "count": "1", + "quote": "Big. Bad. Ugly. Squats in the sewers." + }, + "mo_gravehag": { + "name": "Grave Hag", + "deck": "monsters", + "row": "ranged", + "strength": "5", + "ability": "necrophage", + "filename": "gravehag", + "count": "1", + "quote": "Their long tongues're for slurping marrow - and whipping prey." + }, + "mo_leshen": { + "name": "Leshen", + "deck": "monsters", + "row": "ranged", + "strength": "10", + "ability": "hero", + "filename": "leshen", + "count": "1", + "quote": "We never hunt in these woods. Not even if it means the whole village starves." + }, + "mo_caranthir": { + "name": "Caranthir Ar-Feiniel", + "deck": "monsters", + "row": "ranged", + "strength": "6", + "ability": "hero frost", + "filename": "caranthir", + "count": "1", + "quote": "Zirael! I await." + }, + "mo_wyvern": { + "name": "Wyvern", + "deck": "monsters", + "row": "agile_rs", + "strength": "7", + "ability": "", + "filename": "wyvern", + "count": "1", + "quote": "Imagine a cross between a winged snake and a nightmare. Wyverns are worse." + }, + "mo_gryffin": { + "name": "Griffin", + "deck": "monsters", + "row": "agile_rs", + "strength": "7", + "ability": "", + "filename": "gryffin", + "count": "1", + "quote": "Griffins like to toy with their prey. Eat 'em alive, piece by piece." + }, + "mo_arachas": { + "name": "Arachas ", + "id": 1, + "deck": "monsters", + "row": "siege", + "strength": "4", + "ability": "muster", + "filename": "arachas", + "count": "1", + "target": "mo_arachas", + "quote": "Ugly - nature's way of saying 'Stay the fuck away'" + }, + "mo_arachas_1": { + "name": "Arachas ", + "id": 2, + "deck": "monsters", + "row": "siege", + "strength": "4", + "ability": "muster", + "filename": "arachas_1", + "count": "1", + "target": "mo_arachas", + "quote": "Ugly - nature's way of saying 'Stay the fuck away'" + }, + "mo_arachas_2": { + "name": "Arachas ", + "id": 3, + "deck": "monsters", + "row": "siege", + "strength": "4", + "ability": "muster", + "filename": "arachas_2", + "count": "1", + "target": "mo_arachas", + "quote": "Ugly - nature's way of saying 'Stay the fuck away'" + }, + "mo_arachas_behemoth": { + "name": "Arachas- Behemoth", + "id": 4, + "deck": "monsters", + "row": "siege", + "strength": "5", + "ability": "muster", + "filename": "arachas_behemoth", + "count": "1", + "target": "mo_arachas", + "quote": "Like a cross between a crab, a spider... and a ploughin' moutain." + }, + "mo_draug": { + "name": "Draug", + "deck": "monsters", + "row": "siege", + "strength": "10", + "ability": "hero", + "filename": "draug", + "count": "1", + "quote": "Some men cannot admit defeat. Some keep fighting from beyond the grave." + }, +}; + +var ext_st_cards = { + "sc_francesca_queen": { + "name": "Francesca Findabair - Queen of Dol Blathanna", + "deck": "scoiatael", + "row": "leader", + "strength": "", + "ability": "francesca_queen", + "filename": "francesca_queen", + "count": "1", + "quote": "Ash shall fertilize the soil. By spring, the valley shall bloom once more." + }, + "sc_francesca_beautiful": { + "name": "Francesca Findabair - the Beautiful", + "deck": "scoiatael", + "row": "leader", + "strength": "", + "ability": "francesca_beautiful", + "filename": "francesca_beautiful", + "count": "1", + "quote": "The Elder Races have forgotten more than humans can ever hope to know." + }, + "sc_francesca_daisy": { + "name": "Francesca Findabair - Daisy of the Valley", + "deck": "scoiatael", + "row": "leader", + "strength": "", + "ability": "francesca_daisy", + "filename": "francesca_daisy", + "count": "1", + "quote": "Do not let my beauty distract your aim." + }, + "sc_francesca_pureblood": { + "name": "Francesca Findabair - Pureblood Elf", + "deck": "scoiatael", + "row": "leader", + "strength": "", + "ability": "francesca_pureblood", + "filename": "francesca_pureblood", + "count": "1", + "quote": "To live in peave, we first must kill. This is human oppression's cruel finale." + }, + "sc_francesca_hope_of_the_aen_seidhe": { + "name": "Francesca Findabair - Hope of the Aen Seidhe", + "deck": "scoiatael", + "row": "leader", + "strength": "", + "ability": "francesca_hope", + "filename": "francesca_hope_of_the_aen_seidhe", + "count": "1", + "quote": "Daede sian caente, Aen Seidhe en'allane ael coeden..." + }, + "sc_riordain": { + "name": "Riordain", + "deck": "scoiatael", + "row": "close", + "strength": "1", + "ability": "scorch_c", + "filename": "riordain", + "count": "1", + "quote": "Stare into their eyes, feast on their terror. Then go in for the kill." + }, + "sc_havekar_support": { + "name": "Havekar Smuggler", + "id": 1, + "deck": "scoiatael", + "row": "close", + "strength": "5", + "ability": "muster", + "filename": "havekar_support", + "count": "1", + "target": "sc_havekar_support", + "quote": "I fight for whoever's paying the best. Or whoever's easiest to rob." + }, + "sc_havekar_support_1": { + "name": "Havekar Smuggler", + "id": 2, + "deck": "scoiatael", + "row": "close", + "strength": "5", + "ability": "muster", + "filename": "havekar_support_1", + "count": "1", + "target": "sc_havekar_support", + "quote": "I fight for whoever's paying the best. Or whoever's easiest to rob." + }, + "sc_havekar_support_2": { + "name": "Havekar Smuggler", + "id": 3, + "deck": "scoiatael", + "row": "close", + "strength": "5", + "ability": "muster", + "filename": "havekar_support_2", + "count": "1", + "target": "sc_havekar_support", + "quote": "I fight for whoever's paying the best. Or whoever's easiest to rob." + }, + "sc_dennis": { + "name": "Dennis Cranmer", + "deck": "scoiatael", + "row": "close", + "strength": "8", + "ability": "", + "filename": "dennis", + "count": "1", + "quote": "I know how to carry out orders, so you can shove you advice up your coal chute." + }, + "sc_mahakam": { + "name": "Mahakaman Defender", + "deck": "scoiatael", + "row": "close", + "strength": "7", + "ability": "bond", + "filename": "mahakam", + "count": "1", + "target": "sc_mahakam_defender", + "quote": "I'm telling ye, we're born for battle - we slash straight at their kneed!" + }, + "sc_mahakam_1": { + "name": "Mahakaman Defender", + "deck": "scoiatael", + "row": "close", + "strength": "7", + "ability": "bond", + "filename": "mahakam_1", + "count": "1", + "target": "sc_mahakam_defender", + "quote": "I'm telling ye, we're born for battle - we slash straight at their kneed!" + }, + "sc_barclay": { + "name": "Barclay Els", + "deck": "scoiatael", + "row": "close", + "strength": "2", + "ability": "horn", + "filename": "barclay", + "count": "1", + "quote": "Our mead smells like piss, do it? Easy to fix - I'll break your fuckin' nose!" + }, + "sc_geralt": { + "name": "Geralt of Rivia", + "deck": "scoiatael", + "row": "close", + "strength": "12", + "ability": "hero", + "filename": "geralt", + "count": "1", + "quote": "If that's what it takes to save the world, it's better to let that world die." + }, + "sc_ciri": { + "name": "Cirilla Fiona Elen Riannon", + "deck": "scoiatael", + "row": "close", + "strength": "12", + "ability": "hero", + "filename": "ciri", + "count": "1", + "quote": "Know when fairy tales cease to be tales? When people start believing in them." + }, + "sc_mysterious_elf": { + "name": "Avallach'h", + "deck": "scoiatael", + "row": "close", + "strength": "6", + "ability": "hero spy", + "filename": "mysterious_elf", + "count": "1", + "quote": "You humans have... unusual tastes." + }, + "sc_isengrim": { + "name": "Isengrim Faoiltiarna", + "deck": "scoiatael", + "row": "close", + "strength": "10", + "ability": "hero morale", + "filename": "isengrim", + "count": "1", + "quote": "It dawns on them once they notice my scar: a realization of imminent death." + }, + "sc_dol_infantry_1": { + "name": "Dol Blathanna Scout", + "deck": "scoiatael", + "row": "agile_cr", + "strength": "5", + "ability": "muster", + "filename": "dol_infantry_1", + "count": "1", + "target": "sc_dol_infantry", + "quote": "They track like hounds, run like deer and kill like cold-hearted bastards." + }, + "sc_dol_infantry_2": { + "name": "Dol Blathanna Scout", + "deck": "scoiatael", + "row": "agile_cr", + "strength": "5", + "ability": "muster", + "filename": "dol_infantry_2", + "count": "1", + "target": "sc_dol_infantry", + "quote": "They track like hounds, run like deer and kill like cold-hearted bastards." + }, + "sc_vrihedd_cadet": { + "name": "Vrihedd Brigade Recruit", + "deck": "scoiatael", + "row": "agile_cr", + "strength": "4", + "ability": "decoy", + "filename": "vrihedd_cadet", + "count": "1", + "quote": "Hatred burns brighter than any fire, and cuts deeper than any blade." + }, + "sc_vrihedd_brigade_1": { + "name": "Vrihedd Brigade Veteran", + "deck": "scoiatael", + "row": "agile_cs", + "strength": "7", + "ability": "", + "filename": "vrihedd_brigade_1", + "count": "1", + "quote": "'Vrihedd? What's that mean?' 'Trouble.'" + }, + "sc_saskia": { + "name": "Saesenthessis", + "deck": "scoiatael", + "row": "agile_cr", + "strength": "7", + "ability": "hero morale", + "filename": "saskia", + "count": "1", + "quote": "Beautiful, pure, fierce - the perfect icon for a rebellion." + }, + "sc_havekar_nurse": { + "name": "Havekar Healer", + "deck": "scoiatael", + "row": "ranged", + "strength": "2", + "ability": "medic", + "filename": "havekar_nurse", + "count": "1", + "quote": "Sure, I'll patch you up. Gonna cost you, though." + }, + "sc_havekar_nurse_1": { + "name": "Havekar Healer", + "deck": "scoiatael", + "row": "ranged", + "strength": "2", + "ability": "medic", + "filename": "havekar_nurse_1", + "count": "1", + "quote": "Sure, I'll patch you up. Gonna cost you, though." + }, + "sc_havekar_nurse_2": { + "name": "Havekar Healer", + "deck": "scoiatael", + "row": "ranged", + "strength": "2", + "ability": "medic", + "filename": "havekar_nurse_2", + "count": "1", + "quote": "Sure, I'll patch you up. Gonna cost you, though." + }, + "sc_elf_skirmisher": { + "name": "Elven Skirmisher", + "id": 1, + "deck": "scoiatael", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "elf_skirmisher", + "count": "1", + "target": "sc_elf_skirmisher", + "quote": "No matter what you may have heard, elves don't take human scalps. Too much lice." + }, + "sc_elf_skirmisher_1": { + "name": "Elven Skirmisher", + "id": 2, + "deck": "scoiatael", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "elf_skirmisher_1", + "count": "1", + "target": "sc_elf_skirmisher", + "quote": "No matter what you may have heard, elves don't take human scalps. Too much lice." + }, + "sc_elf_skirmisher_2": { + "name": "Elven Skirmisher", + "id": 3, + "deck": "scoiatael", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "elf_skirmisher_2", + "count": "1", + "target": "sc_elf_skirmisher", + "quote": "No matter what you may have heard, elves don't take human scalps. Too much lice." + }, + "sc_dol_archer": { + "name": "Dol Blathanna Archer", + "deck": "scoiatael", + "row": "ranged", + "strength": "8", + "ability": "", + "filename": "dol_archer", + "count": "1", + "quote": "Take another step, dh'oine. You'd look better with an arrow between your eyes." + }, + "sc_milva": { + "name": "Milva", + "deck": "scoiatael", + "row": "ranged", + "strength": "6", + "ability": "morale", + "filename": "milva", + "count": "1", + "quote": "With each arrow I loose, I think of my da. He'd be proud. I think." + }, + "sc_yennefer": { + "name": "Yennefer of Vengerberg", + "deck": "scoiatael", + "row": "ranged", + "strength": "7", + "ability": "hero medic", + "filename": "yennefer", + "count": "1", + "quote": "Magic is Chaos, Art and Science. It is a curse, a blessing and a progression." + }, + "sc_iorveth": { + "name": "Iorveth", + "deck": "scoiatael", + "row": "ranged", + "strength": "10", + "ability": "hero morale", + "filename": "iorveth", + "count": "1", + "quote": "King or beggar, what's the difference? One dh'oine less." + }, + "sc_vrihedd_brigade": { + "name": "Vrihedd Brigade Veteran", + "deck": "scoiatael", + "row": "agile_rs", + "strength": "7", + "ability": "", + "filename": "vrihedd_brigade", + "count": "1", + "quote": "'Vrihedd? What's that mean?' 'Trouble.'" + }, + "sc_yaevinn": { + "name": "Yaevinn", + "deck": "scoiatael", + "row": "agile_crs", + "strength": "6", + "ability": "", + "filename": "yaevinn", + "count": "1", + "quote": "We are drops of rain that together make a ferocious storm." + }, + "sc_toruviel": { + "name": "Toruviel", + "deck": "scoiatael", + "row": "agile_crs", + "strength": "6", + "ability": "", + "filename": "toruviel", + "count": "1", + "quote": "I'd gladly kill you from up close, stare in your eyese... But you reek, human." + }, + "sc_filavandrel": { + "name": "Filavandrel aen Fidhail", + "deck": "scoiatael", + "row": "agile_crs", + "strength": "6", + "ability": "", + "filename": "filavandrel", + "count": "1", + "quote": "Though we are now few and scattered, our hearts burn brighter than ever." + }, + "sc_temptress": { + "name": "Temptress", + "deck": "scoiatael", + "row": "agile_crs", + "strength": "0", + "ability": "hero ambush", + "filename": "temptress", + "count": "1", + "quote": "Hey! Would you like to have some fun?" + }, + "sc_schirru": { + "name": "Schirru", + "deck": "scoiatael", + "row": "siege", + "strength": "8", + "ability": "scorch_s", + "filename": "schirru", + "count": "1", + "quote": "Time to look death in the face." + } +}; + +var ext_sk_cards = { + "spe_mardroeme": { + "name": "Mardroeme", + "deck": "special skellige", + "row": "", + "strength": "", + "ability": "mardroeme", + "filename": "mardroeme", + "count": "3", + "quote": "Eat enough of them, and the world will never be the same..." + }, + "spe_skellige_fleet": { + "name": "Skellige Fleet", + "deck": "special skellige", + "row": "", + "strength": "", + "ability": "skellige_fleet", + "filename": "skellige_fleet", + "count": "3", + "quote": "Look at the horizon! They are coming!" + }, + "spe_storm": { + "name": "Skellige Storm", + "deck": "weather skellige", + "row": "", + "strength": "", + "ability": "storm", + "filename": "storm", + "count": "2", + "quote": "This ain't no normal storm. This here's the wrath of the gods." + }, + "sk_crach_an_craite": { + "name": "Crach an Craite", + "deck": "skellige", + "row": "leader", + "strength": "", + "ability": "crach_an_craite", + "filename": "crach_an_craite", + "count": "0", + "quote": "A king's gotta be wise. A king's gotta command respect. A king's gotta have stones." + }, + "sk_king_bran": { + "name": "Bran an Tuirseach: Iron King", + "deck": "skellige", + "row": "leader", + "strength": "", + "ability": "king_bran", + "filename": "king_bran", + "count": "0", + "quote": "No one can replace Bran. Though they're sure to try." + }, + "sk_birna": { + "name": "Birna Bran: Conspirator", + "deck": "skellige", + "row": "leader", + "strength": "", + "ability": "birna", + "filename": "birna", + "count": "0", + "quote": "Skellige must have a strong king. No matter what it takes." + }, + "sk_madman_lugos": { + "name": "Lugos an Drummond: Madman", + "deck": "skellige", + "row": "leader", + "strength": "", + "ability": "madman_lugos", + "filename": "madman_lugos", + "count": "0", + "quote": "WAAAAAAAGH!!!!" + }, + "sk_holger": { + "name": "Holger an Dimun: Blackhand", + "deck": "skellige", + "row": "leader", + "strength": "", + "ability": "holger_blakhand", + "filename": "holger_blakhand", + "count": "0", + "quote": "Now let's drink to Emperor of Nilfgaard - may his prick forever stay limp!" + }, + "sk_arnvald": { + "name": "Arnvald", + "deck": "skellige", + "row": "close", + "strength": "2", + "ability": "mardroeme", + "filename": "arnvald", + "count": "1", + "quote": "His name on the island was synonymous with loyalty. For a time." + }, + "sk_kambi": { + "name": "Kambi", + "deck": "skellige", + "row": "close", + "strength": "0", + "ability": "avenger", + "filename": "kambi", + "count": "1", + "target": "sk_hemdall", + "quote": "When the time comes, the cockerel Kambi shall crow and awaken Hemdall." + }, + "sk_shield_maiden_1": { + "name": "Clan Drummond Shield Maiden", + "id": 1, + "deck": "skellige", + "row": "close", + "strength": "4", + "ability": "bond", + "filename": "shield_maiden_1", + "count": "1", + "target": "sk_shield_maiden", + "quote": "They'll shatter on our shields like waves on a rocky shore." + }, + "sk_shield_maiden_2": { + "name": "Clan Drummond Shield Maiden", + "id": 2, + "deck": "skellige", + "row": "close", + "strength": "4", + "ability": "bond", + "filename": "shield_maiden_2", + "count": "1", + "target": "sk_shield_maiden", + "quote": "They'll shatter on our shields like waves on a rocky shore." + }, + "sk_shield_maiden_3": { + "name": "Clan Drummond Shield Maiden", + "id": 3, + "deck": "skellige", + "row": "close", + "strength": "4", + "ability": "bond", + "filename": "shield_maiden_3", + "count": "1", + "target": "sk_shield_maiden", + "quote": "They'll shatter on our shields like waves on a rocky shore." + }, + "sk_draig": { + "name": "Draig Bon-Dhu", + "deck": "skellige", + "row": "close", + "strength": "3", + "ability": "horn", + "filename": "draig", + "count": "1", + "quote": "Hear ye now the tale of the heroic deeds of Clan an Craite." + }, + "sk_donar": { + "name": "Donar an Hindar", + "deck": "skellige", + "row": "close", + "strength": "8", + "ability": "", + "filename": "donar", + "count": "1", + "quote": "I've gathered all the jarls together. Now make your case." + }, + "sk_craite_warrior_1": { + "name": "Clan an Craite Warrior", + "id": 1, + "deck": "skellige", + "row": "close", + "strength": "6", + "ability": "bond", + "filename": "craite_warrior_1", + "count": "1", + "target": "sk_craite_warrior", + "quote": "I'll bring the an Craites such glory, bards'll go hoarse singin' me praises!" + }, + "sk_craite_warrior_2": { + "name": "Clan an Craite Warrior", + "id": 2, + "deck": "skellige", + "row": "close", + "strength": "6", + "ability": "bond", + "filename": "craite_warrior_2", + "count": "1", + "target": "sk_craite_warrior", + "quote": "I'll bring the an Craites such glory, bards'll go hoarse singin' me praises!" + }, + "sk_ciri": { + "name": "Cirilla Fiona Elen Riannon", + "deck": "skellige", + "row": "close", + "strength": "12", + "ability": "hero", + "filename": "ciri", + "count": "1", + "quote": "Know when fairy tales cease to be tales? When people start believing in them." + }, + "sk_geralt": { + "name": "Geralt of Rivia", + "deck": "skellige", + "row": "close", + "strength": "12", + "ability": "hero", + "filename": "geralt", + "count": "1", + "quote": "If that's what it takes to save the world, it's better to let that world die." + }, + "sk_cerys": { + "name": "Cerys", + "id": 4, + "deck": "skellige", + "row": "close", + "strength": "7", + "ability": "hero invoke", + "filename": "cerys", + "count": "1", + "target": "sk_shield_maiden", + "quote": "They call me Sparrowhawk, know why? Because I eat rats like you for breakfast." + }, + "sk_hemdall": { + "name": "Hemdall", + "deck": "skellige", + "row": "close", + "strength": "11", + "ability": "hero", + "filename": "hemdall", + "count": "1", + "quote": "When the time of the White Frost comes, Hemdall will sound the call for battle." + }, + "sk_hjalmar": { + "name": "Hjalmar an Craite", + "deck": "skellige", + "row": "close", + "strength": "10", + "ability": "hero morale", + "filename": "hjalmar", + "count": "1", + "quote": "Instead of mournin' the fallen, let's drink to their memory!" + }, + "sk_young_berserker_1": { + "name": "Young Berserker", + "id": 1, + "deck": "skellige", + "row": "agile_cr", + "strength": "3", + "ability": "berserker", + "filename": "young_berserker_1", + "count": "1", + "target": "sk_transformed_young_berserker", + "quote": "Want some?" + }, + "sk_young_berserker_2": { + "name": "Young Berserker", + "id": 2, + "deck": "skellige", + "row": "agile_cr", + "strength": "3", + "ability": "berserker", + "filename": "young_berserker_2", + "count": "1", + "target": "sk_transformed_young_berserker", + "quote": "Blood for Svalblod! Skulls for his throne!" + }, + "sk_young_berserker_3": { + "name": "Young Berserker", + "id": 3, + "deck": "skellige", + "row": "agile_cr", + "strength": "3", + "ability": "berserker", + "filename": "young_berserker_3", + "count": "1", + "target": "sk_transformed_young_berserker", + "quote": "Strike me! C'mon, harder! You call this pain?" + }, + "sk_transformed_young_berserker": { + "name": "Transformed Young Berserker", + "id": 1, + "deck": "skellige", + "row": "agile_cr", + "strength": "9", + "ability": "bond", + "filename": "transformed_young_berserker", + "count": "0", + "target": "sk_transformed_young_berserker", + "quote": "Rooaaar!" + }, + "sk_vildkaarl": { + "name": "Vildkaarl", + "deck": "skellige", + "row": "agile_cr", + "strength": "4", + "ability": "berserker", + "filename": "vildkaarl", + "count": "1", + "target": "sk_transformed_vildkaarl", + "quote": "Kill, crush, cleave!" + }, + "sk_berserker": { + "name": "Berserker", + "deck": "skellige", + "row": "agile_cr", + "strength": "5", + "ability": "berserker", + "filename": "berserker", + "count": "1", + "target": "sk_transformed_berserker", + "quote": "Mercenaries fight for coin. Knights duel for honor. He kills for blood." + }, + "sk_transformed_vildkaarl": { + "name": "Transformed Vildkaarl", + "deck": "skellige", + "row": "agile_cr", + "strength": "14", + "ability": "scorch", + "filename": "transformed_vildkaarl", + "count": "0", + "quote": "Saw them fight once in my life... and once was enough." + }, + "sk_transformed_berserker": { + "name": "Transformed Berserker", + "deck": "skellige", + "row": "agile_cr", + "strength": "16", + "ability": "morale", + "filename": "transformed_berserker", + "count": "0", + "quote": "This bear taste funny to you? " + }, + "sk_blueboy": { + "name": "Blueboy Lugos", + "deck": "skellige", + "row": "agile_cr", + "strength": "6", + "ability": "", + "filename": "blueboy", + "count": "1", + "quote": "I'm damn near ready to puke from boredom." + }, + "sk_gremist": { + "name": "Gremist", + "deck": "skellige", + "row": "ranged", + "strength": "3", + "ability": "medic", + "filename": "gremist", + "count": "1", + "quote": "An archdruid, a master of alchemy, and the grumpiest old fart in the Isles." + }, + "sk_brokva_archer": { + "name": "Clan Brokvar Archer", + "deck": "skellige", + "row": "ranged", + "strength": "8", + "ability": "", + "filename": "brokva_archer", + "count": "1", + "quote": "So ye can hit a movin' target at two hundred paces. Me, too. In a storm." + }, + "sk_ermion": { + "name": "Ermion", + "deck": "skellige", + "row": "ranged", + "strength": "7", + "ability": "hero mardroeme", + "filename": "ermion", + "count": "1", + "quote": "Only the ignorant dismiss the importance of myths." + }, + "sk_yennefer": { + "name": "Yennefer of Vengerberg", + "deck": "skellige", + "row": "ranged", + "strength": "7", + "ability": "hero medic", + "filename": "yennefer", + "count": "1", + "quote": "Magic is Chaos, Art and Science. It is a curse, a blessing and a progression." + }, + "sk_longship_1": { + "name": "Longship: Black Helga", + "id": 1, + "deck": "skellige", + "row": "siege", + "strength": "6", + "ability": "bond", + "filename": "longship_1", + "count": "1", + "target": "sk_longship", + "quote": "You can't take it upriver, but you can certainly take it to the cahse of the imperial fleet." + }, + "sk_longship_2": { + "name": "Longship: Ulfhedinn", + "id": 2, + "deck": "skellige", + "row": "siege", + "strength": "6", + "ability": "bond", + "filename": "longship_2", + "count": "1", + "target": "sk_longship", + "quote": "Ulfhedinn? Is it a fish? Oh, no, no... this is something far, far worse." + }, + "sk_longship_3": { + "name": "Longship: Ragnarök", + "id": 3, + "deck": "skellige", + "row": "siege", + "strength": "6", + "ability": "bond", + "filename": "longship_3", + "count": "1", + "target": "sk_longship", + "quote": "The sea's ours, along with everythin' that floats, swims or sails in it!" + }, + "sk_war_longship": { + "name": "War Longship: Sea Terror", + "deck": "skellige", + "row": "siege", + "strength": "8", + "ability": "", + "filename": "war_longship", + "count": "1", + "quote": "Merely mention this name to a Nilfgaardian, and they'll feel a spreading warmth in their knickers." + }, + "sk_light_longship_1": { + "name": "Light Longship: Sail Hound", + "id": 1, + "deck": "skellige", + "row": "siege", + "strength": "4", + "ability": "muster", + "filename": "light_longship_1", + "count": "1", + "target": "sk_light_longship", + "quote": "They are light and fast, perfect for racing down slow merchant frigates." + }, + "sk_light_longship_2": { + "name": "Light Longship: Sea Vulture", + "id": 2, + "deck": "skellige", + "row": "siege", + "strength": "4", + "ability": "muster", + "filename": "light_longship_2", + "count": "1", + "target": "sk_light_longship", + "quote": "Escape them? In the waters of Skellige? Good luck." + }, + "sk_light_longship_3": { + "name": "Light Longship: Wave Horse", + "id": 3, + "deck": "skellige", + "row": "siege", + "strength": "4", + "ability": "muster", + "filename": "light_longship_3", + "count": "1", + "target": "sk_light_longship", + "quote": "All it takes is a small hole for the largest ship to sink." + } +}; + +var ext_re_cards = { + "spe_execution": { + "name": "Execution", + "deck": "special redania", + "row": "", + "strength": "", + "ability": "scorch", + "filename": "execution", + "count": "3", + "quote": "I can't bloody breathe! Won't they burn the wretches someplace else?" + }, + "spe_royal_decree": { + "name": "Royal Decree", + "deck": "special redania", + "row": "", + "strength": "", + "ability": "royal_decree", + "filename": "royal_decree", + "count": "3", + "quote": "...do hereby decree the following..." + }, + "re_radovid_king_redania": { + "name": "Radovid: King of Redania", + "deck": "redania", + "row": "leader", + "strength": "", + "ability": "radovid_king_redania", + "filename": "radovid_king_redania", + "count": "1", + "quote": "Judge. Jury. Excecutioner. King." + }, + "re_radovid_mad_king": { + "name": "Radovid: Mad King", + "deck": "redania", + "row": "leader", + "strength": "", + "ability": "radovid_mad_king", + "filename": "radovid_mad_king", + "count": "1", + "quote": "A king should be merciless towards his enemies and generous to his friends." + }, + "re_radovid_strategist": { + "name": "Radovid: Strategist", + "deck": "redania", + "row": "leader", + "strength": "", + "ability": "radovid_strategist", + "filename": "radovid_strategist", + "count": "1", + "quote": "They say chess teaches one ot think strategically. What a load of rubbish!" + }, + "re_redanian_knight_1": { + "name": "Redanian Knight", + "id": 1, + "deck": "redania", + "row": "close", + "strength": "6", + "ability": "bond", + "filename": "redanian_knight_1", + "target": "re_redanian_knight", + "count": "1", + "quote": "For glory! For Radovid!" + }, + "re_redanian_knight_2": { + "name": "Redanian Knight", + "id": 2, + "deck": "redania", + "row": "close", + "strength": "6", + "ability": "bond", + "filename": "redanian_knight_2", + "target": "re_redanian_knight", + "count": "1", + "quote": "You can't stop a galloping cavalry horse!" + }, + "re_priscilla": { + "name": "Priscilla", + "deck": "redania", + "row": "close", + "strength": "2", + "ability": "horn", + "filename": "priscilla", + "count": "1", + "quote": "Picture Dandelion in a dress and you've got the general idea." + }, + "re_redanian_elite": { + "name": "Redanian Elite", + "deck": "redania", + "row": "close", + "strength": "8", + "ability": "", + "filename": "redanian_elite", + "count": "1", + "quote": "I'll die for Redania, I'll kill for Redania… I'll even eat worms for Redania!" + }, + "re_kurt": { + "name": "Kurt", + "deck": "redania", + "row": "close", + "strength": "5", + "ability": "witch_hunt", + "filename": "kurt", + "count": "1", + "quote": "Oy, Kurt, find out what Merigold's hollerin' about, if she needs anything. A hot iron to the tongue, maybe?" + }, + "re_witch_hunter": { + "name": "Witch Hunter", + "deck": "redania", + "row": "close", + "strength": "5", + "ability": "witch_hunt", + "filename": "witch_hunter", + "count": "1", + "quote": "Long coats, wide-brimmed hats, and crooked grins – witch hunters are hard to miss." + }, + "re_olgierd": { + "name": "Olgierd von Everec", + "deck": "redania", + "row": "close", + "strength": "4", + "ability": "immortal", + "filename": "olgierd", + "count": "1", + "quote": "At least you now know I don't easily lose my head." + }, + "re_cyprian_wiley": { + "name": "Cyprian Wiley: Whoreson Junior", + "deck": "redania", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "cyprian_wiley", + "count": "1", + "quote": "A war with Whoreson will see Novigrad's gutters run red with blood." + }, + "re_carlo_varese": { + "name": "Carlo Varese: Cleaver", + "deck": "redania", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "carlo_varese", + "count": "1", + "quote": "Me hogs willnae go hungry th' day thanks to ye." + }, + "re_geralt": { + "name": "Geralt of Rivia", + "deck": "redania", + "row": "close", + "strength": "12", + "ability": "hero", + "filename": "geralt", + "count": "1", + "quote": "If that's what it takes to save the world, it's better to let that world die." + }, + "re_trollololo": { + "name": "Trollololo", + "deck": "redania", + "row": "agile_cs", + "strength": "7", + "ability": "", + "filename": "trollololo", + "count": "1", + "quote": "Join me King Ravodid army. Order got – guard boatses." + }, + "re_caleb_menge": { + "name": "Caleb Menge", + "deck": "redania", + "row": "agile_crs", + "strength": "0", + "ability": "hero witch_hunt", + "filename": "caleb_menge", + "count": "1", + "quote": "Deceivers, heretics, witches! They flood our city, corrupt our virtue, and threaten our very way of life!" + }, + "re_gaunter_odimm": { + "name": "Gaunter O'Dimm", + "id": 1, + "deck": "redania", + "row": "ranged", + "strength": "3", + "ability": "muster", + "filename": "gaunter_odimm", + "count": "1", + "target": "ne_gaunter_odimm", + "quote": "He always grants exactly what you wish for. That's the problem." + }, + "re_gaunter_odimm_darkness": { + "name": "Gaunter O'Dimm - Darkness", + "id": 2, + "deck": "redania", + "row": "ranged", + "strength": "2", + "ability": "muster", + "filename": "gaunter_odimm_darkness", + "count": "3", + "target": "ne_gaunter_odimm", + "quote": "Fear not the shadows, but the light." + }, + "re_black_cat_dog": { + "name": "Black Cat and Dog", + "deck": "redania", + "row": "ranged", + "strength": "8", + "ability": "spy", + "filename": "black_cat_dog", + "count": "1", + "quote": "We'd rather keep our names to ourselves. Think of us as… friends of the house." + }, + "re_vlodimir_von_everec": { + "name": "Vlodimir von Everec", + "deck": "redania", + "row": "ranged", + "strength": "4", + "ability": "immortal", + "filename": "vlodimir_von_everec", + "count": "1", + "quote": "Vlodimir liked to have a good time when he was alive and greatly missed having fun after his death." + }, + "re_caretaker": { + "name": "Caretaker", + "deck": "redania", + "row": "ranged", + "strength": "6", + "ability": "medic", + "filename": "caretaker", + "count": "1", + "quote": "There are more things in heaven and earth than all the world's philosophers have dreamt." + }, + "re_rico_meiersdorf": { + "name": "Rico Meiersdorf", + "deck": "redania", + "row": "ranged", + "strength": "7", + "ability": "spy", + "filename": "rico_meiersdorf", + "count": "1", + "quote": "I never did much like bees." + }, + "re_moreelse": { + "name": "Moreelse", + "deck": "redania", + "row": "ranged", + "strength": "5", + "ability": "witch_hunt", + "filename": "moreelse", + "count": "1", + "quote": "Some witch hunters truly believed the eradication of mages and sorceresses would make the world a better place. Some did not require such justification." + }, + "re_graden": { + "name": "Graden", + "deck": "redania", + "row": "ranged", + "strength": "5", + "ability": "witch_hunt", + "filename": "graden", + "count": "1", + "quote": "Initially, we burned any tomes on black magic we found.Recently we decided it might be wise to read them first." + }, + "re_shani": { + "name": "Shani", + "deck": "redania", + "row": "ranged", + "strength": "5", + "ability": "hero medic", + "filename": "shani", + "count": "1", + "quote": "I'm a medic. I tend to know what I'm doing when I prescribe something." + }, + "re_iris_von_everec": { + "name": "Iris von Everec", + "deck": "redania", + "row": "ranged", + "strength": "0", + "ability": "hero summon_one_of", + "filename": "iris_von_everec", + "target": ["re_black_cat_dog","re_caretaker"], + "count": "1", + "quote": "I remember so little... Yet when I think of my rose, I begin to recall what was." + }, + "re_ewald_borsodi": { + "name": "Ewald Borsodi", + "deck": "redania", + "row": "agile_rs", + "strength": "7", + "ability": "", + "filename": "ewald_borsodi", + "count": "1", + "quote": "I've crafted this plan for over a year, but now the time's come for action. Can I count on your help?" + }, + "re_horst_borsodi": { + "name": "Horst Borsodi", + "deck": "redania", + "row": "agile_rs", + "strength": "7", + "ability": "", + "filename": "horst_borsodi", + "count": "1", + "quote": "My auction house is, above all, a gathering place for the elite of the elite." + }, + "re_eternal_fire_priest": { + "name": "Eternal Fire Priest", + "deck": "redania", + "row": "siege", + "strength": "5", + "ability": "witch_hunt", + "filename": "eternal_fire_priest", + "count": "1", + "quote": "Closer, my sheep, gather closer. May the Eternal Fire warm your souls!" + }, + "re_nathaniel_pastodi": { + "name": "Nathaniel Pastodi", + "deck": "redania", + "row": "siege", + "strength": "5", + "ability": "witch_hunt", + "filename": "nathaniel_pastodi", + "count": "1", + "quote": "Novigrad – where the impossible becomes possible. A professional torturer turned reverend, for instance." + }, + "re_sigi_reuven": { + "name": "Sigi Reuven", + "deck": "redania", + "row": "siege", + "strength": "10", + "ability": "hero", + "filename": "sigi_reuven", + "count": "1", + "quote": "You sure he don't look the least bit familar...?" + }, + "re_francis_bedlam": { + "name": "Francis Bedlam: King of Beggars", + "deck": "redania", + "row": "siege", + "strength": "10", + "ability": "hero", + "filename": "francis_bedlam", + "count": "1", + "quote": "You say tribute, I say taxes." + }, + "re_cyrus_hemmelfart": { + "name": "Cyrus Hemmelfart: Hierarch of Novigrad", + "deck": "redania", + "row": "siege", + "strength": "2", + "ability": "hero scorch", + "filename": "cyrus_hemmelfart", + "count": "1", + "quote": "Beneath all that lust, greed, and vanity, stands an honorable man." + }, +}; + +var ext_to_cards = { + "spe_toussaint_wine": { + "name": "Toussaint Wine", + "deck": "special toussaint", + "row": "", + "strength": "", + "ability": "toussaint_wine", + "filename": "toussaint_wine", + "count": "3", + "quote": "To honour our fair knights, we shall feast from eve till dawn's first light!" + }, + "to_anna_henrietta_duchess": { + "name": "Anna Henrietta: Duchess of Toussaint", + "deck": "toussaint", + "row": "leader", + "strength": "", + "ability": "anna_henrietta_duchess", + "filename": "anna_henrietta_duchess", + "count": "1", + "quote": "Fair knights I salute you." + }, + "to_anna_henrietta_ladyship": { + "name": "Anna Henrietta: Her Enlightened Ladyship", + "deck": "toussaint", + "row": "leader", + "strength": "", + "ability": "anna_henrietta_ladyship", + "filename": "anna_henrietta_ladyship", + "count": "1", + "quote": "Impertinence is the one thing I cannot abide." + }, + "to_anna_henrietta_little_weasel": { + "name": "Anna Henrietta: Little Weasel", + "deck": "toussaint", + "row": "leader", + "strength": "", + "ability": "anna_henrietta_little_weasel", + "filename": "anna_henrietta_little_weasel", + "count": "1", + "quote": "You have sworn your vows, you have readied body and soul. The time has come to test them." + }, + "to_gregoire_gorgon": { + "name": "Gregoire de Gorgon", + "deck": "toussaint", + "row": "close", + "strength": "8", + "ability": "", + "filename": "gregoire_gorgon", + "count": "1", + "quote": "Gregoire? That mountain o' muscle wrapped in armor? Course, I 'eard of 'im! Who hasn't?" + }, + "to_knight_errant_1": { + "name": "Knights-Errant", + "id": 1, + "deck": "toussaint", + "row": "close", + "strength": "4", + "ability": "muster", + "filename": "knight_errant_1", + "count": "1", + "target": "to_knight_errant", + "quote": "Abandon the path of shame and we will spare you." + }, + "to_knight_errant_2": { + "name": "Knights-Errant", + "id": 2, + "deck": "toussaint", + "row": "close", + "strength": "4", + "ability": "muster", + "filename": "knight_errant_2", + "count": "1", + "target": "to_knight_errant", + "quote": "Abandon the path of shame and we will spare you." + }, + "to_bootblack": { + "name": "Bootblack", + "deck": "toussaint", + "row": "close", + "strength": "5", + "ability": "spy", + "filename": "bootblack", + "count": "1", + "quote": "Wouldn't be looking for work, would you? We'd make a fine duo." + }, + "to_toussaint_knight_1": { + "name": "Toussaint Knight", + "id": 1, + "deck": "toussaint", + "row": "close", + "strength": "3", + "ability": "muster", + "filename": "toussaint_knight_1", + "count": "1", + "target": "to_toussaint_knight", + "quote": "I swear upon the heron you will pay with your own blood." + }, + "to_toussaint_knight_2": { + "name": "Toussaint Knight", + "id": 2, + "deck": "toussaint", + "row": "close", + "strength": "3", + "ability": "muster", + "filename": "toussaint_knight_2", + "count": "1", + "target": "to_toussaint_knight", + "quote": "I swear upon the heron you will pay with your own blood." + }, + "to_toussaint_knight_3": { + "name": "Toussaint Knight", + "id": 3, + "deck": "toussaint", + "row": "close", + "strength": "3", + "ability": "muster", + "filename": "toussaint_knight_3", + "count": "1", + "target": "to_toussaint_knight", + "quote": "I swear upon the heron you will pay with your own blood." + }, + "to_minstrel": { + "name": "Minstrel", + "deck": "toussaint", + "row": "close", + "strength": "1", + "ability": "horn", + "filename": "minstrel", + "count": "1", + "quote": "There was a knight who drunk with wine. A ridding along the way sir; And there he met with a lady fine, Among the cocks of hay, sir..." + }, + "to_regis": { + "name": "Regis", + "deck": "toussaint", + "row": "close", + "strength": "4", + "ability": "monster_toussaint", + "filename": "regis", + "count": "1", + "target": "to_regis_higher_vampire", + "meta": ["toussaint_monster_level_1"], + "quote": "Some consider me a monster. A blood-crazed, savage monster." + }, + "to_regis_higher_vampire": { + "name": "Regis: Higher Vampire", + "deck": "toussaint", + "row": "close", + "strength": "4", + "ability": "scorch_c", + "filename": "regis_higher_vampire", + "count": "0", + "target": "to_regis", + "meta": ["toussaint_monster_level_2"], + "quote": "His glance hypnotizes into a deep sleep. He then drinks his fill, turns into a bat and flies off." + }, + "to_damien_tour": { + "name": "Damien de la Tour", + "deck": "toussaint", + "row": "close", + "strength": "9", + "ability": "hero morale", + "filename": "damien_tour", + "count": "1", + "quote": "I served Beauclair well. At least... I hope I did." + }, + "to_geralt": { + "name": "Geralt of Rivia", + "deck": "toussaint", + "row": "close", + "strength": "12", + "ability": "hero", + "filename": "geralt", + "count": "1", + "quote": "If that's what it takes to save the world, it's better to let that world die." + }, + "to_dettlaff": { + "name": "Dettlaff", + "deck": "toussaint", + "row": "close", + "strength": "5", + "ability": "hero monster_toussaint", + "filename": "dettlaff", + "count": "1", + "target": "to_dettlaff_higher_vampire", + "meta": ["toussaint_monster_level_1"], + "quote": "He did not love like a man, but like an animal. Madly, deeply, unconditionally. Wildly." + }, + "to_dettlaff_higher_vampire": { + "name": "Dettlaff: Higher Vampire", + "deck": "toussaint", + "row": "close", + "strength": "8", + "ability": "hero scorch", + "filename": "dettlaff_higher_vampire", + "count": "0", + "target": "to_dettlaff", + "meta": ["toussaint_monster_level_2"], + "quote": "He did not love like a man, but like an animal. Madly, deeply, unconditionally. Wildly." + }, + "to_champion": { + "name": "Tournament Champion", + "deck": "toussaint", + "row": "agile_cr", + "strength": "7", + "ability": "", + "filename": "champion", + "count": "1", + "quote": "Your presence at this tourney is an affront to my honor!" + }, + "to_milton": { + "name": "Milton de Peyrac-Peyran", + "id": 1, + "deck": "toussaint", + "row": "agile_cr", + "strength": "7", + "ability": "", + "filename": "milton", + "count": "1", + "quote": "Glinting under the rays of the Beauclair sun, there was no mistaking this knight-errant who bore the head of a great, white bull on his shield." + }, + "to_lui_alberni": { + "name": "Lui Alberni", + "deck": "toussaint", + "row": "agile_cr", + "strength": "4", + "ability": "monster_toussaint", + "filename": "lui_alberni", + "count": "1", + "target": "to_lui_alberni_golyat", + "meta": ["toussaint_monster_level_1"], + "quote": "Some claim Golyat was once a famous knight..." + }, + "to_lui_alberni_golyat": { + "name": "Lui Alberni: Golyat", + "deck": "toussaint", + "row": "agile_cr", + "strength": "4", + "ability": "decoy", + "filename": "lui_alberni_golyat", + "count": "0", + "target": "to_lui_alberni", + "meta": ["toussaint_monster_level_2"], + "quote": "Some claim Golyat was once a famous knight..." + }, + "to_barnabas": { + "name": "Barnabas Basil-Foulty", + "deck": "toussaint", + "row": "ranged", + "strength": "0", + "ability": "toussaint_wine", + "filename": "barnabas", + "count": "1", + "quote": "I shall serve you as majordomo of Corvo Bianco." + }, + "to_vivienne": { + "name": "Vivienne", + "deck": "toussaint", + "row": "ranged", + "strength": "0", + "ability": "monster_toussaint", + "filename": "vivienne", + "count": "1", + "target": "to_vivienne_oriole", + "meta": ["toussaint_monster_level_1"], + "quote": "Vivienne's a bit of an odd duck for a lady-in-waitin'. But by the Gods, ye can't deny her beauty an' grace!" + }, + "to_vivienne_oriole": { + "name": "Vivienne: Oriole", + "deck": "toussaint", + "row": "ranged", + "strength": "7", + "ability": "spy", + "filename": "vivienne_oriole", + "count": "0", + "target": "to_vivienne", + "meta": ["toussaint_monster_level_2"], + "quote": "Who'd not like to live free as a bird? Well, just ask Vivienne de Tabris." + }, + "to_marlene": { + "name": "Marlene: Wight", + "deck": "toussaint", + "row": "ranged", + "strength": "6", + "ability": "", + "filename": "marlene", + "count": "1", + "quote": "None shall sit and dine with you at your table, no spoon you have shall sate you, never again shall you wish to spy your reflection in the mirror." + }, + "to_orianna": { + "name": "Orianna", + "deck": "toussaint", + "row": "ranged", + "strength": "4", + "ability": "monster_toussaint", + "filename": "orianna", + "count": "1", + "target": "to_orianna_bruxa", + "meta": ["toussaint_monster_level_1"], + "quote": "Wolves asleep amidst the trees, Bats all swaying in the breeze..." + }, + "to_orianna_bruxa": { + "name": "Orianna", + "deck": "toussaint", + "row": "ranged", + "strength": "4", + "ability": "scorch_r", + "filename": "orianna_bruxa", + "count": "0", + "target": "to_orianna", + "meta": ["toussaint_monster_level_2"], + "quote": "...but one soul lies anxious, wide awake, fearing the manner of ghouls, hags and wraiths." + }, + "to_artorius_vigo": { + "name": "Artorius Vigo", + "deck": "toussaint", + "row": "ranged", + "strength": "0", + "ability": "medic", + "filename": "artorius_vigo", + "count": "1", + "quote": "It is said he created an illusion so realistic that he began to believe it himself..." + }, + "to_witch_lynx_crag": { + "name": "Witch of Lynx Crag", + "deck": "toussaint", + "row": "ranged", + "strength": "8", + "ability": "", + "filename": "witch_lynx_crag", + "count": "1", + "quote": "Lives in a hut atop Lynx Crag and is feared by many of the locals." + }, + "to_guillaume": { + "name": "Guillaume de Launfal", + "id": 1, + "deck": "toussaint", + "row": "ranged", + "strength": "3", + "ability": "muster", + "filename": "guillaume", + "count": "1", + "target": "to_guillaume_palmerin", + "quote": "Guillaume was the very model of a knight-errant - the placard boy for Toussaint." + }, + "to_palmerin": { + "name": "Palmerin de Launfal", + "id": 2, + "deck": "toussaint", + "row": "close", + "strength": "4", + "ability": "muster", + "filename": "palmerin", + "count": "1", + "target": "to_guillaume_palmerin", + "quote": "Rumor had it the esteemed baron Palmerin de Launfal had fallen into a profane affair with a succubus." + }, + "to_duchess_informant": { + "name": "Duchess Informant", + "deck": "toussaint", + "row": "ranged", + "strength": "6", + "ability": "spy", + "filename": "duchess_informant", + "count": "1", + "quote": "Anna Henrietta wakes every morn to the tune of her songbirds." + }, + "to_prophet_lebioda": { + "name": "Prophet Lebioda", + "deck": "toussaint", + "row": "ranged", + "strength": "3", + "ability": "medic", + "filename": "prophet_lebioda", + "count": "1", + "quote": "To thine own self be judge and ruler for thou alone shalt answer for thine deeds before thee." + }, + "to_roderick": { + "name": "Roderick of Dun Tynne", + "deck": "toussaint", + "row": "ranged", + "strength": "9", + "ability": "hero morale", + "filename": "roderick", + "count": "1", + "quote": "Roderick lived as a recluse, avoiding society at large." + }, + "to_unseen_elder": { + "name": "Unseen Elder", + "deck": "toussaint", + "row": "ranged", + "strength": "12", + "ability": "hero", + "filename": "unseen_elder", + "count": "1", + "quote": "No one, not even among the higher vampires, knows exactly how old the Unseen Elder is." + }, + "to_syanna": { + "name": "Sylvia Anna", + "deck": "toussaint", + "row": "siege", + "strength": "6", + "ability": "hero spy", + "filename": "syanna", + "count": "1", + "quote": "Your Majesty... The princess has been touched by the curse o' the Black Sun. There's no hope, I'm afraid..." + }, + "to_lady_lake": { + "name": "Lade of the Lake", + "deck": "toussaint", + "row": "siege", + "strength": "0", + "ability": "hero aerondight", + "filename": "lady_lake", + "count": "1", + "quote": "Take this sword as a sign of my favor. For centuries it lay in these depths, waiting... for you." + }, +}; + +var ext_ve_cards = { + "spe_curse": { + "name": "Curse", + "deck": "special velen", + "row": "", + "strength": "", + "ability": "curse", + "filename": "curse", + "count": "3", + "quote": "Anyone who comes here will die in terrible agony." + }, + "ve_lady_wood_brewess": { + "name": "Ladies of the Wood: Brewess", + "deck": "velen", + "row": "leader", + "strength": "", + "ability": "lady_wood_brewess", + "filename": "lady_wood_brewess", + "count": "1", + "quote": "We'll cut you up, boy. A fina broth you will make." + }, + "ve_lady_wood_weavess": { + "name": "Ladies of the Wood: Weavess", + "deck": "velen", + "row": "leader", + "strength": "", + "ability": "lady_wood_weavess", + "filename": "lady_wood_weavess", + "count": "1", + "quote": "I sense your pain. I see your fear..." + }, + "ve_lady_wood_whispess": { + "name": "Ladies of the Wood: Whispess", + "deck": "velen", + "row": "leader", + "strength": "", + "ability": "lady_wood_whispess", + "filename": "lady_wood_whispess", + "count": "1", + "quote": "I'll be your best - and last." + }, + "ve_ghost_tree": { + "name": "The Ghost in the Tree", + "deck": "velen", + "row": "leader", + "strength": "0", + "ability": "ghost_tree", + "filename": "ghost_tree", + "count": "1", + "quote": "A lot of mystery surrounds the spirit but one thing appears to be certain: the Crones killed her, then captured her spirit and imprisoned it in the tree." + }, + "ve_cutthroat": { + "name": "Cutthroat", + "deck": "velen", + "row": "close", + "strength": "6", + "ability": "", + "filename": "cutthroat", + "count": "1", + "quote": "Ahhh, nothin' so soothin' as the sound of gurglin' blood." + }, + "ve_angry_peasants": { + "name": "Angry peasants", + "deck": "velen", + "row": "close", + "strength": "3", + "ability": "scorch_c", + "filename": "angry_peasants", + "count": "1", + "quote": "Wanna know their problem? They are always hungry." + }, + "ve_deserter_1": { + "name": "Deserter", + "id": 1, + "deck": "velen", + "row": "close", + "strength": "4", + "ability": "bond", + "filename": "deserter_1", + "count": "1", + "target": "ve_deserter", + "quote": "Fuck the army." + }, + "ve_deserter_2": { + "name": "Deserter", + "id":2, + "deck": "velen", + "row": "close", + "strength": "4", + "ability": "bond", + "filename": "deserter_2", + "count": "1", + "target": "ve_deserter", + "quote": "Fuck the king!" + }, + "ve_marauder_1": { + "name": "Marauder", + "id": 1, + "deck": "velen", + "row": "close", + "strength": "4", + "ability": "bond", + "filename": "marauder_1", + "count": "1", + "target": "ve_marauder", + "quote": "We'll torture the merchant and sell the horses." + }, + "ve_marauder_2": { + "name": "Marauder", + "id": 2, + "deck": "velen", + "row": "close", + "strength": "4", + "ability": "bond", + "filename": "marauder_2", + "count": "1", + "target": "ve_marauder", + "quote": "It's because we're free to do whatever we want! Ha, ha ha!" + }, + "ve_abandoned_girl": { + "name": "Abandoned Girl", + "deck": "velen", + "row": "close", + "strength": "0", + "ability": "bait", + "filename": "abandoned_girl", + "count": "1", + "quote": "Local peasants leave children in the forest as a gift to the Ladies of the Wood." + }, + "ve_bloody_baron": { + "name": "Bloody Baron", + "deck": "velen", + "row": "close", + "strength": "8", + "ability": "hero morale", + "filename": "bloody_baron", + "count": "1", + "quote": "I've not been a good father. But I've certainly been a good warrior!" + }, + "ve_ciri": { + "name": "Cirilla", + "deck": "velen", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "ciri", + "count": "1", + "quote": "Where am I? What is this dreadful place?" + }, + "ve_geralt": { + "name": "Geralt of Rivia", + "deck": "velen", + "row": "close", + "strength": "6", + "ability": "hero scorch", + "filename": "geralt", + "count": "1", + "quote": "Whom should I kill this time?" + }, + "ve_vesemir": { + "name": "Vesemir", + "deck": "velen", + "row": "close", + "strength": "6", + "ability": "hero scorch", + "filename": "vesemir", + "count": "1", + "quote": "If you're to be hanged, ask for water. Anything can happen before they fetch it." + }, + "ve_water_hag": { + "name": "Water Hag", + "deck": "velen", + "row": "agile_cr", + "strength": "5", + "ability": "", + "filename": "water_hag", + "count": "1", + "quote": "Folk say water hags are drowner's wives. If that be true, 'tain't no wonder why they're such ornery bitches." + }, + "ve_allgod": { + "name": "Allgod", + "deck": "velen", + "row": "agile_cr", + "strength": "4", + "ability": "morale", + "filename": "allgod", + "count": "1", + "quote": "Make your sacrifices or face divine anger! The food better be good or prepare to face my wrath nonetheless." + }, + "ve_drowner": { + "name": "Drowner", + "deck": "velen", + "row": "agile_cr", + "strength": "5", + "ability": "", + "filename": "drowner", + "count": "1", + "quote": "Though the witchman lusts for gold, for the smiting of a drowner thou shalt give him but a silver penny, or three halfpence, at most." + }, + "ve_ghoul_1": { + "name": "Ghoul", + "id": 1, + "deck": "velen", + "row": "ranged", + "strength": "4", + "ability": "bond", + "filename": "ghoul_1", + "count": "1", + "target": "ve_ghoul", + "quote": "If ghouls are part of the Circle of Life... then it's a damn vicious circle." + }, + "ve_ghoul_2": { + "name": "Ghoul", + "id": 2, + "deck": "velen", + "row": "ranged", + "strength": "4", + "ability": "bond", + "filename": "ghoul_2", + "count": "1", + "target": "ve_ghoul", + "quote": "A frequent visitor of the battlefields." + }, + "ve_hungry_wolves_1": { + "name": "Hungry Wolves", + "id": 1, + "deck": "velen", + "row": "ranged", + "strength": "2", + "ability": "muster", + "filename": "hungry_wolves_1", + "count": "1", + "target": "ve_hungry_wolves", + "quote": "Surrounded by that pack of wolves, we felt like three little pigs." + }, + "ve_hungry_wolves_2": { + "name": "Hungry Wolves", + "id": 2, + "deck": "velen", + "row": "ranged", + "strength": "2", + "ability": "muster", + "filename": "hungry_wolves_2", + "count": "1", + "target": "ve_hungry_wolves", + "quote": "Wolves came out of the forest, ate the cattle and then surrounded the house. They were howling madly." + }, + "ve_hungry_wolves_3": { + "name": "Hungry Wolves", + "id": 3, + "deck": "velen", + "row": "ranged", + "strength": "2", + "ability": "muster", + "filename": "hungry_wolves_3", + "count": "1", + "target": "ve_hungry_wolves", + "quote": "'Relax, I know how to tame wolves...' - Dunbar the Hunter's last words." + }, + "ve_hungry_wolves_4": { + "name": "Hungry Wolves", + "id": 4, + "deck": "velen", + "row": "ranged", + "strength": "3", + "ability": "muster", + "filename": "hungry_wolves_4", + "count": "1", + "target": "ve_hungry_wolves", + "quote": "Just like any beast, he deals with them swiftly and carefully." + }, + "ve_noonwraith": { + "name": "Noonwraith", + "deck": "velen", + "row": "ranged", + "strength": "6", + "ability": "", + "filename": "noonwraith", + "count": "1", + "quote": "They are born of some horrible tragedy tied to ill-fated love." + }, + "ve_penitent": { + "name": "Penitent", + "deck": "velen", + "row": "ranged", + "strength": "6", + "ability": "", + "filename": "penitent", + "count": "1", + "quote": "The places this monster haunts are quickly covered by fog and darkness. Those that get lost in it usually don't return to the living." + }, + "ve_nightwraith": { + "name": "Nightwraith", + "deck": "velen", + "row": "ranged", + "strength": "6", + "ability": "", + "filename": "nightwraith", + "count": "1", + "quote": "How much damage can a pale, emaciated woman, entangled in a ripped dress, do? A lot, it turns out." + }, + + "ve_fiend": { + "name": "Fiend", + "deck": "velen", + "row": "siege", + "strength": "6", + "ability": "bond", + "filename": "fiend", + "count": "1", + "quote": "A fiend looks like a deer. An enormous, evil deer." + }, + "ve_chort": { + "name": "Chort", + "deck": "velen", + "row": "siege", + "strength": "6", + "ability": "bond", + "filename": "chort", + "count": "1", + "quote": "Chorts are smaller than fiends, true. But still big enough to kill." + }, + "ve_fugas": { + "name": "Fugas", + "deck": "velen", + "row": "siege", + "strength": "7", + "ability": "", + "filename": "fugas", + "count": "1", + "quote": "Heh, givin' me orders? You? A human?" + }, + "ve_tamara_strenger": { + "name": "Tamara Strenger", + "deck": "velen", + "row": "siege", + "strength": "4", + "ability": "hero medic", + "filename": "tamara_strenger", + "count": "1", + "quote": "Once the heat of the Fire has set your heart aflame, it gives you strength and leads you down the path of truth for the rest of your life." + }, + "ve_johnny": { + "name": "Johnny", + "deck": "velen", + "row": "siege", + "strength": "8", + "ability": "hero spy", + "filename": "johnny", + "count": "1", + "quote": "Peter Piper picked Prince Proximo a peck of pickled peppers by the Pontar." + }, + "ve_thecla": { + "name": "Thecla", + "deck": "velen", + "row": "siege", + "strength": "4", + "ability": "hero soothsayer", + "filename": "thecla", + "count": "1", + "quote": "She was a very old, blind woman that was considered to be wise by the locals." + }, + "ve_anna_strenger": { + "name": "Anna Strenger", + "deck": "velen", + "row": "siege", + "strength": "4", + "ability": "hero soothsayer", + "filename": "anna_strenger", + "count": "1", + "quote": "Anna hated her husband so much that she was ready to do anything in order to be free of the man — and the child he had put inside her." + }, + "ve_pellar": { + "name": "Pellar", + "deck": "velen", + "row": "siege", + "strength": "4", + "ability": "hero soothsayer", + "filename": "pellar", + "count": "1", + "quote": "Gather spirits for this wake, A passing soul ne'er forsake, Hear my call, my humble plea, Unbind his chains, set him free." + }, +}; + +var ext_wu_cards = { + "wu_vilgefortz_magician_kovir": { + "name": "Vilgefortz: Magician of Kovir", + "deck": "witcher_universe", + "row": "leader", + "strength": "", + "ability": "vilgefortz_magician_kovir", + "filename": "vilgefortz_magician_kovir", + "count": "1", + "quote": "The nature does not have the knowledge of the philosophical thought." + }, + "wu_tissaia": { + "name": "Tissaia de Vries", + "deck": "witcher_universe", + "row": "ranged", + "strength": "6", + "ability": "medic", + "filename": "tissaia", + "count": "1", + "quote": "They will not enter here. No one invited those royalist lackeys, who carry out the orders of their short-sighted kings!" + }, + "wu_rats_giselher": { + "name": "The Rats: Giselher", + "deck": "witcher_universe", + "row": "close", + "strength": "4", + "ability": "muster", + "filename": "rats_giselher", + "count": "1", + "target": "wu_rats", + "quote": "He wants to make us angry? Let the bastard talk." + }, + "wu_rats_asse": { + "name": "The Rats: Asse", + "deck": "witcher_universe", + "row": "close", + "strength": "3", + "ability": "muster", + "filename": "rats_asse", + "count": "1", + "target": "wu_rats", + "quote": "He had been hunting the Nilfgaardians for three days, insane with the desire for revenge for what the marauders had done to his familly." + }, + "wu_rats_iskra": { + "name": "The Rats: Iskra", + "deck": "witcher_universe", + "row": "ranged", + "strength": "3", + "ability": "muster", + "filename": "rats_iskra", + "count": "1", + "target": "wu_rats", + "quote": "The speed blew her beautiful, dark hair around, revealing a small, pointed ear decorated with a filigree earring." + }, + "wu_rats_kayleigh": { + "name": "The Rats: Kayleigh", + "deck": "witcher_universe", + "row": "close", + "strength": "3", + "ability": "muster", + "filename": "rats_kayleigh", + "count": "1", + "target": "wu_rats", + "quote": "He had woken up in smoke, fire and blood, lying among the corpses of his adoptive parents and siblings." + }, + "wu_rats_mistle": { + "name": "The Rats: Mistle", + "deck": "witcher_universe", + "row": "ranged", + "strength": "3", + "ability": "muster", + "filename": "rats_mistle", + "count": "1", + "target": "wu_rats", + "quote": "The tree stump was followed by a young woman with close-cropped fair hair in a red doublet and high, shiny boots reaching above the knee." + }, + "wu_rats_reef": { + "name": "The Rats: Reef", + "deck": "witcher_universe", + "row": "ranged", + "strength": "3", + "ability": "muster", + "filename": "rats_reef", + "count": "1", + "target": "wu_rats", + "quote": "Caring for the wounded was not a custom among the killers of the Nilfgaardian special squads." + }, + "wu_ralf_blunden": { + "name": "Ralf Blunden", + "deck": "witcher_universe", + "row": "ranged", + "strength": "7", + "ability": "spy", + "filename": "ralf_blunden", + "count": "1", + "quote": "The Professor's trademark is his sophisticated choice of words, and witty comments." + }, + "wu_bomb_heaver": { + "name": "Bomb Heaver", + "deck": "witcher_universe", + "row": "siege", + "strength": "3", + "ability": "scorch", + "filename": "bomb_heaver", + "count": "1", + "quote": "Watch your heads!" + }, + "wu_gascon_light_cavalry": { + "name": "Gascon's Light Cavalry", + "deck": "witcher_universe", + "row": "close", + "strength": "5", + "ability": "muster", + "filename": "gascon_light_cavalry", + "count": "1", + "target": "wu_gascon_troops", + "quote": "The chase is on!" + }, + "wu_gascon_slinger": { + "name": "Gascon's Slingers", + "deck": "witcher_universe", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "gascon_slinger", + "count": "1", + "target": "wu_gascon_troops", + "quote": "Bigger they are, easier they are to target." + }, + "wu_gascon_infiltrator": { + "name": "Gascon's Infiltrator", + "deck": "witcher_universe", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "gascon_infiltrator", + "count": "1", + "target": "wu_gascon_troops", + "quote": "We got a job to do." + }, + "wu_gascon": { + "name": "Gascon", + "deck": "witcher_universe", + "row": "siege", + "strength": "7", + "ability": "hero muster", + "filename": "gascon", + "count": "1", + "target": "wu_gascon_troops", + "quote": "Th' Strays of Spalla – 'tis you who lead them? 'Tis you they call the Duke of Dogs?" + }, + "wu_dorregaray": { + "name": "Dorregaray of Vole", + "deck": "witcher_universe", + "row": "ranged", + "strength": "10", + "ability": "hero", + "filename": "dorregaray", + "count": "1", + "quote": "Dorregaray is a monster aficionado, though he's developed his own classification system." + }, + "wu_ortolan": { + "name": "Grandmaster Ortolan", + "deck": "witcher_universe", + "row": "siege", + "strength": "5", + "ability": "medic", + "filename": "ortolan", + "count": "1", + "quote": "He was a legendary mage who was in charge of the experiments done at Rissberg Castle." + }, + "wu_coral": { + "name": "Coral", + "deck": "witcher_universe", + "row": "siege", + "strength": "6", + "ability": "", + "filename": "coral", + "count": "1", + "quote": "Her true name's Astrid Lyttneyd Ásgeirrfinnbjornsdottir, but that never fit on any forms." + }, + "wu_leo_bonhart": { + "name": "Leo Bonhart", + "deck": "witcher_universe", + "row": "close", + "strength": "11", + "ability": "hero", + "filename": "leo_bonhart", + "count": "1", + "quote": "So you do not fear death? Then look at that little Rat. This is death." + }, + "wu_azar_javed": { + "name": "Azar Javed", + "deck": "witcher_universe", + "row": "ranged", + "strength": "7", + "ability": "", + "filename": "azar_javed", + "count": "1", + "quote": "This time you pissed into a tornado." + }, + "wu_strays_spalla": { + "name": "Strays of Spalla", + "deck": "witcher_universe", + "row": "close", + "strength": "8", + "ability": "", + "filename": "strays_spalla", + "count": "1", + "quote": "I'll release ye o' that pouch." + }, + "wu_gerhart_aelle": { + "name": "Gerhart of Aelle", + "deck": "witcher_universe", + "row": "siege", + "strength": "10", + "ability": "hero", + "filename": "gerhart_aelle", + "count": "1", + "quote": "Gerhart of Aelle, otherwise known as Hen Gedymdeith, was the oldest living sorcerer. That is, until his death on Thanedd Island during the coup." + }, + "wu_lydia_bredevoort": { + "name": "Lydia van Bredevoort", + "deck": "witcher_universe", + "row": "ranged", + "strength": "5", + "ability": "medic", + "filename": "lydia_bredevoort", + "count": "1", + "quote": "Whether by brush or by sorcery, there was no event, emotion, or scene beyond Lydia's power to depict. Apart from joy." + }, + "wu_dana_meadbh": { + "name": "Dana Meadbh", + "deck": "witcher_universe", + "row": "ranged", + "strength": "8", + "ability": "hero morale", + "filename": "dana_meadbh", + "count": "1", + "quote": "Through the grasses covering the glade floated a golden-haired queen. Queen of the Fields." + }, + "wu_rience": { + "name": "Rience", + "deck": "witcher_universe", + "row": "siege", + "strength": "5", + "ability": "", + "filename": "rience", + "count": "1", + "quote": "I love watching people suffer." + }, + "wu_visenna": { + "name": "Visenna", + "deck": "witcher_universe", + "row": "siege", + "strength": "3", + "ability": "medic", + "filename": "visenna", + "count": "1", + "quote": "The scar will remain, of course. A new one for your collection." + }, + "wu_operator": { + "name": "Operator", + "deck": "witcher_universe", + "row": "ranged", + "strength": "5", + "ability": "scorch_c", + "filename": "operator", + "count": "1", + "quote": "As time and space collapse before us, they expand behind us..." + }, + "wu_cosimo_malaspina": { + "name": "Cosimo Malaspina: Master of Mutations", + "deck": "witcher_universe", + "row": "leader", + "strength": "", + "ability": "cosimo_malaspina", + "filename": "cosimo_malaspina", + "count": "1", + "quote": "Children keep asking him for gifts. He doesn’t know why, but it really helps with finding subjects for his experiments." + }, + "wu_coen": { + "name": "Coën", + "deck": "witcher_universe", + "row": "close", + "strength": "8", + "ability": "witcher_griffin_school", + "filename": "coen", + "count": "1", + "quote": "There is no such thing as a fair fight. Every advantage and every opportunity that arises is used in combat." + }, + "wu_stygga_castle": { + "name": "Stygga Castle", + "deck": "witcher_universe", + "row": "siege", + "strength": "8", + "ability": "hero resilience witcher_cat_school", + "filename": "stygga_castle", + "count": "1", + "quote": "The Feline witchers did not stay in Stygga Castle for long. Nor anywhere else, actually." + }, + "wu_vesemir": { + "name": "Vesemir", + "deck": "witcher_universe", + "row": "close", + "strength": "6", + "ability": "witcher_wolf_school", + "filename": "vesemir", + "count": "1", + "quote": "If you're to be hanged, ask for water. Anything can happen before they fetch it." + }, + "wu_haern_caduch": { + "name": "Haern Caduch", + "deck": "witcher_universe", + "row": "siege", + "strength": "8", + "ability": "hero resilience witcher_bear_school", + "filename": "haern_caduch", + "count": "1", + "quote": "Carved into the icy rock of the Amell Mountains, the location of the long-abandoned School of the Bear remains a well-kept secret." + }, + "wu_ivo_belhaven": { + "name": "Ivo of Belhaven", + "deck": "witcher_universe", + "row": "close", + "strength": "6", + "ability": "witcher_bear_school", + "filename": "ivo_belhaven", + "count": "1", + "quote": "It's not reason I'm devoid of, just emotion." + }, + "wu_lambert": { + "name": "Lambert", + "deck": "witcher_universe", + "row": "close", + "strength": "7", + "ability": "witcher_wolf_school", + "filename": "lambert", + "count": "1", + "quote": "Now that's the kind of negotiating I understand." + }, + "wu_keldar": { + "name": "Keldar", + "deck": "witcher_universe", + "row": "siege", + "strength": "6", + "ability": "medic witcher_griffin_school", + "filename": "keldar", + "count": "1", + "quote": "You blunt, brainless humanoids! What do you mean by 'I don't know?'. You would go hunt the vampires with the Lebioda idol, smeared in garlic!" + }, + "wu_ivar": { + "name": "Ivar Evil-Eye", + "deck": "witcher_universe", + "row": "ranged", + "strength": "8", + "ability": "witcher_viper_school", + "filename": "ivar", + "count": "1", + "quote": "There’s a terrible tale behind each and every scar⁠—you’d be surprised just how many are true." + }, + "wu_gorthur_gvaed": { + "name": "Gorthur Gvaed", + "deck": "witcher_universe", + "row": "siege", + "strength": "8", + "ability": "hero resilience witcher_viper_school", + "filename": "gorthur_gvaed", + "count": "1", + "quote": "There were many scrolls and manuscripts about the legend of the Wild Hunt in the stronghold—and for a good reason." + }, + "wu_kaer_morhen": { + "name": "Kaer Morhen", + "deck": "witcher_universe", + "row": "siege", + "strength": "8", + "ability": "hero resilience witcher_wolf_school", + "filename": "kaer_morhen", + "count": "1", + "quote": "The bones of the dead remain at the bottom of the moat surrounding the stronghold, left there as a reminder of the massacre that was born from hatred." + }, + "wu_kaer_seren": { + "name": "Kaer Seren", + "deck": "witcher_universe", + "row": "siege", + "strength": "8", + "ability": "hero resilience witcher_griffin_school", + "filename": "kaer_seren", + "count": "1", + "quote": "Kaer Seren’s literary collection was its greatest treasure and the envy of a group of overzealous mages." + }, + "wu_gezras": { + "name": "Gezras of Leyda", + "deck": "witcher_universe", + "row": "siege", + "strength": "9", + "ability": "witcher_cat_school", + "filename": "gezras", + "count": "1", + "quote": "Take a contract from Aen Seidhe over a dh'oine any day, as you’re far less likely to receive a knife between the ribs in place of coin." + }, + "wu_geralt_1": { + "name": "Geralt of Rivia", + "deck": "witcher_universe", + "row": "close", + "strength": "9", + "ability": "scorch_c witcher_wolf_school", + "filename": "geralt_1", + "count": "1", + "quote": "If that's what it takes to save the world, it's better to let that world die." + }, + "wu_gaetan": { + "name": "Gaetan", + "deck": "witcher_universe", + "row": "ranged", + "strength": "7", + "ability": "witcher_cat_school", + "filename": "gaetan", + "count": "1", + "quote": "Murder me just to save few crowns? I’m supposed to protect whoresons like that?" + }, + "wu_brehen": { + "name": "Brehen", + "deck": "witcher_universe", + "row": "close", + "strength": "6", + "ability": "scorch_c witcher_cat_school", + "filename": "brehen", + "count": "1", + "quote": "Known as the Cat of Iello. A moniker earned not from origins, but as a result of slaughtering peasants there. More of a massacre, really." + }, + "wu_gerd": { + "name": "Gerd", + "deck": "witcher_universe", + "row": "close", + "strength": "8", + "ability": "scorch_c witcher_bear_school", + "filename": "gerd", + "count": "1", + "quote": "He was contracted to slay a dragon, a siren, and a striga. He was also being pursued by a vengeful knight, bounty hunters, and bandits." + }, + "wu_warrit": { + "name": "Warrit the All-Seeing", + "deck": "witcher_universe", + "row": "ranged", + "strength": "7", + "ability": "witcher_viper_school", + "filename": "warrit", + "count": "1", + "quote": "By slightly modifying the Supirre sign, Warritt gained the ability to see... everything." + }, + "wu_erland": { + "name": "Erland of Larvik", + "deck": "witcher_universe", + "row": "ranged", + "strength": "9", + "ability": "witcher_griffin_school", + "filename": "erland", + "count": "1", + "quote": "Erland founded the School of the Griffin, and hoped his emphasis on knightly values would help elevate the reputation of witchers among the common folk." + }, + "wu_arnaghad": { + "name": "Arnaghad", + "deck": "witcher_universe", + "row": "close", + "strength": "9", + "ability": "witcher_bear_school", + "filename": "arnaghad", + "count": "1", + "quote": "A witcher’s job is to kill monsters and collect coin. No more, no less." + }, + "wu_letho": { + "name": "Letho of Gulet", + "deck": "witcher_universe", + "row": "close", + "strength": "9", + "ability": "scorch_c witcher_viper_school", + "filename": "letho", + "count": "1", + "quote": "Witchers never die in their beds." + }, + "wu_eskel": { + "name": "Eskel", + "deck": "witcher_universe", + "row": "ranged", + "strength": "8", + "ability": "witcher_wolf_school", + "filename": "eskel", + "count": "1", + "quote": "I'm a simple witcher, Wolf. Don't fight dragons, don't fraternize with kings and don't sleep with sorceresses..." + }, + "wu_kolgrim": { + "name": "Kolgrim", + "deck": "witcher_universe", + "row": "close", + "strength": "6", + "ability": "witcher_viper_school", + "filename": "kolgrim", + "count": "1", + "quote": "Fortune only smiled upon him if it was accompanied by a stroke of very bad luck." + }, + "wu_swallow_potion": { + "name": "Swallow Potion", + "deck": "witcher_universe", + "row": "agile_cr", + "strength": "2", + "ability": "horn", + "filename": "swallow_potion", + "count": "1", + "quote": "Symbolizing spring and rejuvenation, the swallow lent its name to this potion that accelerates the rate at which wounds scab over and heal." + }, + "spe_sign_igni": { + "name": "Sign: Igni", + "deck": "special witcher_universe", + "row": "", + "strength": "", + "ability": "scorch", + "filename": "sign_igni", + "count": "3", + "quote": "A twist of a witcher's fingers can light a lamp… or incinerate a foe." + }, + "spe_sign_quen": { + "name": "Sign: Quen", + "deck": "special witcher_universe", + "row": "", + "strength": "", + "ability": "shield", + "filename": "sign_quen", + "count": "3", + "quote": "Geralt, feeling the iron taste of blood in his mouth, shouted a spell, with his fingers open in the Quen Sign." + }, + "spe_sign_axii": { + "name": "Sign: Axii", + "deck": "special witcher_universe", + "row": "", + "strength": "", + "ability": "seize", + "filename": "sign_axii", + "count": "3", + "quote": "Geralt makes the Axii sign with the fingers of his right hand above the steed's head and whispers the incantation." + }, + "spe_sign_aard": { + "name": "Sign: Aard", + "deck": "special witcher_universe", + "row": "", + "strength": "", + "ability": "knockback", + "filename": "sign_aard", + "count": "3", + "quote": "A blast of concentrated energy that pummels everything in its path. Great for when you forget your keys." + }, + "spe_sign_yrden": { + "name": "Sign: Yrden", + "deck": "special witcher_universe", + "row": "", + "strength": "", + "ability": "lock", + "filename": "sign_yrden", + "count": "3", + "quote": "He lay down next to Adda's mummified remains, drawing the Yrden Sign on the inner side of her sarcophagus' lid." + }, + "wu_alzur_maker": { + "name": "Alzur: The Maker of Spells", + "deck": "witcher_universe", + "row": "leader", + "strength": "", + "ability": "alzur_maker", + "filename": "alzur_maker", + "count": "1", + "quote": "A rebel… outcast... knight… even sorcerer if you can believe that." + }, + "wu_koshchey": { + "name": "Koshchey", + "deck": "witcher_universe", + "row": "close", + "strength": "9", + "ability": "scorch_c", + "filename": "koshchey", + "count": "0", + "quote": "If I tell you koshchey is death, you'll go to the creek anyway, right?" + }, + "wu_doppler_1": { + "name": "Doppler", + "deck": "witcher_universe", + "row": "agile_cr", + "strength": "4", + "ability": "spy", + "filename": "doppler_1", + "count": "1", + "quote": "I'll be on my way and lose myself in the crowd." + }, + "wu_idr": { + "name": "Idr", + "deck": "witcher_universe", + "row": "close", + "strength": "10", + "ability": "", + "filename": "idr", + "count": "1", + "quote": "Who's a good boy? ⁠— Idarran" + }, + "wu_iris_von_everec": { + "name": "Iris von Everec", + "deck": "witcher_universe", + "row": "ranged", + "strength": "9", + "ability": "hero", + "filename": "iris_von_everec", + "count": "1", + "quote": "I remember so little... Yet when I think of my rose, I begin to recall what was." + }, + "wu_sarah": { + "name": "Sarah", + "deck": "witcher_universe", + "row": "siege", + "strength": "7", + "ability": "spy", + "filename": "sarah", + "count": "1", + "quote": "Little Sarah wants to play!" + }, + "wu_djinn": { + "name": "Djinn", + "deck": "witcher_universe", + "row": "siege", + "strength": "6", + "ability": "hero scorch_c", + "filename": "djinn", + "count": "1", + "quote": "A djinn, good sirs, fulfills but three wishes. Thus freed, it flees to dimensions unknown." + }, + "wu_myrgtabrakke": { + "name": "Myrgtabrakke", + "deck": "witcher_universe", + "row": "siege", + "strength": "10", + "ability": "", + "filename": "myrgtabrakke", + "count": "1", + "quote": "Never get between a mother dragon and her young." + }, + "wu_vincent_meis": { + "name": "Vincent Meis", + "deck": "witcher_universe", + "row": "close", + "strength": "5", + "ability": "scorch_c", + "filename": "vincent_meis", + "count": "1", + "quote": "By day, Captain of the Vizima City Guard. By night, merciless avenger and defender of the downtrodden." + }, + "wu_raging_bear": { + "name": "Raging Bear", + "deck": "witcher_universe", + "row": "agile_cr", + "strength": "6", + "ability": "scorch", + "filename": "raging_bear", + "count": "1", + "quote": "Tame? Och, lad, people might train bears but that don't at all mean they tame 'em..." + }, + "wu_iris_companions_1": { + "name": "Iris Companions: Black Dog", + "deck": "witcher_universe", + "row": "close", + "strength": "4", + "ability": "muster", + "filename": "iris_companions", + "count": "1", + "target": "wu_iris_companions", + "quote": "We'd rather keep our names to ourselves. Think of us as… friends of the house." + }, + "wu_iris_companions_2": { + "name": "Iris Companions: Black Cat", + "deck": "witcher_universe", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "iris_companions", + "count": "1", + "target": "wu_iris_companions", + "quote": "We'd rather keep our names to ourselves. Think of us as… friends of the house." + }, + "wu_vlodimir_von_everec": { + "name": "Vlodimir von Everec", + "deck": "witcher_universe", + "row": "close", + "strength": "7", + "ability": "", + "filename": "vlodimir_von_everec", + "count": "1", + "quote": "Vlodimir liked to have a good time when he was alive and greatly missed having fun after his death." + }, + "wu_phoenix": { + "name": "Phoenix", + "deck": "witcher_universe", + "row": "agile_cr", + "strength": "10", + "ability": "hero", + "filename": "phoenix", + "count": "1", + "quote": "What came first, the chicken or the egg? Compared to the conundrum that is the phoenix, that question seems downright trivial." + }, + "wu_boris": { + "name": "Boris", + "deck": "witcher_universe", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "boris", + "count": "1", + "quote": "After getting a taste of human flesh, he won't eat anything else." + }, + "wu_marlene_trastamara": { + "name": "Marlene de Trastamara", + "deck": "witcher_universe", + "row": "close", + "strength": "6", + "ability": "", + "filename": "marlene_trastamara", + "count": "1", + "quote": "None shall sit and dine with you at your table, no spoon you have shall sate you, never again shall you wish to spy your reflection in the mirror." + }, + "wu_idarran_ulivo": { + "name": "Idarran of Ulivo", + "deck": "witcher_universe", + "row": "ranged", + "strength": "8", + "ability": "hero avenger", + "filename": "idarran_ulivo", + "count": "1", + "target": "wu_idr", + "quote": "After getting a taste of human flesh, he won't eat anything else." + }, + "wu_mad_kiyan": { + "name": "Mad Kiyan", + "deck": "witcher_universe", + "row": "close", + "strength": "7", + "ability": "witcher_cat_school", + "filename": "mad_kiyan", + "count": "1", + "quote": "We live on a placid island of ignorance in the midst of black seas of infinity, and it was not meant that we should voyage far." + }, + "wu_cicada": { + "name": "Cicada", + "deck": "witcher_universe", + "row": "close", + "strength": "7", + "ability": "", + "filename": "cicada", + "count": "1", + "quote": "Ivo Mierce, better known by his nickname Cicada, war a criminal and bodyguard." + }, + "wu_nivellen": { + "name": "Nivellen", + "deck": "witcher_universe", + "row": "agile_cr", + "strength": "8", + "ability": "", + "filename": "nivellen", + "count": "1", + "quote": "Flee mortal man! I'll devour you! Tear you to pieces!" + }, + "wu_vilgefortz_sorcerer": { + "name": "Vilgefortz: Sorcerer of Roggeveen", + "deck": "witcher_universe", + "row": "leader", + "strength": "", + "ability": "vilgefortz_sorcerer", + "filename": "vilgefortz_sorcerer", + "count": "1", + "quote": "You've mistaken the stars reflected on the surface of the lake at night for the heavens." + }, + "wu_doppler_2": { + "name": "Doppler", + "deck": "witcher_universe", + "row": "agile_cr", + "strength": "6", + "ability": "spy", + "filename": "doppler_2", + "count": "1", + "quote": "I'll be on my way and lose myself in the crowd." + }, + "wu_pellar": { + "name": "Pellar", + "deck": "witcher_universe", + "row": "ranged", + "strength": "2", + "ability": "medic", + "filename": "pellar", + "count": "1", + "quote": "Gather spirits for this wake, A passing soul ne'er forsake, Hear my call, my humble plea, Unbind his chains, set him free." + }, + "wu_kelpie": { + "name": "Kelpie", + "deck": "witcher_universe", + "row": "siege", + "strength": "0", + "ability": "avenger", + "filename": "kelpie", + "count": "1", + "target": "ntr_ciri", + "quote": "In the north 'Kelpie' was a sea monster..." + }, + "wu_vysogota": { + "name": "Vysogota of Corvo", + "deck": "witcher_universe", + "row": "siege", + "strength": "2", + "ability": "medic", + "filename": "vysogota", + "count": "1", + "quote": "I, Vysogota of Corvo, do not believe in the existence of the gods." + }, + "wu_angouleme": { + "name": "Angouleme", + "deck": "witcher_universe", + "row": "agile_cr", + "strength": "5", + "ability": "", + "filename": "angouleme", + "count": "1", + "quote": "You damned tricksters! Nothing but swindlers!" + }, + "wu_tea_vea_1": { + "name": "Tea & Vea", + "deck": "witcher_universe", + "row": "close", + "strength": "5", + "ability": "muster", + "filename": "tea_vea_1", + "count": "1", + "target": "wu_tea_vea", + "quote": "Her sabre, drawn faster than they eye could see, cut through the air." + }, + "wu_tea_vea_2": { + "name": "Tea & Vea", + "deck": "witcher_universe", + "row": "close", + "strength": "5", + "ability": "muster", + "filename": "tea_vea_2", + "count": "1", + "target": "wu_tea_vea", + "quote": "Her sabre, drawn faster than they eye could see, cut through the air." + }, + "wu_iola": { + "name": "Iola", + "deck": "witcher_universe", + "row": "ranged", + "strength": "0", + "ability": "medic", + "filename": "iola", + "count": "1", + "quote": "The priestess slowly shook her head, sniffed and wiped a tear away." + }, + "wu_rhapsodic_melody": { + "name": "Rhapsodic Melody", + "deck": "witcher_universe", + "row": "agile_cr", + "strength": "2", + "ability": "horn", + "filename": "rhapsodic_melody", + "count": "1", + "quote": "War's not so horrific when you put a catchy tune to it." + }, + "wu_nenneke": { + "name": "Nenneke", + "deck": "witcher_universe", + "row": "siege", + "strength": "1", + "ability": "medic", + "filename": "nenneke", + "count": "1", + "quote": "Few know more about healing than Nenneke." + }, + "wu_roach": { + "name": "Roach", + "deck": "witcher_universe", + "row": "close", + "strength": "0", + "ability": "avenger", + "filename": "roach", + "count": "1", + "target": "ntr_geralt", + "quote": "Geralt, we gotta have a man–to–horse talk. No offense, but your riding skills? They leave a bit to be desired, buddy." + }, + "wu_kalkstein": { + "name": "Adalbertus Kalkstein", + "deck": "witcher_universe", + "row": "siege", + "strength": "4", + "ability": "morale", + "filename": "kalkstein", + "count": "1", + "quote": "Before Kalkstein departed this world, he left us with some rather unflattering words about our gracious king..." + }, + "wu_gerd_2": { + "name": "Gerd", + "deck": "witcher_universe", + "row": "close", + "strength": "11", + "ability": "hero", + "filename": "gerd_2", + "count": "1", + "quote": "Righteous and brave, of death never scared. Such a man had we in the witcher Gerd." + }, + "wu_lambert_2": { + "name": "Lambert", + "deck": "witcher_universe", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "lambert_2", + "count": "1", + "quote": "Lambert, Lambert, what a prick." + }, + "wu_eskel_2": { + "name": "Eskel", + "deck": "witcher_universe", + "row": "close", + "strength": "10", + "ability": "hero morale", + "filename": "eskel_2", + "count": "1", + "quote": "Heard you panting from three miles away. Just didn't wanna give up that vantage point." + }, + "wu_sheenaz": { + "name": "Sh'eenaz", + "deck": "witcher_universe", + "row": "close", + "strength": "5", + "ability": "hero morale", + "filename": "sheenaz", + "count": "1", + "quote": "The excuses, the stupid and naive excuses: not the slightest bit of dedication!" + }, + "wu_george_kagen": { + "name": "George of Kagen", + "deck": "witcher_universe", + "row": "close", + "strength": "6", + "ability": "witcher_griffin_school", + "filename": "george_kagen", + "count": "1", + "quote": "Instead of monsters, he only found villagers lighting fake fires to sink and loot all arriving ships." + }, + "wu_leo": { + "name": "Leo", + "deck": "witcher_universe", + "row": "close", + "strength": "6", + "ability": "witcher_wolf_school", + "filename": "leo", + "count": "1", + "quote": "He would have caught the arrow if he only had some heads-up." + }, + "wu_renfri": { + "name": "Renfri", + "deck": "witcher_universe", + "row": "close", + "strength": "7", + "ability": "", + "filename": "renfri", + "count": "1", + "quote": "In this fairytale, the princess and the monster are the same person." + }, + "wu_gimpy_gerwin": { + "name": "Gimpy Gerwin", + "deck": "witcher_universe", + "row": "close", + "strength": "6", + "ability": "", + "filename": "gimpy_gerwin", + "count": "1", + "quote": "Keep the vermin on a short leash. And don't be afraid to use that whip!" + }, + "wu_fugas": { + "name": "Fugas", + "deck": "witcher_universe", + "row": "close", + "strength": "7", + "ability": "", + "filename": "fugas", + "count": "1", + "quote": "Heh, givin' me orders? You? A human?" + }, + "wu_barnabas": { + "name": "Barnabas Beckenbauer", + "deck": "witcher_universe", + "row": "close", + "strength": "1", + "ability": "medic", + "filename": "barnabas", + "count": "1", + "quote": "I think you'll really like this one!" + }, + "wu_torque": { + "name": "Torque", + "deck": "witcher_universe", + "row": "close", + "strength": "6", + "ability": "", + "filename": "torque", + "count": "1", + "quote": "Where an elf cannot go himself, he sends a devil." + }, + "wu_deserter_1": { + "name": "Deserter", + "deck": "witcher_universe", + "row": "close", + "strength": "4", + "ability": "muster", + "filename": "deserter_1", + "count": "1", + "target": "wu_deserter", + "quote": "It is interesting that every second deserter is a volunteer." + }, + "wu_deserter_2": { + "name": "Deserter", + "deck": "witcher_universe", + "row": "close", + "strength": "3", + "ability": "muster", + "filename": "deserter_2", + "count": "1", + "target": "wu_deserter", + "quote": "It is interesting that every second deserter is a volunteer." + }, + "wu_deserter_3": { + "name": "Deserter", + "deck": "witcher_universe", + "row": "close", + "strength": "3", + "ability": "muster", + "filename": "deserter_3", + "count": "1", + "target": "wu_deserter", + "quote": "It is interesting that every second deserter is a volunteer." + }, + "wu_bloody_baron": { + "name": "Bloody Baron", + "deck": "witcher_universe", + "row": "close", + "strength": "5", + "ability": "", + "filename": "bloody_baron", + "count": "1", + "quote": "I've not been a good father, I know, but… perhaps it's not too late." + }, + "wu_essi_daven": { + "name": "Essi Daven", + "deck": "witcher_universe", + "row": "ranged", + "strength": "2", + "ability": "horn", + "filename": "essi_daven", + "count": "1", + "quote": "When you have no talent, you don't have the luxury of choosing your audience." + }, + "wu_fercart": { + "name": "Fercart", + "deck": "witcher_universe", + "row": "ranged", + "strength": "5", + "ability": "", + "filename": "fercart", + "count": "1", + "quote": "Pawns will never know of the unseen hands, maneuvering them toward certain doom." + }, + "wu_artaud_terranova": { + "name": "Artaud Terranova", + "deck": "witcher_universe", + "row": "ranged", + "strength": "5", + "ability": "", + "filename": "artaud_terranova", + "count": "1", + "quote": "Ambition can be blinding." + }, + "wu_auckes": { + "name": "Auckes", + "deck": "witcher_universe", + "row": "ranged", + "strength": "6", + "ability": "witcher_viper_school", + "filename": "auckes", + "count": "1", + "quote": "Letho's got a plan… what could go wrong?" + }, + "wu_serrit": { + "name": "Serrit", + "deck": "witcher_universe", + "row": "ranged", + "strength": "6", + "ability": "witcher_viper_school", + "filename": "serrit", + "count": "1", + "quote": "We do what we must. I am not ashamed of that." + }, + "wu_junod": { + "name": "Junod of Belhaven", + "deck": "witcher_universe", + "row": "ranged", + "strength": "6", + "ability": "witcher_bear_school", + "filename": "junod", + "count": "1", + "quote": "Rumour has it he was born of an unusual love between a lady giant and one VERY brave dwarf." + }, + "wu_berengar": { + "name": "Berengar", + "deck": "witcher_universe", + "row": "ranged", + "strength": "6", + "ability": "witcher_wolf_school", + "filename": "berengar", + "count": "1", + "quote": "Talking the vodyanoi out of sacrificing the prize-winning cow wasn’t an easy task." + }, + "wu_stregobor": { + "name": "Stregobor", + "deck": "witcher_universe", + "row": "ranged", + "strength": "4", + "ability": "", + "filename": "stregobor", + "count": "1", + "quote": "I'll be honest, although for my own sake I shouldn't." + }, + "wu_renew": { + "name": "Renew", + "deck": "witcher_universe", + "row": "ranged", + "strength": "2", + "ability": "medic", + "filename": "renew", + "count": "1", + "quote": "Medicus curat, magicae sanat." + }, + "wu_prophet_lebioda": { + "name": "Prophet Lebioda", + "deck": "witcher_universe", + "row": "ranged", + "strength": "8", + "ability": "", + "filename": "prophet_lebioda", + "count": "1", + "quote": "To thine own self be judge and ruler for thou alone shalt answer for thine deeds before thee." + }, + "wu_johnny": { + "name": "Johnny", + "deck": "witcher_universe", + "row": "siege", + "strength": "8", + "ability": "spy", + "filename": "johnny", + "count": "1", + "quote": "Peter Piper picked Prince Proximo a peck of pickled peppers by the Pontar." + }, + "wu_istredd": { + "name": "Istredd", + "deck": "witcher_universe", + "row": "siege", + "strength": "5", + "ability": "", + "filename": "istredd", + "count": "1", + "quote": "Love can make one do crazy things. The loss of love, even more so." + }, + "wu_salma": { + "name": "Salma", + "deck": "witcher_universe", + "row": "siege", + "strength": "4", + "ability": "", + "filename": "salma", + "count": "1", + "quote": "I'm not one to lie. Nor do I kill without reason." + }, + "wu_field_marshal_duda": { + "name": "Field Marshal Duda", + "deck": "witcher_universe", + "row": "siege", + "strength": "1", + "ability": "morale", + "filename": "field_marshal_duda", + "count": "1", + "quote": "Brilliants! Brilliants!" + } +}; + + + +var ext_lr_cards = { + "spe_lyria_rivia_morale": { + "name": "Lyria & Rivia: Morale Boost", + "deck": "special lyria_rivia", + "row": "", + "strength": "", + "ability": "morale", + "filename": "lyria_rivia_morale", + "count": "0", + "quote": "For Lyria and Rivia!" + }, + "lr_meve_princess": { + "name": "Meve: The Princess of Lyria", + "deck": "lyria_rivia", + "row": "leader", + "strength": "", + "ability": "meve_princess", + "filename": "meve_princess", + "count": "1", + "quote": "The Gods watch over us, we'll come through the fray unharmed." + }, + "lr_rivian_mauler": { + "name": "Rivia Mauler", + "deck": "lyria_rivia", + "row": "close", + "strength": "7", + "ability": "", + "filename": "rivian_mauler", + "count": "1", + "quote": "Ugh, these guys can be a real headache." + }, + "lr_grey_rider": { + "name": "Grey Rider", + "deck": "lyria_rivia", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "grey_rider", + "count": "2", + "target": "lr_grey_rider", + "quote": "This is not steel and blood that win wars, but information." + }, + "lr_prince_anseis": { + "name": "Prince Anséis", + "deck": "lyria_rivia", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "prince_anseis", + "count": "1", + "quote": "Your presence at this tourney is an affront to my honor!" + }, + "lr_royal_guard": { + "name": "Royal Guard", + "deck": "lyria_rivia", + "row": "close", + "strength": "9", + "ability": "", + "filename": "royal_guard", + "count": "1", + "quote": "Each must serve with unconditionnal loyalty and possess a devilishly handsome jawline." + }, + "lr_landsknecht": { + "name": "Lyrian Landsknecht", + "deck": "lyria_rivia", + "row": "close", + "strength": "3", + "ability": "muster", + "filename": "landsknecht", + "count": "3", + "target": "lr_landsknecht", + "quote": "Best not laugh at their silly-arse hats. Believe me." + }, + "lr_knighthood": { + "name": "Knighthood", + "deck": "lyria_rivia", + "row": "close", + "strength": "10", + "ability": "", + "filename": "knighthood", + "count": "1", + "quote": "Kneel an everyman, arise a knight." + }, + "lr_reynard_odo": { + "name": "Reynard Odo", + "deck": "lyria_rivia", + "row": "close", + "strength": "10", + "ability": "hero morale", + "filename": "reynard_odo", + "count": "1", + "quote": "Under your husband I served ten years, under you another eight." + }, + "lr_war_wagon": { + "name": "War Wagon", + "deck": "lyria_rivia", + "row": "ranged", + "strength": "4", + "ability": "avenger", + "filename": "war_wagon", + "count": "1", + "target": "lr_wagenburg", + "quote": "Hay out, archersin! Go, go go!" + }, + "lr_wagenburg": { + "name": "Wagenburg", + "deck": "lyria_rivia", + "row": "ranged", + "strength": "3", + "ability": "muster", + "filename": "wagenburg", + "count": "3", + "target": "lr_wagenburg_muster", + "quote": "Dh'oine can turn anything into a weapon. Even a simple wagon..." + }, + "lr_gascon": { + "name": "Gascon", + "deck": "lyria_rivia", + "row": "ranged", + "strength": "10", + "ability": "hero", + "filename": "gascon", + "count": "1", + "quote": "I'm doing what I used to do and they're paying me for it!" + }, + "lr_pikeman": { + "name": "Rivian Pikeman", + "deck": "lyria_rivia", + "row": "close", + "strength": "6", + "ability": "", + "filename": "pikeman", + "count": "1", + "quote": "Get off your high horse and face me!" + }, + "lr_light_cavalry": { + "name": "Light Cavalry", + "deck": "lyria_rivia", + "row": "close", + "strength": "5", + "ability": "muster", + "filename": "light_cavalry", + "count": "2", + "target": "lr_light_cavalry", + "quote": "Stay calm, everyone. And be alert." + }, + "lr_rayla": { + "name": "Rayla", + "deck": "lyria_rivia", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "rayla", + "count": "1", + "quote": "Exceptions are a clear road to human blood spilt. All Scoia'tael must die." + }, + "lr_wagon": { + "name": "Wagon", + "deck": "lyria_rivia", + "row": "agile_cr", + "strength": "1", + "ability": "medic", + "filename": "wagon", + "count": "1", + "quote": "The driver swore he was carrying seeds. But seeds don't clank on bumps in the road..." + }, + "lr_lyrian_cavalry": { + "name": "Lyrian Cavalry", + "deck": "lyria_rivia", + "row": "close", + "strength": "8", + "ability": "", + "filename": "lyrian_cavalry", + "count": "1", + "quote": "A horseman's worth no less than his steed. And Lyrian horses are among the Continent's best." + }, + "lr_isbel_hagge": { + "name": "Isbel of Hagge", + "deck": "lyria_rivia", + "row": "ranged", + "strength": "4", + "ability": "medic", + "filename": "isbel_hagge", + "count": "1", + "quote": "I promised I would never again use magic to harm others." + }, + "lr_hajduk": { + "name": "Lyrian Hajduk", + "deck": "lyria_rivia", + "row": "agile_cr", + "strength": "3", + "ability": "horn", + "filename": "hajduk", + "count": "1", + "quote": "War, war... What's it bloody good for..." + }, + "spe_wyvern_shield": { + "name": "Wyvern Scale Shield", + "deck": "special lyria_rivia", + "row": "", + "strength": "", + "ability": "shield_c", + "filename": "wyvern_shield", + "count": "1", + "quote": "Stronger than your average shield and far more stylish." + }, + "spe_mantlet": { + "name": "Mantlet", + "deck": "special lyria_rivia", + "row": "", + "strength": "", + "ability": "shield_r", + "filename": "mantlet", + "count": "1", + "quote": "Something like the bastard child of a shield and a palisade." + }, + "spe_watchman": { + "name": "Watchman", + "deck": "special lyria_rivia", + "row": "", + "strength": "", + "ability": "shield_r", + "filename": "watchman", + "count": "1", + "quote": "I can't even see over this bloody thing." + }, + "spe_garrison": { + "name": "Garrison", + "deck": "special lyria_rivia", + "row": "", + "strength": "", + "ability": "shield_s", + "filename": "garrison", + "count": "1", + "quote": "Knock, knock… anybody home?" + }, + "lr_meve_white_queen": { + "name": "Meve: The White Queen", + "deck": "lyria_rivia", + "row": "leader", + "strength": "", + "ability": "meve_white_queen", + "filename": "meve_white_queen", + "count": "1", + "quote": "I've made my choice. Time you made yours." + }, + "lr_piercing_missile": { + "name": "Piercing Missile", + "deck": "lyria_rivia", + "row": "ranged", + "strength": "3", + "ability": "scorch_c", + "filename": "piercing_missile", + "count": "1", + "quote": "There's no armor that can't be pierced." + }, + "lr_eavesdrop": { + "name": "Eavesdrop", + "deck": "lyria_rivia", + "row": "ranged", + "strength": "6", + "ability": "spy", + "filename": "eavesdrop", + "count": "1", + "quote": "There are always more ears in the room than those you can count." + }, + "lr_trebuchet": { + "name": "Lyrian Trebuchet", + "deck": "lyria_rivia", + "row": "siege", + "strength": "9", + "ability": "", + "filename": "trebuchet", + "count": "1", + "quote": "Feel that? The earth trembles each time Big Bertha loose a stone." + }, + "lr_arbalest": { + "name": "Lyrian Arbalest", + "deck": "lyria_rivia", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "arbalest", + "count": "3", + "target": "lr_arbalest", + "quote": "I can find the bull's-eye from a hundred paces! Perhaps not with my first shot, mind you..." + }, + "lr_spellweaver": { + "name": "Spellweaver", + "deck": "lyria_rivia", + "row": "ranged", + "strength": "7", + "ability": "", + "filename": "spellweaver", + "count": "1", + "quote": "Reality is so terribly tedious..." + }, + "lr_forager": { + "name": "Forager", + "deck": "lyria_rivia", + "row": "ranged", + "strength": "5", + "ability": "", + "filename": "forager", + "count": "1", + "quote": "If you'll not be needin' it, I'm willin' to take it off your hands..." + }, + "lr_sapper": { + "name": "Rivian Sapper", + "deck": "lyria_rivia", + "row": "ranged", + "strength": "4", + "ability": "scorch", + "filename": "sapper", + "count": "1", + "quote": "First Nilfgaardian who tried to slip 'cross our line was a right sneaky bastard." + }, + "lr_villem": { + "name": "Prince Villem", + "deck": "lyria_rivia", + "row": "siege", + "strength": "8", + "ability": "hero", + "filename": "villem", + "count": "1", + "quote": "The boy's not fit to wear the crown. Hasn't sufficient wit nor valor." + }, + "lr_scout": { + "name": "Scout", + "deck": "lyria_rivia", + "row": "siege", + "strength": "5", + "ability": "spy", + "filename": "scout", + "count": "1", + "quote": "If our scouts don't come back, we turn around." + }, + "lr_winch": { + "name": "Winch", + "deck": "lyria_rivia", + "row": "siege", + "strength": "5", + "ability": "morale", + "filename": "winch", + "count": "1", + "quote": "It's a winch. Not much to flap your jaw about." + }, + "lr_banner": { + "name": "Lyrian Banner", + "deck": "lyria_rivia", + "row": "siege", + "strength": "2", + "ability": "horn", + "filename": "banner", + "count": "1", + "quote": "Our emblem? A black eagle. Fate of our foes? Pure misery." + }, + "lr_scytheman_1": { + "name": "Lyrian Scytheman", + "deck": "lyria_rivia", + "row": "close", + "strength": "3", + "ability": "decoy", + "filename": "scytheman", + "count": "1", + "quote": "Our folk they feed, and our foes they bleed." + }, + "lr_scytheman_2": { + "name": "Lyrian Scytheman", + "deck": "lyria_rivia", + "row": "ranged", + "strength": "3", + "ability": "decoy", + "filename": "scytheman", + "count": "1", + "quote": "Our folk they feed, and our foes they bleed." + }, + "lr_scytheman_3": { + "name": "Lyrian Scytheman", + "deck": "lyria_rivia", + "row": "siege", + "strength": "3", + "ability": "decoy", + "filename": "scytheman", + "count": "1", + "quote": "Our folk they feed, and our foes they bleed." + }, + "lr_caldwell": { + "name": "Count Caldwell", + "deck": "lyria_rivia", + "row": "ranged", + "strength": "9", + "ability": "hero spy", + "filename": "caldwell", + "count": "1", + "quote": "Your Majesty... For the queen to question commoners, why, it's simply not proper..." + }, + "lr_physician": { + "name": "Physician", + "deck": "lyria_rivia", + "row": "siege", + "strength": "3", + "ability": "medic", + "filename": "physician", + "count": "1", + "quote": "Do not twitch, lie still..." + }, + "lr_pyrokinesis": { + "name": "Pyrokinesis", + "deck": "lyria_rivia", + "row": "ranged", + "strength": "8", + "ability": "", + "filename": "pyrokinesis", + "count": "1", + "quote": "I really hope that's boot leather I smell burning..." + }, + "lr_carroballista": { + "name": "Carroballista", + "deck": "lyria_rivia", + "row": "siege", + "strength": "10", + "ability": "", + "filename": "carroballista", + "count": "1", + "quote": "This ballista's on the wagon." + }, + "lr_artificer": { + "name": "Artificer", + "deck": "lyria_rivia", + "row": "ranged", + "strength": "2", + "ability": "medic", + "filename": "artificer", + "count": "1", + "quote": "What shall I call it? Perhaps Andúril..." + }, + "lr_siege": { + "name": "Siege", + "deck": "lyria_rivia", + "row": "siege", + "strength": "6", + "ability": "scorch", + "filename": "siege", + "count": "1", + "quote": "There's no fortress that can't be taken. There are just fortresses not worth taking." + }, + "lr_onager": { + "name": "Rivian Onager", + "deck": "lyria_rivia", + "row": "siege", + "strength": "6", + "ability": "", + "filename": "onager", + "count": "1", + "quote": "For Riviaaa!" + }, + "lr_blacksmith": { + "name": "Lyrian Blacksmith", + "deck": "lyria_rivia", + "row": "close", + "strength": "4", + "ability": "morale", + "filename": "blacksmith", + "count": "1", + "quote": "Somethin' from nothin'... my speciality." + }, + "lr_peasant_militia": { + "name": "Peasant Militia", + "deck": "lyria_rivia", + "row": "close", + "strength": "4", + "ability": "", + "filename": "peasant_militia", + "count": "1", + "quote": "We's the militia. We keep the peace." + } +}; + +var ext_sy_cards = { + "sy_carlo_varese": { + "name": "Carlo Varese: Cleaver", + "deck": "syndicate", + "row": "leader", + "strength": "", + "ability": "carlo_varese", + "filename": "carlo_varese", + "count": "1", + "quote": "Me hogs willnae go hungry th' day thanks to ye." + }, + "sy_francis_bedlam": { + "name": "Francis Bedlam: King of Beggars", + "deck": "syndicate", + "row": "leader", + "strength": "", + "ability": "francis_bedlam", + "filename": "francis_bedlam", + "count": "1", + "quote": "You say tribute, I say taxes." + }, + "sy_cyprian_wiley": { + "name": "Cyprian Wiley: Whoreson Junior", + "deck": "syndicate", + "row": "leader", + "strength": "", + "ability": "cyprian_wiley", + "filename": "cyprian_wiley", + "count": "1", + "quote": "A war with Whoreson will see Novigrad's gutters run red with blood." + }, + "sy_gudrun_bjornsdottir": { + "name": "Gudrun Bjornsdottir: Pirate Queen", + "deck": "syndicate", + "row": "leader", + "strength": "", + "ability": "gudrun_bjornsdottir", + "filename": "gudrun_bjornsdottir", + "count": "1", + "quote": "She found her freedom among blue waters and salty wind." + }, + "sy_cyrus_hemmelfart": { + "name": "Cyrus Hemmelfart: Hierarch of Novigrad", + "deck": "syndicate", + "row": "leader", + "strength": "", + "ability": "cyrus_hemmelfart", + "filename": "cyrus_hemmelfart", + "count": "1", + "quote": "Beneath all that lust, greed, and vanity, stands an honorable man." + }, + "sy_sigi_reuven": { + "name": "Sigi Reuven", + "deck": "syndicate", + "row": "close", + "strength": "8", + "ability": "hero morale", + "filename": "sigi_reuven", + "count": "0", + "quote": "You sure he don't look the least bit familar...?" + }, + "sy_flyndr_crew": { + "name": "Flyndr' Crew", + "deck": "syndicate", + "row": "close", + "strength": "4", + "ability": "horn", + "filename": "flyndr_crew", + "count": "0", + "quote": "Wretches and thieves drunk on grog, bloodshed and booty - could you ever hope for a better crew?" + }, + "spe_dimeritium_shackles": { + "name": "Dimeritium Shackles", + "deck": "special syndicate", + "row": "", + "strength": "", + "ability": "lock", + "filename": "dimeritium_shackles", + "count": "3", + "quote": "Terranova cried out, lurched, bent backwards, bowed forward, then retched and groaned. It was clear of what his manacles were made." + }, + "sy_flaming_rose_footman": { + "name": "Flaming Rose Footman", + "deck": "syndicate", + "row": "close", + "strength": "6", + "ability": "", + "filename": "flaming_rose_footman", + "count": "1", + "quote": "Anyone can join The Order – a knight, a peasant, even a witcher. " + }, + "sy_bare_knuckle_brawler": { + "name": "Bare Knuckle Brawler", + "deck": "syndicate", + "row": "close", + "strength": "8", + "ability": "hero", + "filename": "bare_knuckle_brawler", + "count": "1", + "quote": "Is tha' all that's left of 'im? Think I'm goin' tae boak..." + }, + "sy_eibhear_hattori": { + "name": "Eibhear Hattori", + "deck": "syndicate", + "row": "ranged", + "strength": "2", + "ability": "medic", + "filename": "eibhear_hattori", + "count": "1", + "quote": "Only thing that can rival his swords? His dumplings." + }, + "sy_witch_hunter": { + "name": "Witch Hunter", + "deck": "syndicate", + "row": "close", + "strength": "2", + "ability": "witch_hunt", + "filename": "witch_hunter", + "count": "1", + "quote": "Long coats, wide-brimmed hats, and crooked grins – witch hunters are hard to miss." + }, + "sy_witch_hunter_executioner": { + "name": "Witch Hunter Executioner", + "deck": "syndicate", + "row": "close", + "strength": "3", + "ability": "witch_hunt", + "filename": "witch_hunter_executioner", + "count": "1", + "quote": "It'd be a right shame if I cut any of your beautiful hair." + }, + "sy_casino_bouncers": { + "name": "Casino Bouncers", + "deck": "syndicate", + "row": "close", + "strength": "7", + "ability": "", + "filename": "casino_bouncers", + "count": "1", + "quote": "Junior said our nasty mugs was frightenin' off all the coin. Don't rightly see 'ow this helps any..." + }, + "sy_caleb_menge": { + "name": "Caleb Menge", + "deck": "syndicate", + "row": "agile_cr", + "strength": "7", + "ability": "hero witch_hunt", + "filename": "caleb_menge", + "count": "1", + "quote": "Deceivers, heretics, witches! They flood our city, corrupt our virtue, and threaten our very way of life!" + }, + "sy_greater_brothers": { + "name": "Greater Brothers", + "deck": "syndicate", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "greater_brothers", + "count": "1", + "quote": "A battering ram? No need, we'll handle it another way." + }, + "sy_eternal_fire_inquisitor": { + "name": "Eternal Fire Inquisitor", + "deck": "syndicate", + "row": "agile_cr", + "strength": "2", + "ability": "witch_hunt", + "filename": "eternal_fire_inquisitor", + "count": "1", + "quote": "The burning light of the Eternal Fire reveals all!" + }, + "sy_eternal_fire_priest_1": { + "name": "Eternal Fire Priest", + "id": 1, + "deck": "syndicate", + "row": "ranged", + "strength": "3", + "ability": "muster", + "filename": "eternal_fire_priest_1", + "count": "1", + "target": "sy_eternal_fire_priest", + "quote": "Closer, my sheep, gather closer. May the Eternal Fire warm your souls!" + }, + "sy_eternal_fire_priest_2": { + "name": "Eternal Fire Priest", + "id": 2, + "deck": "syndicate", + "row": "ranged", + "strength": "3", + "ability": "muster", + "filename": "eternal_fire_priest_2", + "count": "1", + "target": "sy_eternal_fire_priest", + "quote": "Closer, my sheep, gather closer. May the Eternal Fire warm your souls!" + }, + "sy_eternal_fire_priest_3": { + "name": "Eternal Fire Priest", + "id": 3, + "deck": "syndicate", + "row": "ranged", + "strength": "3", + "ability": "muster", + "filename": "eternal_fire_priest_3", + "count": "1", + "target": "sy_eternal_fire_priest", + "quote": "Closer, my sheep, gather closer. May the Eternal Fire warm your souls!" + }, + "sy_roderick_wett": { + "name": "Roderick de Wett", + "deck": "syndicate", + "row": "close", + "strength": "7", + "ability": "", + "filename": "roderick_wett", + "count": "1", + "quote": "Count de Wett is exceptionally loathsome and arrogant, but at least he enjoys a little dice poker on the side." + }, + "sy_ulrich": { + "name": "Ulrich", + "deck": "syndicate", + "row": "agile_cr", + "strength": "8", + "ability": "", + "filename": "ulrich", + "count": "1", + "quote": "When the Order was disbanded, those who didn't join the witch hunters formed the Fallen Knights, of which Ulrich became the Grand Master." + }, + "sy_inquisitional_pyres": { + "name": "Inquisitional Pyres", + "deck": "syndicate", + "row": "agile_cr", + "strength": "4", + "ability": "witch_hunt", + "filename": "inquisitional_pyres", + "count": "1", + "quote": "Fire cleanses." + }, + "sy_imke": { + "name": "Imke", + "deck": "syndicate", + "row": "ranged", + "strength": "5", + "ability": "spy", + "filename": "imke", + "count": "1", + "quote": "No sooner had she caught Gudrun's attention than sought to exploit it." + }, + "sy_professor": { + "name": "Professor", + "deck": "syndicate", + "row": "ranged", + "strength": "8", + "ability": "hero", + "filename": "professor", + "count": "1", + "quote": "I fear our conventicle may end disastrously for you." + }, + "sy_salamandra_assassin": { + "name": "Salamandra Assassin", + "deck": "syndicate", + "row": "ranged", + "strength": "5", + "ability": "scorch_c", + "filename": "salamandra_assassin", + "count": "1", + "quote": "A name and bag full of gold. That's all I need." + }, + "sy_salamandra_assassin_2": { + "name": "Salamandra Assassin", + "deck": "syndicate", + "row": "ranged", + "strength": "5", + "ability": "scorch_c", + "filename": "salamandra_assassin_2", + "count": "1", + "quote": "A name and bag full of gold. That's all I need." + }, + "sy_walter_veritas": { + "name": "Walter Veritas", + "deck": "syndicate", + "row": "ranged", + "strength": "7", + "ability": "spy", + "filename": "walter_veritas", + "count": "1", + "quote": "In a city that feeds on lies, truth can be a weapon." + }, + "sy_passiflora": { + "name": "Passiflora", + "deck": "syndicate", + "row": "ranged", + "strength": "3", + "ability": "horn", + "filename": "passiflora", + "count": "1", + "quote": "More pilgrims come here than to the Temple of the Eternal Fire..." + }, + "sy_fence": { + "name": "Fence", + "deck": "syndicate", + "row": "ranged", + "strength": "5", + "ability": "", + "filename": "fence", + "count": "1", + "quote": "I prefer the term curator." + }, + "sy_sly_seductress": { + "name": "Sly Seductress", + "deck": "syndicate", + "row": "ranged", + "strength": "8", + "ability": "spy", + "filename": "sly_seductress", + "count": "1", + "quote": "The sweeter her words, the more bitter your losses." + }, + "sy_azar_javed": { + "name": "Azar Javed: Renegade", + "deck": "syndicate", + "row": "leader", + "strength": "", + "ability": "azar_javed", + "filename": "azar_javed", + "count": "1", + "quote": "The sorcerer not only deftly manipulates the power of fire, it can be said that fire has become a part of his very being." + }, + "sy_fisstech_trafficker": { + "name": "Fisstech Trafficker", + "deck": "syndicate", + "row": "ranged", + "strength": "2", + "ability": "avenger", + "filename": "fisstech_trafficker", + "count": "1", + "target": "sy_fisstech", + "quote": "Addictive? Why, not at all! I've quit several times before!" + }, + "sy_fisstech": { + "name": "Fisstech", + "deck": "syndicate", + "row": "siege", + "strength": "8", + "ability": "spy", + "filename": "fisstech", + "count": "1", + "target": "sy_fisstech", + "quote": "Large pupils, chattering teeth, a mad cackle... Aye, that's fisstech for ye." + }, + "sy_savolla": { + "name": "Savolla", + "deck": "syndicate", + "row": "siege", + "strength": "6", + "ability": "hero scorch", + "filename": "savolla", + "count": "1", + "quote": "Witcher mutagens are a forgotten treasure. It's time the world learned of their potential." + }, + "sy_madame_luiza": { + "name": "Madame Luiza", + "deck": "syndicate", + "row": "siege", + "strength": "8", + "ability": "hero", + "filename": "madame_luiza", + "count": "1", + "quote": "We've bedded more men than all Redania's army barracks combined." + }, + "sy_saul_navarette": { + "name": "Saul de Navarette", + "deck": "syndicate", + "row": "siege", + "strength": "5", + "ability": "", + "filename": "saul_navarette", + "count": "1", + "quote": "A connoisseur with bottomless pockets and a soul black as tar." + }, + "sy_cleaver_gang_1": { + "name": "Cleaver's Gang", + "id": 1, + "deck": "syndicate", + "row": "agile_cr", + "strength": "3", + "ability": "bond", + "filename": "cleaver_gang_1", + "count": "1", + "target": "sy_cleaver_gang", + "quote": "With both arms tied behind me back, recall ye said. So feel free to start kickin' me in the arse when the mood strikes ye." + }, + "sy_cleaver_gang_2": { + "name": "Cleaver's Gang", + "id": 2, + "deck": "syndicate", + "row": "agile_cr", + "strength": "3", + "ability": "bond", + "filename": "cleaver_gang_2", + "count": "1", + "target": "sy_cleaver_gang", + "quote": "Frilly frock or Mahakam steel breastplate – wouldn't have mattered." + }, + "sy_cleaver_gang_3": { + "name": "Cleaver's Gang", + "id": 3, + "deck": "syndicate", + "row": "agile_cr", + "strength": "3", + "ability": "bond", + "filename": "cleaver_gang_3", + "count": "1", + "target": "sy_cleaver_gang", + "quote": "Those who try to cheat Cleaver are in for a rude awakening... And a rough landing." + }, + "sy_cleaver_gang_4": { + "name": "Cleaver's Gang", + "id": 4, + "deck": "syndicate", + "row": "agile_cr", + "strength": "3", + "ability": "bond", + "filename": "cleaver_gang_4", + "count": "1", + "target": "sy_cleaver_gang", + "quote": "Nae need to be stingy, pal. There's plenty to go 'round. " + }, + "sy_mutant_killer": { + "name": "Mutant Killer", + "deck": "syndicate", + "row": "ranged", + "strength": "7", + "ability": "", + "filename": "mutant_killer", + "count": "1", + "quote": "You have to keep him on a leash, muzzled and with blinders on, otherwise it'll be trouble." + }, + "sy_moreelse": { + "name": "Moreelse", + "deck": "syndicate", + "row": "ranged", + "strength": "7", + "ability": "", + "filename": "moreelse", + "count": "1", + "quote": "Some witch hunters truly believed the eradication of mages and sorceresses would make the world a better place. Some did not require such justification." + }, + "sy_graden": { + "name": "Graden", + "deck": "syndicate", + "row": "ranged", + "strength": "6", + "ability": "morale", + "filename": "graden", + "count": "1", + "quote": "Initially, we burned any tomes on black magic we found.Recently we decided it might be wise to read them first." + }, + "sy_robber_1": { + "name": "Robber", + "id": 1, + "deck": "syndicate", + "row": "ranged", + "strength": "4", + "ability": "bond", + "filename": "robber_1", + "count": "1", + "target": "sy_robber", + "quote": "I-I already gave ye all me coin!" + }, + "sy_robber_2": { + "name": "Robber", + "id": 2, + "deck": "syndicate", + "row": "ranged", + "strength": "4", + "ability": "bond", + "filename": "robber_2", + "count": "1", + "target": "sy_robber", + "quote": "I-I already gave ye all me coin!" + }, + "sy_robber_3": { + "name": "Robber", + "id": 3, + "deck": "syndicate", + "row": "ranged", + "strength": "4", + "ability": "bond", + "filename": "robber_3", + "count": "1", + "target": "sy_robber", + "quote": "I-I already gave ye all me coin!" + }, + "sy_robber_4": { + "name": "Robber", + "id": 4, + "deck": "syndicate", + "row": "ranged", + "strength": "4", + "ability": "bond", + "filename": "robber_4", + "count": "1", + "target": "sy_robber", + "quote": "I-I already gave ye all me coin!" + }, + "sy_dudu_biberveldt": { + "name": "Dudu Biberveldt", + "deck": "syndicate", + "row": "ranged", + "strength": "1", + "ability": "spy", + "filename": "dudu_biberveldt", + "count": "1", + "quote": "A mimic, among the many other names for his sort: changelings, doublings, vexlings… or dopplers." + }, + "sy_tamara_strenger": { + "name": "Tamara Strenger", + "deck": "syndicate", + "row": "siege", + "strength": "5", + "ability": "", + "filename": "tamara_strenger", + "count": "1", + "quote": "Once the heat of the Fire has set your heart aflame, it gives you strength and leads you down the path of truth for the rest of your life." + }, + "sy_nathaniel_pastodi": { + "name": "Nathaniel Pastodi", + "deck": "syndicate", + "row": "siege", + "strength": "6", + "ability": "", + "filename": "nathaniel_pastodi", + "count": "1", + "quote": "Novigrad – where the impossible becomes possible. A professional torturer turned reverend, for instance." + }, + "sy_jacques_aldersberg": { + "name": "Jacques de Aldersberg", + "deck": "syndicate", + "row": "siege", + "strength": "10", + "ability": "hero", + "filename": "jacques_aldersberg", + "count": "1", + "quote": "Knowledge is my burden. Only I can prevent a calamity." + }, + "sy_jacques_aldersberg": { + "name": "Jacques de Aldersberg", + "deck": "syndicate", + "row": "siege", + "strength": "10", + "ability": "hero", + "filename": "jacques_aldersberg", + "count": "1", + "quote": "Knowledge is my burden. Only I can prevent a calamity." + }, + "sy_igor_hook": { + "name": "Igor the Hook", + "deck": "syndicate", + "row": "siege", + "strength": "10", + "ability": "hero", + "filename": "igor_hook", + "count": "1", + "quote": "In the left corner, a bloodthirsty shaelmaar, and in the right co--oh bollocks... Fight's over, hold your bets!" + }, + "sy_fallen_rayla": { + "name": "Fallen Rayla", + "deck": "syndicate", + "row": "siege", + "strength": "10", + "ability": "hero", + "filename": "fallen_rayla", + "count": "1", + "quote": "Slain by the arrows of those she had hunted. Or so many thought. The Salamandra had different plans for her." + }, + "sy_sausage_maker": { + "name": "Sausage Maker", + "deck": "syndicate", + "row": "close", + "strength": "5", + "ability": "morale", + "filename": "sausage_maker", + "count": "1", + "quote": "Body disposal and sausage makin', that's what I do." + }, + "sy_octavia_hale": { + "name": "Vigilantes: Octavia Hale", + "id": 1, + "deck": "syndicate", + "row": "siege", + "strength": "8", + "ability": "hero muster", + "filename": "octavia_hale", + "count": "1", + "target": "sy_hale_brothers", + "quote": "Woe to all those who find themselves on the wrong side of Octavia Hale, the self-proclaimed world-renowned finder⁠—and punisher⁠." + }, + "sy_fabian_hale": { + "name": "Vigilantes: Fabian Hale", + "id": 2, + "deck": "syndicate", + "row": "ranged", + "strength": "6", + "ability": "", + "filename": "fabian_hale", + "count": "1", + "target": "sy_hale_brothers", + "quote": "Fabian takes great pride in his work, with each “victory” etched upon his skin as a permanent reminder of memories most pleasant." + }, + "sy_ignatius_hale": { + "name": "Vigilantes: Ignatius Hale", + "id": 3, + "deck": "syndicate", + "row": "close", + "strength": "6", + "ability": "", + "filename": "ignatius_hale", + "count": "1", + "target": "sy_hale_brothers", + "quote": "He’s a good boy." + }, + "sy_gellert_bleinheim": { + "name": "Bleinheim Brothers: Gellert", + "id": 1, + "deck": "syndicate", + "row": "ranged", + "strength": "7", + "ability": "bond", + "filename": "gellert_bleinheim", + "count": "1", + "target": "sy_bleinheim_brothers", + "quote": "How's my brother doing in the woods, I wonder..." + }, + "sy_roland_bleinheim": { + "name": "Bleinheim Brothers: Roland", + "id": 1, + "deck": "syndicate", + "row": "ranged", + "strength": "7", + "ability": "bond", + "filename": "roland_bleinheim", + "count": "1", + "target": "sy_bleinheim_brothers", + "quote": "How's my brother doing in the sewers, I wonder..." + }, + "sy_caesar_bilzen": { + "name": "Caesar Bilzen", + "deck": "syndicate", + "row": "ranged", + "strength": "3", + "ability": "morale", + "filename": "caesar_bilzen", + "count": "1", + "quote": "Avid angler, meticulous collector, and a real piece of work." + }, + "sy_rico_meiersdorf": { + "name": "Rico Meiersdorf", + "deck": "syndicate", + "row": "agile_cr", + "strength": "7", + "ability": "spy", + "filename": "rico_meiersdorf", + "count": "1", + "quote": "I never did much like bees." + }, + "sy_cleric_flaming_rose": { + "name": "Cleric of the Flaming Rose", + "id": 1, + "deck": "syndicate", + "row": "ranged", + "strength": "5", + "ability": "muster", + "filename": "cleric_flaming_rose", + "count": "1", + "target": "sy_eternal_fire_disciple", + "quote": "We have two eyes, two ears, but only one tongue, so that we would look and listen twice more than we speak. " + }, + "sy_eternal_fire_disciple": { + "name": "Eternal Fire Disciple", + "id": 2, + "deck": "syndicate", + "row": "ranged", + "strength": "3", + "ability": "", + "filename": "eternal_fire_disciple", + "count": "2", + "target": "sy_eternal_fire_disciple", + "quote": "Look into your hearts, dear brethen. Does a contempt for injustice not burn within it?" + }, + "sy_tidecloack_ransacker": { + "name": "Tidecloack Ransacker", + "deck": "syndicate", + "row": "close", + "strength": "3", + "ability": "scorch_c", + "filename": "tidecloack_ransacker", + "count": "1", + "quote": "There's more wealth in Novigrad than in all of Skellige – and the number of poor saps to match." + }, + "sy_salamandra_lackey": { + "name": "Salamandra Lackey", + "deck": "syndicate", + "row": "close", + "strength": "5", + "ability": "", + "filename": "salamandra_lackey", + "count": "1", + "quote": "Lackeys are expected to perform their first five jobs for no pay, demonstrating their passion for the gig." + }, + "sy_mutant": { + "name": "Mutant", + "deck": "syndicate", + "row": "close", + "strength": "4", + "ability": "muster", + "filename": "mutant", + "count": "3", + "target": "sy_mutant", + "quote": "With the right tools you can shape the human body like wet clay." + }, + "sy_salamandra_mage": { + "name": "Salamandra Mage", + "deck": "syndicate", + "row": "ranged", + "strength": "6", + "ability": "", + "filename": "salamandra_mage", + "count": "1", + "quote": "Building a fire warms people for a day, but setting them on fire..." + }, + "sy_sewer_raider": { + "name": "Sewer Raider", + "deck": "syndicate", + "row": "ranged", + "strength": "8", + "ability": "spy", + "filename": "sewer_raider", + "count": "1", + "quote": "Built for movin' shite, but it moves coin just as well." + }, + "sy_inquisitor_helveed": { + "name": "Grand Inquisitor Helveed", + "deck": "syndicate", + "row": "siege", + "strength": "10", + "ability": "hero", + "filename": "inquisitor_helveed", + "count": "1", + "quote": "No sinful wretch shall escape his fate in the Fire. Of that, I will make sure." + }, + "sy_boris": { + "name": "Boris", + "deck": "syndicate", + "row": "close", + "strength": "9", + "ability": "", + "filename": "boris", + "count": "1", + "quote": "After getting a taste of human flesh, he won't eat anything else." + }, + "sy_halfling_safecracker": { + "name": "Halfling Safecracker", + "deck": "syndicate", + "row": "ranged", + "strength": "8", + "ability": "spy", + "filename": "halfling_safecracker", + "count": "1", + "quote": "With ears sharp as his, he could've been a musician. Alas, one cannot get rich as quickly from applause." + }, + "sy_hammond": { + "name": "Hammond", + "deck": "syndicate", + "row": "close", + "strength": "7", + "ability": "", + "filename": "hammond", + "count": "1", + "quote": "Once mistaken for a whale calf and nearly harpooned. He's avoided swimming ever since." + }, + "sy_sir_skewertooth": { + "name": "Sir Skewertooth", + "deck": "syndicate", + "row": "close", + "strength": "6", + "ability": "", + "filename": "sir_skewertooth", + "count": "1", + "quote": "Here he is! My knight in swining armor!" + }, + "sy_ferko": { + "name": "Ferko the Sculptor", + "deck": "syndicate", + "row": "close", + "strength": "5", + "ability": "scorch", + "filename": "ferko", + "count": "1", + "quote": "Some call it base thuggery. But me, I consider it the highest art form." + }, + "sy_hvitr_aelydia": { + "name": "Hvitr and Aelydia", + "deck": "syndicate", + "row": "close", + "strength": "8", + "ability": "hero", + "filename": "hvitr_aelydia", + "count": "1", + "quote": "Inseparable. Invincible. Irresponsible." + }, + "sy_bincy_blumerholdt": { + "name": "Bincy_Blumerholdt", + "deck": "syndicate", + "row": "close", + "strength": "7", + "ability": "spy", + "filename": "bincy_blumerholdt", + "count": "1", + "quote": "In all Novigrad, she has the hairiest feet and the stickiest hands." + }, + "sy_freak_show_1": { + "name": "Freak Show", + "id": 1, + "deck": "syndicate", + "row": "close", + "strength": "3", + "ability": "muster", + "filename": "freak_show_1", + "count": "1", + "target": "sy_freak_show", + "quote": "What do ye mean, Why? The game was beginnin' to drag!" + }, + "sy_freak_show_2": { + "name": "Freak Show", + "id": 2, + "deck": "syndicate", + "row": "close", + "strength": "3", + "ability": "muster", + "filename": "freak_show_2", + "count": "1", + "target": "sy_freak_show", + "quote": "The boss always gets to have the most fun. Truth be told, I prefer to watch anyway." + }, + "sy_freak_show_3": { + "name": "Freak Show", + "id": 3, + "deck": "syndicate", + "row": "close", + "strength": "3", + "ability": "muster", + "filename": "freak_show_3", + "count": "1", + "target": "sy_freak_show", + "quote": "A game where good aim is considered subjective." + }, + "sy_freak_show_4": { + "name": "Freak Show", + "id": 4, + "deck": "syndicate", + "row": "close", + "strength": "3", + "ability": "muster", + "filename": "freak_show_4", + "count": "1", + "target": "sy_freak_show", + "quote": "Why the long face, friend?" + }, + "sy_mutated_hound_1": { + "name": "Mutated Hounds", + "id": 1, + "deck": "syndicate", + "row": "close", + "strength": "5", + "ability": "muster", + "filename": "mutated_hound_1", + "count": "1", + "target": "sy_mutated_hound", + "quote": "We couldn't decide what to name him and it just kind of came up..." + }, + "sy_mutated_hound_2": { + "name": "Mutated Hounds", + "id": 2, + "deck": "syndicate", + "row": "close", + "strength": "5", + "ability": "muster", + "filename": "mutated_hound_2", + "count": "1", + "target": "sy_mutated_hound", + "quote": "Out of man's best friend we made his worst enemy." + }, + "sy_adriano_mink": { + "name": "Adriano the Mink", + "deck": "syndicate", + "row": "close", + "strength": "6", + "ability": "", + "filename": "adriano_mink", + "count": "1", + "quote": "Right here, beautiful. Have a sit on daddy's lap." + }, + "sy_beggar": { + "name": "Beggar", + "deck": "syndicate", + "row": "close", + "strength": "3", + "ability": "avenger", + "filename": "beggar", + "count": "1", + "target": "sy_beggar", + "quote": "Say what you will about his technique, I think he captured your good side." + }, + "sy_payroll_specialist": { + "name": "Payroll Specialist", + "deck": "syndicate", + "row": "close", + "strength": "3", + "ability": "morale", + "filename": "payroll_specialist", + "count": "1", + "quote": "Guards in Novigrad work for very little money, yet live like kings. Just another paradox of the Free City..." + }, + "sy_arena_endrega": { + "name": "Arena Endrega", + "deck": "syndicate", + "row": "close", + "strength": "6", + "ability": "", + "filename": "arena_endrega", + "count": "1", + "quote": "Strong as an ox, dumb as a box." + }, + "sy_arena_ghoul": { + "name": "Arena Ghoul", + "deck": "syndicate", + "row": "close", + "strength": "6", + "ability": "", + "filename": "arena_ghoul", + "count": "1", + "quote": "He'll be a perfect fit for your arena. Just like a mutt lickin' your plate after dinner." + }, + "sy_tatterwing": { + "name": "Tatterwing", + "deck": "syndicate", + "row": "close", + "strength": "6", + "ability": "", + "filename": "tatterwing", + "count": "1", + "quote": "She seems a bit sluggish. A few quick jabs to the ribs oughta liven her up." + }, + "sy_temple_guard": { + "name": "Temple Guard", + "deck": "syndicate", + "row": "close", + "strength": "5", + "ability": "", + "filename": "temple_guard", + "count": "1", + "quote": "Halt! Who goes there?! Firesworn or heretic?" + }, + "sy_passiflora_peaches": { + "name": "Passiflora Peaches", + "deck": "syndicate", + "row": "close", + "strength": "9", + "ability": "spy", + "filename": "passiflora_peaches", + "count": "1", + "quote": "They'll mess with your head, break your heart and empty your purse." + }, + "sy_lieutenant_herst": { + "name": "Lieutenant von Herst", + "deck": "syndicate", + "row": "close", + "strength": "5", + "ability": "", + "filename": "lieutenant_herst", + "count": "1", + "quote": "The fall of the Order wasn’t so hard for him like for the others." + }, + "sy_mutant_maker": { + "name": "Mutant Maker", + "deck": "syndicate", + "row": "close", + "strength": "5", + "ability": "avenger", + "filename": "mutant_maker", + "count": "1", + "target": "sy_failed_experiment", + "quote": "I’m a scientist, truly. I can’t help it if the Oxenfurt professors were just too narrow-sighted to appreciate my particular research methods." + }, + "sy_sea_jackal": { + "name": "Sea Jackal", + "deck": "syndicate", + "row": "close", + "strength": "5", + "ability": "", + "filename": "sea_jackal", + "count": "1", + "quote": "You ever lift rings off a body that's been left to soak for two weeks? No? Then don't complain." + }, + "sy_fallen_knight": { + "name": "Fallen Knight", + "deck": "syndicate", + "row": "close", + "strength": "6", + "ability": "", + "filename": "fallen_knight", + "count": "1", + "quote": "He abandoned the righteous fight and the flame in him has long gone." + }, + "sy_sukrus": { + "name": "Sukrus", + "deck": "syndicate", + "row": "close", + "strength": "6", + "ability": "", + "filename": "sukrus", + "count": "1", + "quote": "One of many who sought fortune in Novigrad. And one of many more who never found it. " + }, + "sy_kurt": { + "name": "Kurt", + "deck": "syndicate", + "row": "close", + "strength": "6", + "ability": "", + "filename": "kurt", + "count": "1", + "quote": "Oy, Kurt, find out what Merigold's hollerin' about, if she needs anything. A hot iron to the tongue, maybe?" + }, + "sy_whoreson_senior": { + "name": "Whoreson Senior", + "deck": "syndicate", + "row": "close", + "strength": "9", + "ability": "hero", + "filename": "whoreson_senior", + "count": "1", + "quote": "Like father, like son." + }, + "sy_lonely_champion": { + "name": "Lonely Champion", + "deck": "syndicate", + "row": "close", + "strength": "10", + "ability": "", + "filename": "lonely_champion", + "count": "1", + "quote": "So long as he continues the righteous fight, the Order and its flame endure." + }, + "sy_failed_experiment": { + "name": "Failed Experiment", + "deck": "syndicate", + "row": "close", + "strength": "8", + "ability": "", + "filename": "failed_experiment", + "count": "1", + "quote": "Even failed experiments can serve a purpose. How else would one be expected to push the boundaries of knowledge?" + }, + "sy_frightener": { + "name": "Savolla's Frightener", + "deck": "syndicate", + "row": "close", + "strength": "9", + "ability": "hero scorch_c", + "filename": "frightener", + "count": "1", + "quote": "The witchers thought the Salamandra thugs wouldn't get through Kaer Morhen's walls. The witchers were wrong." + }, + "sy_stolen_mutagens": { + "name": "Stolen Mutagens", + "deck": "syndicate", + "row": "close", + "strength": "1", + "ability": "horn", + "filename": "stolen_mutagens", + "count": "1", + "quote": "Like organ harvesting—but far more lucrative." + }, + "spe_vivaldi_bank": { + "name": "Vivaldi Bank", + "deck": "special syndicate", + "row": "", + "strength": "", + "ability": "bank", + "filename": "vivaldi_bank", + "count": "2", + "quote": "We're sorry to lose your business, but we wish ye well!" + } +}; + +var ext_ze_cards = { + "ze_zerrikanterment": { + "name": "Zerrikanterment", + "deck": "zerrikania", + "row": "leader", + "strength": "", + "ability": "zerrikanterment", + "filename": "zerrikanterment", + "count": "1", + "quote": "Legend says he burned the forests around Zerrikania making it isolated from the world by deserts and wastelands." + }, + "ze_baal_zebuth": { + "name": "Ball-Zebuth", + "deck": "zerrikania", + "row": "leader", + "strength": "", + "ability": "baal_zebuth", + "filename": "baal_zebuth", + "count": "1", + "quote": "God of moist and dark sky, it is believed to be the polar opposite of Raróg." + }, + "ze_rarog": { + "name": "Raróg", + "deck": "zerrikania", + "row": "leader", + "strength": "", + "ability": "rarog", + "filename": "rarog", + "count": "1", + "quote": "Fierce deity of fire and warm sky, it is believed to be the polar opposite of Baal-Zebuth." + }, + "ze_villentretenmerth": { + "name": "Villentretenmerth", + "deck": "zerrikania", + "row": "close", + "strength": "9", + "ability": "whorshipped", + "filename": "villentretenmerth", + "count": "1", + "quote": "Also calls himself Borkh Three Jackdaws... he's not the best at names." + }, + "ze_myrgtabrakke": { + "name": "Myrgtabrakke", + "deck": "zerrikania", + "row": "siege", + "strength": "8", + "ability": "whorshipped medic", + "filename": "myrgtabrakke", + "count": "1", + "quote": "Never get between a mother dragon and her young." + }, + "ze_merineaevelth": { + "name": "Merineaevelth", + "deck": "zerrikania", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "merineaevelth", + "count": "1", + "quote": "Queen of Zerrikania and founder of the Faithel." + }, + "ze_saulrenith": { + "name": "Saulrenith", + "deck": "zerrikania", + "row": "ranged", + "strength": "8", + "ability": "hero medic", + "filename": "saulrenith", + "count": "1", + "quote": "Impulsive and violent - not the mixture of traits one would trifle with." + }, + "ze_tea_vea_1": { + "name": "Tea & Vea", + "deck": "zerrikania", + "row": "close", + "strength": "5", + "ability": "muster whorshipper", + "filename": "tea_vea_1", + "count": "1", + "target": "wu_tea_vea", + "quote": "Her sabre, drawn faster than they eye could see, cut through the air." + }, + "ze_tea_vea_2": { + "name": "Tea & Vea", + "deck": "zerrikania", + "row": "close", + "strength": "5", + "ability": "muster whorshipper", + "filename": "tea_vea_2", + "count": "1", + "target": "wu_tea_vea", + "quote": "Her sabre, drawn faster than they eye could see, cut through the air." + }, + "ze_faithel_1": { + "name": "Faithel", + "deck": "zerrikania", + "row": "close", + "strength": "4", + "ability": "whorshipper", + "filename": "faithel_1", + "count": "1", + "quote": "Their goal is to find a dragon, honour it and swear their allegiance." + }, + "ze_faithel_2": { + "name": "Faithel", + "deck": "zerrikania", + "row": "close", + "strength": "4", + "ability": "whorshipper", + "filename": "faithel_2", + "count": "1", + "quote": "Their goal is to find a dragon, honour it and swear their allegiance." + }, + "ze_faithel_3": { + "name": "Faithel", + "deck": "zerrikania", + "row": "close", + "strength": "4", + "ability": "whorshipper", + "filename": "faithel_3", + "count": "1", + "quote": "Their goal is to find a dragon, honour it and swear their allegiance." + }, + "ze_myrgot": { + "name": "Myrgot", + "deck": "zerrikania", + "row": "close", + "strength": "6", + "ability": "", + "filename": "myrgot", + "count": "1", + "quote": "Scarred with shame, Myrgot never again returned to Caingorn after his disgraceful lost in the jouting with the pious knight Eyck of Denesle." + }, + "ze_lilit_niya": { + "name": "Lilit-Niya", + "deck": "zerrikania", + "row": "ranged", + "strength": "11", + "ability": "hero", + "filename": "lilit_niya", + "count": "1", + "quote": "The Black Sun was to announce the imminent return of Lilit, still honoured in the East under the name of Niya, and the extermination of the human race." + }, + "ze_ocvist": { + "name": "Ocvist", + "deck": "zerrikania", + "row": "ranged", + "strength": "7", + "ability": "whorshipped", + "filename": "ocvist", + "count": "1", + "quote": "The Master of Quartz Mountain, the Destroyer, Trajan's Slayer. In his free time, he likes long walks and candlelight dinners." + }, + "ze_keltullis": { + "name": "Keltullis", + "deck": "zerrikania", + "row": "close", + "strength": "6", + "ability": "whorshipped scorch_c", + "filename": "keltullis", + "count": "1", + "quote": "They fought 'er for near a century and they realized she weren't goin' nowheres, so... they cut a deal.She dinnae bother 'em, they give 'er what she needs." + }, + "ze_ostreverg": { + "name": "Ostreverg", + "deck": "zerrikania", + "row": "siege", + "strength": "7", + "ability": "whorshipped", + "filename": "ostreverg", + "count": "1", + "quote": "A long time ago the dragon Ostreverg ravaged and plundered the sacred Temple of Freya on the Skellige Islands." + }, + "ze_germinus": { + "name": "Germinus", + "deck": "zerrikania", + "row": "ranged", + "strength": "8", + "ability": "whorshipped", + "filename": "germinus", + "count": "1", + "quote": "The dragon valued its treasures above all else, unleashing its wrath on anything threatening it." + }, + "ze_azar_javed": { + "name": "Azar Javed", + "deck": "zerrikania", + "row": "ranged", + "strength": "7", + "ability": "scorch", + "filename": "azar_javed", + "count": "1", + "quote": "The sorcerer not only deftly manipulates the power of fire, it can be said that fire has become a part of his very being." + }, + "ze_bart": { + "name": "Bart", + "deck": "zerrikania", + "row": "close", + "strength": "4", + "ability": "morale", + "filename": "bart", + "count": "1", + "quote": "A good watchman should be brainless enough to render any thought of betraying his master impossible." + }, + "ze_venomous_basilisk": { + "name": "Venomous Basilisk", + "deck": "zerrikania", + "row": "ranged", + "strength": "6", + "ability": "scorch_c", + "filename": "venomous_basilisk", + "count": "1", + "quote": "The Basilisk is the most venomous creature in the world! For the basilisk is the king of all serpents!" + }, + "ze_giant_spotted_spider": { + "name": "Giant Spotted Spider", + "deck": "zerrikania", + "row": "ranged", + "strength": "10", + "ability": "hero", + "filename": "giant_spotted_spider", + "count": "1", + "quote": "Every beast roaming the forest is its prey, even elephants." + }, + "ze_emetouka": { + "name": "Emetouka", + "deck": "zerrikania", + "row": "close", + "strength": "6", + "ability": "", + "filename": "emetouka", + "count": "1", + "quote": "Their horn have immense value, mostly because many died trying to hunt them." + }, + "ze_leopard_1": { + "name": "Leopard", + "deck": "zerrikania", + "row": "close", + "strength": "4", + "ability": "bond", + "filename": "leopard_1", + "count": "1", + "target": "ze_leopard", + "quote": "Many their preys have mistaken their relaxed state for safety, leopards simply know they will quickly catch up on them." + }, + "ze_leopard_2": { + "name": "Leopard", + "deck": "zerrikania", + "row": "close", + "strength": "4", + "ability": "bond", + "filename": "leopard_2", + "count": "1", + "target": "ze_leopard", + "quote": "Many their preys have mistaken their relaxed state for safety, leopards simply know they will quickly catch up on them." + }, + "ze_tiger_1": { + "name": "Tiger", + "deck": "zerrikania", + "row": "close", + "strength": "5", + "ability": "bond", + "filename": "tiger_1", + "count": "1", + "target": "ze_tiger", + "quote": "The queen favourite beast. After dragons obviously." + }, + "ze_tiger_2": { + "name": "Tiger", + "deck": "zerrikania", + "row": "close", + "strength": "5", + "ability": "bond", + "filename": "tiger_2", + "count": "1", + "target": "ze_tiger", + "quote": "The queen favourite beast. After dragons obviously." + }, + "ze_jackals": { + "name": "Jackals", + "deck": "zerrikania", + "row": "ranged", + "strength": "3", + "ability": "muster", + "filename": "jackals", + "count": "3", + "target": "ze_jackals", + "quote": "Not the most dangerous but surprisingly one of the most hated wild beasts around." + }, + "ze_boa": { + "name": "Boa", + "deck": "zerrikania", + "row": "close", + "strength": "4", + "ability": "", + "filename": "boa", + "count": "1", + "quote": "Living choking hazard." + }, + "ze_python": { + "name": "Python", + "deck": "zerrikania", + "row": "close", + "strength": "4", + "ability": "", + "filename": "python", + "count": "1", + "quote": "'Look at this weird fallen tree! Oh shit, it's moving towards us!'" + }, + "ze_viper": { + "name": "Viper", + "deck": "zerrikania", + "row": "close", + "strength": "4", + "ability": "", + "filename": "viper", + "count": "1", + "quote": "'Had to flee me home, some damn viper had made it its den.'" + }, + "ze_hyenas": { + "name": "Hyenas", + "deck": "zerrikania", + "row": "close", + "strength": "5", + "ability": "", + "filename": "hyenas", + "count": "1", + "quote": "'Those ploughin' wretches always hunt in packs. They killed all my hens and I couldn't do nothin'.'" + }, + "ze_collective_trance": { + "name": "Collective Trance", + "deck": "zerrikania", + "row": "siege", + "strength": "4", + "ability": "medic", + "filename": "collective_trance", + "count": "1", + "quote": "Zerrikanians have this old tradition to join together, share a strong psychedelic decoction and escape the harsh reality." + }, + "ze_hippotoxotai_1": { + "name": "Hippotoxotai", + "deck": "zerrikania", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "hippotoxotai_1", + "count": "1", + "target": "ze_hippotoxotai", + "quote": "Only dust clouds, arrows and death." + }, + "ze_hippotoxotai_2": { + "name": "Hippotoxotai", + "deck": "zerrikania", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "hippotoxotai_2", + "count": "1", + "target": "ze_hippotoxotai", + "quote": "Only dust clouds, arrows and death." + }, + "ze_hippotoxotai_3": { + "name": "Hippotoxotai", + "deck": "zerrikania", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "hippotoxotai_3", + "count": "1", + "target": "ze_hippotoxotai", + "quote": "Only dust clouds, arrows and death." + }, + "ze_skuda_amazon_1": { + "name": "Skuda Amazon", + "deck": "zerrikania", + "row": "ranged", + "strength": "6", + "ability": "bond", + "filename": "skuda_amazon_1", + "count": "1", + "target": "ze_skuda_amazon", + "quote": "Their legendary markswomanship is very real." + }, + "ze_skuda_amazon_2": { + "name": "Skuda Amazon", + "deck": "zerrikania", + "row": "ranged", + "strength": "6", + "ability": "bond", + "filename": "skuda_amazon_2", + "count": "1", + "target": "ze_skuda_amazon", + "quote": "'I don't need to cut my breast to hit a bull's eye at full speed.'" + }, + "ze_bomb_maker_1": { + "name": "Zerrikanian Bomb Maker", + "deck": "zerrikania", + "row": "ranged", + "strength": "3", + "ability": "scorch", + "filename": "bomb_maker_1", + "count": "1", + "quote": "Business of Zerrikanian bombs is... booming." + }, + "ze_bomb_maker_2": { + "name": "Zerrikanian Bomb Maker", + "deck": "zerrikania", + "row": "ranged", + "strength": "3", + "ability": "scorch", + "filename": "bomb_maker_2", + "count": "1", + "quote": "Business of Zerrikanian bombs is... booming." + }, + "ze_heavy_fire_scorpion": { + "name": "Heavy Zerrikanian Fire Scorprion", + "deck": "zerrikania", + "row": "siege", + "strength": "10", + "ability": "", + "filename": "heavy_fire_scorpion", + "count": "1", + "quote": "Not the best for taking cities, but great for razing them to the ground." + }, + "ze_free_warrior_1": { + "name": "Free Warrior", + "deck": "zerrikania", + "row": "close", + "strength": "4", + "ability": "inspire", + "filename": "free_warrior_1", + "count": "1", + "quote": "'Hmm, that feeling of freedom after defeating your foe!'" + }, + "ze_free_warrior_2": { + "name": "Free Warrior", + "deck": "zerrikania", + "row": "close", + "strength": "5", + "ability": "inspire", + "filename": "free_warrior_2", + "count": "1", + "quote": "She first lets her prey get lost in the jungle, then she starts the hunt." + }, + "ze_free_warrior_3": { + "name": "Free Warrior", + "deck": "zerrikania", + "row": "close", + "strength": "8", + "ability": "inspire", + "filename": "free_warrior_3", + "count": "1", + "quote": "Few in the northern realms can afford his sword." + }, + "ze_free_warrior_4": { + "name": "Free Warrior", + "deck": "zerrikania", + "row": "ranged", + "strength": "6", + "ability": "inspire", + "filename": "free_warrior_4", + "count": "1", + "quote": "'See that thing running over there, I'll make it stop.'" + }, + "ze_free_warrior_5": { + "name": "Free Warrior", + "deck": "zerrikania", + "row": "ranged", + "strength": "7", + "ability": "inspire", + "filename": "free_warrior_5", + "count": "1", + "quote": "'At first I thought it was one o' those leopards, ye know? Till I saw the spear and realized 'twas in fact a woman.'" + }, + "ze_first_faithel_kia": { + "name": "First Faithel Kia", + "deck": "zerrikania", + "row": "close", + "strength": "9", + "ability": "hero whorshipper", + "filename": "first_faithel_kia", + "count": "1", + "quote": "Once a close friend of Merineaevelth, she was the first tasked to find and protect the devine dragons of the world." + }, + "ze_apucunpture_healer": { + "name": "Apucunpture Healer", + "deck": "zerrikania", + "row": "siege", + "strength": "6", + "ability": "medic", + "filename": "apucunpture_healer", + "count": "1", + "quote": "You might find it surprising, but these needles soothe pain." + }, + "ze_canyon_herbalist": { + "name": "Canyon Herbalist", + "deck": "zerrikania", + "row": "ranged", + "strength": "5", + "ability": "morale", + "filename": "canyon_herbalist", + "count": "1", + "quote": "It is easy to get lost in the canyon, but knowing its herbs is a rare gift." + }, + "ze_high_priestess_nia": { + "name": "High Priestess Nia", + "deck": "zerrikania", + "row": "ranged", + "strength": "10", + "ability": "hero", + "filename": "high_priestess_nia", + "count": "1", + "quote": "Battles have been fought in her name. Each bloodier than the last." + }, + "ze_dragon_priestess_lua": { + "name": "Dragon Priestess Lua", + "deck": "zerrikania", + "row": "siege", + "strength": "8", + "ability": "hero whorshipper", + "filename": "dragon_priestess_lua", + "count": "1", + "quote": "Mastering the arcana of dragon magic is no small feat." + }, + "ze_rainforest_pathfinder": { + "name": "Rainforest Pathfinder", + "deck": "zerrikania", + "row": "ranged", + "strength": "8", + "ability": "spy", + "filename": "rainforest_pathfinder", + "count": "1", + "quote": "How to cross the Sar'gaedd forest? Take a map, see where the nearest tribal village is, then hire a local guide." + }, + "ze_steppes_nomad_1": { + "name": "Steppes Nomad", + "id": 1, + "deck": "zerrikania", + "row": "siege", + "strength": "5", + "ability": "muster", + "filename": "steppes_nomad_1", + "count": "1", + "target": "ze_steppes_nomad", + "quote": "It takes robustness and unity to survive in these vast steppes." + }, + "ze_steppes_nomad_2": { + "name": "Steppes Nomad", + "id": 2, + "deck": "zerrikania", + "row": "siege", + "strength": "5", + "ability": "muster", + "filename": "steppes_nomad_2", + "count": "1", + "target": "ze_steppes_nomad", + "quote": "It takes robustness and unity to survive in these vast steppes." + }, + "ze_war_elephant": { + "name": "War Elephant", + "deck": "zerrikania", + "row": "close", + "strength": "9", + "ability": "", + "filename": "war_elephant", + "count": "1", + "quote": "It's hard to find journals of what it is like to see a Zerrikanian elephant battalion charging towards you, for it requires survivors." + }, + "ze_behemoth": { + "name": "Behemoth", + "deck": "zerrikania", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "behemoth", + "count": "1", + "quote": "A beast so huge its turd piles were big enough to provide housing for whole families. If it wasn't for the stench that is." + }, + "ze_balladeer": { + "name": "Balladeer", + "deck": "zerrikania", + "row": "ranged", + "strength": "1", + "ability": "horn", + "filename": "balladeer", + "count": "1", + "quote": "It is known the Zerrikanian queen was a tought woman and that only the mellifluous voice of a deft singer could penetrate the hard shell around her heart." + }, + "ze_alchemist": { + "name": "Zerrikanian Alchemist", + "deck": "zerrikania", + "row": "siege", + "strength": "1", + "ability": "medic", + "filename": "alchemist", + "count": "1", + "quote": "'What if I put some of this too...'" + }, + "ze_yellow_witch_korath": { + "name": "Yellow Witch Korath", + "deck": "zerrikania", + "row": "ranged", + "strength": "10", + "ability": "hero", + "filename": "yellow_witch_korath", + "count": "1", + "quote": "A man once forgot her full title is mistakenly called her a 'sand witch'. Now is lacquered skull decorates her staff." + }, + "ze_sandworm": { + "name": "Sandworm", + "deck": "zerrikania", + "row": "close", + "strength": "11", + "ability": "hero", + "filename": "sandworm", + "count": "1", + "quote": "Despite its massive size, many sense it coming only too late." + }, + "spe_giant_spider_web": { + "name": "Giant Spider Webs", + "deck": "weather zerrikania", + "row": "", + "strength": "", + "ability": "frost", + "filename": "giant_spider_web", + "count": "3", + "quote": "Zerrikania hosts spiders so large they can trap elephants in their webs." + }, + "spe_tse_tse_flies": { + "name": "Tse Tse Flies", + "deck": "weather zerrikania", + "row": "", + "strength": "", + "ability": "fog", + "filename": "tse_tse_flies", + "count": "3", + "quote": "The flies are especially repulsive, laying their eggs in the human body, the resulting larvae maturing within the host's head." + }, + "spe_dragon_wrath": { + "name": "Dragon Wrath", + "deck": "weather zerrikania", + "row": "", + "strength": "", + "ability": "rain", + "filename": "dragon_wrath", + "count": "3", + "quote": "Blackened skies from wisps of smoke, the greenery's vanished in a fiery stroke." + }, +}; + +/* + * Selecting cards to use + */ +var card_dict = default_cards; + +card_dict = Object.assign({}, card_dict, ext_nr_cards); +card_dict = Object.assign({}, card_dict, ext_ne_cards); +card_dict = Object.assign({}, card_dict, ext_mo_cards); +card_dict = Object.assign({}, card_dict, ext_st_cards); +card_dict = Object.assign({}, card_dict, ext_sk_cards); +card_dict = Object.assign({}, card_dict, ext_re_cards); +card_dict = Object.assign({}, card_dict, ext_to_cards); +card_dict = Object.assign({}, card_dict, ext_ve_cards); + +card_dict = Object.assign({}, card_dict, ext_wu_cards); +card_dict = Object.assign({}, card_dict, ext_lr_cards); +card_dict = Object.assign({}, card_dict, ext_sy_cards); +card_dict = Object.assign({}, card_dict, ext_ze_cards); \ No newline at end of file diff --git a/cards.old.js b/cards.old.js new file mode 100644 index 0000000..8696e28 --- /dev/null +++ b/cards.old.js @@ -0,0 +1,9604 @@ +/* + * Original cards from The Witcher 3 + */ + +var default_cards = { + "spe_decoy": { + "name": "Decoy", + "deck": "special", + "row": "", + "strength": "", + "ability": "decoy", + "filename": "decoy", + "count": "3", + "quote": "When you run out of peasants, decoys also make decent arrow fodder." + }, + "spe_frost": { + "name": "Biting Frost", + "deck": "weather", + "row": "", + "strength": "", + "ability": "frost", + "filename": "frost", + "count": "3", + "quote": "Best part about frost - bodies of the fallen don't rot so quickly." + }, + "ntr_ciri": { + "name": "Cirilla Fiona Elen Riannon", + "deck": "neutral", + "row": "close", + "strength": "15", + "ability": "hero", + "filename": "ciri", + "count": "1", + "quote": "Know when fairy tales cease to be tales? When people start believing in them." + }, + "spe_clear": { + "name": "Clear Weather", + "deck": "weather", + "row": "", + "strength": "", + "ability": "clear", + "filename": "clear", + "count": "2", + "quote": "The sun' shinin', Dromle! The sun's shinin'! Maybe there's hope left after all..." + }, + "spe_horn": { + "name": "Commander's Horn", + "deck": "special", + "row": "", + "strength": "", + "ability": "horn", + "filename": "horn", + "count": "3", + "quote": "Plus one to morale, minus three to hearing." + }, + "ntr_mysterious_elf": { + "name": "Avallach'h", + "deck": "neutral", + "row": "close", + "strength": "0", + "ability": "hero spy", + "filename": "mysterious_elf", + "count": "1", + "quote": "You humans have... unusual tastes." + }, + "ntr_dandelion": { + "name": "Dandelion", + "deck": "neutral", + "row": "close", + "strength": "2", + "ability": "horn", + "filename": "dandelion", + "count": "1", + "quote": "Dandelion, you're a cynic, a lecher, a whoremonger, a liar - and my best friend." + }, + "ntr_emiel": { + "name": "Emiel Regis Rohellec Terzieff", + "deck": "neutral", + "row": "close", + "strength": "5", + "ability": "", + "filename": "emiel", + "count": "1", + "quote": "Men, the polites ones at least, would call me a monster. A blood-drinking freak." + }, + "ntr_geralt": { + "name": "Geralt of Rivia", + "deck": "neutral", + "row": "close", + "strength": "15", + "ability": "hero", + "filename": "geralt", + "count": "1", + "quote": "If that's what it takes to save the world, it's better to let that world die." + }, + "spe_fog": { + "name": "Impenetrable Fog", + "deck": "weather", + "row": "", + "strength": "", + "ability": "fog", + "filename": "fog", + "count": "3", + "quote": "A good commander's dream... a bad one's horror." + }, + "spe_scorch": { + "name": "Scorch", + "deck": "special", + "row": "", + "strength": "", + "ability": "scorch", + "filename": "scorch", + "count": "3", + "quote": "Pillars of flame turn the mightiest to ash. All others tremble in shock and awe." + }, + "spe_rain": { + "name": "Torrential Rain", + "deck": "weather", + "row": "", + "strength": "", + "ability": "rain", + "filename": "rain", + "count": "2", + "quote": "Even the rain in this land smells like piss." + }, + "ntr_triss": { + "name": "Triss Merigold", + "deck": "neutral", + "row": "close", + "strength": "7", + "ability": "hero", + "filename": "triss", + "count": "1", + "quote": "I can take care of myself. Trust me." + }, + "ntr_vesemir": { + "name": "Vesemir", + "deck": "neutral", + "row": "close", + "strength": "6", + "ability": "", + "filename": "vesemir", + "count": "1", + "quote": "If you're to be hanged, ask for water. Anything can happen before they fetch it." + }, + "ntr_villen": { + "name": "Villentretenmerth", + "deck": "neutral", + "row": "close", + "strength": "7", + "ability": "scorch_c", + "filename": "villen", + "count": "1", + "quote": "Also calls himself Borkh Three Jackdaws... he's not the best at names." + }, + "ntr_yennefer": { + "name": "Yennefer of Vengerberg", + "deck": "neutral", + "row": "ranged", + "strength": "7", + "ability": "hero medic", + "filename": "yennefer", + "count": "1", + "quote": "Magic is Chaos, Art and Science. It is a curse, a blessing and a progression." + }, + "ntr_zoltan": { + "name": "Zoltan Chivay", + "deck": "neutral", + "row": "close", + "strength": "5", + "ability": "", + "filename": "zoltan", + "count": "1", + "quote": "Life without old mates and booze is like a woman without a rump." + }, + "ntr_olgierd": { + "name": "Olgierd von Everec", + "deck": "neutral", + "row": "agile", + "strength": "6", + "ability": "morale", + "filename": "olgierd", + "count": "1", + "quote": "At least you now know I don't easily lose my head." + }, + "ntr_gaunter_odimm": { + "name": "Gaunter O'Dimm", + "id": 1, + "deck": "neutral", + "row": "siege", + "strength": "2", + "ability": "muster", + "filename": "gaunter_odimm", + "count": "1", + "target": "ntr_gaunter_odimm", + "quote": "He always grants exactly what you wish for. That's the problem." + }, + "ntr_gaunter_odimm_darkness": { + "name": "Gaunter O'Dimm - Darkness", + "id": 2, + "deck": "neutral", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "gaunter_odimm_darkness", + "count": "3", + "target": "ntr_gaunter_odimm", + "quote": "Fear not the shadows, but the light." + }, + "ntr_cow": { + "name": "Cow", + "deck": "neutral", + "row": "ranged", + "strength": "0", + "ability": "avenger", + "filename": "cow", + "count": "1", + "target": "ntr_chort", + "quote": "Mooo!" + }, + "ntr_chort": { + "name": "Bovine Defense Force", + "deck": "neutral", + "row": "close", + "strength": "8", + "ability": "", + "filename": "chort", + "count": "0", + "quote": "Grrrrr!" + }, + "nr_foltest_king": { + "name": "Foltest - King of Temeria", + "deck": "realms", + "row": "leader", + "strength": "", + "ability": "foltest_king", + "filename": "foltest_king", + "count": "1", + "quote": "It is natural and beautiful that a man should love his sister." + }, + "nr_foltest_lord": { + "name": "Foltest - Lord Commander of the North", + "deck": "realms", + "row": "leader", + "strength": "", + "ability": "foltest_lord", + "filename": "foltest_lord", + "count": "1", + "quote": "Sod advisors and their schemes. I place my trust in my soldiers' blades." + }, + "nr_foltest_siegemaster": { + "name": "Foltest - The Siegemaster", + "deck": "realms", + "row": "leader", + "strength": "", + "ability": "foltest_siegemaster", + "filename": "foltest_siegemaster", + "count": "1", + "quote": "A well-aimed ballista razes not just the enemy's wall, but his morale as well." + }, + "nr_foltest_steelforged": { + "name": "Foltest - The Steel-Forged", + "deck": "realms", + "row": "leader", + "strength": "", + "ability": "foltest_steelforged", + "filename": "foltest_steelforged", + "count": "1", + "quote": "A beautiful day for battle" + }, + "nr_foltest_son_of_medell": { + "name": "Foltest - Son of Medell", + "deck": "realms", + "row": "leader", + "strength": "", + "ability": "foltest_son", + "filename": "foltest_son_of_medell", + "count": "1", + "quote": "Dammit, I rule this land and I refuse to creep around its corners." + }, + "nr_ballista": { + "name": "Ballista", + "deck": "realms", + "row": "siege", + "strength": "6", + "ability": "", + "filename": "ballista", + "count": "1", + "quote": "'Usually we give 'em female names.' 'Like Jenny?' 'More like Bertha.'" + }, + "nr_blue_stripes_1": { + "name": "Blue Stripes Commando", + "id": 1, + "deck": "realms", + "row": "close", + "strength": "4", + "ability": "bond", + "filename": "blue_stripes_1", + "count": "1", + "target": "nr_blue_stripes", + "quote": "I'd do anything for Temeria. Mostly, though, I kill for her." + }, + "nr_blue_stripes_2": { + "name": "Blue Stripes Commando", + "id": 2, + "deck": "realms", + "row": "close", + "strength": "4", + "ability": "bond", + "filename": "blue_stripes_2", + "count": "1", + "target": "nr_blue_stripes", + "quote": "I'd do anything for Temeria. Mostly, though, I kill for her." + }, + "nr_blue_stripes_3": { + "name": "Blue Stripes Commando", + "id": 3, + "deck": "realms", + "row": "close", + "strength": "4", + "ability": "bond", + "filename": "blue_stripes_3", + "count": "1", + "target": "nr_blue_stripes", + "quote": "I'd do anything for Temeria. Mostly, though, I kill for her." + }, + "nr_catapult_1": { + "name": "Catapult", + "id": 1, + "deck": "realms", + "row": "siege", + "strength": "8", + "ability": "bond", + "filename": "catapult_1", + "count": "1", + "target": "nr_catapult", + "quote": "The gods help those who have better catapults." + }, + "nr_catapult_2": { + "name": "Catapult", + "id": 2, + "deck": "realms", + "row": "siege", + "strength": "8", + "ability": "bond", + "filename": "catapult_2", + "count": "1", + "target": "nr_catapult", + "quote": "The gods help those who have better catapults." + }, + "nr_crinfrid_1": { + "name": "Crinfrid Reavers Dragon Hunter", + "id": 1, + "deck": "realms", + "row": "ranged", + "strength": "5", + "ability": "bond", + "filename": "crinfrid_1", + "count": "1", + "target": "nr_crinfrid", + "quote": "Haven't had much luck with monsters of late, so we enlisted." + }, + "nr_crinfrid_2": { + "name": "Crinfrid Reavers Dragon Hunter", + "id": 2, + "deck": "realms", + "row": "ranged", + "strength": "5", + "ability": "bond", + "filename": "crinfrid_2", + "count": "1", + "target": "nr_crinfrid", + "quote": "Haven't had much luck with monsters of late, so we enlisted." + }, + "nr_crinfrid_3": { + "name": "Crinfrid Reavers Dragon Hunter", + "id": 3, + "deck": "realms", + "row": "ranged", + "strength": "5", + "ability": "bond", + "filename": "crinfrid_3", + "count": "1", + "target": "nr_crinfrid", + "quote": "Haven't had much luck with monsters of late, so we enlisted." + }, + "nr_dethmold": { + "name": "Dethmold", + "deck": "realms", + "row": "ranged", + "strength": "6", + "ability": "", + "filename": "dethmold", + "count": "1", + "quote": "I conce made a prisoner vomit his own entrails... Ah, good times..." + }, + "nr_banner_nurse": { + "name": "Dun Banner Medic", + "deck": "realms", + "row": "siege", + "strength": "5", + "ability": "medic", + "filename": "banner_nurse", + "count": "1", + "quote": "Stitch red to red, white to white, and everything will be all right." + }, + "nr_esterad": { + "name": "Esterad Thyssen", + "deck": "realms", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "esterad", + "count": "1", + "quote": "Like all Thyssen men, he was tall, powerfully built and criminally handsome" + }, + "nr_natalis": { + "name": "John Natalis", + "deck": "realms", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "natalis", + "count": "1", + "quote": "That square should bear the names of my soldiers, of the dead. Not mine." + }, + "nr_kaedwen_siege": { + "name": "Kaedweni Siege Expert", + "deck": "realms", + "row": "siege", + "strength": "1", + "ability": "morale", + "filename": "kaedwen_siege", + "count": "1", + "quote": "'You gotta recalibrate the arm by five degrees.' 'Do what by the what now?'" + }, + "nr_kaedwen_siege_1": { + "name": "Kaedweni Siege Expert", + "deck": "realms", + "row": "siege", + "strength": "1", + "ability": "morale", + "filename": "kaedwen_siege_1", + "count": "1", + "quote": "'You gotta recalibrate the arm by five degrees.' 'Do what by the what now?'" + }, + "nr_kaedwen_siege_2": { + "name": "Kaedweni Siege Expert", + "deck": "realms", + "row": "siege", + "strength": "1", + "ability": "morale", + "filename": "kaedwen_siege_2", + "count": "1", + "quote": "'You gotta recalibrate the arm by five degrees.' 'Do what by the what now?'" + }, + "nr_keira": { + "name": "Keira Metz", + "deck": "realms", + "row": "ranged", + "strength": "5", + "ability": "", + "filename": "keira", + "count": "1", + "quote": "If I'm to die today, I wish to look smashing for the occasion." + }, + "nr_philippa": { + "name": "Philippa Eilhart", + "deck": "realms", + "row": "ranged", + "strength": "10", + "ability": "hero", + "filename": "philippa", + "count": "1", + "quote": "Soon the power of kings will wither, and the Lodge shall seize its rightful place." + }, + "nr_poor_infantry_1": { + "name": "Poor Fucking Infantry", + "id": 1, + "deck": "realms", + "row": "close", + "strength": "1", + "ability": "bond", + "filename": "poor_infantry_1", + "count": "1", + "target": "nr_poor_infantry", + "quote": "I's a war veteran! ... spare me a crown?" + }, + "nr_poor_infantry_2": { + "name": "Poor Fucking Infantry", + "id": 2, + "deck": "realms", + "row": "close", + "strength": "1", + "ability": "bond", + "filename": "poor_infantry_2", + "count": "1", + "target": "nr_poor_infantry", + "quote": "I's a war veteran! ... spare me a crown?" + }, + "nr_poor_infantry_3": { + "name": "Poor Fucking Infantry", + "id": 3, + "deck": "realms", + "row": "close", + "strength": "1", + "ability": "bond", + "filename": "poor_infantry_3", + "count": "1", + "target": "nr_poor_infantry", + "quote": "I's a war veteran! ... spare me a crown?" + }, + "nr_stennis": { + "name": "Prince Stennis", + "deck": "realms", + "row": "close", + "strength": "5", + "ability": "spy", + "filename": "stennis", + "count": "1", + "quote": "He ploughin' wears the golden armor. Golden. 'Course he's an arsehole." + }, + "nr_redania": { + "name": "Redanian Foot Soldier", + "deck": "realms", + "row": "close", + "strength": "1", + "ability": "", + "filename": "redania", + "count": "1", + "quote": "I've bled for Redania! I've killed for Redania... Dammit, I've even raped for Redania!" + }, + "nr_redania_1": { + "name": "Redanian Foot Soldier", + "deck": "realms", + "row": "close", + "strength": "1", + "ability": "", + "filename": "redania_1", + "count": "1", + "quote": "I've bled for Redania! I've killed for Redania... Dammit, I've even raped for Redania!" + }, + "nr_sheldon": { + "name": "Sheldon Skaggs", + "deck": "realms", + "row": "ranged", + "strength": "4", + "ability": "", + "filename": "sheldon", + "count": "1", + "quote": "I was there, on the front lines! Right where the fightin' was the thickest!" + }, + "nr_siege_tower": { + "name": "Siege Tower", + "deck": "realms", + "row": "siege", + "strength": "6", + "ability": "", + "filename": "siege_tower", + "count": "1", + "quote": "I love the clamor of siege towers in the morning. Sounds like victory." + }, + "nr_siegfried": { + "name": "Siegfried of Denesle", + "deck": "realms", + "row": "close", + "strength": "5", + "ability": "", + "filename": "siegfried", + "count": "1", + "quote": "We're on the same side, witcher. You'll realize this one day." + }, + "nr_dijkstra": { + "name": "Sigismund Dijkstra", + "deck": "realms", + "row": "close", + "strength": "4", + "ability": "spy", + "filename": "dijkstra", + "count": "1", + "quote": "Gwent's like politics, just more honest." + }, + "nr_sheala": { + "name": "Síle de Tansarville", + "deck": "realms", + "row": "ranged", + "strength": "5", + "ability": "", + "filename": "sheala", + "count": "1", + "quote": "The Lodge lacks humility. Our lust for power may yet be our undoing." + }, + "nr_thaler": { + "name": "Thaler", + "deck": "realms", + "row": "siege", + "strength": "1", + "ability": "spy", + "filename": "thaler", + "count": "1", + "quote": "Fuck off! We aren't all ploughin' philanderers. Some of us have depth..." + }, + "nr_sabrina": { + "name": "Sabrina Glevissig", + "deck": "realms", + "row": "ranged", + "strength": "4", + "ability": "", + "filename": "sabrina", + "count": "1", + "quote": "The Daughter of the Kaedweni Wilderness." + }, + "nr_vernon": { + "name": "Vernon Roche", + "deck": "realms", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "vernon", + "count": "1", + "quote": "A partiot... and a real son of a bitch." + }, + "nr_ves": { + "name": "Ves", + "deck": "realms", + "row": "close", + "strength": "5", + "ability": "", + "filename": "ves", + "count": "1", + "quote": "Better to live one day as a king than a whole life as a beggar." + }, + "nr_yarpen": { + "name": "Yarpen Zigrin", + "deck": "realms", + "row": "close", + "strength": "2", + "ability": "", + "filename": "yarpen", + "count": "1", + "quote": "The world belongs to whoever's best at crackin' skulls and impregnatin' lasses." + }, + "nr_trebuchet": { + "name": "Trebuchet", + "deck": "realms", + "row": "siege", + "strength": "6", + "ability": "", + "filename": "trebuchet", + "count": "1", + "quote": "Castle won't batter itself down, now will it? Get them trebuchets rollin'!" + }, + "nr_trebuchet_1": { + "name": "Trebuchet", + "deck": "realms", + "row": "siege", + "strength": "6", + "ability": "", + "filename": "trebuchet_1", + "count": "1", + "quote": "Castle won't batter itself down, now will it? Get them trebuchets rollin'!" + }, + "ne_emhyr_imperial": { + "name": "Emhyr var Emreis - His Imperial Majesty", + "deck": "nilfgaard", + "row": "leader", + "strength": "", + "ability": "emhyr_imperial", + "filename": "emhyr_imperial", + "count": "1", + "quote": "The skies wept when my Pavetta died. They will not weep for me." + }, + "ne_emhyr_emperor": { + "name": "Emhyr var Emreis - Emperor of Nilfgaard", + "deck": "nilfgaard", + "row": "leader", + "strength": "", + "ability": "emhyr_emperor", + "filename": "emhyr_emperor", + "count": "1", + "quote": "Your motives do not interest me. Only results." + }, + "ne_emhyr_whiteflame": { + "name": "Emhyr var Emreis - the White Flame", + "deck": "nilfgaard", + "row": "leader", + "strength": "", + "ability": "emhyr_whiteflame", + "filename": "emhyr_whiteflame", + "count": "1", + "quote": "A sword is but one of many tools at a ruler's disposal." + }, + "ne_emhyr_relentless": { + "name": "Emhyr var Emreis - The Relentless", + "deck": "nilfgaard", + "row": "leader", + "strength": "", + "ability": "emhyr_relentless", + "filename": "emhyr_relentless", + "count": "1", + "quote": "They do not call me the Patient. Take care they do not call you the Headless." + }, + "ne_emhyr_invader_of_the_north": { + "name": "Emhyr var Emreis - Invader of the North", + "deck": "nilfgaard", + "row": "leader", + "strength": "", + "ability": "emhyr_invader", + "filename": "emhyr_invader_of_the_north", + "count": "1", + "quote": "Emperors command multitudes, yet cannot control two things: their time and their hearts." + }, + "ne_albrich": { + "name": "Albrich", + "deck": "nilfgaard", + "row": "ranged", + "strength": "2", + "ability": "", + "filename": "albrich", + "count": "1", + "quote": "A fireball? Of course. Whatever Your Imperial Majesty whishes." + }, + "ne_assire": { + "name": "Assire var Anahid", + "deck": "nilfgaard", + "row": "ranged", + "strength": "6", + "ability": "", + "filename": "assire", + "count": "1", + "quote": "Nilfgaardian mages do have a choice, servile submission, or the gallows." + }, + "ne_black_archer": { + "name": "Black Infantry Archer", + "deck": "nilfgaard", + "row": "ranged", + "strength": "10", + "ability": "", + "filename": "black_archer", + "count": "1", + "quote": "I aim for the knee. Always." + }, + "ne_black_archer_1": { + "name": "Black Infantry Archer", + "deck": "nilfgaard", + "row": "ranged", + "strength": "10", + "ability": "", + "filename": "black_archer_1", + "count": "1", + "quote": "I aim for the knee. Always." + }, + "ne_cahir": { + "name": "Cahir Mawr Dyffryn aep Ceallach", + "deck": "nilfgaard", + "row": "close", + "strength": "6", + "ability": "", + "filename": "cahir", + "count": "1", + "quote": "His eyes flashed under his winged helmet. Fire gleamed from his sword's blade." + }, + "ne_cynthia": { + "name": "Cynthia", + "deck": "nilfgaard", + "row": "ranged", + "strength": "4", + "ability": "", + "filename": "cynthia", + "count": "1", + "quote": "Cynthia's talents can be deadly. She needs a tight leash." + }, + "ne_archer_support": { + "name": "Etolian Auxiliary Archers", + "deck": "nilfgaard", + "row": "ranged", + "strength": "1", + "ability": "medic", + "filename": "archer_support", + "count": "1", + "quote": "Double or nothing, aim for his cock" + }, + "ne_archer_support_1": { + "name": "Etolian Auxiliary Archers", + "deck": "nilfgaard", + "row": "ranged", + "strength": "1", + "ability": "medic", + "filename": "archer_support_1", + "count": "1", + "quote": "Double or nothing, aim for his cock" + }, + "ne_fringilla": { + "name": "Fringilla Vigo", + "deck": "nilfgaard", + "row": "ranged", + "strength": "6", + "ability": "", + "filename": "fringilla", + "count": "1", + "quote": "Magic is the highest good. It transcends all borders and divisions." + }, + "ne_heavy_zerri": { + "name": "Heavy Zerrikanian Fire Scorpion", + "deck": "nilfgaard", + "row": "siege", + "strength": "10", + "ability": "", + "filename": "heavy_zerri", + "count": "1", + "quote": "Not the best for taking cities, but great for razing them to the ground." + }, + "ne_impera_brigade_1": { + "name": "Impera Brigade Guard", + "id": 1, + "deck": "nilfgaard", + "row": "close", + "strength": "3", + "ability": "bond", + "filename": "impera_brigade_1", + "count": "1", + "target": "ne_impera_brigade", + "quote": "The Impera Brigade never surrenders. Ever." + }, + "ne_impera_brigade_2": { + "name": "Impera Brigade Guard", + "id": 2, + "deck": "nilfgaard", + "row": "close", + "strength": "3", + "ability": "bond", + "filename": "impera_brigade_2", + "count": "1", + "target": "ne_impera_brigade", + "quote": "The Impera Brigade never surrenders. Ever." + }, + "ne_impera_brigade_3": { + "name": "Impera Brigade Guard", + "id": 3, + "deck": "nilfgaard", + "row": "close", + "strength": "3", + "ability": "bond", + "filename": "impera_brigade_3", + "count": "1", + "target": "ne_impera_brigade", + "quote": "The Impera Brigade never surrenders. Ever." + }, + "ne_impera_brigade_4": { + "name": "Impera Brigade Guard", + "id": 4, + "deck": "nilfgaard", + "row": "close", + "strength": "3", + "ability": "bond", + "filename": "impera_brigade_4", + "count": "1", + "target": "ne_impera_brigade", + "quote": "The Impera Brigade never surrenders. Ever." + }, + "ne_letho": { + "name": "Letho of Gulet", + "deck": "nilfgaard", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "letho", + "count": "1", + "quote": "Witchers never die in the beds." + }, + "ne_menno": { + "name": "Menno Coehoorn", + "deck": "nilfgaard", + "row": "close", + "strength": "10", + "ability": "hero medic", + "filename": "menno", + "count": "1", + "quote": "I'll take an attentive reconnaissance unit over a fine cavalry brigade any day." + }, + "ne_morteisen": { + "name": "Morteisen", + "deck": "nilfgaard", + "row": "close", + "strength": "3", + "ability": "", + "filename": "morteisen", + "count": "1", + "quote": "No Nordling pikemen or dwarven spearbearers can hope to best trained cavalary." + }, + "ne_moorvran": { + "name": "Morvran Voorhis", + "deck": "nilfgaard", + "row": "siege", + "strength": "10", + "ability": "hero", + "filename": "moorvran", + "count": "1", + "quote": "Summer sun reflecting in the quiet waters of Alba - that's Nilfgaard to me." + }, + "ne_nauzicaa_1": { + "name": "Nausicaa Cavalry Rider", + "id": 1, + "deck": "nilfgaard", + "row": "close", + "strength": "4", + "ability": "bond", + "filename": "nauzicaa_1", + "count": "1", + "target": "ne_nauzicaa", + "quote": "The Emperor will teach the North discipline." + }, + "ne_nauzicaa_2": { + "name": "Nausicaa Cavalry Rider", + "id": 2, + "deck": "nilfgaard", + "row": "close", + "strength": "4", + "ability": "bond", + "filename": "nauzicaa_2", + "count": "1", + "target": "ne_nauzicaa", + "quote": "The Emperor will teach the North discipline." + }, + "ne_nauzicaa_3": { + "name": "Nausicaa Cavalry Rider", + "id": 3, + "deck": "nilfgaard", + "row": "close", + "strength": "4", + "ability": "bond", + "filename": "nauzicaa_3", + "count": "1", + "target": "ne_nauzicaa", + "quote": "The Emperor will teach the North discipline." + }, + "ne_puttkammer": { + "name": "Puttkammer", + "deck": "nilfgaard", + "row": "ranged", + "strength": "3", + "ability": "", + "filename": "puttkammer", + "count": "1", + "quote": "Learned a lot at Braibant Military Academy. How to scrub potatoes, for instance." + }, + "ne_rainfarn": { + "name": "Rainfarn", + "deck": "nilfgaard", + "row": "close", + "strength": "4", + "ability": "", + "filename": "rainfarn", + "count": "1", + "quote": "You'll die as painfully as the pathetic traitor Windhalm did." + }, + "ne_renuald": { + "name": "Renuald aep Matsen", + "deck": "nilfgaard", + "row": "close", + "strength": "5", + "ability": "morale", + "filename": "renuald", + "count": "1", + "quote": "They say the Impera fear nothing. Untrue. Renuald scares them shitless." + }, + "ne_rotten": { + "name": "Rotten Mangonel", + "deck": "nilfgaard", + "row": "siege", + "strength": "3", + "ability": "", + "filename": "rotten", + "count": "1", + "quote": "The rotten smell brings back childhood memories." + }, + "ne_shilard": { + "name": "Shilard Fitz-Oesterlen", + "deck": "nilfgaard", + "row": "close", + "strength": "7", + "ability": "spy", + "filename": "shilard", + "count": "1", + "quote": "Warfare is mere sound and fury - diplomacy is what truly shapes history." + }, + "ne_siege_engineer": { + "name": "Siege Engineer", + "deck": "nilfgaard", + "row": "siege", + "strength": "6", + "ability": "", + "filename": "siege_engineer", + "count": "1", + "quote": "Wielded correctly, a protactor can be a deadly weapon." + }, + "ne_siege_support": { + "name": "Siege Technician", + "deck": "nilfgaard", + "row": "siege", + "strength": "0", + "ability": "medic", + "filename": "siege_support", + "count": "1", + "quote": "I never miss twice." + }, + "ne_stefan": { + "name": "Stefan Skellen", + "deck": "nilfgaard", + "row": "close", + "strength": "9", + "ability": "spy", + "filename": "stefan", + "count": "1", + "quote": "My mark scards the face of our future empress. That is my proudest achievement." + }, + "ne_sweers": { + "name": "Sweers", + "deck": "nilfgaard", + "row": "ranged", + "strength": "2", + "ability": "", + "filename": "sweers", + "count": "1", + "quote": "And hands off the girl! Whatever we may be, we're not savages." + }, + "ne_tibor": { + "name": "Tibor Eggebracht", + "deck": "nilfgaard", + "row": "ranged", + "strength": "10", + "ability": "hero", + "filename": "tibor", + "count": "1", + "quote": "Albaaaa! Forward!! Alba! Long live the Emperor!" + }, + "ne_vanhemar": { + "name": "Vanhemar", + "deck": "nilfgaard", + "row": "ranged", + "strength": "4", + "ability": "", + "filename": "vanhemar", + "count": "1", + "quote": "For a fire mage, he's not very... flamboyant." + }, + "ne_vattier": { + "name": "Vattier de Rideaux", + "deck": "nilfgaard", + "row": "close", + "strength": "4", + "ability": "spy", + "filename": "vattier", + "count": "1", + "quote": "There's never been a problem a well-planned assassination couldn't solve." + }, + "ne_vreemde": { + "name": "Vreemde", + "deck": "nilfgaard", + "row": "close", + "strength": "7", + "ability": "", + "filename": "vreemde", + "count": "1", + "quote": "Discipline is the Empire's deadliest weapon." + }, + "ne_young_emissary_1": { + "name": "Young Emissary", + "id": 1, + "deck": "nilfgaard", + "row": "close", + "strength": "5", + "ability": "bond", + "filename": "young_emissary_1", + "count": "1", + "target": "ne_young_emissary", + "quote": "If I acquit myself well, perhaps next they'll post me somewhere more civilized." + }, + "ne_young_emissary_2": { + "name": "Young Emissary", + "id": 2, + "deck": "nilfgaard", + "row": "close", + "strength": "5", + "ability": "bond", + "filename": "young_emissary_2", + "count": "1", + "target": "ne_young_emissary", + "quote": "If I acquit myself well, perhaps next they'll post me somewhere more civilized." + }, + "ne_zerri": { + "name": "Zerrikanian Fire Scorpion", + "deck": "nilfgaard", + "row": "siege", + "strength": "5", + "ability": "", + "filename": "zerri", + "count": "1", + "quote": "The Zerrikanian Desert used to be a lush garden. Then these came along." + }, + "mo_eredin_commander": { + "name": "Eredin - Commander of the Red Riders", + "deck": "monsters", + "row": "leader", + "strength": "", + "ability": "eredin_commander", + "filename": "eredin_commander", + "count": "1", + "quote": "Go on. Show me your spins, pirouettes and feints. I want to watch." + }, + "mo_eredin_bringer_of_death": { + "name": "Eredin - Bringer of Death", + "deck": "monsters", + "row": "leader", + "strength": "", + "ability": "eredin_bringer_of_death", + "filename": "eredin_bringer_of_death", + "count": "1", + "quote": "It is unavoidable." + }, + "mo_eredin_destroyer": { + "name": "Eredin - Destroyer of Worlds", + "deck": "monsters", + "row": "leader", + "strength": "", + "ability": "eredin_destroyer", + "filename": "eredin_destroyer", + "count": "1", + "quote": "I've long awaited this..." + }, + "mo_eredin_king": { + "name": "Eredin - King of the Wild Hunt", + "deck": "monsters", + "row": "leader", + "strength": "", + "ability": "eredin_king", + "filename": "eredin_king", + "count": "1", + "quote": "Have some dignity. You know how this will end." + }, + "mo_eredin_the_treacherous": { + "name": "Eredin Bréacc Glas - The Treacherous", + "deck": "monsters", + "row": "leader", + "strength": "", + "ability": "eredin_treacherous", + "filename": "eredin_the_treacherous", + "count": "1", + "quote": "I'm enjoying this. You are my toy." + }, + "mo_arachas": { + "name": "Arachas ", + "id": 1, + "deck": "monsters", + "row": "close", + "strength": "4", + "ability": "muster", + "filename": "arachas", + "count": "1", + "target": "mo_arachas", + "quote": "Ugly - nature's way of saying 'Stay the fuck away'" + }, + "mo_arachas_1": { + "name": "Arachas ", + "id": 2, + "deck": "monsters", + "row": "close", + "strength": "4", + "ability": "muster", + "filename": "arachas_1", + "count": "1", + "target": "mo_arachas", + "quote": "Ugly - nature's way of saying 'Stay the fuck away'" + }, + "mo_arachas_2": { + "name": "Arachas ", + "id": 3, + "deck": "monsters", + "row": "close", + "strength": "4", + "ability": "muster", + "filename": "arachas_2", + "count": "1", + "target": "mo_arachas", + "quote": "Ugly - nature's way of saying 'Stay the fuck away'" + }, + "mo_arachas_behemoth": { + "name": "Arachas- Behemoth", + "id": 4, + "deck": "monsters", + "row": "siege", + "strength": "6", + "ability": "muster", + "filename": "arachas_behemoth", + "count": "1", + "target": "mo_arachas", + "quote": "Like a cross between a crab, a spider... and a ploughin' moutain." + }, + "mo_botchling": { + "name": "Botchling", + "deck": "monsters", + "row": "close", + "strength": "4", + "ability": "avenger", + "filename": "botchling", + "count": "1", + "target": "mo_lubberkin", + "quote": "Admit your mistakes and bury them proper - else they'll come back to haunt you." + }, + "mo_celaeno_harpy": { + "name": "Celaeno Harpy", + "deck": "monsters", + "row": "agile", + "strength": "2", + "ability": "", + "filename": "celaeno_harpy", + "count": "1", + "quote": "Common harpies feed on carrion. Calaeno harpies... they feed on dreams." + }, + "mo_cockatrice": { + "name": "Cockatrice", + "deck": "monsters", + "row": "ranged", + "strength": "2", + "ability": "", + "filename": "cockatrice", + "count": "1", + "quote": "Born of an egg laid by a cockerel... if you believe such peasant drivel." + }, + "mo_witch_velen": { + "name": "Crone - Brewess", + "id": 1, + "deck": "monsters", + "row": "close", + "strength": "6", + "ability": "muster", + "filename": "witch_velen", + "count": "1", + "target": "mo_witch_velen", + "quote": "We'll cut you up, boy. A fina broth you will make." + }, + "mo_witch_velen_1": { + "name": "Crone - Weavess", + "id": 2, + "deck": "monsters", + "row": "close", + "strength": "6", + "ability": "muster", + "filename": "witch_velen_1", + "count": "1", + "target": "mo_witch_velen", + "quote": "I sense your pain. I see your fear..." + }, + "mo_witch_velen_2": { + "name": "Crone - Whispess", + "id": 3, + "deck": "monsters", + "row": "close", + "strength": "6", + "ability": "muster", + "filename": "witch_velen_2", + "count": "1", + "target": "mo_witch_velen", + "quote": "I'l be your best - and last." + }, + "mo_draug": { + "name": "Draug", + "deck": "monsters", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "draug", + "count": "1", + "quote": "Some men cannot admit defeat. Some keep fighting from beyond the grave." + }, + "mo_earth_elemental": { + "name": "Earth Elemental", + "deck": "monsters", + "row": "siege", + "strength": "6", + "ability": "", + "filename": "earth_elemental", + "count": "1", + "quote": "How to fight an earth elemental? You don't. You run. Fast as you can." + }, + "mo_endrega": { + "name": "Endrega", + "deck": "monsters", + "row": "ranged", + "strength": "2", + "ability": "", + "filename": "endrega", + "count": "1", + "quote": "The nest! Take out the nest, or the bastard'll just keep coming!" + }, + "mo_fiend": { + "name": "Fiend", + "deck": "monsters", + "row": "close", + "strength": "6", + "ability": "", + "filename": "fiend", + "count": "1", + "quote": "A fiend looks like a deer. An enormous, evil deer." + }, + "mo_fire_elemental": { + "name": "Fire Elemental", + "deck": "monsters", + "row": "siege", + "strength": "6", + "ability": "", + "filename": "fire_elemental", + "count": "1", + "quote": "Fire is so delightful." + }, + "mo_fogling": { + "name": "Foglet", + "deck": "monsters", + "row": "close", + "strength": "2", + "ability": "", + "filename": "fogling", + "count": "1", + "quote": "Fog creeps on little cat feet. Foglets creep over the bodies of their victims." + }, + "mo_forktail": { + "name": "Forktail", + "deck": "monsters", + "row": "close", + "strength": "5", + "ability": "", + "filename": "forktail", + "count": "1", + "quote": "Fork tail.. Bah! Fuckers' tails're more like cleavers." + }, + "mo_frightener": { + "name": "Frightener", + "deck": "monsters", + "row": "close", + "strength": "5", + "ability": "", + "filename": "frightener", + "count": "1", + "quote": "'What have I done?' the mage cried out, frightened of his own creation." + }, + "mo_gargoyle": { + "name": "Gargoyle", + "deck": "monsters", + "row": "ranged", + "strength": "2", + "ability": "", + "filename": "gargoyle", + "count": "1", + "quote": "Ancient sculptors' nightmarish fantasies brought to life by bored mages." + }, + "mo_ghoul": { + "name": "Ghoul", + "id": 1, + "deck": "monsters", + "row": "close", + "strength": "1", + "ability": "muster", + "filename": "ghoul", + "count": "1", + "target": "mo_ghoul", + "quote": "If ghouls are part of the Circle of Life... then it's a damn vicious circle." + }, + "mo_ghoul_1": { + "name": "Ghoul", + "id": 2, + "deck": "monsters", + "row": "close", + "strength": "1", + "ability": "muster", + "filename": "ghoul_1", + "count": "1", + "target": "mo_ghoul", + "quote": "If ghouls are part of the Circle of Life... then it's a damn vicious circle." + }, + "mo_ghoul_2": { + "name": "Ghoul", + "id": 3, + "deck": "monsters", + "row": "close", + "strength": "1", + "ability": "muster", + "filename": "ghoul_2", + "count": "1", + "target": "mo_ghoul", + "quote": "If ghouls are part of the Circle of Life... then it's a damn vicious circle." + }, + "mo_gravehag": { + "name": "Grave Hag", + "deck": "monsters", + "row": "ranged", + "strength": "5", + "ability": "", + "filename": "gravehag", + "count": "1", + "quote": "Their long tongues're for slurping marrow - and whipping prey." + }, + "mo_gryffin": { + "name": "Griffin", + "deck": "monsters", + "row": "close", + "strength": "5", + "ability": "", + "filename": "gryffin", + "count": "1", + "quote": "Griffins like to toy with their prey. Eat 'em alive, piece by piece." + }, + "mo_harpy": { + "name": "Harpy", + "deck": "monsters", + "row": "agile", + "strength": "2", + "ability": "", + "filename": "harpy", + "count": "1", + "quote": "There are many species of harpy, and all are klepmaniacs." + }, + "mo_frost_giant": { + "name": "Ice Giant", + "deck": "monsters", + "row": "siege", + "strength": "5", + "ability": "", + "filename": "frost_giant", + "count": "1", + "quote": "Fled one time in my life. From the Ice Giant. And I'm not a bit ashamed." + }, + "mo_imlerith": { + "name": "Imlerith", + "deck": "monsters", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "imlerith", + "count": "1", + "quote": "Ladd nahw! Kill them! Litter the earth with their entrails!" + }, + "mo_kayran": { + "name": "Kayran", + "deck": "monsters", + "row": "agile", + "strength": "8", + "ability": "hero morale", + "filename": "kayran", + "count": "1", + "quote": "Kill a kayran? Simple. Take your best sword... then sell it and hire a witcher." + }, + "mo_leshen": { + "name": "Leshen", + "deck": "monsters", + "row": "ranged", + "strength": "10", + "ability": "hero", + "filename": "leshen", + "count": "1", + "quote": "We never hunt in these woods. Not even if it means the whole village starves." + }, + "mo_nekker": { + "name": "Nekker", + "id": 1, + "deck": "monsters", + "row": "close", + "strength": "2", + "ability": "muster", + "filename": "nekker", + "count": "1", + "target": "mo_nekker", + "quote": "Damn things are almost cute, if you ignore the whole vicious killer aspect." + }, + "mo_nekker_1": { + "name": "Nekker", + "id": 1, + "deck": "monsters", + "row": "close", + "strength": "2", + "ability": "muster", + "filename": "nekker_1", + "count": "1", + "target": "mo_nekker", + "quote": "Damn things are almost cute, if you ignore the whole vicious killer aspect." + }, + "mo_nekker_2": { + "name": "Nekker", + "id": 3, + "deck": "monsters", + "row": "close", + "strength": "2", + "ability": "muster", + "filename": "nekker_2", + "count": "1", + "target": "mo_nekker", + "quote": "Damn things are almost cute, if you ignore the whole vicious killer aspect." + }, + "mo_mighty_maiden": { + "name": "Plague Maiden", + "deck": "monsters", + "row": "close", + "strength": "5", + "ability": "", + "filename": "mighty_maiden", + "count": "1", + "quote": "The sick rave about a boil-pocked woman surrounded by herds of rabid rats..." + }, + "mo_bruxa": { + "name": "Vampire - Bruxa", + "id": 1, + "deck": "monsters", + "row": "close", + "strength": "4", + "ability": "muster", + "filename": "bruxa", + "count": "1", + "target": "mo_vampire", + "quote": "A vile, bloodthirsty, man-eating hag. Kind of like my mother-in-law." + }, + "mo_ekkima": { + "name": "Vampire - Ekimmara", + "id": 2, + "deck": "monsters", + "row": "close", + "strength": "4", + "ability": "muster", + "filename": "ekkima", + "count": "1", + "target": "mo_vampire", + "quote": "Who would think overgrown bats would have a taste for gaudy jewelry?" + }, + "mo_fleder": { + "name": "Vampire - Fleder", + "id": 3, + "deck": "monsters", + "row": "close", + "strength": "4", + "ability": "muster", + "filename": "fleder", + "count": "1", + "target": "mo_vampire", + "quote": "Higher vampieres embrace their victims. Fleders rim them to shreds." + }, + "mo_garkain": { + "name": "Vampire - Garkain", + "id": 4, + "deck": "monsters", + "row": "close", + "strength": "4", + "ability": "muster", + "filename": "garkain", + "count": "1", + "target": "mo_vampire", + "quote": "Blood-drinkers and corpse-eaters so foul their very ugliness paralyses foes." + }, + "mo_katakan": { + "name": "Vampire - Katakan", + "id": 5, + "deck": "monsters", + "row": "close", + "strength": "5", + "ability": "muster", + "filename": "katakan", + "count": "1", + "target": "mo_vampire", + "quote": "Drinking the blood of the Continent since the Conjunction." + }, + "mo_werewolf": { + "name": "Werewolf", + "deck": "monsters", + "row": "close", + "strength": "5", + "ability": "", + "filename": "werewolf", + "count": "1", + "quote": "Wolves aren't as bad as they say. Werewolves, though - they're worse." + }, + "mo_wyvern": { + "name": "Wyvern", + "deck": "monsters", + "row": "ranged", + "strength": "2", + "ability": "", + "filename": "wyvern", + "count": "1", + "quote": "Imagine a cross between a winged snake and a nightmare. Wyverns are worse." + }, + "mo_toad": { + "name": "Toad", + "deck": "monsters", + "row": "ranged", + "strength": "7", + "ability": "scorch_c", + "filename": "toad", + "count": "1", + "quote": "Big. Bad. Ugly. Squats in the sewers." + }, + "sc_francesca_queen": { + "name": "Francesca Findabair - Queen of Dol Blathanna", + "deck": "scoiatael", + "row": "leader", + "strength": "", + "ability": "francesca_queen", + "filename": "francesca_queen", + "count": "1", + "quote": "Ash shall fertilize the soil. By spring, the valley shall bloom once more." + }, + "sc_francesca_beautiful": { + "name": "Francesca Findabair - the Beautiful", + "deck": "scoiatael", + "row": "leader", + "strength": "", + "ability": "francesca_beautiful", + "filename": "francesca_beautiful", + "count": "1", + "quote": "The Elder Races have forgotten more than humans can ever hope to know." + }, + "sc_francesca_daisy": { + "name": "Francesca Findabair - Daisy of the Valley", + "deck": "scoiatael", + "row": "leader", + "strength": "", + "ability": "francesca_daisy", + "filename": "francesca_daisy", + "count": "1", + "quote": "Do not let my beauty distract your aim." + }, + "sc_francesca_pureblood": { + "name": "Francesca Findabair - Pureblood Elf", + "deck": "scoiatael", + "row": "leader", + "strength": "", + "ability": "francesca_pureblood", + "filename": "francesca_pureblood", + "count": "1", + "quote": "To live in peave, we first must kill. This is human oppression's cruel finale." + }, + "sc_francesca_hope_of_the_aen_seidhe": { + "name": "Francesca Findabair - Hope of the Aen Seidhe", + "deck": "scoiatael", + "row": "leader", + "strength": "", + "ability": "francesca_hope", + "filename": "francesca_hope_of_the_aen_seidhe", + "count": "1", + "quote": "Daede sian caente, Aen Seidhe en'allane ael coeden..." + }, + "sc_ciaran": { + "name": "Ciaran aep Easnillien", + "deck": "scoiatael", + "row": "agile", + "strength": "3", + "ability": "", + "filename": "ciaran", + "count": "1", + "quote": "The path to freedom is paved in blood not ink." + }, + "sc_barclay": { + "name": "Barclay Els", + "deck": "scoiatael", + "row": "agile", + "strength": "6", + "ability": "", + "filename": "barclay", + "count": "1", + "quote": "Our mead smells like piss, do it? Easy to fix - I'll break your fuckin' nose!" + }, + "sc_dennis": { + "name": "Dennis Cranmer", + "deck": "scoiatael", + "row": "close", + "strength": "6", + "ability": "", + "filename": "dennis", + "count": "1", + "quote": "I know how to carry out orders, so you can shove you advice up your coal chute." + }, + "sc_dol_archer": { + "name": "Dol Blathanna Archer", + "deck": "scoiatael", + "row": "ranged", + "strength": "4", + "ability": "", + "filename": "dol_archer", + "count": "1", + "quote": "Take another step, dh'oine. You'd look better with an arrow between your eyes." + }, + "sc_dol_infantry": { + "name": "Dol Blathanna Scout", + "deck": "scoiatael", + "row": "agile", + "strength": "6", + "ability": "", + "filename": "dol_infantry", + "count": "1", + "quote": "They track like hounds, run like deer and kill like cold-hearted bastards." + }, + "sc_dol_infantry_1": { + "name": "Dol Blathanna Scout", + "deck": "scoiatael", + "row": "agile", + "strength": "6", + "ability": "", + "filename": "dol_infantry_1", + "count": "1", + "quote": "They track like hounds, run like deer and kill like cold-hearted bastards." + }, + "sc_dol_infantry_2": { + "name": "Dol Blathanna Scout", + "deck": "scoiatael", + "row": "agile", + "strength": "6", + "ability": "", + "filename": "dol_infantry_2", + "count": "1", + "quote": "They track like hounds, run like deer and kill like cold-hearted bastards." + }, + "sc_dwarf": { + "name": "Dwarven Skirmisher", + "id": 1, + "deck": "scoiatael", + "row": "close", + "strength": "3", + "ability": "muster", + "filename": "dwarf", + "count": "1", + "target": "sc_dwarf", + "quote": "Worked a pickaxe all me life. Battleaxe won't be any trouble." + }, + "sc_dwarf_1": { + "name": "Dwarven Skirmisher", + "id": 2, + "deck": "scoiatael", + "row": "close", + "strength": "3", + "ability": "muster", + "filename": "dwarf_1", + "count": "1", + "target": "sc_dwarf", + "quote": "Worked a pickaxe all me life. Battleaxe won't be any trouble." + }, + "sc_dwarf_2": { + "name": "Dwarven Skirmisher", + "id": 3, + "deck": "scoiatael", + "row": "close", + "strength": "3", + "ability": "muster", + "filename": "dwarf_2", + "count": "1", + "target": "sc_dwarf", + "quote": "Worked a pickaxe all me life. Battleaxe won't be any trouble." + }, + "sc_eithne": { + "name": "Eithné", + "deck": "scoiatael", + "row": "ranged", + "strength": "10", + "ability": "hero", + "filename": "eithne", + "count": "1", + "quote": "The dryad queen has eyes of molten silver, and a heart of cold-forged steel." + }, + "sc_elf_skirmisher": { + "name": "Elven Skirmisher", + "id": 1, + "deck": "scoiatael", + "row": "ranged", + "strength": "2", + "ability": "muster", + "filename": "elf_skirmisher", + "count": "1", + "target": "sc_elf_skirmisher", + "quote": "No matter what you may have heard, elves don't take human scalps. Too much lice." + }, + "sc_elf_skirmisher_1": { + "name": "Elven Skirmisher", + "id": 2, + "deck": "scoiatael", + "row": "ranged", + "strength": "2", + "ability": "muster", + "filename": "elf_skirmisher_1", + "count": "1", + "target": "sc_elf_skirmisher", + "quote": "No matter what you may have heard, elves don't take human scalps. Too much lice." + }, + "sc_elf_skirmisher_2": { + "name": "Elven Skirmisher", + "id": 3, + "deck": "scoiatael", + "row": "ranged", + "strength": "2", + "ability": "muster", + "filename": "elf_skirmisher_2", + "count": "1", + "target": "sc_elf_skirmisher", + "quote": "No matter what you may have heard, elves don't take human scalps. Too much lice." + }, + "sc_filavandrel": { + "name": "Filavandrel aen Fidhail", + "deck": "scoiatael", + "row": "agile", + "strength": "6", + "ability": "", + "filename": "filavandrel", + "count": "1", + "quote": "Though we are now few and scattered, our hearts burn brighter than ever." + }, + "sc_havekar_nurse": { + "name": "Havekar Healer", + "deck": "scoiatael", + "row": "ranged", + "strength": "0", + "ability": "medic", + "filename": "havekar_nurse", + "count": "1", + "quote": "Sure, I'll patch you up. Gonna cost you, though." + }, + "sc_havekar_nurse_1": { + "name": "Havekar Healer", + "deck": "scoiatael", + "row": "ranged", + "strength": "0", + "ability": "medic", + "filename": "havekar_nurse_1", + "count": "1", + "quote": "Sure, I'll patch you up. Gonna cost you, though." + }, + "sc_havekar_nurse_2": { + "name": "Havekar Healer", + "deck": "scoiatael", + "row": "ranged", + "strength": "0", + "ability": "medic", + "filename": "havekar_nurse_2", + "count": "1", + "quote": "Sure, I'll patch you up. Gonna cost you, though." + }, + "sc_havekar_support": { + "name": "Havekar Smuggler", + "id": 1, + "deck": "scoiatael", + "row": "close", + "strength": "5", + "ability": "muster", + "filename": "havekar_support", + "count": "1", + "target": "sc_havekar_support", + "quote": "I fight for whoever's paying the best. Or whoever's easiest to rob." + }, + "sc_havekar_support_1": { + "name": "Havekar Smuggler", + "id": 2, + "deck": "scoiatael", + "row": "close", + "strength": "5", + "ability": "muster", + "filename": "havekar_support_1", + "count": "1", + "target": "sc_havekar_support", + "quote": "I fight for whoever's paying the best. Or whoever's easiest to rob." + }, + "sc_havekar_support_2": { + "name": "Havekar Smuggler", + "id": 3, + "deck": "scoiatael", + "row": "close", + "strength": "5", + "ability": "muster", + "filename": "havekar_support_2", + "count": "1", + "target": "sc_havekar_support", + "quote": "I fight for whoever's paying the best. Or whoever's easiest to rob." + }, + "sc_ida": { + "name": "Ida Emean aep Sivney", + "deck": "scoiatael", + "row": "ranged", + "strength": "6", + "ability": "", + "filename": "ida", + "count": "1", + "quote": "I am a Sage. My power lies in possessing knowledge. Not sharing it." + }, + "sc_iorveth": { + "name": "Iorveth", + "deck": "scoiatael", + "row": "ranged", + "strength": "10", + "ability": "hero", + "filename": "iorveth", + "count": "1", + "quote": "King or beggar, what's the difference? One dh'oine less." + }, + "sc_isengrim": { + "name": "Isengrim Faoiltiarna", + "deck": "scoiatael", + "row": "close", + "strength": "10", + "ability": "hero morale", + "filename": "isengrim", + "count": "1", + "quote": "It dawns on them once they notice my scar: a realization of imminent death." + }, + "sc_mahakam": { + "name": "Mahakaman Defender", + "deck": "scoiatael", + "row": "close", + "strength": "5", + "ability": "", + "filename": "mahakam", + "count": "1", + "quote": "I'm telling ye, we're born for battle - we slash straight at their kneed!" + }, + "sc_mahakam_1": { + "name": "Mahakaman Defender", + "deck": "scoiatael", + "row": "close", + "strength": "5", + "ability": "", + "filename": "mahakam_1", + "count": "1", + "quote": "I'm telling ye, we're born for battle - we slash straight at their kneed!" + }, + "sc_mahakam_2": { + "name": "Mahakaman Defender", + "deck": "scoiatael", + "row": "close", + "strength": "5", + "ability": "", + "filename": "mahakam_2", + "count": "1", + "quote": "I'm telling ye, we're born for battle - we slash straight at their kneed!" + }, + "sc_mahakam_3": { + "name": "Mahakaman Defender", + "deck": "scoiatael", + "row": "close", + "strength": "5", + "ability": "", + "filename": "mahakam_3", + "count": "1", + "quote": "I'm telling ye, we're born for battle - we slash straight at their kneed!" + }, + "sc_mahakam_4": { + "name": "Mahakaman Defender", + "deck": "scoiatael", + "row": "close", + "strength": "5", + "ability": "", + "filename": "mahakam_4", + "count": "1", + "quote": "I'm telling ye, we're born for battle - we slash straight at their kneed!" + }, + "sc_milva": { + "name": "Milva", + "deck": "scoiatael", + "row": "ranged", + "strength": "10", + "ability": "morale", + "filename": "milva", + "count": "1", + "quote": "With each arrow I loose, I think of my da. He'd be proud. I think." + }, + "sc_riordain": { + "name": "Riordain", + "deck": "scoiatael", + "row": "ranged", + "strength": "1", + "ability": "", + "filename": "riordain", + "count": "1", + "quote": "Stare into their eyes, feast on their terror. Then go in for the kill." + }, + "sc_saskia": { + "name": "Saesenthessis", + "deck": "scoiatael", + "row": "ranged", + "strength": "10", + "ability": "hero", + "filename": "saskia", + "count": "1", + "quote": "Beautiful, pure, fierce - the perfect icon for a rebellion." + }, + "sc_toruviel": { + "name": "Toruviel", + "deck": "scoiatael", + "row": "ranged", + "strength": "2", + "ability": "", + "filename": "toruviel", + "count": "1", + "quote": "I'd gladly kill you from up close, stare in your eyese... But you reek, human." + }, + "sc_vrihedd_cadet": { + "name": "Vrihedd Brigade Recruit", + "deck": "scoiatael", + "row": "ranged", + "strength": "4", + "ability": "", + "filename": "vrihedd_cadet", + "count": "1", + "quote": "Hatred burns brighter than any fire, and cuts deeper than any blade." + }, + "sc_vrihedd_brigade": { + "name": "Vrihedd Brigade Veteran", + "deck": "scoiatael", + "row": "agile", + "strength": "5", + "ability": "", + "filename": "vrihedd_brigade", + "count": "1", + "quote": "'Vrihedd? What's that mean?' 'Trouble.'" + }, + "sc_vrihedd_brigade_1": { + "name": "Vrihedd Brigade Veteran", + "deck": "scoiatael", + "row": "agile", + "strength": "5", + "ability": "", + "filename": "vrihedd_brigade_1", + "count": "1", + "quote": "'Vrihedd? What's that mean?' 'Trouble.'" + }, + "sc_yaevinn": { + "name": "Yaevinn", + "deck": "scoiatael", + "row": "agile", + "strength": "6", + "ability": "", + "filename": "yaevinn", + "count": "1", + "quote": "We are drops of rain that together make a ferocious storm." + }, + "sk_berserker": { + "name": "Berserker", + "deck": "skellige", + "row": "close", + "strength": "4", + "ability": "berserker", + "filename": "berserker", + "count": "1", + "target": "sk_vildkaarl", + "quote": "Kill, crush, cleave!" + }, + "sk_birna": { + "name": "Birna Bran", + "deck": "skellige", + "row": "close", + "strength": "2", + "ability": "medic", + "filename": "birna", + "count": "1", + "quote": "Skellige must have a strong king. No matter what it takes." + }, + "sk_blueboy": { + "name": "Blueboy Lugos", + "deck": "skellige", + "row": "close", + "strength": "6", + "ability": "", + "filename": "blueboy", + "count": "1", + "quote": "I'm damn near ready to puke from boredom." + }, + "sk_cerys": { + "name": "Cerys", + "id": 4, + "deck": "skellige", + "row": "close", + "strength": "10", + "ability": "hero muster", + "filename": "cerys", + "count": "1", + "target": "sk_shield_maiden", + "quote": "They call me Sparrowhawk, know why? Because I eat rats like you for breakfast." + }, + "sk_brokva_archer": { + "name": "Clan Brokvar Archer", + "deck": "skellige", + "row": "ranged", + "strength": "6", + "ability": "", + "filename": "brokva_archer", + "count": "2", + "quote": "So ye can hit a movin' target at two hundred paces. Me, too. In a storm." + }, + "sk_dimun_pirate": { + "name": "Clan Dimun Pirate", + "deck": "skellige", + "row": "ranged", + "strength": "6", + "ability": "scorch", + "filename": "dimun_pirate", + "count": "1", + "quote": "Can see the fear in their eyes. Fear o' me... fer o' Clan Dimun!" + }, + "sk_shield_maiden_1": { + "name": "Clan Drummond Shield Maiden", + "id": 1, + "deck": "skellige", + "row": "close", + "strength": "4", + "ability": "bond", + "filename": "shield_maiden_1", + "count": "1", + "target": "sk_shield_maiden", + "quote": "They'll shatter on our shields like waves on a rocky shore." + }, + "sk_shield_maiden_2": { + "name": "Clan Drummond Shield Maiden", + "id": 2, + "deck": "skellige", + "row": "close", + "strength": "4", + "ability": "bond", + "filename": "shield_maiden_2", + "count": "1", + "target": "sk_shield_maiden", + "quote": "They'll shatter on our shields like waves on a rocky shore." + }, + "sk_shield_maiden_3": { + "name": "Clan Drummond Shield Maiden", + "id": 3, + "deck": "skellige", + "row": "close", + "strength": "4", + "ability": "bond", + "filename": "shield_maiden_3", + "count": "1", + "target": "sk_shield_maiden", + "quote": "They'll shatter on our shields like waves on a rocky shore." + }, + "sk_heymaey": { + "name": "Clan Heymaey Skald", + "deck": "skellige", + "row": "close", + "strength": "4", + "ability": "", + "filename": "heymaey", + "count": "1", + "quote": "The deeds of Clan Haymaeu will go down in history." + }, + "sk_tordarroch": { + "name": "Clan Tordarroch Armorsmith", + "deck": "skellige", + "row": "close", + "strength": "4", + "ability": "", + "filename": "tordarroch", + "count": "1", + "quote": "Ye're in for poundin'." + }, + "sk_craite_warrior_1": { + "name": "Clan an Craite Warrior", + "id": 1, + "deck": "skellige", + "row": "close", + "strength": "6", + "ability": "bond", + "filename": "craite_warrior_1", + "count": "1", + "target": "sk_craite_warrior", + "quote": "I'll bring the an Craites such glory, bards'll go hoarse singin' me praises!" + }, + "sk_craite_warrior_2": { + "name": "Clan an Craite Warrior", + "id": 2, + "deck": "skellige", + "row": "close", + "strength": "6", + "ability": "bond", + "filename": "craite_warrior_2", + "count": "1", + "target": "sk_craite_warrior", + "quote": "I'll bring the an Craites such glory, bards'll go hoarse singin' me praises!" + }, + "sk_craite_warrior_3": { + "name": "Clan an Craite Warrior", + "id": 3, + "deck": "skellige", + "row": "close", + "strength": "6", + "ability": "bond", + "filename": "craite_warrior_3", + "count": "1", + "target": "sk_craite_warrior", + "quote": "I'll bring the an Craites such glory, bards'll go hoarse singin' me praises!" + }, + "sk_donar": { + "name": "Donar an Hindar", + "deck": "skellige", + "row": "close", + "strength": "4", + "ability": "", + "filename": "donar", + "count": "1", + "quote": "I've gathered all the jarls together. Now make your case." + }, + "sk_draig": { + "name": "Draig Bon-Dhu", + "deck": "skellige", + "row": "siege", + "strength": "2", + "ability": "horn", + "filename": "draig", + "count": "1", + "quote": "Hear ye now the tale of the heroic deeds of Clan an Craite." + }, + "sk_ermion": { + "name": "Ermion", + "deck": "skellige", + "row": "ranged", + "strength": "8", + "ability": "hero mardroeme", + "filename": "ermion", + "count": "1", + "quote": "Only the ignorant dismiss the importance of myths." + }, + "sk_hemdall": { + "name": "Hemdall", + "deck": "skellige", + "row": "close", + "strength": "11", + "ability": "hero", + "filename": "hemdall", + "count": "1", + "quote": "When the time of the White Frost comes, Hemdall will sound the call for battle." + }, + "sk_hjalmar": { + "name": "Hjalmar", + "deck": "skellige", + "row": "ranged", + "strength": "10", + "ability": "hero", + "filename": "hjalmar", + "count": "1", + "quote": "Instead of mournin' the fallen, let's drink to their memory!" + }, + "sk_holger": { + "name": "Holger Blackhand", + "deck": "skellige", + "row": "siege", + "strength": "4", + "ability": "", + "filename": "holger", + "count": "1", + "quote": "Now let's drink to Emperor of Nilfgaard - may his prick forever stay limp!" + }, + "sk_kambi": { + "name": "Kambi", + "deck": "skellige", + "row": "close", + "strength": "0", + "ability": "avenger", + "filename": "kambi", + "count": "1", + "target": "sk_hemdall", + "quote": "When the time comes, the cockerel Kambi shall crow and awaken Hemdall." + }, + "sk_light_longship": { + "name": "Light Longship", + "id": 1, + "deck": "skellige", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "light_longship", + "count": "3", + "target": "sk_light_longship", + "quote": "Escape them? In the waters of Skellige? Good luck." + }, + "sk_madman_lugos": { + "name": "Madman Lugos", + "deck": "skellige", + "row": "close", + "strength": "6", + "ability": "", + "filename": "madman_lugos", + "count": "1", + "quote": "WAAAAAAAGH!!!!" + }, + "spe_mardroeme": { + "name": "Mardroeme", + "deck": "special skellige", + "row": "", + "strength": "", + "ability": "mardroeme", + "filename": "mardroeme", + "count": "3", + "quote": "Eat enough of them, and the world will never be the same..." + }, + "sk_olaf": { + "name": "Olaf", + "deck": "skellige", + "row": "agile", + "strength": "12", + "ability": "morale", + "filename": "olaf", + "count": "1", + "quote": "Many've tried to defeat Olaf. But wont' hear about it from them - they're dead." + }, + "spe_storm": { + "name": "Skellige Storm", + "deck": "weather realms skellige", + "row": "", + "strength": "", + "ability": "rain fog", + "filename": "storm", + "count": "3", + "quote": "This ain't no normal storm. This here's the wrath of the gods." + }, + "sk_svanrige": { + "name": "Svanrige", + "deck": "skellige", + "row": "close", + "strength": "4", + "ability": "", + "filename": "svanrige", + "count": "1", + "quote": "The emperor also thought him an accidental king. At first." + }, + "sk_vildkaarl": { + "name": "Transformed Vildkaarl", + "deck": "skellige", + "row": "close", + "strength": "14", + "ability": "morale", + "filename": "vildkaarl", + "count": "0", + "quote": "Saw them fight once in my life... and once was enough." + }, + "sk_young_vildkaarl": { + "name": "Transformed Young Vildkaarl", + "id": 1, + "deck": "skellige", + "row": "ranged", + "strength": "8", + "ability": "bond", + "filename": "young_vildkaarl", + "count": "0", + "target": "sk_young_vildkaarl", + "quote": "Rooaaar!" + }, + "sk_udalryk": { + "name": "Udalryk", + "deck": "skellige", + "row": "close", + "strength": "4", + "ability": "", + "filename": "udalryk", + "count": "1", + "quote": "Haaaargh! After me, if ye've the bollocks!" + }, + "sk_war_longship_1": { + "name": "War Longship", + "id": 1, + "deck": "skellige", + "row": "siege", + "strength": "6", + "ability": "bond", + "filename": "war_longship_1", + "count": "1", + "target": "sk_war_longship", + "quote": "They say Hemdall's heart swells whenever the longships sail out on a raid." + }, + "sk_war_longship_2": { + "name": "War Longship", + "id": 2, + "deck": "skellige", + "row": "siege", + "strength": "6", + "ability": "bond", + "filename": "war_longship_2", + "count": "1", + "target": "sk_war_longship", + "quote": "They say Hemdall's heart swells whenever the longships sail out on a raid." + }, + "sk_young_berserker": { + "name": "Young Berserker", + "deck": "skellige", + "row": "ranged", + "strength": "2", + "ability": "berserker", + "filename": "young_berserker", + "count": "3", + "target": "sk_young_vildkaarl", + "quote": "Want some?" + }, + "sk_crach_an_craite": { + "name": "Crach an Craite", + "deck": "skellige", + "row": "leader", + "strength": "", + "ability": "crach_an_craite", + "filename": "crach_an_craite", + "count": "0", + "quote": "A king's gotta be wise. A king's gotta command respect. A king's gotta have stones." + }, + "sk_king_bran": { + "name": "King Bran", + "deck": "skellige", + "row": "leader", + "strength": "", + "ability": "king_bran", + "filename": "king_bran", + "count": "0", + "quote": "No one can replace Bran. Though they're sure to try." + }, + "sc_schirru": { + "name": "Schirru", + "deck": "scoiatael", + "row": "siege", + "strength": "8", + "ability": "scorch_c", + "filename": "schirru", + "count": "1", + "quote": "Time to look death in the face." + } +}; + +/* + * Custom new cards + */ + + +var ext_nr_cards = { + "nr_foltest_pride": { + "name": "Foltest's Pride", + "deck": "realms", + "row": "siege", + "strength": "9", + "ability": "", + "filename": "foltest_pride", + "count": "1", + "quote": "As King Foltest likes to say, it's not size that count, but whether it gets the job done." + }, + "nr_temerian_soldier_1": { + "name": "Temerian Foot Soldier", + "id": 1, + "deck": "realms", + "row": "close", + "strength": "2", + "ability": "bond", + "filename": "temerian_soldier_1", + "count": "1", + "target": "nr_temerian_soldier", + "quote": "Temeria! Gods shed all grace on thee! And smite thy foes with horrid woes, for all eternity!" + }, + "nr_temerian_soldier_2": { + "name": "Temerian Foot Soldier", + "id": 2, + "deck": "realms", + "row": "close", + "strength": "2", + "ability": "bond", + "filename": "temerian_soldier_2", + "count": "1", + "target": "nr_temerian_soldier", + "quote": "Temeria! Gods shed all grace on thee! And smite thy foes with horrid woes, for all eternity!" + }, + "nr_temerian_soldier_3": { + "name": "Temerian Foot Soldier", + "id": 3, + "deck": "realms", + "row": "close", + "strength": "2", + "ability": "bond", + "filename": "temerian_soldier_3", + "count": "1", + "target": "nr_temerian_soldier", + "quote": "Temeria! Gods shed all grace on thee! And smite thy foes with horrid woes, for all eternity!" + }, + "nr_reaver_scout": { + "name": "Reaver Scout", + "deck": "realms", + "row": "ranged", + "strength": "6", + "ability": "spy", + "filename": "reaver_scout", + "count": "1", + "quote": "Haven't had much luck with monsters of late, so we enlisted." + }, + "nr_temerian_drummer": { + "name": "Temerian Drummer", + "deck": "realms", + "row": "siege", + "strength": "1", + "ability": "horn", + "filename": "temerian_drummer", + "count": "1", + "quote": "Not the career he had in mind when he told mummy he wanted to be a musician." + }, + "nr_stripes_scout": { + "name": "Blue Stripes Scout", + "deck": "realms", + "row": "close", + "strength": "5", + "ability": "spy", + "filename": "stripes_scout", + "count": "1", + "quote": "Blue Stripes and Scoia'Tael are similar in one regard - hatred fuels both." + }, + "nr_tridam_infantry": { + "name": "Tridam Infantry", + "deck": "realms", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "tridam_infantry", + "count": "1", + "quote": "Soldiers loyal to the old baron of Tridam left the city with Falibor..." + }, + "nr_vandergrift": { + "name": "Vandergrift", + "deck": "realms", + "row": "ranged", + "strength": "9", + "ability": "hero", + "filename": "vandergrift", + "count": "1", + "quote": "What has that witch done?!" + }, + "nr_kaedweni_siege_support_1": { + "name": "Kaedweni Siege Support", + "deck": "realms", + "row": "siege", + "strength": "2", + "ability": "morale", + "filename": "kaedweni_siege_support_1", + "count": "1", + "quote": "I never miss twice." + }, + "nr_kaedweni_siege_support_2": { + "name": "Kaedweni Siege Support", + "deck": "realms", + "row": "siege", + "strength": "2", + "ability": "morale", + "filename": "kaedweni_siege_support_2", + "count": "1", + "quote": "I never miss twice." + }, + "nr_henselt": { + "name": "Henselt", + "deck": "realms", + "row": "siege", + "strength": "10", + "ability": "hero", + "filename": "henselt", + "count": "1", + "quote": "King Henselt did not look like a thief, but, with all due respect, that's really what he was." + }, + "nr_kaedweni_reinforcement": { + "name": "Kaedweni Reinforcement", + "deck": "realms", + "row": "ranged", + "strength": "3", + "ability": "medic", + "filename": "kaedweni_reinforcement", + "count": "1", + "quote": "Sound the retreat! Regroup! And wait for reinforcements!" + }, + "nr_reinforced_ballista_1": { + "name": "Reinforced Ballista", + "id": 1, + "deck": "realms", + "row": "siege", + "strength": "4", + "ability": "bond", + "filename": "reinforced_ballista_1", + "count": "1", + "target": "nr_reinforced_ballista", + "quote": "Never manages to hit the same place twice, which might constitute a real problem." + }, + "nr_reinforced_ballista_2": { + "name": "Reinforced Ballista", + "id": 2, + "deck": "realms", + "row": "siege", + "strength": "4", + "ability": "bond", + "filename": "reinforced_ballista_2", + "count": "1", + "target": "nr_reinforced_ballista", + "quote": "Never manages to hit the same place twice, which might constitute a real problem." + }, + "nr_reinforced_trebuchet_1": { + "name": "Reinforced Trebuchet", + "id": 1, + "deck": "realms", + "row": "siege", + "strength": "5", + "ability": "bond", + "filename": "reinforced_trebuchet_1", + "count": "1", + "target": "nr_reinforced_trebuchet", + "quote": "Feel that? The earth trembles each time Big Bertha loose a stone." + }, + "nr_reinforced_trebuchet_2": { + "name": "Reinforced Trebuchet", + "id": 2, + "deck": "realms", + "row": "siege", + "strength": "5", + "ability": "bond", + "filename": "reinforced_trebuchet_2", + "count": "1", + "target": "nr_reinforced_trebuchet", + "quote": "Feel that? The earth trembles each time Big Bertha loose a stone." + }, + "nr_ban_ard_tutor": { + "name": "Ban Ard Tutor", + "deck": "realms", + "row": "ranged", + "strength": "10", + "ability": "hero", + "filename": "ban_ard_tutor", + "count": "1", + "quote": "Ban Ard deserved a mention, for it is famous for the school of young adepts of the magical arts." + }, + "nr_demavend": { + "name": "Demavend", + "deck": "realms", + "row": "siege", + "strength": "10", + "ability": "hero", + "filename": "demavend", + "count": "1", + "quote": "War's crux lies in winning, not in being persistent." + }, + "nr_kaedweni_knight": { + "name": "Kaedweni Knight", + "deck": "realms", + "row": "close", + "strength": "7", + "ability": "", + "filename": "kaedweni_knight", + "count": "1", + "quote": "Not every man in the Kaedweni army supports his king's politics..." + }, + "nr_dun_banner_heavy_cavalry_1": { + "name": "Dun Banner Heavy Cavalry", + "deck": "realms", + "row": "ranged", + "strength": "7", + "ability": "", + "filename": "dun_banner_heavy_cavalry_1", + "count": "1", + "quote": "Always wondered... how the blazes do those lads handle nature's call...?" + }, + "nr_dun_banner_heavy_cavalry_2": { + "name": "Dun Banner Heavy Cavalry", + "deck": "realms", + "row": "ranged", + "strength": "7", + "ability": "", + "filename": "dun_banner_heavy_cavalry_2", + "count": "1", + "quote": "Always wondered... how the blazes do those lads handle nature's call...?" + }, + "nr_odrin": { + "name": "Odrin", + "deck": "realms", + "row": "agile", + "strength": "3", + "ability": "morale", + "filename": "odrin", + "count": "1", + "quote": "Drinkin' without Odrin is like rowin' without a paddle." + }, + "nr_seltkirk": { + "name": "Seltkirk of Gulet", + "deck": "realms", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "seltkirk", + "count": "1", + "quote": "Seltkirk of Gulet was Demavend champion, known as the invincible white knight." + }, + "nr_kaedweni_sergeant": { + "name": "Kaedweni Sergeant", + "deck": "realms", + "row": "siege", + "strength": "5", + "ability": "morale", + "filename": "kaedweni_sergeant", + "count": "1", + "quote": "Forward, you sorry sods! Or you'll see the Nilfgaardians are the least of your worries!" + }, + "nr_queen_calanthe": { + "name": "Queen Calanthe: Lioness of Cintra", + "deck": "realms", + "row": "leader", + "strength": "", + "ability": "queen_calanthe", + "filename": "queen_calanthe", + "count": "1", + "quote": "They call her the 'Lioness of Cintra'. And not without good reason." + }, + "nr_viraxas": { + "name": "Viraxas", + "deck": "realms", + "row": "siege", + "strength": "9", + "ability": "hero", + "filename": "viraxas", + "count": "1", + "quote": "Revenge is a dish that tastes best when served for two." + }, + "nr_kerack_fleet_marine_1": { + "name": "Kerack Fleet: Marine", + "id": 1, + "deck": "realms", + "row": "ranged", + "strength": "3", + "ability": "muster", + "filename": "kerack_fleet_marine_1", + "count": "1", + "target": "nr_kerack_fleet", + "quote": "I spy with my little eye something that is... green. Oh, shite! That's a dryad!" + }, + "nr_kerack_fleet_frigate": { + "name": "Kerack Fleet: Frigate", + "id": 2, + "deck": "realms", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "kerack_fleet_frigate", + "count": "1", + "target": "nr_kerack_fleet", + "quote": "'I should buy a boat' said a Kerackian cat once. Or so claims the drunken ballad." + }, + "nr_kerack_fleet_marine_2": { + "name": "Kerack Fleet: Marine", + "id": 3, + "deck": "realms", + "row": "ranged", + "strength": "3", + "ability": "muster", + "filename": "kerack_fleet_marine_2", + "count": "1", + "target": "nr_kerack_fleet", + "quote": "I spy with my little eye something that is... green. Oh, shite! That's a dryad!" + }, + "nr_vissegerd": { + "name": "Vissegerd", + "deck": "realms", + "row": "close", + "strength": "7", + "ability": "", + "filename": "vissegerd", + "count": "1", + "quote": "I will raise Cintra from the ashes no matter how great the cost." + }, + "nr_cintrian_royal_guard": { + "name": "Cintrian Royal Guard", + "deck": "realms", + "row": "close", + "strength": "5", + "ability": "cintra_slaughter", + "filename": "cintrian_royal_guard", + "count": "2", + "quote": "I will raise Cintra from the ashes no matter how great the cost." + }, + "spe_slaughther_cintra_1": { + "name": "Slaughter of Cintra", + "deck": "special realms", + "row": "", + "strength": "", + "ability": "cintra_slaughter", + "filename": "slaughter_cintra_1", + "count": "1", + "quote": "The battle of Cintra, which Nordlings call the Slaughter of Cintra because of the very cruel actions of the Nilfgaardian army." + }, + "spe_slaughther_cintra_2": { + "name": "Slaughter of Cintra", + "deck": "special realms", + "row": "", + "strength": "", + "ability": "cintra_slaughter", + "filename": "slaughter_cintra_2", + "count": "1", + "quote": "The battle of Cintra, which Nordlings call the Slaughter of Cintra because of the very cruel actions of the Nilfgaardian army." + }, + "spe_slaughther_cintra_3": { + "name": "Slaughter of Cintra", + "deck": "special realms", + "row": "", + "strength": "", + "ability": "cintra_slaughter", + "filename": "slaughter_cintra_3", + "count": "1", + "quote": "The battle of Cintra, which Nordlings call the Slaughter of Cintra because of the very cruel actions of the Nilfgaardian army." + }, + "nr_eist_tuirseach": { + "name": "Eist Tuirseach", + "id": 4, + "deck": "realms", + "row": "close", + "strength": "10", + "ability": "hero muster", + "filename": "eist_tuirseach", + "count": "1", + "target": "skellige_fleet", + "quote": "Skellige and Cintra shall stand ever together." + }, + "nr_skellige_fleet_1": { + "name": "Skellige Raiders Fleet", + "id": 1, + "deck": "realms", + "row": "ranged", + "strength": "3", + "ability": "morale", + "filename": "skellige_fleet_1", + "count": "1", + "target": "skellige_fleet", + "quote": "The islanders know that there is fertile soil on the other side of the sea..." + }, + "nr_skellige_fleet_2": { + "name": "Skellige Raiders Fleet", + "id": 2, + "deck": "realms", + "row": "ranged", + "strength": "3", + "ability": "morale", + "filename": "skellige_fleet_2", + "count": "1", + "target": "skellige_fleet", + "quote": "The islanders know that there is fertile soil on the other side of the sea..." + }, + "nr_skellige_fleet_3": { + "name": "Skellige Raiders Fleet", + "id": 3, + "deck": "realms", + "row": "ranged", + "strength": "3", + "ability": "morale", + "filename": "skellige_fleet_3", + "count": "1", + "target": "skellige_fleet", + "quote": "The islanders know that there is fertile soil on the other side of the sea..." + }, + "nr_cintrian_knight": { + "name": "Cintrian Knight", + "deck": "realms", + "row": "close", + "strength": "7", + "ability": "cintra_slaughter", + "filename": "cintrian_knight", + "count": "2", + "quote": "For whom does the bell toll?" + }, + "nr_roegner": { + "name": "Roegner de Salm", + "deck": "realms", + "row": "close", + "strength": "6", + "ability": "", + "filename": "roegner", + "count": "1", + "quote": "Roegner de Salm was the son of a prince of Salm in Ebbing." + }, + "nr_pavetta": { + "name": "Pavetta", + "deck": "realms", + "row": "ranged", + "strength": "10", + "ability": "hero", + "filename": "pavetta", + "count": "1", + "quote": "They said the queen was prone to outbursts but I did not expect that..." + }, + "nr_kistrin_verden": { + "name": "Kistrin of Verden", + "deck": "realms", + "row": "ranged", + "strength": "6", + "ability": "", + "filename": "kistrin_verden", + "count": "1", + "quote": "Oh dammit. Kistrin? Prince Kistrin? The son of King Ervyll of Verden?" + }, + "nr_sha": { + "name": "Sha", + "deck": "realms", + "row": "siege", + "strength": "3", + "ability": "avenger", + "filename": "sha", + "count": "1", + "target": "nr_kraken", + "quote": "A noblewoman from beyond the seas." + }, + "nr_kraken": { + "name": "Kraken", + "deck": "realms", + "row": "ranged", + "strength": "11", + "ability": "hero scorch", + "filename": "kraken", + "count": "1", + "quote": "'A kra-kraken?' 'Yes, a kraken' the witcher repeated." + }, + "nr_egmund": { + "name": "Egmund", + "deck": "realms", + "row": "close", + "strength": "7", + "ability": "scorch_c", + "filename": "egmund", + "count": "1", + "quote": "Since father has never appreciated nor trusted Egmund, it was but a simple decision to betray him." + }, + "nr_eylembert_tigg": { + "name": "Eylembert of Tigg", + "deck": "realms", + "row": "close", + "strength": "1", + "ability": "horn", + "filename": "eylembert_tigg", + "count": "1", + "quote": "'Coodcoodak!' murmured Calanthe. 'This will be fun.'" + }, + "nr_young_ciri": { + "name": "Young Ciri", + "deck": "realms", + "row": "close", + "strength": "5", + "ability": "avenger", + "filename": "young_ciri", + "count": "1", + "target": "ntr_ciri", + "quote": "I'm not afraid at all!" + }, + "nr_cintrian_peasants": { + "name": "Cintrian Peasants", + "deck": "realms", + "row": "close", + "strength": "3", + "ability": "cintra_slaughter", + "filename": "cintrian_peasants", + "count": "2", + "quote": "There's a time to reap, at time to sow ...and a time to die." + }, + "nr_windhalm": { + "name": "Windhalm of Attre", + "deck": "realms", + "row": "close", + "strength": "6", + "ability": "", + "filename": "windhalm", + "count": "1", + "quote": "Off with his head! But slowly, drag it out, put on a show for all to see." + }, + "nr_queen_meve": { + "name": "Queen Meve", + "deck": "realms", + "row": "close", + "strength": "10", + "ability": "hero morale", + "filename": "queen_meve", + "count": "1", + "quote": "It's war you want? Then war you shall have! For Lyria and Rivia! For the North!" + }, + "nr_prince_anseis": { + "name": "Prince Anseis", + "deck": "realms", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "prince_anseis", + "count": "1", + "quote": "Come forth, coward, and your very own doom confront!" + }, + "nr_nastrog_levecque": { + "name": "Nastrog Division: Levecque", + "id": 4, + "deck": "realms", + "row": "close", + "strength": "4", + "ability": "muster", + "filename": "nastrog_levecque", + "count": "1", + "target": "nastrog_division", + "quote": "Oh, what a clever girl, you are. Too clever." + }, + "nr_nastrog_junghans": { + "name": "Nastrog Division: Junghans", + "id": 1, + "deck": "realms", + "row": "close", + "strength": "3", + "ability": "muster", + "filename": "nastrog_junghans", + "count": "1", + "target": "nastrog_division", + "quote": "Junghans, a forester, can read spoors like a book." + }, + "nr_nastrog_brick": { + "name": "Nastrog Division: Brick", + "id": 2, + "deck": "realms", + "row": "close", + "strength": "3", + "ability": "muster", + "filename": "nastrog_brick", + "count": "1", + "target": "nastrog_division", + "quote": "Blood for blood, I say!" + }, + "nr_nastrog_beady_eyes": { + "name": "Nastrog Division: Beady-eyes", + "id": 3, + "deck": "realms", + "row": "close", + "strength": "3", + "ability": "muster", + "filename": "nastrog_beady_eyes", + "count": "1", + "target": "nastrog_division", + "quote": "There aren't any witnesses. But we know what happened." + }, + "nr_letande_lavet": { + "name": "Letande Lavet", + "deck": "realms", + "row": "close", + "strength": "7", + "ability": "scorch", + "filename": "letande_lavet", + "count": "1", + "quote": "Killing enemies is not the same as slaughtering your countrymen. The Butcher of Cidaris likes the latter. And he's good at it." + }, + "nr_kerack_city_guard": { + "name": "Kerack City Guard", + "id": 1, + "deck": "realms", + "row": "close", + "strength": "6", + "ability": "bond", + "filename": "kerack_city_guard", + "count": "2", + "target": "kerack_city_guard", + "quote": "Geralt thought there were no ugly women, but in the guardhouse of Kerack he felt compelled to revise this view." + }, + "nr_rainfarn": { + "name": "Rainfarn of Attre", + "deck": "realms", + "row": "close", + "strength": "5", + "ability": "", + "filename": "rainfarn", + "count": "1", + "quote": "When Cintra fell, Attre followed, leaving the defenders a choice: accept the Nilfgaardian leash or die." + }, + "nr_falibor": { + "name": "Falibor", + "deck": "realms", + "row": "close", + "strength": "8", + "ability": "", + "filename": "falibor", + "count": "1", + "quote": "I shan't fail... I cannot fail. For the baron!" + }, + "nr_black_rayla": { + "name": "Black Rayla", + "deck": "realms", + "row": "close", + "strength": "7", + "ability": "", + "filename": "black_rayla", + "count": "1", + "quote": "Enough chit-chat, draw your weapon. You'll never take me alive." + }, + "nr_lyrian_landsknecht": { + "name": "Lyrian Landsknecht", + "deck": "realms", + "row": "close", + "strength": "4", + "ability": "", + "filename": "lyrian_landsknecht", + "count": "1", + "quote": "Back to the dust whence you came!" + }, + "nr_lyrian_heavy_cavalry": { + "name": "Lyrian Heavy Cavalry", + "deck": "realms", + "row": "close", + "strength": "6", + "ability": "", + "filename": "lyrian_heavy_cavalry", + "count": "1", + "quote": "Gods save the queen!" + }, + "nr_poor_infantry_4": { + "name": "Poor Fucking Infantry", + "id": 4, + "deck": "realms", + "row": "close", + "strength": "1", + "ability": "bond", + "filename": "poor_infantry_4", + "count": "1", + "target": "nr_poor_infantry", + "quote": "I's a war veteran! ... spare me a crown?" + }, + "nr_poor_infantry_5": { + "name": "Poor Fucking Infantry", + "id": 5, + "deck": "realms", + "row": "close", + "strength": "1", + "ability": "bond", + "filename": "poor_infantry_5", + "count": "1", + "target": "nr_poor_infantry", + "quote": "I's a war veteran! ... spare me a crown?" + }, + "nr_poor_infantry_6": { + "name": "Poor Fucking Infantry", + "id": 6, + "deck": "realms", + "row": "close", + "strength": "1", + "ability": "bond", + "filename": "poor_infantry_6", + "count": "1", + "target": "nr_poor_infantry", + "quote": "I's a war veteran! ... spare me a crown?" + }, + "nr_dun_banner_light_cavalry": { + "name": "Dun Banner Light Cavalry", + "deck": "realms", + "row": "close", + "strength": "4", + "ability": "", + "filename": "dun_banner_light_cavalry", + "count": "1", + "quote": "The true owners of those cloaks and beaver-skin caps might be elsewhere." + }, + "nr_cintrian_envoy": { + "name": "Cintrian Envoy", + "deck": "realms", + "row": "ranged", + "strength": "10", + "ability": "spy", + "filename": "cintrian_envoy", + "count": "1", + "quote": "She thought service in the diplomatic corps would mean a quiet life behind a desk. She and her blistered feet were sorely mistaken." + }, + "nr_freixenet": { + "name": "Freixenet", + "deck": "realms", + "row": "ranged", + "strength": "6", + "ability": "", + "filename": "freixenet", + "count": "1", + "quote": "He was only meant to be a breeding stud to her. But int he end, they fell in love regardless." + }, + "nr_dorregaray": { + "name": "Dorregaray of Vole", + "deck": "realms", + "row": "ranged", + "strength": "6", + "ability": "spy", + "filename": "dorregaray", + "count": "1", + "quote": "Like the witchers, Dorregaray is a monster aficionado, though he's developed his own classification system." + }, + "nr_valdo_marx": { + "name": "Valdo Marx", + "deck": "realms", + "row": "ranged", + "strength": "2", + "ability": "horn", + "filename": "valdo_marx", + "count": "1", + "quote": "'Firstly, may Valdo Marx, the troubadour of Cidaris, die of apoplexy as soon as possible.' - Dandellion" + }, + "nr_mousesack": { + "name": "Mousesack", + "deck": "realms", + "row": "ranged", + "strength": "5", + "ability": "medic", + "filename": "mousesack", + "count": "1", + "quote": "Only the ignorant dismiss the importance of myths." + }, + "nr_isbel_hagge": { + "name": "Isbel of Hagge", + "deck": "realms", + "row": "ranged", + "strength": "5", + "ability": "", + "filename": "isbel_hagge", + "count": "1", + "quote": "So much anger and suggering, for what?" + }, + "nr_lyrian_arbalest": { + "name": "Lyrian Arbalest", + "deck": "realms", + "row": "ranged", + "strength": "6", + "ability": "", + "filename": "lyrian_arbalest", + "count": "1", + "quote": "Arbalist at your command. Armour won't save them! One bolt's all I need..." + }, + "nr_northern_wind": { + "name": "Northern Wind", + "deck": "realms", + "row": "ranged", + "strength": "3", + "ability": "scorch", + "filename": "northern_wind", + "count": "1", + "quote": "An unnatural fog enveloped Demavend's ship and his crew turned into icy sculptures." + }, + "nr_aretuza_adept": { + "name": "Aretuza Adept", + "deck": "realms", + "row": "ranged", + "strength": "4", + "ability": "medic", + "filename": "aretuza_adept", + "count": "1", + "quote": "The adepts' every whim is catered to - the live like princesses at Aretuza." + }, + "nr_blue_stripes_skirmisher_1": { + "name": "Blue Stripes Skirmisher", + "id": 1, + "deck": "realms", + "row": "ranged", + "strength": "4", + "ability": "bond", + "filename": "blue_stripes_skirmisher_1", + "count": "1", + "target": "blue_stripes_skirmisher", + "quote": "What do you mean 'we're surrounded'? Bah! I feel sorry for those dogs." + }, + "nr_blue_stripes_skirmisher_2": { + "name": "Blue Stripes Skirmisher", + "id": 2, + "deck": "realms", + "row": "ranged", + "strength": "4", + "ability": "bond", + "filename": "blue_stripes_skirmisher_2", + "count": "1", + "target": "blue_stripes_skirmisher", + "quote": "What do you mean 'we're surrounded'? Bah! I feel sorry for those dogs." + }, + "nr_blue_stripes_skirmisher_3": { + "name": "Blue Stripes Skirmisher", + "id": 3, + "deck": "realms", + "row": "ranged", + "strength": "4", + "ability": "bond", + "filename": "blue_stripes_skirmisher_3", + "count": "1", + "target": "blue_stripes_skirmisher", + "quote": "What do you mean 'we're surrounded'? Bah! I feel sorry for those dogs." + }, + "nr_ethain_cidaris": { + "name": "Ethain of Cidaris", + "deck": "realms", + "row": "siege", + "strength": "10", + "ability": "hero", + "filename": "ethain_cidaris", + "count": "1", + "quote": "Balads aren't just lively music and rhymes, but a way of spreading news, they are chronicle of humankind." + }, + "nr_henry_attre": { + "name": "Henry var Attre", + "deck": "realms", + "row": "siege", + "strength": "8", + "ability": "spy", + "filename": "henry_attre", + "count": "1", + "quote": "Edna and Rosa, I must attend to their needs, their well being." + }, + "nr_ildiko_breckl": { + "name": "Ildiko Breckl", + "deck": "realms", + "row": "siege", + "strength": "4", + "ability": "morale", + "filename": "ildiko_breckl", + "count": "1", + "quote": "The necklace was Ildiko's gift to king Belohun in honor of their impending marriage. By choking the old fool, it solved that problem." + }, + "nr_king_belohun": { + "name": "King Belohun", + "deck": "realms", + "row": "siege", + "strength": "5", + "ability": "", + "filename": "king_belohun", + "count": "1", + "quote": "The king, quite rightly, didn't trust anyone. He also didn't believe anobody capable of outsmarting him. This proved a fatal assumption." + }, + "nr_urcheon": { + "name": "Urcheon of Erlenwald", + "deck": "realms", + "row": "siege", + "strength": "6", + "ability": "spy", + "filename": "urcheon", + "count": "1", + "quote": "This is how I look, which you well knew, Calanthe." + }, + "nr_rivian_onager": { + "name": "Rivian Onager", + "deck": "realms", + "row": "siege", + "strength": "6", + "ability": "", + "filename": "rivian_onager", + "count": "1", + "quote": "For Riviaaa!" + }, + "nr_reinforced_tower": { + "name": "Reinforced Tower", + "deck": "realms", + "row": "siege", + "strength": "7", + "ability": "", + "filename": "reinforced_tower", + "count": "1", + "quote": "The latest rage in assaults on walled cities." + }, + "nr_battering_ram": { + "name": "Battering Ram", + "deck": "realms", + "row": "siege", + "strength": "6", + "ability": "", + "filename": "battering_ram", + "count": "1", + "quote": "The hulking siege engine rolled to the front, within few bashes the gates crashed open." + }, + "nr_fake_ciri": { + "name": "Fake Ciri: Empress of Nilfgaard", + "deck": "realms", + "row": "leader", + "strength": "", + "ability": "fake_ciri", + "filename": "fake_ciri", + "count": "1", + "quote": "It is a dull name. A name just right for somebody who's a nobody. As long as a am Cirilla Fiona I mean something." + }, + "nr_radovid_stern": { + "name": "Radovid V: the Stern", + "deck": "realms", + "row": "leader", + "strength": "", + "ability": "radovid_stern", + "filename": "radovid_stern", + "count": "1", + "quote": "They say chess teaches one ot think strategically. What a load of rubbish!" + }, + "nr_radovid_ruthless": { + "name": "Radovid V: the Ruthless", + "deck": "realms", + "row": "leader", + "strength": "", + "ability": "radovid_ruthless", + "filename": "radovid_ruthless", + "count": "1", + "quote": "A king should be merciless towards his enemies and generous to his friends." + }, + "nr_redanian_elite": { + "name": "Redanian Elite", + "deck": "realms", + "row": "close", + "strength": "6", + "ability": "", + "filename": "redanian_elite", + "count": "1", + "quote": "I'll die for Redania, I'll kill for Redania… I'll even eat worms for Redania!" + }, + "nr_donimir_troy": { + "name": "Donimir of Troy", + "deck": "realms", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "donimir_troy", + "count": "1", + "quote": "I fought twice at Sodden and lived. I think you can surmise I'm not so bad at this sword thing." + }, + "nr_joachim_gratz": { + "name": "Joachim von Gratz", + "deck": "realms", + "row": "siege", + "strength": "2", + "ability": "medic", + "filename": "joachim_gratz", + "count": "1", + "quote": "Chief surgeon at Vilmerius Hospital was a cool-headed doctor." + }, + "nr_hedwig_malleore": { + "name": "Hedwig of Malleore", + "deck": "realms", + "row": "siege", + "strength": "5", + "ability": "hero medic", + "filename": "hedwig_malleore", + "count": "1", + "quote": "Queen of Redania, mother of Radovid, figure-head to the Regency Council." + }, + "nr_ewald_borsodi": { + "name": "Ewald Borsodi", + "deck": "realms", + "row": "ranged", + "strength": "7", + "ability": "", + "filename": "ewald_borsodi", + "count": "1", + "quote": "I've crafted this plan for over a year, but now the time's come for action. Can I count on your help?" + }, + "nr_horst_borsodi": { + "name": "Horst Borsodi", + "deck": "realms", + "row": "close", + "strength": "4", + "ability": "", + "filename": "horst_borsodi", + "count": "1", + "quote": "My auction house is, above all, a gathering place for the elite of the elite." + }, + "nr_flying_redanian": { + "name": "Flying Redanian", + "deck": "realms", + "row": "siege", + "strength": "10", + "ability": "", + "filename": "flying_redanian", + "count": "1", + "quote": "Legend tells of a Redanian crew from generations past..." + }, + "nr_redanian_knight": { + "name": "Redanian Knight", + "deck": "realms", + "row": "close", + "strength": "9", + "ability": "", + "filename": "redanian_knight", + "count": "1", + "quote": "For glory! For Radovid!" + }, + "nr_shani": { + "name": "Shani", + "deck": "realms", + "row": "agile", + "strength": "2", + "ability": "medic", + "filename": "shani", + "count": "1", + "quote": "I'm a medic. I tend to know what I'm doing when I prescribe something." + }, + "nr_milo_vanderbeck": { + "name": "Milo Vanderbeck", + "deck": "realms", + "row": "siege", + "strength": "2", + "ability": "medic", + "filename": "milo_vanderbeck", + "count": "1", + "quote": "He's lying on my table. And to me, as I hum to myself, a duke's worth a jester." + }, + "nr_vizimir": { + "name": "Vizimir the Just", + "deck": "realms", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "vizimir", + "count": "1", + "quote": "Vizimir II, known as the Just, was the king of Redania and the son of Heribert." + }, + "nr_marching_orders": { + "name": "Marching Orders", + "deck": "realms", + "row": "agile", + "strength": "1", + "ability": "horn", + "filename": "marching_orders", + "count": "1", + "quote": "We are but pawns in a game played by old men, sent to fight and die on their senile whims..." + }, + "nr_eyck_denesle": { + "name": "Eyck of Denesle", + "deck": "realms", + "row": "close", + "strength": "11", + "ability": "hero", + "filename": "eyck_denesle", + "count": "1", + "quote": "The Good Book says the world is a garden which the gods once conferred upon man." + }, + "nr_radovid_royal_guards": { + "name": "Radovid Royal Guards", + "deck": "realms", + "row": "close", + "strength": "8", + "ability": "", + "filename": "radovid_royal_guards", + "count": "1", + "quote": "They'll do anything for their king. They know what he'll do to them if they refuse." + }, + "nr_redanian_archer": { + "name": "Redanian Archer", + "deck": "realms", + "row": "ranged", + "strength": "5", + "ability": "", + "filename": "redanian_archer", + "count": "1", + "quote": "The last thing you'll hear is the twang of the bowstring being let go." + }, + "nr_trollololo": { + "name": "Trollololo", + "deck": "realms", + "row": "siege", + "strength": "8", + "ability": "", + "filename": "trollololo", + "count": "1", + "quote": "Join me King Ravodid army. Order got – guard boatses." + }, + "nr_royal_decree": { + "name": "Royal Decree", + "deck": "realms", + "row": "siege", + "strength": "1", + "ability": "horn", + "filename": "royal_decree", + "count": "1", + "quote": "...do hereby decree the following..." + }, + "nr_voymir": { + "name": "Voymir", + "deck": "realms", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "voymir", + "count": "1", + "quote": "Quietly, on tiptoes, no noise, no fuss. Through the back alleys. In Loxia and the port keep your mouth shut! Go!" + }, + "nr_mage_infiltrator": { + "name": "Mage Infiltrator", + "deck": "realms", + "row": "ranged", + "strength": "8", + "ability": "spy", + "filename": "mage_infiltrator", + "count": "1", + "quote": "In her spare time, she likes playing practical jokes on others. Her favorite gag is switching footwraps and headwear." + }, + "nr_queen_adalia": { + "name": "Queen Adalia", + "deck": "realms", + "row": "ranged", + "strength": "7", + "ability": "hero medic", + "filename": "queen_adalia", + "count": "1", + "quote": "Queen Adalia of Cintra possessed the power to raise a drawbridge with a twitch of her brow." + } +}; + +var ext_ne_cards = { + "ne_vicovaro_medic": { + "name": "Vicovaro Medic", + "deck": "nilfgaard", + "row": "ranged", + "strength": "1", + "ability": "hero medic", + "filename": "vicovaro_medic", + "count": "1", + "quote": "Both war and plague always take men by surprise." + }, + "ne_alba_pikeman_1": { + "name": "Alba Pikeman", + "deck": "nilfgaard", + "row": "close", + "strength": "5", + "ability": "hero", + "filename": "alba_pikeman_1", + "count": "1", + "quote": "Pledge your allegiance to our Emperor Emhyr van Emreis... or die." + }, + "ne_alba_spearman": { + "name": "Alba Spearman", + "deck": "nilfgaard", + "row": "close", + "strength": "5", + "ability": "hero", + "filename": "alba_spearman", + "count": "1", + "quote": "Death and glory!" + }, + "ne_nausicaa_brigade": { + "name": "Nausicaa Brigade", + "deck": "nilfgaard", + "row": "close", + "strength": "6", + "ability": "", + "filename": "nausicaa_brigade", + "count": "1", + "quote": "They call us the Death's Heads. Care to find out why?" + }, + "ne_imperial_golem": { + "name": "Imperial Golem", + "deck": "nilfgaard", + "row": "close", + "strength": "8", + "ability": "hero", + "filename": "imperial_golem", + "count": "1", + "quote": "The most powerful of Nilfgaard's mages have mastered the oart of creating golems." + }, + "ne_daerlan_soldier": { + "name": "Daerlan Foot Soldier", + "deck": "nilfgaard", + "row": "close", + "strength": "6", + "ability": "", + "filename": "daerlan_soldier", + "count": "1", + "quote": "Learned a lot at Braibant Military Academy. How to scrub potatoes, for instance." + }, + "ne_hefty_helge": { + "name": "Hefty Helge", + "deck": "nilfgaard", + "row": "siege", + "strength": "7", + "ability": "", + "filename": "hefty_helge", + "count": "1", + "quote": "Not the best for taking cities, but great for razing them to the ground." + }, + "ne_slave_infantry_1": { + "name": "Slave Infantry", + "id": 1, + "deck": "nilfgaard", + "row": "close", + "strength": "5", + "ability": "bond", + "filename": "slave_infantry_1", + "count": "1", + "target": "ne_slave_infantry", + "quote": "A free man's got a choice. A slave's choices are made for him." + }, + "ne_slave_infantry_2": { + "name": "Slave Infantry", + "id": 2, + "deck": "nilfgaard", + "row": "close", + "strength": "5", + "ability": "bond", + "filename": "slave_infantry_2", + "count": "1", + "target": "ne_slave_infantry", + "quote": "A free man's got a choice. A slave's choices are made for him." + }, + "ne_magne_division": { + "name": "Magne Division", + "deck": "nilfgaard", + "row": "close", + "strength": "5", + "ability": "", + "filename": "magne_division", + "count": "1", + "quote": "A garrison in this blasted waste is like a chastity belt on a grave hag." + }, + "ne_emissary": { + "name": "Emissary", + "deck": "nilfgaard", + "row": "siege", + "strength": "10", + "ability": "spy", + "filename": "emissary", + "count": "1", + "quote": "But there's no justice in it! One does not kill the messenger!" + }, + "ne_standard_bearer": { + "name": "Standard Bearer", + "deck": "nilfgaard", + "row": "ranged", + "strength": "1", + "ability": "horn", + "filename": "standard_bearer", + "count": "1", + "quote": "You shall defend this standard if it costs you your lives! Gloir aen Ard Feainn!" + }, + "ne_deithwen_arbalest": { + "name": "Deithwen Arbalest", + "deck": "nilfgaard", + "row": "ranged", + "strength": "7", + "ability": "", + "filename": "deithwen_arbalest", + "count": "1", + "quote": "I aim for the knees. Always." + }, + "ne_guardian": { + "name": "The Guardian", + "deck": "nilfgaard", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "guardian", + "count": "1", + "quote": "Stone fists to stop intruders armed with swords. Ironclad logic to stop those armed with lies." + }, + "ne_nausicaa_standard_bearer": { + "name": "Nausicaa Standard Bearer", + "deck": "nilfgaard", + "row": "close", + "strength": "1", + "ability": "horn", + "filename": "nausicaa_standard_bearer", + "count": "1", + "quote": "The Emperor will teach the North discipline." + }, + "ne_knight": { + "name": "Nilfgaardian Knight", + "deck": "nilfgaard", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "knight", + "count": "1", + "quote": "Sons of noble houses, born in the City of the Golden Towers, form the elite backbone of the Imperial Army." + }, + "ne_alba_armored_cavalry": { + "name": "Alba Armored Cavalry", + "deck": "nilfgaard", + "row": "ranged", + "strength": "6", + "ability": "", + "filename": "alba_armored_cavalry", + "count": "1", + "quote": "The wedge of riders thundered into the phalanx with crushing momentum." + }, + "ne_peter_saar_gwynleve": { + "name": "Peter Saar Gwynleve", + "deck": "nilfgaard", + "row": "close", + "strength": "9", + "ability": "hero", + "filename": "peter_saar_gwynleve", + "count": "1", + "quote": "These are not the hands of an Excellency, but of a farmer. So we speak peasant to peasant." + }, + "ne_impera_brigade_5": { + "name": "Impera Brigade Guard", + "id": 5, + "deck": "nilfgaard", + "row": "close", + "strength": "3", + "ability": "bond", + "filename": "impera_brigade_5", + "count": "1", + "target": "ne_impera_brigade", + "quote": "The Impera Brigade never surrenders. Ever." + }, + "ne_jan_calveit": { + "name": "Jan Calveit", + "deck": "nilfgaard", + "row": "ranged", + "strength": "8", + "ability": "hero", + "filename": "jan_calveit", + "count": "1", + "quote": "To prepare for the future, it’s best to first know it." + }, + "ne_bribery": { + "name": "Bribery", + "deck": "nilfgaard", + "row": "agile", + "strength": "10", + "ability": "spy", + "filename": "bribery", + "count": "1", + "quote": "In truth, the Nilfgaardian floren rules the world." + }, + "ne_rot_tosser": { + "name": "Rot Tosser", + "deck": "nilfgaard", + "row": "siege", + "strength": "0", + "ability": "avenger", + "filename": "rot_tosser", + "count": "1", + "target": "ne_epidemic", + "quote": "Let historians debate whether spreading plague in a besieged city is ethical." + }, + "ne_epidemic": { + "name": "Epidemic", + "deck": "nilfgaard", + "row": "siege", + "strength": "7", + "ability": "", + "filename": "epidemic", + "count": "1", + "quote": "Epidemics respect no persons, no borders." + }, + "ne_joachim_de_wett": { + "name": "Joachim de Wett", + "deck": "nilfgaard", + "row": "siege", + "strength": "7", + "ability": "", + "filename": "joachim_de_wett", + "count": "1", + "quote": "To describe the manner in which Duke de Wett led the Verden Group as incompetent would be far too kind." + }, + "ne_ardal_aep_dahy": { + "name": "Ardal aep Dahy", + "deck": "nilfgaard", + "row": "ranged", + "strength": "9", + "ability": "hero", + "filename": "ardal_aep_dahy", + "count": "1", + "quote": "In my home, in the civilized world, a general commands his forces. He does not rush and thrash about like some rabid hound." + }, + "ne_cantarella": { + "name": "Cantarella", + "deck": "nilfgaard", + "row": "close", + "strength": "10", + "ability": "hero spy", + "filename": "cantarella", + "count": "1", + "quote": "Men require constant alluring. Mystique and refinement do the job quite well." + }, + "ne_treason": { + "name": "Treason", + "deck": "nilfgaard", + "row": "siege", + "strength": "3", + "ability": "scorch", + "filename": "treason", + "count": "1", + "quote": "In Nilfgaard, trustful people are considered an endangered species." + }, + "ne_usurper": { + "name": "Usurper", + "deck": "nilfgaard", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "usurper", + "count": "1", + "quote": "Why should something as trivial as birth decide who rules over us?" + }, + "ne_infiltrator": { + "name": "Infiltrator", + "deck": "nilfgaard", + "row": "close", + "strength": "8", + "ability": "hero", + "filename": "infiltrator", + "count": "1", + "quote": "You can run, but you'll never hide." + }, + "ne_venendal_elite": { + "name": "Venendal Elite", + "deck": "nilfgaard", + "row": "close", + "strength": "7", + "ability": "", + "filename": "venendal_elite", + "count": "1", + "quote": "Ebbing is famed for its top-notch mercenaries and light cavalry." + }, + "ne_master_disguise": { + "name": "Master of Disguise", + "deck": "nilfgaard", + "row": "ranged", + "strength": "7", + "ability": "hero spy", + "filename": "master_disguise", + "count": "1", + "quote": "O Great Sun which dost in Heavens fly, save us from the lice which do so stubbornly infest our bloomers. " + }, + "ne_fake_ciri": { + "name": "Fake Ciri", + "deck": "nilfgaard", + "row": "ranged", + "strength": "2", + "ability": "", + "filename": "fake_ciri", + "count": "1", + "quote": "A mock-princess, a mock-queen for Cintra. A mock-ruler for the mouth of the Yarra, future lifeblood of the empire." + }, + "ne_imperial_diviner": { + "name": "Imperial Diviner", + "deck": "nilfgaard", + "row": "ranged", + "strength": "6", + "ability": "", + "filename": "imperial_diviner", + "count": "1", + "quote": "All these signs can mean but one thing. The starts contend you shall be victorious today." + }, + "ne_xarthisius": { + "name": "Xarthisius", + "deck": "nilfgaard", + "row": "ranged", + "strength": "7", + "ability": "", + "filename": "xarthisius", + "count": "1", + "quote": "Astrology, hydromancy, haruspicy, ceromancy. Ovomancy, spodomancy, metroscopy, brontoscopy..." + }, + "ne_impera_enforcers": { + "name": "Impera Enforcers", + "deck": "nilfgaard", + "row": "ranged", + "strength": "5", + "ability": "", + "filename": "impera_enforcers", + "count": "1", + "quote": "Members of the emperor's fanatic body guard fight to the bitter end." + }, + "ne_mangonel": { + "name": "Mangonel", + "deck": "nilfgaard", + "row": "siege", + "strength": "6", + "ability": "", + "filename": "mangonel", + "count": "1", + "quote": "This model specializes in slinging corpses and ripe dung." + }, + "ne_combat_engineer": { + "name": "Combat Engineer", + "deck": "nilfgaard", + "row": "siege", + "strength": "3", + "ability": "morale", + "filename": "combat_engineer", + "count": "1", + "quote": "Look at war. Man gets better at killing with each one." + }, + "ne_affan_hillergrand": { + "name": "Affan Hillergrand", + "deck": "nilfgaard", + "row": "agile", + "strength": "3", + "ability": "horn", + "filename": "affan_hillergrand", + "count": "1", + "quote": "Jarre doesn't mention him in his books. Maybe he never heard of him. Maybe he heard too much." + }, + "ne_fergus_emreis": { + "name": "Fergus var Emreis", + "deck": "nilfgaard", + "row": "siege", + "strength": "8", + "ability": "hero avenger", + "filename": "fergus_emreis", + "count": "1", + "target": "ne_dunny", + "quote": "Usurper demanded that the fallen emperor grant legitimacy to the coup, and when Fergus refused, his 13-year-old son, Emhyr, was tortured." + }, + "ne_dunny": { + "name": "Dunny", + "deck": "nilfgaard", + "row": "siege", + "strength": "9", + "ability": "spy", + "filename": "dunny", + "count": "0", + "quote": "After the curse was lifted Duny claimed ignorance regarding its origin, or who was responsible. He was lying, of course." + }, + "ne_glynnis_loernach": { + "name": "Glynnis aep Loernach", + "deck": "nilfgaard", + "row": "close", + "strength": "6", + "ability": "morale", + "filename": "glynnis_loernach", + "count": "1", + "quote": "She loved every soldier like a son. She cried for each one." + }, + "ne_ard_feainn_crossbowman": { + "name": "Ard Feainn Crossbowman", + "deck": "nilfgaard", + "row": "ranged", + "strength": "5", + "ability": "scorch_c", + "filename": "ard_feainn_crossbowman", + "count": "1", + "quote": "Many thought that mounted crossbowmen wouldn't work. Until they saw them in action." + }, + "ne_ard_feainn_light_cavalry": { + "name": "Ard Feainn Light Cavalry", + "deck": "nilfgaard", + "row": "close", + "strength": "3", + "ability": "muster", + "filename": "ard_feainn_light_cavalry", + "count": "3", + "target": "ne_ard_feainn_light_cavalry", + "quote": "Light cavalry, heavy burden!" + }, + "ne_ard_feainn_tortoise": { + "name": "Ard Feainn Tortoise", + "deck": "nilfgaard", + "row": "close", + "strength": "6", + "ability": "bond", + "filename": "ard_feainn_tortoise", + "count": "3", + "target": "ne_ard_feainn_tortoise", + "quote": "Close formation, clench your sphincters! Left, right, left, steady!" + }, + "ne_ard_feainn_heavy_cavalry": { + "name": "Ard Feainn Heavy Cavalry", + "deck": "nilfgaard", + "row": "ranged", + "strength": "6", + "ability": "", + "filename": "ard_feainn_heavy_cavalry", + "count": "1", + "target": "ne_ard_feainn_heavy_cavalry", + "quote": "When Emhyr declared that his cavalry would stomp his enemies into the mud, we thought he was speaking metaphorically. We were wrong." + }, + "ne_ramon_tyrconnel": { + "name": "Ramon Tyrconnel", + "deck": "nilfgaard", + "row": "ranged", + "strength": "8", + "ability": "hero muster", + "filename": "ramon_tyrconnel", + "count": "1", + "target": "ne_ard_feainn_heavy_cavalry", + "quote": "Colonel Ramon Tyrconnel, the young commander of the Ard Feainn division, whistled softly, staring at a point somewhere off in the distance..;" + }, + "ne_ffion_gaernel": { + "name": "Ffion var Gaernel", + "deck": "nilfgaard", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "ffion_gaernel", + "count": "1", + "quote": "Everyone will die somehow. I'll die last." + }, + "ne_vrygheff": { + "name": "Vrygheff", + "deck": "nilfgaard", + "row": "siege", + "strength": "9", + "ability": "hero scorch", + "filename": "vrygheff", + "count": "1", + "quote": "An eye for an eye only ends when the whole world's blind." + }, + "ne_traheaern_vdyffir": { + "name": "Traheaern var Vdyffir", + "deck": "nilfgaard", + "row": "close", + "strength": "8", + "ability": "spy", + "filename": "traheaern_vdyffir", + "count": "1", + "quote": "The man leading the Nilfgaardians was clad in rich robes. He exuded pride... and the scent of musk." + }, + "ne_spotter": { + "name": "Spotter", + "deck": "nilfgaard", + "row": "ranged", + "strength": "10", + "ability": "spy", + "filename": "spotter", + "count": "1", + "quote": "The North has nothing with which it could surprise us." + }, + "ne_illusionist": { + "name": "Illusionist", + "deck": "nilfgaard", + "row": "ranged", + "strength": "5", + "ability": "medic", + "filename": "illusionist", + "count": "1", + "quote": "When you are few, make them believe you are many. If they still attack, well... you were fucked either way." + }, + "ne_imperial_practitioner": { + "name": "Imperial Practitioner", + "deck": "nilfgaard", + "row": "siege", + "strength": "3", + "ability": "medic", + "filename": "imperial_practitioner", + "count": "1", + "quote": "The body is a slab of wet clay. One need only use the correct tools to shape it into something... more." + } +}; + +var ext_mo_cards = { + "mo_golem": { + "name": "Golem", + "deck": "monsters", + "row": "close", + "strength": "6", + "ability": "", + "filename": "golem", + "count": "1", + "quote": "Does not drink. Does not eat. Does walk, however. And fight." + }, + "mo_geels": { + "name": "Ge'els", + "deck": "monsters", + "row": "siege", + "strength": "10", + "ability": "hero", + "filename": "geels", + "count": "1", + "quote": "Paintings should convey emotion, not words." + }, + "mo_ifrit_1": { + "name": "Ifrit", + "id": 1, + "deck": "monsters", + "row": "siege", + "strength": "6", + "ability": "muster", + "filename": "ifrit_1", + "count": "1", + "target": "mo_ifrit", + "quote": "Can't stand the heat? Then you don't stand a chance." + }, + "mo_ifrit_2": { + "name": "Ifrit", + "id": 2, + "deck": "monsters", + "row": "siege", + "strength": "6", + "ability": "muster", + "filename": "ifrit_2", + "count": "1", + "target": "mo_ifrit", + "quote": "Can't stand the heat? Then you don't stand a chance." + }, + "mo_wild_hunt_rider_1": { + "name": "Wild Hunt Rider", + "id": 1, + "deck": "monsters", + "row": "close", + "strength": "4", + "ability": "muster", + "filename": "wild_hunt_rider_1", + "count": "1", + "target": "mo_wild_hunt_rider", + "quote": "First the buffalo horns atop their helms penetrate one's view, then the crest betwixt them." + }, + "mo_wild_hunt_rider_2": { + "name": "Wild Hunt Rider", + "id": 2, + "deck": "monsters", + "row": "close", + "strength": "4", + "ability": "muster", + "filename": "wild_hunt_rider_2", + "count": "1", + "target": "mo_wild_hunt_rider", + "quote": "First the buffalo horns atop their helms penetrate one's view, then the crest betwixt them." + }, + "mo_wild_hunt_rider_3": { + "name": "Wild Hunt Rider", + "id": 3, + "deck": "monsters", + "row": "close", + "strength": "4", + "ability": "muster", + "filename": "wild_hunt_rider_3", + "count": "1", + "target": "mo_wild_hunt_rider", + "quote": "First the buffalo horns atop their helms penetrate one's view, then the crest betwixt them." + }, + "mo_nithral": { + "name": "Nithral", + "deck": "monsters", + "row": "close", + "strength": "7", + "ability": "", + "filename": "nithral", + "count": "1", + "quote": "Eredin's personal cavalcade includes only the most brutal and most ferocious of the Aen Elle." + }, + "mo_therazane": { + "name": "Therazane", + "deck": "monsters", + "row": "close", + "strength": "8", + "ability": "hero", + "filename": "therazane", + "count": "1", + "quote": "Fighting such a monster is no easy task." + }, + "mo_naglfar": { + "name": "Naglfar", + "deck": "monsters", + "row": "siege", + "strength": "10", + "ability": "", + "filename": "naglfar", + "count": "1", + "quote": "Naglfar will wage the final battle of good and evil known as Ragh nar Roog." + }, + "mo_caranthir": { + "name": "Caranthir Ar-Feiniel", + "deck": "monsters", + "row": "ranged", + "strength": "10", + "ability": "hero", + "filename": "caranthir", + "count": "1", + "quote": "Zirael! I await." + }, + "mo_jotunn": { + "name": "Jotunnl", + "deck": "monsters", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "jotunn", + "count": "1", + "quote": "Skellige legend claims the mighty and terrible Jotunn, King of Giants, reigned over the isles in ancient times." + }, + "mo_old_speartip": { + "name": "Old Speartip", + "deck": "monsters", + "row": "close", + "strength": "7", + "ability": "", + "filename": "old_speartip", + "count": "1", + "quote": "Old Speartip is one deep sleeper, wake him up and you'll sleep deeper." + }, + "mo_navigator": { + "name": "Wild Hunt Navigator", + "deck": "monsters", + "row": "agile", + "strength": "5", + "ability": "hero", + "filename": "navigator", + "count": "1", + "quote": "For hundreds of years, Avallac'h tried to recreate the Elder Blood gene through back breeding." + }, + "mo_cyclops": { + "name": "Cyclops", + "deck": "monsters", + "row": "ranged", + "strength": "6", + "ability": "", + "filename": "cyclops", + "count": "1", + "quote": "Don't stare at his eye, he hates that..." + }, + "mo_ice_troll": { + "name": "Ice Troll", + "deck": "monsters", + "row": "siege", + "strength": "10", + "ability": "hero", + "filename": "ice_troll", + "count": "1", + "quote": "Trolls come in many shapes, but always with about as much brains as a bucket of rusty nails." + }, + "mo_morvudd": { + "name": "Morvudd", + "deck": "monsters", + "row": "agile", + "strength": "7", + "ability": "hero", + "filename": "morvudd", + "count": "1", + "quote": "An unusual fiend specimen found on Ard Skellig. Unusually picky in terms of food." + }, + "mo_lamia_1": { + "name": "Lamia", + "id": 1, + "deck": "monsters", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "lamia_1", + "count": "1", + "target": "mo_lamia", + "quote": "The fool didn't hear the warning. He ran his ship straight into the rocks." + }, + "mo_lamia_2": { + "name": "Lamia", + "id": 2, + "deck": "monsters", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "lamia_2", + "count": "1", + "target": "mo_lamia", + "quote": "The fool didn't hear the warning. He ran his ship straight into the rocks." + }, + "mo_lamia_3": { + "name": "Lamia", + "id": 3, + "deck": "monsters", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "lamia_3", + "count": "1", + "target": "mo_lamia", + "quote": "The fool didn't hear the warning. He ran his ship straight into the rocks." + }, + "mo_glustyworp": { + "name": "Glustyworp", + "deck": "monsters", + "row": "close", + "strength": "9", + "ability": "hero", + "filename": "glustyworp", + "count": "1", + "quote": "Two long, mantis-like forelimbs bristling with spikes shot out from the murk." + }, + "mo_alghoul": { + "name": "Alghoul", + "id": 4, + "deck": "monsters", + "row": "close", + "strength": "6", + "ability": "muster", + "filename": "alghoul", + "count": "1", + "target": "mo_ghoul", + "quote": "A particularly large ghoul that is fattened and craves warm meat is called an alghoul." + }, + "mo_archgriffin": { + "name": "Archgriffin", + "deck": "monsters", + "row": "close", + "strength": "9", + "ability": "hero", + "filename": "archgriffin", + "count": "1", + "quote": "It's a griffin, just more... griffiny." + }, + "mo_alp": { + "name": "Alp", + "deck": "monsters", + "row": "agile", + "strength": "7", + "ability": "", + "filename": "alp", + "count": "1", + "quote": "No other monster inspires so many myths and fallacies as the alp." + }, + "mo_armoured_arachas": { + "name": "Armoured Arachas", + "deck": "monsters", + "row": "siege", + "strength": "7", + "ability": "", + "filename": "armoured_arachas", + "count": "1", + "quote": "Like a cross between a crab, a spider... and a ploughin' mountain." + }, + "mo_arachas_queen": { + "name": "Arachas Queen", + "deck": "monsters", + "row": "siege", + "strength": "8", + "ability": "hero avenger", + "filename": "arachas_queen", + "count": "1", + "target": "mo_arachas_drone", + "quote": "Her children inherited her beauty." + }, + "mo_arachas_drone": { + "name": "Arachas Drone", + "id": 1, + "deck": "monsters", + "row": "siege", + "strength": "2", + "ability": "muster", + "filename": "arachas_drone", + "count": "4", + "target": "mo_arachas_drone_spawn", + "quote": "Ugly – nature's way of saying stay away." + }, + "mo_dragon_fyresdal": { + "name": "Dragon of Fyresdal", + "deck": "monsters", + "row": "agile", + "strength": "10", + "ability": "hero", + "filename": "dragon_fyresdal", + "count": "1", + "quote": "It's got scales, wings, claws.. A dragon's a dragon! No point gabbin', just go kill it!" + }, + "mo_manticore": { + "name": "Imperial Manticore", + "deck": "monsters", + "row": "ranged", + "strength": "7", + "ability": "", + "filename": "manticore", + "count": "1", + "quote": "Thoug many have seen manticores, very few have lived to tell their tale." + }, + "mo_manticore_venom": { + "name": "Manticore Venom", + "deck": "monsters", + "row": "siege", + "strength": "3", + "ability": "scorch_c", + "filename": "manticore_venom", + "count": "1", + "quote": "Kills quicker than you can recite the Emperor of Nilfgaard's title in full." + }, + "mo_great_oak": { + "name": "The Great Oak", + "deck": "monsters", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "great_oak", + "count": "1", + "quote": "The trees of Brokilon oft rustle amongst themselves, despairing of the ancient oak whose heart now rots with hatred." + }, + "mo_striga": { + "name": "Striga", + "deck": "monsters", + "row": "close", + "strength": "6", + "ability": "", + "filename": "striga", + "count": "1", + "quote": "She is filled with hatred towards all living beings." + }, + "mo_noonwraith": { + "name": "Noonwraith", + "deck": "monsters", + "row": "close", + "strength": "6", + "ability": "", + "filename": "noonwraith", + "count": "1", + "quote": "They are born of some horrible tragedy tied to ill-fated love." + }, + "mo_vran_warrior": { + "name": "Vran Warrior", + "deck": "monsters", + "row": "close", + "strength": "5", + "ability": "", + "filename": "vran_warrior", + "count": "1", + "quote": "He saw their weapons – short spears with wide tips." + }, + "mo_caretaker": { + "name": "Caretaker", + "deck": "monsters", + "row": "close", + "strength": "5", + "ability": "scorch", + "filename": "caretaker", + "count": "1", + "quote": "There are more things in heaven and earth than all the world's philosophers have dreamt." + }, + "mo_lubberkin": { + "name": "Lubberkin", + "deck": "monsters", + "row": "ranged", + "strength": "7", + "ability": "", + "filename": "lubberkin", + "count": "1", + "quote": "I name thee Dea and embrace thee as my daugther." + }, + "mo_ruehin": { + "name": "Ruehin", + "deck": "monsters", + "row": "agile", + "strength": "10", + "ability": "hero", + "filename": "ruehin", + "count": "1", + "quote": "No one has ever entered that forest and lived to tell the tale..." + }, + "mo_queen_night": { + "name": "Queen of the Night", + "deck": "monsters", + "row": "agile", + "strength": "10", + "ability": "hero", + "filename": "queen_night", + "count": "1", + "quote": "Those seduced by her charms find themselves willing to pay any price." + }, + "mo_moonlight": { + "name": "Moonlight", + "deck": "monsters", + "row": "agile", + "strength": "2", + "ability": "scorch_c", + "filename": "moonlight", + "count": "1", + "quote": "When the moon is full, nightmares crawl out of the dark nooks and crannies of the world." + }, + "mo_dagon": { + "name": "Dagon", + "deck": "monsters", + "row": "ranged", + "strength": "10", + "ability": "hero", + "filename": "dagon", + "count": "1", + "quote": "That is not dead which can eternal lie, and with strange aeons even death may die." + }, + "mo_aguara": { + "name": "Aguara", + "deck": "monsters", + "row": "ranged", + "strength": "5", + "ability": "scorch_c", + "filename": "aguara", + "count": "1", + "quote": "Smarten up right now, or it's off to an aguara with you!" + }, + "mo_succubus": { + "name": "Succubus", + "deck": "monsters", + "row": "siege", + "strength": "6", + "ability": "", + "filename": "succubus", + "count": "1", + "quote": "Why fight? There are much better ways to work off excess energy..." + } +}; + +var ext_st_cards = { + "sc_elven_mercenary_1": { + "name": "Elven Mercenary", + "id": 1, + "deck": "scoiatael", + "row": "close", + "strength": "6", + "ability": "muster", + "filename": "elven_mercenary_1", + "count": "1", + "target": "sc_elven_mercenary", + "quote": "I spit on Scoia'Tael ideals, but not on their coin." + }, + "sc_elven_mercenary_2": { + "name": "Elven Mercenary", + "id": 2, + "deck": "scoiatael", + "row": "close", + "strength": "6", + "ability": "muster", + "filename": "elven_mercenary_2", + "count": "1", + "target": "sc_elven_mercenary", + "quote": "I spit on Scoia'Tael ideals, but not on their coin." + }, + "sc_vrihedd_sapper": { + "name": "Vrihedd Sapper", + "deck": "scoiatael", + "row": "ranged", + "strength": "4", + "ability": "scorch", + "filename": "vrihedd_sapper", + "count": "1", + "quote": "No matter what you may have heard, elves don't take human scalps. Too much lice." + }, + "sc_vrihedd_dragoon_1": { + "name": "Vrihedd Dragoon", + "id": 1, + "deck": "scoiatael", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "vrihedd_dragoon_1", + "count": "1", + "target": "sc_vrihedd_dragoon", + "quote": "Most terrible things I've witnessed? The Catriona plague, the razing of Vengerberg and the charge of the Vrihedd Dragoons." + }, + "sc_vrihedd_dragoon_2": { + "name": "Vrihedd Dragoon", + "id": 2, + "deck": "scoiatael", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "vrihedd_dragoon_2", + "count": "1", + "target": "sc_vrihedd_dragoon", + "quote": "Most terrible things I've witnessed? The Catriona plague, the razing of Vengerberg and the charge of the Vrihedd Dragoons." + }, + "sc_vrihedd_dragoon_3": { + "name": "Vrihedd Dragoon", + "id": 3, + "deck": "scoiatael", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "vrihedd_dragoon_3", + "count": "1", + "target": "sc_vrihedd_dragoon", + "quote": "Most terrible things I've witnessed? The Catriona plague, the razing of Vengerberg and the charge of the Vrihedd Dragoons." + }, + "sc_aelirenn": { + "name": "Aelirenn", + "deck": "scoiatael", + "row": "ranged", + "strength": "10", + "ability": "hero medic", + "filename": "aelirenn", + "count": "1", + "quote": "Was also known as the White Rose of Shaerrawedd." + }, + "sc_saesenthessis_saskia": { + "name": "Saesenthessis: Saskia", + "deck": "scoiatael", + "row": "ranged", + "strength": "10", + "ability": "hero avenger", + "filename": "saesenthessis_saskia", + "count": "1", + "target": "sc_saesenthessis_dragon", + "quote": "Beautiful, pure, fierce... the perfect icon for a rebellion." + }, + "sc_saesenthessis_dragon": { + "name": "Saesenthessis: Dragon", + "deck": "scoiatael", + "row": "close", + "strength": "11", + "ability": "hero", + "filename": "saesenthessis_dragon", + "count": "1", + "quote": "I care not for kings and their titles. In the east lives one who truly deserves a crown." + }, + "sc_neophyte": { + "name": "Commando Neophyte", + "deck": "scoiatael", + "row": "close", + "strength": "7", + "ability": "", + "filename": "neophyte", + "count": "1", + "quote": "Many nonhumans, fed up with the racism and xenophobia they encounter in the cities, decide to join the Scoia'tael." + }, + "sc_vrihedd_officer": { + "name": "Vrihedd Officer", + "deck": "scoiatael", + "row": "close", + "strength": "9", + "ability": "", + "filename": "vrihedd_officer", + "count": "1", + "quote": "Temerians, Redanians, all the same. Better off dead." + }, + "sc_dol_blathanna_sentry": { + "name": "Dol Blathanna Sentry", + "deck": "scoiatael", + "row": "close", + "strength": "8", + "ability": "", + "filename": "dol_blathanna_sentry", + "count": "1", + "quote": "As long as we stand, no human foot shall trample Dol Blathanna's meadows." + }, + "sc_dryads_1": { + "name": "Dryads", + "deck": "scoiatael", + "id": 1, + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "dryads_1", + "count": "1", + "target": "sc_dryads", + "quote": "I do not live in the forst of Brokilon. I am part of it." + }, + "sc_dryads_2": { + "name": "Dryads", + "id": 2, + "deck": "scoiatael", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "dryads_2", + "count": "1", + "target": "sc_dryads", + "quote": "I do not live in the forst of Brokilon. I am part of it." + }, + "sc_dryads_3": { + "name": "Dryads", + "id": 3, + "deck": "scoiatael", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "dryads_3", + "count": "1", + "target": "sc_dryads", + "quote": "I do not live in the forst of Brokilon. I am part of it." + }, + "sc_dryads_4": { + "name": "Dryads", + "id": 4, + "deck": "scoiatael", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "dryads_4", + "count": "1", + "target": "sc_dryads", + "quote": "I do not live in the forst of Brokilon. I am part of it." + }, + "sc_brouver_hoog": { + "name": "Brouver Hoog", + "deck": "scoiatael", + "row": "agile", + "strength": "10", + "ability": "hero", + "filename": "brouver_hoog", + "count": "1", + "quote": "That doddery dolt? Ye cannae even tell if he's alive or stuffed!" + }, + "sc_dol_blathanna_guard_1": { + "name": "Dol Blathanna Guard", + "id": 1, + "deck": "scoiatael", + "row": "agile", + "strength": "3", + "ability": "muster", + "filename": "dol_blathanna_guard_1", + "count": "1", + "target": "sc_dol_blathanna_guard", + "quote": "We are the drops of rain that together make a ferocious storm." + }, + "sc_dol_blathanna_guard_2": { + "name": "Dol Blathanna Guard", + "id": 2, + "deck": "scoiatael", + "row": "agile", + "strength": "3", + "ability": "muster", + "filename": "dol_blathanna_guard_2", + "count": "1", + "target": "sc_dol_blathanna_guard", + "quote": "We are the drops of rain that together make a ferocious storm." + }, + "sc_dol_blathanna_guard_3": { + "name": "Dol Blathanna Guard", + "id": 3, + "deck": "scoiatael", + "row": "agile", + "strength": "3", + "ability": "muster", + "filename": "dol_blathanna_guard_3", + "count": "1", + "target": "sc_dol_blathanna_guard", + "quote": "We are the drops of rain that together make a ferocious storm." + }, + "sc_aglais": { + "name": "Aglais", + "deck": "scoiatael", + "row": "agile", + "strength": "8", + "ability": "hero medic", + "filename": "aglais", + "count": "1", + "quote": "Brokilon bleeds… and not even I can heal it." + }, + "sc_elven_deadeye": { + "name": "Elven Deadeye", + "deck": "scoiatael", + "row": "ranged", + "strength": "8", + "ability": "", + "filename": "elven_deadeye", + "count": "1", + "quote": "One, two, come into view. Three, four, hide 'hind the door..." + }, + "sc_morenn": { + "name": "Morenn", + "deck": "scoiatael", + "row": "agile", + "strength": "8", + "ability": "hero", + "filename": "morenn", + "count": "1", + "quote": "Lady Eithné's daughter had inherited her sublime beauty and her wild hatred for all that is human." + }, + "sc_mahakam_pyrotechnician": { + "name": "Mahakam Pyrotechnician", + "deck": "scoiatael", + "row": "siege", + "strength": "8", + "ability": "", + "filename": "mahakam_pyrotechnician", + "count": "1", + "quote": "An extraordinarily risky, and thus much revered, Mahakam trade. Its best-known practitioner was a dwarf by the name of Mikkel Bay." + }, + "sc_mahakam_guard_1": { + "name": "Mahakam Guard", + "id": 1, + "deck": "scoiatael", + "row": "close", + "strength": "6", + "ability": "muster", + "filename": "mahakam_guard_1", + "count": "1", + "target": "sc_mahakam_guard", + "quote": "Only one punishment for disturbin' the peace in Mahakam: a hammer to the heid." + }, + "sc_mahakam_guard_2": { + "name": "Mahakam Guard", + "id": 2, + "deck": "scoiatael", + "row": "close", + "strength": "6", + "ability": "muster", + "filename": "mahakam_guard_2", + "count": "1", + "target": "sc_mahakam_guard", + "quote": "Only one punishment for disturbin' the peace in Mahakam: a hammer to the heid." + }, + "sc_mahakam_ale": { + "name": "Mahakam Ale", + "deck": "scoiatael", + "row": "agile", + "strength": "3", + "ability": "morale", + "filename": "mahakam_ale", + "count": "1", + "quote": "Considered to be the dwarves' greatest contribution to world culture." + }, + "sc_yannick_brass": { + "name": "Yannick Brass", + "deck": "scoiatael", + "row": "close", + "strength": "8", + "ability": "hero", + "filename": "yannick_brass", + "count": "1", + "quote": "Any of uz wanna gud luk at mah axe?!" + }, + "sc_dol_blathanna_trapper": { + "name": "Dol Blathanna Trapper", + "deck": "scoiatael", + "row": "ranged", + "strength": "5", + "ability": "scorch_c", + "filename": "dol_blathanna_trapper", + "count": "1", + "quote": "They track like hounds, run like deer and kill like heartless demons." + }, + "sc_gabor_zigrin": { + "name": "Gabor Zigrin", + "deck": "scoiatael", + "row": "agile", + "strength": "9", + "ability": "hero morale", + "filename": "gabor_zigrin", + "count": "1", + "quote": "Brouver Hoog wanted to kick him out of Mahakam once for having a lama in his living room... it's a long story." + }, + "sc_eleyas": { + "name": "Ele'yas", + "deck": "scoiatael", + "row": "close", + "strength": "7", + "ability": "hero morale", + "filename": "eleyas", + "count": "1", + "quote": "Love justifies madness in any of its forms." + }, + "sc_ithlinne": { + "name": "Ithlinne Aegli aep Aevenien", + "deck": "scoiatael", + "row": "agile", + "strength": "10", + "ability": "hero", + "filename": "ithlinne", + "count": "1", + "quote": "Famed for constantly prophesying the world's doom. Not much fun at parties." + }, + "sc_malena": { + "name": "Malena", + "deck": "scoiatael", + "row": "agile", + "strength": "1", + "ability": "hero horn", + "filename": "malena", + "count": "1", + "quote": "I hate you, dh'oine. You are all the same." + }, + "sc_dwarven_mercenary_1": { + "name": "Dwarven Mercenary", + "id": 1, + "deck": "scoiatael", + "row": "agile", + "strength": "5", + "ability": "muster", + "filename": "dwarven_mercenary_1", + "count": "1", + "target": "sc_dwarven_mercenary", + "quote": "The key's mixin' pleasure an' business – like smackin' foes and gettin' coin for it." + }, + "sc_dwarven_mercenary_2": { + "name": "Dwarven Mercenary", + "id": 2, + "deck": "scoiatael", + "row": "agile", + "strength": "5", + "ability": "muster", + "filename": "dwarven_mercenary_2", + "count": "1", + "target": "sc_dwarven_mercenary", + "quote": "The key's mixin' pleasure an' business – like smackin' foes and gettin' coin for it." + }, + "sc_hawker_smuggler": { + "name": "Hawker Smuggler", + "deck": "scoiatael", + "row": "agile", + "strength": "3", + "ability": "morale", + "filename": "hawker_smuggler", + "count": "1", + "quote": "I fight for whoever's paying the best. Or whoever's easiest to rob." + }, + "sc_dwarven_agitator": { + "name": "Dwarven Agitator", + "deck": "scoiatael", + "row": "agile", + "strength": "3", + "ability": "morale", + "filename": "dwarven_agitator", + "count": "1", + "quote": "Mark me words, if ye dinnae get up off yer arses, humans're gonnae come here an' steal our wenches!" + }, + "sc_mahakam_marauder": { + "name": "Mahakam Marauder", + "deck": "scoiatael", + "row": "agile", + "strength": "6", + "ability": "", + "filename": "mahakam_marauder", + "count": "1", + "quote": "Hunting on Mahakam's craggy cliffs is not particularly easy… but nor are dwarves particularly put off by danger." + }, + "sc_fauve": { + "name": "Fauve", + "deck": "scoiatael", + "row": "agile", + "strength": "5", + "ability": "", + "filename": "fauve", + "count": "1", + "quote": "Dandelion recognized her at once – the very same with green hair who had given them light in dark of night and urged the bard to continue his ballads." + }, + "sc_farseer": { + "name": "Farseer", + "deck": "scoiatael", + "row": "ranged", + "strength": "9", + "ability": "hero", + "filename": "farseer", + "count": "1", + "quote": "Her words might seem unintelligible at times, but they always contain hidden meanings and tremendous wisdom." + }, + "sc_sirssa": { + "name": "Sirssa", + "deck": "scoiatael", + "row": "ranged", + "strength": "9", + "ability": "hero", + "filename": "sirssa", + "count": "1", + "quote": "With silent grace, a dark-haired dryad nimbly descended a spiralling cascade of mushrooms along the tree's trunk." + }, + "sc_braenn": { + "name": "Braenn", + "deck": "scoiatael", + "row": "ranged", + "strength": "5", + "ability": "", + "filename": "braenn", + "count": "1", + "quote": "Mona…? No… no. I'm Braenn. A daughter of Brokilon." + }, + "sc_hawker_support": { + "name": "Hawker Support", + "deck": "scoiatael", + "row": "siege", + "strength": "4", + "ability": "medic", + "filename": "hawker_support", + "count": "1", + "quote": "Elf, dwarf, makes no difference – long as they've got coin." + }, + "sc_eldain": { + "name": "Eldain", + "deck": "scoiatael", + "row": "agile", + "strength": "9", + "ability": "hero", + "filename": "eldain", + "count": "1", + "quote": "The king once dispatched an envoy to Eldain… despite my advice to the contrary." + }, + "sc_giantslayer": { + "name": "Giantslayer", + "deck": "scoiatael", + "row": "agile", + "strength": "5", + "ability": "scorch", + "filename": "giantslayer", + "count": "1", + "quote": "Aye, they call me the Giantslayer, and nay, it ain't from bein' a humongous bastard now, is it?" + }, + "sc_elven_scout": { + "name": "Elven Scout", + "deck": "scoiatael", + "row": "close", + "strength": "10", + "ability": "spy", + "filename": "elven_scout", + "count": "1", + "quote": "They say elves leave no tracks in the snow, but if you ask me, they are just a pack of village idiots, babbling nonsense." + }, + "sc_elven_swordmaster": { + "name": "Elven Swordmaster", + "deck": "scoiatael", + "row": "close", + "strength": "7", + "ability": "scorch_c", + "filename": "elven_swordmaster", + "count": "1", + "quote": "Combat is a dance, and you must never allow your opponent to lead." + }, + "sc_vrihedd_saboteur": { + "name": "Vrihedd Saboteur", + "deck": "scoiatael", + "row": "siege", + "strength": "7", + "ability": "spy", + "filename": "vrihedd_saboteur", + "count": "1", + "quote": "The gates were ordered to be closed… But they didn't budge." + } +}; + +var ext_sk_cards = { + "sk_svalblod": { + "name": "Svalblod", + "deck": "skellige", + "row": "agile", + "strength": "11", + "ability": "hero", + "filename": "svalblod", + "count": "1", + "quote": "He proclaimed to his worshippers but one commandement. Kill." + }, + "sk_an_craite_raiders": { + "name": "Clan an Craite Raiders", + "deck": "skellige", + "row": "close", + "strength": "5", + "ability": "", + "filename": "an_craite_raiders", + "count": "1", + "quote": "Cabbage, really? It’s just the worst when there’s nothing good to plunder." + }, + "sk_svalblod_fanatic": { + "name": "Svalblod Fanatic", + "deck": "skellige", + "row": "close", + "strength": "8", + "ability": "", + "filename": "svalblod_fanatic", + "count": "1", + "quote": "Not all are worthy of Svalblod's blessing." + }, + "sk_harald_cripple": { + "name": "Harald the Cripple", + "deck": "skellige", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "harald_cripple", + "count": "1", + "quote": "He did not stop until the islands were his and the head of the old jarl lay on the ground before him." + }, + "sk_drummond_warmonger": { + "name": "Drummond Warmonger", + "deck": "skellige", + "row": "ranged", + "strength": "5", + "ability": "", + "filename": "drummond_warmonger", + "count": "1", + "quote": "Think o' the greater good?! War's the greatest good, the greatest bad, the greatest damn anythin' man's ever come up with!" + }, + "sk_an_craite_greatsword": { + "name": "Clan an Craite Greatsword", + "deck": "skellige", + "row": "close", + "strength": "6", + "ability": "", + "filename": "an_craite_greatsword", + "count": "1", + "quote": "Ahh, ye gave me a good laugh there, Nordling! Why, this bastard, ye couldn't even grip it, let alone gut me with it." + }, + "sk_vabjorn": { + "name": "Vabjorn", + "deck": "skellige", + "row": "close", + "strength": "9", + "ability": "hero", + "filename": "vabjorn", + "count": "1", + "quote": "Blood for Svalblod! Skulls for his throne!" + }, + "sk_tuirseach_bearmaster": { + "name": "Tuirseach Bearmaster", + "deck": "skellige", + "row": "close", + "strength": "7", + "ability": "", + "filename": "tuirseach_bearmaster", + "count": "1", + "quote": "Blood for Svalblod! Skulls for his throne!" + }, + "sk_morkvarg": { + "name": "Morkvarg", + "deck": "skellige", + "row": "close", + "strength": "7", + "ability": "", + "filename": "morkvarg", + "count": "1", + "quote": "The vilest man Skellige's ever known." + }, + "sk_drummond_berserker": { + "name": "Drummond Berserker", + "deck": "skellige", + "row": "close", + "strength": "5", + "ability": "berserker", + "filename": "drummond_berserker", + "count": "1", + "target": "sk_vildkaarl", + "quote": "The vilest man Skellige's ever known." + }, + "sk_chosen_berserker": { + "name": "Chosen Berserker", + "deck": "skellige", + "row": "agile", + "strength": "5", + "ability": "berserker", + "filename": "chosen_berserker", + "count": "1", + "target": "sk_champion_svalblod", + "quote": "Strike me! C'mon, harder! You call this pain?! " + }, + "sk_champion_svalblod": { + "name": "Champion of Svalblod", + "deck": "skellige", + "row": "agile", + "strength": "14", + "ability": "scorch_c", + "filename": "champion_svalblod", + "count": "1", + "quote": "This bear taste funny to you? " + }, + "sk_war_longship_3": { + "name": "War Longship", + "id": 3, + "deck": "skellige", + "row": "siege", + "strength": "6", + "ability": "bond", + "filename": "war_longship_3", + "count": "1", + "target": "sk_war_longship", + "quote": "They say Hemdall's heart swells whenever the longships sail out on a raid." + }, + "sk_dimun_pirate_captain": { + "name": "Clan Dimun Pirate Captain", + "deck": "skellige", + "row": "agile", + "strength": "6", + "ability": "", + "filename": "dimun_pirate_captain", + "count": "1", + "quote": "Haul together, hoist the colors high!" + }, + "sk_vigi_loon": { + "name": "Vigi the Loon", + "deck": "skellige", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "vigi_loon", + "count": "1", + "quote": "Even for Skelligers Vigi's fearlessness went far beyond the pale of bravery." + }, + "sk_tuirseach_warrior_1": { + "name": "Clan Tuirseach Warrior", + "id": 1, + "deck": "skellige", + "row": "agile", + "strength": "3", + "ability": "bond", + "filename": "tuirseach_warrior_1", + "count": "1", + "target": "sk_tuirseach_warrior", + "quote": "Friends we show heart, foes we show our axe. Remember that." + }, + "sk_tuirseach_warrior_2": { + "name": "Clan Tuirseach Warrior", + "id": 2, + "deck": "skellige", + "row": "agile", + "strength": "3", + "ability": "bond", + "filename": "tuirseach_warrior_2", + "count": "1", + "target": "sk_tuirseach_warrior", + "quote": "Friends we show heart, foes we show our axe. Remember that." + }, + "sk_heymaey_flaminica": { + "name": "Clan Heymaey Flaminica", + "deck": "skellige", + "row": "siege", + "strength": "3", + "ability": "medic", + "filename": "heymaey_flaminica", + "count": "1", + "quote": "A flaminica, the highest position among the druidesses, commands a great deal of respect and wields a great deal of power." + }, + "sk_arnjolf": { + "name": "Arnjolf the Patricide", + "deck": "skellige", + "row": "ranged", + "strength": "8", + "ability": "", + "filename": "arnjolf", + "count": "1", + "quote": "Only death can cleanse me o' shame." + }, + "sk_otkell": { + "name": "otkell", + "deck": "skellige", + "row": "ranged", + "strength": "8", + "ability": "hero morale", + "filename": "otkell", + "count": "1", + "quote": "The mother Godess' power knows no bounds." + }, + "sk_dagur": { + "name": "Dagur Two Blades", + "deck": "skellige", + "row": "close", + "strength": "7", + "ability": "", + "filename": "dagur", + "count": "1", + "quote": "Shields are for flower-pickin' saps." + }, + "sk_sigrdrifa": { + "name": "Sigrdrifa", + "deck": "skellige", + "row": "ranged", + "strength": "0", + "ability": "medic", + "filename": "sigrdrifa", + "count": "1", + "quote": "Fall on your knees and beg Modron Freya for forgiveness." + }, + "sk_jutta": { + "name": "Jutta an Dimun", + "deck": "skellige", + "row": "close", + "strength": "9", + "ability": "hero", + "filename": "jutta", + "count": "1", + "quote": "Some call her the Iron Maiden." + }, + "sk_eist_tuirseach": { + "name": "Eist Tuirseach", + "deck": "skellige", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "eist_tuirseach", + "count": "1", + "quote": "Skellige and Cintra shall stand ever together!" + }, + "sk_troll_errant": { + "name": "Troll Errant", + "deck": "skellige", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "troll_errant", + "count": "1", + "quote": "Champion of Champions!" + }, + "sk_giant_boar": { + "name": "Giant Boar", + "deck": "skellige", + "row": "close", + "strength": "6", + "ability": "", + "filename": "giant_boar", + "count": "1", + "quote": "Most men, seeing a massive boar in the woods, mess their trousers and scurry up the nearest tree. A Skelliger, though - he just drools." + }, + "sk_harald_houndsnout": { + "name": "Harald Houndsnout", + "deck": "skellige", + "row": "close", + "strength": "3", + "ability": "", + "filename": "harald_houndsnout", + "count": "1", + "quote": "Once proud jarl of Clan Tordarroch, now a muttering madman." + }, + "sk_skjall": { + "name": "Skjall", + "deck": "skellige", + "row": "close", + "strength": "4", + "ability": "", + "filename": "skjall", + "count": "1", + "quote": "Strike his name from the Saga of Elders! No one dare grant him shelter or sustenance!" + }, + "sk_brokvar_hunter": { + "name": "Clan Brokvar Hunter", + "deck": "skellige", + "row": "agile", + "strength": "4", + "ability": "", + "filename": "brokvar_hunter", + "count": "1", + "quote": "Better believe we can hunt. Thing is, not much game on Spikeroog..." + }, + "sk_tuirseach_veteran": { + "name": "Clan Tuirseach Veteran", + "deck": "skellige", + "row": "agile", + "strength": "4", + "ability": "", + "filename": "tuirseach_veteran", + "count": "1", + "quote": "I've seen wonders no man's ever dreamt of, and done things no man should ever do." + }, + "sk_djenge_frett": { + "name": "Djenge Frett", + "deck": "skellige", + "row": "ranged", + "strength": "7", + "ability": "hero", + "filename": "djenge_frett", + "count": "1", + "quote": "Should I catch you, you'll hang, and I'll tickle your feet as you expire." + }, + "sk_heymaey_herbalist": { + "name": "Heymaey Herbalist", + "deck": "skellige", + "row": "ranged", + "strength": "1", + "ability": "hero medic", + "filename": "heymaey_herbalist", + "count": "1", + "quote": "We don't burn cunning women in Skellige - we take their advice." + }, + "sk_gremist": { + "name": "Gremist", + "deck": "skellige", + "row": "ranged", + "strength": "5", + "ability": "", + "filename": "gremist", + "count": "1", + "quote": "An archdruid, a master of alchemy, and the grumpiest old fart in the Isles." + }, + "sk_holger_blackhand": { + "name": "Holger Blackhand", + "deck": "skellige", + "row": "siege", + "strength": "4", + "ability": "", + "filename": "holger_blackhand", + "count": "1", + "quote": "Now let's drink to the Emperor of Nilfgaard – may he die of somethin' hideous!" + }, + "sk_an_craite_blacksmith": { + "name": "Clan an Craite Blacksmith", + "deck": "skellige", + "row": "ranged", + "strength": "4", + "ability": "", + "filename": "an_craite_blacksmith", + "count": "1", + "quote": "Remember me words – a good shield can save yer life." + }, + "sk_hym": { + "name": "Hym", + "deck": "skellige", + "row": "siege", + "strength": "10", + "ability": "hero", + "filename": "hym", + "count": "1", + "quote": "The gods' speak to me... I hear them whisper from the shadows..." + }, + "sk_wild_boar": { + "name": "Wild Boar of the Sea", + "deck": "skellige", + "row": "siege", + "strength": "6", + "ability": "", + "filename": "wild_boar", + "count": "1", + "quote": "Merely mention this name to a Nilfgaardian, and they'll feel a spreading warmth in their knickers..." + }, + "sk_whale_harpooner": { + "name": "Whale Harpooner", + "deck": "skellige", + "row": "siege", + "strength": "7", + "ability": "", + "filename": "whale_harpooner", + "count": "1", + "quote": "Skelligers have long known that harpoons are effective against more than mere whales..." + }, + "sk_blue_whale": { + "name": "Blue Whale", + "deck": "skellige", + "row": "siege", + "strength": "8", + "ability": "", + "filename": "blue_whale", + "count": "1", + "quote": "Too big for a razorback. That's a blue." + } +}; + +var ext_wu_cards = { + "wu_vilgefortz_magician_kovir": { + "name": "Vilgefortz: Magician of Kovir", + "deck": "witcher_universe", + "row": "leader", + "strength": "", + "ability": "vilgefortz_magician_kovir", + "filename": "vilgefortz_magician_kovir", + "count": "1", + "quote": "The nature does not have the knowledge of the philosophical thought." + }, + "wu_tissaia": { + "name": "Tissaia de Vries", + "deck": "witcher_universe", + "row": "ranged", + "strength": "6", + "ability": "medic", + "filename": "tissaia", + "count": "1", + "quote": "They will not enter here. No one invited those royalist lackeys, who carry out the orders of their short-sighted kings!" + }, + "wu_rats_giselher": { + "name": "The Rats: Giselher", + "deck": "witcher_universe", + "row": "close", + "strength": "4", + "ability": "muster", + "filename": "rats_giselher", + "count": "1", + "target": "wu_rats", + "quote": "He wants to make us angry? Let the bastard talk." + }, + "wu_rats_asse": { + "name": "The Rats: Asse", + "deck": "witcher_universe", + "row": "close", + "strength": "3", + "ability": "muster", + "filename": "rats_asse", + "count": "1", + "target": "wu_rats", + "quote": "He had been hunting the Nilfgaardians for three days, insane with the desire for revenge for what the marauders had done to his familly." + }, + "wu_rats_iskra": { + "name": "The Rats: Iskra", + "deck": "witcher_universe", + "row": "ranged", + "strength": "3", + "ability": "muster", + "filename": "rats_iskra", + "count": "1", + "target": "wu_rats", + "quote": "The speed blew her beautiful, dark hair around, revealing a small, pointed ear decorated with a filigree earring." + }, + "wu_rats_kayleigh": { + "name": "The Rats: Kayleigh", + "deck": "witcher_universe", + "row": "close", + "strength": "3", + "ability": "muster", + "filename": "rats_kayleigh", + "count": "1", + "target": "wu_rats", + "quote": "He had woken up in smoke, fire and blood, lying among the corpses of his adoptive parents and siblings." + }, + "wu_rats_mistle": { + "name": "The Rats: Mistle", + "deck": "witcher_universe", + "row": "ranged", + "strength": "3", + "ability": "muster", + "filename": "rats_mistle", + "count": "1", + "target": "wu_rats", + "quote": "The tree stump was followed by a young woman with close-cropped fair hair in a red doublet and high, shiny boots reaching above the knee." + }, + "wu_rats_reef": { + "name": "The Rats: Reef", + "deck": "witcher_universe", + "row": "ranged", + "strength": "3", + "ability": "muster", + "filename": "rats_reef", + "count": "1", + "target": "wu_rats", + "quote": "Caring for the wounded was not a custom among the killers of the Nilfgaardian special squads." + }, + "wu_ralf_blunden": { + "name": "Ralf Blunden", + "deck": "witcher_universe", + "row": "ranged", + "strength": "7", + "ability": "spy", + "filename": "ralf_blunden", + "count": "1", + "quote": "The Professor's trademark is his sophisticated choice of words, and witty comments." + }, + "wu_bomb_heaver": { + "name": "Bomb Heaver", + "deck": "witcher_universe", + "row": "siege", + "strength": "3", + "ability": "scorch", + "filename": "bomb_heaver", + "count": "1", + "quote": "Watch your heads!" + }, + "wu_gascon_light_cavalry": { + "name": "Gascon's Light Cavalry", + "deck": "witcher_universe", + "row": "close", + "strength": "5", + "ability": "muster", + "filename": "gascon_light_cavalry", + "count": "1", + "target": "wu_gascon_troops", + "quote": "The chase is on!" + }, + "wu_gascon_slinger": { + "name": "Gascon's Slingers", + "deck": "witcher_universe", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "gascon_slinger", + "count": "1", + "target": "wu_gascon_troops", + "quote": "Bigger they are, easier they are to target." + }, + "wu_gascon_infiltrator": { + "name": "Gascon's Infiltrator", + "deck": "witcher_universe", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "gascon_infiltrator", + "count": "1", + "target": "wu_gascon_troops", + "quote": "We got a job to do." + }, + "wu_gascon": { + "name": "Gascon", + "deck": "witcher_universe", + "row": "siege", + "strength": "7", + "ability": "hero muster", + "filename": "gascon", + "count": "1", + "target": "wu_gascon_troops", + "quote": "Th' Strays of Spalla – 'tis you who lead them? 'Tis you they call the Duke of Dogs?" + }, + "wu_dorregaray": { + "name": "Dorregaray of Vole", + "deck": "witcher_universe", + "row": "ranged", + "strength": "10", + "ability": "hero", + "filename": "dorregaray", + "count": "1", + "quote": "Dorregaray is a monster aficionado, though he's developed his own classification system." + }, + "wu_ortolan": { + "name": "Grandmaster Ortolan", + "deck": "witcher_universe", + "row": "siege", + "strength": "5", + "ability": "medic", + "filename": "ortolan", + "count": "1", + "quote": "He was a legendary mage who was in charge of the experiments done at Rissberg Castle." + }, + "wu_coral": { + "name": "Coral", + "deck": "witcher_universe", + "row": "siege", + "strength": "6", + "ability": "", + "filename": "coral", + "count": "1", + "quote": "Her true name's Astrid Lyttneyd Ásgeirrfinnbjornsdottir, but that never fit on any forms." + }, + "wu_leo_bonhart": { + "name": "Leo Bonhart", + "deck": "witcher_universe", + "row": "close", + "strength": "11", + "ability": "hero", + "filename": "leo_bonhart", + "count": "1", + "quote": "So you do not fear death? Then look at that little Rat. This is death." + }, + "wu_azar_javed": { + "name": "Azar Javed", + "deck": "witcher_universe", + "row": "ranged", + "strength": "7", + "ability": "", + "filename": "azar_javed", + "count": "1", + "quote": "This time you pissed into a tornado." + }, + "wu_strays_spalla": { + "name": "Strays of Spalla", + "deck": "witcher_universe", + "row": "close", + "strength": "8", + "ability": "", + "filename": "strays_spalla", + "count": "1", + "quote": "I'll release ye o' that pouch." + }, + "wu_gerhart_aelle": { + "name": "Gerhart of Aelle", + "deck": "witcher_universe", + "row": "siege", + "strength": "10", + "ability": "hero", + "filename": "gerhart_aelle", + "count": "1", + "quote": "Gerhart of Aelle, otherwise known as Hen Gedymdeith, was the oldest living sorcerer. That is, until his death on Thanedd Island during the coup." + }, + "wu_lydia_bredevoort": { + "name": "Lydia van Bredevoort", + "deck": "witcher_universe", + "row": "ranged", + "strength": "5", + "ability": "medic", + "filename": "lydia_bredevoort", + "count": "1", + "quote": "Whether by brush or by sorcery, there was no event, emotion, or scene beyond Lydia's power to depict. Apart from joy." + }, + "wu_dana_meadbh": { + "name": "Dana Meadbh", + "deck": "witcher_universe", + "row": "ranged", + "strength": "8", + "ability": "hero morale", + "filename": "dana_meadbh", + "count": "1", + "quote": "Through the grasses covering the glade floated a golden-haired queen. Queen of the Fields." + }, + "wu_rience": { + "name": "Rience", + "deck": "witcher_universe", + "row": "siege", + "strength": "5", + "ability": "", + "filename": "rience", + "count": "1", + "quote": "I love watching people suffer." + }, + "wu_visenna": { + "name": "Visenna", + "deck": "witcher_universe", + "row": "siege", + "strength": "3", + "ability": "medic", + "filename": "visenna", + "count": "1", + "quote": "The scar will remain, of course. A new one for your collection." + }, + "wu_operator": { + "name": "Operator", + "deck": "witcher_universe", + "row": "ranged", + "strength": "5", + "ability": "scorch_c", + "filename": "operator", + "count": "1", + "quote": "As time and space collapse before us, they expand behind us..." + }, + "wu_cosimo_malaspina": { + "name": "Cosimo Malaspina: Master of Mutations", + "deck": "witcher_universe", + "row": "leader", + "strength": "", + "ability": "cosimo_malaspina", + "filename": "cosimo_malaspina", + "count": "1", + "quote": "Children keep asking him for gifts. He doesn’t know why, but it really helps with finding subjects for his experiments." + }, + "wu_coen": { + "name": "Coën", + "deck": "witcher_universe", + "row": "close", + "strength": "8", + "ability": "witcher_griffin_school", + "filename": "coen", + "count": "1", + "quote": "There is no such thing as a fair fight. Every advantage and every opportunity that arises is used in combat." + }, + "wu_stygga_castle": { + "name": "Stygga Castle", + "deck": "witcher_universe", + "row": "siege", + "strength": "8", + "ability": "hero resilience witcher_cat_school", + "filename": "stygga_castle", + "count": "1", + "quote": "The Feline witchers did not stay in Stygga Castle for long. Nor anywhere else, actually." + }, + "wu_vesemir": { + "name": "Vesemir", + "deck": "witcher_universe", + "row": "close", + "strength": "6", + "ability": "witcher_wolf_school", + "filename": "vesemir", + "count": "1", + "quote": "If you're to be hanged, ask for water. Anything can happen before they fetch it." + }, + "wu_haern_caduch": { + "name": "Haern Caduch", + "deck": "witcher_universe", + "row": "siege", + "strength": "8", + "ability": "hero resilience witcher_bear_school", + "filename": "haern_caduch", + "count": "1", + "quote": "Carved into the icy rock of the Amell Mountains, the location of the long-abandoned School of the Bear remains a well-kept secret." + }, + "wu_ivo_belhaven": { + "name": "Ivo of Belhaven", + "deck": "witcher_universe", + "row": "close", + "strength": "6", + "ability": "witcher_bear_school", + "filename": "ivo_belhaven", + "count": "1", + "quote": "It's not reason I'm devoid of, just emotion." + }, + "wu_lambert": { + "name": "Lambert", + "deck": "witcher_universe", + "row": "close", + "strength": "7", + "ability": "witcher_wolf_school", + "filename": "lambert", + "count": "1", + "quote": "Now that's the kind of negotiating I understand." + }, + "wu_keldar": { + "name": "Keldar", + "deck": "witcher_universe", + "row": "siege", + "strength": "6", + "ability": "medic witcher_griffin_school", + "filename": "keldar", + "count": "1", + "quote": "You blunt, brainless humanoids! What do you mean by 'I don't know?'. You would go hunt the vampires with the Lebioda idol, smeared in garlic!" + }, + "wu_ivar": { + "name": "Ivar Evil-Eye", + "deck": "witcher_universe", + "row": "ranged", + "strength": "8", + "ability": "witcher_viper_school", + "filename": "ivar", + "count": "1", + "quote": "There’s a terrible tale behind each and every scar⁠—you’d be surprised just how many are true." + }, + "wu_gorthur_gvaed": { + "name": "Gorthur Gvaed", + "deck": "witcher_universe", + "row": "siege", + "strength": "8", + "ability": "hero resilience witcher_viper_school", + "filename": "gorthur_gvaed", + "count": "1", + "quote": "There were many scrolls and manuscripts about the legend of the Wild Hunt in the stronghold—and for a good reason." + }, + "wu_kaer_morhen": { + "name": "Kaer Morhen", + "deck": "witcher_universe", + "row": "siege", + "strength": "8", + "ability": "hero resilience witcher_wolf_school", + "filename": "kaer_morhen", + "count": "1", + "quote": "The bones of the dead remain at the bottom of the moat surrounding the stronghold, left there as a reminder of the massacre that was born from hatred." + }, + "wu_kaer_seren": { + "name": "Kaer Seren", + "deck": "witcher_universe", + "row": "siege", + "strength": "8", + "ability": "hero resilience witcher_griffin_school", + "filename": "kaer_seren", + "count": "1", + "quote": "Kaer Seren’s literary collection was its greatest treasure and the envy of a group of overzealous mages." + }, + "wu_gezras": { + "name": "Gezras of Leyda", + "deck": "witcher_universe", + "row": "siege", + "strength": "9", + "ability": "witcher_cat_school", + "filename": "gezras", + "count": "1", + "quote": "Take a contract from Aen Seidhe over a dh'oine any day, as you’re far less likely to receive a knife between the ribs in place of coin." + }, + "wu_geralt_1": { + "name": "Geralt of Rivia", + "deck": "witcher_universe", + "row": "close", + "strength": "9", + "ability": "scorch_c witcher_wolf_school", + "filename": "geralt_1", + "count": "1", + "quote": "If that's what it takes to save the world, it's better to let that world die." + }, + "wu_gaetan": { + "name": "Gaetan", + "deck": "witcher_universe", + "row": "ranged", + "strength": "7", + "ability": "witcher_cat_school", + "filename": "gaetan", + "count": "1", + "quote": "Murder me just to save few crowns? I’m supposed to protect whoresons like that?" + }, + "wu_brehen": { + "name": "Brehen", + "deck": "witcher_universe", + "row": "close", + "strength": "6", + "ability": "scorch_c witcher_cat_school", + "filename": "brehen", + "count": "1", + "quote": "Known as the Cat of Iello. A moniker earned not from origins, but as a result of slaughtering peasants there. More of a massacre, really." + }, + "wu_gerd": { + "name": "Gerd", + "deck": "witcher_universe", + "row": "close", + "strength": "8", + "ability": "scorch_c witcher_bear_school", + "filename": "gerd", + "count": "1", + "quote": "He was contracted to slay a dragon, a siren, and a striga. He was also being pursued by a vengeful knight, bounty hunters, and bandits." + }, + "wu_warrit": { + "name": "Warrit the All-Seeing", + "deck": "witcher_universe", + "row": "ranged", + "strength": "7", + "ability": "witcher_viper_school", + "filename": "warrit", + "count": "1", + "quote": "By slightly modifying the Supirre sign, Warritt gained the ability to see... everything." + }, + "wu_erland": { + "name": "Erland of Larvik", + "deck": "witcher_universe", + "row": "ranged", + "strength": "9", + "ability": "witcher_griffin_school", + "filename": "erland", + "count": "1", + "quote": "Erland founded the School of the Griffin, and hoped his emphasis on knightly values would help elevate the reputation of witchers among the common folk." + }, + "wu_arnaghad": { + "name": "Arnaghad", + "deck": "witcher_universe", + "row": "close", + "strength": "9", + "ability": "witcher_bear_school", + "filename": "arnaghad", + "count": "1", + "quote": "A witcher’s job is to kill monsters and collect coin. No more, no less." + }, + "wu_letho": { + "name": "Letho of Gulet", + "deck": "witcher_universe", + "row": "close", + "strength": "9", + "ability": "scorch_c witcher_viper_school", + "filename": "letho", + "count": "1", + "quote": "Witchers never die in their beds." + }, + "wu_eskel": { + "name": "Eskel", + "deck": "witcher_universe", + "row": "ranged", + "strength": "8", + "ability": "witcher_wolf_school", + "filename": "eskel", + "count": "1", + "quote": "I'm a simple witcher, Wolf. Don't fight dragons, don't fraternize with kings and don't sleep with sorceresses..." + }, + "wu_kolgrim": { + "name": "Kolgrim", + "deck": "witcher_universe", + "row": "close", + "strength": "6", + "ability": "witcher_viper_school", + "filename": "kolgrim", + "count": "1", + "quote": "Fortune only smiled upon him if it was accompanied by a stroke of very bad luck." + }, + "wu_swallow_potion": { + "name": "Swallow Potion", + "deck": "witcher_universe", + "row": "agile", + "strength": "2", + "ability": "horn", + "filename": "swallow_potion", + "count": "1", + "quote": "Symbolizing spring and rejuvenation, the swallow lent its name to this potion that accelerates the rate at which wounds scab over and heal." + }, + "spe_sign_igni": { + "name": "Sign: Igni", + "deck": "special witcher_universe", + "row": "", + "strength": "", + "ability": "scorch", + "filename": "sign_igni", + "count": "3", + "quote": "A twist of a witcher's fingers can light a lamp… or incinerate a foe." + }, + "spe_sign_quen": { + "name": "Sign: Quen", + "deck": "special witcher_universe", + "row": "", + "strength": "", + "ability": "shield", + "filename": "sign_quen", + "count": "3", + "quote": "Geralt, feeling the iron taste of blood in his mouth, shouted a spell, with his fingers open in the Quen Sign." + }, + "spe_sign_axii": { + "name": "Sign: Axii", + "deck": "special witcher_universe", + "row": "", + "strength": "", + "ability": "seize", + "filename": "sign_axii", + "count": "3", + "quote": "Geralt makes the Axii sign with the fingers of his right hand above the steed's head and whispers the incantation." + }, + "spe_sign_aard": { + "name": "Sign: Aard", + "deck": "special witcher_universe", + "row": "", + "strength": "", + "ability": "knockback", + "filename": "sign_aard", + "count": "3", + "quote": "A blast of concentrated energy that pummels everything in its path. Great for when you forget your keys." + }, + "spe_sign_yrden": { + "name": "Sign: Yrden", + "deck": "special witcher_universe", + "row": "", + "strength": "", + "ability": "lock", + "filename": "sign_yrden", + "count": "3", + "quote": "He lay down next to Adda's mummified remains, drawing the Yrden Sign on the inner side of her sarcophagus' lid." + }, + "wu_alzur_maker": { + "name": "Alzur: The Maker of Spells", + "deck": "witcher_universe", + "row": "leader", + "strength": "", + "ability": "alzur_maker", + "filename": "alzur_maker", + "count": "1", + "quote": "A rebel… outcast... knight… even sorcerer if you can believe that." + }, + "wu_koshchey": { + "name": "Koshchey", + "deck": "witcher_universe", + "row": "close", + "strength": "9", + "ability": "scorch_c", + "filename": "koshchey", + "count": "0", + "quote": "If I tell you koshchey is death, you'll go to the creek anyway, right?" + }, + "wu_doppler_1": { + "name": "Doppler", + "deck": "witcher_universe", + "row": "agile", + "strength": "4", + "ability": "spy", + "filename": "doppler_1", + "count": "1", + "quote": "I'll be on my way and lose myself in the crowd." + }, + "wu_idr": { + "name": "Idr", + "deck": "witcher_universe", + "row": "close", + "strength": "10", + "ability": "", + "filename": "idr", + "count": "1", + "quote": "Who's a good boy? ⁠— Idarran" + }, + "wu_iris_von_everec": { + "name": "Iris von Everec", + "deck": "witcher_universe", + "row": "ranged", + "strength": "9", + "ability": "hero", + "filename": "iris_von_everec", + "count": "1", + "quote": "I remember so little... Yet when I think of my rose, I begin to recall what was." + }, + "wu_sarah": { + "name": "Sarah", + "deck": "witcher_universe", + "row": "siege", + "strength": "7", + "ability": "spy", + "filename": "sarah", + "count": "1", + "quote": "Little Sarah wants to play!" + }, + "wu_djinn": { + "name": "Djinn", + "deck": "witcher_universe", + "row": "siege", + "strength": "6", + "ability": "hero scorch_c", + "filename": "djinn", + "count": "1", + "quote": "A djinn, good sirs, fulfills but three wishes. Thus freed, it flees to dimensions unknown." + }, + "wu_myrgtabrakke": { + "name": "Myrgtabrakke", + "deck": "witcher_universe", + "row": "siege", + "strength": "10", + "ability": "", + "filename": "myrgtabrakke", + "count": "1", + "quote": "Never get between a mother dragon and her young." + }, + "wu_vincent_meis": { + "name": "Vincent Meis", + "deck": "witcher_universe", + "row": "close", + "strength": "5", + "ability": "scorch_c", + "filename": "vincent_meis", + "count": "1", + "quote": "By day, Captain of the Vizima City Guard. By night, merciless avenger and defender of the downtrodden." + }, + "wu_raging_bear": { + "name": "Raging Bear", + "deck": "witcher_universe", + "row": "agile", + "strength": "6", + "ability": "scorch", + "filename": "raging_bear", + "count": "1", + "quote": "Tame? Och, lad, people might train bears but that don't at all mean they tame 'em..." + }, + "wu_iris_companions_1": { + "name": "Iris Companions: Black Dog", + "deck": "witcher_universe", + "row": "close", + "strength": "4", + "ability": "muster", + "filename": "iris_companions", + "count": "1", + "target": "wu_iris_companions", + "quote": "We'd rather keep our names to ourselves. Think of us as… friends of the house." + }, + "wu_iris_companions_2": { + "name": "Iris Companions: Black Cat", + "deck": "witcher_universe", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "iris_companions", + "count": "1", + "target": "wu_iris_companions", + "quote": "We'd rather keep our names to ourselves. Think of us as… friends of the house." + }, + "wu_vlodimir_von_everec": { + "name": "Vlodimir von Everec", + "deck": "witcher_universe", + "row": "close", + "strength": "7", + "ability": "", + "filename": "vlodimir_von_everec", + "count": "1", + "quote": "Vlodimir liked to have a good time when he was alive and greatly missed having fun after his death." + }, + "wu_phoenix": { + "name": "Phoenix", + "deck": "witcher_universe", + "row": "agile", + "strength": "10", + "ability": "hero", + "filename": "phoenix", + "count": "1", + "quote": "What came first, the chicken or the egg? Compared to the conundrum that is the phoenix, that question seems downright trivial." + }, + "wu_boris": { + "name": "Boris", + "deck": "witcher_universe", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "boris", + "count": "1", + "quote": "After getting a taste of human flesh, he won't eat anything else." + }, + "wu_marlene_trastamara": { + "name": "Marlene de Trastamara", + "deck": "witcher_universe", + "row": "close", + "strength": "6", + "ability": "", + "filename": "marlene_trastamara", + "count": "1", + "quote": "None shall sit and dine with you at your table, no spoon you have shall sate you, never again shall you wish to spy your reflection in the mirror." + }, + "wu_idarran_ulivo": { + "name": "Idarran of Ulivo", + "deck": "witcher_universe", + "row": "ranged", + "strength": "8", + "ability": "hero avenger", + "filename": "idarran_ulivo", + "count": "1", + "target": "wu_idr", + "quote": "After getting a taste of human flesh, he won't eat anything else." + }, + "wu_mad_kiyan": { + "name": "Mad Kiyan", + "deck": "witcher_universe", + "row": "close", + "strength": "7", + "ability": "witcher_cat_school", + "filename": "mad_kiyan", + "count": "1", + "quote": "We live on a placid island of ignorance in the midst of black seas of infinity, and it was not meant that we should voyage far." + }, + "wu_cicada": { + "name": "Cicada", + "deck": "witcher_universe", + "row": "close", + "strength": "7", + "ability": "", + "filename": "cicada", + "count": "1", + "quote": "Ivo Mierce, better known by his nickname Cicada, war a criminal and bodyguard." + }, + "wu_nivellen": { + "name": "Nivellen", + "deck": "witcher_universe", + "row": "agile", + "strength": "8", + "ability": "", + "filename": "nivellen", + "count": "1", + "quote": "Flee mortal man! I'll devour you! Tear you to pieces!" + }, + "wu_vilgefortz_sorcerer": { + "name": "Vilgefortz: Sorcerer of Roggeveen", + "deck": "witcher_universe", + "row": "leader", + "strength": "", + "ability": "vilgefortz_sorcerer", + "filename": "vilgefortz_sorcerer", + "count": "1", + "quote": "You've mistaken the stars reflected on the surface of the lake at night for the heavens." + }, + "wu_doppler_2": { + "name": "Doppler", + "deck": "witcher_universe", + "row": "agile", + "strength": "6", + "ability": "spy", + "filename": "doppler_2", + "count": "1", + "quote": "I'll be on my way and lose myself in the crowd." + }, + "wu_pellar": { + "name": "Pellar", + "deck": "witcher_universe", + "row": "ranged", + "strength": "2", + "ability": "medic", + "filename": "pellar", + "count": "1", + "quote": "Gather spirits for this wake, A passing soul ne'er forsake, Hear my call, my humble plea, Unbind his chains, set him free." + }, + "wu_kelpie": { + "name": "Kelpie", + "deck": "witcher_universe", + "row": "siege", + "strength": "0", + "ability": "avenger", + "filename": "kelpie", + "count": "1", + "target": "ntr_ciri", + "quote": "In the north 'Kelpie' was a sea monster..." + }, + "wu_vysogota": { + "name": "Vysogota of Corvo", + "deck": "witcher_universe", + "row": "siege", + "strength": "2", + "ability": "medic", + "filename": "vysogota", + "count": "1", + "quote": "I, Vysogota of Corvo, do not believe in the existence of the gods." + }, + "wu_angouleme": { + "name": "Angouleme", + "deck": "witcher_universe", + "row": "agile", + "strength": "5", + "ability": "", + "filename": "angouleme", + "count": "1", + "quote": "You damned tricksters! Nothing but swindlers!" + }, + "wu_tea_vea_1": { + "name": "Tea & Vea", + "deck": "witcher_universe", + "row": "close", + "strength": "5", + "ability": "muster", + "filename": "tea_vea_1", + "count": "1", + "target" :"wu_tea_vea", + "quote": "Her sabre, drawn faster than they eye could see, cut through the air." + }, + "wu_tea_vea_2": { + "name": "Tea & Vea", + "deck": "witcher_universe", + "row": "close", + "strength": "5", + "ability": "muster", + "filename": "tea_vea_2", + "count": "1", + "target": "wu_tea_vea", + "quote": "Her sabre, drawn faster than they eye could see, cut through the air." + }, + "wu_iola": { + "name": "Iola", + "deck": "witcher_universe", + "row": "ranged", + "strength": "0", + "ability": "medic", + "filename": "iola", + "count": "1", + "quote": "The priestess slowly shook her head, sniffed and wiped a tear away." + }, + "wu_rhapsodic_melody": { + "name": "Rhapsodic Melody", + "deck": "witcher_universe", + "row": "agile", + "strength": "2", + "ability": "horn", + "filename": "rhapsodic_melody", + "count": "1", + "quote": "War's not so horrific when you put a catchy tune to it." + }, + "wu_nenneke": { + "name": "Nenneke", + "deck": "witcher_universe", + "row": "siege", + "strength": "1", + "ability": "medic", + "filename": "nenneke", + "count": "1", + "quote": "Few know more about healing than Nenneke." + }, + "wu_roach": { + "name": "Roach", + "deck": "witcher_universe", + "row": "close", + "strength": "0", + "ability": "avenger", + "filename": "roach", + "count": "1", + "target": "ntr_geralt", + "quote": "Geralt, we gotta have a man–to–horse talk. No offense, but your riding skills? They leave a bit to be desired, buddy." + }, + "wu_kalkstein": { + "name": "Adalbertus Kalkstein", + "deck": "witcher_universe", + "row": "siege", + "strength": "4", + "ability": "morale", + "filename": "kalkstein", + "count": "1", + "quote": "Before Kalkstein departed this world, he left us with some rather unflattering words about our gracious king..." + }, + "wu_gerd_2": { + "name": "Gerd", + "deck": "witcher_universe", + "row": "close", + "strength": "11", + "ability": "hero", + "filename": "gerd_2", + "count": "1", + "quote": "Righteous and brave, of death never scared. Such a man had we in the witcher Gerd." + }, + "wu_lambert_2": { + "name": "Lambert", + "deck": "witcher_universe", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "lambert_2", + "count": "1", + "quote": "Lambert, Lambert, what a prick." + }, + "wu_eskel_2": { + "name": "Eskel", + "deck": "witcher_universe", + "row": "close", + "strength": "10", + "ability": "hero morale", + "filename": "eskel_2", + "count": "1", + "quote": "Heard you panting from three miles away. Just didn't wanna give up that vantage point." + }, + "wu_sheenaz": { + "name": "Sh'eenaz", + "deck": "witcher_universe", + "row": "close", + "strength": "5", + "ability": "hero morale", + "filename": "sheenaz", + "count": "1", + "quote": "The excuses, the stupid and naive excuses: not the slightest bit of dedication!" + }, + "wu_george_kagen": { + "name": "George of Kagen", + "deck": "witcher_universe", + "row": "close", + "strength": "6", + "ability": "witcher_griffin_school", + "filename": "george_kagen", + "count": "1", + "quote": "Instead of monsters, he only found villagers lighting fake fires to sink and loot all arriving ships." + }, + "wu_leo": { + "name": "Leo", + "deck": "witcher_universe", + "row": "close", + "strength": "6", + "ability": "witcher_wolf_school", + "filename": "leo", + "count": "1", + "quote": "He would have caught the arrow if he only had some heads-up." + }, + "wu_renfri": { + "name": "Renfri", + "deck": "witcher_universe", + "row": "close", + "strength": "7", + "ability": "", + "filename": "renfri", + "count": "1", + "quote": "In this fairytale, the princess and the monster are the same person." + }, + "wu_gimpy_gerwin": { + "name": "Gimpy Gerwin", + "deck": "witcher_universe", + "row": "close", + "strength": "6", + "ability": "", + "filename": "gimpy_gerwin", + "count": "1", + "quote": "Keep the vermin on a short leash. And don't be afraid to use that whip!" + }, + "wu_fugas": { + "name": "Fugas", + "deck": "witcher_universe", + "row": "close", + "strength": "7", + "ability": "", + "filename": "fugas", + "count": "1", + "quote": "Heh, givin' me orders? You? A human?" + }, + "wu_barnabas": { + "name": "Barnabas Beckenbauer", + "deck": "witcher_universe", + "row": "close", + "strength": "1", + "ability": "medic", + "filename": "barnabas", + "count": "1", + "quote": "I think you'll really like this one!" + }, + "wu_torque": { + "name": "Torque", + "deck": "witcher_universe", + "row": "close", + "strength": "6", + "ability": "", + "filename": "torque", + "count": "1", + "quote": "Where an elf cannot go himself, he sends a devil." + }, + "wu_deserter_1": { + "name": "Deserter", + "deck": "witcher_universe", + "row": "close", + "strength": "4", + "ability": "muster", + "filename": "deserter_1", + "count": "1", + "target": "wu_deserter", + "quote": "It is interesting that every second deserter is a volunteer." + }, + "wu_deserter_2": { + "name": "Deserter", + "deck": "witcher_universe", + "row": "close", + "strength": "3", + "ability": "muster", + "filename": "deserter_2", + "count": "1", + "target": "wu_deserter", + "quote": "It is interesting that every second deserter is a volunteer." + }, + "wu_deserter_3": { + "name": "Deserter", + "deck": "witcher_universe", + "row": "close", + "strength": "3", + "ability": "muster", + "filename": "deserter_3", + "count": "1", + "target": "wu_deserter", + "quote": "It is interesting that every second deserter is a volunteer." + }, + "wu_bloody_baron": { + "name": "Bloody Baron", + "deck": "witcher_universe", + "row": "close", + "strength": "5", + "ability": "", + "filename": "bloody_baron", + "count": "1", + "quote": "I've not been a good father, I know, but… perhaps it's not too late." + }, + "wu_essi_daven": { + "name": "Essi Daven", + "deck": "witcher_universe", + "row": "ranged", + "strength": "2", + "ability": "horn", + "filename": "essi_daven", + "count": "1", + "quote": "When you have no talent, you don't have the luxury of choosing your audience." + }, + "wu_fercart": { + "name": "Fercart", + "deck": "witcher_universe", + "row": "ranged", + "strength": "5", + "ability": "", + "filename": "fercart", + "count": "1", + "quote": "Pawns will never know of the unseen hands, maneuvering them toward certain doom." + }, + "wu_artaud_terranova": { + "name": "Artaud Terranova", + "deck": "witcher_universe", + "row": "ranged", + "strength": "5", + "ability": "", + "filename": "artaud_terranova", + "count": "1", + "quote": "Ambition can be blinding." + }, + "wu_auckes": { + "name": "Auckes", + "deck": "witcher_universe", + "row": "ranged", + "strength": "6", + "ability": "witcher_viper_school", + "filename": "auckes", + "count": "1", + "quote": "Letho's got a plan… what could go wrong?" + }, + "wu_serrit": { + "name": "Serrit", + "deck": "witcher_universe", + "row": "ranged", + "strength": "6", + "ability": "witcher_viper_school", + "filename": "serrit", + "count": "1", + "quote": "We do what we must. I am not ashamed of that." + }, + "wu_junod": { + "name": "Junod of Belhaven", + "deck": "witcher_universe", + "row": "ranged", + "strength": "6", + "ability": "witcher_bear_school", + "filename": "junod", + "count": "1", + "quote": "Rumour has it he was born of an unusual love between a lady giant and one VERY brave dwarf." + }, + "wu_berengar": { + "name": "Berengar", + "deck": "witcher_universe", + "row": "ranged", + "strength": "6", + "ability": "witcher_wolf_school", + "filename": "berengar", + "count": "1", + "quote": "Talking the vodyanoi out of sacrificing the prize-winning cow wasn’t an easy task." + }, + "wu_stregobor": { + "name": "Stregobor", + "deck": "witcher_universe", + "row": "ranged", + "strength": "4", + "ability": "", + "filename": "stregobor", + "count": "1", + "quote": "I'll be honest, although for my own sake I shouldn't." + }, + "wu_renew": { + "name": "Renew", + "deck": "witcher_universe", + "row": "ranged", + "strength": "2", + "ability": "medic", + "filename": "renew", + "count": "1", + "quote": "Medicus curat, magicae sanat." + }, + "wu_prophet_lebioda": { + "name": "Prophet Lebioda", + "deck": "witcher_universe", + "row": "ranged", + "strength": "8", + "ability": "", + "filename": "prophet_lebioda", + "count": "1", + "quote": "To thine own self be judge and ruler for thou alone shalt answer for thine deeds before thee." + }, + "wu_johnny": { + "name": "Johnny", + "deck": "witcher_universe", + "row": "siege", + "strength": "8", + "ability": "spy", + "filename": "johnny", + "count": "1", + "quote": "Peter Piper picked Prince Proximo a peck of pickled peppers by the Pontar." + }, + "wu_istredd": { + "name": "Istredd", + "deck": "witcher_universe", + "row": "siege", + "strength": "5", + "ability": "", + "filename": "istredd", + "count": "1", + "quote": "Love can make one do crazy things. The loss of love, even more so." + }, + "wu_salma": { + "name": "Salma", + "deck": "witcher_universe", + "row": "siege", + "strength": "4", + "ability": "", + "filename": "salma", + "count": "1", + "quote": "I'm not one to lie. Nor do I kill without reason." + }, + "wu_field_marshal_duda": { + "name": "Field Marshal Duda", + "deck": "witcher_universe", + "row": "siege", + "strength": "1", + "ability": "morale", + "filename": "field_marshal_duda", + "count": "1", + "quote": "Brilliants! Brilliants!" + } +}; + +var ext_to_cards = { + "to_anna_henrietta_duchess": { + "name": "Anna Henrietta: Lady Duchess", + "deck": "toussaint", + "row": "leader", + "strength": "", + "ability": "anna_henrietta_duchess", + "filename": "anna_henrietta_duchess", + "count": "1", + "quote": "Fair knights I salute you." + }, + "to_dun_tynne_infantry": { + "name": "Dun Tynne Infantry", + "deck": "toussaint", + "row": "close", + "strength": "4", + "ability": "", + "filename": "dun_tynne_infantry", + "count": "1", + "quote": "If you've blood in your veins, come collect what's deserved." + }, + "to_champion": { + "name": "Toussaint Champion", + "deck": "toussaint", + "row": "close", + "strength": "9", + "ability": "", + "filename": "champion", + "count": "1", + "quote": "With a thunderous roar, hooves pound the ground!" + }, + "to_panther_1": { + "name": "Panthers", + "id": 1, + "deck": "toussaint", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "panther_1", + "count": "1", + "target": "to_panthers", + "quote": "Pussy cat, pussy cat, what did you do there? Run fool, that's not a cat but a panther!" + }, + "to_panther_2": { + "name": "Panthers", + "id": 2, + "deck": "toussaint", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "panther_2", + "count": "1", + "target": "to_panthers", + "quote": "Pussy cat, pussy cat, what did you do there? Run fool, that's not a cat but a panther!" + }, + "to_panther_3": { + "name": "Panthers", + "id": 3, + "deck": "toussaint", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "panther_3", + "count": "1", + "target": "to_panthers", + "quote": "Pussy cat, pussy cat, what did you do there? Run fool, that's not a cat but a panther!" + }, + "to_knight_errant_1": { + "name": "Knights-Errant", + "id": 1, + "deck": "toussaint", + "row": "agile", + "strength": "5", + "ability": "bond", + "filename": "knight_errant_1", + "count": "1", + "target": "to_knight_errant", + "quote": "Abandon the path of shame and we will spare you." + }, + "to_knight_errant_2": { + "name": "Knights-Errant", + "id": 2, + "deck": "toussaint", + "row": "agile", + "strength": "5", + "ability": "bond", + "filename": "knight_errant_2", + "count": "1", + "target": "to_knight_errant", + "quote": "Abandon the path of shame and we will spare you." + }, + "to_knight_errant_3": { + "name": "Knights-Errant", + "id": 3, + "deck": "toussaint", + "row": "agile", + "strength": "5", + "ability": "bond", + "filename": "knight_errant_3", + "count": "1", + "target": "to_knight_errant", + "quote": "Abandon the path of shame and we will spare you." + }, + "to_damien_tour": { + "name": "Damien de la Tour", + "deck": "toussaint", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "damien_tour", + "count": "1", + "quote": "I served Beauclair well. At least... I hope I did." + }, + "to_gregoire_gorgon": { + "name": "Gregoire de Gorgon", + "deck": "toussaint", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "gregoire_gorgon", + "count": "1", + "quote": "Gregoire? That mountain o' muscle wrapped in armor? Course, I 'eard of 'im! Who hasn't?" + }, + "to_lady_lake": { + "name": "Lade of the Lake", + "deck": "toussaint", + "row": "siege", + "strength": "5", + "ability": "medic", + "filename": "lady_lake", + "count": "1", + "quote": "Take this sword as a sign of my favor. For centuries it lay in these depths, waiting... for you." + }, + "to_jousting_champion": { + "name": "Jousting Champioin", + "deck": "toussaint", + "row": "close", + "strength": "8", + "ability": "morale", + "filename": "jousting_champion", + "count": "1", + "quote": "The flower of chivalry, at your command!" + }, + "to_guillaume": { + "name": "Guillaume de Launfal", + "deck": "toussaint", + "row": "close", + "strength": "3", + "ability": "", + "filename": "guillaume", + "count": "1", + "quote": "Guillaume was the very model of a knight-errant - the placard boy for Toussaint." + }, + "to_artorius_vigo": { + "name": "Artorius Vigo", + "deck": "toussaint", + "row": "ranged", + "strength": "10", + "ability": "hero medic", + "filename": "artorius_vigo", + "count": "1", + "quote": "It is said he created an illusion so realistic that he began to believe it himself..." + }, + "to_fringilla_vigo": { + "name": "Fringilla Vigo", + "deck": "toussaint", + "row": "ranged", + "strength": "10", + "ability": "hero", + "filename": "fringilla_vigo", + "count": "1", + "quote": "Magic is the highest good. It transcends all borders and divisions." + }, + "to_beauclair_cavalry_1": { + "name": "Beauclair Knight", + "id": 1, + "deck": "toussaint", + "row": "close", + "strength": "7", + "ability": "bond", + "filename": "beauclair_cavalry_1", + "count": "1", + "target": "to_beauclair_cavalry", + "quote": "I swear upon the heron you will pay with your own blood." + }, + "to_beauclair_cavalry_2": { + "name": "Beauclair Knight", + "id": 2, + "deck": "toussaint", + "row": "close", + "strength": "7", + "ability": "bond", + "filename": "beauclair_cavalry_2", + "count": "1", + "target": "to_beauclair_cavalry", + "quote": "I swear upon the heron you will pay with your own blood." + }, + "to_milton": { + "name": "Milton de Peyrac-Peyran", + "id": 1, + "deck": "toussaint", + "row": "close", + "strength": "5", + "ability": "muster", + "filename": "milton", + "count": "1", + "target": "to_milton_palmerin", + "quote": "Glinting under the rays of the Beauclair sun, there was no mistaking this knight-errant who bore the head of a great, white bull on his shield." + }, + "to_palmerin": { + "name": "Palmerin de Launfal", + "id": 2, + "deck": "toussaint", + "row": "close", + "strength": "5", + "ability": "muster", + "filename": "palmerin", + "count": "1", + "target": "to_milton_palmerin", + "quote": "Rumor had it the esteemed baron Palmerin de Launfal had fallen into a profane affair with a succubus." + }, + "to_vivienne": { + "name": "Vivienne de Tabris", + "deck": "toussaint", + "row": "ranged", + "strength": "2", + "ability": "avenger", + "filename": "vivienne", + "count": "1", + "target": "to_vivienne_oriole", + "quote": "Vivienne's a bit of an odd duck for a lady-in-waitin'. But by the Gods, ye can't deny her beauty an' grace!" + }, + "to_vivienne_oriole": { + "name": "Vivienne: Oriole", + "deck": "toussaint", + "row": "ranged", + "strength": "6", + "ability": "", + "filename": "vivienne_oriole", + "count": "1", + "quote": "Who'd not like to live free as a bird? Well, just ask Vivienne de Tabris." + }, + "to_syanna": { + "name": "Sylvia Anna", + "deck": "toussaint", + "row": "siege", + "strength": "2", + "ability": "hero spy", + "filename": "syanna", + "count": "1", + "quote": "Your Majesty... The princess has been touched by the curse o' the Black Sun. There's no hope, I'm afraid..." + }, + "to_fisher_king": { + "name": "Fisher King", + "deck": "toussaint", + "row": "ranged", + "strength": "4", + "ability": "", + "filename": "fisher_king", + "count": "1", + "quote": "Mhmm." + }, + "spe_toussaint_wine": { + "name": "Toussaint Wine", + "deck": "special toussaint", + "row": "", + "strength": "", + "ability": "toussaint_wine", + "filename": "toussaint_wine", + "count": "3", + "quote": "To honour our fair knights, we shall feast from eve till dawn's first light!" + }, + "to_anna_henrietta_ladyship": { + "name": "Anna Henrietta: Her Enlightened Ladyship", + "deck": "toussaint", + "row": "leader", + "strength": "", + "ability": "anna_henrietta_ladyship", + "filename": "anna_henrietta_ladyship", + "count": "1", + "quote": "Impertinence is the one thing I cannot abide." + }, + "to_protofleder": { + "name": "Protofleder", + "deck": "toussaint", + "row": "close", + "strength": "9", + "ability": "", + "filename": "protofleder", + "count": "1", + "quote": "Limited to only one region of the Continent, scholars consider them critically endangered. Gods be praised..." + }, + "to_dettlaff_higher_vampire": { + "name": "Dettlaff: Higher Vampire", + "deck": "toussaint", + "row": "agile", + "strength": "11", + "ability": "hero", + "filename": "dettlaff_higher_vampire", + "count": "1", + "quote": "In his true form, the Beast of Beauclair could cause even a witcher to quake in his boots." + }, + "to_barghest_1": { + "name": "Barghest", + "id": 1, + "deck": "toussaint", + "row": "ranged", + "strength": "5", + "ability": "muster", + "filename": "barghest_1", + "count": "1", + "target": "to_barghest", + "quote": "Some claim they're the vanguard of the Wild Hunt." + }, + "to_barghest_2": { + "name": "Barghest", + "id": 2, + "deck": "toussaint", + "row": "ranged", + "strength": "5", + "ability": "muster", + "filename": "barghest_2", + "count": "1", + "target": "to_barghest", + "quote": "Some claim they're the vanguard of the Wild Hunt." + }, + "to_barghest_3": { + "name": "Barghest", + "id": 3, + "deck": "toussaint", + "row": "ranged", + "strength": "5", + "ability": "muster", + "filename": "barghest_3", + "count": "1", + "target": "to_barghest", + "quote": "Some claim they're the vanguard of the Wild Hunt." + }, + "to_cloud_giant": { + "name": "Cloud Giant", + "deck": "toussaint", + "row": "close", + "strength": "5", + "ability": "scorch", + "filename": "cloud_giant", + "count": "1", + "quote": "Many things fall from the sky. Frogs for instance... And the Cloud Giant." + }, + "to_garkain": { + "name": "Garkain", + "deck": "toussaint", + "row": "close", + "strength": "5", + "ability": "", + "filename": "garkain", + "count": "1", + "quote": "Blood on the ceiling, entrails on the wall... Got garkain written all over it." + }, + "to_wolves_1": { + "name": "Wolves", + "id": 1, + "deck": "toussaint", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "wolves_1", + "count": "1", + "target": "to_wolves", + "quote": "We never hunt in these woods." + }, + "to_wolves_2": { + "name": "Wolves", + "id": 2, + "deck": "toussaint", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "wolves_2", + "count": "1", + "target": "to_wolves", + "quote": "We never hunt in these woods." + }, + "to_yghern": { + "name": "Yghern", + "deck": "toussaint", + "row": "agile", + "strength": "10", + "ability": "", + "filename": "yghern", + "count": "1", + "quote": "Its other name is scolopendromorph. Rarely used, as it's hard to say without spitting all over oneself." + }, + "to_unseen_elder": { + "name": "Unseen Elder", + "deck": "toussaint", + "row": "agile", + "strength": "12", + "ability": "hero", + "filename": "unseen_elder", + "count": "1", + "quote": "No one, not even among the higher vampires, knows exactly how old the Unseen Elder is." + }, + "to_alpha_garkain": { + "name": "Alpha Garkain", + "deck": "toussaint", + "row": "close", + "strength": "6", + "ability": "", + "filename": "alpha_garkain", + "count": "1", + "quote": "The vilest vampire I've ever had the misfortune to lay eyes upon." + }, + "to_archespore": { + "name": "Archespore", + "deck": "toussaint", + "row": "siege", + "strength": "5", + "ability": "scorch_c", + "filename": "archespore", + "count": "1", + "quote": "Folklore claims they sprout from soil watered with the blood of the dying." + }, + "to_dettlaff": { + "name": "Dettlaff van der Eretein", + "deck": "toussaint", + "row": "close", + "strength": "8", + "ability": "hero avenger", + "filename": "dettlaff", + "count": "1", + "target": "to_dettlaff_ghastly_beast", + "quote": "He did not love like a man, but like an animal. Madly, deeply, unconditionally. Wildly." + }, + "to_dettlaff_ghastly_beast": { + "name": "Dettlaff: Ghastly Beast", + "deck": "toussaint", + "row": "close", + "strength": "10", + "ability": "", + "filename": "dettlaff_ghastly_beast", + "count": "1", + "quote": "The gentleman suddenly turned into a ghastly beast and... tore those men to shreds." + }, + "to_bruxa_corvo_bianco": { + "name": "Bruxa of Corvo Bianco", + "deck": "toussaint", + "row": "agile", + "strength": "5", + "ability": "", + "filename": "bruxa_corvo_bianco", + "count": "1", + "quote": "The vampiress lunged in a blur, unleashing an inhuman shriek." + }, + "to_orianna": { + "name": "Orianna", + "deck": "toussaint", + "row": "ranged", + "strength": "9", + "ability": "hero", + "filename": "orianna", + "count": "1", + "quote": "Lady Orianna's been a blessin' for us... She 'elps the beggarly, supports the arts – why, she even runs a home for them poor orphans!" + }, + "to_lacerate": { + "name": "Lacerate", + "deck": "toussaint", + "row": "close", + "strength": "9", + "ability": "", + "filename": "lacerate", + "count": "1", + "quote": "A sight more horrid you've never seen… The poor soul lay shredded as the beast lapped up its blood from the ground all around." + }, + "to_fleder": { + "name": "Fleder", + "deck": "toussaint", + "row": "close", + "strength": "5", + "ability": "", + "filename": "fleder", + "count": "1", + "quote": "The children o' the night come as punishment from the gods!" + }, + "to_golyat": { + "name": "Golyat", + "deck": "toussaint", + "row": "close", + "strength": "6", + "ability": "", + "filename": "golyat", + "count": "1", + "quote": "Some claim Golyat was once a famous knight. Sadly, one day he earned the wrath of the Lady of the Lake, who turned him into a monster." + }, + "to_tufo_monster": { + "name": "The Tufo Monster", + "deck": "toussaint", + "row": "siege", + "strength": "9", + "ability": "hero", + "filename": "tufo_monster", + "count": "1", + "quote": "A cross between a mole and an armadillo with an appetite for human flesh." + }, + "to_shaelmaar": { + "name": "Shaelmaar", + "deck": "toussaint", + "row": "close", + "strength": "7", + "ability": "", + "filename": "shaelmaar", + "count": "1", + "quote": "The earth's innards are home to mighty strange and fearsome beasts." + }, + "to_anna_henrietta_grace": { + "name": "Anna Henrietta: Her Grace", + "deck": "toussaint", + "row": "leader", + "strength": "", + "ability": "anna_henrietta_grace", + "filename": "anna_henrietta_grace", + "count": "1", + "quote": "You have sworn your vows, you have readied body and soul. The time has come to test them." + }, + "to_benoit": { + "name": "Benoit", + "deck": "toussaint", + "row": "close", + "strength": "2", + "ability": "medic", + "filename": "benoit", + "count": "1", + "quote": "Aged in barrles of Beauclair oak. Hue - deep burgundy, clarity - high." + }, + "to_roderick": { + "name": "Roderick of Dun Tynne", + "deck": "toussaint", + "row": "close", + "strength": "9", + "ability": "spy", + "filename": "roderick", + "count": "1", + "quote": "Roderick lived as a recluse, avoiding society at large." + }, + "to_vampire_invasion": { + "name": "Vampire Invasion", + "deck": "toussaint", + "row": "close", + "strength": "4", + "ability": "avenger", + "filename": "vampire_invasion", + "count": "1", + "target" : "to_lacerate", + "quote": "Drinking the blood of the Continent since the Conjunction." + }, + "to_ducal_guard_1": { + "name": "Ducal Guard", + "id": 1, + "deck": "toussaint", + "row": "close", + "strength": "3", + "ability": "bond", + "filename": "ducal_guard_1", + "count": "1", + "target": "to_ducal_guard", + "quote": "Search your hearts! Do you not see that they are blackened?" + }, + "to_ducal_guard_2": { + "name": "Ducal Guard", + "id": 2, + "deck": "toussaint", + "row": "close", + "strength": "3", + "ability": "bond", + "filename": "ducal_guard_2", + "count": "1", + "target": "to_ducal_guard", + "quote": "Search your hearts! Do you not see that they are blackened?" + }, + "to_bootblack": { + "name": "Bootblack", + "deck": "toussaint", + "row": "agile", + "strength": "9", + "ability": "spy", + "filename": "bootblack", + "count": "1", + "quote": "Wouldn't be looking for work, would you? We'd make a fine duo." + }, + "to_menagerie_keeper": { + "name": "Menagerie Keeper", + "deck": "toussaint", + "row": "agile", + "strength": "2", + "ability": "scorch", + "filename": "menagerie_keeper", + "count": "1", + "quote": "If there's one thing Nilfgaardians love more than blood-soaked arena battles, it's blood-soaked arena battles with exotic beasts." + }, + "to_barnabas": { + "name": "Barnabas Basil-Foulty", + "deck": "toussaint", + "row": "ranged", + "strength": "1", + "ability": "medic", + "filename": "barnabas", + "count": "1", + "quote": "I shall serve you as majordomo of Corvo Bianco." + }, + "to_caed_myrkvid_druid_1": { + "name": "Caed Myrkvid Druid", + "id": 1, + "deck": "toussaint", + "row": "ranged", + "strength": "4", + "ability": "bond", + "filename": "caed_myrkvid_druid_1", + "count": "1", + "target": "to_caed_myrkvid_druid", + "quote": "We fled here to escape people such as you." + }, + "to_caed_myrkvid_druid_2": { + "name": "Caed Myrkvid Druid", + "id": 2, + "deck": "toussaint", + "row": "ranged", + "strength": "4", + "ability": "bond", + "filename": "caed_myrkvid_druid_2", + "count": "1", + "target": "to_caed_myrkvid_druid", + "quote": "We fled here to escape people such as you." + }, + "to_field_medic": { + "name": "Field Medic", + "deck": "toussaint", + "row": "ranged", + "strength": "2", + "ability": "bond", + "filename": "field_medic", + "count": "1", + "quote": "I'm a medic. I tend to know what I am doing when I prescribe something." + }, + "to_seditious_aristocrats": { + "name": "Seditious Aristocrats", + "deck": "toussaint", + "row": "ranged", + "strength": "8", + "ability": "spy", + "filename": "seditious_aristocrats", + "count": "1", + "quote": "They love expensive wine, horse riding, and good old backstabbing." + }, + "to_poisoner": { + "name": "Poisoner", + "deck": "toussaint", + "row": "ranged", + "strength": "3", + "ability": "scorch_c", + "filename": "poisoner", + "count": "1", + "quote": "For a courtesan, a single drop. For a rock troll, an entire bottle. And for Nordling scum? Why waste good poison when a rusty dagger will do?" + }, + "to_wicked_witch": { + "name": "Wicked Witch", + "deck": "toussaint", + "row": "ranged", + "strength": "1", + "ability": "scorch_c", + "filename": "wicked_witch", + "count": "1", + "quote": "A bit of butter, a bit of spice, and you'll make a tasty morsel." + }, + "to_alchemist": { + "name": "Alchemist", + "deck": "toussaint", + "row": "siege", + "strength": "3", + "ability": "scorch", + "filename": "alchemist", + "count": "1", + "quote": "Two ounces of calcium equum, one ounce of rubedo..." + }, + "to_duchess_informant": { + "name": "Duchess Informant", + "deck": "toussaint", + "row": "siege", + "strength": "7", + "ability": "spy", + "filename": "duchess_informant", + "count": "1", + "quote": "Anna Henrietta wakes every morn to the tune of her songbirds." + } +}; + +var ext_lr_cards = { + "spe_lyria_rivia_morale": { + "name": "Lyria & Rivia: Morale Boost", + "deck": "special lyria_rivia", + "row": "", + "strength": "", + "ability": "morale", + "filename": "lyria_rivia_morale", + "count": "0", + "quote": "For Lyria and Rivia!" + }, + "lr_meve_princess": { + "name": "Meve: The Princess of Lyria", + "deck": "lyria_rivia", + "row": "leader", + "strength": "", + "ability": "meve_princess", + "filename": "meve_princess", + "count": "1", + "quote": "The Gods watch over us, we'll come through the fray unharmed." + }, + "lr_rivian_mauler": { + "name": "Rivia Mauler", + "deck": "lyria_rivia", + "row": "close", + "strength": "7", + "ability": "", + "filename": "rivian_mauler", + "count": "1", + "quote": "Ugh, these guys can be a real headache." + }, + "lr_grey_rider": { + "name": "Grey Rider", + "deck": "lyria_rivia", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "grey_rider", + "count": "2", + "target": "lr_grey_rider", + "quote": "This is not steel and blood that win wars, but information." + }, + "lr_prince_anseis": { + "name": "Prince Anséis", + "deck": "lyria_rivia", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "prince_anseis", + "count": "1", + "quote": "Your presence at this tourney is an affront to my honor!" + }, + "lr_royal_guard": { + "name": "Royal Guard", + "deck": "lyria_rivia", + "row": "close", + "strength": "9", + "ability": "", + "filename": "royal_guard", + "count": "1", + "quote": "Each must serve with unconditionnal loyalty and possess a devilishly handsome jawline." + }, + "lr_landsknecht": { + "name": "Lyrian Landsknecht", + "deck": "lyria_rivia", + "row": "close", + "strength": "3", + "ability": "muster", + "filename": "landsknecht", + "count": "3", + "target": "lr_landsknecht", + "quote": "Best not laugh at their silly-arse hats. Believe me." + }, + "lr_knighthood": { + "name": "Knighthood", + "deck": "lyria_rivia", + "row": "close", + "strength": "10", + "ability": "", + "filename": "knighthood", + "count": "1", + "quote": "Kneel an everyman, arise a knight." + }, + "lr_reynard_odo": { + "name": "Reynard Odo", + "deck": "lyria_rivia", + "row": "close", + "strength": "10", + "ability": "hero morale", + "filename": "reynard_odo", + "count": "1", + "quote": "Under your husband I served ten years, under you another eight." + }, + "lr_war_wagon": { + "name": "War Wagon", + "deck": "lyria_rivia", + "row": "ranged", + "strength": "4", + "ability": "avenger", + "filename": "war_wagon", + "count": "1", + "target": "lr_wagenburg", + "quote": "Hay out, archersin! Go, go go!" + }, + "lr_wagenburg": { + "name": "Wagenburg", + "deck": "lyria_rivia", + "row": "ranged", + "strength": "3", + "ability": "muster", + "filename": "wagenburg", + "count": "3", + "target": "lr_wagenburg_muster", + "quote": "Dh'oine can turn anything into a weapon. Even a simple wagon..." + }, + "lr_gascon": { + "name": "Gascon", + "deck": "lyria_rivia", + "row": "ranged", + "strength": "10", + "ability": "hero", + "filename": "gascon", + "count": "1", + "quote": "I'm doing what I used to do and they're paying me for it!" + }, + "lr_pikeman": { + "name": "Rivian Pikeman", + "deck": "lyria_rivia", + "row": "close", + "strength": "6", + "ability": "", + "filename": "pikeman", + "count": "1", + "quote": "Get off your high horse and face me!" + }, + "lr_light_cavalry": { + "name": "Light Cavalry", + "deck": "lyria_rivia", + "row": "close", + "strength": "5", + "ability": "muster", + "filename": "light_cavalry", + "count": "2", + "target": "lr_light_cavalry", + "quote": "Stay calm, everyone. And be alert." + }, + "lr_rayla": { + "name": "Rayla", + "deck": "lyria_rivia", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "rayla", + "count": "1", + "quote": "Exceptions are a clear road to human blood spilt. All Scoia'tael must die." + }, + "lr_wagon": { + "name": "Wagon", + "deck": "lyria_rivia", + "row": "agile", + "strength": "1", + "ability": "medic", + "filename": "wagon", + "count": "1", + "quote": "The driver swore he was carrying seeds. But seeds don't clank on bumps in the road..." + }, + "lr_lyrian_cavalry": { + "name": "Lyrian Cavalry", + "deck": "lyria_rivia", + "row": "close", + "strength": "8", + "ability": "", + "filename": "lyrian_cavalry", + "count": "1", + "quote": "A horseman's worth no less than his steed. And Lyrian horses are among the Continent's best." + }, + "lr_isbel_hagge": { + "name": "Isbel of Hagge", + "deck": "lyria_rivia", + "row": "ranged", + "strength": "4", + "ability": "medic", + "filename": "isbel_hagge", + "count": "1", + "quote": "I promised I would never again use magic to harm others." + }, + "lr_hajduk": { + "name": "Lyrian Hajduk", + "deck": "lyria_rivia", + "row": "agile", + "strength": "3", + "ability": "horn", + "filename": "hajduk", + "count": "1", + "quote": "War, war... What's it bloody good for..." + }, + "spe_wyvern_shield": { + "name": "Wyvern Scale Shield", + "deck": "special lyria_rivia", + "row": "", + "strength": "", + "ability": "shield_c", + "filename": "wyvern_shield", + "count": "1", + "quote": "Stronger than your average shield and far more stylish." + }, + "spe_mantlet": { + "name": "Mantlet", + "deck": "special lyria_rivia", + "row": "", + "strength": "", + "ability": "shield_r", + "filename": "mantlet", + "count": "1", + "quote": "Something like the bastard child of a shield and a palisade." + }, + "spe_watchman": { + "name": "Watchman", + "deck": "special lyria_rivia", + "row": "", + "strength": "", + "ability": "shield_r", + "filename": "watchman", + "count": "1", + "quote": "I can't even see over this bloody thing." + }, + "spe_garrison": { + "name": "Garrison", + "deck": "special lyria_rivia", + "row": "", + "strength": "", + "ability": "shield_s", + "filename": "garrison", + "count": "1", + "quote": "Knock, knock… anybody home?" + }, + "lr_meve_white_queen": { + "name": "Meve: The White Queen", + "deck": "lyria_rivia", + "row": "leader", + "strength": "", + "ability": "meve_white_queen", + "filename": "meve_white_queen", + "count": "1", + "quote": "I've made my choice. Time you made yours." + }, + "lr_piercing_missile": { + "name": "Piercing Missile", + "deck": "lyria_rivia", + "row": "ranged", + "strength": "3", + "ability": "scorch_c", + "filename": "piercing_missile", + "count": "1", + "quote": "There's no armor that can't be pierced." + }, + "lr_eavesdrop": { + "name": "Eavesdrop", + "deck": "lyria_rivia", + "row": "ranged", + "strength": "6", + "ability": "spy", + "filename": "eavesdrop", + "count": "1", + "quote": "There are always more ears in the room than those you can count." + }, + "lr_trebuchet": { + "name": "Lyrian Trebuchet", + "deck": "lyria_rivia", + "row": "siege", + "strength": "9", + "ability": "", + "filename": "trebuchet", + "count": "1", + "quote": "Feel that? The earth trembles each time Big Bertha loose a stone." + }, + "lr_arbalest": { + "name": "Lyrian Arbalest", + "deck": "lyria_rivia", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "arbalest", + "count": "3", + "target": "lr_arbalest", + "quote": "I can find the bull's-eye from a hundred paces! Perhaps not with my first shot, mind you..." + }, + "lr_spellweaver": { + "name": "Spellweaver", + "deck": "lyria_rivia", + "row": "ranged", + "strength": "7", + "ability": "", + "filename": "spellweaver", + "count": "1", + "quote": "Reality is so terribly tedious..." + }, + "lr_forager": { + "name": "Forager", + "deck": "lyria_rivia", + "row": "ranged", + "strength": "5", + "ability": "", + "filename": "forager", + "count": "1", + "quote": "If you'll not be needin' it, I'm willin' to take it off your hands..." + }, + "lr_sapper": { + "name": "Rivian Sapper", + "deck": "lyria_rivia", + "row": "ranged", + "strength": "4", + "ability": "scorch", + "filename": "sapper", + "count": "1", + "quote": "First Nilfgaardian who tried to slip 'cross our line was a right sneaky bastard." + }, + "lr_villem": { + "name": "Prince Villem", + "deck": "lyria_rivia", + "row": "siege", + "strength": "8", + "ability": "hero", + "filename": "villem", + "count": "1", + "quote": "The boy's not fit to wear the crown. Hasn't sufficient wit nor valor." + }, + "lr_scout": { + "name": "Scout", + "deck": "lyria_rivia", + "row": "siege", + "strength": "5", + "ability": "spy", + "filename": "scout", + "count": "1", + "quote": "If our scouts don't come back, we turn around." + }, + "lr_winch": { + "name": "Winch", + "deck": "lyria_rivia", + "row": "siege", + "strength": "5", + "ability": "morale", + "filename": "winch", + "count": "1", + "quote": "It's a winch. Not much to flap your jaw about." + }, + "lr_banner": { + "name": "Lyrian Banner", + "deck": "lyria_rivia", + "row": "siege", + "strength": "2", + "ability": "horn", + "filename": "banner", + "count": "1", + "quote": "Our emblem? A black eagle. Fate of our foes? Pure misery." + }, + "lr_scytheman_1": { + "name": "Lyrian Scytheman", + "deck": "lyria_rivia", + "row": "close", + "strength": "3", + "ability": "decoy", + "filename": "scytheman", + "count": "1", + "quote": "Our folk they feed, and our foes they bleed." + }, + "lr_scytheman_2": { + "name": "Lyrian Scytheman", + "deck": "lyria_rivia", + "row": "ranged", + "strength": "3", + "ability": "decoy", + "filename": "scytheman", + "count": "1", + "quote": "Our folk they feed, and our foes they bleed." + }, + "lr_scytheman_3": { + "name": "Lyrian Scytheman", + "deck": "lyria_rivia", + "row": "siege", + "strength": "3", + "ability": "decoy", + "filename": "scytheman", + "count": "1", + "quote": "Our folk they feed, and our foes they bleed." + }, + "lr_caldwell": { + "name": "Count Caldwell", + "deck": "lyria_rivia", + "row": "ranged", + "strength": "9", + "ability": "hero spy", + "filename": "caldwell", + "count": "1", + "quote": "Your Majesty... For the queen to question commoners, why, it's simply not proper..." + }, + "lr_physician": { + "name": "Physician", + "deck": "lyria_rivia", + "row": "siege", + "strength": "3", + "ability": "medic", + "filename": "physician", + "count": "1", + "quote": "Do not twitch, lie still..." + }, + "lr_pyrokinesis": { + "name": "Pyrokinesis", + "deck": "lyria_rivia", + "row": "ranged", + "strength": "8", + "ability": "", + "filename": "pyrokinesis", + "count": "1", + "quote": "I really hope that's boot leather I smell burning..." + }, + "lr_carroballista": { + "name": "Carroballista", + "deck": "lyria_rivia", + "row": "siege", + "strength": "10", + "ability": "", + "filename": "carroballista", + "count": "1", + "quote": "This ballista's on the wagon." + }, + "lr_artificer": { + "name": "Artificer", + "deck": "lyria_rivia", + "row": "ranged", + "strength": "2", + "ability": "medic", + "filename": "artificer", + "count": "1", + "quote": "What shall I call it? Perhaps Andúril..." + }, + "lr_siege": { + "name": "Siege", + "deck": "lyria_rivia", + "row": "siege", + "strength": "6", + "ability": "scorch", + "filename": "siege", + "count": "1", + "quote": "There's no fortress that can't be taken. There are just fortresses not worth taking." + }, + "lr_onager": { + "name": "Rivian Onager", + "deck": "lyria_rivia", + "row": "siege", + "strength": "6", + "ability": "", + "filename": "onager", + "count": "1", + "quote": "For Riviaaa!" + }, + "lr_blacksmith": { + "name": "Lyrian Blacksmith", + "deck": "lyria_rivia", + "row": "close", + "strength": "4", + "ability": "morale", + "filename": "blacksmith", + "count": "1", + "quote": "Somethin' from nothin'... my speciality." + }, + "lr_peasant_militia": { + "name": "Peasant Militia", + "deck": "lyria_rivia", + "row": "close", + "strength": "4", + "ability": "", + "filename": "peasant_militia", + "count": "1", + "quote": "We's the militia. We keep the peace." + } +}; + +var ext_sy_cards = { + "sy_carlo_varese": { + "name": "Carlo Varese: Cleaver", + "deck": "syndicate", + "row": "leader", + "strength": "", + "ability": "carlo_varese", + "filename": "carlo_varese", + "count": "1", + "quote": "Me hogs willnae go hungry th' day thanks to ye." + }, + "sy_francis_bedlam": { + "name": "Francis Bedlam: King of Beggars", + "deck": "syndicate", + "row": "leader", + "strength": "", + "ability": "francis_bedlam", + "filename": "francis_bedlam", + "count": "1", + "quote": "You say tribute, I say taxes." + }, + "sy_cyprian_wiley": { + "name": "Cyprian Wiley: Whoreson Junior", + "deck": "syndicate", + "row": "leader", + "strength": "", + "ability": "cyprian_wiley", + "filename": "cyprian_wiley", + "count": "1", + "quote": "A war with Whoreson will see Novigrad's gutters run red with blood." + }, + "sy_gudrun_bjornsdottir": { + "name": "Gudrun Bjornsdottir: Pirate Queen", + "deck": "syndicate", + "row": "leader", + "strength": "", + "ability": "gudrun_bjornsdottir", + "filename": "gudrun_bjornsdottir", + "count": "1", + "quote": "She found her freedom among blue waters and salty wind." + }, + "sy_cyrus_hemmelfart": { + "name": "Cyrus Hemmelfart: Hierarch of Novigrad", + "deck": "syndicate", + "row": "leader", + "strength": "", + "ability": "cyrus_hemmelfart", + "filename": "cyrus_hemmelfart", + "count": "1", + "quote": "Beneath all that lust, greed, and vanity, stands an honorable man." + }, + "sy_sigi_reuven": { + "name": "Sigi Reuven", + "deck": "syndicate", + "row": "close", + "strength": "8", + "ability": "hero morale", + "filename": "sigi_reuven", + "count": "0", + "quote": "You sure he don't look the least bit familar...?" + }, + "sy_flyndr_crew": { + "name": "Flyndr' Crew", + "deck": "syndicate", + "row": "close", + "strength": "4", + "ability": "horn", + "filename": "flyndr_crew", + "count": "0", + "quote": "Wretches and thieves drunk on grog, bloodshed and booty - could you ever hope for a better crew?" + }, + "spe_dimeritium_shackles": { + "name": "Dimeritium Shackles", + "deck": "special syndicate", + "row": "", + "strength": "", + "ability": "lock", + "filename": "dimeritium_shackles", + "count": "3", + "quote": "Terranova cried out, lurched, bent backwards, bowed forward, then retched and groaned. It was clear of what his manacles were made." + }, + "sy_flaming_rose_footman": { + "name": "Flaming Rose Footman", + "deck": "syndicate", + "row": "close", + "strength": "6", + "ability": "", + "filename": "flaming_rose_footman", + "count": "1", + "quote": "Anyone can join The Order – a knight, a peasant, even a witcher. " + }, + "sy_bare_knuckle_brawler": { + "name": "Bare Knuckle Brawler", + "deck": "syndicate", + "row": "close", + "strength": "8", + "ability": "hero", + "filename": "bare_knuckle_brawler", + "count": "1", + "quote": "Is tha' all that's left of 'im? Think I'm goin' tae boak..." + }, + "sy_eibhear_hattori": { + "name": "Eibhear Hattori", + "deck": "syndicate", + "row": "ranged", + "strength": "2", + "ability": "medic", + "filename": "eibhear_hattori", + "count": "1", + "quote": "Only thing that can rival his swords? His dumplings." + }, + "sy_witch_hunter": { + "name": "Witch Hunter", + "deck": "syndicate", + "row": "close", + "strength": "2", + "ability": "witch_hunt", + "filename": "witch_hunter", + "count": "1", + "quote": "Long coats, wide-brimmed hats, and crooked grins – witch hunters are hard to miss." + }, + "sy_witch_hunter_executioner": { + "name": "Witch Hunter Executioner", + "deck": "syndicate", + "row": "close", + "strength": "3", + "ability": "witch_hunt", + "filename": "witch_hunter_executioner", + "count": "1", + "quote": "It'd be a right shame if I cut any of your beautiful hair." + }, + "sy_casino_bouncers": { + "name": "Casino Bouncers", + "deck": "syndicate", + "row": "close", + "strength": "7", + "ability": "", + "filename": "casino_bouncers", + "count": "1", + "quote": "Junior said our nasty mugs was frightenin' off all the coin. Don't rightly see 'ow this helps any..." + }, + "sy_caleb_menge": { + "name": "Caleb Menge", + "deck": "syndicate", + "row": "agile", + "strength": "7", + "ability": "hero witch_hunt", + "filename": "caleb_menge", + "count": "1", + "quote": "Deceivers, heretics, witches! They flood our city, corrupt our virtue, and threaten our very way of life!" + }, + "sy_greater_brothers": { + "name": "Greater Brothers", + "deck": "syndicate", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "greater_brothers", + "count": "1", + "quote": "A battering ram? No need, we'll handle it another way." + }, + "sy_eternal_fire_inquisitor": { + "name": "Eternal Fire Inquisitor", + "deck": "syndicate", + "row": "agile", + "strength": "2", + "ability": "witch_hunt", + "filename": "eternal_fire_inquisitor", + "count": "1", + "quote": "The burning light of the Eternal Fire reveals all!" + }, + "sy_eternal_fire_priest_1": { + "name": "Eternal Fire Priest", + "id": 1, + "deck": "syndicate", + "row": "ranged", + "strength": "3", + "ability": "muster", + "filename": "eternal_fire_priest_1", + "count": "1", + "target": "sy_eternal_fire_priest", + "quote": "Closer, my sheep, gather closer. May the Eternal Fire warm your souls!" + }, + "sy_eternal_fire_priest_2": { + "name": "Eternal Fire Priest", + "id": 2, + "deck": "syndicate", + "row": "ranged", + "strength": "3", + "ability": "muster", + "filename": "eternal_fire_priest_2", + "count": "1", + "target": "sy_eternal_fire_priest", + "quote": "Closer, my sheep, gather closer. May the Eternal Fire warm your souls!" + }, + "sy_eternal_fire_priest_3": { + "name": "Eternal Fire Priest", + "id": 3, + "deck": "syndicate", + "row": "ranged", + "strength": "3", + "ability": "muster", + "filename": "eternal_fire_priest_3", + "count": "1", + "target": "sy_eternal_fire_priest", + "quote": "Closer, my sheep, gather closer. May the Eternal Fire warm your souls!" + }, + "sy_roderick_wett": { + "name": "Roderick de Wett", + "deck": "syndicate", + "row": "close", + "strength": "7", + "ability": "", + "filename": "roderick_wett", + "count": "1", + "quote": "Count de Wett is exceptionally loathsome and arrogant, but at least he enjoys a little dice poker on the side." + }, + "sy_ulrich": { + "name": "Ulrich", + "deck": "syndicate", + "row": "agile", + "strength": "8", + "ability": "", + "filename": "ulrich", + "count": "1", + "quote": "When the Order was disbanded, those who didn't join the witch hunters formed the Fallen Knights, of which Ulrich became the Grand Master." + }, + "sy_inquisitional_pyres": { + "name": "Inquisitional Pyres", + "deck": "syndicate", + "row": "agile", + "strength": "4", + "ability": "witch_hunt", + "filename": "inquisitional_pyres", + "count": "1", + "quote": "Fire cleanses." + }, + "sy_imke": { + "name": "Imke", + "deck": "syndicate", + "row": "ranged", + "strength": "5", + "ability": "spy", + "filename": "imke", + "count": "1", + "quote": "No sooner had she caught Gudrun's attention than sought to exploit it." + }, + "sy_professor": { + "name": "Professor", + "deck": "syndicate", + "row": "ranged", + "strength": "8", + "ability": "hero", + "filename": "professor", + "count": "1", + "quote": "I fear our conventicle may end disastrously for you." + }, + "sy_salamandra_assassin": { + "name": "Salamandra Assassin", + "deck": "syndicate", + "row": "ranged", + "strength": "5", + "ability": "scorch_c", + "filename": "salamandra_assassin", + "count": "1", + "quote": "A name and bag full of gold. That's all I need." + }, + "sy_salamandra_assassin_2": { + "name": "Salamandra Assassin", + "deck": "syndicate", + "row": "ranged", + "strength": "5", + "ability": "scorch_c", + "filename": "salamandra_assassin_2", + "count": "1", + "quote": "A name and bag full of gold. That's all I need." + }, + "sy_walter_veritas": { + "name": "Walter Veritas", + "deck": "syndicate", + "row": "ranged", + "strength": "7", + "ability": "spy", + "filename": "walter_veritas", + "count": "1", + "quote": "In a city that feeds on lies, truth can be a weapon." + }, + "sy_passiflora": { + "name": "Passiflora", + "deck": "syndicate", + "row": "ranged", + "strength": "3", + "ability": "horn", + "filename": "passiflora", + "count": "1", + "quote": "More pilgrims come here than to the Temple of the Eternal Fire..." + }, + "sy_fence": { + "name": "Fence", + "deck": "syndicate", + "row": "ranged", + "strength": "5", + "ability": "", + "filename": "fence", + "count": "1", + "quote": "I prefer the term curator." + }, + "sy_sly_seductress": { + "name": "Sly Seductress", + "deck": "syndicate", + "row": "ranged", + "strength": "8", + "ability": "spy", + "filename": "sly_seductress", + "count": "1", + "quote": "The sweeter her words, the more bitter your losses." + }, + "sy_azar_javed": { + "name": "Azar Javed: Renegade", + "deck": "syndicate", + "row": "leader", + "strength": "", + "ability": "azar_javed", + "filename": "azar_javed", + "count": "1", + "quote": "The sorcerer not only deftly manipulates the power of fire, it can be said that fire has become a part of his very being." + }, + "sy_fisstech_trafficker": { + "name": "Fisstech Trafficker", + "deck": "syndicate", + "row": "ranged", + "strength": "2", + "ability": "avenger", + "filename": "fisstech_trafficker", + "count": "1", + "target": "sy_fisstech", + "quote": "Addictive? Why, not at all! I've quit several times before!" + }, + "sy_fisstech": { + "name": "Fisstech", + "deck": "syndicate", + "row": "siege", + "strength": "8", + "ability": "spy", + "filename": "fisstech", + "count": "1", + "target": "sy_fisstech", + "quote": "Large pupils, chattering teeth, a mad cackle... Aye, that's fisstech for ye." + }, + "sy_savolla": { + "name": "Savolla", + "deck": "syndicate", + "row": "siege", + "strength": "6", + "ability": "hero scorch", + "filename": "savolla", + "count": "1", + "quote": "Witcher mutagens are a forgotten treasure. It's time the world learned of their potential." + }, + "sy_madame_luiza": { + "name": "Madame Luiza", + "deck": "syndicate", + "row": "siege", + "strength": "8", + "ability": "hero", + "filename": "madame_luiza", + "count": "1", + "quote": "We've bedded more men than all Redania's army barracks combined." + }, + "sy_saul_navarette": { + "name": "Saul de Navarette", + "deck": "syndicate", + "row": "siege", + "strength": "5", + "ability": "", + "filename": "saul_navarette", + "count": "1", + "quote": "A connoisseur with bottomless pockets and a soul black as tar." + }, + "sy_cleaver_gang_1": { + "name": "Cleaver's Gang", + "id": 1, + "deck": "syndicate", + "row": "agile", + "strength": "3", + "ability": "bond", + "filename": "cleaver_gang_1", + "count": "1", + "target": "sy_cleaver_gang", + "quote": "With both arms tied behind me back, recall ye said. So feel free to start kickin' me in the arse when the mood strikes ye." + }, + "sy_cleaver_gang_2": { + "name": "Cleaver's Gang", + "id": 2, + "deck": "syndicate", + "row": "agile", + "strength": "3", + "ability": "bond", + "filename": "cleaver_gang_2", + "count": "1", + "target": "sy_cleaver_gang", + "quote": "Frilly frock or Mahakam steel breastplate – wouldn't have mattered." + }, + "sy_cleaver_gang_3": { + "name": "Cleaver's Gang", + "id": 3, + "deck": "syndicate", + "row": "agile", + "strength": "3", + "ability": "bond", + "filename": "cleaver_gang_3", + "count": "1", + "target": "sy_cleaver_gang", + "quote": "Those who try to cheat Cleaver are in for a rude awakening... And a rough landing." + }, + "sy_cleaver_gang_4": { + "name": "Cleaver's Gang", + "id": 4, + "deck": "syndicate", + "row": "agile", + "strength": "3", + "ability": "bond", + "filename": "cleaver_gang_4", + "count": "1", + "target": "sy_cleaver_gang", + "quote": "Nae need to be stingy, pal. There's plenty to go 'round. " + }, + "sy_mutant_killer": { + "name": "Mutant Killer", + "deck": "syndicate", + "row": "ranged", + "strength": "7", + "ability": "", + "filename": "mutant_killer", + "count": "1", + "quote": "You have to keep him on a leash, muzzled and with blinders on, otherwise it'll be trouble." + }, + "sy_moreelse": { + "name": "Moreelse", + "deck": "syndicate", + "row": "ranged", + "strength": "7", + "ability": "", + "filename": "moreelse", + "count": "1", + "quote": "Some witch hunters truly believed the eradication of mages and sorceresses would make the world a better place. Some did not require such justification." + }, + "sy_graden": { + "name": "Graden", + "deck": "syndicate", + "row": "ranged", + "strength": "6", + "ability": "morale", + "filename": "graden", + "count": "1", + "quote": "Initially, we burned any tomes on black magic we found.Recently we decided it might be wise to read them first." + }, + "sy_robber_1": { + "name": "Robber", + "id": 1, + "deck": "syndicate", + "row": "ranged", + "strength": "4", + "ability": "bond", + "filename": "robber_1", + "count": "1", + "target": "sy_robber", + "quote": "I-I already gave ye all me coin!" + }, + "sy_robber_2": { + "name": "Robber", + "id": 2, + "deck": "syndicate", + "row": "ranged", + "strength": "4", + "ability": "bond", + "filename": "robber_2", + "count": "1", + "target": "sy_robber", + "quote": "I-I already gave ye all me coin!" + }, + "sy_robber_3": { + "name": "Robber", + "id": 3, + "deck": "syndicate", + "row": "ranged", + "strength": "4", + "ability": "bond", + "filename": "robber_3", + "count": "1", + "target": "sy_robber", + "quote": "I-I already gave ye all me coin!" + }, + "sy_robber_4": { + "name": "Robber", + "id": 4, + "deck": "syndicate", + "row": "ranged", + "strength": "4", + "ability": "bond", + "filename": "robber_4", + "count": "1", + "target": "sy_robber", + "quote": "I-I already gave ye all me coin!" + }, + "sy_dudu_biberveldt": { + "name": "Dudu Biberveldt", + "deck": "syndicate", + "row": "ranged", + "strength": "1", + "ability": "spy", + "filename": "dudu_biberveldt", + "count": "1", + "quote": "A mimic, among the many other names for his sort: changelings, doublings, vexlings… or dopplers." + }, + "sy_tamara_strenger": { + "name": "Tamara Strenger", + "deck": "syndicate", + "row": "siege", + "strength": "5", + "ability": "", + "filename": "tamara_strenger", + "count": "1", + "quote": "Once the heat of the Fire has set your heart aflame, it gives you strength and leads you down the path of truth for the rest of your life." + }, + "sy_nathaniel_pastodi": { + "name": "Nathaniel Pastodi", + "deck": "syndicate", + "row": "siege", + "strength": "6", + "ability": "", + "filename": "nathaniel_pastodi", + "count": "1", + "quote": "Novigrad – where the impossible becomes possible. A professional torturer turned reverend, for instance." + }, + "sy_jacques_aldersberg": { + "name": "Jacques de Aldersberg", + "deck": "syndicate", + "row": "siege", + "strength": "10", + "ability": "hero", + "filename": "jacques_aldersberg", + "count": "1", + "quote": "Knowledge is my burden. Only I can prevent a calamity." + }, + "sy_jacques_aldersberg": { + "name": "Jacques de Aldersberg", + "deck": "syndicate", + "row": "siege", + "strength": "10", + "ability": "hero", + "filename": "jacques_aldersberg", + "count": "1", + "quote": "Knowledge is my burden. Only I can prevent a calamity." + }, + "sy_igor_hook": { + "name": "Igor the Hook", + "deck": "syndicate", + "row": "siege", + "strength": "10", + "ability": "hero", + "filename": "igor_hook", + "count": "1", + "quote": "In the left corner, a bloodthirsty shaelmaar, and in the right co--oh bollocks... Fight's over, hold your bets!" + }, + "sy_fallen_rayla": { + "name": "Fallen Rayla", + "deck": "syndicate", + "row": "siege", + "strength": "10", + "ability": "hero", + "filename": "fallen_rayla", + "count": "1", + "quote": "Slain by the arrows of those she had hunted. Or so many thought. The Salamandra had different plans for her." + }, + "sy_sausage_maker": { + "name": "Sausage Maker", + "deck": "syndicate", + "row": "close", + "strength": "5", + "ability": "morale", + "filename": "sausage_maker", + "count": "1", + "quote": "Body disposal and sausage makin', that's what I do." + }, + "sy_octavia_hale": { + "name": "Vigilantes: Octavia Hale", + "id": 1, + "deck": "syndicate", + "row": "siege", + "strength": "8", + "ability": "hero muster", + "filename": "octavia_hale", + "count": "1", + "target": "sy_hale_brothers", + "quote": "Woe to all those who find themselves on the wrong side of Octavia Hale, the self-proclaimed world-renowned finder⁠—and punisher⁠." + }, + "sy_fabian_hale": { + "name": "Vigilantes: Fabian Hale", + "id": 2, + "deck": "syndicate", + "row": "ranged", + "strength": "6", + "ability": "", + "filename": "fabian_hale", + "count": "1", + "target": "sy_hale_brothers", + "quote": "Fabian takes great pride in his work, with each “victory” etched upon his skin as a permanent reminder of memories most pleasant." + }, + "sy_ignatius_hale": { + "name": "Vigilantes: Ignatius Hale", + "id": 3, + "deck": "syndicate", + "row": "close", + "strength": "6", + "ability": "", + "filename": "ignatius_hale", + "count": "1", + "target": "sy_hale_brothers", + "quote": "He’s a good boy." + }, + "sy_gellert_bleinheim": { + "name": "Bleinheim Brothers: Gellert", + "id": 1, + "deck": "syndicate", + "row": "ranged", + "strength": "7", + "ability": "bond", + "filename": "gellert_bleinheim", + "count": "1", + "target": "sy_bleinheim_brothers", + "quote": "How's my brother doing in the woods, I wonder..." + }, + "sy_roland_bleinheim": { + "name": "Bleinheim Brothers: Roland", + "id": 1, + "deck": "syndicate", + "row": "ranged", + "strength": "7", + "ability": "bond", + "filename": "roland_bleinheim", + "count": "1", + "target": "sy_bleinheim_brothers", + "quote": "How's my brother doing in the sewers, I wonder..." + }, + "sy_caesar_bilzen": { + "name": "Caesar Bilzen", + "deck": "syndicate", + "row": "ranged", + "strength": "3", + "ability": "morale", + "filename": "caesar_bilzen", + "count": "1", + "quote": "Avid angler, meticulous collector, and a real piece of work." + }, + "sy_rico_meiersdorf": { + "name": "Rico Meiersdorf", + "deck": "syndicate", + "row": "agile", + "strength": "7", + "ability": "spy", + "filename": "rico_meiersdorf", + "count": "1", + "quote": "I never did much like bees." + }, + "sy_cleric_flaming_rose": { + "name": "Cleric of the Flaming Rose", + "id": 1, + "deck": "syndicate", + "row": "ranged", + "strength": "5", + "ability": "muster", + "filename": "cleric_flaming_rose", + "count": "1", + "target": "sy_eternal_fire_disciple", + "quote": "We have two eyes, two ears, but only one tongue, so that we would look and listen twice more than we speak. " + }, + "sy_eternal_fire_disciple": { + "name": "Eternal Fire Disciple", + "id": 2, + "deck": "syndicate", + "row": "ranged", + "strength": "3", + "ability": "", + "filename": "eternal_fire_disciple", + "count": "2", + "target": "sy_eternal_fire_disciple", + "quote": "Look into your hearts, dear brethen. Does a contempt for injustice not burn within it?" + }, + "sy_tidecloack_ransacker": { + "name": "Tidecloack Ransacker", + "deck": "syndicate", + "row": "close", + "strength": "3", + "ability": "scorch_c", + "filename": "tidecloack_ransacker", + "count": "1", + "quote": "There's more wealth in Novigrad than in all of Skellige – and the number of poor saps to match." + }, + "sy_salamandra_lackey": { + "name": "Salamandra Lackey", + "deck": "syndicate", + "row": "close", + "strength": "5", + "ability": "", + "filename": "salamandra_lackey", + "count": "1", + "quote": "Lackeys are expected to perform their first five jobs for no pay, demonstrating their passion for the gig." + }, + "sy_mutant": { + "name": "Mutant", + "deck": "syndicate", + "row": "close", + "strength": "4", + "ability": "muster", + "filename": "mutant", + "count": "3", + "target": "sy_mutant", + "quote": "With the right tools you can shape the human body like wet clay." + }, + "sy_salamandra_mage": { + "name": "Salamandra Mage", + "deck": "syndicate", + "row": "ranged", + "strength": "6", + "ability": "", + "filename": "salamandra_mage", + "count": "1", + "quote": "Building a fire warms people for a day, but setting them on fire..." + }, + "sy_sewer_raider": { + "name": "Sewer Raider", + "deck": "syndicate", + "row": "ranged", + "strength": "8", + "ability": "spy", + "filename": "sewer_raider", + "count": "1", + "quote": "Built for movin' shite, but it moves coin just as well." + }, + "sy_inquisitor_helveed": { + "name": "Grand Inquisitor Helveed", + "deck": "syndicate", + "row": "siege", + "strength": "10", + "ability": "hero", + "filename": "inquisitor_helveed", + "count": "1", + "quote": "No sinful wretch shall escape his fate in the Fire. Of that, I will make sure." + }, + "sy_boris": { + "name": "Boris", + "deck": "syndicate", + "row": "close", + "strength": "9", + "ability": "", + "filename": "boris", + "count": "1", + "quote": "After getting a taste of human flesh, he won't eat anything else." + }, + "sy_halfling_safecracker": { + "name": "Halfling Safecracker", + "deck": "syndicate", + "row": "ranged", + "strength": "8", + "ability": "spy", + "filename": "halfling_safecracker", + "count": "1", + "quote": "With ears sharp as his, he could've been a musician. Alas, one cannot get rich as quickly from applause." + }, + "sy_hammond": { + "name": "Hammond", + "deck": "syndicate", + "row": "close", + "strength": "7", + "ability": "", + "filename": "hammond", + "count": "1", + "quote": "Once mistaken for a whale calf and nearly harpooned. He's avoided swimming ever since." + }, + "sy_sir_skewertooth": { + "name": "Sir Skewertooth", + "deck": "syndicate", + "row": "close", + "strength": "6", + "ability": "", + "filename": "sir_skewertooth", + "count": "1", + "quote": "Here he is! My knight in swining armor!" + }, + "sy_ferko": { + "name": "Ferko the Sculptor", + "deck": "syndicate", + "row": "close", + "strength": "5", + "ability": "scorch", + "filename": "ferko", + "count": "1", + "quote": "Some call it base thuggery. But me, I consider it the highest art form." + }, + "sy_hvitr_aelydia": { + "name": "Hvitr and Aelydia", + "deck": "syndicate", + "row": "close", + "strength": "8", + "ability": "hero", + "filename": "hvitr_aelydia", + "count": "1", + "quote": "Inseparable. Invincible. Irresponsible." + }, + "sy_bincy_blumerholdt": { + "name": "Bincy_Blumerholdt", + "deck": "syndicate", + "row": "close", + "strength": "7", + "ability": "spy", + "filename": "bincy_blumerholdt", + "count": "1", + "quote": "In all Novigrad, she has the hairiest feet and the stickiest hands." + }, + "sy_freak_show_1": { + "name": "Freak Show", + "id": 1, + "deck": "syndicate", + "row": "close", + "strength": "3", + "ability": "muster", + "filename": "freak_show_1", + "count": "1", + "target": "sy_freak_show", + "quote": "What do ye mean, Why? The game was beginnin' to drag!" + }, + "sy_freak_show_2": { + "name": "Freak Show", + "id": 2, + "deck": "syndicate", + "row": "close", + "strength": "3", + "ability": "muster", + "filename": "freak_show_2", + "count": "1", + "target": "sy_freak_show", + "quote": "The boss always gets to have the most fun. Truth be told, I prefer to watch anyway." + }, + "sy_freak_show_3": { + "name": "Freak Show", + "id": 3, + "deck": "syndicate", + "row": "close", + "strength": "3", + "ability": "muster", + "filename": "freak_show_3", + "count": "1", + "target": "sy_freak_show", + "quote": "A game where good aim is considered subjective." + }, + "sy_freak_show_4": { + "name": "Freak Show", + "id": 4, + "deck": "syndicate", + "row": "close", + "strength": "3", + "ability": "muster", + "filename": "freak_show_4", + "count": "1", + "target": "sy_freak_show", + "quote": "Why the long face, friend?" + }, + "sy_mutated_hound_1": { + "name": "Mutated Hounds", + "id": 1, + "deck": "syndicate", + "row": "close", + "strength": "5", + "ability": "muster", + "filename": "mutated_hound_1", + "count": "1", + "target": "sy_mutated_hound", + "quote": "We couldn't decide what to name him and it just kind of came up..." + }, + "sy_mutated_hound_2": { + "name": "Mutated Hounds", + "id": 2, + "deck": "syndicate", + "row": "close", + "strength": "5", + "ability": "muster", + "filename": "mutated_hound_2", + "count": "1", + "target": "sy_mutated_hound", + "quote": "Out of man's best friend we made his worst enemy." + }, + "sy_adriano_mink": { + "name": "Adriano the Mink", + "deck": "syndicate", + "row": "close", + "strength": "6", + "ability": "", + "filename": "adriano_mink", + "count": "1", + "quote": "Right here, beautiful. Have a sit on daddy's lap." + }, + "sy_beggar": { + "name": "Beggar", + "deck": "syndicate", + "row": "close", + "strength": "3", + "ability": "avenger", + "filename": "beggar", + "count": "1", + "target": "sy_beggar", + "quote": "Say what you will about his technique, I think he captured your good side." + }, + "sy_payroll_specialist": { + "name": "Payroll Specialist", + "deck": "syndicate", + "row": "close", + "strength": "3", + "ability": "morale", + "filename": "payroll_specialist", + "count": "1", + "quote": "Guards in Novigrad work for very little money, yet live like kings. Just another paradox of the Free City..." + }, + "sy_arena_endrega": { + "name": "Arena Endrega", + "deck": "syndicate", + "row": "close", + "strength": "6", + "ability": "", + "filename": "arena_endrega", + "count": "1", + "quote": "Strong as an ox, dumb as a box." + }, + "sy_arena_ghoul": { + "name": "Arena Ghoul", + "deck": "syndicate", + "row": "close", + "strength": "6", + "ability": "", + "filename": "arena_ghoul", + "count": "1", + "quote": "He'll be a perfect fit for your arena. Just like a mutt lickin' your plate after dinner." + }, + "sy_tatterwing": { + "name": "Tatterwing", + "deck": "syndicate", + "row": "close", + "strength": "6", + "ability": "", + "filename": "tatterwing", + "count": "1", + "quote": "She seems a bit sluggish. A few quick jabs to the ribs oughta liven her up." + }, + "sy_temple_guard": { + "name": "Temple Guard", + "deck": "syndicate", + "row": "close", + "strength": "5", + "ability": "", + "filename": "temple_guard", + "count": "1", + "quote": "Halt! Who goes there?! Firesworn or heretic?" + }, + "sy_passiflora_peaches": { + "name": "Passiflora Peaches", + "deck": "syndicate", + "row": "close", + "strength": "9", + "ability": "spy", + "filename": "passiflora_peaches", + "count": "1", + "quote": "They'll mess with your head, break your heart and empty your purse." + }, + "sy_lieutenant_herst": { + "name": "Lieutenant von Herst", + "deck": "syndicate", + "row": "close", + "strength": "5", + "ability": "", + "filename": "lieutenant_herst", + "count": "1", + "quote": "The fall of the Order wasn’t so hard for him like for the others." + }, + "sy_mutant_maker": { + "name": "Mutant Maker", + "deck": "syndicate", + "row": "close", + "strength": "5", + "ability": "avenger", + "filename": "mutant_maker", + "count": "1", + "target": "sy_failed_experiment", + "quote": "I’m a scientist, truly. I can’t help it if the Oxenfurt professors were just too narrow-sighted to appreciate my particular research methods." + }, + "sy_sea_jackal": { + "name": "Sea Jackal", + "deck": "syndicate", + "row": "close", + "strength": "5", + "ability": "", + "filename": "sea_jackal", + "count": "1", + "quote": "You ever lift rings off a body that's been left to soak for two weeks? No? Then don't complain." + }, + "sy_fallen_knight": { + "name": "Fallen Knight", + "deck": "syndicate", + "row": "close", + "strength": "6", + "ability": "", + "filename": "fallen_knight", + "count": "1", + "quote": "He abandoned the righteous fight and the flame in him has long gone." + }, + "sy_sukrus": { + "name": "Sukrus", + "deck": "syndicate", + "row": "close", + "strength": "6", + "ability": "", + "filename": "sukrus", + "count": "1", + "quote": "One of many who sought fortune in Novigrad. And one of many more who never found it. " + }, + "sy_kurt": { + "name": "Kurt", + "deck": "syndicate", + "row": "close", + "strength": "6", + "ability": "", + "filename": "kurt", + "count": "1", + "quote": "Oy, Kurt, find out what Merigold's hollerin' about, if she needs anything. A hot iron to the tongue, maybe?" + }, + "sy_whoreson_senior": { + "name": "Whoreson Senior", + "deck": "syndicate", + "row": "close", + "strength": "9", + "ability": "hero", + "filename": "whoreson_senior", + "count": "1", + "quote": "Like father, like son." + }, + "sy_lonely_champion": { + "name": "Lonely Champion", + "deck": "syndicate", + "row": "close", + "strength": "10", + "ability": "", + "filename": "lonely_champion", + "count": "1", + "quote": "So long as he continues the righteous fight, the Order and its flame endure." + }, + "sy_failed_experiment": { + "name": "Failed Experiment", + "deck": "syndicate", + "row": "close", + "strength": "8", + "ability": "", + "filename": "failed_experiment", + "count": "1", + "quote": "Even failed experiments can serve a purpose. How else would one be expected to push the boundaries of knowledge?" + }, + "sy_frightener": { + "name": "Savolla's Frightener", + "deck": "syndicate", + "row": "close", + "strength": "9", + "ability": "hero scorch_c", + "filename": "frightener", + "count": "1", + "quote": "The witchers thought the Salamandra thugs wouldn't get through Kaer Morhen's walls. The witchers were wrong." + }, + "sy_stolen_mutagens": { + "name": "Stolen Mutagens", + "deck": "syndicate", + "row": "close", + "strength": "1", + "ability": "horn", + "filename": "stolen_mutagens", + "count": "1", + "quote": "Like organ harvesting—but far more lucrative." + }, + "spe_vivaldi_bank": { + "name": "Vivaldi Bank", + "deck": "special syndicate", + "row": "", + "strength": "", + "ability": "bank", + "filename": "vivaldi_bank", + "count": "2", + "quote": "We're sorry to lose your business, but we wish ye well!" + } +}; + +var ext_ze_cards = { + "ze_zerrikanterment": { + "name": "Zerrikanterment", + "deck": "zerrikania", + "row": "leader", + "strength": "", + "ability": "zerrikanterment", + "filename": "zerrikanterment", + "count": "1", + "quote": "Legend says he burned the forests around Zerrikania making it isolated from the world by deserts and wastelands." + }, + "ze_baal_zebuth": { + "name": "Ball-Zebuth", + "deck": "zerrikania", + "row": "leader", + "strength": "", + "ability": "baal_zebuth", + "filename": "baal_zebuth", + "count": "1", + "quote": "God of moist and dark sky, it is believed to be the polar opposite of Raróg." + }, + "ze_rarog": { + "name": "Raróg", + "deck": "zerrikania", + "row": "leader", + "strength": "", + "ability": "rarog", + "filename": "rarog", + "count": "1", + "quote": "Fierce deity of fire and warm sky, it is believed to be the polar opposite of Baal-Zebuth." + }, + "ze_villentretenmerth": { + "name": "Villentretenmerth", + "deck": "zerrikania", + "row": "close", + "strength": "9", + "ability": "whorshipped", + "filename": "villentretenmerth", + "count": "1", + "quote": "Also calls himself Borkh Three Jackdaws... he's not the best at names." + }, + "ze_myrgtabrakke": { + "name": "Myrgtabrakke", + "deck": "zerrikania", + "row": "siege", + "strength": "8", + "ability": "whorshipped medic", + "filename": "myrgtabrakke", + "count": "1", + "quote": "Never get between a mother dragon and her young." + }, + "ze_merineaevelth": { + "name": "Merineaevelth", + "deck": "zerrikania", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "merineaevelth", + "count": "1", + "quote": "Queen of Zerrikania and founder of the Faithel." + }, + "ze_saulrenith": { + "name": "Saulrenith", + "deck": "zerrikania", + "row": "ranged", + "strength": "8", + "ability": "hero medic", + "filename": "saulrenith", + "count": "1", + "quote": "Impulsive and violent - not the mixture of traits one would trifle with." + }, + "ze_tea_vea_1": { + "name": "Tea & Vea", + "deck": "zerrikania", + "row": "close", + "strength": "5", + "ability": "muster whorshipper", + "filename": "tea_vea_1", + "count": "1", + "target": "wu_tea_vea", + "quote": "Her sabre, drawn faster than they eye could see, cut through the air." + }, + "ze_tea_vea_2": { + "name": "Tea & Vea", + "deck": "zerrikania", + "row": "close", + "strength": "5", + "ability": "muster whorshipper", + "filename": "tea_vea_2", + "count": "1", + "target": "wu_tea_vea", + "quote": "Her sabre, drawn faster than they eye could see, cut through the air." + }, + "ze_faithel_1": { + "name": "Faithel", + "deck": "zerrikania", + "row": "close", + "strength": "4", + "ability": "whorshipper", + "filename": "faithel_1", + "count": "1", + "quote": "Their goal is to find a dragon, honour it and swear their allegiance." + }, + "ze_faithel_2": { + "name": "Faithel", + "deck": "zerrikania", + "row": "close", + "strength": "4", + "ability": "whorshipper", + "filename": "faithel_2", + "count": "1", + "quote": "Their goal is to find a dragon, honour it and swear their allegiance." + }, + "ze_faithel_3": { + "name": "Faithel", + "deck": "zerrikania", + "row": "close", + "strength": "4", + "ability": "whorshipper", + "filename": "faithel_3", + "count": "1", + "quote": "Their goal is to find a dragon, honour it and swear their allegiance." + }, + "ze_myrgot": { + "name": "Myrgot", + "deck": "zerrikania", + "row": "close", + "strength": "6", + "ability": "", + "filename": "myrgot", + "count": "1", + "quote": "Scarred with shame, Myrgot never again returned to Caingorn after his disgraceful lost in the jouting with the pious knight Eyck of Denesle." + }, + "ze_lilit_niya": { + "name": "Lilit-Niya", + "deck": "zerrikania", + "row": "ranged", + "strength": "11", + "ability": "hero", + "filename": "lilit_niya", + "count": "1", + "quote": "The Black Sun was to announce the imminent return of Lilit, still honoured in the East under the name of Niya, and the extermination of the human race." + }, + "ze_ocvist": { + "name": "Ocvist", + "deck": "zerrikania", + "row": "ranged", + "strength": "7", + "ability": "whorshipped", + "filename": "ocvist", + "count": "1", + "quote": "The Master of Quartz Mountain, the Destroyer, Trajan's Slayer. In his free time, he likes long walks and candlelight dinners." + }, + "ze_keltullis": { + "name": "Keltullis", + "deck": "zerrikania", + "row": "close", + "strength": "6", + "ability": "whorshipped scorch_c", + "filename": "keltullis", + "count": "1", + "quote": "They fought 'er for near a century and they realized she weren't goin' nowheres, so... they cut a deal.She dinnae bother 'em, they give 'er what she needs." + }, + "ze_ostreverg": { + "name": "Ostreverg", + "deck": "zerrikania", + "row": "siege", + "strength": "7", + "ability": "whorshipped", + "filename": "ostreverg", + "count": "1", + "quote": "A long time ago the dragon Ostreverg ravaged and plundered the sacred Temple of Freya on the Skellige Islands." + }, + "ze_germinus": { + "name": "Germinus", + "deck": "zerrikania", + "row": "ranged", + "strength": "8", + "ability": "whorshipped", + "filename": "germinus", + "count": "1", + "quote": "The dragon valued its treasures above all else, unleashing its wrath on anything threatening it." + }, + "ze_azar_javed": { + "name": "Azar Javed", + "deck": "zerrikania", + "row": "ranged", + "strength": "7", + "ability": "scorch", + "filename": "azar_javed", + "count": "1", + "quote": "The sorcerer not only deftly manipulates the power of fire, it can be said that fire has become a part of his very being." + }, + "ze_bart": { + "name": "Bart", + "deck": "zerrikania", + "row": "close", + "strength": "4", + "ability": "morale", + "filename": "bart", + "count": "1", + "quote": "A good watchman should be brainless enough to render any thought of betraying his master impossible." + }, + "ze_venomous_basilisk": { + "name": "Venomous Basilisk", + "deck": "zerrikania", + "row": "ranged", + "strength": "6", + "ability": "scorch_c", + "filename": "venomous_basilisk", + "count": "1", + "quote": "The Basilisk is the most venomous creature in the world! For the basilisk is the king of all serpents!" + }, + "ze_giant_spotted_spider": { + "name": "Giant Spotted Spider", + "deck": "zerrikania", + "row": "ranged", + "strength": "10", + "ability": "hero", + "filename": "giant_spotted_spider", + "count": "1", + "quote": "Every beast roaming the forest is its prey, even elephants." + }, + "ze_emetouka": { + "name": "Emetouka", + "deck": "zerrikania", + "row": "close", + "strength": "6", + "ability": "", + "filename": "emetouka", + "count": "1", + "quote": "Their horn have immense value, mostly because many died trying to hunt them." + }, + "ze_leopard_1": { + "name": "Leopard", + "deck": "zerrikania", + "row": "close", + "strength": "4", + "ability": "bond", + "filename": "leopard_1", + "count": "1", + "target": "ze_leopard", + "quote": "Many their preys have mistaken their relaxed state for safety, leopards simply know they will quickly catch up on them." + }, + "ze_leopard_2": { + "name": "Leopard", + "deck": "zerrikania", + "row": "close", + "strength": "4", + "ability": "bond", + "filename": "leopard_2", + "count": "1", + "target": "ze_leopard", + "quote": "Many their preys have mistaken their relaxed state for safety, leopards simply know they will quickly catch up on them." + }, + "ze_tiger_1": { + "name": "Tiger", + "deck": "zerrikania", + "row": "close", + "strength": "5", + "ability": "bond", + "filename": "tiger_1", + "count": "1", + "target": "ze_tiger", + "quote": "The queen favourite beast. After dragons obviously." + }, + "ze_tiger_2": { + "name": "Tiger", + "deck": "zerrikania", + "row": "close", + "strength": "5", + "ability": "bond", + "filename": "tiger_2", + "count": "1", + "target": "ze_tiger", + "quote": "The queen favourite beast. After dragons obviously." + }, + "ze_jackals": { + "name": "Jackals", + "deck": "zerrikania", + "row": "ranged", + "strength": "3", + "ability": "muster", + "filename": "jackals", + "count": "3", + "target": "ze_jackals", + "quote": "Not the most dangerous but surprisingly one of the most hated wild beasts around." + }, + "ze_boa": { + "name": "Boa", + "deck": "zerrikania", + "row": "close", + "strength": "4", + "ability": "", + "filename": "boa", + "count": "1", + "quote": "Living choking hazard." + }, + "ze_python": { + "name": "Python", + "deck": "zerrikania", + "row": "close", + "strength": "4", + "ability": "", + "filename": "python", + "count": "1", + "quote": "'Look at this weird fallen tree! Oh shit, it's moving towards us!'" + }, + "ze_viper": { + "name": "Viper", + "deck": "zerrikania", + "row": "close", + "strength": "4", + "ability": "", + "filename": "viper", + "count": "1", + "quote": "'Had to flee me home, some damn viper had made it its den.'" + }, + "ze_hyenas": { + "name": "Hyenas", + "deck": "zerrikania", + "row": "close", + "strength": "5", + "ability": "", + "filename": "hyenas", + "count": "1", + "quote": "'Those ploughin' wretches always hunt in packs. They killed all my hens and I couldn't do nothin'.'" + }, + "ze_collective_trance": { + "name": "Collective Trance", + "deck": "zerrikania", + "row": "siege", + "strength": "4", + "ability": "medic", + "filename": "collective_trance", + "count": "1", + "quote": "Zerrikanians have this old tradition to join together, share a strong psychedelic decoction and escape the harsh reality." + }, + "ze_hippotoxotai_1": { + "name": "Hippotoxotai", + "deck": "zerrikania", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "hippotoxotai_1", + "count": "1", + "target": "ze_hippotoxotai", + "quote": "Only dust clouds, arrows and death." + }, + "ze_hippotoxotai_2": { + "name": "Hippotoxotai", + "deck": "zerrikania", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "hippotoxotai_2", + "count": "1", + "target": "ze_hippotoxotai", + "quote": "Only dust clouds, arrows and death." + }, + "ze_hippotoxotai_3": { + "name": "Hippotoxotai", + "deck": "zerrikania", + "row": "ranged", + "strength": "4", + "ability": "muster", + "filename": "hippotoxotai_3", + "count": "1", + "target": "ze_hippotoxotai", + "quote": "Only dust clouds, arrows and death." + }, + "ze_skuda_amazon_1": { + "name": "Skuda Amazon", + "deck": "zerrikania", + "row": "ranged", + "strength": "6", + "ability": "bond", + "filename": "skuda_amazon_1", + "count": "1", + "target": "ze_skuda_amazon", + "quote": "Their legendary markswomanship is very real." + }, + "ze_skuda_amazon_2": { + "name": "Skuda Amazon", + "deck": "zerrikania", + "row": "ranged", + "strength": "6", + "ability": "bond", + "filename": "skuda_amazon_2", + "count": "1", + "target": "ze_skuda_amazon", + "quote": "'I don't need to cut my breast to hit a bull's eye at full speed.'" + }, + "ze_bomb_maker_1": { + "name": "Zerrikanian Bomb Maker", + "deck": "zerrikania", + "row": "ranged", + "strength": "3", + "ability": "scorch", + "filename": "bomb_maker_1", + "count": "1", + "quote": "Business of Zerrikanian bombs is... booming." + }, + "ze_bomb_maker_2": { + "name": "Zerrikanian Bomb Maker", + "deck": "zerrikania", + "row": "ranged", + "strength": "3", + "ability": "scorch", + "filename": "bomb_maker_2", + "count": "1", + "quote": "Business of Zerrikanian bombs is... booming." + }, + "ze_heavy_fire_scorpion": { + "name": "Heavy Zerrikanian Fire Scorprion", + "deck": "zerrikania", + "row": "siege", + "strength": "10", + "ability": "", + "filename": "heavy_fire_scorpion", + "count": "1", + "quote": "Not the best for taking cities, but great for razing them to the ground." + }, + "ze_free_warrior_1": { + "name": "Free Warrior", + "deck": "zerrikania", + "row": "close", + "strength": "4", + "ability": "inspire", + "filename": "free_warrior_1", + "count": "1", + "quote": "'Hmm, that feeling of freedom after defeating your foe!'" + }, + "ze_free_warrior_2": { + "name": "Free Warrior", + "deck": "zerrikania", + "row": "close", + "strength": "5", + "ability": "inspire", + "filename": "free_warrior_2", + "count": "1", + "quote": "She first lets her prey get lost in the jungle, then she starts the hunt." + }, + "ze_free_warrior_3": { + "name": "Free Warrior", + "deck": "zerrikania", + "row": "close", + "strength": "8", + "ability": "inspire", + "filename": "free_warrior_3", + "count": "1", + "quote": "Few in the northern realms can afford his sword." + }, + "ze_free_warrior_4": { + "name": "Free Warrior", + "deck": "zerrikania", + "row": "ranged", + "strength": "6", + "ability": "inspire", + "filename": "free_warrior_4", + "count": "1", + "quote": "'See that thing running over there, I'll make it stop.'" + }, + "ze_free_warrior_5": { + "name": "Free Warrior", + "deck": "zerrikania", + "row": "ranged", + "strength": "7", + "ability": "inspire", + "filename": "free_warrior_5", + "count": "1", + "quote": "'At first I thought it was one o' those leopards, ye know? Till I saw the spear and realized 'twas in fact a woman.'" + }, + "ze_first_faithel_kia": { + "name": "First Faithel Kia", + "deck": "zerrikania", + "row": "close", + "strength": "9", + "ability": "hero whorshipper", + "filename": "first_faithel_kia", + "count": "1", + "quote": "Once a close friend of Merineaevelth, she was the first tasked to find and protect the devine dragons of the world." + }, + "ze_apucunpture_healer": { + "name": "Apucunpture Healer", + "deck": "zerrikania", + "row": "siege", + "strength": "6", + "ability": "medic", + "filename": "apucunpture_healer", + "count": "1", + "quote": "You might find it surprising, but these needles soothe pain." + }, + "ze_canyon_herbalist": { + "name": "Canyon Herbalist", + "deck": "zerrikania", + "row": "ranged", + "strength": "5", + "ability": "morale", + "filename": "canyon_herbalist", + "count": "1", + "quote": "It is easy to get lost in the canyon, but knowing its herbs is a rare gift." + }, + "ze_high_priestess_nia": { + "name": "High Priestess Nia", + "deck": "zerrikania", + "row": "ranged", + "strength": "10", + "ability": "hero", + "filename": "high_priestess_nia", + "count": "1", + "quote": "Battles have been fought in her name. Each bloodier than the last." + }, + "ze_dragon_priestess_lua": { + "name": "Dragon Priestess Lua", + "deck": "zerrikania", + "row": "siege", + "strength": "8", + "ability": "hero whorshipper", + "filename": "dragon_priestess_lua", + "count": "1", + "quote": "Mastering the arcana of dragon magic is no small feat." + }, + "ze_rainforest_pathfinder": { + "name": "Rainforest Pathfinder", + "deck": "zerrikania", + "row": "ranged", + "strength": "8", + "ability": "spy", + "filename": "rainforest_pathfinder", + "count": "1", + "quote": "How to cross the Sar'gaedd forest? Take a map, see where the nearest tribal village is, then hire a local guide." + }, + "ze_steppes_nomad_1": { + "name": "Steppes Nomad", + "id": 1, + "deck": "zerrikania", + "row": "siege", + "strength": "5", + "ability": "muster", + "filename": "steppes_nomad_1", + "count": "1", + "target": "ze_steppes_nomad", + "quote": "It takes robustness and unity to survive in these vast steppes." + }, + "ze_steppes_nomad_2": { + "name": "Steppes Nomad", + "id": 2, + "deck": "zerrikania", + "row": "siege", + "strength": "5", + "ability": "muster", + "filename": "steppes_nomad_2", + "count": "1", + "target": "ze_steppes_nomad", + "quote": "It takes robustness and unity to survive in these vast steppes." + }, + "ze_war_elephant": { + "name": "War Elephant", + "deck": "zerrikania", + "row": "close", + "strength": "9", + "ability": "", + "filename": "war_elephant", + "count": "1", + "quote": "It's hard to find journals of what it is like to see a Zerrikanian elephant battalion charging towards you, for it requires survivors." + }, + "ze_behemoth": { + "name": "Behemoth", + "deck": "zerrikania", + "row": "close", + "strength": "10", + "ability": "hero", + "filename": "behemoth", + "count": "1", + "quote": "A beast so huge its turd piles were big enough to provide housing for whole families. If it wasn't for the stench that is." + }, + "ze_balladeer": { + "name": "Balladeer", + "deck": "zerrikania", + "row": "ranged", + "strength": "1", + "ability": "horn", + "filename": "balladeer", + "count": "1", + "quote": "It is known the Zerrikanian queen was a tought woman and that only the mellifluous voice of a deft singer could penetrate the hard shell around her heart." + }, + "ze_alchemist": { + "name": "Zerrikanian Alchemist", + "deck": "zerrikania", + "row": "siege", + "strength": "1", + "ability": "medic", + "filename": "alchemist", + "count": "1", + "quote": "'What if I put some of this too...'" + }, + "ze_yellow_witch_korath": { + "name": "Yellow Witch Korath", + "deck": "zerrikania", + "row": "ranged", + "strength": "10", + "ability": "hero", + "filename": "yellow_witch_korath", + "count": "1", + "quote": "A man once forgot her full title is mistakenly called her a 'sand witch'. Now is lacquered skull decorates her staff." + }, + "ze_sandworm": { + "name": "Sandworm", + "deck": "zerrikania", + "row": "close", + "strength": "11", + "ability": "hero", + "filename": "sandworm", + "count": "1", + "quote": "Despite its massive size, many sense it coming only too late." + }, + "spe_giant_spider_web": { + "name": "Giant Spider Webs", + "deck": "weather zerrikania", + "row": "", + "strength": "", + "ability": "frost", + "filename": "giant_spider_web", + "count": "3", + "quote": "Zerrikania hosts spiders so large they can trap elephants in their webs." + }, + "spe_tse_tse_flies": { + "name": "Tse Tse Flies", + "deck": "weather zerrikania", + "row": "", + "strength": "", + "ability": "fog", + "filename": "tse_tse_flies", + "count": "3", + "quote": "The flies are especially repulsive, laying their eggs in the human body, the resulting larvae maturing within the host's head." + }, + "spe_dragon_wrath": { + "name": "Dragon Wrath", + "deck": "weather zerrikania", + "row": "", + "strength": "", + "ability": "rain", + "filename": "dragon_wrath", + "count": "3", + "quote": "Blackened skies from wisps of smoke, the greenery's vanished in a fiery stroke." + }, +}; + +/* + * Selecting cards to use + */ +var card_dict = default_cards; + +card_dict = Object.assign({}, card_dict, ext_nr_cards); +card_dict = Object.assign({}, card_dict, ext_ne_cards); +card_dict = Object.assign({}, card_dict, ext_mo_cards); +card_dict = Object.assign({}, card_dict, ext_st_cards); +card_dict = Object.assign({}, card_dict, ext_sk_cards); +card_dict = Object.assign({}, card_dict, ext_wu_cards); +card_dict = Object.assign({}, card_dict, ext_to_cards); +card_dict = Object.assign({}, card_dict, ext_lr_cards); +card_dict = Object.assign({}, card_dict, ext_sy_cards); +card_dict = Object.assign({}, card_dict, ext_ze_cards); \ No newline at end of file diff --git a/decks.html b/decks.html new file mode 100644 index 0000000..730e665 --- /dev/null +++ b/decks.html @@ -0,0 +1,848 @@ + + + + Gwent 4.0 + + + + + + + + + + + + + + +
+ + + + + + + + +
+
+

Gwent 4.0

+

The Witcher 3 minigame pulled to the browser and pushed further

+
+ + +
+ + +

Building a deck in Gwent

+ +

Gwent was initially a deck building game. Now, the main difficulty to make Gwent interesting and playable with 2 human players is ... building decks. No kidding.

+ +

+ In The Witcher 3, the purpose was to build the strongest and most imbalance deck. Of course, players wanted to win and the computer does not complain about always losing. + As a consequence, there was obvious choices of decks to have the highest chances of victory, using Nilfgaard or the Northern Realms as faction, with a lot of spies, medics and decoys. + Such decks are boring to play, especially as multiplier, so we want to get out of this dead end and make something more interesting out of the existing game. +

+ +

+ Firstly, we want to accept one thing, to have more enjoyable games, decks must be weaker. They must contain less broken cards to leave more room for actual strategy. + Goal is no longer to win 100% of games but instead to enjoy all games. +

+ +

+ There hasn't yet been any consensus about the best method to constitute a balanced and enjoyable deck. Various discussions can be found on the internet but most of them suggest the draw method, with variations. + Basically, the idea is like this: + +

    +
  • Pick a Faction (randomly if you prefer)
  • +
  • Pick a Leader (randomly if you prefer)
  • +
  • Now constitue your deck as follows (or with your own variation):
  • +
  • Shuffle your deck
  • +
  • Draw 3 cards. Keep 1 and discard the 2 others (variation, you can keep two, but only a limited amount of times)
  • +
  • Do this until you have at least 22 unit cards and max 10 special cards.
  • +
+

+ +

+ For more balance, it is recommanded to add more restrictions, such as: + +

    +
  • Max 5 heroes per deck.
  • +
  • Max 2 spies per deck.
  • +
+

+ + +

Our approach

+ +

+ The above approach has the advantage to add more variety, because there is some uncertainty in the building of the deck. + It is less likely to face several times the same deck. + We however see several big drawbacks which we don't like: + +

    +
  • Building your deck over and over is slow. Unless you have fun building a new deck again incrementaly, this is a waste of time.
  • +
  • You are less likely to build an efficient deck with a specific playstyle.
  • +
  • The outcome will be a rather random mix of cards with a limited connection to the Witcher Universe.
  • +
+

+ +

+ Consequently, we have built a set of decks with the following method and state of mind: + +

    +
  • A deck must be coherent to a part of the Witcher universe.
  • +
  • A deck must have a playstyle that is unique if possible, but at least different from most decks.
  • +
  • Preferably a deck must have 5 heroes, + or - 1.
  • +
  • Preferably a deck must have between 22 and 30 unit cards (heroes included).
  • +
  • Preferably a deck must have between 5 and 10 special cards, usually around 7.
  • +
  • The weight of a deck should be balanced as compared to the weight of the other decks (often between 270 and 300 in our method).
  • +
  • A character should preferably be available in only one deck.
  • +
+

+ + +

Wait, did you say weight?

+ +

+ Well yes, our main method for balancing decks is actually similar to the modern Gwent game. + We try to compute a weight for each card (except special cards), which is comparable to the "Provision" value the modern Gwent game is using. +

+ +

+ Don't be too scared! Just like the classic Gwent 3.0 is simpler with less abilities, it does not need to fine tune the weight of each card accurately. + Basically, the idea is to statistically estimate the strength potential of a card, based on its abilities. This isn't easy to do it for each ability, but we tried to have a good estimation. + Here are the big lines: + +

    +
  • A basic unit card with a strength of 7 has a weight of 7. Simple, we play it, it adds 7 points to the total score. Of course this can be altered, in good or bad, but this is not the point.
  • +
  • On the other hand, a hero of strength 10 will also add 10 points, but it cannot be altered. We took the decision to apply a multiplier of 2, so the weight of this hero would be 20. This is the trickiest part to weight, the fact it can or cannot be affected by abilities. However, since most hero cards have the same strength (around 10), and if each deck has almost the same amount of heroes, this multiplier does not really have a significance in the balance/total weight.
  • +
  • + Before talking about the other abilities weight, we need to jump to the end to justify some choices. + We have seen that overall, the average weight of a card is around 10, heroes included. It goes down to around 8 without heroes. So this gives us an idea of the average value/potential of a card. +
  • +
  • Let's start with the infamous spy ability. It gives 2 cards but gives some strength to the enemy, so the weight is (2*10) - spy_strength (10 being the average weight of a card).
  • +
  • Similarly, a medic brings back a unit card (not a hero) of average weight 8. However some of these units won't be able to use their ability (such as Muster), so we considerd the weight to be 7 + medic_strength.
  • +
  • + Muster and Tight Bond: these are a little tricky because they work in groups. You have several copies of the same card, but their potential changes a lot when used correcly. + Actual potential also changes depending on the number of copies available. + In short, we have chosen to apply a multiplier of 2 for both. It simplifies their behaviour, but a probability analysis of these abilities has shown that, compared to a basic card being played, the effect of these abilities multiples the outcome potential by around 2. +
  • +
  • + We will not go into details for each of the other abilities because they are even more guesses (very situational). Most of the other abilities have an added weight of 5 (added to the unit strength), such as for Scorch, Morale Boost or Summon Avenger. + The main exception to this is Commander's Horn which has an added weight of 10. We have also decided to give an added weigth of 2 to agile cards, which have the option to be played in 2 rows; +
  • +
  • For now, all leaders have a weight of 20 by default. We haven't yet gone into the trouble of fine tuning their weight.
  • +
+

+ +

+ Let's be realistic, this is not exact science, this is not perfect. + But try it yourself and you'll see that it is already enough to show when a deck is far stronger (put a lot of Tight Bond cards in a deck) or very weak. + We believe it does its job well enough to end up with decks of comparable potential. Tests have shown good results. +

+ +

+ With all this in mind, we came up with a selection of decks which we think remain true to the Witcher Universe all while being interesting to play. +

+ + +

Suggestion of decks

+ +

+ For more details about the content of these decks, launch the game and inspect them! +

+ + + + +
+
+ Deck leader +
+
+
Northern Realms - Temeria
+
+

+ Leader: +
+ Deck weight: +
+ Leader Ability: +
+ Play style: Revolves around Tight Bond, Spy and siege cards. +

+

+ This deck focuses mostly on units and characters from the realm of Temeria, including Blue Stripes units. + Spy units will increase the chances of getting Tight Bond units together. You will also have a good selection of Siege units to rely on. +

+
+
+
+ +
+
+ Deck leader +
+
+
Northern Realms - Aedirn & Kaedwen
+
+

+ Leader: +
+ Deck weight: +
+ Leader Ability: +
+ Play style: Revolves around Tight Bond, Morale Boost and siege cards. +

+

+ This deck focuses mostly on units and characters from the realms of Aedirn and Kaedwen. + It has a great selection of siege units (several with the Tight Bond ability) which can be boosted with the several Morale Boost applying on the Siege row. +

+
+
+
+ +
+
+ Deck leader +
+
+
Northern Realms - Cintra
+
+

+ Leader: +
+ Deck weight: +
+ Leader Ability: +
+ Play style: Revolves around Muster, Slaughter of Cintra and Summon Avenger. +

+

+ This deck focuses mostly on units and characters from the realm of Cintra and some minor neighbour realms, such as Kerack or Cidaris. + It also brings the power of the Skellige fleet thanks to the presence of Eist Tuirseach. + The idea of the deck is to emphasize the slaughter of Cintra and its rebirth, hence the selection of abilities. +

+
+
+
+ +
+
+ Deck leader +
+
+
Northern Realms - Redania
+
+

+ Leader: +
+ Deck weight: +
+ Leader Ability: +
+ Play style: Revolves around Spies, Medic and Tall units. +

+

+ This deck focuses mostly on units and characters from the realm of Redania. + Its many strong units combine well with spies and medics. You also have the option to try to combine the Crinfrid Reavers. +

+
+
+
+ + +
+ +
+
+ Deck leader +
+
+
Nilfgaard Empire - Army
+
+

+ Leader: +
+ Deck weight: +
+ Leader Ability: +
+ Play style: Revolves around Spies, Medic, Commander's Horn and some Tight Bond. +

+

+ This deck focuses mostly on army units of the Empire of Nilfgaard. + It aims at representing the mass of the army of Nilfgaard, hence the higher amount of cards. + Its many medics and few spies allow it to bring in more units on the board, which can be amplified by the available Commander's Horns. + It has more heroes than usual, but some of them are weak hero cards. +

+
+
+
+ +
+
+ Deck leader +
+
+
Nilfgaard Empire - Nobility
+
+

+ Leader: +
+ Deck weight: +
+ Leader Ability: +
+ Play style: Revolves around Spies and Tight Bond. +

+

+ This deck focuses mostly on nobles and aristocrats of the Empire of Nilfgaard. + It aims at representing the court of the Empire and its schemes. + The many spies allow to make great use of the Impera Brigade. +

+
+
+
+ +
+
+ Deck leader +
+
+
Nilfgaard Empire - Second Army
+
+

+ Leader: +
+ Deck weight: +
+ Leader Ability: +
+ Play style: Revolves around Muster, Scorch, Medic and Spies. +

+

+ This deck focuses on other army units of the Empire of Nilfgaard. + Unlike the other army deck, this one features some Muster and Scorch and relies less on the mass. +

+
+
+
+ + +
+ +
+
+ Deck leader +
+
+
Monsters - Wild Hunt & Giants
+
+

+ Leader: +
+ Deck weight: +
+ Leader Ability: +
+ Play style: Revolves around Muster and tall units. +

+

+ This deck focuses on cards related to the Wild Hunt along with other giant monsters. + Even though Muster of Melee units is the main focus of this deck, it's got a decent selection of Siege units as well. +

+
+
+
+ +
+
+ Deck leader +
+
+
Monsters - Beasts & Creatures
+
+

+ Leader: +
+ Deck weight: +
+ Leader Ability: +
+ Play style: Revolves around a lot of Muster units. +

+

+ This deck focuses on the wide variety of monters in the Witcher universe, the smaller but more numerous ones. + This deck relies heavily on a lot of Muster, mostly on the Melee row. This is why this deck has more cards than usual. + It can quickly swarm the opponent, though the cards must be played carefully because you can quickly exhaust of of your musters. +

+
+
+
+ + +
+ +
+
+ Deck leader +
+
+
Scoia'Tael - Commandos
+
+

+ Leader: +
+ Deck weight: +
+ Leader Ability: +
+ Play style: Revolves around Muster and Medic units. +

+

+ This deck focuses on the non-human guerilla fighters of Scoia'Tael. + It relies mostly on Muster, combined with a good amount of medic cards. +

+
+
+
+ +
+
+ Deck leader +
+
+
Scoia'Tael - Independant Realms
+
+

+ Leader: +
+ Deck weight: +
+ Leader Ability: +
+ Play style: Revolves around Muster and Morale Boost units. +

+

+ This deck focuses on the more passific non-human realms, such sa Brokilon, Dol Blathanna and Mahakam. + It relies on a combination of Muster and Morale Boost. +

+
+
+
+ + +
+ +
+
+ Deck leader +
+
+
Skellige - Ard Skellig & Svalblod
+
+

+ Leader: +
+ Deck weight: +
+ Leader Ability: +
+ Play style: Revolves around Berserker, Muster and Tight Bond units. +

+

+ This deck focuses on the main island of Skellige, Ard Skellige, and the two clans base on it (an Craite and Drummond) along with the Svalblod cult. + This decks focuses on the Berserker/Mardroeme abilities, along with some Tight Bond and one very powerfull Muster. +

+
+
+
+ +
+
+ Deck leader +
+
+
Skellige - Small Islands
+
+

+ Leader: +
+ Deck weight: +
+ Leader Ability: +
+ Play style: Revolves around Muster, Tight Bond and Medic units. +

+

+ This deck focuses on the other small islands of Skellige and the clans living on them. + It relies on a good combination of Tight Bond and Muster units, supported by a decent amount of medics. +

+
+
+
+ + +
+ +
+
+ Deck leader +
+
+
Witcher Universe - Fighters & Mages
+
+

+ Leader: +
+ Deck weight: +
+ Leader Ability: +
+ Play style: Revolves around Muster and Medic units. +

+

+ This deck focuses on some famous fighters and mages of the Witcher universe which aren't very attached to a realm. + It relies mostly on Muster and Medic units. +

+
+
+
+ +
+
+ Deck leader +
+
+
Witcher Universe - Witchers
+
+

+ Leader: +
+ Deck weight: +
+ Leader Ability: +
+ Play style: Revolves around Witcher Schools, Resilience and Scorch. +

+

+ This deck focuses on the actual witchers and their school. + It uses a specific set of abilities that encourage to play witchers of the same school together along with their keep. + Instead of the usual special cards, signs are available with some unique abilities. +

+
+
+
+ +
+
+ Deck leader +
+
+
Witcher Universe - Demons & Creatures
+
+

+ Leader: +
+ Deck weight: +
+ Leader Ability: +
+ Play style: Revolves around Muster, Scorch and Spy units. +

+

+ This deck focuses on some rare creatures and demons of the witcher universe, including the characters of Heart of Stone. + It relies mostly on Muster and Scorch units, supported by some spies and overall strong units. +

+
+
+
+ +
+
+ Deck leader +
+
+
Witcher Universe - Geralt & Friends
+
+

+ Leader: +
+ Deck weight: +
+ Leader Ability: +
+ Play style: Revolves around Summon Avenger and Medic units. +

+

+ This deck focuses on Geralt of Rivia, his close friends and various allies within the Witcher Universe. + Summon Avenger plays an important part of the deck, with Roach & Kelpie summoning Geralt and Ciri. + Combined with Medic units, it can become very powerfull. +

+
+
+
+ + +
+ +
+
+ Deck leader +
+
+
Toussaint - Knights & Nobles
+
+

+ Leader: +
+ Deck weight: +
+ Leader Ability: +
+ Play style: Revolves around Tight Bond, Muster and tall units. +

+

+ This deck focuses on the knights and noble people of Toussaint. + It is composed of mostly strong units, some with Tight Bond, which can be very strong if left unckecked. +

+
+
+
+ +
+
+ Deck leader +
+
+
Toussaint - Monsters & Vampires
+
+

+ Leader: +
+ Deck weight: +
+ Leader Ability: +
+ Play style: Revolves around Muster and tall units. +

+

+ This deck focuses on the monsters and vampires of Toussaint. + It is composed of mostly strong units along with some Muster units. It is a quite resilient mix. +

+
+
+
+ + +
+ +
+
+ Deck leader +
+
+
Lyria & Rivia - First Line
+
+

+ Leader: +
+ Deck weight: +
+ Leader Ability: +
+ Play style: Revolves around Muster and Medic units. +

+

+ This deck focuses on the first line of the Lyria & Rivia army (mix of Melee and Ranged units). + It is composed of a good mix of Muster units, supported by medics. The shield special cards give great potential to the concentration of Muster units. +

+
+
+
+ +
+
+ Deck leader +
+
+
Lyria & Rivia - Rear Guard
+
+

+ Leader: +
+ Deck weight: +
+ Leader Ability: +
+ Play style: Revolves around Scorch, Spy and Medic units. +

+

+ This deck focuses on the first line of the Lyria & Rivia army (mix of Melee and Ranged units). + It is composed of a good mix of Muster units, supported by medics. The shield special cards give great potential to the concentration of Muster units. +

+
+
+
+ + +
+ +
+
+ Deck leader +
+
+
Syndicate - Church of Eternal Fire
+
+

+ Leader: +
+ Deck weight: +
+ Leader Ability: +
+ Play style: Revolves around Witch Hunt, Muster and Dimeritium. +

+

+ This deck focuses on the cult of the Eternal Fire along with the Order of the Flaming Rose. + Due to its nature, it has the unique ability Witch Hunt, combined with Muster and Dimeritium Shackles special cards. + This decks looks weak in numbers, but it is quite aggressive. +

+
+
+
+ +
+
+ Deck leader +
+
+
Syndicate - Salamandra
+
+

+ Leader: +
+ Deck weight: +
+ Leader Ability: +
+ Play style: Revolves around Muster, Scorch and Summon Avenger. +

+

+ This deck focuses on the Salamandra gang. + It relies mostly on many Scorch units along with some Muster and Summon Avenger, making it an aggressive deck as well. +

+
+
+
+ +
+
+ Deck leader +
+
+
Syndicate - Novidgrad Gangs
+
+

+ Leader: +
+ Deck weight: +
+ Leader Ability: +
+ Play style: Revolves around Spy, Tight Bond and Muster. +

+

+ This deck focuses on gangs of Novigrad (the core of the Syndicate). + It relies mostly heavily on many spies to make the multiple Tight Bond units work. +

+
+
+
+ + +
+ +
+
+ Deck leader +
+
+
Zerrikania - Dragon Cult
+
+

+ Leader: +
+ Deck weight: +
+ Leader Ability: +
+ Play style: Revolves around Whorshipper and Whorshipped units along with Medic. +

+

+ This deck focuses on the cult of dragons in Zerrikania. + It requires to combine on the board dragons and faithel to make use of the powerfull boost. + Since dragons are rather strong units anyway, you can either play all in a massive round, or spread them accross several rounds. + Usage of Medics will allow to bring back dragons later. +

+
+
+
+ +
+
+ Deck leader +
+
+
Zerrikania - Army
+
+

+ Leader: +
+ Deck weight: +
+ Leader Ability: +
+ Play style: Revolves around Inspire, Scorch and a various selection of abilities. +

+

+ This deck focuses on the fighting units and creatures of Zerrikania. + It primarly features Free Warriors which can boost each other. + This deck also has a balanced variety of most abilities, especially Scorch and Medics; +

+
+
+
+ +
+
+
+ + + + + diff --git a/decks.js b/decks.js new file mode 100644 index 0000000..e326a7f --- /dev/null +++ b/decks.js @@ -0,0 +1,367 @@ +let default_decks = [{ + "title": "Northern Realms Deck 1 - Spies & Bonds", + "description": "Deck relying mostly on Tight Bonds units and Spies", + "leader": "nr_foltest_lord", + "faction": "realms", + "cards": [ + ["spe_horn", 1], + ["spe_decoy", 2], + ["spe_scorch", 1], + ["spe_clear", 1], + ["spe_fog", 1], + ["spe_rain", 1], + ["nr_ciri", 1], + ["nr_geralt", 1], + ["nr_natalis", 1], + ["nr_vernon", 1], + ["nr_stennis", 1], + ["nr_keira", 1], + ["nr_dijkstra", 1], + ["nr_sheala", 1], + ["nr_thaler", 1], + ["nr_triss", 1], + ["nr_olgierd", 1], + ["nr_crinfrid_1", 1], + ["nr_crinfrid_2", 1], + ["nr_crinfrid_3", 1], + ["nr_villen", 1], + ["nr_blue_stripes_1", 1], + ["nr_blue_stripes_2", 1], + ["nr_blue_stripes_3", 1], + ["nr_poor_infantry_1", 1], + ["nr_poor_infantry_2", 1], + ["nr_poor_infantry_3", 1], + ["nr_banner_nurse", 1] + ] +}, +{ + "title": "Nilfgaard Deck 1 - Spies & Bonds", + "description": "Deck relying mostly on Spies, Emissaries, some Tight Bond and strong ranged units", + "leader": "ne_emhyr_invader_of_the_north", + "faction": "nilfgaard", + "cards": [ + ["spe_horn", 1], + ["spe_decoy", 2], + ["spe_scorch", 1], + ["spe_clear", 1], + ["ne_ciri", 1], + ["ne_geralt", 1], + ["ne_yennefer", 1], + ["ne_black_archer", 1], + ["ne_black_archer_1", 1], + ["ne_letho", 1], + ["ne_moorvran", 1], + ["ne_stefan", 1], + ["ne_shilard", 1], + ["ne_young_emissary_1", 1], + ["ne_young_emissary_2", 1], + ["ne_vattier", 1], + ["ne_impera_brigade_1", 1], + ["ne_impera_brigade_2", 1], + ["ne_impera_brigade_3", 1], + ["ne_impera_brigade_4", 1], + ["ne_archer_support", 1], + ["ne_archer_support_1", 1], + ["ne_cahir", 1], + ["ne_renuald", 1], + ["ne_vreemde", 1], + ["ne_morteisen", 1], + ["ne_albrich", 1], + ] + }, + { + "title": "Monsters Deck 1 - Massive Muster", + "description": "Deck relying on a lot of muster units", + "leader": "mo_eredin_commander", + "faction": "monsters", + "cards": [ + ["spe_horn", 1], + ["spe_decoy", 1], + ["spe_scorch", 1], + ["spe_clear", 1], + ["spe_fog", 1], + ["spe_rain", 1], + ["mo_draug", 1], + ["mo_imlerith", 1], + ["mo_leshen", 1], + ["mo_gaunter_odimm", 1], + ["mo_kayran", 1], + ["mo_witch_velen", 1], + ["mo_witch_velen_1", 1], + ["mo_witch_velen_2", 1], + ["mo_foglet", 1], + ["mo_arachas_behemoth", 1], + ["mo_nekker", 1], + ["mo_nekker_1", 1], + ["mo_nekker_2", 1], + ["mo_toad", 1], + ["mo_katakan", 1], + ["mo_arachas", 1], + ["mo_arachas_1", 1], + ["mo_arachas_2", 1], + ["mo_plague_maiden", 1], + ["mo_bruxa", 1], + ["mo_ekkima", 1], + ["mo_fleder", 1], + ["mo_garkain", 1], + ["mo_gaunter_odimm_darkness", 1] + ] + }, + { + "title": "Scoia'Tael Deck 1 - Agile & Muster", + "description": "Deck relying on agile units and muster", + "leader": "sc_francesca_pureblood", + "faction": "scoiatael", + "cards": [ + ["spe_horn", 1], + ["spe_decoy", 1], + ["spe_scorch", 1], + ["spe_clear", 1], + ["spe_frost", 1], + ["spe_rain", 1], + ["sc_iorveth", 1], + ["sc_isengrim", 1], + ["sc_schirru", 1], + ["sc_mahakam", 1], + ["sc_mahakam_1", 1], + ["sc_saskia", 1], + ["sc_vrihedd_brigade_1", 1], + ["sc_vrihedd_brigade", 1], + ["sc_mysterious_elf", 1], + ["sc_filavandrel", 1], + ["sc_toruviel", 1], + ["sc_yaevinn", 1], + ["sc_dol_infantry_1", 1], + ["sc_dol_infantry_2", 1], + ["sc_havekar_support", 1], + ["sc_havekar_support_1", 1], + ["sc_havekar_support_2", 1], + ["sc_elf_skirmisher", 1], + ["sc_elf_skirmisher_1", 1], + ["sc_elf_skirmisher_2", 1], + ["sc_vrihedd_cadet", 1], + ["sc_havekar_nurse", 1], + ["sc_havekar_nurse_2", 1], + ["sc_temptress", 1] + ] + }, + { + "title": "Skellige Deck 1 - Berserkers", + "description": "Deck relying mostly on berserker units", + "leader": "sk_holger", + "faction": "skellige", + "cards": [ + ["spe_mardroeme", 2], + ["spe_skellige_fleet", 2], + ["spe_horn", 1], + ["spe_decoy", 1], + ["spe_scorch", 1], + ["spe_clear", 1], + ["spe_frost", 1], + ["spe_rain", 1], + ["sk_hjalmar", 1], + ["sk_brokva_archer", 1], + ["sk_cerys", 1], + ["sk_ermion", 1], + ["sk_yennefer", 1], + ["sk_longship_1", 1], + ["sk_longship_3", 1], + ["sk_longship_2", 1], + ["sk_berserker", 1], + ["sk_shield_maiden_1", 1], + ["sk_shield_maiden_2", 1], + ["sk_shield_maiden_3", 1], + ["sk_light_longship_1", 1], + ["sk_light_longship_2", 1], + ["sk_light_longship_3", 1], + ["sk_vildkaarl", 1], + ["sk_gremist", 1], + ["sk_young_berserker_1", 1], + ["sk_young_berserker_2", 1], + ["sk_young_berserker_3", 1], + ["sk_arnvald", 1], + ["sk_kambi", 1] + ] + }, + { + "title": "Redania Deck 1 - Witch Hunt", + "description": "Deck relying mostly on witch hunters", + "leader": "re_radovid_mad_king", + "faction": "redania", + "cards": [ + ["spe_horn", 1], + ["spe_decoy", 2], + ["spe_execution", 1], + ["spe_royal_decree", 2], + ["spe_clear", 1], + ["spe_rain", 1], + ["re_carlo_varese", 1], + ["re_cyprian_wiley", 1], + ["re_francis_bedlam", 1], + ["re_black_cat_dog", 1], + ["re_redanian_elite", 1], + ["re_rico_meiersdorf", 1], + ["re_caretaker", 1], + ["re_redanian_knight_1", 1], + ["re_redanian_knight_2", 1], + ["re_eternal_fire_priest", 1], + ["re_graden", 1], + ["re_kurt", 1], + ["re_moreelse", 1], + ["re_nathaniel_pastodi", 1], + ["re_shani", 1], + ["re_witch_hunter", 1], + ["re_olgierd", 1], + ["re_vlodimir_von_everec", 1], + ["re_cyrus_hemmelfart", 1], + ["re_sigi_reuven", 1], + ["re_caleb_menge", 1], + ["re_iris_von_everec", 1] + ] + }, + { + "title": "Toussaint Deck 1 - Monsters & Knights", + "description": "Deck relying mostly Toussaint monsters, spies and muster", + "leader": "to_anna_henrietta_little_weasel", + "faction": "toussaint", + "cards": [ + ["spe_horn", 1], + ["spe_decoy", 2], + ["spe_scorch", 1], + ["spe_toussaint_wine", 2], + ["spe_clear", 1], + ["to_unseen_elder", 1], + ["to_damien_tour", 1], + ["to_roderick", 1], + ["to_gregoire_gorgon", 1], + ["to_witch_lynx_crag", 1], + ["to_milton", 1], + ["to_champion", 1], + ["to_duchess_informant", 1], + ["to_syanna", 1], + ["to_bootblack", 1], + ["to_dettlaff", 1], + ["to_knight_errant_1", 1], + ["to_knight_errant_2", 1], + ["to_lui_alberni", 1], + ["to_orianna", 1], + ["to_regis", 1], + ["to_prophet_lebioda", 1], + ["to_toussaint_knight_1", 1], + ["to_toussaint_knight_2", 1], + ["to_toussaint_knight_3", 1], + ["to_artorius_vigo", 1], + ["to_lady_lake", 1], + ["to_vivienne", 1] + ] + }, + { + "title": "Velen Deck 1 - Cursed Land", + "description": "Deck relying mostly on bond, scorch and drawing cards", + "leader": "ve_lady_wood_weavess", + "faction": "velen", + "cards": [ + ["spe_horn", 1], + ["spe_curse", 3], + ["spe_decoy", 2], + ["spe_scorch", 1], + ["spe_clear", 1], + ["ve_bloody_baron", 1], + ["ve_geralt", 1], + ["ve_johnny", 1], + ["ve_fugas", 1], + ["ve_pellar", 1], + ["ve_anna_strenger", 1], + ["ve_fiend", 1], + ["ve_chort", 1], + ["ve_vesemir", 1], + ["ve_thecla", 1], + ["ve_deserter_1", 1], + ["ve_deserter_2", 1], + ["ve_ghoul_1", 1], + ["ve_ghoul_2", 1], + ["ve_marauder_1", 1], + ["ve_marauder_2", 1], + ["ve_tamara_strenger", 1], + ["ve_angry_peasants", 1], + ["ve_hungry_wolves_4", 1], + ["ve_hungry_wolves_1", 1], + ["ve_hungry_wolves_2", 1], + ["ve_hungry_wolves_3", 1], + ["ve_abandoned_girl", 1] + ] + } +]; + +/* + * + */ + +var premade_deck = default_decks; +//premade_deck = custom_decks.concat(premade_deck); +//premade_deck = custom_decks; + +var deckWeightConsts = { + "spyBase": 20, + "heroMult": 2, + "musterMult": 2, + "tightBondMult": 2, + "medic": 7, + "scorch": 5, + "scorch_c": 5, + "morale": 5, + "agile": 2, + "horn": 10, + "berserker": 5, + "mardroeme": 5, + "avenger": 5, + "decoy": 7, + "clearWeatherWeight": 7, + "heroSpyBase": 5, + "cintra_slaughter": 5, + "resilience": 5, + "witcherSchoolWeight": 1, + "witch_hunt": 5, + "whorshipper": 2, + "whorshipped": 2, + "inspire": 3, + "comrade": 7, + "emissary": 5 +}; + +function calcDeckWeight(deck) { + var total = 0; + deck.cards.forEach(entry => { + let c = card_dict[entry[0]]; + let cnt = parseInt(entry[1]); + let abi = c["ability"].split(" "); + let cStr = 0; + if (!c["deck"].startsWith("special") && !c["deck"].startsWith("weather")) { + if (abi.includes("spy")) { + cStr = deckWeightConsts["spyBase"] - parseInt(c["strength"]); + if (abi.includes("hero")) + cStr += deckWeightConsts["heroSpyBase"]; + if (c.row === "agile") + cStr += deckWeightConsts["agile"]; + } else { + cStr = parseInt(c["strength"]); + if (abi.includes("hero")) + cStr *= deckWeightConsts["heroMult"]; + if (abi.includes("bond")) + cStr *= deckWeightConsts["tightBondMult"]; + if (abi.includes("muster")) + cStr *= deckWeightConsts["musterMult"]; + abi.forEach(a => { + if (a in deckWeightConsts) + cStr += deckWeightConsts[a]; + }); + if (abi.includes("witcher_wolf_school") || abi.includes("witcher_bear_school") || abi.includes("witcher_viper_school") || abi.includes("witcher_cat_school") || abi.includes("witcher_griffin_school")) + cStr += deckWeightConsts["witcherSchoolWeight"]; + if (c.row === "agile") + cStr += deckWeightConsts["agile"]; + } + } + total += (cStr * cnt); + }); + return total; +} \ No newline at end of file diff --git a/decks.old.js b/decks.old.js new file mode 100644 index 0000000..e28c43d --- /dev/null +++ b/decks.old.js @@ -0,0 +1,1396 @@ +let default_decks = [ + { + "title": "Default Northern Realms Deck 1", + "description": "TBD", + "leader": "nr_foltest_siegemaster", + "faction": "realms", + "cards": [ + ["spe_horn", 1], + ["spe_decoy", 3], + ["spe_frost", 1], + ["ntr_ciri", 1], + ["ntr_geralt", 1], + ["nr_esterad", 1], + ["nr_natalis", 1], + ["nr_philippa", 1], + ["nr_vernon", 1], + ["nr_catapult_1", 1], + ["nr_catapult_2", 1], + ["ntr_triss", 1], + ["ntr_villen", 1], + ["ntr_yennefer", 1], + ["nr_ballista", 1], + ["ntr_olgierd", 1], + ["nr_siege_tower", 1], + ["nr_trebuchet", 1], + ["nr_trebuchet_1", 1], + ["nr_crinfrid_1", 1], + ["nr_crinfrid_2", 1], + ["nr_crinfrid_3", 1], + ["nr_banner_nurse", 1], + ["nr_stennis", 1], + ["nr_blue_stripes_1", 1], + ["nr_blue_stripes_2", 1], + ["nr_blue_stripes_3", 1], + ["ntr_gaunter_odimm_darkness", 3], + ["nr_dijkstra", 1], + ["ntr_dandelion", 1], + ["ntr_gaunter_odimm", 1], + ["nr_thaler", 1], + ["ntr_mysterious_elf", 1] + ] + }, + { + "title": "Default Northern Realms Deck 2", + "description": "TBD", + "leader": "nr_foltest_siegemaster", + "faction": "realms", + "cards": [ + ["spe_horn", 1], + ["spe_decoy", 3], + ["spe_frost", 1], + ["spe_clear", 1], + ["spe_fog", 1], + ["spe_rain", 1], + ["ntr_ciri", 1], + ["ntr_geralt", 1], + ["nr_esterad", 1], + ["nr_natalis", 1], + ["nr_philippa", 1], + ["nr_vernon", 1], + ["nr_catapult_1", 1], + ["nr_catapult_2", 1], + ["ntr_triss", 1], + ["ntr_villen", 1], + ["ntr_yennefer", 1], + ["nr_ballista", 1], + ["ntr_olgierd", 1], + ["nr_siege_tower", 1], + ["nr_trebuchet", 1], + ["nr_trebuchet_1", 1], + ["nr_crinfrid_1", 1], + ["nr_crinfrid_2", 1], + ["nr_crinfrid_3", 1], + ["nr_banner_nurse", 1], + ["nr_stennis", 1], + ["nr_blue_stripes_1", 1], + ["nr_blue_stripes_2", 1], + ["nr_blue_stripes_3", 1], + ["ntr_gaunter_odimm_darkness", 3], + ["nr_dijkstra", 1], + ["ntr_dandelion", 1], + ["ntr_gaunter_odimm", 1], + ["nr_thaler", 1], + ["ntr_mysterious_elf", 1] + ] + }, + { + "title": "Default Nilfgaard Deck 1", + "description": "TBD", + "leader": "ne_emhyr_relentless", + "faction": "nilfgaard", + "cards": [ + ["spe_horn", 1], + ["spe_decoy", 3], + ["spe_scorch", 1], + ["spe_frost", 1], + ["spe_clear", 1], + ["spe_fog", 1], + ["spe_rain", 1], + ["ntr_ciri", 1], + ["ntr_geralt", 1], + ["ne_black_archer", 1], + ["ne_black_archer_1", 1], + ["ne_heavy_zerri", 1], + ["ne_menno", 1], + ["ne_moorvran", 1], + ["ne_stefan", 1], + ["ne_shilard", 1], + ["ntr_villen", 1], + ["ntr_yennefer", 1], + ["ntr_olgierd", 1], + ["ne_young_emissary_1", 1], + ["ne_young_emissary_2", 1], + ["ntr_gaunter_odimm_darkness", 3], + ["ne_vattier", 1], + ["ne_impera_brigade_1", 1], + ["ne_impera_brigade_2", 1], + ["ne_impera_brigade_3", 1], + ["ne_impera_brigade_4", 1], + ["ntr_dandelion", 1], + ["ntr_gaunter_odimm", 1], + ["ne_archer_support", 1], + ["ne_archer_support_1", 1], + ["ntr_mysterious_elf", 1], + ["ne_siege_support", 1] + ] + }, + { + "title": "Default Nilfgaard Deck 2", + "description": "TBD", + "leader": "ne_emhyr_whiteflame", + "faction": "nilfgaard", + "cards": [ + ["spe_horn", 1], + ["spe_decoy", 3], + ["spe_scorch", 2], + ["spe_clear", 1], + ["spe_fog", 1], + ["spe_rain", 1], + ["ntr_ciri", 1], + ["ntr_geralt", 1], + ["ne_black_archer", 1], + ["ne_black_archer_1", 1], + ["ne_heavy_zerri", 1], + ["ne_menno", 1], + ["ne_moorvran", 1], + ["ntr_villen", 1], + ["ntr_yennefer", 1], + ["ne_assire", 1], + ["ne_cahir", 1], + ["ne_fringilla", 1], + ["ntr_olgierd", 1], + ["ntr_vesemir", 1], + ["ne_young_emissary_1", 1], + ["ne_young_emissary_2", 1], + ["ne_vattier", 1], + ["ne_impera_brigade_1", 1], + ["ne_impera_brigade_2", 1], + ["ne_impera_brigade_3", 1], + ["ne_impera_brigade_4", 1], + ["ntr_dandelion", 1], + ["ne_archer_support", 1], + ["ne_archer_support_1", 1], + ["ntr_cow", 1], + ["ntr_mysterious_elf", 1], + ["ne_siege_support", 1] + ] + }, + { + "title": "Default Monster Deck 1", + "description": "TBD", + "leader": "mo_eredin_commander", + "faction": "monsters", + "cards": [ + ["spe_horn", 1], + ["spe_decoy", 3], + ["spe_scorch", 1], + ["spe_clear", 1], + ["spe_fog", 1], + ["spe_rain", 1], + ["ntr_ciri", 1], + ["ntr_geralt", 1], + ["mo_imlerith", 1], + ["mo_kayran", 1], + ["mo_toad", 1], + ["ntr_villen", 1], + ["ntr_yennefer", 1], + ["mo_arachas_behemoth", 1], + ["mo_witch_velen", 1], + ["mo_witch_velen_1", 1], + ["mo_witch_velen_2", 1], + ["ntr_olgierd", 1], + ["mo_katakan", 1], + ["mo_arachas", 1], + ["mo_arachas_1", 1], + ["mo_arachas_2", 1], + ["mo_botchling", 1], + ["ntr_gaunter_odimm_darkness", 3], + ["mo_bruxa", 1], + ["mo_ekkima", 1], + ["mo_fleder", 1], + ["mo_garkain", 1], + ["ntr_dandelion", 1], + ["ntr_gaunter_odimm", 1], + ["mo_nekker", 1], + ["mo_nekker_1", 1], + ["mo_nekker_2", 1], + ["ntr_mysterious_elf", 1] + ] + }, + { + "title": "Default Monster Deck 2", + "description": "TBD", + "leader": "mo_eredin_bringer_of_death", + "faction": "monsters", + "cards": [ + ["spe_horn", 1], + ["spe_decoy", 1], + ["spe_scorch", 3], + ["spe_clear", 1], + ["spe_fog", 1], + ["spe_rain", 1], + ["ntr_ciri", 1], + ["ntr_geralt", 1], + ["mo_kayran", 1], + ["ntr_villen", 1], + ["ntr_yennefer", 1], + ["mo_arachas_behemoth", 1], + ["mo_witch_velen", 1], + ["mo_witch_velen_1", 1], + ["mo_witch_velen_2", 1], + ["ntr_olgierd", 1], + ["mo_katakan", 1], + ["mo_arachas", 1], + ["mo_arachas_1", 1], + ["mo_arachas_2", 1], + ["ntr_gaunter_odimm_darkness", 3], + ["mo_bruxa", 1], + ["mo_ekkima", 1], + ["mo_fleder", 1], + ["mo_garkain", 1], + ["ntr_mysterious_elf", 1] + ] + }, + { + "title": "Default Scoia'Tael Deck 1", + "description": "TBD", + "leader": "sc_francesca_daisy", + "faction": "scoiatael", + "cards": [ + ["spe_horn", 1], + ["spe_decoy", 3], + ["spe_scorch", 1], + ["spe_frost", 1], + ["spe_clear", 1], + ["spe_fog", 1], + ["spe_rain", 1], + ["ntr_ciri", 1], + ["ntr_geralt", 1], + ["sc_isengrim", 1], + ["sc_milva", 1], + ["sc_schirru", 1], + ["ntr_villen", 1], + ["ntr_yennefer", 1], + ["sc_dol_infantry", 1], + ["ntr_olgierd", 1], + ["sc_havekar_support", 1], + ["sc_havekar_support_1", 1], + ["sc_havekar_support_2", 1], + ["ntr_gaunter_odimm_darkness", 3], + ["sc_ciaran", 1], + ["sc_dwarf", 1], + ["sc_dwarf_1", 1], + ["sc_dwarf_2", 1], + ["ntr_dandelion", 1], + ["ntr_gaunter_odimm", 1], + ["sc_havekar_nurse", 1], + ["sc_havekar_nurse_1", 1], + ["ntr_mysterious_elf", 1] + ] + }, + { + "title": "Default Scoia'Tael Deck 2", + "description": "TBD", + "leader": "sc_francesca_hope_of_the_aen_seidhe", + "faction": "scoiatael", + "cards": [ + ["spe_horn", 1], + ["spe_decoy", 3], + ["spe_scorch", 1], + ["spe_frost", 1], + ["spe_clear", 1], + ["spe_fog", 1], + ["spe_rain", 1], + ["ntr_ciri", 1], + ["ntr_geralt", 1], + ["sc_isengrim", 1], + ["sc_milva", 1], + ["sc_schirru", 1], + ["ntr_villen", 1], + ["ntr_yennefer", 1], + ["sc_dol_infantry", 1], + ["sc_dol_infantry_1", 1], + ["sc_dol_infantry_2", 1], + ["sc_filavandrel", 1], + ["ntr_olgierd", 1], + ["sc_havekar_support", 1], + ["sc_havekar_support_1", 1], + ["sc_havekar_support_2", 1], + ["ntr_gaunter_odimm_darkness", 3], + ["ntr_dandelion", 1], + ["ntr_gaunter_odimm", 1], + ["ntr_cow", 1], + ["sc_havekar_nurse", 1], + ["sc_havekar_nurse_1", 1], + ["ntr_mysterious_elf", 1] + ] + }, + { + "title": "Default Skellige Deck 1", + "description": "TBD", + "leader": "sk_crach_an_craite", + "faction": "skellige", + "cards": [ + ["spe_horn", 1], + ["spe_mardroeme", 1], + ["spe_scorch", 1], + ["spe_frost", 1], + ["spe_storm", 1], + ["spe_rain", 1], + ["ntr_ciri", 1], + ["ntr_geralt", 1], + ["sk_olaf", 1], + ["sk_cerys", 1], + ["sk_ermion", 1], + ["ntr_villen", 1], + ["ntr_yennefer", 1], + ["sk_craite_warrior_1", 1], + ["sk_craite_warrior_2", 1], + ["sk_craite_warrior_3", 1], + ["sk_dimun_pirate", 1], + ["ntr_olgierd", 1], + ["sk_shield_maiden_1", 1], + ["sk_shield_maiden_2", 1], + ["sk_shield_maiden_3", 1], + ["sk_light_longship", 3], + ["sk_birna", 1], + ["ntr_dandelion", 1], + ["sk_young_berserker", 3], + ["sk_kambi", 1], + ["ntr_mysterious_elf", 1] + ] + }, + { + "title": "Default Skellige Deck 2", + "description": "TBD", + "leader": "sk_crach_an_craite", + "faction": "skellige", + "cards": [ + ["spe_horn", 1], + ["spe_decoy", 2], + ["ntr_ciri", 1], + ["ntr_geralt", 1], + ["sk_olaf", 1], + ["sk_cerys", 1], + ["ntr_villen", 1], + ["sk_craite_warrior_1", 1], + ["sk_craite_warrior_2", 1], + ["sk_craite_warrior_3", 1], + ["sk_dimun_pirate", 1], + ["ntr_olgierd", 1], + ["sk_war_longship_1", 1], + ["sk_war_longship_2", 1], + ["sk_shield_maiden_1", 1], + ["sk_shield_maiden_2", 1], + ["sk_shield_maiden_3", 1], + ["ntr_gaunter_odimm_darkness", 3], + ["sk_light_longship", 3], + ["sk_birna", 1], + ["ntr_mysterious_elf", 1] + ] + } +]; + +/* + * Custom decks with custom cards + */ + +var custom_decks = [ + { + "title": "Northern Realms - Temeria", + "description": "Northern Realms deck focusing on Temerian cards - Playstyle: Tight Bond, Spy", + "leader": "nr_foltest_lord", + "faction": "realms", + "cards": [ + ["spe_horn", 1], + ["spe_decoy", 1], + ["spe_fog", 1], + ["spe_scorch", 1], + ["nr_esterad", 1], + ["nr_natalis", 1], + ["ntr_triss", 1], + ["nr_vernon", 1], + ["nr_ballista", 1], + ["nr_siege_tower", 1], + ["nr_trebuchet_1", 1], + ["nr_blue_stripes_skirmisher_1", 1], + ["nr_blue_stripes_skirmisher_2", 1], + ["nr_blue_stripes_skirmisher_3", 1], + ["nr_blue_stripes_1", 1], + ["nr_blue_stripes_2", 1], + ["nr_blue_stripes_3", 1], + ["nr_dijkstra", 1], + ["nr_thaler", 1], + ["nr_temerian_soldier_1", 1], + ["nr_temerian_soldier_2", 1], + ["nr_temerian_soldier_3", 1], + ["nr_stripes_scout", 1], + ["nr_temerian_drummer", 1], + ["nr_foltest_pride", 1], + ["nr_queen_adalia", 1], + ["nr_mage_infiltrator", 1], + ["nr_aretuza_adept", 1] + ] + }, + { + "title": "Northern Realms - Kaedwen & Aedirn", + "description": "Northern Realms deck focusing on Kaedwen and Aedirn cards - Playstyle: Siege units, Morale boost, Tight Bond", + "leader": "nr_foltest_siegemaster", + "faction": "realms", + "cards": [ + ["spe_horn", 2], + ["spe_decoy", 2], + ["spe_fog", 1], + ["spe_clear", 1], + ["spe_scorch", 2], + ["nr_stennis", 1], + ["nr_vandergrift", 1], + ["nr_kaedweni_siege_support_1", 1], + ["nr_kaedweni_siege_support_2", 1], + ["nr_catapult_1", 1], + ["nr_catapult_2", 1], + ["nr_henselt", 1], + ["nr_kaedweni_reinforcement", 1], + ["nr_reinforced_ballista_1", 1], + ["nr_reinforced_ballista_2", 1], + ["nr_reinforced_trebuchet_1", 1], + ["nr_reinforced_trebuchet_2", 1], + ["nr_banner_nurse", 1], + ["nr_ban_ard_tutor", 1], + ["nr_demavend", 1], + ["nr_kaedweni_knight", 1], + ["nr_dun_banner_heavy_cavalry_1", 1], + ["nr_dun_banner_heavy_cavalry_2", 1], + ["nr_odrin", 1], + ["nr_seltkirk", 1], + ["nr_kaedweni_sergeant", 1], + ["nr_dethmold", 1] + ] + }, + { + "title": "Northern Realms - Cintra & Neighbours", + "description": "Northern Realms deck focusing on Cintra and neighbour minor realsms - Playstyle: Summon Avenger, Slaughter of Cintra, Muster", + "leader": "nr_queen_calanthe", + "faction": "realms", + "cards": [ + ["spe_horn", 1], + ["spe_decoy", 2], + ["spe_storm", 1], + ["spe_clear", 1], + ["spe_scorch", 1], + ["spe_slaughther_cintra_1", 1], + ["spe_slaughther_cintra_2", 1], + ["nr_viraxas", 1], + ["nr_kerack_fleet_marine_2", 1], + ["nr_kerack_fleet_frigate", 1], + ["nr_kerack_fleet_marine_1", 1], + ["nr_vissegerd", 1], + ["nr_cintrian_royal_guard", 1], + ["nr_eist_tuirseach", 1], + ["nr_skellige_fleet_1", 1], + ["nr_skellige_fleet_2", 1], + ["nr_skellige_fleet_3", 1], + ["nr_cintrian_knight", 1], + ["nr_roegner", 1], + ["nr_pavetta", 1], + ["nr_kistrin_verden", 1], + ["nr_sha", 1], + ["nr_kraken", 1], + ["nr_egmund", 1], + ["nr_eylembert_tigg", 1], + ["nr_young_ciri", 1], + ["ntr_ciri", 1], + ["nr_cintrian_peasants", 1], + ["nr_windhalm", 1] + ] + }, + { + "title": "Northern Realms - Redania", + "description": "Northern Realms deck focusing on Redania - Playstyle: Medic, Tall units, Commander's Horn", + "leader": "nr_radovid_ruthless", + "faction": "realms", + "cards": [ + ["spe_horn", 1], + ["spe_decoy", 2], + ["spe_rain", 1], + ["spe_clear", 1], + ["spe_scorch", 1], + ["nr_redanian_elite", 1], + ["nr_donimir_troy", 1], + ["nr_joachim_gratz", 1], + ["nr_philippa", 1], + ["nr_ewald_borsodi", 1], + ["nr_flying_redanian", 1], + ["nr_redanian_knight", 1], + ["nr_shani", 1], + ["nr_milo_vanderbeck", 1], + ["nr_marching_orders", 1], + ["nr_eyck_denesle", 1], + ["nr_radovid_royal_guards", 1], + ["nr_redanian_archer", 1], + ["nr_trollololo", 1], + ["nr_battering_ram", 1], + ["nr_dijkstra", 1], + ["nr_falibor", 1], + ["nr_siegfried", 1], + ["nr_reinforced_tower", 1], + ["nr_crinfrid_1", 1], + ["nr_crinfrid_2", 1], + ["nr_crinfrid_3", 1], + ["nr_voymir", 1], + ["nr_reaver_scout", 1], + ["nr_tridam_infantry", 1] + ] + }, + { + "title": "Nilfgaard Empire - Army", + "description": "Nilfgaard Empire deck focusing on army cards - Playstyle: Tight Bond, Heroes, Medic, Horn", + "leader": "ne_emhyr_relentless", + "faction": "nilfgaard", + "cards": [ + ["spe_fog", 1], + ["spe_decoy", 2], + ["spe_rain", 1], + ["spe_clear", 2], + ["spe_scorch", 2], + ["ne_vicovaro_medic", 1], + ["ne_nauzicaa_1", 1], + ["ne_nauzicaa_2", 1], + ["ne_nauzicaa_3", 1], + ["ne_shilard", 1], + ["ne_alba_pikeman_1", 1], + ["ne_archer_support", 1], + ["ne_archer_support_1", 1], + ["ne_nausicaa_brigade", 1], + ["ne_imperial_golem", 1], + ["ne_daerlan_soldier", 1], + ["ne_hefty_helge", 1], + ["ne_heavy_zerri", 1], + ["ne_slave_infantry_1", 1], + ["ne_slave_infantry_2", 1], + ["ne_magne_division", 1], + ["ne_emissary", 1], + ["ne_alba_spearman", 1], + ["ne_standard_bearer", 1], + ["ne_black_archer", 1], + ["ne_black_archer_1", 1], + ["ne_deithwen_arbalest", 1], + ["ne_guardian", 1], + ["ne_siege_support", 1], + ["ne_nausicaa_standard_bearer", 1], + ["ne_knight", 1], + ["ne_alba_armored_cavalry", 1], + ["ne_menno", 1] + + ] + }, + { + "title": "Nilfgaard Empire - Nobility", + "description": "Nilfgaard Empire deck focusing on the nobility & aristocrats - Playstyle: Tight Bond, Spy", + "leader": "ne_emhyr_emperor", + "faction": "nilfgaard", + "cards": [ + ["spe_fog", 2], + ["spe_horn", 2], + ["spe_clear", 2], + ["spe_scorch", 1], + ["ne_impera_brigade_1", 1], + ["ne_impera_brigade_2", 1], + ["ne_impera_brigade_3", 1], + ["ne_impera_brigade_4", 1], + ["ne_impera_brigade_5", 1], + ["ne_jan_calveit", 1], + ["ne_vattier", 1], + ["ne_letho", 1], + ["ne_bribery", 1], + ["ne_moorvran", 1], + ["ne_fringilla", 1], + ["ne_fergus_emreis",1], + ["ne_young_emissary_1", 1], + ["ne_young_emissary_2", 1], + ["ne_cahir", 1], + ["ne_stefan", 1], + ["ne_usurper", 1], + ["ne_cantarella", 1], + ["ne_assire", 1], + ["ne_treason", 1], + ["ne_peter_saar_gwynleve", 1], + ["ne_xarthisius", 1], + ["ne_impera_enforcers", 1], + ["ne_imperial_diviner", 1], + ["ne_renuald", 1] + ] + }, + { + "title": "Nilfgaard Empire - Second Army", + "description": "Nilfgaard Empire deck focusing on other army units - Playstyle: Muster", + "leader": "ne_emhyr_invader_of_the_north", + "faction": "nilfgaard", + "cards": [ + ["spe_rain", 1], + ["spe_fog", 1], + ["spe_horn", 2], + ["spe_clear", 1], + ["spe_scorch", 1], + ["spe_decoy", 1], + ["ne_tibor", 1], + ["ne_ardal_aep_dahy", 1], + ["ne_glynnis_loernach", 1], + ["ne_ard_feainn_crossbowman", 1], + ["ne_ard_feainn_light_cavalry", 3], + ["ne_ard_feainn_tortoise", 3], + ["ne_ard_feainn_heavy_cavalry", 1], + ["ne_ramon_tyrconnel", 1], + ["ne_ffion_gaernel", 1], + ["ne_vrygheff", 1], + ["ne_epidemic", 1], + ["ne_rot_tosser", 1], + ["ne_traheaern_vdyffir", 1], + ["ne_vreemde", 1], + ["ne_spotter", 1], + ["ne_illusionist", 1], + ["ne_mangonel", 1], + ["ne_joachim_de_wett", 1], + ["ne_imperial_practitioner", 1] + ] + }, + { + "title": "Monsters - Wild Hunt & Giants", + "description": "Monsters deck focusing on the wild hunt and giants - Playstyle: Muster, Tall units", + "leader": "mo_eredin_bringer_of_death", + "faction": "monsters", + "cards": [ + ["spe_fog", 2], + ["spe_decoy", 2], + ["spe_clear", 1], + ["spe_scorch", 2], + ["spe_horn", 1], + ["mo_witch_velen", 1], + ["mo_witch_velen_1", 1], + ["mo_witch_velen_2", 1], + ["mo_golem", 1], + ["mo_geels", 1], + ["mo_ifrit_1", 1], + ["mo_ifrit_2", 1], + ["mo_fire_elemental", 1], + ["mo_wild_hunt_rider_1", 1], + ["mo_wild_hunt_rider_2", 1], + ["mo_wild_hunt_rider_3", 1], + ["mo_nithral", 1], + ["mo_therazane", 1], + ["mo_naglfar", 1], + ["mo_caranthir", 1], + ["mo_jotunn", 1], + ["mo_frost_giant", 1], + ["mo_imlerith", 1], + ["mo_old_speartip", 1], + ["mo_navigator", 1], + ["mo_cyclops", 1], + ["mo_ice_troll", 1], + ["mo_earth_elemental", 1] + ] + }, + { + "title": "Monsters - Beasts & Creatures", + "description": "Monsters deck focusing on the multitude of beasts and creatures - Playstyle: Muster", + "leader": "mo_eredin_commander", + "faction": "monsters", + "cards": [ + ["spe_rain", 2], + ["spe_decoy", 1], + ["spe_clear", 1], + ["spe_scorch", 1], + ["spe_horn", 2], + ["mo_morvudd", 1], + ["mo_fleder", 1], + ["mo_garkain", 1], + ["mo_ekkima", 1], + ["mo_bruxa", 1], + ["mo_katakan", 1], + ["mo_ghoul", 1], + ["mo_ghoul_1", 1], + ["mo_ghoul_2", 1], + ["mo_kayran", 1], + ["mo_lamia_1", 1], + ["mo_lamia_2", 1], + ["mo_lamia_3", 1], + ["mo_glustyworp", 1], + ["mo_alghoul", 1], + ["mo_archgriffin", 1], + ["mo_alp", 1], + ["mo_toad", 1], + ["mo_arachas", 1], + ["mo_arachas_1", 1], + ["mo_arachas_2", 1], + ["mo_arachas_behemoth", 1], + ["mo_armoured_arachas", 1], + ["mo_leshen", 1], + ["mo_dragon_fyresdal", 1], + ["mo_manticore", 1], + ["mo_manticore_venom", 1] + ] + }, + { + "title": "Scoia'Tael - Commandos", + "description": "Scoia'Tael deck focusing on the commandos units - Playstyle: Muster, Medic", + "leader": "sc_francesca_daisy", + "faction": "scoiatael", + "cards": [ + ["spe_rain", 1], + ["spe_decoy", 2], + ["spe_clear", 1], + ["spe_scorch", 1], + ["spe_horn", 2], + ["sc_elven_mercenary_1", 1], + ["sc_elven_mercenary_2", 1], + ["sc_vrihedd_sapper", 1], + ["sc_havekar_nurse", 1], + ["sc_havekar_nurse_1", 1], + ["sc_havekar_nurse_2", 1], + ["sc_iorveth", 1], + ["sc_vrihedd_dragoon_1", 1], + ["sc_vrihedd_dragoon_2", 1], + ["sc_vrihedd_dragoon_3", 1], + ["sc_isengrim", 1], + ["sc_vrihedd_brigade", 1], + ["sc_vrihedd_brigade_1", 1], + ["sc_havekar_support", 1], + ["sc_havekar_support_1", 1], + ["sc_havekar_support_2", 1], + ["sc_aelirenn", 1], + ["sc_saesenthessis_saskia", 1], + ["sc_saesenthessis_dragon", 1], + ["sc_neophyte", 1], + ["sc_yaevinn", 1], + ["sc_vrihedd_officer", 1] + ] + }, + { + "title": "Scoia'Tael - Independant Realms", + "description": "Scoia'Tael deck focusing on the non-humans realms such as Dol Blathanna, Mahakam or Brokilon - Playstyle: Muster, Morale", + "leader": "sc_francesca_beautiful", + "faction": "scoiatael", + "cards": [ + ["spe_rain", 1], + ["spe_frost", 1], + ["spe_decoy", 1], + ["spe_clear", 1], + ["spe_scorch", 2], + ["spe_horn", 1], + ["sc_eithne", 1], + ["sc_barclay", 1], + ["sc_dol_blathanna_sentry", 1], + ["sc_milva", 1], + ["sc_dryads_1", 1], + ["sc_dryads_2", 1], + ["sc_dryads_3", 1], + ["sc_dryads_4", 1], + ["sc_brouver_hoog", 1], + ["sc_dol_blathanna_guard_1", 1], + ["sc_dol_blathanna_guard_2", 1], + ["sc_dol_blathanna_guard_3", 1], + ["sc_aglais", 1], + ["sc_elven_deadeye", 1], + ["sc_morenn", 1], + ["sc_mahakam_pyrotechnician", 1], + ["sc_mahakam_guard_1", 1], + ["sc_mahakam_guard_2", 1], + ["sc_mahakam_ale", 1], + ["sc_yannick_brass", 1], + ["sc_dol_blathanna_trapper", 1], + ["sc_gabor_zigrin", 1] + ] + }, + { + "title": "Skellige - Ard Skellig & Svalblod", + "description": "Skellige deck focusing on the cards from Ard Skellige and the Svalblod cult - Playstyle: Berserker, Muster, Tight Bond", + "leader": "sk_crach_an_craite", + "faction": "skellige", + "cards": [ + ["spe_storm", 1], + ["spe_mardroeme", 3], + ["spe_decoy", 2], + ["spe_clear", 1], + ["spe_scorch", 1], + ["spe_horn", 1], + ["sk_blueboy", 1], + ["sk_hjalmar", 1], + ["sk_vabjorn", 1], + ["sk_young_berserker", 3], + ["sk_shield_maiden_1", 1], + ["sk_shield_maiden_2", 1], + ["sk_shield_maiden_3", 1], + ["sk_an_craite_greatsword", 1], + ["sk_drummond_warmonger", 1], + ["sk_madman_lugos", 1], + ["sk_harald_cripple", 1], + ["sk_craite_warrior_1", 1], + ["sk_craite_warrior_2", 1], + ["sk_craite_warrior_3", 1], + ["sk_cerys", 1], + ["sk_ermion", 1], + ["sk_svalblod_fanatic", 1], + ["sk_berserker", 1], + ["sk_drummond_berserker", 1], + ["sk_svalblod", 1], + ["sk_chosen_berserker", 1] + ] + }, + { + "title": "Skellige - Small islands", + "description": "Skellige deck focusing on the cards from the other islands - Playstyle: Muster, Tight Bond, Medic", + "leader": "sk_king_bran", + "faction": "skellige", + "cards": [ + ["spe_frost", 3], + ["spe_decoy", 2], + ["spe_scorch", 2], + ["spe_horn", 2], + ["sk_olaf", 1], + ["sk_birna", 1], + ["sk_war_longship_1", 1], + ["sk_war_longship_2", 1], + ["sk_war_longship_3", 1], + ["sk_dimun_pirate_captain", 1], + ["sk_vigi_loon", 1], + ["sk_light_longship", 3], + ["sk_brokva_archer", 2], + ["sk_tuirseach_warrior_1", 1], + ["sk_tuirseach_warrior_2", 1], + ["sk_heymaey_flaminica", 1], + ["sk_eist_tuirseach", 1], + ["sk_kambi", 1], + ["sk_arnjolf", 1], + ["sk_otkell", 1], + ["sk_dagur", 1], + ["sk_sigrdrifa", 1], + ["sk_dimun_pirate", 1], + ["sk_jutta", 1], + ["sk_hemdall", 1] + ] + }, + { + "title": "Witcher Universe - Fighters & Mages", + "description": "Witcher Universe deck focusing on the famous fighters and mages - Playstyle: Muster, Medic", + "leader": "wu_vilgefortz_magician_kovir", + "faction": "witcher_universe", + "cards": [ + ["spe_frost", 1], + ["spe_fog", 1], + ["spe_decoy", 1], + ["spe_clear", 1], + ["spe_scorch", 1], + ["spe_horn", 1], + ["wu_tissaia", 1], + ["wu_rats_giselher", 1], + ["wu_rats_asse", 1], + ["wu_rats_iskra", 1], + ["wu_rats_kayleigh", 1], + ["wu_rats_mistle", 1], + ["wu_rats_reef", 1], + ["wu_ralf_blunden", 1], + ["wu_bomb_heaver", 1], + ["wu_gascon_light_cavalry", 1], + ["wu_gascon_slinger", 1], + ["wu_gascon_infiltrator", 1], + ["wu_gascon", 1], + ["wu_dorregaray", 1], + ["wu_ortolan", 1], + ["wu_coral", 1], + ["wu_leo_bonhart", 1], + ["wu_azar_javed", 1], + ["wu_strays_spalla", 1], + ["wu_gerhart_aelle", 1], + ["wu_lydia_bredevoort", 1], + ["wu_dana_meadbh", 1], + ["wu_rience", 1], + ["wu_visenna", 1], + ["wu_operator",1] + ] + }, + { + "title": "Witcher Universe - Witchers", + "description": "Witcher Universe deck focusing on witcher schools - Playstyle: Witcher Schools, Resilience, Scorch", + "leader": "wu_cosimo_malaspina", + "faction": "witcher_universe", + "cards": [ + ["wu_coen", 1], + ["wu_stygga_castle", 1], + ["wu_vesemir", 1], + ["wu_haern_caduch", 1], + ["wu_ivo_belhaven", 1], + ["wu_lambert", 1], + ["wu_keldar", 1], + ["wu_ivar", 1], + ["wu_gorthur_gvaed", 1], + ["wu_kaer_morhen", 1], + ["wu_kaer_seren", 1], + ["wu_gezras", 1], + ["wu_geralt_1", 1], + ["wu_gaetan", 1], + ["wu_brehen", 1], + ["wu_gerd", 1], + ["wu_warrit", 1], + ["wu_erland", 1], + ["wu_arnaghad", 1], + ["wu_letho", 1], + ["wu_eskel", 1], + ["wu_kolgrim", 1], + ["spe_sign_igni", 2], + ["spe_sign_quen", 2], + ["spe_sign_axii", 2], + ["spe_sign_aard", 2], + ["spe_sign_yrden", 2], + ["wu_swallow_potion", 1], + ] + }, + { + "title": "Witcher Universe - Demons & Creatures", + "description": "Witcher Universe deck focusing on demons and rare creatures - Playstyle: Muster, Scorch, Spy", + "leader": "wu_alzur_maker", + "faction": "witcher_universe", + "cards": [ + ["spe_horn", 1], + ["spe_sign_yrden", 1], + ["spe_rain", 1], + ["spe_decoy", 2], + ["spe_scorch", 2], + ["spe_clear", 1], + ["wu_doppler_1", 1], + ["ntr_gaunter_odimm_darkness", 3], + ["ntr_gaunter_odimm", 1], + ["wu_idr", 1], + ["wu_iris_von_everec", 1], + ["wu_sarah", 1], + ["wu_djinn", 1], + ["wu_myrgtabrakke", 1], + ["wu_vincent_meis", 1], + ["wu_raging_bear", 1], + ["wu_iris_companions_1", 1], + ["wu_iris_companions_2", 1], + ["wu_vlodimir_von_everec", 1], + ["wu_phoenix", 1], + ["wu_boris", 1], + ["ntr_olgierd", 1], + ["wu_marlene_trastamara", 1], + ["wu_idarran_ulivo", 1], + ["wu_mad_kiyan", 1], + ["wu_cicada", 1], + ["wu_nivellen", 1] + + ] + }, + { + "title": "Witcher Universe - Geralt & Friends", + "description": "Witcher Universe deck focusing on Geralt and his friends - Playstyle: Muster, Summon Avenger, Medic", + "leader": "wu_vilgefortz_sorcerer", + "faction": "witcher_universe", + "cards": [ + ["spe_horn", 1], + ["spe_sign_aard", 1], + ["spe_rain", 1], + ["spe_fog", 1], + ["spe_clear", 1], + ["wu_doppler_2", 1], + ["wu_pellar", 1], + ["ntr_yennefer", 1], + ["ntr_geralt", 1], + ["wu_kelpie", 1], + ["wu_vysogota", 1], + ["wu_angouleme", 1], + ["wu_tea_vea_1", 1], + ["wu_tea_vea_2", 1], + ["wu_iola", 1], + ["ntr_villen", 1], + ["wu_rhapsodic_melody", 1], + ["ntr_mysterious_elf", 1], + ["ntr_zoltan", 1], + ["ntr_triss", 1], + ["wu_nenneke", 1], + ["wu_roach", 1], + ["ntr_dandelion", 1], + ["ntr_emiel", 1], + ["ntr_ciri", 1], + ["ntr_vesemir", 1], + ["wu_kalkstein", 1] + ] + }, + { + "title": "Toussaint - Knight & Nobles", + "description": "Toussaint deck focusing on knight and nobles - Playstyle: Tight Bond, Muster, Tall units", + "leader": "to_anna_henrietta_duchess", + "faction": "toussaint", + "cards": [ + ["spe_horn", 2], + ["spe_toussaint_wine", 1], + ["spe_rain", 1], + ["spe_frost", 1], + ["spe_clear", 1], + ["spe_scorch", 1], + ["spe_decoy", 1], + ["to_dun_tynne_infantry", 1], + ["to_champion", 1], + ["to_panther_1", 1], + ["to_panther_2", 1], + ["to_panther_3", 1], + ["to_knight_errant_1", 1], + ["to_knight_errant_2", 1], + ["to_knight_errant_3", 1], + ["to_damien_tour", 1], + ["to_gregoire_gorgon", 1], + ["to_lady_lake", 1], + ["to_jousting_champion", 1], + ["to_guillaume", 1], + ["to_artorius_vigo", 1], + ["to_fringilla_vigo", 1], + ["to_beauclair_cavalry_1", 1], + ["to_beauclair_cavalry_2", 1], + ["to_milton", 1], + ["to_palmerin", 1], + ["to_vivienne_oriole", 1], + ["to_syanna", 1], + ["to_fisher_king", 1] + ] + }, + { + "title": "Toussaint - Monsters", + "description": "Toussaint deck focusing on vampires and other monsters - Playstyle: Muster, Tall units", + "leader": "to_anna_henrietta_ladyship", + "faction": "toussaint", + "cards": [ + ["spe_horn", 1], + ["spe_toussaint_wine", 2], + ["spe_rain", 1], + ["spe_clear", 2], + ["spe_scorch", 1], + ["to_protofleder", 1], + ["to_dettlaff_higher_vampire", 1], + ["to_barghest_1", 1], + ["to_barghest_2", 1], + ["to_barghest_3", 1], + ["to_cloud_giant", 1], + ["to_garkain", 1], + ["to_wolves_1", 1], + ["to_wolves_2", 1], + ["to_yghern", 1], + ["to_unseen_elder", 1], + ["to_alpha_garkain", 1], + ["to_archespore", 1], + ["to_dettlaff", 1], + ["to_dettlaff_ghastly_beast", 1], + ["to_bruxa_corvo_bianco", 1], + ["to_orianna", 1], + ["to_lacerate", 1], + ["to_fleder", 1], + ["to_golyat", 1], + ["to_tufo_monster", 1], + ["to_shaelmaar", 1] + ] + }, + { + "title": "Lyria & Rivia - First Line", + "description": "Lyria & Rivia deck focusing on cards of the first line (Melee/Ranged) - Playstyle: Muster, Medic", + "leader": "lr_meve_princess", + "faction": "lyria_rivia", + "cards": [ + ["spe_horn", 1], + ["spe_decoy", 1], + ["spe_rain", 1], + ["spe_clear", 2], + ["spe_scorch", 1], + ["lr_rivian_mauler", 1], + ["lr_grey_rider", 2], + ["lr_prince_anseis", 1], + ["lr_royal_guard", 1], + ["lr_landsknecht", 3], + ["lr_knighthood", 1], + ["lr_reynard_odo", 1], + ["lr_war_wagon", 1], + ["lr_wagenburg", 3], + ["lr_gascon", 1], + ["lr_pikeman", 1], + ["lr_light_cavalry", 2], + ["lr_rayla", 1], + ["lr_wagon", 1], + ["lr_lyrian_cavalry", 1], + ["lr_isbel_hagge", 1], + ["lr_hajduk", 1], + ["ntr_geralt", 1], + ["spe_wyvern_shield", 1], + ["spe_mantlet", 1] + ] + }, + { + "title": "Lyria & Rivia - Rear Guard", + "description": "Lyria & Rivia deck focusing on cards of the rear guard (Ranged/Siege) - Playstyle: Scorch, Spy, Medic", + "leader": "lr_meve_white_queen", + "faction": "lyria_rivia", + "cards": [ + ["spe_horn", 1], + ["spe_decoy", 1], + ["spe_frost", 2], + ["spe_clear", 1], + ["spe_scorch", 1], + ["spe_garrison", 1], + ["lr_piercing_missile", 1], + ["lr_eavesdrop", 1], + ["lr_trebuchet", 1], + ["lr_arbalest", 3], + ["lr_spellweaver", 1], + ["lr_forager", 1], + ["lr_sapper", 1], + ["lr_villem", 1], + ["lr_scout", 1], + ["lr_winch", 1], + ["lr_banner", 1], + ["lr_scytheman_2", 1], + ["lr_scytheman_3", 1], + ["lr_caldwell", 1], + ["lr_physician", 1], + ["lr_pyrokinesis", 1], + ["lr_carroballista", 1], + ["lr_artificer", 1], + ["lr_siege", 1], + ["lr_onager", 1] + ] + }, + { + "title": "Syndicate - Church of Eternal Fire", + "description": "Syndicate deck focusing on cards of the Eternal Fire - Playstyle: Witch Hunt, Muster, Dimeritium", + "leader": "sy_cyrus_hemmelfart", + "faction": "syndicate", + "cards": [ + ["spe_horn", 1], + ["spe_decoy", 2], + ["spe_rain", 1], + ["spe_clear", 1], + ["spe_dimeritium_shackles", 2], + ["sy_flaming_rose_footman", 1], + ["sy_witch_hunter", 1], + ["sy_witch_hunter_executioner", 1], + ["sy_eternal_fire_inquisitor", 1], + ["sy_caleb_menge", 1], + ["sy_moreelse", 1], + ["sy_jacques_aldersberg", 1], + ["sy_temple_guard", 1], + ["sy_roderick_wett", 1], + ["sy_ulrich", 1], + ["sy_inquisitional_pyres", 1], + ["sy_walter_veritas", 1], + ["sy_eternal_fire_priest_1", 1], + ["sy_eternal_fire_priest_2", 1], + ["sy_eternal_fire_priest_3", 1], + ["sy_octavia_hale", 1], + ["sy_fabian_hale", 1], + ["sy_ignatius_hale", 1], + ["sy_cleric_flaming_rose", 1], + ["sy_eternal_fire_disciple", 2], + ["sy_lonely_champion", 1], + ["sy_inquisitor_helveed", 1] + ] + }, + { + "title": "Syndicate - Salamandra", + "description": "Syndicate deck focusing on cards of the Salamandra - Playstyle: Muster, Scorch, Summon Avenger", + "leader": "sy_azar_javed", + "faction": "syndicate", + "cards": [ + ["spe_horn", 1], + ["spe_decoy", 2], + ["spe_rain", 1], + ["spe_clear", 1], + ["spe_scorch", 2], + ["sy_greater_brothers", 1], + ["sy_mutant_killer", 1], + ["sy_mutated_hound_1", 1], + ["sy_mutated_hound_2", 1], + ["sy_mutant_maker", 1], + ["sy_fisstech_trafficker", 1], + ["sy_fisstech", 1], + ["sy_professor", 1], + ["sy_salamandra_assassin", 1], + ["sy_salamandra_assassin_2", 1], + ["sy_savolla", 1], + ["sy_fallen_rayla", 1], + ["sy_gellert_bleinheim", 1], + ["sy_roland_bleinheim", 1], + ["sy_salamandra_lackey", 1], + ["sy_mutant", 3], + ["sy_salamandra_mage", 1], + ["sy_failed_experiment", 1], + ["sy_frightener", 1], + ["sy_stolen_mutagens", 1] + ] + }, + { + "title": "Syndicate - Novigrad Gangs", + "description": "Syndicate deck focusing on cards of the Gangs of Novigrad - Playstyle: Spy, Tight Bond, Muster", + "leader": "sy_cyprian_wiley", + "faction": "syndicate", + "cards": [ + ["spe_horn", 1], + ["spe_rain", 1], + ["spe_clear", 1], + ["spe_scorch", 2], + ["spe_vivaldi_bank", 2], + ["sy_bare_knuckle_brawler", 1], + ["sy_casino_bouncers", 1], + ["sy_cleaver_gang_1", 1], + ["sy_cleaver_gang_2", 1], + ["sy_cleaver_gang_3", 1], + ["sy_cleaver_gang_4", 1], + ["sy_robber_1", 1], + ["sy_robber_2", 1], + ["sy_robber_3", 1], + ["sy_igor_hook", 1], + ["sy_ferko", 1], + ["sy_hvitr_aelydia", 1], + ["sy_bincy_blumerholdt", 1], + ["sy_freak_show_1", 1], + ["sy_freak_show_2", 1], + ["sy_freak_show_3", 1], + ["sy_freak_show_4", 1], + ["sy_beggar", 1], + ["sy_whoreson_senior", 1], + ["sy_imke", 1], + ["sy_sly_seductress", 1], + ["sy_madame_luiza", 1], + ["sy_rico_meiersdorf", 1], + ["sy_sewer_raider", 1], + ["sy_boris", 1] + ] + }, + { + "title": "Zerrikania - Dragon Cult", + "description": "Zerrikania deck focusing on dragons and their whorshippers - Playstyle: Worshipper / Whorshipped", + "leader": "ze_zerrikanterment", + "faction": "zerrikania", + "cards": [ + ["spe_horn", 1], + ["spe_decoy", 2], + ["spe_dragon_wrath", 1], + ["spe_tse_tse_flies", 1], + ["spe_clear", 1], + ["spe_scorch", 1], + ["ze_villentretenmerth", 1], + ["ze_myrgtabrakke", 1], + ["ze_merineaevelth", 1], + ["ze_ocvist", 1], + ["ze_keltullis", 1], + ["ze_ostreverg", 1], + ["ze_germinus", 1], + ["ze_first_faithel_kia", 1], + ["ze_tea_vea_1", 1], + ["ze_tea_vea_2", 1], + ["ze_faithel_1", 1], + ["ze_faithel_2", 1], + ["ze_faithel_3", 1], + ["ze_balladeer", 1], + ["ze_tiger_1", 1], + ["ze_tiger_2", 1], + ["ze_yellow_witch_korath", 1], + ["ze_emetouka", 1], + ["ze_dragon_priestess_lua", 1], + ["ze_high_priestess_nia", 1], + ["ze_apucunpture_healer", 1], + ["ze_collective_trance", 1], + ] + }, + { + "title": "Zerrikania - Army", + "description": "Zerrikania deck focusing on fighting units and creatures - Playstyle: Inspire, Scorch, Tall units", + "leader": "ze_rarog", + "faction": "zerrikania", + "cards": [ + ["spe_horn", 2], + ["spe_decoy", 1], + ["spe_giant_spider_web", 2], + ["spe_clear", 1], + ["spe_scorch", 1], + ["ze_hippotoxotai_1", 1], + ["ze_hippotoxotai_2", 1], + ["ze_hippotoxotai_3", 1], + ["ze_azar_javed", 1], + ["ze_bomb_maker_1", 1], + ["ze_giant_spotted_spider", 1], + ["ze_free_warrior_1", 1], + ["ze_free_warrior_2", 1], + ["ze_free_warrior_3", 1], + ["ze_free_warrior_4", 1], + ["ze_free_warrior_5", 1], + ["ze_heavy_fire_scorpion", 1], + ["ze_skuda_amazon_1", 1], + ["ze_skuda_amazon_2", 1], + ["ze_behemoth", 1], + ["ze_war_elephant", 1], + ["ze_sandworm", 1], + ["ze_alchemist", 1], + ["ze_lilit_niya", 1], + ["ze_myrgot", 1], + ["ze_venomous_basilisk", 1], + ["ze_saulrenith", 1], + ] + } +]; + +/* + * + */ + +var premade_deck = default_decks; +//premade_deck = custom_decks.concat(premade_deck); +//premade_deck = custom_decks; + +var deckWeightConsts = { + "spyBase": 20, + "heroMult": 2, + "musterMult": 2, + "tightBondMult": 2, + "medic": 7, + "scorch": 5, + "scorch_c": 5, + "morale": 5, + "agile": 2, + "horn": 10, + "berserker": 5, + "mardroeme": 5, + "avenger": 5, + "decoy": 7, + "clearWeatherWeight": 7, + "heroSpyBase": 5, + "cintra_slaughter": 5, + "resilience": 5, + "witcherSchoolWeight": 1, + "witch_hunt": 5, + "whorshipper": 2, + "whorshipped": 2, + "inspire": 3 +}; + +function calcDeckWeight(deck) { + var total = 0; + deck.cards.forEach(entry => { + let c = card_dict[entry[0]]; + let cnt = parseInt(entry[1]); + let abi = c["ability"].split(" "); + let cStr = 0; + if (!c["deck"].startsWith("special") && !c["deck"].startsWith("weather")) { + if (abi.includes("spy")) { + cStr = deckWeightConsts["spyBase"] - parseInt(c["strength"]); + if (abi.includes("hero")) + cStr += deckWeightConsts["heroSpyBase"]; + if (c.row === "agile") + cStr += deckWeightConsts["agile"]; + } else { + cStr = parseInt(c["strength"]); + if (abi.includes("hero")) + cStr *= deckWeightConsts["heroMult"]; + if (abi.includes("bond")) + cStr *= deckWeightConsts["tightBondMult"]; + if (abi.includes("muster")) + cStr *= deckWeightConsts["musterMult"]; + abi.forEach(a => { + if (a in deckWeightConsts) + cStr += deckWeightConsts[a]; + }); + if (abi.includes("witcher_wolf_school") || abi.includes("witcher_bear_school") || abi.includes("witcher_viper_school") || abi.includes("witcher_cat_school") || abi.includes("witcher_griffin_school")) + cStr += deckWeightConsts["witcherSchoolWeight"]; + if (c.row === "agile") + cStr += deckWeightConsts["agile"]; + } + } + total += (cStr*cnt); + }); + return total; +} \ No newline at end of file diff --git a/decks/lyria_rivia_1_first_line.json b/decks/lyria_rivia_1_first_line.json new file mode 100644 index 0000000..78f3d0c --- /dev/null +++ b/decks/lyria_rivia_1_first_line.json @@ -0,0 +1 @@ +{"faction":"lyria_rivia","leader":"lr_meve_princess","cards":[["spe_horn",1],["spe_decoy",1],["spe_mantlet",1],["spe_scorch",1],["spe_wyvern_shield",1],["spe_clear",2],["spe_rain",1],["ntr_geralt",1],["lr_gascon",1],["lr_knighthood",1],["lr_prince_anseis",1],["lr_rayla",1],["lr_reynard_odo",1],["lr_royal_guard",1],["lr_lyrian_cavalry",1],["lr_rivian_mauler",1],["lr_pikeman",1],["lr_light_cavalry",2],["lr_grey_rider",2],["lr_isbel_hagge",1],["lr_war_wagon",1],["lr_hajduk",1],["lr_landsknecht",3],["lr_wagenburg",3],["lr_wagon",1]]} \ No newline at end of file diff --git a/decks/lyria_rivia_2_rear_guard.json b/decks/lyria_rivia_2_rear_guard.json new file mode 100644 index 0000000..50d5e7d --- /dev/null +++ b/decks/lyria_rivia_2_rear_guard.json @@ -0,0 +1 @@ +{"faction":"lyria_rivia","leader":"lr_meve_white_queen","cards":[["spe_horn",1],["spe_decoy",1],["spe_garrison",1],["spe_scorch",1],["spe_frost",2],["spe_clear",1],["lr_carroballista",1],["lr_caldwell",1],["lr_trebuchet",1],["lr_villem",1],["lr_pyrokinesis",1],["lr_spellweaver",1],["lr_eavesdrop",1],["lr_onager",1],["lr_siege",1],["lr_forager",1],["lr_scout",1],["lr_winch",1],["lr_arbalest",3],["lr_sapper",1],["lr_scytheman_2",1],["lr_scytheman_3",1],["lr_physician",1],["lr_piercing_missile",1],["lr_artificer",1],["lr_banner",1]]} \ No newline at end of file diff --git a/decks/monsters_1_wild_hunt_giants.json b/decks/monsters_1_wild_hunt_giants.json new file mode 100644 index 0000000..1960fba --- /dev/null +++ b/decks/monsters_1_wild_hunt_giants.json @@ -0,0 +1 @@ +{"faction":"monsters","leader":"mo_eredin_bringer_of_death","cards":[["spe_horn",1],["spe_decoy",2],["spe_scorch",2],["spe_clear",1],["spe_fog",2],["mo_caranthir",1],["mo_geels",1],["mo_ice_troll",1],["mo_imlerith",1],["mo_jotunn",1],["mo_naglfar",1],["mo_therazane",1],["mo_nithral",1],["mo_old_speartip",1],["mo_witch_velen",1],["mo_witch_velen_1",1],["mo_witch_velen_2",1],["mo_cyclops",1],["mo_earth_elemental",1],["mo_fire_elemental",1],["mo_golem",1],["mo_ifrit_1",1],["mo_ifrit_2",1],["mo_frost_giant",1],["mo_navigator",1],["mo_wild_hunt_rider_1",1],["mo_wild_hunt_rider_2",1],["mo_wild_hunt_rider_3",1]]} \ No newline at end of file diff --git a/decks/monsters_2_creatures.json b/decks/monsters_2_creatures.json new file mode 100644 index 0000000..88e4cb4 --- /dev/null +++ b/decks/monsters_2_creatures.json @@ -0,0 +1 @@ +{"faction":"monsters","leader":"mo_eredin_commander","cards":[["spe_horn",2],["spe_decoy",1],["spe_scorch",1],["spe_clear",1],["spe_rain",2],["mo_dragon_fyresdal",1],["mo_leshen",1],["mo_archgriffin",1],["mo_glustyworp",1],["mo_kayran",1],["mo_alp",1],["mo_armoured_arachas",1],["mo_manticore",1],["mo_morvudd",1],["mo_toad",1],["mo_alghoul",1],["mo_arachas_behemoth",1],["mo_katakan",1],["mo_arachas",1],["mo_arachas_1",1],["mo_arachas_2",1],["mo_lamia_1",1],["mo_lamia_2",1],["mo_lamia_3",1],["mo_bruxa",1],["mo_ekkima",1],["mo_fleder",1],["mo_garkain",1],["mo_manticore_venom",1],["mo_ghoul",1],["mo_ghoul_1",1],["mo_ghoul_2",1]]} \ No newline at end of file diff --git a/decks/nilfgaard_1_army.json b/decks/nilfgaard_1_army.json new file mode 100644 index 0000000..5b5ec36 --- /dev/null +++ b/decks/nilfgaard_1_army.json @@ -0,0 +1 @@ +{"faction":"nilfgaard","leader":"ne_emhyr_relentless","cards":[["spe_decoy",2],["spe_scorch",2],["spe_clear",2],["spe_fog",1],["spe_rain",1],["ne_black_archer",1],["ne_black_archer_1",1],["ne_emissary",1],["ne_heavy_zerri",1],["ne_menno",1],["ne_knight",1],["ne_guardian",1],["ne_imperial_golem",1],["ne_deithwen_arbalest",1],["ne_hefty_helge",1],["ne_shilard",1],["ne_alba_armored_cavalry",1],["ne_daerlan_soldier",1],["ne_nausicaa_brigade",1],["ne_alba_pikeman_1",1],["ne_alba_spearman",1],["ne_magne_division",1],["ne_slave_infantry_1",1],["ne_slave_infantry_2",1],["ne_nauzicaa_1",1],["ne_nauzicaa_2",1],["ne_nauzicaa_3",1],["ne_archer_support",1],["ne_archer_support_1",1],["ne_nausicaa_standard_bearer",1],["ne_standard_bearer",1],["ne_vicovaro_medic",1],["ne_siege_support",1]]} \ No newline at end of file diff --git a/decks/nilfgaard_2_nobility.json b/decks/nilfgaard_2_nobility.json new file mode 100644 index 0000000..31e33ca --- /dev/null +++ b/decks/nilfgaard_2_nobility.json @@ -0,0 +1 @@ +{"faction":"nilfgaard","leader":"ne_emhyr_emperor","cards":[["spe_horn",2],["spe_scorch",1],["spe_clear",2],["spe_fog",2],["ne_bribery",1],["ne_cantarella",1],["ne_letho",1],["ne_moorvran",1],["ne_usurper",1],["ne_peter_saar_gwynleve",1],["ne_stefan",1],["ne_fergus_emreis",1],["ne_jan_calveit",1],["ne_xarthisius",1],["ne_assire",1],["ne_cahir",1],["ne_fringilla",1],["ne_imperial_diviner",1],["ne_impera_enforcers",1],["ne_renuald",1],["ne_young_emissary_1",1],["ne_young_emissary_2",1],["ne_vattier",1],["ne_impera_brigade_1",1],["ne_impera_brigade_2",1],["ne_impera_brigade_3",1],["ne_impera_brigade_4",1],["ne_impera_brigade_5",1],["ne_treason",1]]} \ No newline at end of file diff --git a/decks/nilfgaard_3_second_army.json b/decks/nilfgaard_3_second_army.json new file mode 100644 index 0000000..4e46c4f --- /dev/null +++ b/decks/nilfgaard_3_second_army.json @@ -0,0 +1 @@ +{"faction":"nilfgaard","leader":"ne_emhyr_invader_of_the_north","cards":[["spe_horn",2],["spe_decoy",1],["spe_scorch",1],["spe_clear",1],["spe_fog",1],["spe_rain",1],["ne_ffion_gaernel",1],["ne_spotter",1],["ne_tibor",1],["ne_ardal_aep_dahy",1],["ne_vrygheff",1],["ne_ramon_tyrconnel",1],["ne_traheaern_vdyffir",1],["ne_epidemic",1],["ne_joachim_de_wett",1],["ne_vreemde",1],["ne_ard_feainn_heavy_cavalry",1],["ne_ard_feainn_tortoise",3],["ne_glynnis_loernach",1],["ne_mangonel",1],["ne_ard_feainn_crossbowman",1],["ne_illusionist",1],["ne_ard_feainn_light_cavalry",3],["ne_imperial_practitioner",1],["ne_rot_tosser",1]]} \ No newline at end of file diff --git a/decks/nothern_realms_1_temeria.json b/decks/nothern_realms_1_temeria.json new file mode 100644 index 0000000..752ed13 --- /dev/null +++ b/decks/nothern_realms_1_temeria.json @@ -0,0 +1 @@ +{"faction":"realms","leader":"nr_foltest_lord","cards":[["spe_horn",1],["spe_decoy",1],["spe_scorch",1],["spe_fog",1],["nr_esterad",1],["nr_natalis",1],["nr_vernon",1],["nr_foltest_pride",1],["nr_mage_infiltrator",1],["nr_queen_adalia",1],["ntr_triss",1],["nr_ballista",1],["nr_siege_tower",1],["nr_trebuchet_1",1],["nr_stripes_scout",1],["nr_aretuza_adept",1],["nr_blue_stripes_1",1],["nr_blue_stripes_2",1],["nr_blue_stripes_3",1],["nr_blue_stripes_skirmisher_1",1],["nr_blue_stripes_skirmisher_2",1],["nr_blue_stripes_skirmisher_3",1],["nr_dijkstra",1],["nr_temerian_soldier_1",1],["nr_temerian_soldier_2",1],["nr_temerian_soldier_3",1],["nr_temerian_drummer",1],["nr_thaler",1]]} \ No newline at end of file diff --git a/decks/nothern_realms_2_aedirn_kaedwen.json b/decks/nothern_realms_2_aedirn_kaedwen.json new file mode 100644 index 0000000..ffd76e4 --- /dev/null +++ b/decks/nothern_realms_2_aedirn_kaedwen.json @@ -0,0 +1 @@ +{"faction":"realms","leader":"nr_foltest_siegemaster","cards":[["spe_horn",2],["spe_decoy",2],["spe_scorch",2],["spe_clear",1],["spe_fog",1],["nr_ban_ard_tutor",1],["nr_demavend",1],["nr_henselt",1],["nr_seltkirk",1],["nr_vandergrift",1],["nr_catapult_1",1],["nr_catapult_2",1],["nr_dun_banner_heavy_cavalry_1",1],["nr_dun_banner_heavy_cavalry_2",1],["nr_kaedweni_knight",1],["nr_dethmold",1],["nr_banner_nurse",1],["nr_kaedweni_sergeant",1],["nr_stennis",1],["nr_reinforced_trebuchet_1",1],["nr_reinforced_trebuchet_2",1],["nr_reinforced_ballista_1",1],["nr_reinforced_ballista_2",1],["nr_kaedweni_reinforcement",1],["nr_odrin",1],["nr_kaedweni_siege_support_1",1],["nr_kaedweni_siege_support_2",1]]} \ No newline at end of file diff --git a/decks/nothern_realms_3_cintra.json b/decks/nothern_realms_3_cintra.json new file mode 100644 index 0000000..5fe65f6 --- /dev/null +++ b/decks/nothern_realms_3_cintra.json @@ -0,0 +1 @@ +{"faction":"realms","leader":"nr_queen_calanthe","cards":[["spe_horn",1],["spe_decoy",2],["spe_scorch",1],["spe_slaughther_cintra_1",1],["spe_slaughther_cintra_2",1],["spe_clear",1],["spe_storm",1],["ntr_ciri",1],["nr_kraken",1],["nr_eist_tuirseach",1],["nr_pavetta",1],["nr_viraxas",1],["nr_cintrian_knight",1],["nr_egmund",1],["nr_vissegerd",1],["nr_kistrin_verden",1],["nr_roegner",1],["nr_windhalm",1],["nr_cintrian_royal_guard",1],["nr_young_ciri",1],["nr_kerack_fleet_frigate",1],["nr_cintrian_peasants",1],["nr_kerack_fleet_marine_1",1],["nr_kerack_fleet_marine_2",1],["nr_sha",1],["nr_skellige_fleet_1",1],["nr_skellige_fleet_2",1],["nr_skellige_fleet_3",1],["nr_eylembert_tigg",1]]} \ No newline at end of file diff --git a/decks/nothern_realms_4_redania.json b/decks/nothern_realms_4_redania.json new file mode 100644 index 0000000..6b1f5ba --- /dev/null +++ b/decks/nothern_realms_4_redania.json @@ -0,0 +1 @@ +{"faction":"realms","leader":"nr_radovid_ruthless","cards":[["spe_horn",1],["spe_decoy",2],["spe_scorch",1],["spe_clear",1],["spe_rain",1],["nr_eyck_denesle",1],["nr_donimir_troy",1],["nr_flying_redanian",1],["nr_philippa",1],["nr_tridam_infantry",1],["nr_voymir",1],["nr_redanian_knight",1],["nr_falibor",1],["nr_radovid_royal_guards",1],["nr_trollololo",1],["nr_ewald_borsodi",1],["nr_reinforced_tower",1],["nr_battering_ram",1],["nr_reaver_scout",1],["nr_redanian_elite",1],["nr_crinfrid_1",1],["nr_crinfrid_2",1],["nr_crinfrid_3",1],["nr_redanian_archer",1],["nr_siegfried",1],["nr_dijkstra",1],["nr_joachim_gratz",1],["nr_milo_vanderbeck",1],["nr_shani",1],["nr_marching_orders",1]]} \ No newline at end of file diff --git a/decks/scoiatael_1_commandos.json b/decks/scoiatael_1_commandos.json new file mode 100644 index 0000000..40c4d2a --- /dev/null +++ b/decks/scoiatael_1_commandos.json @@ -0,0 +1 @@ +{"faction":"scoiatael","leader":"sc_francesca_daisy","cards":[["spe_horn",2],["spe_decoy",2],["spe_scorch",1],["spe_clear",1],["spe_rain",1],["sc_saesenthessis_dragon",1],["sc_aelirenn",1],["sc_iorveth",1],["sc_isengrim",1],["sc_saesenthessis_saskia",1],["sc_vrihedd_officer",1],["sc_neophyte",1],["sc_elven_mercenary_1",1],["sc_elven_mercenary_2",1],["sc_yaevinn",1],["sc_havekar_support",1],["sc_havekar_support_1",1],["sc_havekar_support_2",1],["sc_vrihedd_brigade",1],["sc_vrihedd_brigade_1",1],["sc_vrihedd_dragoon_1",1],["sc_vrihedd_dragoon_2",1],["sc_vrihedd_dragoon_3",1],["sc_vrihedd_sapper",1],["sc_havekar_nurse",1],["sc_havekar_nurse_1",1],["sc_havekar_nurse_2",1]]} \ No newline at end of file diff --git a/decks/scoiatael_2_independant_realms.json b/decks/scoiatael_2_independant_realms.json new file mode 100644 index 0000000..cf3afdc --- /dev/null +++ b/decks/scoiatael_2_independant_realms.json @@ -0,0 +1 @@ +{"faction":"scoiatael","leader":"sc_francesca_beautiful","cards":[["spe_horn",1],["spe_decoy",1],["spe_scorch",2],["spe_frost",1],["spe_clear",1],["spe_rain",1],["sc_brouver_hoog",1],["sc_eithne",1],["sc_milva",1],["sc_gabor_zigrin",1],["sc_aglais",1],["sc_dol_blathanna_sentry",1],["sc_elven_deadeye",1],["sc_mahakam_pyrotechnician",1],["sc_morenn",1],["sc_yannick_brass",1],["sc_barclay",1],["sc_mahakam_guard_1",1],["sc_mahakam_guard_2",1],["sc_dol_blathanna_trapper",1],["sc_dryads_1",1],["sc_dryads_2",1],["sc_dryads_3",1],["sc_dryads_4",1],["sc_dol_blathanna_guard_1",1],["sc_dol_blathanna_guard_2",1],["sc_dol_blathanna_guard_3",1],["sc_mahakam_ale",1]]} \ No newline at end of file diff --git a/decks/skellige_1_ard_skellig_svalblod.json b/decks/skellige_1_ard_skellig_svalblod.json new file mode 100644 index 0000000..ce6965f --- /dev/null +++ b/decks/skellige_1_ard_skellig_svalblod.json @@ -0,0 +1 @@ +{"faction":"skellige","leader":"sk_crach_an_craite","cards":[["spe_horn",1],["spe_decoy",1],["spe_mardroeme",3],["spe_scorch",1],["spe_clear",1],["spe_storm",2],["sk_svalblod",1],["sk_cerys",1],["sk_harald_cripple",1],["sk_hjalmar",1],["sk_vabjorn",1],["sk_ermion",1],["sk_svalblod_fanatic",1],["sk_morkvarg",1],["sk_blueboy",1],["sk_an_craite_greatsword",1],["sk_craite_warrior_1",1],["sk_craite_warrior_2",1],["sk_craite_warrior_3",1],["sk_madman_lugos",1],["sk_an_craite_raiders",1],["sk_drummond_warmonger",1],["sk_berserker",1],["sk_shield_maiden_1",1],["sk_shield_maiden_2",1],["sk_shield_maiden_3",1],["sk_young_berserker",3]]} \ No newline at end of file diff --git a/decks/skellige_2_small_islands.json b/decks/skellige_2_small_islands.json new file mode 100644 index 0000000..94371b9 --- /dev/null +++ b/decks/skellige_2_small_islands.json @@ -0,0 +1 @@ +{"faction":"skellige","leader":"sk_king_bran","cards":[["spe_horn",2],["spe_decoy",2],["spe_scorch",2],["spe_frost",3],["sk_olaf",1],["sk_hemdall",1],["sk_eist_tuirseach",1],["sk_vigi_loon",1],["sk_jutta",1],["sk_arnjolf",1],["sk_otkell",1],["sk_dagur",1],["sk_brokva_archer",2],["sk_dimun_pirate",1],["sk_dimun_pirate_captain",1],["sk_war_longship_1",1],["sk_war_longship_2",1],["sk_war_longship_3",1],["sk_light_longship",3],["sk_heymaey_flaminica",1],["sk_tuirseach_warrior_1",1],["sk_tuirseach_warrior_2",1],["sk_birna",1],["sk_kambi",1],["sk_sigrdrifa",1]]} \ No newline at end of file diff --git a/decks/syndicate_1_eternal_fire.json b/decks/syndicate_1_eternal_fire.json new file mode 100644 index 0000000..f8e3e94 --- /dev/null +++ b/decks/syndicate_1_eternal_fire.json @@ -0,0 +1 @@ +{"faction":"syndicate","leader":"sy_cyrus_hemmelfart","cards":[["spe_horn",1],["spe_decoy",2],["spe_dimeritium_shackles",2],["spe_clear",1],["spe_rain",1],["sy_inquisitor_helveed",1],["sy_jacques_aldersberg",1],["sy_lonely_champion",1],["sy_ulrich",1],["sy_octavia_hale",1],["sy_caleb_menge",1],["sy_moreelse",1],["sy_roderick_wett",1],["sy_walter_veritas",1],["sy_flaming_rose_footman",1],["sy_fabian_hale",1],["sy_ignatius_hale",1],["sy_cleric_flaming_rose",1],["sy_temple_guard",1],["sy_inquisitional_pyres",1],["sy_eternal_fire_disciple",2],["sy_eternal_fire_priest_1",1],["sy_eternal_fire_priest_2",1],["sy_eternal_fire_priest_3",1],["sy_witch_hunter_executioner",1],["sy_eternal_fire_inquisitor",1],["sy_witch_hunter",1]]} \ No newline at end of file diff --git a/decks/syndicate_2_salamandra.json b/decks/syndicate_2_salamandra.json new file mode 100644 index 0000000..3725536 --- /dev/null +++ b/decks/syndicate_2_salamandra.json @@ -0,0 +1 @@ +{"faction":"syndicate","leader":"sy_azar_javed","cards":[["spe_horn",1],["spe_decoy",2],["spe_scorch",2],["spe_clear",1],["spe_rain",1],["sy_fallen_rayla",1],["sy_greater_brothers",1],["sy_frightener",1],["sy_failed_experiment",1],["sy_fisstech",1],["sy_professor",1],["sy_gellert_bleinheim",1],["sy_roland_bleinheim",1],["sy_mutant_killer",1],["sy_salamandra_mage",1],["sy_savolla",1],["sy_mutant_maker",1],["sy_mutated_hound_1",1],["sy_mutated_hound_2",1],["sy_salamandra_assassin",1],["sy_salamandra_assassin_2",1],["sy_salamandra_lackey",1],["sy_mutant",3],["sy_fisstech_trafficker",1],["sy_stolen_mutagens",1]]} \ No newline at end of file diff --git a/decks/syndicate_3_gangs.json b/decks/syndicate_3_gangs.json new file mode 100644 index 0000000..b3c9481 --- /dev/null +++ b/decks/syndicate_3_gangs.json @@ -0,0 +1 @@ +{"faction":"syndicate","leader":"sy_cyprian_wiley","cards":[["spe_horn",1],["spe_decoy",2],["spe_scorch",2],["spe_vivaldi_bank",2],["spe_clear",1],["spe_rain",1],["sy_igor_hook",1],["sy_boris",1],["sy_casino_bouncers",1],["sy_whoreson_senior",1],["sy_bare_knuckle_brawler",1],["sy_hvitr_aelydia",1],["sy_madame_luiza",1],["sy_sewer_raider",1],["sy_sly_seductress",1],["sy_bincy_blumerholdt",1],["sy_ferko",1],["sy_rico_meiersdorf",1],["sy_robber_1",1],["sy_robber_2",1],["sy_robber_3",1],["sy_robber_4",1],["sy_imke",1],["sy_beggar",1],["sy_cleaver_gang_1",1],["sy_cleaver_gang_2",1],["sy_cleaver_gang_3",1],["sy_cleaver_gang_4",1],["sy_freak_show_1",1],["sy_freak_show_2",1],["sy_freak_show_3",1],["sy_freak_show_4",1]]} \ No newline at end of file diff --git a/decks/toussaint_1_knights_nobles.json b/decks/toussaint_1_knights_nobles.json new file mode 100644 index 0000000..5bf304a --- /dev/null +++ b/decks/toussaint_1_knights_nobles.json @@ -0,0 +1 @@ +{"faction":"toussaint","leader":"to_anna_henrietta_duchess","cards":[["spe_horn",2],["spe_decoy",1],["spe_scorch",1],["spe_toussaint_wine",1],["spe_frost",1],["spe_clear",1],["spe_rain",1],["to_artorius_vigo",1],["to_damien_tour",1],["to_fringilla_vigo",1],["to_gregoire_gorgon",1],["to_champion",1],["to_jousting_champion",1],["to_beauclair_cavalry_1",1],["to_beauclair_cavalry_2",1],["to_vivienne_oriole",1],["to_knight_errant_1",1],["to_knight_errant_2",1],["to_knight_errant_3",1],["to_lady_lake",1],["to_milton",1],["to_palmerin",1],["to_dun_tynne_infantry",1],["to_fisher_king",1],["to_panther_1",1],["to_panther_2",1],["to_panther_3",1],["to_guillaume",1],["to_syanna",1]]} \ No newline at end of file diff --git a/decks/toussaint_2_monsters_vampires.json b/decks/toussaint_2_monsters_vampires.json new file mode 100644 index 0000000..27a6213 --- /dev/null +++ b/decks/toussaint_2_monsters_vampires.json @@ -0,0 +1 @@ +{"faction":"toussaint","leader":"to_anna_henrietta_ladyship","cards":[["spe_horn",1],["spe_scorch",1],["spe_toussaint_wine",2],["spe_clear",2],["spe_rain",1],["to_unseen_elder",1],["to_dettlaff_higher_vampire",1],["to_dettlaff_ghastly_beast",1],["to_yghern",1],["to_lacerate",1],["to_orianna",1],["to_protofleder",1],["to_tufo_monster",1],["to_dettlaff",1],["to_shaelmaar",1],["to_alpha_garkain",1],["to_golyat",1],["to_archespore",1],["to_barghest_1",1],["to_barghest_2",1],["to_barghest_3",1],["to_bruxa_corvo_bianco",1],["to_cloud_giant",1],["to_fleder",1],["to_garkain",1],["to_wolves_1",1],["to_wolves_2",1]]} \ No newline at end of file diff --git a/decks/witcher_universe_1_fighters_mages.json b/decks/witcher_universe_1_fighters_mages.json new file mode 100644 index 0000000..0545892 --- /dev/null +++ b/decks/witcher_universe_1_fighters_mages.json @@ -0,0 +1 @@ +{"faction":"witcher_universe","leader":"wu_vilgefortz_magician_kovir","cards":[["spe_horn",1],["spe_decoy",1],["spe_scorch",1],["spe_frost",1],["spe_clear",1],["spe_fog",1],["wu_leo_bonhart",1],["wu_dorregaray",1],["wu_gerhart_aelle",1],["wu_dana_meadbh",1],["wu_strays_spalla",1],["wu_azar_javed",1],["wu_gascon",1],["wu_ralf_blunden",1],["wu_coral",1],["wu_tissaia",1],["wu_gascon_light_cavalry",1],["wu_ortolan",1],["wu_lydia_bredevoort",1],["wu_operator",1],["wu_rience",1],["wu_gascon_infiltrator",1],["wu_gascon_slinger",1],["wu_rats_giselher",1],["wu_bomb_heaver",1],["wu_rats_asse",1],["wu_rats_iskra",1],["wu_rats_kayleigh",1],["wu_rats_mistle",1],["wu_rats_reef",1],["wu_visenna",1]]} \ No newline at end of file diff --git a/decks/witcher_universe_2_witchers.json b/decks/witcher_universe_2_witchers.json new file mode 100644 index 0000000..7a1fcca --- /dev/null +++ b/decks/witcher_universe_2_witchers.json @@ -0,0 +1 @@ +{"faction":"witcher_universe","leader":"wu_cosimo_malaspina","cards":[["spe_sign_aard",2],["spe_sign_axii",2],["spe_sign_igni",2],["spe_sign_quen",2],["spe_sign_yrden",2],["wu_arnaghad",1],["wu_erland",1],["wu_geralt_1",1],["wu_gezras",1],["wu_letho",1],["wu_coen",1],["wu_eskel",1],["wu_gerd",1],["wu_gorthur_gvaed",1],["wu_haern_caduch",1],["wu_ivar",1],["wu_kaer_morhen",1],["wu_kaer_seren",1],["wu_stygga_castle",1],["wu_gaetan",1],["wu_lambert",1],["wu_warrit",1],["wu_brehen",1],["wu_ivo_belhaven",1],["wu_keldar",1],["wu_kolgrim",1],["wu_vesemir",1],["wu_swallow_potion",1]]} \ No newline at end of file diff --git a/decks/witcher_universe_3_demons.json b/decks/witcher_universe_3_demons.json new file mode 100644 index 0000000..4926f75 --- /dev/null +++ b/decks/witcher_universe_3_demons.json @@ -0,0 +1 @@ +{"faction":"witcher_universe","leader":"wu_alzur_maker","cards":[["spe_horn",1],["spe_decoy",2],["spe_scorch",2],["spe_sign_yrden",1],["spe_clear",1],["spe_rain",1],["wu_boris",1],["wu_idr",1],["wu_myrgtabrakke",1],["wu_phoenix",1],["wu_iris_von_everec",1],["wu_idarran_ulivo",1],["wu_nivellen",1],["wu_cicada",1],["wu_mad_kiyan",1],["wu_sarah",1],["wu_vlodimir_von_everec",1],["wu_djinn",1],["wu_marlene_trastamara",1],["ntr_olgierd",1],["wu_raging_bear",1],["wu_vincent_meis",1],["wu_doppler_1",1],["ntr_gaunter_odimm_darkness",3],["wu_iris_companions_2",1],["wu_iris_companions_1",1],["ntr_gaunter_odimm",1]]} \ No newline at end of file diff --git a/decks/witcher_universe_4_geralt_friends.json b/decks/witcher_universe_4_geralt_friends.json new file mode 100644 index 0000000..ede4b73 --- /dev/null +++ b/decks/witcher_universe_4_geralt_friends.json @@ -0,0 +1 @@ +{"faction":"witcher_universe","leader":"wu_vilgefortz_sorcerer","cards":[["spe_horn",1],["spe_sign_aard",1],["spe_clear",1],["spe_fog",1],["spe_rain",1],["ntr_ciri",1],["ntr_geralt",1],["ntr_triss",1],["ntr_villen",1],["ntr_yennefer",1],["wu_doppler_2",1],["ntr_vesemir",1],["wu_angouleme",1],["ntr_emiel",1],["wu_tea_vea_1",1],["wu_tea_vea_2",1],["ntr_zoltan",1],["wu_kalkstein",1],["ntr_dandelion",1],["wu_pellar",1],["wu_rhapsodic_melody",1],["wu_vysogota",1],["wu_nenneke",1],["ntr_mysterious_elf",1],["wu_iola",1],["wu_kelpie",1],["wu_roach",1]]} \ No newline at end of file diff --git a/factions.js b/factions.js new file mode 100644 index 0000000..96cb018 --- /dev/null +++ b/factions.js @@ -0,0 +1,355 @@ +"use strict" + +var factions = { + realms: { + name: "Northern Realms", + factionAbility: player => game.roundStart.push(async () => { + if (game.roundCount > 1 && game.roundHistory[game.roundCount - 2].winner !== player) { + player.deck.draw(player.hand); + await ui.notification("north", 1200); + } + return false; + }), + activeAbility: false, + abilityUses: 0, + description: "Draw a card from your deck whenever you lose a round.", + unavailableSpecials: [] + }, + nilfgaard: { + name: "Nilfgaardian Empire", + description: "Wins any round that ends in a draw.", + activeAbility: false, + abilityUses: 0, + unavailableSpecials: [] + }, + monsters: { + name: "Monsters", + factionAbility: player => { + game.gameStart.push(() => { player.capabilities["endTurnRetake"] = 1; return true; }); + game.roundEnd.push(async () => { + if (player.capabilities["endTurnRetake"] < 1) + return false; + let cards = new CardContainer(); + cards.cards = player.getAllRowCards(); + let retakeCard = null; + if (cards.cards.length == 0) + return false; + if (player.controller instanceof ControllerAI) { + player.capabilities["endTurnRetake"] = 0; + retakeCard = player.controller.medic(player.leader, cards); + await ui.notification("monsters", 1200); + await board.toHand(retakeCard, retakeCard.currentLocation); + return true; + } else { + let c = await ui.popup("Retake a card [E]", (p) => p.choice = true, "Not yet [Q]", (p) => p.choice = false, "Would you like to retake one of your cards?", "Once per battle, you may retake any of your cards from the board to your hand."); + if (c) { + await ui.queueCarousel(cards, 1, (c, i) => retakeCard = c.cards[i], c => true, true, false, "Which card to retake?"); + player.capabilities["endTurnRetake"] = 0; + await ui.notification("monsters", 1200); + await board.toHand(retakeCard, retakeCard.currentLocation); + return true; + } + } + + return false; + }); + }, + description: "Once per battle, at the end of the round, you may take one card back to your hand.", + activeAbility: false, + abilityUses: 0, + unavailableSpecials: [] + }, + scoiatael: { + name: "Scoia'tael", + factionAbility: player => game.roundStart.push(async () => { + let notif = ""; + if (!game.isPvP() && player === player_me && !(player.controller instanceof ControllerAI)) { + await ui.popup("Go First [E]", () => game.currPlayer = player, "Let Opponent Start [Q]", () => game.currPlayer = player.opponent(), "Would you like to go first?", "The Scoia'tael faction perk allows you to decide each round who will get to go first."); + notif = game.currPlayer.tag + "-first"; + } else if (game.isPvP()) { + await ui.popup("Player 1 first [E]", () => game.currPlayer = player_me, "Player 2 first [Q]", () => game.currPlayer = player_op, "Who should go first?", "The Scoia'tael faction perk allows you to decide each round who will get to go first."); + notif = game.currPlayer.tag + "-first"; + } else if (player.controller instanceof ControllerAI) { + if (Math.random() < 0.5) { + game.currPlayer = player; + notif = "scoiatael"; + } else { + game.currPlayer = player.opponent(); + notif = game.currPlayer.tag + "-first"; + } + } + //Tricky bit, sides are actually swapped shortly after + game.currPlayer = game.currPlayer.opponent(); + // If first round, set first player too + if (game.roundCount == 1) + game.firstPlayer = game.currPlayer; + await ui.notification(notif, 1200); + return false; + }), + description: "Decides who takes first turn on each round.", + activeAbility: false, + abilityUses: 0, + unavailableSpecials: [] + }, + skellige: { + name: "Skellige", + factionAbility: player => game.roundStart.push(async () => { + if (game.roundCount != 3) + return false; + await ui.notification("skellige-" + player.tag, 1200); + await Promise.all(player.grave.findCardsRandom(c => c.isUnit(), 2).map(c => board.toRow(c, player.grave))); + return true; + }), + description: "2 random cards from the graveyard are placed on the battlefield at the start of the third round.", + activeAbility: false, + abilityUses: 0, + unavailableSpecials: [] + }, + witcher_universe: { + name: "Witcher Universe", + factionAbility: async player => { + await ui.notification("witcher_universe", 1200); + }, + factionAbilityInit: player => game.roundStart.push(async () => { + player.updateFactionAbilityUses(1); + return false; + }), + description: "Can skip a turn once every round.", + activeAbility: true, + abilityUses: 1, + weight: (player) => { + return 20; + }, + unavailableSpecials: [] + }, + toussaint: { + name: "Toussaint", + factionAbility: async player => { + let monsters = player.getAllRowCards().filter(c => c.abilities.includes("monster_toussaint") && !c.isLocked()); + if (monsters.length < 1) + return; + let targetCard = null; + if (player.controller instanceof ControllerAI) { + let targets = monsters.map(c => new Card(c.target, card_dict[c.target], player)); + let best = player.controller.getHighestWeightCard(targets); + if(best) + targetCard = monsters.filter(c => c.target === best.key)[0]; + } else { + await ui.queueCarousel({ cards: monsters }, 1, async (c, i) => targetCard = c.cards[i], () => true, true, false, "Choose which monster to transform."); + } + if (targetCard) { + let newCard = new Card(targetCard.target, card_dict[targetCard.target], player); + targetCard.currentLocation.removeCard(targetCard); + player.deck.addCard(newCard); + //await board.addCardToRow(newCard, targetCard.currentLocation, player); + if (player.controller instanceof ControllerAI) { + newCard.autoplay(player.deck); + } else { + // let player select where to play the card + player.selectCardDestination(newCard, player.deck); + } + } + }, + factionAbilityInit: player => { + game.gameStart.push(async () => { + player.mulliganCount = 3; + return true; + }); + game.turnStart.push(async () => { + if (player.getAllRowCards().filter(c => c.abilities.includes("monster_toussaint")).length > 0) + player.updateFactionAbilityUses(1); + else + player.updateFactionAbilityUses(0); + return false; + }) + }, + weight: (player) => { + let monsters = player.getAllRowCards().filter(c => c.abilities.includes("monster_toussaint") && !c.isLocked()); + if (monsters.length < 1) + return 0; + let targets = monsters.map(c => new Card(c.target, card_dict[c.target], player)); + let w = player.controller.getWeights(targets).sort((a, b) => (b.weight - a.weight)); + return w[0].weight; + }, + activeAbility: true, + abilityUses: 0, + description: "At the beginning of the game, you can change 3 cards instead of 2. During the game, you can turn a Toussaint Monster into its next form instead of playing a card.", + unavailableSpecials: ["spe_frost", "spe_fog","spe_rain"] + }, + lyria_rivia: { + name: "Lyria & Rivia", + factionAbility: player => { + let card = new Card("spe_lyria_rivia_morale", card_dict["spe_lyria_rivia_morale"], player); + card.removed.push(() => setTimeout(() => card.holder.grave.removeCard(card), 2000)); + card.placed.push(async () => await ui.notification("lyria_rivia", 1200)); + player.endTurnAfterAbilityUse = false; + ui.showPreviewVisuals(card); + ui.enablePlayer(true); + if (!(player.controller instanceof ControllerAI)) + ui.setSelectable(card, true); + }, + activeAbility: true, + abilityUses: 1, + description: "Apply a Morale Boost effect in the selected row (boost all units by 1 in this turn).", + weight: (player) => { + let units = player.getAllRowCards().concat(player.hand.cards).filter(c => c.isUnit()).filter(c => !c.abilities.includes("spy")); + let rowStats = { + "close": 0, + "ranged": 0, + "siege": 0, + "agile": 0 + }; + units.forEach(c => { + rowStats[c.row] += 1; + }); + rowStats["close"] += rowStats["agile"]; + return Math.max(rowStats["close"], rowStats["ranged"], rowStats["siege"]); + }, + unavailableSpecials: [] + }, + syndicate: { + name: "Syndicate", + factionAbility: player => game.gameStart.push(async () => { + let card = new Card("sy_sigi_reuven", card_dict["sy_sigi_reuven"], player); + await board.addCardToRow(card, card.row, card.holder); + }), + activeAbility: false, + abilityUses: 0, + description: "Starts the game with the Hero card Sigi Reuven on the board.", + unavailableSpecials: [] + }, + zerrikania: { + name: "Zerrikania", + factionAbility: player => game.roundStart.push(async () => { + if (game.roundCount > 1 && !(game.roundHistory[game.roundCount - 2].winner === player)) { + if (player.grave.findCards(c => c.isUnit()) <= 0) + return; + let grave = player.grave; + let respawns = []; + if (player.controller instanceof ControllerAI) { + respawns.push({ + card: player.controller.medic(player.leader, grave) + }); + } else { + await ui.queueCarousel(player.grave, 1, (c, i) => respawns.push({ + card: c.cards[i] + }), c => c.isUnit(), true); + } + await Promise.all(respawns.map(async wrapper => { + let res = wrapper.card; + grave.removeCard(res); + grave.addCard(res); + await res.animate("medic"); + await res.autoplay(grave); + })); + await ui.notification("zerrikania", 1200); + } + return false; + }), + activeAbility: false, + abilityUses: 0, + description: "Restore a unit card of your choice whenever you lose a round.", + unavailableSpecials: [] + }, + redania: { + name: "Redania", + factionAbility: async player => { + await ui.notification("redania", 1200); + }, + factionAbilityInit: player => game.gameStart.push(async () => { + player.updateFactionAbilityUses(1); + return false; + }), + description: "Can skip a turn once per game.", + activeAbility: true, + abilityUses: 1, + weight: (player) => { + return 20; + }, + unavailableSpecials: ["spe_scorch"] + }, + velen: { + name: "Velen", + factionAbilityAction: async player => { + await ui.notification("velen", 1000); + let cardsToDraw = player.velenCardDraw + player.getAllRowCards().filter(c => c.abilities.includes("soothsayer")).length; + let cards = { cards: player.deck.cards.slice(0, cardsToDraw) }; + let targetCard = null; + ui.helper.showMessage(String(player.destroyedCards)+" card(s) were destroyed last round.",3); + if (player.controller instanceof ControllerAI) { + targetCard = player.controller.getHighestWeightCard(cards.cards); + } else { + try { + Carousel.curr.cancel(); + } catch (err) { } + await ui.queueCarousel(cards, 1, (c, i) => targetCard = c.cards[i], c => true, true, true, "Choose up to one card to draw and play immediatly"); + } + if (player.destroyedCards > 1) { + player.destroyedCards = 1; + } else { + player.destroyedCards = 0; + } + cards.cards.forEach(c => { + if (c !== targetCard) { + // Remove to shuffle back at a random place (default behaviour on addCard in deck) + player.deck.removeCard(c); + player.deck.addCard(c); + } + }); + // Game can get stuck if the player selects a Decoy but there is no decoyable card + if (targetCard.key === "spe_decoy") { + let units = player.getAllRowCards().filter(c => c.isUnit()); + if (units.length == 0) { + await board.toHand(targetCard, player.deck); + targetCard = null; + } + } + if (player.controller instanceof ControllerAI) { + if(targetCard) + targetCard.autoplay(player.deck); + // If more than 1 card was destroyed, we trigger the faction ability once more + if (player.destroyedCards > 0) { + await factions["velen"].factionAbilityAction(player); + } + } else { + if (targetCard) { + // let player select where to play the card + let choiceDone = false; + player.selectCardDestination(targetCard, player.deck, async () => { + choiceDone = true; + }); + // We sleep until the choice is made, otherwise the round starts as normal + await sleepUntil(() => choiceDone, 100); + } + // If more than 1 card was destroyed, we trigger the faction ability once more + if (player.destroyedCards > 0) { + await factions["velen"].factionAbilityAction(player); + } + } + }, + factionAbility: player => { + game.gameStart.push(async () => { + player.destroyedCards = 0; + player.velenCardDraw = 1; + return false; + }); + game.unitDestroyed.push(async c => { + if (c.isUnit()) + player.destroyedCards += 1; + }); + game.turnStart.push(async () => { + if (player.destroyedCards > 0) { + await factions["velen"].factionAbilityAction(player); + } + return false; + }); + }, + description: "Every time when a unit card of any player dies, draw one card from your deck and play it immediatly. If several unit cards die at the same time, repeat this action once. If you don't want to play a drawn card, shuffle it back into the deck.", + activeAbility: false, + abilityUses: 0, + weight: (player) => { + return 0; + }, + unavailableSpecials: [] + }, +} \ No newline at end of file diff --git a/gametracker.js b/gametracker.js new file mode 100644 index 0000000..41df520 --- /dev/null +++ b/gametracker.js @@ -0,0 +1,326 @@ +"use strict" + +class GameTracker { + constructor(player1,player2) { + this.player1 = player1; + this.player2 = player2; + this.rounds = []; + this.winner = null; + } + + startRound() { + this.currentRound = new Round(this.rounds.length + 1); + this.currentRound.setBeforeStats([player_me.total, player_op.total], board.row, [player_me.hand.cards.length, player_op.hand.cards.length]); + } + + endRound(winpl) { + this.currentRound.setAfterStats([player_me.total, player_op.total], board.row, [player_me.hand.cards.length, player_op.hand.cards.length]); + this.currentRound.endRound(winpl); + this.rounds.push(this.currentRound); + } + + startTurn(pl) { + this.currentRound.startTurn(pl); + } + + endTurn() { + this.currentRound.endTurn(); + } + + getCurrentTurn() { + return this.currentRound.currentTurn; + } + + endGame(winpl) { + this.winner = winpl; + } + + getScores() { + let scores = []; + this.rounds.forEach(r => { + scores.push([r.finalScores[0], r.finalScores[1]]); + }); + return scores; + } + + getCardImpacts() { + let data = {}; + + this.rounds.forEach(r => { + r.turns.forEach(t => { + if (t.action instanceof UnitCardAction) { + let ckey = t.action.card.key; + if (!data[ckey]) + data[ckey] = []; + data[ckey].push(t.action.impact); + } + }); + }); + return data; + } + + getAbilitiesImpact() { + let cimp = this.getCardImpacts(); + let data = {"bond":[],"muster":[],"medic":[],"witcher":[],"whorshiped":[],"inspire":[],"scorch":[],"scorch_c":[],"morale":[],"horn":[], "witch_hunt":[]}; + + Object.keys(cimp).forEach(key => { + let abi = card_dict[key]["ability"].split(" "); + if (abi.includes("bond")) { + data["bond"] = data["bond"].concat(cimp[key].map(v => v / card_dict[key]["strength"])); + } else if (abi.includes("muster")) { + data["muster"] = data["muster"].concat(cimp[key].map(v => v / card_dict[key]["strength"])); + } else if (abi.includes("medic")) { + data["medic"] = data["medic"].concat(cimp[key].map(v => v - card_dict[key]["strength"])); + } else if (abi.at(-1) && abi.at(-1).startsWith("witcher_")) { + data["witcher"] = data["witcher"].concat(cimp[key].map(v => v - card_dict[key]["strength"])); + } else if (abi.includes("whorshiped")) { + data["whorshiped"] = data["whorshiped"].concat(cimp[key].map(v => v - card_dict[key]["strength"])); + } else if (abi.includes("inspire")) { + data["inspire"] = data["inspire"].concat(cimp[key].map(v => v - card_dict[key]["strength"])); + } else if (abi.includes("scorch")) { + data["scorch"] = data["scorch"].concat(cimp[key].map(v => v - card_dict[key]["strength"])); + } else if (abi.includes("scorch_c")) { + data["scorch_c"] = data["scorch_c"].concat(cimp[key].map(v => v - card_dict[key]["strength"])); + } else if (abi.includes("morale")) { + data["morale"] = data["morale"].concat(cimp[key].map(v => v - card_dict[key]["strength"])); + } else if (abi.includes("horn")) { + data["horn"] = data["horn"].concat(cimp[key].map(v => v - card_dict[key]["strength"])); + } else if (abi.includes("witch_hunt")) { + data["witch_hunt"] = data["witch_hunt"].concat(cimp[key].map(v => v - card_dict[key]["strength"])); + } + }); + + return data; + } +} + +class Round { + constructor(n) { + this.number = n; + this.turns = []; + this.winner = null; + this.finalScores = [0, 0]; + this.start_hand_size = [0, 0]; + this.end_hand_size = [0, 0]; + } + + startTurn(pl) { + this.currentTurn = new Turn(this.turns.length + 1, this, pl); + this.currentTurn.setBeforeStats([player_me.total, player_op.total], board.row, [player_me.hand.cards.length, player_op.hand.cards.length]); + } + + endTurn() { + this.currentTurn.setAfterStats([player_me.total, player_op.total], board.row, [player_me.hand.cards.length, player_op.hand.cards.length]); + this.turns.push(this.currentTurn); + } + + setBeforeStats(scores, rows, handsize) { + this.startScores = scores; + this.startRows = []; + rows.forEach(r => { + this.startRows.push(Object.assign({}, r)); + }); + this.start_hand_size = handsize; + } + + setAfterStats(scores, rows, handsize) { + this.endScores = scores; + this.endRows = []; + rows.forEach(r => { + this.endRows.push(Object.assign({}, r)); + }); + this.end_hand_size = handsize; + this.turns.forEach(t => { + if (t.action instanceof UnitCardAction && t.action.card.currentLocation instanceof Row) { + let pl = t.action.card.holder; + if (!t.action.card.isLocked() && + (t.action.card.abilities.includes("bond") + || t.action.card.abilities.includes("whorshipped") + || t.action.card.abilities.includes("inspire") + || (t.action.card.abilities.at(-1) && t.action.card.abilities.at(-1).startsWith("witcher_")) + )) { + t.action.impact = t.action.card.power; + } else if (!t.action.card.isLocked() && + (t.action.card.abilities.includes("scorch") + || t.action.card.abilities.includes("scorch_c") + || t.action.card.abilities.includes("medic") + || t.action.card.abilities.includes("witch_hunt") + )) { + t.action.impact = (t.endScores[getPlayerIndex(pl)] - t.startScores[getPlayerIndex(pl)]) + (t.startScores[getPlayerIndex(pl.opponent())] - t.endScores[getPlayerIndex(pl.opponent())]); + } else if (!t.action.card.isLocked() && t.action.card.abilities.includes("morale")) { + t.action.impact = t.action.card.power + t.action.card.currentLocation.cards.filter(c => c.isUnit()).length; + } else if (!t.action.card.isLocked() && t.action.card.abilities.includes("horn")) { + t.action.impact = t.action.card.power + t.action.card.currentLocation.cards.filter(c => c.isUnit()).reduce((a,c) => a + (c.power / 2),0); + } + } + }); + } + + endRound(winpl) { + this.winner = winpl; + this.finalScores = [player_me.total, player_op.total]; + } +} + +class Turn { + constructor(n,rnd,pl) { + this.number = n; + this.round = rnd; + this.player = pl; + this.action = null; + this.start_hand_size = [0, 0]; + this.end_hand_size = [0, 0]; + } + + setBeforeStats(scores, rows, handsize) { + this.startScores = scores; + this.startRows = []; + rows.forEach(r => { + this.startRows.push(Object.assign({}, r)); + }); + this.start_hand_size = handsize; + } + + setAfterStats(scores, rows, handsize) { + this.endScores = scores; + this.endRows = []; + rows.forEach(r => { + this.endRows.push(Object.assign({}, r)); + }); + this.end_hand_size = handsize; + if (this.action instanceof UnitCardAction) { + var pl = this.action.card.holder; + if (this.action.card.abilities.length === 0) { + this.action.impact = this.action.card.power; + } else if (this.action.card.abilities.includes("muster")) { + // We devide the impact by the number of cards from hand it took + let handdiff = Math.max(1, (this.start_hand_size[getPlayerIndex(pl)] - this.end_hand_size[getPlayerIndex(pl)])); + this.action.impact = (this.endScores[getPlayerIndex(pl)] - this.startScores[getPlayerIndex(pl)]) / handdiff; + } + } + } + + playUnitCard(card, row) { + this.action = new UnitCardAction(this, card, row.getRowType()); + } + + playWeatherCard(card) { + this.action = new WeatherCardAction(this, card.key, card.abilities.at(-1)); + } + + playSpecialCard(card, row) { + this.action = new SpecialCardAction(this, card.key, row.getRowType()); + } + + playSpecialCardBoard(card) { + this.action = new SpecialCardAction(this, card.key, "board"); + } + + passAction() { + this.action = new PassAction(this); + } + + useLeader(card) { + this.action = new LeaderAction(this, card.key); + } + + useLeaderOnRow(card,r) { + this.action = new LeaderAction(this, card.key, r.getRowType()); + } + + useLeaderOnCard(card,t) { + this.action = new LeaderAction(this, card.key, false, t.key); + } + + summary() { + let action_string = "No action"; + if (this.action) + action_string = this.action.summary(); + return `[Round:${this.round.number}] [Turn:${this.number}] [ScoresBefore:${this.startScores[0]}/${this.startScores[1]}]\nPlayer ${this.player.tag}: ${action_string}]\n[ScoresAfter:${this.endScores[0]}/${this.endScores[1]}]`; + } +} + +class Action { + constructor(turn) { + this.turn = turn; + this.targetRow = false; + this.targetCard = false; + this.impact = 0; + } + + summary() { + return "No output"; + } +} + +class UnitCardAction extends Action { + constructor(turn, card, r) { + super(turn); + this.card = card; + this.key = card.key; + this.targetRow = r; + } + + summary() { + return `Card '${this.key}' played in ${this.targetRow} row.`; + } +} + +class SpecialCardAction extends Action { + constructor(turn, ckey, r) { + super(turn); + this.key = ckey; + this.targetRow = r; + } + + summary() { + return `Special Card '${this.key}' played on ${this.targetRow}.`; + } +} + +class WeatherCardAction extends Action { + constructor(turn, ckey, type) { + super(turn); + this.key = ckey; + this.type = type; + } + + summary() { + return `Weather Card '${this.key}' played with ${this.type} effect.`; + } +} + +class LeaderAction extends Action { + constructor(turn, ckey, targetRow=false, targetCard=false) { + super(turn); + this.key = ckey; + this.targetRow = targetRow; + this.targetCard = targetCard; + } + + summary() { + return `Leader '${this.key}' ability used`; + } +} + +class FactionAction extends Action { + constructor(turn, ckey) { + super(turn); + this.key = ckey; + } +} + +class PassAction extends Action { + constructor(turn) { + super(turn); + } + + summary() { + return "Passed"; + } +} + +// UTIL FUNCTIONS +function getPlayerIndex(pl) { + return pl.tag === "me" ? 0 : 1; +} \ No newline at end of file diff --git a/gwent.js b/gwent.js new file mode 100644 index 0000000..9059348 --- /dev/null +++ b/gwent.js @@ -0,0 +1,5775 @@ +"use strict" + +class Controller { } + +var nilfgaard_wins_draws = false; + +// Makes decisions for the AI opponent player +class ControllerAI { + constructor(player) { + this.player = player; + } + + // Computes the weights of the given cards + getWeights(cards) { + let data_max = this.getMaximums(); + let data_board = this.getBoardData(); + return cards.map(c => + ({ + weight: this.weightCard(c, data_max, data_board), + card: c + })); + } + + // Return the card among the provided list having the highest weight + getHighestWeightCard(cards) { + let w = this.getWeights(cards).sort((a, b) => (b.weight - a.weight)); + if (w.length > 0) { + return w[0].card; + } + return null; + } + + // Return the card among the provided list having the lowest weight + getLowestWeightCard(cards) { + let w = this.getWeights(cards).sort((a, b) => (a.weight - b.weight)); + if (w.length > 0) { + return w[0].card; + } + return null; + } + + // Collects data and weighs options before taking a weighted random action + async startTurn(player) { + let data_max = this.getMaximums(); + let data_board = this.getBoardData(); + // In case of a forced action, play it if positive weight, pass otherwise + if (player.forcedActions.length > 0) { + let card = player.forcedActions.splice(0, 1)[0]; + let w = this.weightCard(card, data_max, data_board); + if (w > 0) { + await this.playCard(card, data_max, data_board) + } else { + await player.passRound(); + } + return; + } + if (player.opponent().passed && (player.winning || player.deck.faction === "nilfgaard" && player.total === player.opponent().total)) { + nilfgaard_wins_draws = player.deck.faction === "nilfgaard" && player.total === player.opponent().total; + await player.passRound(); + return; + } + + let weights = player.hand.cards.map(c => + ({ + weight: this.weightCard(c, data_max, data_board), + action: async () => await this.playCard(c, data_max, data_board), + card: c + })); + + // If the opponent has passed and is not too far ahead, let's try to take the win + let diff = player.opponent().total - player.total; + if (player.opponent().passed && diff < 16) { + // Looking for a one shot that isn't overkill + let oneshot = weights.filter(w => (w.card.basePower > diff && w.card.basePower < diff + 5) || (w.weight > diff && w.weight > diff + 5)); + if (oneshot.length > 0) { + let oneshot_card = oneshot.sort((a, b) => (a.weight - b.weight))[0]; + await oneshot_card.action(); + return; + } + // Can we catch up in 2 plays? + let playable = weights.filter(w => w.weight > 0).sort((a, b) => (b.weight - a.weight)); + if (playable.length > 2) + playable = playable.slice(0, 2); + let weightTotal = playable.reduce((a, c) => a + c.weight, 0); + if (weightTotal > diff) { + await playable[0].action(); + return; + } + } + if (player.leaderAvailable) + weights.push({ + name: "Leader Ability", + weight: this.weightLeader(player.leader, data_max, data_board), + action: async () => { + await ui.notification("op-leader", 1200); + await player.activateLeader(); + } + }); + if (player.factionAbilityUses > 0) { + let factionAbility = factions[player.deck.faction]; + weights.push({ + name: "Faction ability", + weight: factionAbility.weight(player), + action: async () => { + await player.useFactionAbility(); + } + }); + } + weights.push({ + name: "Pass", + weight: this.weightPass(), + action: async () => await player.passRound() + }); + let weightTotal = weights.reduce((a, c) => a + c.weight, 0); + if (weightTotal === 0) { + for (let i = 0; i < player.hand.cards.length; ++i) { + let card = player.hand.cards[i]; + if (card.row === "weather" && this.weightWeather(card) > -1 || card.abilities.includes("avenger")) { + await weights[i].action(); + return; + } + } + await player.passRound(); + } else { + for (var i = 0; i < weights.length; ++i) { + if (weights[i].card) + console.log("[" + weights[i].card.name + "] Weight: " + weights[i].weight); + else + console.log("[" + weights[i].name + "] Weight: " + weights[i].weight); + } + let rand = randomInt(weightTotal); + console.log("Chosen weight: " + rand); + for (var i = 0; i < weights.length; ++i) { + rand -= weights[i].weight; + if (rand < 0) + break; + } + console.log(weights[i]); + await weights[i].action(); + } + } + + isSelfRowIndex(i) { + return (this.player === player_me && i > 2) || (this.player === player_op && i < 3); + } + + getSelfRowIndexes() { + if (this.player === player_me) + return [3, 4, 5]; + return [0, 1, 2]; + } + + // Collects data about card with the hightest power on the board + getMaximums() { + let rmax = board.row.map(r => ({ + row: r, + cards: r.cards.filter(c => c.isUnit() && !c.isImmortal()).reduce((a, c) => + (!a.length || a[0].power < c.power) ? [c] : a[0].power === c.power ? a.concat([c]) : a, []) + })); + + let max = rmax.filter((r, i) => r.cards.length && this.isSelfRowIndex(i)).reduce((a, r) => Math.max(a, r.cards[0].power), 0); + let max_me = rmax.filter((r, i) => this.isSelfRowIndex(i) && r.cards.length && r.cards[0].power === max).reduce((a, r) => + a.concat(r.cards.map(c => ({ + row: r, + card: c + }))), []); + + max = rmax.filter((r, i) => r.cards.length && !this.isSelfRowIndex(i)).reduce((a, r) => Math.max(a, r.cards[0].power), 0); + let max_op = rmax.filter((r, i) => !this.isSelfRowIndex(i) && r.cards.length && r.cards[0].power === max).reduce((a, r) => + a.concat(r.cards.map(c => ({ + row: r, + card: c + }))), []); + + // Also compute for rows without a shield + let rmax_noshield = rmax.filter((r, i) => !r.row.isShielded()); + let max_noshield = rmax_noshield.filter((r, i) => r.cards.length && this.isSelfRowIndex(i)).reduce((a, r) => Math.max(a, r.cards[0].power), 0); + let max_me_noshield = rmax_noshield.filter((r, i) => this.isSelfRowIndex(i) && r.cards.length && r.cards[0].power === max_noshield).reduce((a, r) => + a.concat(r.cards.map(c => ({ + row: r, + card: c + }))), []); + + max_noshield = rmax_noshield.filter((r, i) => r.cards.length && !this.isSelfRowIndex(i)).reduce((a, r) => Math.max(a, r.cards[0].power), 0); + let max_op_noshield = rmax_noshield.filter((r, i) => !this.isSelfRowIndex(i) && r.cards.length && r.cards[0].power === max_noshield).reduce((a, r) => + a.concat(r.cards.map(c => ({ + row: r, + card: c + }))), []); + + return { + rmax: rmax, + me: max_me, + op: max_op, + rmax_noshield: rmax_noshield, + me_noshield: max_me_noshield, + op_noshield: max_op_noshield + }; + } + + // Collects data about the types of cards on the board and in each player's graves + getBoardData() { + let data = this.countCards(new CardContainer()); + this.player.getAllRows().forEach(r => this.countCards(r, data)); + data.grave_me = this.countCards(this.player.grave); + data.grave_op = this.countCards(this.player.opponent().grave); + return data; + } + + // Catalogs the kinds of cards in a given CardContainer + countCards(container, data) { + data = data ? data : { + spy: [], + medic: [], + bond: {}, + scorch: [] + }; + container.cards.filter(c => c.isUnit()).forEach(c => { + for (let x of c.abilities) { + if (!c.isLocked()) { + switch (x) { + case "spy": + case "medic": + data[x].push(c); + break; + case "scorch_r": + case "scorch_c": + case "scorch_s": + data["scorch"].push(c); + break; + case "bond": + if (!data.bond[c.target]) + data.bond[c.target] = 0; + data.bond[c.target]++; + } + } + } + }); + return data; + } + + // Swaps a card from the hand with the deck if beneficial + redraw() { + let card = this.discardOrder({ + holder: this.player + }).shift(); + if (card && card.power < 15) { + this.player.deck.swap(this.player.hand, this.player.hand.removeCard(card)); + } + } + + // Orders discardable cards from most to least discardable + discardOrder(card, src = null, force = false) { + let cards = []; + let groups = {}; + let source = src ? src : card.holder.hand; + + let musters = source.cards.filter(c => c.abilities.includes("muster")); + // Grouping Musters together + musters.forEach(curr => { + let name = curr.target; + if (!groups[name]) + groups[name] = []; + groups[name].push(curr); + }); + // Keeping one in hand for each muster group + for (let group of Object.values(groups)) { + group.sort(Card.compare); + group.pop(); + cards.push(...group); + } + + // Targets of muster that do not have the ability themselves for which we already have the "summoner" + let tmusters = source.cards.filter(c => Object.keys(groups).includes(c.target) && !c.abilities.includes("muster")); + cards.push(...tmusters); + + // Discarding randomly weather cards to keep only 1 in hand + let weathers = source.cards.filter(c => c.row === "weather"); + if (weathers.length > 1) { + weathers.splice(randomInt(weathers.length), 1); + cards.push(...weathers); + } + // Discarding cards with no abilities by order of strength, unless they are of 7+ + let normal = source.cards.filter(c => c.abilities.length === 0 && c.basePower < 7); + normal.sort(Card.compare); + cards.push(...normal); + + // Grouping bonds together + let bonds = source.cards.filter(c => c.abilities.includes("bond")); + groups = {}; + bonds.forEach(curr => { + let name = curr.target; + if (!groups[name]) + groups[name] = []; + groups[name].push(curr); + }); + // Discarding those that are alone and weak (< 6) + for (let group of Object.values(groups)) { + if (group.length === 1 && group[0].basePower < 6) { + cards.push(group[0]); + } + } + + // In this mode, we force all cards to be ordered - let's add remaining ones by order of basePower + if (force) { + source.cards.sort((a, b) => a.basePower - b.basePower).forEach(c => { + if (cards.indexOf(c) < 0) + cards.push(c); + }); + } + + return cards; + } + + // Tells the Player that this object controls to play a card + async playCard(c, max, data) { + if (c.key === "spe_horn") + await this.horn(c); + else if (c.key === "spe_mardroeme") + await this.mardroeme(c); + else if (c.abilities.includes("decoy")) + await this.decoy(c, max, data); + else if (c.faction === "special" && c.abilities.includes("scorch")) + await this.scorch(c, max, data); + else if (c.faction === "special" && c.abilities.includes("cintra_slaughter")) + await this.slaughterCintra(c); + else if (c.faction === "special" && c.abilities.includes("seize")) + await this.seizeCards(c); + else if (c.faction === "special" && (c.abilities.includes("shield") || c.abilities.includes("shield_c") || c.abilities.includes("shield_r") || c.abilities.includes("shield_s"))) + await this.shieldCards(c); + else if (c.faction === "special" && c.abilities.includes("lock")) + await this.lock(c); + else if (c.faction === "special" && c.abilities.includes("curse")) + await this.curse(c); + else if (c.faction === "special" && c.abilities.includes("knockback")) + await this.knockback(c); + else if (c.faction === "special" && c.abilities.includes("toussaint_wine")) + await this.toussaintWine(c); + else if ((c.isUnit() || c.hero) && c.abilities.includes("witch_hunt")) + await this.witchHunt(c); + else if ((c.isUnit() || c.hero) && c.row.includes("agile") && (c.abilities.includes("morale") || c.abilities.includes("horn") || c.abilities.includes("bond") )) + await this.player.playCardToRow(c, this.bestAgileRowChange(c).row); + else if (c.faction === "special" && c.abilities.includes("bank")) + await this.bank(c); + else if (c.faction === "special" && c.abilities.includes("skellige_fleet")) + await this.skelligeFleet(c); + else if (c.faction === "special" && c.abilities.includes("royal_decree")) + await this.royalDecree(c); + else + await this.player.playCard(c); + } + + // Plays a Commander's Horn to the most beneficial row. Assumes at least one viable row. + async horn(card) { + let rows = this.player.getAllRows().filter(r => !r.special.containsCardByKey("spe_horn")); + let max_row; + let max = 0; + for (let i = 0; i < rows.length; ++i) { + let r = rows[i]; + let dif = [0, 0]; + this.calcRowPower(r, dif, true); + r.effects.horn++; + this.calcRowPower(r, dif, false); + r.effects.horn--; + let score = dif[1] - dif[0]; + if (max < score) { + max = score; + max_row = r; + } + } + await this.player.playCardToRow(card, max_row); + } + + // Plays a Mardroeme to the most beneficial row. Assumes at least one viable row. + async mardroeme(card) { + let row, max = 0; + this.getSelfRowIndexes().forEach(i => { + let curr = this.weightMardroemeRow(card, board.row[i]); + if (curr > max) { + max = curr; + row = board.row[i]; + } + }); + await this.player.playCardToRow(card, row); + } + + // Selects a card to remove from a Grave. Assumes at least one valid card. + medic(card, grave) { + let data = this.countCards(grave); + let targ; + if (data.spy.length) { + let min = data.spy.reduce((a, c) => Math.min(a, c.power), Number.MAX_VALUE); + targ = data.spy.filter(c => c.power === min)[0]; + } else if (data.medic.length) { + let max = data.medic.reduce((a, c) => Math.max(a, c.power), 0); + targ = data.medic.filter(c => c.power === max)[0]; + } else if (data.scorch.length) { + targ = data.scorch[randomInt(data.scorch.length)]; + } else { + let units = grave.findCards(c => c.isUnit()); + targ = units.reduce((a, c) => a.power < c.power ? c : a, units[0]); + } + return targ; + } + + // Selects a card to return to the Hand and replaces it with a Decoy. Assumes at least one valid card. + async decoy(card, max, data) { + let targ, row; + if (game.decoyCancelled) + return; + let usable_data; + if (card.row.length > 0) { + // Units with decoy ability only work on a specific row + if (["close", "agile","agile_cr","agile_cs","agile_crs"].includes(card.row)) + usable_data = this.countCards(board.getRow(card, "close", this.player), usable_data); + if (["ranged", "agile", "agile_cr", "agile_rs", "agile_crs"].includes(card.row)) + usable_data = this.countCards(board.getRow(card, "ranged", this.player), usable_data); + if (["siege", "agile_rs", "agile_cs", "agile_crs"].includes(card.row)) + usable_data = this.countCards(board.getRow(card, "siege", this.player), usable_data); + } else { + usable_data = data; + } + if (usable_data.spy.length) { + let min = usable_data.spy.reduce((a, c) => Math.min(a, c.power), Number.MAX_VALUE); + targ = usable_data.spy.filter(c => c.power === min)[0]; + } else if (usable_data.medic.length) { + targ = usable_data.medic[randomInt(usable_data.medic.length)]; + } else if (usable_data.scorch.length) { + targ = usable_data.scorch[randomInt(usable_data.scorch.length)]; + } else { + let pairs = max.rmax.filter((r, i) => this.isSelfRowIndex(i) && r.cards.length) + .filter((r, i) => card.row.length === 0 || (["close", "agile", "agile_cr", "agile_cs", "agile_crs"].includes(card.row) && (i === 2 || i === 3)) + || (["ranged", "agile", "agile_cr", "agile_rs", "agile_crs"].includes(card.row) && (i === 1 || i === 4)) + || (["siege", "agile_rs", "agile_cs", "agile_crs"].includes(card.row) && (i === 0 || i === 5))) + .reduce((a, r) => + r.cards.map(c => ({ + r: r.row, + c: c + })).concat(a), []); + + if (pairs.length) { + let pair = pairs[randomInt(pairs.length)]; + targ = pair.c; + row = pair.r; + } + } + + if (targ) { + for (let i = 0; !row; ++i) { + if (board.row[i].cards.indexOf(targ) !== -1) { + row = board.row[i]; + break; + } + } + targ.decoyTarget = true; + setTimeout(() => board.toHand(targ, row), 1000); + } else { + row = ["close", "agile", "agile_cr", "agile_cs", "agile_crs"].includes(card.row) ? board.getRow(card, "close", this.player) : ["ranged", "agile_rs"].includes(card.row) ? board.getRow(card, "ranged", this.player) : board.getRow(card, "siege", this.player); + } + await this.player.playCardToRow(card, row); + } + + // Tells the controlled Player to play the Scorch card + async scorch(card, max, data) { + await this.player.playScorch(card); + } + + // Tells the controlled Player to play the Scorch card + async slaughterCintra(card) { + await this.player.playSlaughterCintra(card); + } + + // Tells the controlled Player to play the seize special card + async seizeCards(card) { + await this.player.playSeize(card); + } + + // Plays a shield special card to the most beneficial row. Assumes at least one viable row. + // Also applicable for shield cards which affect only one row. + async shieldCards(card) { + if (card.abilities.includes("shield_c")) { + await this.player.playCardToRow(card, board.getRow(card, "close", this.player)); + return; + } else if (card.abilities.includes("shield_r")) { + await this.player.playCardToRow(card, board.getRow(card, "ranged", this.player)); + return; + } + if (card.abilities.includes("shield_s")) { + await this.player.playCardToRow(card, board.getRow(card, "siege", this.player)); + return; + } + + let units = card.holder.getAllRowCards().concat(card.holder.hand.cards).filter(c => c.isUnit()).filter(c => !c.abilities.includes("spy")); + let rowStats = { + "close": 0, + "ranged": 0, + "siege": 0, + "agile": 0, + "agile_cr": 0, + "agile_rs": 0, + "agile_cs": 0, + "agile_crs": 0 + }; + units.forEach(c => { + rowStats[c.row] += c.power; + }); + rowStats["close"] += (rowStats["agile"] + rowStats["agile_cr"] + rowStats["agile_cs"] + rowStats["agile_crs"]); + rowStats["ranged"] += rowStats["agile_rs"] + let max_row; + if (rowStats["close"] >= rowStats["ranged"] && rowStats["close"] >= rowStats["siege"]) + max_row = board.getRow(card, "close", this.player); + else if (rowStats["ranged"] > rowStats["close"] && rowStats["ranged"] >= rowStats["siege"]) + max_row = board.getRow(card, "ranged", this.player); + else + max_row = board.getRow(card, "siege", this.player); + await this.player.playCardToRow(card, max_row); + } + + // Plays the lock special card in the enemy melee row + async lock(card) { + await this.player.playCardToRow(card, board.getRow(card, "close", this.player.opponent())); + } + + // Plays the curse special card in the enemy melee row + async curse(card) { + await this.player.playCardToRow(card, board.getRow(card, "close", this.player.opponent())); + } + + // Plays the knockback special card in the most beneficial row - by default enemy melee row + async knockback(card) { + await this.player.playKnockback(card); + } + + // Play special wine card to the most beneficial row. + async toussaintWine(card) { + await this.player.playCardToRow(card, this.bestRowToussaintWine(card)); + } + + // Play special wine card to the most beneficial row. + async witchHunt(card) { + await this.player.playCardToRow(card, this.bestWitchHuntRow(card).getOppositeRow()); + } + + // Plays the bank special card + async bank(card) { + await this.player.playBank(card); + } + + // Plays the Skellige Fleet special card + async skelligeFleet(card) { + await this.player.playSkelligeFleet(card); + } + + // Plays the Royal Decree special card + async royalDecree(card) { + await this.player.playRoyalDecree(card); + } + + bestWitchHuntRow(card) { + if (card.row.includes("agile")) { + let r = board.getAgileRows(card, this.player.opponent()); + let rows = r.filter(r => !r.isShielded() && !game.scorchCancelled).map(r => ({ + row: r, + value: r.minUnits().reduce((a, c) => a + c.power, 0) + })); + if (rows.length > 0) + return rows.sort((a, b) => b.value - a.value)[0].row; + else + return r[0]; + } else { + return board.getRow(card, card.row, card.holder.opponent()); + } + } + + bestRowToussaintWine(card) { + let units = card.holder.getAllRowCards().concat(card.holder.hand.cards).filter(c => c.isUnit()).filter(c => !c.abilities.includes("spy")); + let rowStats = { + "close": 0, + "ranged": 0, + "siege": 0, + "agile": 0, + "agile_cr": 0, + "agile_rs": 0, + "agile_cs": 0, + "agile_crs": 0 + }; + units.forEach(c => { + rowStats[c.row] += 1; + }); + rowStats["close"] += (rowStats["agile"] + rowStats["agile_cr"] + rowStats["agile_cs"] + rowStats["agile_crs"]); + rowStats["ranged"] += rowStats["agile_rs"] + let rows = card.holder.getAllRows(); + rowStats["close"] = board.getRow(card, "close", this.player).effects.toussaint_wine > 0 ? 0 : rowStats["close"]; + rowStats["ranged"] = board.getRow(card, "ranged", this.player).effects.toussaint_wine > 0 ? 0 : rowStats["ranged"]; + rowStats["siege"] = board.getRow(card, "siege", this.player).effects.toussaint_wine > 0 ? 0 : rowStats["siege"]; + let max_row; + if (rowStats["close"] >= rowStats["ranged"] && rowStats["close"] >= rowStats["siege"]) + max_row = board.getRow(card, "close", this.player); + else if (rowStats["ranged"] > rowStats["close"] && rowStats["ranged"] >= rowStats["siege"]) + max_row = board.getRow(card, "ranged", this.player); + else + max_row = board.getRow(card, "siege", this.player); + return max_row; + } + + // Gives the list of cards on the board for which we can find a similar card in the grave or deck (either same name or target) + // Returns for each entry: target card on bard / card in deck or grave / target row / weight + bestSimilarCards(card) { + let units = card.holder.getAllRowCards().filter(c => c.isUnit()); + let candidates = new Array(); + units.forEach(srcCard => { + let targets = srcCard.holder.grave.cards.concat(srcCard.holder.deck.cards).filter((c => srcCard.name === c.name || ("target" in srcCard && srcCard.target !== "" && srcCard.target === c.target))); + if (targets.length > 0) { + targets.forEach(c => { + let pRows = c.getPlayableRows(); + pRows.forEach(r => { + let weight = this.weightRowChange(c, r); + candidates.push([srcCard, c, r, weight]); + }); + }); + } + }); + return candidates.sort((a, b) => b[3] - a[3]); + } + + // Assigns a weight for how likely the conroller is to Pass the round + weightPass() { + if (this.player.health === 1) + return 0; + let dif = this.player.opponent().total - this.player.total; + if (dif > 30) + return 100; + if (dif < -30 && this.player.opponent().hand.cards.length - this.player.hand.cards.length > 2) + return 100; + return Math.floor(Math.abs(dif)); + } + + // Assigns a weight for how likely the controller is to activate its leader ability + weightLeader(card, max, data) { + let w = ability_dict[card.abilities[0]].weight; + if (ability_dict[card.abilities[0]].weight) { + let score = w(card, this, max, data); + return score; + } + return 10 + (game.roundCount - 1) * 15; + } + + // Assigns a weight for how likely the controller will use a scorch-row card + weightScorchRow(card, max, row_name) { + if (game.scorchCancelled) + return 0; + let index = 3 + (row_name === "close" ? 0 : row_name === "ranged" ? 1 : 2); + if (this.player === player_me) + index = 2 - (row_name === "close" ? 0 : row_name === "ranged" ? 1 : 2); + if (board.row[index].total < 10 || board.row[index].isShielded()) + return 0; + let score = max.rmax[index].cards.reduce((a, c) => a + c.power, 0); + return score; + } + + // Calculates a weight for how likely the controller will use horn on this row + weightHornRow(card, row) { + return row.effects.horn ? 0 : this.weightRowChange(card, row); + } + + // Calculates weight for playing a card on a given row, min 0 + weightRowChange(card, row) { + return Math.max(0, this.weightRowChangeTrue(card, row)); + } + + bestAgileRowChange(card) { + let rows = []; + let r = board.getAgileRows(card, card.holder); + r.forEach(row => rows.push({ row: row, score: 0 })); + for (var i = 0; i < rows.length ; i++) { + rows[i].score = this.weightRowChange(card, rows[i].row); + } + return rows.sort((a, b) => b.score - a.score)[0]; + } + + // Calculates weight for playing a card on the given row + weightRowChangeTrue(card, row) { + let dif = [0, 0]; + this.calcRowPower(row, dif, true); + row.updateState(card, true); + this.calcRowPower(row, dif, false); + if (!card.isSpecial()) + dif[0] -= row.calcCardScore(card); + row.updateState(card, false); + return dif[1] - dif[0]; + } + + // Weights the diff of changing a card from a row to another + weightRowSwap(card, src, dest) { + if (src === dest) + return 0; + return (this.weightRowChangeTrue(card, dest) - this.weightRowChangeTrue(card, src)); + } + + // Calculates for all cards on the given player's side of the board the diff of score if changing location to another row + // Returns results sorted by best or worst first, depending if "best" parameter is on or off + weightAllCardsRowChanges(player, best = true) { + let weights = []; + let cards = player.getAllRowCards(); + let rows = player.getAllRows(); + cards.filter(c => c.hero || c.isUnit()).forEach(c => { + rows.forEach(r => { + if (r !== c.currentLocation) { + weights.push({ row: r, card: c, score: this.weightRowSwap(c, c.currentLocation, r) }) + } + }); + }); + if (best) { + return weights.sort((a, b) => b.score - a.score); + } else { + return weights.sort((a, b) => a.score - b.score); + } + } + + // Calculates the weight for playing a weather card + weightWeather(card) { + let rows; + // This specific weather card has 2 modes + if (card.key === "spe_storm") { + return Math.max(this.weightWeather({ key: "storm", abilities: ["frost", "fog"] }), this.weightWeather({ key: "storm", abilities: ["rain", "fog"] })); + } + if (card.abilities) { + if (card.key === "spe_clear") + rows = Object.values(weather.types).filter(t => t.count > 0).flatMap(t => t.rows); + else + rows = Object.values(weather.types).filter(t => t.count === 0 && card.abilities.includes(t.name)).flatMap(t => t.rows); + } else { + if (card.ability == "clear") + rows = Object.values(weather.types).filter(t => t.count > 0).flatMap(t => t.rows); + else + rows = Object.values(weather.types).filter(t => t.count === 0 && t.name === card.ability).flatMap(t => t.rows); + } + + if (!rows.length) + return 1; + let dif = [0, 0]; + rows.forEach(r => { + let state = r.effects.weather; + this.calcRowPower(r, dif, true); + r.effects.weather = !state; + this.calcRowPower(r, dif, false); + r.effects.weather = state; + }); + return dif[1] - dif[0]; + } + + // Calculates the weight for playing a mardroeme card + weightMardroemeRow(card, row) { + if (card.key === "spe_mardroeme" && row.special.containsCardByKey("spe_mardroeme")) + return 0; + let ermion = card.holder.hand.cards.filter(c => c.key === "sk_ermion").length > 0; + if (ermion && card.key !== "sk_ermion" && row === board.getRow(card, "ranged", this.player)) + return 0; + let bers_cards = row.cards.filter(c => c.abilities.includes("berserker")); + let weightData = { + bond: {}, + strength: 0, + scorch: 0 + }; + + for (var i = 0; i < bers_cards.length; i++) { + var c = bers_cards[i]; + var ctarget = card_dict[c.target]; + weightData.strength -= c.power; + if (ctarget.ability.includes("morale")) + weightData.strength += Number(ctarget["strength"]) + row.cards.filter(c => c.isUnit()).length - 1; + if (ctarget.ability.includes("bond")) { + if (!weightData.bond[c.target]) + weightData.bond[c.target] = [0, Number(ctarget["strength"])]; + weightData.bond[c.target][0]++; + } + if (ctarget.ability.includes("scorch_c")) + weightData.scorch += this.weightScorchRow(card, this.getMaximums(), "close"); + } + let weight = weightData.strength + Object.keys(weightData.bond).reduce((s, c) => s + Math.pow(weightData.bond[c][0], 2) * weightData.bond[c][1], 0) + weightData.scorch; + return Math.max(1, weight); + } + + // Calculates the weight for cards with the medic ability + weightMedic(data, score, owner) { + let units = owner.grave.findCards(c => c.isUnit()); + let grave = data["grave_" + owner.opponent().tag]; + return !units.length ? Math.min(1, score) : score + (grave.spy.length ? 50 : grave.medic.length ? 15 : grave.scorch.length ? 10 : this.player.health === 1 ? 1 : 0); + } + + // Calculates the weight for cards with the berserker ability + weightBerserker(card, row, score) { + if (card.holder.hand.cards.filter(c => c.abilities.includes("mardroeme")).length < 1 && !row.effects.mardroeme > 0) + return score; + score -= card.basePower; + let ctarget = card_dict[card.target]; + if (ctarget.ability.includes("morale")) { + score += Number(ctarget["strength"]) + row.cards.filter(c => c.isUnit()).length - 1; + } else if (ctarget.ability.includes("bond")) { + let n = 1; + if (!row.effects.mardroeme) + n += row.cards.filter(c => c.key === card.key).filter(c => !c.isLocked()).length; + else + n += row.cards.filter(c => c.key === card.target).filter(c => !c.isLocked()).length; + score += Number(ctarget["strength"]) * (n * n); + } else if (ctarget.ability.includes("scorch_c")) { + score += this.weightScorchRow(card, this.getMaximums(), "close"); + } else { + score += Number(ctarget["strength"]); + } + return Math.max(1, score); + } + + // Calculates the weight for a weather card if played from the deck + weightWeatherFromDeck(card, weather_id) { + if (card.holder.deck.findCard(c => c.abilities.includes(weather_id)) === undefined) + return 0; + return this.weightCard({ + abilities: [weather_id], + row: "weather" + }); + } + + // Assigns a weights for how likely the controller with play a card from its hand + weightCard(card, max, data) { + let abi + if (card.abilities) { + abi = card.abilities; + } else if (card["ability"]) { + abi = card["ability"].split(" "); + } else { + abi = []; + console.log("Missing abilities for card:"); + console.log(card); + } + if (abi.includes("decoy")) { + if (card.row.length > 0) { + let row_data; + if (["close","agile","agile_cr","agile_cs","agile_crs"].includes(card.row)) + row_data = this.countCards(board.getRow(card, "close", this.player), row_data); + if (["ranged", "agile", "agile_cr", "agile_rs", "agile_crs"].includes(card.row)) + row_data = this.countCards(board.getRow(card, "ranged", this.player), row_data); + if (["agile_cs", "agile_rs", "agile_crs"].includes(card.row)) + row_data = this.countCards(board.getRow(card, "siege", this.player), row_data); + return game.decoyCancelled ? 0 : row_data.spy.length ? 50 : row_data.medic.length ? 15 : row_data.scorch.length ? 10 : max.me.length ? card.power : 0; + } else + return game.decoyCancelled ? 0 : data.spy.length ? 50 : data.medic.length ? 15 : data.scorch.length ? 10 : max.me.length ? 1 : 0; + } + if (abi.includes("horn")) { + let rows = this.player.getAllRows().filter(r => !r.special.containsCardByKey("spe_horn")); + if (!rows.length) + return 0; + rows = rows.map(r => this.weightHornRow(card, r)); + return Math.max(...rows) / 2; + } + + if (abi) { + if (abi.includes("scorch")) { + if (game.scorchCancelled) + return Math.max(0, card.power); + let power_op = max.op_noshield.length ? max.op_noshield[0].card.power : 0; + let power_me = max.me_noshield.length ? max.me_noshield[0].card.power : 0; + let total_op = power_op * max.op_noshield.length; + let total_me = power_me * max.me_noshield.length; + return power_me > power_op ? 0 : power_me < power_op ? total_op : Math.max(0, total_op - total_me); + } + if (abi.includes("decoy")) { + return game.decoyCancelled ? 0 : data.spy.length ? 50 : data.medic.length ? 15 : data.scorch.length ? 10 : max.me.length ? 1 : 0; + } + if (abi.includes("mardroeme")) { + let rows = this.player.getAllRows(); + return Math.max(...rows.map(r => this.weightMardroemeRow(card, r))); + } + if (["cintra_slaughter", "seize", "lock", "shield", "knockback", "shield_c", "shield_r", "shield_s", "bank", "skellige_fleet","immortal","royal_decree","summon_one_of","curse"].includes(abi.at(-1))) { + return ability_dict[abi.at(-1)].weight(card); + } + if (abi.includes("witch_hunt")) { + if (game.scorchCancelled) + return card.power; + let best_row = this.bestWitchHuntRow(card) + if (best_row) { + let dmg = best_row.minUnits().reduce((a, c) => a + c.power, 0); + if (dmg < 6) // Let's not waste it on isolated weak units + dmg = 0; + return dmg + card.power; + } + return card.power + } + if (abi.includes("toussaint_wine")) { + let units = card.holder.getAllRowCards().concat(card.holder.hand.cards).filter(c => c.isUnit()).filter(c => !c.abilities.includes("spy")); + let rowStats = { + "close": 0, + "ranged": 0, + "siege": 0, + "agile": 0, + "agile_cr": 0, + "agile_rs": 0, + "agile_cs": 0, + "agile_crs": 0 + }; + units.forEach(c => { + rowStats[c.row] += 1; + }); + rowStats["close"] += (rowStats["agile"] + rowStats["agile_cr"] + rowStats["agile_cs"] + rowStats["agile_crs"]); + rowStats["ranged"] += rowStats["agile_rs"] + + let rows = card.holder.getAllRows(); + rowStats["close"] = board.getRow(card, "close", this.player).effects.toussaint_wine > 0 ? 0 : rowStats["close"]; + rowStats["ranged"] = board.getRow(card, "ranged", this.player).effects.toussaint_wine > 0 ? 0 : rowStats["ranged"]; + rowStats["siege"] = board.getRow(card, "siege", this.player).effects.toussaint_wine > 0 ? 0 : rowStats["siege"]; + return 2 * Math.max(rowStats["close"], rowStats["ranged"], rowStats["siege"]); + } + if (abi.at(-1) && abi.at(-1).startsWith("witcher_")) { + let witchers = card.holder.getAllRowCards().filter(c => c.abilities.includes(abi.at(-1))); + let keep = witchers.filter(c => c.hero); + return card.power + (2 * witchers.length * 2) + (keep.length > 0 ? keep[0].power : 0); + } + if (abi.includes("inspire")) { + let insp = card.holder.getAllRowCards().filter(c => c.abilities.includes("inspire")); + let best_power = 0; + if (insp.length > 0) + best_power = insp.sort((a, b) => b.power - a.power)[0].power; + let max_power = Math.max(card.power, best_power); + if (card.power === max_power) + return max_power + insp.map(c => max_power - c.power).reduce((a, c) => a + c, 0); + return max_power; + } + } + + if (card.row === "weather" || (card.deck && card.deck.startsWith("weather"))) { + return Math.max(0, this.weightWeather(card)); + } + + let row = board.getRow(card, ["agile", "agile_cr", "agile_cs", "agile_crs"].includes(card.row) ? "close" : ["ranged","agile_rs"].includes(card.row) ? "ranged" : card.row, this.player); + let score = row.calcCardScore(card); + switch (abi[abi.length - 1]) { + case "bond": + case "morale": + case "toussaint_wine": + case "horn": + score = card.row.includes("agile") ? this.bestAgileRowChange(card).score : this.weightRowChange(card, row); + break; + case "medic": + score = this.weightMedic(data, score, card.holder); + break; + case "spy": + score = 15 + score; + break; + case "muster": + let pred = c => c.target === card.target; + let units = card.holder.hand.cards.filter(pred).concat(card.holder.deck.cards.filter(pred)); + score *= units.length; + break; + case "scorch_c": + score = Math.max(1, this.weightScorchRow(card, max, "close")); + break; + case "scorch_r": + score = Math.max(1, this.weightScorchRow(card, max, "ranged")); + break; + case "scorch_s": + score = Math.max(1, this.weightScorchRow(card, max, "siege")); + break; + case "berserker": + score = this.weightBerserker(card, row, score); + break; + case "avenger": + case "avenger_kambi": + case "whorshipper": + case "necrophage": + case "goetia": + case "ambush": + return score + ability_dict[abi.at(-1)].weight(card); + } + + return score; + } + + // Calculates the current power of a row associated with each Player + calcRowPower(r, dif, add) { + r.findCards(c => c.isUnit()).forEach(c => { + let p = r.calcCardScore(c); + c.holder === this.player ? (dif[0] += add ? p : -p) : (dif[1] += add ? p : -p); + }); + } +} + +var may_leader = true, + exibindo_lider = false; + +// Can make actions during turns like playing cards that it owns +class Player { + constructor(id, name, deck, isAI = true) { + this.id = id; + this.tag = (id === 0) ? "me" : "op"; + //this.controller = (id === 0) ? new Controller() : new ControllerAI(this); + if (isAI) { + this.controller = new ControllerAI(this); + } else { + this.controller = new Controller(); + this.ai = new ControllerAI(this); // Exposes AI features which can be used by the actual AI to make estimations + } + + if (game.mode === 2) { + // AI vs AI + this.hand = (id === 0) ? new Hand(document.getElementById("hand-row"), this.tag) : new Hand(document.getElementById("op-hand-row"), this.tag); + } else if (game.mode === 3) { + // Player vs Player + if (id === 0) { + this.hand = new Hand(document.getElementById("hand-row"), this.tag); + } else { + this.hand = new Hand(document.getElementById("op-hand-row"), this.tag); + document.getElementById("op-hand-row").classList.add("human-op"); // This a playable opponent hand + } + } else { + this.hand = (id === 0) ? new Hand(document.getElementById("hand-row"), this.tag) : new HandAI(this.tag); + } + this.hand.player = this; + this.grave = new Grave(document.getElementById("grave-" + this.tag)); + this.deck = new Deck(deck.faction, document.getElementById("deck-" + this.tag)); + this.deck_data = deck; + this.leader = new Card(deck.leader.index, deck.leader.card, this); + this.elem_leader = document.getElementById("leader-" + this.tag); + this.elem_leader.children[0].appendChild(this.leader.elem); + + this.reset(); + + this.name = name; + document.getElementById("name-" + this.tag).innerHTML = name; + + if (deck.title) + document.getElementById("deck-name-" + this.tag).innerHTML = deck.title; + else + document.getElementById("deck-name-" + this.tag).innerHTML = factions[deck.faction].name; + document.getElementById("stats-" + this.tag).getElementsByClassName("profile-img")[0].children[0].children[0]; + let x = document.querySelector("#stats-" + this.tag + " .profile-img > div > div"); + x.style.backgroundImage = iconURL("deck_shield_" + deck.faction); + } + + getAIController() { + if (this.controller instanceof ControllerAI) { + return this.controller; + } else { + return this.ai; + } + } + + // Sets default values + reset() { + this.grave.reset(); + this.hand.reset(); + this.deck.reset(); + this.deck.initializeFromID(this.deck_data.cards, this); + + this.health = 2; + this.total = 0; + this.passed = false; + this.handsize = 10; + this.mulliganCount = 2; + this.winning = false; + this.factionAbilityUses = 0; + this.effects = { + "witchers": {}, + "whorshippers": 0, + "inspire": 0 + }; + this.capabilities = { + "drawOPdeck": 0, + "endTurnRetake": 0, + "cardEdit": 0 + }; + this.forcedActions = []; + this.endturn_action = null; + + // Handling Faction abilities: active or passive + let factionAbility = factions[this.deck.faction]; + if (factionAbility["activeAbility"]) { + // Init ability if need be + if (factionAbility.factionAbilityInit) { + factionAbility.factionAbilityInit(this); + } + this.updateFactionAbilityUses(factionAbility["abilityUses"]); + + document.getElementById("faction-ability-" + this.tag).classList.remove("hide"); + if (this.tag === "me" || game.isPvP()) + document.getElementById("faction-ability-" + this.tag).addEventListener("click", () => this.activateFactionAbility(), false); + } else { + document.getElementById("faction-ability-" + this.tag).classList.add("hide"); + } + + this.enableLeader(); + this.setPassed(false); + document.getElementById("gem1-" + this.tag).classList.add("gem-on"); + document.getElementById("gem2-" + this.tag).classList.add("gem-on"); + } + + roundStartReset() { + this.effects = { + "witchers": {}, + "whorshippers": 0, + "inspire": 0 + }; + this.forcedActions = []; + } + + // Returns the opponent Player + opponent() { + return board.opponent(this); + } + + // Updates the player's total score and notifies the gamee + updateTotal(n) { + this.total += n; + document.getElementById("score-total-" + this.tag).children[0].innerHTML = this.total; + board.updateLeader(); + } + + // Puts the player in the winning state + setWinning(isWinning) { + if (this.winning ^ isWinning) + document.getElementById("score-total-" + this.tag).classList.toggle("score-leader"); + this.winning = isWinning; + } + + // Puts the player in the passed state + setPassed(hasPassed) { + if (this.passed ^ hasPassed) + document.getElementById("passed-" + this.tag).classList.toggle("passed"); + this.passed = hasPassed; + } + + // Sets up board for turn + async startTurn() { + document.getElementById("stats-" + this.tag).classList.add("current-turn"); + if (this.leaderAvailable) + this.elem_leader.children[1].classList.remove("hide"); + + if (this === player_me || game.isPvP()) { + document.getElementById("pass-button").classList.remove("noclick"); + may_pass1 = true; + } + + if (this.controller instanceof ControllerAI) { + await this.controller.startTurn(this); + } else { + // If there is a pending forced action, do it or pass + if (this.forcedActions.length > 0) { + let card = this.forcedActions.splice(0, 1)[0]; + ui.showPreviewVisuals(card); + // Ask if the player wants to play the card or pass + let c = await ui.popup("Play card [E]", (p) => p.choice = true, "Pass [Q]", (p) => p.choice = false, "Play card or pass?", "You are forced to play this card or pass for this round, which option do you choose?"); + ui.enablePlayer(true); + if (c) { + document.getElementById("click-background").classList.add("noclick"); + this.hand.cards.forEach(c => c.elem.classList.add("noclick")); + ui.setSelectable(card, true); + } else { + this.passRound(); + } + } + } + } + + // Passes the round and ends the turn + async passRound() { + this.setPassed(true); + ui.notification("op-pass", 1200); + await this.endTurn(); + } + + // Plays a scorch card + async playScorch(card) { + if (!game.scorchCancelled) + await this.playCardAction(card, async () => await ability_dict["scorch"].activated(card)); + } + + // Plays a Slaughter of Cintra card + async playSlaughterCintra(card) { + await this.playCardAction(card, async () => await ability_dict["cintra_slaughter"].activated(card)); + } + + // Plays a Seize special card card + async playSeize(card) { + await this.playCardAction(card, async () => await ability_dict["seize"].activated(card)); + } + + // Plays a Knockback special card card, assuming 1 valid + async playKnockback(card) { + let best_row = board.getRow(card, "close", this.opponent()); + //If melee row is empty, better target ranged + if (board.getRow(card, "close", this.opponent()).cards.length === 0) + best_row = board.getRow(card, "ranged", this.opponent()); + // If siege has an active weather effect, better target ranged + if (board.getRow(card, "ranged", this.opponent()).cards.length > 1 && board.getRow(card, "siege", this.opponent()).effects.weather) + best_row = board.getRow(card, "ranged", this.opponent()); + // If ranged has a horn or shield effect, better target it + if ((board.getRow(card, "ranged", this.opponent()).isShielded() || board.getRow(card, "ranged", this.opponent()).effects.horn > 0) && board.getRow(card, "ranged", this.opponent()).cards.length > 0) + best_row = board.getRow(card, "ranged", this.opponent()); + // If there are some bond units in the ranged row, better try to break it before it grows + if (Object.keys(board.getRow(card, "ranged", this.opponent()).effects.bond).length > 0 && board.getRow(card, "siege", this.opponent()).effects.horn === 0) + best_row = board.getRow(card, "ranged", this.opponent()); + await this.playCardAction(card, async () => await ability_dict["knockback"].activated(card, best_row)); + } + + // Play the bank card + async playBank(card) { + await this.playCardAction(card, async () => await ability_dict["bank"].activated(card)); + } + + // Play the skellige fleet card + async playSkelligeFleet(card) { + await this.playCardAction(card, async () => await ability_dict["skellige_fleet"].activated(card)); + } + + // Play the royal decree card + async playRoyalDecree(card) { + await this.playCardAction(card, async () => await ability_dict["royal_decree"].activated(card)); + } + + // Plays a card to a specific row + async playCardToRow(card, row, endTurn=true) { + await this.playCardAction(card, async () => await board.moveTo(card, row, this.hand), endTurn); + } + + // Plays a card to the board + async playCard(card) { + await this.playCardAction(card, async () => await card.autoplay(this.hand)); + } + + // Shows a preview of the card being played, plays it to the board and ends the turn + async playCardAction(card, action, endTurn = true) { + ui.showPreviewVisuals(card); + await sleep(1000); + ui.hidePreview(card); + await action(); + if(endTurn) + await this.endTurn(); + } + + // Handles end of turn visuals and behavior the notifies the game + async endTurn(noEffects=false) { + if (this.endturn_action) { + // Call action instead of ending turn + await this.endturn_action(); + return; + } + if (!this.passed && !this.canPlay()) { + this.setPassed(true); + ui.notification("op-pass", 1200); + } + if (this === player_me) { + document.getElementById("pass-button").classList.add("noclick"); + may_pass1 = false; + } + document.getElementById("stats-" + this.tag).classList.remove("current-turn"); + this.elem_leader.children[1].classList.add("hide"); + game.endTurn(noEffects) + } + + // Tells the the Player if it won the round. May damage health. + endRound(win) { + if (!win) { + if (this.health < 1) + return; + document.getElementById("gem" + this.health + "-" + this.tag).classList.remove("gem-on"); + this.health--; + } + this.setPassed(false); + this.setWinning(false); + } + + // Returns true if the Player can make any action other than passing + canPlay() { + return this.hand.cards.length > 0 || this.leaderAvailable || this.factionAbilityUses > 0; + } + + // Use a leader's Activate ability, then disable the leader + // Option to not end turn and disable leader - useful when we want to trigger the leader ability in other circumstances + async activateLeader(endTurn=true,disableLeader=true) { + try { + Carousel.curr.cancel(); + } catch (err) { } + if (this.leaderAvailable) { + this.endTurnAfterAbilityUse = endTurn; + let res = await this.leader.activated[0](this.leader, this); + // If the leader activity signaled it couldn't be actually used, we stop right here + if (res == false) { + ui.enablePlayer(true); + return false; + } + if (disableLeader) + this.disableLeader(); + // Some abilities require further actions before ending the turn, such as selecting a card + if (this.endTurnAfterAbilityUse) + await this.endTurn(); + else { + // Make selections for AI player + if (this.controller instanceof ControllerAI) { + if (this.leader.key === "wu_alzur_maker") { + let worse_unit = this.getAllRowCards().filter(c => c.isUnit()).sort((a, b) => a.power - b.power)[0]; + ui.selectCard(worse_unit); + } else if (this.leader.key === "to_anna_henrietta_duchess") { + let horns = player_me.getAllRows().filter(r => r.special.findCards(c => c.abilities.includes("horn")).length > 0).sort((a, b) => b.total - a.total); + if (horns[0]) + ui.selectRow(horns[0]); + } else if (this.leader.key === "lr_meve_princess" || this.leader.key === "sy_carlo_varese") { + let max = this.controller.getMaximums(); + let rows = [this.controller.weightScorchRow(this.leader, max, "close"), this.controller.weightScorchRow(this.leader, max, "ranged"), this.controller.weightScorchRow(this.leader, max, "siege")]; + let maxv = 0, + max_row; + let offset = 3; + if (this === player_me) { + offset = 0; + rows = rows.reverse(); + } + for (var i = 0; i < 3; i++) { + if (rows[i] > maxv) { + maxv = rows[i]; + max_row = board.row[offset + i]; + } + } + if (max_row) + ui.selectRow(max_row); + } else if (this.leader.key === "sy_cyrus_hemmelfart") { + // We select a random row to put shackles on + let offset = 3; + if (this === player_me) + offset = 0; + ui.selectRow(board.row[offset + randomInt(2)]); + } + } + } + } + } + + // Disable access to leader ability and toggles leader visuals to off state + disableLeader() { + this.leaderAvailable = false; + let elem = this.elem_leader.cloneNode(true); + this.elem_leader.parentNode.replaceChild(elem, this.elem_leader); + this.elem_leader = elem; + this.elem_leader.children[0].classList.add("fade"); + this.elem_leader.children[1].classList.add("hide"); + this.elem_leader.addEventListener("click", async () => await ui.viewCard(this.leader), false); + } + + // Enable access to leader ability and toggles leader visuals to on state + enableLeader() { + this.leaderAvailable = this.leader.activated.length > 0; + let elem = this.elem_leader.cloneNode(true); + this.elem_leader.parentNode.replaceChild(elem, this.elem_leader); + this.elem_leader = elem; + this.elem_leader.children[0].classList.remove("fade"); + this.elem_leader.children[1].classList.remove("hide"); + + if ((this.id === 0 || game.isPvP()) && this.leader.activated.length > 0) { + this.elem_leader.children[0].addEventListener("click", + async () => await ui.viewCard(this.leader, async () => await this.activateLeader()), + false + ); + this.elem_leader.children[0].addEventListener("mouseover", function () { + tocar("card", false); + this.style.boxShadow = "0 0 1.5vw #6d5210" + }); + this.elem_leader.children[0].addEventListener("mouseout", function () { + this.style.boxShadow = "0 0 0 #6d5210" + }); + + window.addEventListener("keydown", function (e) { + if (may_leader && may_pass1) { + if (e.keyCode == 88) { + if (exibindo_lider) { + exibindo_lider = false; + player_me.activateLeader(); + } else if (player_me.leaderAvailable) { + may_leader = false; + exibindo_lider = true; + player_me.callLeader(); + } + } + } + }); + window.addEventListener("keyup", function (e) { + if (player_me.leaderAvailable) may_leader = true; + }); + } else { + this.elem_leader.children[0].addEventListener("click", async () => await ui.viewCard(this.leader), false); + this.elem_leader.children[0].addEventListener("mouseover", function () { }); + this.elem_leader.children[0].addEventListener("mouseout", function () { }); + } + // TODO set crown color + } + + async callLeader() { + await ui.viewCard(player_me.leader, async () => await player_me.activateLeader()); + } + + async activateFactionAbility() { + let factionData = factions[this.deck.faction]; + if (factionData.activeAbility && this.factionAbilityUses > 0) { + await ui.popup("Use faction ability [E]", () => this.useFactionAbility(), "Cancel [Q]", () => this.escapeFactionAbility(), "Would you like to use your faction ability?", "Faction ability: " + factionData.description); + } + return; + } + + async useFactionAbility() { + let factionData = factions[this.deck.faction]; + if (factionData.activeAbility && this.factionAbilityUses > 0) { + this.endTurnAfterAbilityUse = true; + await factionData.factionAbility(this); + this.updateFactionAbilityUses(this.factionAbilityUses - 1); + // Some faction abilities require extra interractions + if (this.endTurnAfterAbilityUse) + await this.endTurn(); + if (this.controller instanceof ControllerAI) { + if (this.deck.faction === "lyria_rivia") { + let best_row = this.controller.bestRowToussaintWine(ui.previewCard); // Reusing bestRowToussaintWine because it is nearly the same principle + ui.selectRow(best_row, true); + } + } + } + return; + } + + // Called when chose to not play the faction ability + async escapeFactionAbility() { + ui.enablePlayer(true); + } + + updateFactionAbilityUses(count) { + this.factionAbilityUses = Math.max(0, count); + document.getElementById("faction-ability-count-" + this.tag).innerHTML = this.factionAbilityUses; + if (this.factionAbilityUses === 0) { + document.getElementById("faction-ability-" + this.tag).classList.add("fade"); + } else { + document.getElementById("faction-ability-" + this.tag).classList.remove("fade"); + } + } + + // Get all rows for this player, sorted to have close > ranged > siege + getAllRows() { + if (this === player_me) { + return board.row.filter((r, i) => i > 2); + } + return board.row.filter((r, i) => i < 3).reverse(); + } + + // Get all special rows for this player, sorted to have close > ranged > siege + getAllSpecialRows() { + return this.getAllRows().map(r => r.special); + } + + // Get all cards in rows for this player + getAllRowCards() { + return this.getAllRows().reduce((a, r) => r.cards.concat(a), []); + } + + // Get all cards in special rows for this player + getAllSpecialRowCards() { + return this.getAllSpecialRows().reduce((a, r) => r.cards.concat(a), []); + } + + // Prepare game and UI to let the player select where on the board to play the given card + selectCardDestination(card,src=null,callback=null) { + // Move from deck to hand + if(src) + src.removeCard(card); + this.hand.addCard(card); + // Enable board interaction - Force to select a destination + ui.showPreviewVisuals(card); + document.getElementById("click-background").classList.add("noclick"); + this.hand.cards.forEach(c => c.elem.classList.add("noclick")); + ui.setSelectable(card, true); + // Prevent the end of turn while selecting cards + this.endturn_action = async () => { + this.endturn_action = null; + if (callback) + callback(); + } + ui.enablePlayer(true); + } +} + +function alteraClicavel(obj, add) { + try { + if (!add && fileira_clicavel.elem.id == obj.elem.id) fileira_clicavel = null; + else fileira_clicavel = obj; + } catch (err) { } +} + +// Handles the adding, removing and formatting of cards in a container +class CardContainer { + constructor(elem) { + this.elem = elem; + this.cards = []; + } + + // Indicates whether or not this container contains any card + isEmpty() { + return this.cards.length === 0; + } + + // Returns the first card that satisfies the predcicate. Does not modify container. + findCard(predicate) { + for (let i = this.cards.length - 1; i >= 0; --i) + if (predicate(this.cards[i])) + return this.cards[i]; + } + + // Returns a list of cards that satisfy the predicate. Does not modify container. + findCards(predicate) { + return this.cards.filter(predicate); + } + + // Indicates whether or not the card with given Key can be found in container + containsCardByKey(key) { + return (this.findCards(c => c.key === key).length) > 0; + } + + // Returns a list of up to n cards that satisfy the predicate. Does not modify container. + findCardsRandom(predicate, n) { + let valid = predicate ? this.cards.filter(predicate) : this.cards; + if (valid.length === 0) + return []; + if (!n || n === 1) + return [valid[randomInt(valid.length)]]; + // Randum shuffle then select first n items + valid = [...valid].sort(() => 0.5 - Math.random()) + return valid.slice(0, n); + } + + // Removes and returns a list of cards that satisy the predicate. + getCards(predicate) { + return this.cards.reduce((a, c, i) => (predicate(c, i) ? [i] : []).concat(a), []).map(i => this.removeCard(i)); + } + + // Removes and returns a card that satisfies the predicate. + getCard(predicate) { + for (let i = this.cards.length - 1; i >= 0; --i) + if (predicate(this.cards[i])) + return this.removeCard(i); + } + + // Removes and returns any cards up to n that satisfy the predicate. + getCardsRandom(predicate, n) { + return this.findCardsRandom(predicate, n).map(c => this.removeCard(c)); + } + + // Adds a card to the container along with its associated HTML element. + addCard(card, index) { + this.cards.push(card); + this.addCardElement(card, index ? index : 0); + this.resize(); + card.currentLocation = this; + } + + // Removes a card from the container along with its associated HTML element. + removeCard(card, index) { + if (this.cards.length === 0) + throw "Cannot draw from empty " + this.constructor.name; + card = this.cards.splice(isNumber(card) ? card : this.cards.indexOf(card), 1)[0]; + this.removeCardElement(card, index ? index : 0); + this.resize(); + if (card.temporaryPower) { + card.basePower = card.originalBasePower; + card.originalBasePower = null; + card.temporaryPower = false; + } + return card; + } + + // Adds a card to a pre-sorted CardContainer + addCardSorted(card) { + let i = this.getSortedIndex(card); + this.cards.splice(i, 0, card); + return i; + } + + // Returns the expected index of a card in a sorted CardContainer + getSortedIndex(card) { + for (var i = 0; i < this.cards.length; ++i) + if (Card.compare(card, this.cards[i]) < 0) + break; + return i; + } + + // Adds a card to a random index of the CardContainer + addCardRandom(card) { + this.cards.push(card); + let index = randomInt(this.cards.length); + if (index !== this.cards.length - 1) { + let t = this.cards[this.cards.length - 1]; + this.cards[this.cards.length - 1] = this.cards[index]; + this.cards[index] = t; + } + card.currentLocation = this; + return index; + } + + // Removes the HTML element associated with the card from this CardContainer + removeCardElement(card, index) { + if (this.elem) + this.elem.removeChild(card.elem); + } + + // Adds the HTML element associated with the card to this CardContainer + addCardElement(card, index) { + if (this.elem) { + if (index === this.cards.length) + this.elem.appendChild(card.elem); + else + this.elem.insertBefore(card.elem, this.elem.children[index]); + } + } + + // Empty function to be overried by subclasses that resize their content + resize() { } + + // Modifies the margin of card elements inside a row-like container to stack properly + resizeCardContainer(overlap_count, gap, coef) { + let n = this.elem.children.length; + let param = (n < overlap_count) ? "" + gap + "vw" : defineCardRowMargin(n, coef); + let children = this.elem.getElementsByClassName("card"); + for (let x of children) + x.style.marginLeft = x.style.marginRight = param; + + function defineCardRowMargin(n, coef = 0) { + return "calc((100% - (4.45vw * " + n + ")) / (2*" + n + ") - (" + coef + "vw * " + n + "))"; + } + } + + // Allows the row to be clicked + setSelectable() { + this.elem.classList.add("row-selectable"); + alteraClicavel(this, true); + } + + // Disallows the row to be clicked + clearSelectable() { + this.elem.classList.remove("row-selectable"); + alteraClicavel(this, false); + for (card in this.cards) + card.elem.classList.add("noclick"); + } + + // Returns the container to its default, empty state + reset() { + while (this.cards.length) + this.removeCard(0); + if (this.elem) + while (this.elem.firstChild) + this.elem.removeChild(this.elem.firstChild); + this.cards = []; + } + +} + +// Contians all used cards in the order that they were discarded +class Grave extends CardContainer { + constructor(elem) { + super(elem) + elem.addEventListener("click", () => ui.viewCardsInContainer(this), false); + } + + // Override + addCard(card) { + this.setCardOffset(card, this.cards.length); + super.addCard(card, this.cards.length); + card.destructionRound = game.roundCount; + } + + // Override + removeCard(card) { + let n = isNumber(card) ? card : this.cards.indexOf(card); + return super.removeCard(card, n); + } + + // Override + removeCardElement(card, index) { + card.elem.style.left = ""; + for (let i = index; i < this.cards.length; ++i) this.setCardOffset(this.cards[i], i); + super.removeCardElement(card, index); + } + + // Offsets the card element in the deck + setCardOffset(card, n) { + card.elem.style.left = -0.03 * n + "vw"; + } +} + +// Contians all special cards for a given row +class RowSpecial extends CardContainer { + constructor(elem, row) { + super(elem) + this.row = row; + } + + // Override + addCard(card) { + this.setCardOffset(card, this.cards.length); + super.addCard(card, this.cards.length); + } + + // Override + removeCard(card) { + let n = isNumber(card) ? card : this.cards.indexOf(card); + if (card.removed) { + for (let x of card.removed) + x(card); + } + return super.removeCard(card, n); + } + + // Override + removeCardElement(card, index) { + card.elem.style.left = ""; + for (let i = index; i < this.cards.length; ++i) this.setCardOffset(this.cards[i], i); + super.removeCardElement(card, index); + } + + // Offsets the card element in the deck + setCardOffset(card, n) { + card.elem.style.left = (1 + n) + "vw"; + } + +} + +// Contains a randomized set of cards to be drawn from +class Deck extends CardContainer { + constructor(faction, elem) { + super(elem); + this.faction = faction; + + this.counter = document.createElement("div"); + this.counter.classList = "deck-counter center"; + this.counter.appendChild(document.createTextNode(this.cards.length)); + this.elem.appendChild(this.counter); + } + + // Creates duplicates of cards with a count of more than one, then initializes deck + initializeFromID(card_id_list, player) { + this.initialize(card_id_list.reduce((a, c) => a.concat(clone(c.count, c)), []), player); + + function clone(n, elem) { + for (var i = 0, a = []; i < n; ++i) a.push(elem); + return a; + } + } + + // Populates a this deck with a list of card data and associated those cards with the owner of this deck. + initialize(card_data_list, player) { + this.player = player; + for (let i = 0; i < card_data_list.length; ++i) { + let card = new Card(card_data_list[i].index, card_dict[card_data_list[i].index], player); + card.holder = player; + this.addCardRandom(card); + this.addCardElement(); + } + this.resize(); + } + + // Override + addCard(card) { + this.addCardRandom(card); + this.addCardElement(); + this.resize(); + card.currentLocation = this; + } + + // Sends the top card to the passed hand + async draw(hand) { + tocar("game_buy", false); + // In case a player draws from opponent deck + if (hand.player && this.player !== hand.player) + this.cards[0].holder = hand.player; + if (hand instanceof HandAI) + hand.addCard(this.removeCard(0)); + else + await board.toHand(this.cards[0], this, hand); + } + + // Draws a card and sends it to the container before adding a card from the container back to the deck. + swap(container, card) { + container.addCard(this.removeCard(0)); + this.addCard(card); + } + + // Override + addCardElement() { + let elem = document.createElement("div"); + elem.classList.add("deck-card"); + elem.style.backgroundImage = iconURL("deck_back_" + this.faction, "jpg"); + this.setCardOffset(elem, this.cards.length - 1); + this.elem.insertBefore(elem, this.counter); + } + + // Override + removeCardElement() { + this.elem.removeChild(this.elem.children[this.cards.length]).style.left = ""; + } + + // Offsets the card element in the deck + setCardOffset(elem, n) { + elem.style.left = -0.03 * n + "vw"; + } + + // Override + resize() { + this.counter.innerHTML = this.cards.length; + this.setCardOffset(this.counter, this.cards.length); + } + + // Override + reset() { + super.reset(); + this.elem.appendChild(this.counter); + } +} + +// Hand used by computer AI. Has an offscreen HTML element for card transitions. +class HandAI extends CardContainer { + constructor(tag) { + super(undefined, tag); + this.player = null; + if (this.tag === "me") { + this.counter = document.getElementById("hand-count-me"); + this.hidden_elem = document.getElementById("hand-me"); + } else { + this.counter = document.getElementById("hand-count-op"); + this.hidden_elem = document.getElementById("hand-op"); + } + + } + resize() { + this.counter.innerHTML = this.cards.length; + } +} + +// Hand used by current player +class Hand extends CardContainer { + constructor(elem, tag) { + super(elem); + this.tag = tag; + this.player = null; + if (this.tag === "me") { + this.counter = document.getElementById("hand-count-me"); + } else { + this.counter = document.getElementById("hand-count-op"); + } + } + + // Override + addCard(card) { + let i = this.addCardSorted(card); + this.addCardElement(card, i); + this.resize(); + card.currentLocation = this; + } + + // Override + resize() { + this.counter.innerHTML = this.cards.length; + this.resizeCardContainer(11, 0.075, .00225); + } + + toggleDisplay() { + if (this.elem.hidden) { + this.elem.style.visibility = "visible"; + } else { + this.elem.style.visibility = "hidden"; + } + this.elem.hidden = !this.elem.hidden; + } + + hide() { + this.elem.style.visibility = "hidden"; + } + + show() { + this.elem.style.visibility = "visible"; + } +} + +var may_act_card = true; + +// Contains active cards and effects. Calculates the current score of each card and the row. +class Row extends CardContainer { + constructor(elem) { + super(elem.getElementsByClassName("row-cards")[0]); + this.elem_parent = elem; + this.special = new RowSpecial(elem.getElementsByClassName("row-special")[0], this); + this.total = 0; + this.effects = { + weather: false, + weather_type: "", + bond: {}, + morale: 0, + horn: 0, + mardroeme: 0, + shield: 0, + lock: 0, + curse: 0, + toussaint_wine: 0, + ambush: false + }; + this.halfWeather = false; + this.elem.addEventListener("click", () => ui.selectRow(this), true); + this.elem.addEventListener("mouseover", function () { + if (hover_row) { + tocar("card", false); + this.style.boxShadow = "0 0 1.5vw #6d5210"; + } + }); + this.elem.addEventListener("mouseout", function () { + this.style.boxShadow = "0 0 0 #6d5210" + }); + window.addEventListener("keydown", function (e) { + if (e.keyCode == 13 && fileira_clicavel !== null && may_act_card) { + ui.selectRow(fileira_clicavel); + may_act_card = false; + fileira_clicavel = null; + } + }); + window.addEventListener("keyup", function (e) { + if (e.keyCode == 13) may_act_card = true; + }); + this.special.elem.addEventListener("click", () => ui.selectRow(this, true), false, true); + } + + // Override + async addCard(card, runEffect = true) { + if (card.isSpecial()) { + this.special.addCard(card); + } else { + let index = this.addCardSorted(card); + this.addCardElement(card, index); + this.resize(); + } + card.currentLocation = this; + if (this.effects.curse && card.isUnit()) { + this.effects.curse = Math.max(this.effects.curse - 1, 0); + await card.animate("curse"); + await board.toGrave(card, this); + let curse_card = this.special.findCard(c => c.abilities.includes("curse")); + await board.toGrave(curse_card, this.special); + return; + } else if (this.effects.lock && card.isUnit() && card.abilities.length) { + card.locked = true; + this.effects.lock = Math.max(this.effects.lock - 1, 0); + let lock_card = this.special.findCard(c => c.abilities.includes("lock")); + // If several units arrive at the same time, it can be triggered several times, so we first remove the lock before doing animations + if (lock_card) + await board.toGrave(lock_card, this.special); + await card.animate("lock"); + } + // Some cards have abilities with permanent row effects - such has horn, bond or morale + if (!runEffect && card.abilities.length > 0) { + for (var i = 0; i < card.abilities.length; i++) { + if ("effectAfterMove" in ability_dict[card.abilities[i]] && ability_dict[card.abilities[i]]["effectAfterMove"]) + runEffect = true; + } + } + if (runEffect && !card.isLocked()) { + this.updateState(card, true); + for (let x of card.placed) + await x(card, this); + } + if (runEffect && this.effects.ambush) { + let ambushCards = this.cards.filter(c => c.abilities.includes("ambush") && + (c.holder !== card.holder && !card.abilities.includes("spy") && !card.abilities.includes("emissary")) || + (c.holder === card.holder && (card.abilities.includes("spy") || card.abilities.includes("emissary")))); // Spy/Emissaries switch sides before being placed and would have triggerd when played by the owner of an ambush card + if (ambushCards.length > 0 && ambushCards[0] !== card) { + let targetCard = ambushCards[0]; + // Remove status first before animations to avoid triggering the ambush several times when several cards arrive at the same time + if (ambushCards.length < 2) + this.effects.ambush = false; + // Owner draws 2 cards + await targetCard.animate("ambush"); + targetCard.holder.deck.draw(targetCard.holder.hand); + targetCard.holder.deck.draw(targetCard.holder.hand); + // Cards goes to the grave + await board.toGrave(targetCard, targetCard.currentLocation); + + } + } + card.elem.classList.add("noclick"); + await sleep(600); + //this.updateScore(); + // Let's update all rows for better accuracy + board.updateScores(); + } + + // Override + removeCard(card, runEffect = true) { + // TODO: This case should no longer happen + if (isNumber(card) && card === -1) { + card = this.special.cards[0]; + this.special.reset(); + return card; + } + card = isNumber(card) ? this.cards[card] : card; + if (card.isSpecial()) { + this.special.removeCard(card); + } else { + super.removeCard(card); + card.resetPower(); + card.locked = false; + } + this.updateState(card, false); + if (runEffect) { + if (!card.decoyTarget) { + for (let x of card.removed) + x(card); + } else { + card.decoyTarget = false; + } + + } + this.updateScore(); + return card; + } + + // Override + removeCardElement(card, index) { + super.removeCardElement(card, index); + let x = card.elem; + x.style.marginLeft = x.style.marginRight = ""; + x.classList.remove("noclick"); + } + + // Updates a card's effect on the row + updateState(card, activate) { + for (let x of card.abilities) { + if (!card.isLocked()) { + switch (x) { + case "morale": + case "horn": + case "mardroeme": + case "lock": + case "curse": + case "toussaint_wine": + this.effects[x] += activate ? 1 : -1; + break; + case "shield": + case "shield_c": + case "shield_r": + case "shield_s": + if (activate) + Promise.all(this.cards.filter(c => c.isUnit()).map(c => c.animate("shield"))); + this.effects["shield"] += activate ? 1 : -1; + break; + case "bond": + if (!this.effects.bond[card.target]) + this.effects.bond[card.target] = 0; + this.effects.bond[card.target] += activate ? 1 : -1; + break; + } + } + } + } + + // Activates weather effect and visuals + addOverlay(overlay) { + var som = overlay == "fog" || overlay == "rain" ? overlay : overlay == "frost" ? "cold" : ""; + if (som != "") tocar(som, false); + this.effects.weather = true; + this.effects.weather_type = overlay; + this.elem_parent.getElementsByClassName("row-weather")[0].classList.add(overlay); + this.updateScore(); + } + + // Deactivates weather effect and visuals + removeOverlay(overlay) { + this.effects.weather = false; + this.effects.weather_type = ""; + this.elem_parent.getElementsByClassName("row-weather")[0].classList.remove(overlay); + this.updateScore(); + } + + // Override + resize() { + this.resizeCardContainer(10, 0.075, .00325); + } + + // Updates the row's score by summing the current power of its cards + updateScore() { + let total = 0; + for (let card of this.cards) { + total += this.cardScore(card); + } + let player = this.elem_parent.parentElement.id === "field-op" ? player_op : player_me; + player.updateTotal(total - this.total); + this.total = total; + this.elem_parent.getElementsByClassName("row-score")[0].innerHTML = this.total; + } + + // Calculates and set the card's current power + cardScore(card) { + let total = this.calcCardScore(card); + card.setPower(total); + return total; + } + + // Calculates the current power of a card affected by row affects + calcCardScore(card) { + if (card.key === "spe_decoy") + return 0; + let total = card.basePower * card.multiplier; + if (card.hero) + return total; + if (card.abilities.includes("spy") || card.abilities.includes("emissary")) + total = Math.floor(game.spyPowerMult * total); + // Inspire - changes base strength, before weather + if (card.abilities.includes("inspire") && !card.isLocked()) { + let inspires = card.holder.getAllRowCards().filter(c => !c.isLocked() && c.abilities.includes("inspire")); + if (inspires.length > 1) { + let maxBase = inspires.reduce((a, b) => a.power > b.power ? a : b); + total = maxBase.power; + } + } + if (this.effects.weather) + if (!(card.abilities.includes("fog_summoning") && this.effects.weather_type === "fog")) { + if (this.halfWeather) + total = Math.max(Math.min(1, total), Math.floor(total / 2)); // 2 special cases, if intially 1, we want to keep one, not 0 (floor(0.5)). If 0, we want to keep 0, not 1 + else + total = Math.min(1, total); + } + // Bond + if (card.abilities.includes("bond")) { + let bond = this.effects.bond[card.target]; + if (isNumber(bond) && bond > 1 && !card.isLocked()) + total *= Number(bond); + } + // Morale + total += Math.max(0, this.effects.morale + (card.abilities.includes("morale") ? -1 : 0)); + // Toussiant Wine + total += Math.max(0, 3 * this.effects.toussaint_wine); + // Witcher Schools + if (card.abilities.at(-1) && card.abilities.at(-1).startsWith("witcher_") && !card.isLocked()) { + let school = card.abilities.at(-1); + if (card.holder.effects["witchers"][school]) { + total += (card.holder.effects["witchers"][school] - 1) * 2; + } + } + // Whorshipped + if (card.abilities.includes("whorshipped") && card.holder.effects["whorshippers"] > 0 && !card.isLocked()) + total += card.holder.effects["whorshippers"] * game.whorshipBoost; + // Horn + if (this.effects.horn - (card.abilities.includes("horn") ? 1 : 0) > 0) + total *= 2; + return total; + } + + // Applies a temporary leader horn affect that is removed at the end of the round + async leaderHorn(card) { + if (this.special.containsCardByKey("spe_horn")) + return; + let horn = new Card("spe_horn", card_dict["spe_horn"], card.holder); + await this.addCard(horn); + game.roundEnd.push(() => this.removeCard(horn)); + } + + // Applies a local scorch effect to this row + async scorch() { + if (this.total >= 10 && !this.isShielded() && !game.scorchCancelled) + await Promise.all(this.maxUnits().map(async c => { + await c.animate("scorch", true, false); + await board.toGrave(c, this); + })); + } + + // Removes all cards and effects from this row + clear() { + this.special.cards.filter(c => !c.noRemove).forEach(c => board.toGrave(c, this, true)); + this.cards.filter(c => !c.noRemove).forEach(c => board.toGrave(c, this, true)); + } + + // Returns all regular unit cards with the heighest power + maxUnits() { + let max = []; + for (let i = 0; i < this.cards.length; ++i) { + let card = this.cards[i]; + if (!card.isUnit() || card.isImmortal()) + continue; + if (!max[0] || max[0].power < card.power) + max = [card]; + else if (max[0].power === card.power) + max.push(card); + } + return max; + } + + minUnits() { + let min = []; + for (let i = 0; i < this.cards.length; ++i) { + let card = this.cards[i]; + if (!card.isUnit() || card.isImmortal()) + continue; + if (!min[0] || min[0].power > card.power) + min = [card]; + else if (min[0].power === card.power) + min.push(card); + } + return min; + } + + // Override + reset() { + super.reset(); + this.special.reset(); + this.total = 0; + this.effects = { + weather: false, + bond: {}, + morale: 0, + horn: 0, + mardroeme: 0, + shield: 0, + lock: 0, + curse: 0, + toussaint_wine: 0, + ambush: false + }; + } + + // Indicates whether or not a shield is protecting that row from abilities (does not protect from weather effects though) + isShielded() { + return (this.effects.shield > 0); + } + + // True if at least 1 unit and total of power >= 10 + canBeScorched() { + if (game.scorchCancelled) + return false; + return (this.cards.reduce((a, c) => a + c.power, 0) >= 10) && (this.cards.filter(c => c.isUnit()).length > 0); + } + + // Return the index of the current row in the list of rows on the board + getRowIndex() { + for (let i = 0; i < board.row.length; i++) { + if (board.row[i] === this) + return i; + } + return -1; + } + + // Returns the opposite Row object - the one on the opponent's side of the field + getOppositeRow() { + let index = 5 - this.getRowIndex(); + if (index >= 0 && index < board.row.length) + return board.row[index] + return null; + } + + // Debug/cheat - Invokes any given card to the row + invokeCard(key) { + let player = this.elem_parent.parentElement.id === "field-op" ? player_op : player_me; + this.addCard(new Card(key, card_dict[key], player), true) + } +} + +// Handles how weather effects are added and removed +class Weather extends CardContainer { + constructor(elem) { + super(document.getElementById("weather")); + this.types = { + rain: { + name: "rain", + count: 0, + rows: [] + }, + fog: { + name: "fog", + count: 0, + rows: [] + }, + frost: { + name: "frost", + count: 0, + rows: [] + } + } + let i = 0; + for (let key of Object.keys(this.types)) + this.types[key].rows = [board.row[i], board.row[5 - i++]]; + + this.elem.addEventListener("click", () => ui.selectRow(this), false); + } + + // Adds a card if unique and clears all weather if 'clear weather' card added + async addCard(card, withEffects = true) { + super.addCard(card); + card.elem.classList.add("noclick"); + if (!withEffects) + return; + // Run possible actions + if (withEffects && !card.isLocked()) { + for (let x of card.placed) + await x(card, this); + } + if (card.key === "spe_clear") { + // TODO Sunlight animation + tocar("clear", false); + await sleep(500); + this.clearWeather(); + } else { + this.changeWeather(card, x => ++this.types[x].count === 1, (r, t) => r.addOverlay(t.name)); + for (let i = this.cards.length - 2; i >= 0; --i) { + if (card.abilities.at(-1) === this.cards[i].abilities.at(-1)) { + await sleep(750); + await board.toGrave(card, this); + break; + } + } + } + await sleep(750); + } + + // Override + removeCard(card, withEffects = true) { + card = super.removeCard(card); + card.elem.classList.remove("noclick"); + if (withEffects) { + this.changeWeather(card, x => --this.types[x].count === 0, (r, t) => r.removeOverlay(t.name)); + // Run possible actions + if (withEffects && !card.isLocked()) { + for (let x of card.removed) { + x(card, this); + } + } + } + return card; + } + + // Checks if a card's abilities are a weather type. If the predicate is met, perfom the action + // on the type's associated rows + changeWeather(card, predicate, action) { + for (let x of card.abilities) { + if (x in this.types && predicate(x)) { + for (let r of this.types[x].rows) + action(r, this.types[x]); + } + } + } + + // Removes all weather effects and cards + async clearWeather() { + await Promise.all(this.cards.map((c, i) => this.cards[this.cards.length - i - 1]).map(c => board.toGrave(c, this))); + } + + // Override + resize() { + this.resizeCardContainer(4, 0.075, .045); + } + + // Override + reset() { + super.reset(); + Object.keys(this.types).map(t => this.types[t].count = 0); + } +} + +// +class Board { + constructor() { + this.op_score = 0; + this.me_score = 0; + this.row = []; + for (let x = 0; x < 6; ++x) { + let elem = document.getElementById((x < 3) ? "field-op" : "field-me").children[x % 3]; + this.row[x] = new Row(elem); + } + } + + // Get the opponent of this Player + opponent(player) { + return player === player_me ? player_op : player_me; + } + + // Sends and translates a card from the source to the Deck of the card's holder + async toDeck(card, source) { + tocar("discard", false); + await this.moveTo(card, "deck", source); + } + + // Sends and translates a card from the source to the Grave of the card's holder + async toGrave(card, source, turnEnd=false) { + let destroy = true; + let protectors = null; + if (card.isUnit() && source instanceof Row) { + + // Checking Protection abilities such as Comrade + protectors = card.holder.getAllRowCards().filter(c => c.abilities.includes("comrade") && c.protects); + if (protectors.length > 0) { + let choice = false; + if (!(card.holder.controller instanceof ControllerAI)) { + choice = await ui.popup("Save it [E]", () => true, "Let it die [Q]", () => false, "Do you want to save this unit?", "Comrade ability can prevent the destruction of the following card: " + card.name + " (strength: " + card.power + "). Do you want to save it?"); + if (choice) { + destroy = false; + protectors[0].protects = false; + } + + } else { + // AI saves the unit only if its value is > 5 + if (card.power > 5) { + protectors[0].protects = false; + destroy = false; + } + } + } + } + if (destroy) { + await this.moveTo(card, "grave", source); + if (game.unitDestroyed && game.unitDestroyed.length > 0 && !turnEnd) { + for (var i = 0; i < game.unitDestroyed.length; i++) { + let cb = game.unitDestroyed[i]; + if (await cb(card)) + game.unitDestroyed.splice(i, 1) + } + } + } else { + card.animate("comrade"); + await protectors[0].animate("comrade"); + } + } + + // Sends and translates a card from the source to the Hand of the card's holder + // Possible to specify a different destination + async toHand(card, source, dest = null) { + await this.moveTo(card, dest ? dest : "hand", source); + } + + // Sends and translates a card from the source to Weather + async toWeather(card, source) { + await this.moveTo(card, weather, source); + } + + // Sends and translates a card from the source to the Deck of the card's combat row + async toRow(card, source) { + let row = ["close", "agile", "agile_cr", "agile_cs", "agile_crs"].includes(card.row) ? "close" : ["ranged", "agile_rs"].includes(card.row) ? "ranged" : card.row ? card.row : "close"; + await this.moveTo(card, row, source); + } + + // Sends and translates a card from the source to a specified row name or CardContainer + async moveTo(card, dest, source = null) { + if (isString(dest)) dest = this.getRow(card, dest); + try { + cartaNaLinha(dest.elem.id, card); + } catch (err) { } + await translateTo(card, source ? source : null, dest); + if (dest instanceof Row || dest instanceof Weather) + await dest.addCard(source ? source.removeCard(card) : card); //Only the override in the Row/Weather classes are asynchronous + else + dest.addCard(source ? source.removeCard(card) : card); + } + + // Sends and translates a card from the source to a specified row name or CardContainer - NO EFFECTS/ABILITIES + async moveToNoEffects(card, dest, source = null) { + if (isString(dest)) dest = this.getRow(card, dest); + try { + cartaNaLinha(dest.elem.id, card); + } catch (err) { } + await translateTo(card, source ? source : null, dest); + if (dest instanceof Row || dest instanceof Weather) + await dest.addCard(source ? source.removeCard(card, false) : card, false); //Only the override in the Row/Weather classes are asynchronous + else + dest.addCard(source ? source.removeCard(card) : card); + } + + // Sends and translates a card from the source to a row name associated with the passed player + async addCardToRow(card, row_name, player, source) { + let row; + if (row_name instanceof Row) { + row = row_name; + } else { + row = this.getRow(card, row_name, player); + } + try { + cartaNaLinha(row.elem.id, card); + } catch (err) { } + await translateTo(card, source, row); + await row.addCard(card); + } + + // Returns the Card associated with the row name that the card would be sent to + getRow(card, row_name, player) { + player = player ? player : card ? card.holder : player_me; + let isMe = player === player_me; + let isSpy = (card.abilities.includes("spy") || card.abilities.includes("emissary") || card.abilities.includes("ambush")); + switch (row_name) { + case "weather": + return weather; + break; + case "close": + return this.row[isMe ^ isSpy ? 3 : 2]; + case "ranged": + return this.row[isMe ^ isSpy ? 4 : 1]; + case "siege": + return this.row[isMe ^ isSpy ? 5 : 0]; + case "grave": + return player.grave; + case "deck": + return player.deck; + case "hand": + return player.hand; + default: + console.error(card.name + " sent to incorrect row \"" + row_name + "\" by " + card.holder.name); + } + } + + // Return the list of rows possible for the given card + getAgileRows(card, player) { + switch (card.row) { + case "agile": + case "agile_cr": + return [board.getRow(card, "close", player), board.getRow(card, "ranged", player)]; + case "agile_cs": + return [board.getRow(card, "close", player), board.getRow(card, "siege", player)]; + case "agile_rs": + return [board.getRow(card, "ranged", player), board.getRow(card, "siege", player)]; + case "agile_crs": + return [board.getRow(card, "close", player), board.getRow(card, "ranged", player), board.getRow(card, "siege", player)]; + default: + return [board.getRow(card, card.row, player)]; + } + } + + // Updates which player currently is in the lead + updateLeader() { + let dif = player_me.total - player_op.total; + player_me.setWinning(dif > 0); + player_op.setWinning(dif < 0); + } + + updateScores() { + //this.row.map(r => r.cards.map(c => r.cardScore(c))); + this.row.map(r => r.updateScore()); + } +} + +function limpar() { + fileira_clicavel = null; + load_pass = load_passT; + may_pass1 = false; + may_pass2 = ""; + may_pass3 = true; + timer2 = null; + lCard = null; +} + +class Game { + constructor() { + this.endScreen = document.getElementById("end-screen"); + let buttons = this.endScreen.getElementsByTagName("button"); + this.customize_elem = buttons[0]; + this.replay_elem = buttons[1]; + this.customize_elem.addEventListener("click", () => this.returnToCustomization(), false); + this.replay_elem.addEventListener("click", () => this.restartGame(), false); + this.reset(); + this.randomOPDeck = true; + this.mode = 1; + } + + reset() { + this.firstPlayer; + this.currPlayer = null; + + this.gameStart = []; + this.roundStart = []; + this.roundEnd = []; + this.turnStart = []; + this.turnEnd = []; + this.unitDestroyed = []; + + this.roundCount = 0; + this.roundHistory = []; + this.over = false; + + this.randomRespawn = false; + this.medicCount = 1; + this.whorshipBoost = 1; + this.spyPowerMult = 1; + this.decoyCancelled = false; + this.scorchCancelled = false; + + // Also resetting some board/row properties affected during the course of a game + if (board) { + if (board.row) { + board.row.forEach(r => { + r.halfWeather = false; + }); + } + } + + weather.reset(); + board.row.forEach(r => r.reset()); + } + + // Sets up player faction abilities and psasive leader abilities + initPlayers(p1, p2) { + let l1 = ability_dict[p1.leader.abilities[0]]; + let l2 = ability_dict[p2.leader.abilities[0]]; + let special_abilities = { + meve_white_queen: false + }; + initLeader(p1, l1); + initLeader(p2, l2); + if (l1 === ability_dict["meve_white_queen"] || l2 === ability_dict["meve_white_queen"]) + special_abilities["meve_white_queen"] = true; + if (p1.deck.faction === p2.deck.faction && p1.deck.faction === "scoiatael") + return special_abilities; + initFaction(p1); + initFaction(p2); + + function initLeader(player, leader) { + if (leader.placed) + leader.placed(player.leader); + Object.keys(leader).filter(key => game[key]).map(key => game[key].push(leader[key])); + } + + function initFaction(player) { + //Only passive faction abilities + if (factions[player.deck.faction] && factions[player.deck.faction].factionAbility && !factions[player.deck.faction].activeAbility) + factions[player.deck.faction].factionAbility(player); + } + + return special_abilities; + } + + // Sets initializes player abilities, player hands and redraw + async startGame() { + ui.toggleMusic_elem.classList.remove("music-customization"); + var special_abilities = this.initPlayers(player_me, player_op); + await Promise.all([...Array(10).keys()].map(async () => { + await player_me.deck.draw(player_me.hand); + await player_op.deck.draw(player_op.hand); + })); + + await this.runEffects(this.gameStart); + if (!this.firstPlayer) + this.firstPlayer = await this.coinToss(); + if (special_abilities["meve_white_queen"]) await ui.notification("meve_white_queen", 1200); + this.initialRedraw(); + somCarta(); + } + + // Simulated coin toss to determine who starts game + async coinToss() { + this.firstPlayer = (Math.random() < 0.5) ? player_me : player_op; + await ui.notification(this.firstPlayer.tag + "-coin", 1200); + return this.firstPlayer; + } + + // Allows the player to swap out up to two cards from their iniitial hand + async initialRedraw() { + if (player_op.controller instanceof ControllerAI) { + if (player_op.leader.key === "sc_francesca_daisy") { + let cards = player_op.controller.discardOrder(player_op.leader, player_op.hand, true).splice(0, player_op.mulliganCount); + cards.forEach(c => { + board.toDeck(c, player_op.hand); + }); + } else { + for (let i = 0; i < player_op.mulliganCount; i++) + player_op.controller.redraw(); + } + } + if (player_me.controller instanceof ControllerAI) { + if (player_me.leader.key === "sc_francesca_daisy") { + let cards = player_me.controller.discardOrder(player_me.leader, player_me.hand, true).splice(0, player_me.mulliganCount); + cards.forEach(c => { + board.toDeck(c, player_me.hand); + }); + } else { + for (let i = 0; i < player_me.mulliganCount; i++) + player_me.controller.redraw(); + } + } else { + // player vs player - both have a redraw - player 1 first + if (this.mode === 3) { + if (player_me.leader.key === "sc_francesca_daisy") { + await ui.queueCarousel(player_me.hand, player_me.mulliganCount, async (c, i) => await board.toDeck(c.cards[i], c), c => true, true, false, "Player 1 - Choose " + player_me.mulliganCount +" cards to put back to deck."); + } else { + await ui.queueCarousel(player_me.hand, player_me.mulliganCount, async (c, i) => await player_me.deck.swap(c, c.removeCard(i)), c => true, true, true, "Player 1 - Choose up to " + player_me.mulliganCount +" cards to redraw."); + } + if (player_op.leader.key === "sc_francesca_daisy") { + await ui.queueCarousel(player_op.hand, player_op.mulliganCount, async (c, i) => await board.toDeck(c.cards[i], c), c => true, true, false, "Player 2 - Choose " + player_op.mulliganCount +" cards to put back to deck."); + } else { + await ui.queueCarousel(player_op.hand, player_op.mulliganCount, async (c, i) => await player_op.deck.swap(c, c.removeCard(i)), c => true, true, true, "Player 2 - Choose up to " + player_op.mulliganCount +" cards to redraw."); + } + } else { + if (player_me.leader.key === "sc_francesca_daisy") { + await ui.queueCarousel(player_me.hand, player_me.mulliganCount, async (c, i) => await board.toDeck(c.cards[i], c), c => true, true, false, "Choose " + player_me.mulliganCount +" cards to put back to deck."); + } else { + await ui.queueCarousel(player_me.hand, player_me.mulliganCount, async (c, i) => await player_me.deck.swap(c, c.removeCard(i)), c => true, true, true, "Choose up to " + player_me.mulliganCount +" cards to redraw."); + } + } + ui.enablePlayer(false); + } + game.startRound(); + } + + // Initiates a new round of the game + async startRound(verdict = false) { + this.roundCount++; + if (verdict && verdict.winner) { + //Last round winner starts the round, verdict.winner can be null if draw + this.currPlayer = verdict.winner.opponent(); + } else { + this.currPlayer = (this.roundCount % 2 === 0) ? this.firstPlayer : this.firstPlayer.opponent(); + } + player_me.roundStartReset(); + player_op.roundStartReset(); + + await this.runEffects(this.roundStart); + + board.row.map(r => r.updateScore()); + + if (!player_me.canPlay()) + player_me.setPassed(true); + if (!player_op.canPlay()) + player_op.setPassed(true); + + if (player_op.passed && player_me.passed) + return this.endRound(); + + if (this.currPlayer.passed) + this.currPlayer = this.currPlayer.opponent(); + + await ui.notification("round-start", 1200); + if (this.currPlayer.opponent().passed) + await ui.notification(this.currPlayer.tag + "-turn", 1200); + + this.startTurn(); + } + + // Starts a new turn. Enables client interraction in client's turn. + async startTurn() { + await this.runEffects(this.turnStart); + if (!this.currPlayer.opponent().passed) { + this.currPlayer = this.currPlayer.opponent(); + await ui.notification(this.currPlayer.tag + "-turn", 1200); + } + ui.enablePlayer(this.currPlayer === player_me); + // Player vs player - hide opponent's hand + if (game.isPvP()) { + this.currPlayer.opponent().hand.hide(); + this.currPlayer.hand.show(); + } + this.currPlayer.startTurn(); + } + + // Ends the current turn and may end round. Disables client interraction in client's turn. + async endTurn(noEffects=false) { + if (this.currPlayer === player_me) + ui.enablePlayer(false); + + if (!noEffects) + await this.runEffects(this.turnEnd); + // Player might have "end turn" events which delay the actual end of the turn + if (this.currPlayer.endturn_action) { + // Call action instead of ending turn + await this.currPlayer.endturn_action(); + return; + } + if (this.currPlayer.passed) + await ui.notification(this.currPlayer.tag + "-pass", 1200); + board.updateScores(); + if (player_op.passed && player_me.passed) + this.endRound(); + else + this.startTurn(); + } + + // Ends the round and may end the game. Determines final scores and the round winner. + async endRound() { + limpar(); + + // Clean and update scores + board.row.forEach(r => { + r.cards.forEach(c => { + if (c.temporaryPower) + c.basePower = c.originalBasePower; + }); + r.updateScore(); + }); + board.updateScores(); + let dif = player_me.total - player_op.total; + if (dif === 0) { + let nilf_me = player_me.deck.faction === "nilfgaard", + nilf_op = player_op.deck.faction === "nilfgaard"; + dif = nilf_me ^ nilf_op ? nilf_me ? 1 : -1 : 0; + } + let winner = dif > 0 ? player_me : dif < 0 ? player_op : null; + let verdict = { + winner: winner, + score_me: player_me.total, + score_op: player_op.total + } + this.roundHistory.push(verdict); + + await this.runEffects(this.roundEnd); + + player_me.endRound(dif > 0); + player_op.endRound(dif < 0); + if (player_me.health === 0 || player_op.health === 0) + this.over = true; + + weather.clearWeather(); + // In case some cards stay on the board, we want to reset their power + board.row.forEach(row => { + row.clear(); + row.cards.forEach(c => { + c.power = c.basePower; + }); + }); + + if (dif > 0) { + await ui.notification("win-round", 1200); + } else if (dif < 0) { + if (nilfgaard_wins_draws) { + nilfgaard_wins_draws = false; + await ui.notification("nilfgaard-wins-draws", 1200); + } + await ui.notification("lose-round", 1200); + } else + await ui.notification("draw-round", 1200); + + if (player_me.health === 0 || player_op.health === 0) + this.endGame(); + else + this.startRound(verdict); + } + + // Sets up and displays the end-game screen + async endGame() { + this.over = true; + let endScreen = document.getElementById("end-screen"); + let rows = endScreen.getElementsByTagName("tr"); + rows[1].children[0].innerHTML = player_me.name; + rows[2].children[0].innerHTML = player_op.name; + + for (let i = 1; i < 4; ++i) { + let round = this.roundHistory[i - 1]; + rows[1].children[i].innerHTML = round ? round.score_me : 0; + rows[1].children[i].style.color = round && round.winner === player_me ? "goldenrod" : ""; + + rows[2].children[i].innerHTML = round ? round.score_op : 0; + rows[2].children[i].style.color = round && round.winner === player_op ? "goldenrod" : ""; + } + + endScreen.children[0].className = ""; + if (player_op.health <= 0 && player_me.health <= 0) { + tocar(""); + endScreen.getElementsByTagName("p")[0].classList.remove("hide"); + endScreen.children[0].classList.add("end-draw"); + } else if (player_op.health === 0) { + tocar("game_win", true); + endScreen.children[0].classList.add("end-win"); + } else { + tocar("game_lose", true); + endScreen.children[0].classList.add("end-lose"); + } + + fadeIn(endScreen, 300); + ui.enablePlayer(true); + } + + // Returns the client to the deck customization screen + returnToCustomization() { + iniciarMusica(); + this.reset(); + player_me.reset(); + player_op.reset(); + ui.toggleMusic_elem.classList.add("music-customization"); + this.endScreen.classList.add("hide"); + document.getElementById("deck-customization").classList.remove("hide"); + } + + // Restarts the last game with the same decks + restartGame() { + iniciarMusica(); + limpar(); + this.reset(); + player_me.reset(); + player_op.reset(); + this.endScreen.classList.add("hide"); + this.startGame(); + } + + // Executes effects in list. If effect returns true, effect is removed. + async runEffects(effects) { + for (let i = effects.length - 1; i >= 0; --i) { + let effect = effects[i]; + if (await effect()) + effects.splice(i, 1) + } + } + + isPvP() { + return (this.mode === 3); + } + +} + +// Contians information and behavior of a Card +class Card { + + constructor(key, card_data, player) { + if (!card_data) { + console.log("Invalid card data for: " + key); + } + this.id; + if (card_data.id) + this.id = Number(card_data.id); + this.key = key; + this.name = card_data.name; + this.basePower = this.power = Number(card_data.strength); + this.faction = card_data.deck; + // To clean the field in case it is a faction specific weather/special card + if (this.faction.startsWith("weather") || this.faction.startsWith("special")) { + this.faction = this.faction.split(" ")[0]; + } + this.abilities = (card_data.ability === "") ? [] : card_data.ability.split(" "); + this.row = (this.faction === "weather") ? this.faction : card_data.row; + this.filename = card_data.filename; + this.placed = []; + this.removed = []; + this.activated = []; + this.holder = player; + this.locked = false; + this.decoyTarget = false; + this.target = ""; + this.currentLocation = board; // By default, updated later + this.temporaryPower = false; + this.multiplier = 1; + if ("target" in card_data) { + this.target = card_data.target; + } + this.quote = ""; + if ("quote" in card_data) { + this.quote = card_data.quote; + } + this.meta = []; + if ("meta" in card_data) { + if (Array.isArray(card_data.meta)) { + this.meta = card_data.meta; + } else { + this.meta = card_data.meta.split(" "); + } + } + + this.hero = false; + if (this.abilities.length > 0) { + if (this.abilities[0] === "hero") { + this.hero = true; + this.abilities.splice(0, 1); + } + for (let x of this.abilities) { + let ab = ability_dict[x]; + if ("placed" in ab) this.placed.push(ab.placed); + if ("removed" in ab) this.removed.push(ab.removed); + if ("activated" in ab) this.activated.push(ab.activated); + } + } + + if (this.row === "leader") + this.desc_name = "Leader Ability"; + else if (this.abilities.length > 0) { + this.desc_name = ability_dict[this.abilities[this.abilities.length - 1]].name; + if (this.abilities.length > 1) + this.desc_name += " / " + ability_dict[this.abilities[this.abilities.length - 2]].name; + } else if (this.row === "agile" || this.row === "agile_cr") + this.desc_name = "Agile Close / Ranged"; + else if (this.row === "agile_cs") + this.desc_name = "Agile Close / Siege"; + else if (this.row === "agile_rs") + this.desc_name = "Agile Ranged / Siege"; + else if (this.row === "agile_crs") + this.desc_name = "Agile Close / Ranged / Siege"; + else if (this.hero) + this.desc_name = "Hero"; + else + this.desc_name = ""; + + this.desc = this.row.includes("agile") ? "

Agile: " + ability_dict[this.row].description + "

" : ""; + for (let i = this.abilities.length - 1; i >= 0; --i) { + let abi_name = (ability_dict[this.abilities[i]].name ? ability_dict[this.abilities[i]].name : "Leader Ability"); + let faction_abi_desc = "description_" + this.faction; + if (ability_dict[this.abilities[i]][faction_abi_desc]) { + // If there is a faction specific description/behaviour + this.desc += "

" + abi_name + " (" + factions[this.faction].name + "): " + ability_dict[this.abilities[i]][faction_abi_desc] + "

"; + } else { + this.desc += "

" + abi_name + ": " + ability_dict[this.abilities[i]].description + "

"; + } + + } + // If Summon Avenger or Invoke card, give information about the card being summoned + if (this.abilities.includes("avenger") && this.target) { + let target = card_dict[this.target]; + this.desc += "

Summons " + target["name"] + " with strength " + target["strength"]; + if (target["ability"].length > 0) + this.desc += " and abilities " + target["ability"].split(" ").map(a => ability_dict[a]["name"]).join(" / "); + this.desc += "

"; + } else if (this.abilities.includes("muster") && this.target) { + let units = Object.keys(card_dict).filter(cid => card_dict[cid].target === this.target).map(cid => card_dict[cid]); + let units_summary = {}; + units.forEach(function (u) { + let key = "" + u.name + " (str: " + u.strength + ")"; + if (!(key in units_summary)) + units_summary[key] = 0; + units_summary[key] = units_summary[key] + 1; + }); + this.desc += "

Summons " + Object.keys(units_summary).map(t => units_summary[t] + " * " + t).join(", "); + + } else if (this.abilities.includes("invoke") && this.target) { + let target = Object.keys(card_dict).filter(cid => card_dict[cid].target === this.target && cid !== this.key).map(cid => card_dict[cid]); + if (target.length > 0) { + target = target[0]; + this.desc += "

Invokes " + target["name"] + " with strength " + target["strength"]; + if (target["ability"].length > 0) + this.desc += " and abilities " + target["ability"].split(" ").map(a => ability_dict[a]["name"]).join(" / "); + this.desc += "

"; + } + } else if ((this.abilities.includes("berserker") || this.abilities.includes("monster_toussaint")) && this.target) { + let target = card_dict[this.target]; + this.desc += "

Turns into " + target["name"] + " with strength " + target["strength"]; + if (target["ability"].length > 0) + this.desc += " and abilities " + target["ability"].split(" ").map(a => ability_dict[a]["name"]).join(" / "); + this.desc += "

"; + } + if (this.hero) + this.desc += "

Hero: " + ability_dict["hero"].description + "

"; + + this.elem = this.createCardElem(this); + } + + // Returns the identifier for this type of card + getId() { + return this.key; + } + + // Sets and displays the current power of this card + setPower(n) { + if (this.key === "spe_decoy") + return; + let elem = this.elem.children[0].children[0]; + if (n !== this.power) { + this.power = n; + elem.innerHTML = this.power; + } + elem.style.color = (n > this.basePower) ? "goldenrod" : (n < this.basePower) ? "red" : ""; + if (this.temporaryPower) + elem.style.color = "green"; + } + + // Resets the power of this card to default + resetPower() { + this.setPower(this.basePower); + this.multiplier = 1; + } + + // Automatically sends and translates this card to its apropriate row from the passed source + async autoplay(source) { + await board.toRow(this, source); + } + + // Animates an ability effect + async animate(name, bFade = true, bExpand = true) { + if (!may_pass1 && playingOnline) await sleep(600); + var guia = { + "medic": "med", + "muster": "ally", + "morale": "moral", + "bond": "moral" + } + var temSom = new Array(); + for (var x in guia) temSom[temSom.length] = x; + var literais = ["scorch", "spy", "horn", "shield", "lock", "seize", "knockback", "resilience", "curse", "immortal", "aerondight", "ambush", "necrophage", "comrade", "emissary", "invoke","monster_toussaint"]; + var som = literais.indexOf(name) > -1 ? literais[literais.indexOf(name)] : temSom.indexOf(name) > -1 ? guia[name] : ""; + if (som != "") tocar(som, false); + if (name === "scorch") { + return await this.scorch(name); + } + let anim = this.elem.children[this.elem.children.length - 1]; + anim.style.backgroundImage = iconURL("anim_" + name); + await sleep(50); + + if (bFade) fadeIn(anim, 300); + if (bExpand) anim.style.backgroundSize = "100% auto"; + await sleep(300); + + if (bExpand) anim.style.backgroundSize = "80% auto"; + await sleep(1000); + + if (bFade) fadeOut(anim, 300); + if (bExpand) anim.style.backgroundSize = "40% auto"; + await sleep(300); + + anim.style.backgroundImage = ""; + } + + // Animates the scorch effect + async scorch(name) { + let anim = this.elem.children[this.elem.children.length - 1]; + anim.style.backgroundSize = "cover"; + anim.style.backgroundImage = iconURL("anim_" + name); + await sleep(50); + + fadeIn(anim, 300); + await sleep(1300); + + fadeOut(anim, 300); + await sleep(300); + + anim.style.backgroundSize = ""; + anim.style.backgroundImage = ""; + } + + // Returns true if this is a combat card that is not a Hero + isUnit() { + return !this.hero && (this.row === "close" || this.row === "ranged" || this.row === "siege" || this.row.includes("agile")); + } + + // Returns true if card is sent to a Row's special slot + isSpecial() { + return ["spe_horn", "spe_mardroeme", "spe_sign_quen", "spe_sign_yrden", "spe_toussaint_wine", "spe_lyria_rivia_morale", "spe_wyvern_shield", "spe_mantlet", "spe_garrison", "spe_dimeritium_shackles", "spe_curse"].includes(this.key); + } + + // Compares by type then power then name + static compare(a, b) { + var dif = factionRank(a) - factionRank(b); + if (dif !== 0) + return dif; + // Muster/Bond cards + if (a.target && b.target && a.target === b.target) { + if (a.id && b.id) + return Number(a.id) - Number(b.id); + if (a.key && b.key) + return a.key.localeCompare(b.key); + } + dif = a.basePower - b.basePower; + if (dif && dif !== 0) + return dif; + + return a.name.localeCompare(b.name); + + function factionRank(c) { + return c.faction === "special" ? -2 : (c.faction === "weather") ? -1 : 0; + } + } + + getPlayableRows() { + if (this.row.includes("agile")) { + return board.getAgileRows(this, this.holder); + } else if (this.isSpecial()) { + return this.getAllRows(); + } + return [board.getRow(this, this.row, this.holder)]; + } + + // Creates an HTML element based on the card's properties + createCardElem(card) { + let elem = document.createElement("div"); + elem.style.backgroundImage = smallURL(card.faction + "_" + card.filename); + elem.classList.add("card"); + elem.addEventListener("click", () => ui.selectCard(card), false); + + if (card.row === "leader") + return elem; + + let power = document.createElement("div"); + elem.appendChild(power); + let bg; + if (card.hero) { + bg = "power_hero"; + elem.classList.add("hero"); + } else if (card.faction === "weather") { + bg = "power_" + card.abilities[0]; + } else if (card.faction === "special") { + let str = card.abilities[0]; + if (str === "shield_c" || str === "shield_r" || str === "shield_s") + str = "shield"; + bg = "power_" + str; + elem.classList.add("special"); + } else { + bg = "power_normal"; + } + power.style.backgroundImage = iconURL(bg); + + let row = document.createElement("div"); + elem.appendChild(row); + if (card.row === "close" || card.row === "ranged" || card.row === "siege" || card.row.includes("agile")) { + let num = document.createElement("div"); + num.appendChild(document.createTextNode(card.basePower)); + num.classList.add("center"); + power.appendChild(num); + row.style.backgroundImage = iconURL("card_row_" + card.row); + } + + let abi = document.createElement("div"); + elem.appendChild(abi); + if (card.faction !== "special" && card.faction !== "weather" && card.abilities.length > 0) { + let str = card.abilities[card.abilities.length - 1]; + if (str === "cerys") + str = "muster"; + if (str.startsWith("avenger")) + str = "avenger"; + if (str === "scorch_c" || str == "scorch_r" || str === "scorch_s") + str = "scorch_combat"; + if (str === "shield_c" || str == "shield_r" || str === "shield_s") + str = "shield"; + abi.style.backgroundImage = iconURL("card_ability_" + str); + } else if (card.row.includes("agile")) + abi.style.backgroundImage = iconURL("card_ability_" + card.row); + + // For cards with 2 abilities + if (card.abilities.length > 1) { + let abi2 = document.createElement("div"); + abi2.classList.add("card-ability-2"); + elem.appendChild(abi2); + let str = card.abilities[card.abilities.length - 2]; + if (str === "cerys") + str = "muster"; + if (str.startsWith("avenger")) + str = "avenger"; + if (str === "scorch_c" || str == "scorch_r" || str === "scorch_s") + str = "scorch_combat"; + if (str === "shield_c" || str == "shield_r" || str === "shield_s") + str = "shield"; + abi2.style.backgroundImage = iconURL("card_ability_" + str); + } + + elem.appendChild(document.createElement("div")); // animation overlay + return elem; + } + + // Indicates whether or not the abilities of this card are locked + isLocked() { + return this.locked; + } + + isImmortal() { + return this.abilities.includes("immortal"); + } +} + +function passBreak() { + clearInterval(timer2); + load_pass = load_passT; + may_pass2 = ""; + document.getElementById("pass-button").innerHTML = original; +} + +function passStart(input) { + if (may_pass1 && may_pass2 == "") { + may_pass2 = input; + ui.passLoad(); + timer2 = setInterval(function () { + ui.passLoad(); + }, 750); + } +} + +var original = "Pass"; +var fileira_clicavel = null; +const load_passT = 3; +var cache_notif = ["op-leader"]; +var load_pass = load_passT, + may_pass1 = false, + may_pass2 = "", + may_pass3 = true, + fimU = false, + carta_c = false, + hover_row = true, + timer2, lCard; + +// Handles notifications and client interration with menus +class UI { + constructor() { + this.carousels = []; + this.notif_elem = document.getElementById("notification-bar"); + this.preview = document.getElementsByClassName("card-preview")[0]; + this.previewCard = null; + this.lastRow = null; + this.underRearrangement = false; + this.underCardPowerEdit = false; + this.arrangementMoves = 0; + if (!isMobile()) { + document.getElementById("pass-button").addEventListener("mousedown", function (e) { + if (e.button == 0) { + passStart("mouse"); + may_pass3 = false; + } else if (may_pass2 == "mouse") passBreak(); + }); + document.getElementById("pass-button").addEventListener("mouseup", () => { + if (may_pass2 == "mouse") passBreak(); + }, false); + document.getElementById("pass-button").addEventListener("mouseout", () => { + if (may_pass2 == "mouse") passBreak(); + }, false); + window.addEventListener("keydown", function (e) { + switch (e.keyCode) { + case 81: + e.preventDefault(); + try { + ui.cancel(); + } catch (err) { } + break; + case 32: + if (may_pass3) passStart("keyboard"); + break; + } + }); + window.addEventListener("keyup", function (e) { + if (e.keyCode == 32 && may_pass1) { + may_pass3 = true; + if (may_pass2 == "keyboard") passBreak(); + } + }); + } else document.getElementById("pass-button").addEventListener("click", function (e) { + if (game.isPvP()) { + game.currPlayer.passRound(); + } else { + player_me.passRound(); + } + }); + document.getElementById("click-background").addEventListener("click", () => ui.cancel(), false); + this.youtube; + this.ytActive; + this.toggleMusic_elem = document.getElementById("toggle-music"); + this.toggleMusic_elem.classList.add("fade"); + this.toggleMusic_elem.addEventListener("click", () => this.toggleMusic(), false); + document.getElementById("arrangementWindow-button").addEventListener("click", () => { + this.updateArrangementCounter(0); + this.underRearrangement = false; + game.currPlayer.endTurn(); + + }, false); + + this.helper = new HelperBox(); + } + + passLoad() { + load_pass--; + if (load_pass == -1) { + document.getElementById("pass-button").innerHTML = original; + load_pass = load_passT; + if (game.isPvP()) { + game.currPlayer.passRound(); + } else { + player_me.passRound(); + } + passBreak(); + } else document.getElementById("pass-button").innerHTML = load_pass + 1; + } + + // Enables or disables client interration + enablePlayer(enable) { + // Player vs player + if (game.isPvP()) { + document.getElementsByTagName("main")[0].classList.remove("noclick"); + } else { + let main = document.getElementsByTagName("main")[0].classList; + if (enable) main.remove("noclick"); + else main.add("noclick"); + } + } + + // Initializes the youtube background music object + initYouTube() { + this.youtube = new YT.Player('youtube', { + videoId: "UE9fPWy1_o4", + playerVars: { + "autoplay": 1, + "controls": 0, + "loop": 1, + "playlist": "UE9fPWy1_o4", + "rel": 0, + "version": 3, + "modestbranding": 1 + }, + events: { + 'onStateChange': initButton + } + }); + + function initButton() { + if (ui.ytActive !== undefined) + return; + ui.ytActive = true; + ui.youtube.playVideo(); + let timer = setInterval(() => { + if (ui.youtube.getPlayerState() !== YT.PlayerState.PLAYING) + ui.youtube.playVideo(); + else { + clearInterval(timer); + ui.toggleMusic_elem.classList.remove("fade"); + } + }, 500); + } + } + + // Called when client toggles the music + toggleMusic() { + if (this.youtube.getPlayerState() !== YT.PlayerState.PLAYING) iniciarMusica(); + else { + this.youtube.pauseVideo(); + this.toggleMusic_elem.classList.add("fade"); + } + } + + // Enables or disables backgorund music + setYouTubeEnabled(enable) { + if (this.ytActive === enable) + return; + if (enable && !this.mute) + ui.youtube.playVideo(); + else + ui.youtube.pauseVideo(); + this.ytActive = enable; + } + + // Called when the player selects a selectable card + async selectCard(card) { + let row = this.lastRow; + let pCard = this.previewCard; + if (this.underRearrangement) { + this.showPreviewVisuals(card); + return; + } + if (this.underCardPowerEdit) { + if (this.previewCard == null) { + this.showPreviewVisuals(card); + ui.editCardPower(card); + } + return; + } + if (card === pCard) + return; + if (pCard === null || card.holder.hand.cards.includes(card)) { + this.setSelectable(null, false); + this.showPreview(card); + } else if (pCard.abilities.includes("decoy")) { + this.hidePreview(card); + this.enablePlayer(false); + card.decoyTarget = true; + board.toHand(card, row); + await board.moveTo(pCard, row, pCard.holder.hand); + await pCard.holder.endTurn(); + } else if (pCard.abilities.includes("alzur_maker")) { + this.hidePreview(card); + this.enablePlayer(false); + await board.toGrave(card, row); + let target = new Card(ability_dict["alzur_maker"].target, card_dict[ability_dict["alzur_maker"].target], card.holder); + //target.removed.push(() => setTimeout(() => target.holder.grave.removeCard(target), 1001)); + await board.addCardToRow(target, target.row, card.holder); + await pCard.holder.endTurn(); + } + } + + // Called when the player selects a selectable CardContainer + async selectRow(row, isSpecial = false) { + this.lastRow = row; + if (this.underRearrangement) { + if (this.previewCard !== null) { + if (row !== this.previewCard.currentLocation) { + board.moveToNoEffects(this.previewCard, row, this.previewCard.currentLocation); + this.updateArrangementCounter(this.arrangementMoves - 1); + } + this.preview.classList.add("hide"); + let holder = this.previewCard.holder; + this.previewCard = null; + this.lastRow = null; + if (this.arrangementMoves < 1) { + this.underRearrangement = false; + ui.helper.hide(); + await holder.endTurn(); + } + } + return; + } + if (this.underCardPowerEdit) + return; + if (this.previewCard === null) { + if (isSpecial) + await ui.viewCardsInContainer(row.special); + else + await ui.viewCardsInContainer(row); + return; + } + if (this.previewCard.key === "spe_decoy" || this.previewCard.abilities.includes("alzur_maker")) + return; + if (this.previewCard.abilities.includes("decoy") && row.cards.filter(c => c.isUnit()).length > 0) + return; // If a unit can be selected, we cannot select the whole row + let card = this.previewCard; + let holder = card.holder; + this.hidePreview(); + this.enablePlayer(false); + if (card.faction === "special" && card.abilities.includes("scorch")) { + this.hidePreview(); + if (game.scorchCancelled) + return; + await ability_dict["scorch"].activated(card); + } else if (card.faction === "special" && card.abilities.includes("cintra_slaughter")) { + this.hidePreview(); + await ability_dict["cintra_slaughter"].activated(card); + } else if (card.faction === "special" && card.abilities.includes("seize")) { + this.hidePreview(); + await ability_dict[card.abilities.at(-1)].activated(card); + } else if (card.faction === "special" && card.abilities.includes("knockback")) { + this.hidePreview(); + await ability_dict[card.abilities.at(-1)].activated(card, row); + } else if (card.key === "spe_decoy" || card.abilities.includes("alzur_maker")) { + return; + } else if (card.abilities.includes("decoy") && row.cards.filter(c => c.isUnit()).length > 0) { + return; // If a unit can be selected, we cannot select the whole row + } else if (card.abilities.includes("anna_henrietta_duchess")) { + this.hidePreview(card); + this.enablePlayer(false); + let horn = row.special.cards.filter(c => c.abilities.includes("horn"))[0]; + if (horn) + await board.toGrave(horn, row); + } else if (card.key === "spe_lyria_rivia_morale") { + await board.moveTo(card, row); + } else if (card.abilities.includes("meve_princess") || card.abilities.includes("carlo_varese")) { + this.hidePreview(card); + this.enablePlayer(false); + if (game.scorchCancelled) + return; + await row.scorch(); + } else if (card.abilities.includes("cyrus_hemmelfart")) { + this.hidePreview(card); + this.enablePlayer(false); + let new_card = new Card("spe_dimeritium_shackles", card_dict["spe_dimeritium_shackles"], card.holder); + await board.moveTo(new_card, row); + } else if (card.faction === "special" && card.abilities.includes("bank")) { + this.hidePreview(); + await ability_dict["bank"].activated(card); + } else if (card.faction === "special" && card.abilities.includes("skellige_fleet")) { + this.hidePreview(); + await ability_dict["skellige_fleet"].activated(card); + } else if (card.faction === "special" && card.abilities.includes("royal_decree")) { + this.hidePreview(); + await ability_dict["royal_decree"].activated(card); + } else { + await board.moveTo(card, row, card.holder.hand); + } + await holder.endTurn(); + } + + // Called when the client cancels out of a card-preview + cancel() { + if (!fimU) { + fimU = true; + tocar("discard", false); + lCard = null; + exibindo_lider = false; + carta_c = false; + this.hidePreview(); + } + } + + // Displays a card preview then enables and highlights potential card destinations + showPreview(card) { + fimU = false; + tocar("explaining", false); + this.showPreviewVisuals(card); + this.setSelectable(card, true); + document.getElementById("click-background").classList.remove("noclick"); + } + + // Sets up the graphics and description for a card preview + showPreviewVisuals(card) { + this.previewCard = card; + this.preview.classList.remove("hide"); + getPreviewElem(this.preview.getElementsByClassName("card-lg")[0], card) + this.preview.getElementsByClassName("card-lg")[0].addEventListener("mousedown", function () { + if (fileira_clicavel !== null && may_act_card) { + ui.selectRow(fileira_clicavel); + may_act_card = false; + fileira_clicavel = null; + } + }); + this.preview.getElementsByClassName("card-lg")[0].addEventListener("mouseup", function () { + may_act_card = true; + }); + let desc_elem = this.preview.getElementsByClassName("card-description")[0]; + this.setDescription(card, desc_elem); + } + + // Hides the card preview then disables and removes highlighting from card destinations + hidePreview() { + document.getElementById("click-background").classList.add("noclick"); + player_me.hand.cards.forEach(c => c.elem.classList.remove("noclick")); + + this.preview.classList.add("hide"); + this.setSelectable(null, false); + this.previewCard = null; + this.lastRow = null; + } + + // Sets up description window for a card + setDescription(card, desc) { + if (card.hero || card.row.includes("agile") || card.abilities.length > 0 || card.faction === "faction") { + desc.classList.remove("hide"); + let str = card.row.includes("agile") ? card.row : ""; + if (card.abilities.length) + str = card.abilities[card.abilities.length - 1]; + if (str === "cerys") + str = "muster"; + if (str.startsWith("avenger")) + str = "avenger"; + if (str === "scorch_c" || str == "scorch_r" || str === "scorch_s") + str = "scorch_combat"; + if (str === "shield_c" || str == "shield_r" || str === "shield_s") + str = "shield"; + + if (card.faction === "faction" || card.abilities.length === 0 && card.row !== "agile") + desc.children[0].style.backgroundImage = ""; + else if (card.row === "leader") + desc.children[0].style.backgroundImage = iconURL("deck_shield_" + card.faction); + else + desc.children[0].style.backgroundImage = iconURL("card_ability_" + str); + desc.children[1].innerHTML = card.desc_name; + desc.children[2].innerHTML = card.desc; + } else { + desc.classList.add("hide"); + } + } + + // Displayed a timed notification to the client + async notification(name, duration) { + var guia1 = { + "notif-nilfgaard-wins-draws": "Nilfgaard wins draws", + "notif-op-white-flame": "The opponent's leader cancel your opponent's Leader Ability", + "notif-op-leader": "Opponent uses leader", + "notif-me-first": "You will go first", + "notif-op-first": "Your opponent will go first", + "notif-me-coin": "You will go first", + "notif-op-coin": "Your opponent will go first", + "notif-round-start": "Round Start", + "notif-me-pass": "Round passed", + "notif-op-pass": "Your opponent has passed", + "notif-win-round": "You won the round!", + "notif-lose-round": "Your opponent won the round", + "notif-draw-round": "The round ended in a draw", + "notif-me-turn": "Your turn!", + "notif-op-turn": "Opponent's turn", + "notif-north": "Northern Realms faction ability triggered - North draws an additional card.", + "notif-monsters": "Monsters faction ability triggered - monsters retake one card to their hand", + "notif-scoiatael": "Opponent used the Scoia'tael faction perk to go first.", + "notif-skellige-op": "Opponent Skellige Ability Triggered!", + "notif-skellige-me": "Skellige Ability Triggered!", + "notif-witcher_universe": "Witcher Universe used its faction ability and skipped a turn", + "notif-toussaint": "Toussaint faction ability triggered - Toussaint draws an additional card.", + "notif-toussaint-decoy-cancelled": "Toussaint Leader ability used - Decoy ability cancelled for the rest of the round.", + "notif-lyria_rivia": "Lyria & Rivia ability used - Morale Boost effect applied to a row.", + "notif-meve_white_queen": "Lyria & Rivia leader allows both players to restore 2 units when using the medic ability.", + "notif-north-scorch-cancelled": "Northern Realms Leader ability used - Scorch ability cancelled for the rest of the round.", + "notif-zerrikania": "Zerrikania ability used - Unit restored from discard pile.", + "notif-redania": "Redania used its faction ability and skipped a turn", + "notif-velen": "Velen ability triggered: Player will draw a card" + } + var guia2 = { + "me-pass": "pass", + "win-round": "round_win", + "lose-round": "round_lose", + "me-turn": "turn_me", + "op-turn": "turn_op", + "op-leader": "turn_op", + "op-white-flame": "turn_op", + "nilfgaard-wins-draws": "turn_op" + } + var temSom = new Array(); + for (var x in guia2) temSom[temSom.length] = x; + var som = temSom.indexOf(name) > -1 ? guia2[name] : name == "round-start" && game.roundHistory.length == 0 ? "round1_start" : ""; + if (som != "") tocar(som, false); + this.notif_elem.children[0].id = "notif-" + name; + this.notif_elem.children[0].style.backgroundImage = name == "op-leader" ? "url(img/icons/notif_" + player_op.deck.faction + ".png)" : ""; + var caracteres = guia1[this.notif_elem.children[0].id].length; + var palavras = guia1[this.notif_elem.children[0].id].split(" ").length; + duration = parseInt(0.7454878 * Math.max(parseInt((1e3 / 17) * caracteres), parseInt((6e4 / 300) * palavras)) + 211.653152) + 1; + const fadeSpeed = 150; + fadeIn(this.notif_elem, fadeSpeed); + var ch = playingOnline && duration < 1000 & cache_notif.indexOf(name) == -1 ? 800 : 0; + cache_notif[cache_notif.length] = name; + duration += ch; + let d = new Date().getTime(); + fadeOut(this.notif_elem, fadeSpeed, duration - fadeSpeed - 50); // Removing some delay to avoid weird behaviours if the fadeOut starts late and has not ended when the next fadeIn starts + await sleep(duration); + } + + // Displays a cancellable Carousel for a single card + async viewCard(card, action) { + if (card === null) return; + if (lCard !== card.name) { + lCard = card.name; + let container = new CardContainer(); + container.cards.push(card); + await this.viewCardsInContainer(container, action); + } + } + + // Displays a cancellable Carousel for all cards in a container + async viewCardsInContainer(container, action) { + action = action ? action : function () { + return this.cancel(); + }; + await this.queueCarousel(container, 1, action, () => true, false, true); + } + + // Displays a Carousel menu of filtered container items that match the predicate. + // Suspends gameplay until the Carousel is closed. Automatically picks random card if activated for AI player + async queueCarousel(container, count, action, predicate, bSort, bQuit, title) { + if (game.currPlayer && game.currPlayer.controller instanceof ControllerAI) { + for (let i = 0; i < count; ++i) { + let cards = container.cards.reduce((a, c, i) => !predicate || predicate(c) ? a.concat([i]) : a, []); + await action(container, cards[randomInt(cards.length)]); + } + return; + } + let carousel = new Carousel(container, count, action, predicate, bSort, bQuit, title); + if (Carousel.curr === undefined || Carousel.curr === null) { + carousel.start(); + } else { + this.carousels.push(carousel); + return; + } + await sleepUntil(() => this.carousels.length === 0 && !Carousel.curr, 100); + } + + // Starts the next queued Carousel + quitCarousel() { + if (this.carousels.length > 0) { + this.carousels.shift().start(); + } + } + + // Displays a custom confirmation menu + async popup(yesName, yes, noName, no, title, description) { + let p = new Popup(yesName, yes, noName, no, title, description); + await sleepUntil(() => !Popup.curr); + return p.choice; + } + + // Displays a custom menu to select a number + async numberPopup(v, min, max, callback, title, description) { + let p = new NumberValuePopup(v, min, max, callback, title, description); + await sleepUntil(() => !NumberValuePopup.curr); + return parseInt(p.value); + } + + async startDeckSorter(cards, player, action, title, bottomAllowed = false) { + let deckSorter = new DeckSorter(cards, player, action, title, bottomAllowed); + deckSorter.start(); + await sleepUntil(() => deckSorter.isCompleted(), 100); + } + + // Enables or disables selection and highlighting of rows specific to the card + setSelectable(card, enable) { + if (!enable) { + for (let row of board.row) { + row.elem.classList.remove("row-selectable"); + row.elem.classList.remove("noclick"); + row.special.elem.classList.remove("row-selectable"); + row.special.elem.classList.remove("noclick"); + alteraClicavel(row, false); + + for (let card of row.cards) { + card.elem.classList.add("noclick"); + } + } + weather.elem.classList.remove("row-selectable"); + weather.elem.classList.remove("noclick"); + alteraClicavel(weather, false); + return; + } + if (card.faction === "weather") { + for (let row of board.row) { + row.elem.classList.add("noclick"); + row.special.elem.classList.add("noclick"); + } + weather.elem.classList.add("row-selectable"); + carta_c = true; + document.getElementById("field-op").addEventListener("click", function () { + cancelaClima(); + }); + document.getElementById("field-me").addEventListener("click", function () { + cancelaClima(); + }); + alteraClicavel(weather, true); + return; + } + + weather.elem.classList.add("noclick"); + + // Affects all board + if (card.faction === "special" && card.abilities.includes("scorch")) { + for (let r of board.row) { + if (r.isShielded() || game.scorchCancelled) { + r.elem.classList.add("noclick"); + r.special.elem.classList.add("noclick"); + } else { + r.elem.classList.add("row-selectable"); + r.special.elem.classList.add("row-selectable"); + alteraClicavel(r, true); + } + } + return; + } + // Affects only own side of board + if (card.faction === "special" && (card.abilities.includes("cintra_slaughter") || card.abilities.includes("bank") || card.abilities.includes("skellige_fleet") || card.abilities.includes("royal_decree"))) { + for (let i = 0; i < 6; i++) { + let r = board.row[i]; + if ((!game.isPvP() && i > 2) || (game.isPvP() && ((card.holder.tag === player_me.tag && i > 2) || (card.holder.tag === player_op.tag && i < 3)))) { + r.elem.classList.add("row-selectable"); + r.special.elem.classList.add("row-selectable"); + alteraClicavel(r, true); + } + } + return; + } + // Affects enemy side of the board + // Affects only opponent melee and ranged row + if (card.faction === "special" && card.abilities.includes("knockback")) { + let rows = [1, 2]; + if (game.isPvP() && card.holder.tag === player_op.tag) { + rows = [3, 4]; + } + for (i of rows) { + let r = board.row[i]; + if (!r.isShielded()) { + r.elem.classList.add("row-selectable"); + r.special.elem.classList.add("row-selectable"); + alteraClicavel(r, true); + } + } + return; + } + // Affects only opponent melee row + if (card.faction === "special" && card.abilities.includes("seize")) { + let r = board.row[2]; + if (game.isPvP() && card.holder.tag === player_op.tag) { + r = board.row[3]; + } + if (!r.isShielded()) { + r.elem.classList.add("row-selectable"); + r.special.elem.classList.add("row-selectable"); + alteraClicavel(r, true); + } + return; + } + //Affects only own rows that are available + if (card.isSpecial()) { + for (let i = 0; i < 6; i++) { + let r = board.row[i]; + //Affects OP side + if (card.abilities.includes("lock")) { + if (r.special.containsCardByKey(card.key) || r.isShielded() || (!game.isPvP() && i > 2) || + (game.isPvP() && ((card.holder.tag === player_me.tag && i > 2) || (card.holder.tag === player_op.tag && i < 3)))) { + r.elem.classList.add("noclick"); + r.special.elem.classList.add("noclick"); + } else { + r.special.elem.classList.add("row-selectable"); + fileira_clicavel = null; + } + } else if (card.abilities.includes("curse")) { + //Affects both sides + if (r.isShielded()) { + r.elem.classList.add("noclick"); + r.special.elem.classList.add("noclick"); + } else { + r.special.elem.classList.add("row-selectable"); + fileira_clicavel = null; + } + + } else if (card.abilities.includes("shield_c") || card.abilities.includes("shield_r") || card.abilities.includes("shield_s")) { + if (((card.abilities.includes("shield_c") && i == 3) || (card.abilities.includes("shield_r") && i == 4) || (card.abilities.includes("shield_s") && i == 5)) && + (!game.isPvP() || (game.isPvP() && card.holder.tag === player_me.tag))) { + r.special.elem.classList.add("row-selectable"); + fileira_clicavel = null; + } else if ((game.isPvP() && card.holder.tag === player_op.tag && ((card.abilities.includes("shield_c") && i == 2) || (card.abilities.includes("shield_r") && i == 1) || (card.abilities.includes("shield_s") && i == 0)))) { } else { + r.elem.classList.add("noclick"); + r.special.elem.classList.add("noclick"); + } + } else { + // Affects own side - Toussaint Wine does not affect siege row + if (r.special.containsCardByKey(card.key) || (!game.isPvP() && ((card.abilities.includes("toussaint_wine") && i == 5) || i < 3)) || + (game.isPvP() && ((card.holder.tag === player_me.tag && ((card.abilities.includes("toussaint_wine") && i == 5) || i < 3)) || + (card.holder.tag === player_op.tag && ((card.abilities.includes("toussaint_wine") && i == 0) || i > 2))))) { + r.elem.classList.add("noclick"); + r.special.elem.classList.add("noclick"); + } else { + r.special.elem.classList.add("row-selectable"); + fileira_clicavel = null; + } + } + + } + return; + } + + if (card.abilities.includes("decoy") || card.abilities.includes("alzur_maker")) { + for (let i = 0; i < 6; i++) { + let r = board.row[i]; + let units = r.cards.filter(c => c.isUnit()); + if ((card.key === "spe_decoy" && units.length === 0) || (card.abilities.includes("decoy") && game.decoyCancelled) || (!game.isPvP() && i < 3) || + (game.isPvP() && ((card.holder.tag === player_me.tag && i < 3) || (card.holder.tag === player_op.tag && i > 2)))) { + r.elem.classList.add("noclick"); + r.special.elem.classList.add("noclick"); + r.elem.classList.remove("card-selectable"); + } else { + // For unit cards with Decoy ability, filter by the appropriate row + if (card.abilities.includes("decoy") && card.row.length > 0) { + if (((!game.isPvP() || (game.isPvP() && card.holder.tag === player_me.tag)) && ((i === 3 && ["close", "agile", "agile_cr", "agile_cs", "agile_crs"].includes(card.row)) || (i === 4 && ["ranged", "agile", "agile_cr", "agile_rs", "agile_crs"].includes(card.row)) || (i === 5 && ["siege", "agile_cs", "agile_rs", "agile_crs"].includes(card.row)))) || + (game.isPvP() && card.holder.tag === player_op.tag && ((i === 2 && ["close", "agile", "agile_cr", "agile_cs", "agile_crs"].includes(card.row)) || (i === 1 && ["ranged", "agile", "agile_cr", "agile_rs", "agile_crs"].includes(card.row)) || (i === 0 && ["siege", "agile_cs", "agile_rs", "agile_crs"].includes(card.row))))) { + r.elem.classList.add("row-selectable"); + // Row is selectable if it contains no unit to select, in order to play the unit itself without its effect + if (units.length === 0) + r.elem.classList.remove("noclick"); + alteraClicavel(r, true); + units.forEach(c => c.elem.classList.remove("noclick")); + } else { + r.elem.classList.add("noclick"); + r.special.elem.classList.add("noclick"); + r.elem.classList.remove("card-selectable"); + } + } else { + r.elem.classList.add("row-selectable"); + alteraClicavel(r, true); + units.forEach(c => c.elem.classList.remove("noclick")); + } + + } + } + return; + } + + if (card.abilities.includes("anna_henrietta_duchess")) { + let rows = [0, 1, 2]; + if (game.isPvP() && card.holder.tag === player_op.tag) { + rows = [3, 4, 5]; + } + for (i of rows) { + let r = board.row[i]; + if (r.effects.horn > 0) { + r.elem.classList.add("row-selectable"); + alteraClicavel(r, true); + } else { + r.elem.classList.add("noclick"); + r.special.elem.classList.add("noclick"); + r.elem.classList.remove("card-selectable"); + } + } + return; + } + + // Target only enemy rows + if (card.abilities.includes("meve_princess") || card.abilities.includes("carlo_varese")) { + let rows = [0, 1, 2]; + if (game.isPvP() && card.holder.tag === player_op.tag) { + rows = [3, 4, 5]; + } + for (i of rows) { + let r = board.row[i]; + if (r.isShielded() || !r.canBeScorched()) { + r.elem.classList.add("noclick"); + r.special.elem.classList.add("noclick"); + r.elem.classList.remove("card-selectable"); + } else { + r.elem.classList.add("row-selectable"); + alteraClicavel(r, true); + } + } + return; + } + + // Play special card on any opponent row, provided it doesn't already have one + if (card.abilities.includes("cyrus_hemmelfart")) { + let rows = [0, 1, 2]; + if (game.isPvP() && card.holder.tag === player_op.tag) { + rows = [3, 4, 5]; + } + for (i of rows) { + let r = board.row[i]; + if (r.containsCardByKey("spe_dimeritium_shackles") || r.isShielded()) { + r.elem.classList.add("noclick"); + r.special.elem.classList.add("noclick"); + r.elem.classList.remove("card-selectable"); + } else { + r.elem.classList.add("row-selectable"); + alteraClicavel(r, true); + } + } + return; + } + + + + let currRows = card.row.includes("agile") ? board.getAgileRows(card, card.holder) : [board.getRow(card, card.row, card.holder)]; + for (let i = 0; i < 6; i++) { + let row = board.row[i]; + if (currRows.includes(row)) { + row.elem.classList.add("row-selectable"); + if (!card.row.includes("agile")) alteraClicavel(row, true); + else fileira_clicavel = null; + } else if (card.abilities.includes("ambush") && currRows.includes(row.getOppositeRow())) { + // Ambush cards are symetrical, they affect available rows on each side of the battlefield + row.elem.classList.add("row-selectable"); + } else { + row.elem.classList.add("noclick"); + } + } + + } + + // Make UI enter a mode where the player can re-arrange the cards on one side of the board (the one associated to the provided player) + // In this mode, when a player clicks a card, it displays the preview + // When the player clicks a row when a preview is displayed, move the card there (unless it was already there) and decrease remaining moves by one + enableBoardRearrangement(player,moves) { + if (this.underRearrangement) + return; + this.underRearrangement = true; + this.updateArrangementCounter(moves); + this.setSelectable(null, false); + let rows = (player === player_op) ? board.row.slice(0, 3) : board.row.slice(3); + player.hand.cards.forEach(c => c.elem.classList.add("noclick")); + for (let i = 0; i < 6; i++) { + let row = board.row[i]; + //Valid side of board + if (rows.includes(row) ) { + row.elem.classList.remove("noclick"); + if (row.cards.length > 0) { + alteraClicavel(row, true); + row.cards.filter(c => c.key !== "spe_decoy").forEach(c => c.elem.classList.remove("noclick")); + } + // Other side of board + } else { + row.elem.classList.add("noclick"); + row.cards.forEach(c => c.elem.classList.add("noclick")); + } + + } + ui.helper.showMessage("Select cards on the board to re-arrange."); + this.enablePlayer(true); + } + + updateArrangementCounter(cnt) { + if (cnt > 0) { + this.arrangementMoves = cnt; + document.getElementById("arrangementWindow").classList.remove("hide"); + document.getElementById("arrangementWindow-counter").innerText = cnt; + } else { + this.arrangementMoves = 0; + document.getElementById("arrangementWindow").classList.add("hide"); + } + } + + enableCardPowerEdit(player) { + if (this.underCardPowerEdit || !player.capabilities["cardEdit"] || player.capabilities["cardEdit"] < 1) + return; + this.underCardPowerEdit = true; + this.setSelectable(null, false); + let rows = (player === player_op) ? board.row.slice(0, 3) : board.row.slice(3); + player.hand.cards.forEach(c => c.elem.classList.add("noclick")); + for (let i = 0; i < 6; i++) { + let row = board.row[i]; + //Valid side of board + if (rows.includes(row)) { + row.elem.classList.remove("noclick"); + if (row.cards.length > 0) { + alteraClicavel(row, true); + row.cards.filter(c => c.hero || c.isUnit()).forEach(c => c.elem.classList.remove("noclick")); + } + // Other side of board + } else { + row.elem.classList.add("noclick"); + row.cards.forEach(c => c.elem.classList.add("noclick")); + } + } + // Prevent the end of turn while selecting cards + player.endturn_action = async () => { + player.endturn_action = null; + } + ui.helper.showMessage("Select a card on your side of the board."); + this.enablePlayer(true); + } + + async editCardPower(card) { + ui.helper.hide(); + let newValue = await this.numberPopup(card.power, 0, 999, null, "Select a new base power", "Select the new base power (before other effects) for the selected card. Currently: " + String(card.power)); + if (!card.originalBasePower) + card.originalBasePower = card.basePower; + card.basePower = newValue; + card.temporaryPower = true; + card.holder.capabilities["cardEdit"] -= 1; + this.underCardPowerEdit = false; + this.preview.classList.add("hide"); + this.previewCard = null; + card.holder.hand.cards.forEach(c => c.elem.classList.remove("noclick")); + card.holder.endTurn(true); + } +} + +var fimC = false; + +// Displays up to 5 cards for the client to cycle through and select to perform an action +// Clicking the middle card performs the action on that card "count" times +// Clicking adejacent cards shifts the menu to focus on that card +class Carousel { + constructor(container, count, action, predicate, bSort, bExit = false, title) { + if (count <= 0 || !container || !action || container.cards.length === 0) + return; + this.container = container; + this.count = count; + this.action = action ? action : () => this.cancel(); + this.predicate = predicate; + this.bSort = bSort; + this.indices = []; + this.index = 0; + this.bExit = bExit; + this.title = title; + this.cancelled = false; + this.selection = []; + + if (!Carousel.elem) { + Carousel.elem = document.getElementById("carousel"); + Carousel.elem.children[0].addEventListener("click", () => Carousel.curr.cancel(), false); + window.addEventListener("keydown", function (e) { + if (e.keyCode == 81) { + e.preventDefault(); + try { + Carousel.curr.cancel(); + } catch (err) { } + } + }); + } + this.elem = Carousel.elem; + document.getElementsByTagName("main")[0].classList.remove("noclick"); + + this.elem.children[0].classList.remove("noclick"); + this.previews = this.elem.getElementsByClassName("card-lg"); + this.desc = this.elem.getElementsByClassName("card-description")[0]; + this.title_elem = this.elem.children[2]; + } + + // Initializes the current Carousel + start() { + if (!this.elem) + return; + this.indices = this.container.cards.reduce((a, c, i) => (!this.predicate || this.predicate(c)) ? a.concat([i]) : a, []); + + if (this.indices.length <= 0) + return this.exit(); + if (this.bSort) + this.indices.sort((a, b) => Card.compare(this.container.cards[a], this.container.cards[b])); + + this.update(); + Carousel.setCurrent(this); + + if (this.title) { + this.title_elem.innerHTML = this.title; + this.title_elem.classList.remove("hide"); + } else { + this.title_elem.classList.add("hide"); + } + + this.elem.classList.remove("hide"); + ui.enablePlayer(true); + tocar("explaining", false); + fimC = false; + setTimeout(function () { + var label = document.getElementById("carousel_label"); + if (label.innerText.indexOf("redraw") > -1 && label.className.indexOf("hide") == -1) tocar("game_start", false); + }, 50); + } + + // Called by the client to cycle cards displayed by n + shift(event, n) { + try { + (event || window.event).stopPropagation(); + } catch (err) { } + tocar("card", false); + this.index = Math.max(0, Math.min(this.indices.length - 1, this.index + n)); + this.update(); + } + + // Called by client to perform action on the middle card in focus + async select(event) { + try { + (event || window.event).stopPropagation(); + } catch (err) { } + // In case of multiple selections, we only do action if not already selected + if (this.selection.indexOf(this.indices[this.index]) < 0) { + var label = document.getElementById("carousel_label"); + if (label.innerText.indexOf("redraw") > -1 && label.className.indexOf("hide") == -1) { + tocar("redraw", false); + } else { + this.selection.push(this.indices[this.index]); + } + --this.count; + if (this.isLastSelection()) + this.elem.classList.add("hide"); + if (this.count <= 0) + ui.enablePlayer(false); + // For redraw, we run the action right away + if (label.innerText.indexOf("redraw") > -1 && label.className.indexOf("hide") == -1) + await this.action(this.container, this.indices[this.index]); + if (this.isLastSelection() && !this.cancelled) { + this.exit(); + this.selection.map(async s => await this.action(this.container, s)); + this.selection = []; + return; + } + + } else { + // If already selected, remove from selection + this.selection.splice(this.selection.indexOf(this.indices[this.index]), 1); + this.count++; + } + this.update(); + } + + // Called by client to exit out of the current Carousel if allowed. Enables player interraction. + cancel() { + if (!fimC) { + fimC = true; + tocar("discard", false); + lCard = null; + exibindo_lider = false; + if (this.bExit) { + this.cancelled = true; + this.exit(); + } + ui.enablePlayer(true); + } + } + + // Returns true if there are no more cards to view or select + isLastSelection() { + return this.count <= 0 || this.indices.length === 0; + } + + // Updates the visuals of the current selection of cards + update() { + this.indices = this.container.cards.reduce((a, c, i) => (!this.predicate || this.predicate(c)) ? a.concat([i]) : a, []); + if (this.index >= this.indices.length) + this.index = this.indices.length - 1; + for (let i = 0; i < this.previews.length; i++) { + let curr = this.index - 2 + i; + if (curr >= 0 && curr < this.indices.length) { + let card = this.container.cards[this.indices[curr]]; + getPreviewElem(this.previews[i], card); + this.previews[i].classList.remove("hide"); + this.previews[i].classList.remove("noclick"); + if (this.selection.indexOf(this.indices[curr]) >= 0) + this.previews[i].classList.add("selection"); + else + this.previews[i].classList.remove("selection"); + } else { + this.previews[i].style.backgroundImage = ""; + this.previews[i].classList.add("hide"); + this.previews[i].classList.add("noclick"); + this.previews[i].classList.remove("selection"); + } + } + ui.setDescription(this.container.cards[this.indices[this.index]], this.desc); + } + + // Clears and quits the current carousel + exit() { + for (let x of this.previews) { + x.style.backgroundImage = ""; + x.classList.remove("selection"); + } + this.elem.classList.add("hide"); + Carousel.clearCurrent(); + ui.quitCarousel(); + } + + // Statically sets the current carousel + static setCurrent(curr) { + this.curr = curr; + } + + // Statically clears the current carousel + static clearCurrent() { + this.curr = null; + } +} + +// Custom confirmation windows +class Popup { + constructor(yesName, yes, noName, no, header, description) { + this.yes = yes ? yes : () => { }; + this.no = no ? no : () => { }; + this.choice = false; + + this.elem = document.getElementById("popup"); + let main = this.elem.children[0]; + main.children[0].innerHTML = header ? header : ""; + main.children[1].innerHTML = description ? description : ""; + main.children[2].children[0].innerHTML = (yesName) ? yesName : "Yes"; + main.children[2].children[1].innerHTML = (noName) ? noName : "No"; + + this.elem.classList.remove("hide"); + Popup.setCurrent(this); + ui.enablePlayer(true); + } + + // Sets this as the current popup window + static setCurrent(curr) { + this.curr = curr; + } + + // Unsets this as the current popup window + static clearCurrent() { + this.curr = null; + } + + // Called when client selects the positive aciton + selectYes() { + this.clear(); + this.choice = true; + this.yes(this); + return true; + } + + // Called when client selects the negative option + selectNo() { + this.clear(); + this.choice = false; + this.no(this); + return false; + } + + // Clears the popup and diables player interraction + clear() { + ui.enablePlayer(false); + this.elem.classList.add("hide"); + Popup.clearCurrent(); + } +} + +class NumberValuePopup { + constructor(value, min=0, max=999, callback, header, description) { + this.callback = callback ? callback : () => { }; + this.choice = false; + + this.elem = document.getElementById("number-popup"); + let main = this.elem.children[0]; + main.children[0].innerHTML = header ? header : ""; + main.children[1].innerHTML = description ? description : ""; + this.numberElem = document.getElementById("number-popup-value"); + main.children[2].children[1].innerHTML = "Done"; + + this.numberElem.setAttribute("value", value); + this.numberElem.value = value; + this.numberElem.setAttribute("min", min); + this.numberElem.setAttribute("max", max); + + this.elem.classList.remove("hide"); + NumberValuePopup.setCurrent(this); + ui.enablePlayer(true); + } + + // Sets this as the current popup window + static setCurrent(curr) { + this.curr = curr; + } + + // Unsets this as the current popup window + static clearCurrent() { + this.curr = null; + } + + // Called when client confirms value + done() { + this.value = this.numberElem.value; + if (!isNaN(this.value) && this.value != "") { + this.clear(); + this.callback(this); + return true; + } + + return false; + } + + // Clears the popup and diables player interraction + clear() { + ui.enablePlayer(false); + this.elem.classList.add("hide"); + NumberValuePopup.clearCurrent(); + } +} + +class HelperBox { + constructor() { + this.text = ""; + + this.elem = document.getElementById("helper-box"); + + document.getElementById("help-box-close").addEventListener("click", () => this.hide(), false); + HelperBox.setCurrent(this); + } + + // Sets this as the current helper box + static setCurrent(curr) { + this.curr = curr; + } + + // Unsets this as the current helper box + static clearCurrent() { + this.curr = null; + } + + showMessage(text, timer=0) { + this.text = text; + document.getElementById("helper-box-message").innerText = text; + this.elem.classList.remove("hide"); + if (timer > 0) { + timer = Math.min(timer, 30); + var opacity = 1; // Initial opacity + var h = this; + setTimeout(function () { + // Fading out - 1s + var interval = setInterval(function () { + if (opacity > 0) { + opacity -= 0.1; + h.elem.style.opacity = opacity; + } else { + clearInterval(interval); // Stop the interval when opacity reaches 0 + h.hide(); // Hide the element + h.elem.style.opacity = 1; + } + }, 100); + },timer*1000); + + } + } + + hide() { + this.elem.classList.add("hide"); + } +} + +var carta_selecionada = null; + +// Screen used to customize, import and export deck contents +class DeckMaker { + constructor() { + this.elem = document.getElementById("deck-customization"); + this.bank_elem = document.getElementById("card-bank"); + this.deck_elem = document.getElementById("card-deck"); + this.leader_elem = document.getElementById("card-leader"); + this.leader_elem.children[1].addEventListener("click", () => this.selectLeader(), false); + this.leader_elem.children[1].addEventListener("mouseover", function () { + tocar("card", false); + this.style.boxShadow = "0 0 1.5vw #6d5210" + }); + this.leader_elem.children[1].addEventListener("mouseout", function () { + this.style.boxShadow = "0 0 0 #6d5210" + }); + + this.faction = "realms"; + this.setFaction(this.faction, true); + + let start_deck = JSON.parse(JSON.stringify(premade_deck[0])); + start_deck.cards = start_deck.cards.map(c => ({ + index: c[0], + count: c[1] + })); + this.me_deck_title = start_deck.title; + this.setLeader(start_deck.leader); + this.makeBank(this.faction, start_deck.cards); + + this.start_op_deck; + this.me_deck_index = 0; + this.op_deck_index = 0; + + this.change_elem = document.getElementById("change-faction"); + this.change_elem.addEventListener("click", () => this.selectFaction(), false); + + document.getElementById("select-deck").addEventListener("click", () => this.selectDeck(), false); + document.getElementById("select-op-deck").addEventListener("click", () => this.selectOPDeck(), false); + document.getElementById("download-deck").addEventListener("click", () => this.downloadDeck(), false); + document.getElementById("add-file").addEventListener("change", () => this.uploadDeck(), false); + document.getElementById("start-game").addEventListener("click", () => this.startNewGame(1), false); + document.getElementById("start-ai-game").addEventListener("click", () => this.startNewGame(2), false); + document.getElementById("start-pvp-game").addEventListener("click", () => this.startNewGame(3), false); + window.addEventListener("keydown", function (e) { + if (document.getElementById("deck-customization").className.indexOf("hide") == -1) { + switch (e.keyCode) { + case 69: + try { + Carousel.curr.cancel(); + } catch (err) { } + if (isLoaded && iniciou) dm.startNewGame(); + break; + case 88: + dm.selectLeader(); + break; + } + } + }); + somCarta(); + + this.update(); + } + + // Called when client selects a deck faction. Clears previous cards and makes valid cards available. + async setFaction(faction_name, silent) { + if (!silent && this.faction === faction_name) + return false; + if (!silent) { + tocar("warning", false); + if (!confirm("Changing factions will clear the current deck. Continue? ")) { + tocar("warning", false); + return false; + } + } + this.elem.getElementsByTagName("h1")[0].innerHTML = factions[faction_name].name; + this.elem.getElementsByTagName("h1")[0].style.backgroundImage = iconURL("deck_shield_" + faction_name); + document.getElementById("faction-description").innerHTML = factions[faction_name].description; + + this.leaders = + Object.keys(card_dict).map(cid => ({ + card: card_dict[cid], + index: cid + })) + .filter(c => c.card.deck === faction_name && c.card.row === "leader"); + if (!this.leader || this.faction !== faction_name) { + this.leader = this.leaders[0]; + getPreviewElem(this.leader_elem.children[1], this.leader.card) + } + this.faction = faction_name; + setTimeout(function () { + somCarta(); + }, 300); + return true; + } + + // Called when client selects a leader for their deck + setLeader(index) { + this.leader = this.leaders.filter(l => l.index == index)[0]; + getPreviewElem(this.leader_elem.children[1], this.leader.card) + } + + // Constructs a bank of cards that can be used by the faction's deck. + // If a deck is provided, will not add cards to bank that are already in the deck. + makeBank(faction, deck) { + this.clear(); + let cards = Object.keys(card_dict).map(cid => ({ + card: card_dict[cid], + index: cid + })).filter( + p => (([faction, "neutral", "weather", "special"].includes(p.card.deck) || + (["weather", "special"].includes(p.card.deck.split(" ")[0]) && p.card.deck.split(" ").includes(faction))) && + p.card.row !== "leader" && !factions[faction].unavailableSpecials.includes(p.index))); + + cards.sort(function (id1, id2) { + let a = card_dict[id1.index], + b = card_dict[id2.index]; + let c1 = { + name: a.name, + basePower: -a.strength, + faction: a.deck.split(" ")[0] // Cleaning for faction specific special/weather cards + }; + let c2 = { + name: b.name, + basePower: -b.strength, + faction: b.deck.split(" ")[0] // Cleaning for faction specific special/weather cards + }; + return Card.compare(c1, c2); + }); + + + let deckMap = {}; + if (deck) { + for (let i of Object.keys(deck)) deckMap[deck[i].index] = deck[i].count; + } + cards.forEach(p => { + let count = deckMap[p.index] !== undefined ? Number(deckMap[p.index]) : 0; + this.makePreview(p.index, Number.parseInt(p.card.count) - count, this.bank_elem, this.bank,); + this.makePreview(p.index, count, this.deck_elem, this.deck); + }); + } + + // Creates HTML elements for the card previews + makePreview(index, num, container_elem, cards) { + let card_data = card_dict[index]; + + let elem = document.createElement("div"); + elem.classList.add("card-lg"); + elem = getPreviewElem(elem, card_data, num); + container_elem.appendChild(elem); + + let bankID = { + index: index, + count: num, + elem: elem + }; + let isBank = cards === this.bank; + cards.push(bankID); + let cardIndex = cards.length - 1; + elem.addEventListener("dblclick", () => this.select(cardIndex, isBank), false); + elem.addEventListener("mouseover", () => { + var aux = this; + carta_selecionada = function () { + aux.select(cardIndex, isBank); + } + }, false); + window.addEventListener("keydown", function (e) { + if (e.keyCode == 13 && carta_selecionada !== null) carta_selecionada(); + }); + // Right click allows to see more details about the selected card + elem.addEventListener('contextmenu', async (e) => { + e.preventDefault(); + let container = new CardContainer(); + container.cards = [new Card(index, card_data, null)]; + try { + Carousel.curr.cancel(); + } catch (err) { } + await ui.viewCardsInContainer(container); + }, false); + + return bankID; + } + + // Updates the card preview elements when any changes are made to the deck + update() { + for (let x of this.bank) { + if (x.count) + x.elem.classList.remove("hide"); + else + x.elem.classList.add("hide"); + } + let total = 0, + units = 0, + special = 0, + strength = 0, + hero = 0; + for (let x of this.deck) { + let card_data = card_dict[x.index]; + if (x.count) + x.elem.classList.remove("hide"); + else + x.elem.classList.add("hide"); + total += x.count; + if (card_data.deck.startsWith("special") || card_data.deck.startsWith("weather")) { + special += x.count; + continue; + } + units += x.count; + strength += card_data.strength * x.count; + if (card_data.ability.split(" ").includes("hero")) + hero += x.count; + } + this.stats = { + total: total, + units: units, + special: special, + strength: strength, + hero: hero + }; + this.updateStats(); + } + + // Updates and displays the statistics describing the cards currently in the deck + updateStats() { + let stats = document.getElementById("deck-stats"); + stats.children[1].innerHTML = this.stats.total; + stats.children[3].innerHTML = this.stats.units + (this.stats.units < 22 ? "/22" : ""); + stats.children[5].innerHTML = this.stats.special + "/10"; + stats.children[7].innerHTML = this.stats.strength; + stats.children[9].innerHTML = this.stats.hero; + + stats.children[3].style.color = this.stats.units < 22 ? "red" : ""; + stats.children[5].style.color = (this.stats.special > 10) ? "red" : ""; + } + + // Opens a Carousel to allow the client to select a leader for their deck + selectLeader() { + let container = new CardContainer(); + container.cards = this.leaders.map(c => { + let card = new Card(c.index, c.card, player_me); + card.data = c; + return card; + }); + + let index = this.leaders.indexOf(this.leader); + ui.queueCarousel(container, 1, (c, i) => { + let data = c.cards[i].data; + this.leader = data; + getPreviewElem(this.leader_elem.children[1], data.card); + }, () => true, false, true); + Carousel.curr.index = index; + Carousel.curr.update(); + } + + // Opens a Carousel to allow the client to select a faction for their deck + selectFaction() { + let container = new CardContainer(); + container.cards = Object.keys(factions).map(f => { + return { + abilities: [f], + filename: f, + desc_name: factions[f].name, + desc: factions[f].description, + faction: "faction" + }; + }); + let index = container.cards.reduce((a, c, i) => c.filename === this.faction ? i : a, 0); + ui.queueCarousel(container, 1, (c, i) => { + let change = this.setFaction(c.cards[i].filename); + if (!change) + return; + this.makeBank(c.cards[i].filename); + this.update(); + }, () => true, false, true); + Carousel.curr.index = index; + Carousel.curr.update(); + } + + // Called when client selects s a preview card. Moves it from bank to deck or vice-versa then updates; + select(index, isBank) { + carta_selecionada = null; + if (isBank) { + tocar("menu_buy", false); + this.add(index, this.deck); + this.remove(index, this.bank); + } else { + tocar("discard", false); + this.add(index, this.bank); + this.remove(index, this.deck); + } + this.update(); + } + + // Adds a card to container (Bank or deck) + add(index, cards) { + let id = cards[index]; + id.elem.getElementsByClassName("card-count")[0].innerHTML = ++id.count; + id.elem.getElementsByClassName("card-count")[0].classList.remove("hide"); + } + + // Removes a card from container (bank or deck) + remove(index, cards) { + let id = cards[index]; + id.elem.getElementsByClassName("card-count")[0].innerHTML = --id.count; + if (id.count === 0) + id.elem.getElementsByClassName("card-count")[0].classList.add("hide"); + } + + // Removes all elements in the bank and deck + clear() { + while (this.bank_elem.firstChild) + this.bank_elem.removeChild(this.bank_elem.firstChild); + while (this.deck_elem.firstChild) + this.deck_elem.removeChild(this.deck_elem.firstChild); + this.bank = []; + this.deck = []; + this.stats = {}; + } + + // Verifies current deck, creates the players and their decks, then starts a new game + // Modes: + // 1 - player VS AI + // 2 - AI vs AI + // 3 - player VS player (hotseat) + startNewGame(mode = 1) { + game.mode = mode; + openFullscreen(); + let warning = ""; + if (this.stats.units < 22) + warning += "Your deck must have at least 22 unit cards. \n"; + if (this.stats.special > 10) + warning += "Your deck must have no more than 10 special cards. \n"; + if (warning != "") { + return aviso(warning); + } + + let me_deck = { + faction: this.faction, + leader: this.leader, + cards: this.deck.filter(x => x.count > 0), + title: this.me_deck_title + }; + + if (game.randomOPDeck || !this.start_op_deck) { + this.start_op_deck = JSON.parse(JSON.stringify(premade_deck[randomInt(Object.keys(premade_deck).length)])); + this.start_op_deck.cards = this.start_op_deck.cards.map(c => ({ + index: c[0], + count: c[1] + })); + + let leaders = Object.keys(card_dict).map(cid => { + return { + index: cid, + card: card_dict[cid] + }; + }).filter(c => c.card.row === "leader" && c.card.deck === this.start_op_deck.faction); + this.start_op_deck.leader = leaders[randomInt(leaders.length)]; + } + + if (game.mode === 1) { + player_me = new Player(0, "Player 1", me_deck, false); + player_op = new Player(1, "Player 2", this.start_op_deck, true); + } else if (game.mode === 2) { + // AI vs AI + player_me = new Player(0, "Player 1", me_deck, true); + player_op = new Player(1, "Player 2", this.start_op_deck, true); + } else { + // PVP + player_me = new Player(0, "Player 1", me_deck, false); + player_op = new Player(1, "Player 2", this.start_op_deck, false); + } + + + this.elem.classList.add("hide"); + tocar("game_opening", false); + game.startGame(); + } + + // Converts the current deck to a JSON string + deckToJSON() { + let obj = { + faction: this.faction, + leader: this.leader.index, + cards: this.deck.filter(x => x.count > 0).map(x => [x.index, x.count]) + }; + return JSON.stringify(obj); + } + + // Select a premade deck + selectDeck() { + let container = new CardContainer(); + container.cards = Object.values(premade_deck).map(d => { + let deck = d; + return { + abilities: [deck["faction"]], + name: card_dict[deck["leader"]]["name"], + row: "leader", + filename: card_dict[deck["leader"]]["filename"], + desc_name: deck["title"], + desc: "

Faction ability: " + factions[deck["faction"]]["description"] + "

Leader ability: " + ability_dict[card_dict[deck["leader"]]["ability"]].description + "

Deck description: " + deck["description"], + faction: deck["faction"] + }; + }); + let index = container.cards.reduce((a, c, i) => c.faction === this.faction ? i : a, 0); + ui.queueCarousel(container, 1, (c, i) => { + this.me_deck_index = i; + this.setFaction(c.cards[i].faction, true); + this.deckFromJSON(premade_deck[i], false); + }, () => true, false, true); + Carousel.curr.index = this.me_deck_index; + Carousel.curr.update(); + } + + selectOPDeck() { + let container = new CardContainer(); + // Adding first the option to select a random deck + container.cards = [{ + abilities: [], + name: "Random deck", + row: "faction", + filename: "random", + desc_name: "Random deck", + desc: "A random deck from the pool that will change every game.", + faction: "faction" + }]; + container.cards = container.cards.concat(Object.values(premade_deck).map(d => { + let deck = d; + return { + abilities: [deck["faction"]], + name: card_dict[deck["leader"]]["name"], + row: "leader", + filename: card_dict[deck["leader"]]["filename"], + desc_name: deck["title"], + desc: "

Faction ability: " + factions[deck["faction"]]["description"] + "

Leader ability: " + ability_dict[card_dict[deck["leader"]]["ability"]].description + "

Deck description: " + deck["description"], + faction: deck["faction"] + }; + })); + ui.queueCarousel(container, 1, (c, i) => { + this.op_deck_index = i; + if (i === 0) { + game.randomOPDeck = true; + document.getElementById("op-deck-name").innerHTML = "Random deck"; + } else { + this.start_op_deck = JSON.parse(JSON.stringify(premade_deck[i - 1])); + this.start_op_deck.cards = this.start_op_deck.cards.map(c => ({ + index: c[0], + count: c[1] + })); + this.start_op_deck.leader = { + index: this.start_op_deck.leader, + card: card_dict[this.start_op_deck.leader] + }; + document.getElementById("op-deck-name").innerHTML = premade_deck[i - 1]["title"]; + game.randomOPDeck = false; + } + }, () => true, false, true); + Carousel.curr.index = this.op_deck_index; + Carousel.curr.update(); + } + + // Called by the client to downlaod the current deck as a JSON file + downloadDeck() { + let json = this.deckToJSON(); + let str = "data:text/json;charset=utf-8," + encodeURIComponent(json); + let hidden_elem = document.getElementById('download-json'); + hidden_elem.href = str; + hidden_elem.download = "MyGwentDeck.json"; + hidden_elem.click(); + } + + // Called by the client to upload a JSON file representing a new deck + uploadDeck() { + let files = document.getElementById("add-file").files; + if (files.length <= 0) + return false; + let fr = new FileReader(); + fr.onload = e => { + try { + this.deckFromJSON(e.target.result, true); + } catch (e) { + aviso("Uploaded deck is not formatted correctly!"); + } + } + fr.readAsText(files.item(0)); + document.getElementById("add-file").value = ""; + openFullscreen(); + } + + // Creates a deck from a JSON file's contents and sets that as the current deck + // Notifies client with warnings if the deck is invalid + deckFromJSON(json, parse) { + let deck; + if (parse) { + try { + deck = JSON.parse(json); + } catch (e) { + aviso("Uploaded deck is not parsable!"); + return; + } + } else { + deck = JSON.parse(JSON.stringify(json)); + } + let warning = ""; + if (card_dict[deck.leader].row !== "leader") + warning += "'" + card_dict[deck.leader].name + "' is cannot be used as a leader\n"; + if (deck.faction != card_dict[deck.leader].deck) + warning += "Leader '" + card_dict[deck.leader].name + "' doesn't match deck faction '" + deck.faction + "'.\n"; + + let cards = deck.cards.filter(c => { + let card = card_dict[c[0]]; + if (!card) { + warning += "ID " + c[0] + " does not correspond to a card.\n"; + return false + } + if (!([deck.faction, "neutral", "special", "weather"].includes(card.deck) || + (["special", "weather"].includes(card.deck.split(" ")[0]) && card.deck.split(" ").includes(deck.faction)))) { + warning += "'" + card.name + "' cannot be used in a deck of faction type '" + deck.faction + "'\n"; + return false; + } + if (card.count < c[1]) { + console.log(card); + warning += "Deck contains " + c[1] + "/" + card.count + " available " + card_dict[c[0]].name + " cards\n"; + return false; + } + return true; + }) + .map(c => ({ + index: c[0], + count: Math.min(c[1], card_dict[c[0]].count) + })); + + if (warning) { + tocar("warning", false); + if (!confirm(warning + "\n\n\Continue importing deck?")) { + tocar("warning", false); + return; + } + } + this.setFaction(deck.faction, true); + if (card_dict[deck.leader].row === "leader" && deck.faction === card_dict[deck.leader].deck) { + this.leader = this.leaders.filter(c => c.index === deck.leader)[0]; + getPreviewElem(this.leader_elem.children[1], this.leader.card); + } + this.me_deck_title = deck.title; + this.makeBank(deck.faction, cards); + this.update(); + } +} + +class DeckSorter { + constructor(cards, player, action, title, bottomAllowed = false) { + if (!player || !cards || cards.length === 0) + return; + this.cards = cards; + this.player = player; + this.bottomAllowed = bottomAllowed; + this.action = action ? action : () => this.close(); + this.title = title; + this.completed = false; + this.target_id = null; + + if (!DeckSorter.elem) { + DeckSorter.elem = document.getElementById("deck-sorter"); + } + this.elem = DeckSorter.elem; + document.getElementsByTagName("main")[0].classList.remove("noclick"); + + this.elem.children[0].classList.remove("noclick"); + this.title_elem = document.getElementById("deck-sorter-title"); + } + + // Initializes the current DeckSorter + start() { + if (!this.elem || !this.cards | this.cards.length == 0) + return; + + let bankRow = document.getElementById("drop-bank"); + let deckTop = document.getElementById("drop-deck-top"); + let deckBottom = document.getElementById("drop-deck-bottom"); + //Remove old card boxes if any + this.elem.querySelectorAll('.drop-box').forEach(oi => { + oi.remove() + }); + this.elem.querySelectorAll('.drop-susp').forEach(oi => { + oi.remove() + }); + + // Add a "..." at the beginning of the bottom row + let box = null; + if (this.bottomAllowed) { + deckBottom.style.visibility = 'visible'; + box = document.createElement("div"); + box.classList.add("drop-susp"); + box.innerHTML = "···"; + deckBottom.appendChild(box); + } else { + deckBottom.style.visibility = 'hidden'; + } + for (var i = 0; i < this.cards.length; i++) { + // Create the bank box + box = document.createElement("div"); + box.classList.add("drop-box"); + bankRow.appendChild(box); + // Create the sortable item + let item = document.createElement("div"); + item.classList.add("drop-item"); + item.setAttribute("draggable", "true"); + item.setAttribute("id", "item-" + i.toString()); + item.setAttribute("data-pos", i.toString()); + item.setAttribute("data-card-key", this.cards[i].key); + box.appendChild(item); + // Add card container + let cardContainer = document.createElement("div"); + cardContainer.classList.add("card-lg"); + // Add the card content + getPreviewElem(cardContainer, this.cards[i]); + cardContainer.classList.remove("hide"); + cardContainer.classList.remove("noclick"); + item.appendChild(cardContainer); + + // Prevent all children elements from being draggable instead of the parent node + let children = item.querySelectorAll('*'); + children.forEach(n => { + n.setAttribute("draggable", "false") + }); + + item.addEventListener('dragstart', dragStart); + item.addEventListener('dragend', dragEnd); + // Add a box in the Top row + box = document.createElement("div"); + box.classList.add("drop-box"); + deckTop.appendChild(box); + // Add a box in the Bottom row + if (this.bottomAllowed) { + box = document.createElement("div"); + box.classList.add("drop-box"); + deckBottom.appendChild(box); + } + } + // Add a "..." at the end of the bottom row + box = document.createElement("div"); + box.classList.add("drop-susp"); + box.innerHTML = "···"; + deckTop.appendChild(box); + // Add done button + box = document.createElement("div"); + box.classList.add("drop-susp"); + //box.innerHTML = "DONE"; + bankRow.appendChild(box); + let submitBtn = document.createElement("button"); + submitBtn.setAttribute("id", "drop-submit"); + submitBtn.disabled = true; + submitBtn.innerText = "DONE"; + submitBtn.addEventListener('click', submitDeckSorter); + box.appendChild(submitBtn); + + function dragStart(e) { + //e.dataTransfer.setData('text/plain', e.target.id); + if (e.target) { + DeckSorter.curr.target_id = e.target.id; + setTimeout(() => { + e.target.classList.add('hide'); + }, 0); + } + } + + function dragEnd(e) { + // get the draggable element + //let id = e.dataTransfer.getData('text/plain'); + let id = DeckSorter.curr.target_id; + let draggable = document.getElementById(id); + + // display the draggable element - by default + if (draggable) { + draggable.classList.remove('hide'); + } + } + + /* drop targets */ + let boxes = document.querySelectorAll('.drop-box'); + boxes.forEach(box => { + box.addEventListener('dragenter', dragEnter) + box.addEventListener('dragover', dragOver); + box.addEventListener('dragleave', dragLeave); + box.addEventListener('drop', drop); + }); + + function dragEnter(e) { + e.preventDefault(); + if (e.target) { + e.target.classList.add('drag-over'); + } + } + + function dragOver(e) { + e.preventDefault(); + if (e.target) { + e.target.classList.add('drag-over'); + } + } + + function dragLeave(e) { + if (e.target) { + e.target.classList.remove('drag-over'); + } + } + + function drop(e) { + if (e.target) { + e.target.classList.remove('drag-over'); + /*let children = e.target.querySelectorAll('*'); + children.forEach(n => { n.setAttribute("draggable", "false") });*/ + //let id = e.dataTransfer.getData('text/plain'); + let id = DeckSorter.curr.target_id; + let draggable = document.getElementById(id); + + // get the draggable element + if (e.target.querySelectorAll('.drop-item').length == 0 && e.target.classList.contains("drop-box")) { + // add it to the drop target + e.target.appendChild(draggable); + } + + // display the draggable element + if (draggable) { + draggable.classList.remove('hide'); + } + + //Enable/disable submit button if all cards have been sorted + var bank = document.getElementById("drop-bank").querySelectorAll('.drop-item'); + document.getElementById("drop-submit").disabled = (bank.length > 0); + } + } + + function submitDeckSorter(e) { + var bank = document.getElementById("drop-bank").querySelectorAll('.drop-item'); + var deckTop = document.getElementById("drop-deck-top").querySelectorAll('.drop-item'); + var deckBottom = document.getElementById("drop-deck-bottom").querySelectorAll('.drop-item'); + + // If bank has been sorted, ready to go + if (bank.length == 0 && (deckTop.length + deckBottom.length) == DeckSorter.curr.cards.length) { + DeckSorter.curr.applyChanges(); + DeckSorter.curr.exit(); + } + } + + if (this.title) { + this.title_elem.innerHTML = this.title; + this.title_elem.classList.remove("hide"); + } else { + this.title_elem.classList.add("hide"); + } + + DeckSorter.setCurrent(this); + + this.elem.classList.remove("hide"); + ui.enablePlayer(true); + } + + // Closes the deck sorter interface + exit() { + let bankRow = document.getElementById("drop-bank"); + let deckTop = document.getElementById("drop-deck-top"); + let deckBottom = document.getElementById("drop-deck-bottom"); + //Remove old card boxes if any + bankRow.querySelectorAll('.drop-item').forEach(oi => { + oi.remove() + }); + deckTop.querySelectorAll('.drop-susp').forEach(oi => { + oi.remove() + }); + deckBottom.querySelectorAll('.drop-susp').forEach(oi => { + oi.remove() + }); + this.elem.classList.add("hide"); + DeckSorter.clearCurrent(); + ui.enablePlayer(true); + } + + isCompleted() { + return this.completed; + } + + applyChanges() { + let deckTop = Array.from(document.getElementById("drop-deck-top").querySelectorAll('.drop-item')); + let deckBottom = Array.from(document.getElementById("drop-deck-bottom").querySelectorAll('.drop-item')); + // Init new deck without the first X cards being sorted + let newdeck = this.player.deck.cards.slice(this.cards.length); + let head = []; + //Adding cards at the top + let cards_bank = this.cards; + deckTop.forEach(function (el) { + let pos = parseInt(el.dataset.pos); + head.push(cards_bank[pos]); + }); + newdeck.unshift(...head); + //Adding cards at the bottom + deckBottom.forEach(function (el) { + let pos = parseInt(el.dataset.pos); + newdeck.push(cards_bank[pos]); + }); + // set new deck order + this.player.deck.cards = newdeck; + + this.completed = true; + } + + // Statically sets the current carousel + static setCurrent(curr) { + this.curr = curr; + } + + // Statically clears the current carousel + static clearCurrent() { + this.curr = null; + } +} + +// Translates a card between two containers +async function translateTo(card, container_source, container_dest) { + if (!container_dest || !container_source) + return; + // When solo vs AI, do not display the translations between hand and deck for the AI + if (game.mode == 1 && (container_dest === player_op.hand && container_source === player_op.deck) || (container_dest === player_op.deck && container_source === player_op.hand) ) + return; + + let elem = card.elem; + let source = !container_source ? card.elem : getSourceElem(card, container_source, container_dest); + let dest = getDestinationElem(card, container_source, container_dest); + if (!isInDocument(elem)) + source.appendChild(elem); + let x = trueOffsetLeft(dest) - trueOffsetLeft(elem) + dest.offsetWidth / 2 - elem.offsetWidth; + let y = trueOffsetTop(dest) - trueOffsetTop(elem) + dest.offsetHeight / 2 - elem.offsetHeight / 2; + if (container_dest instanceof Row && container_dest.cards.length !== 0 && !card.isSpecial()) { + x += (container_dest.getSortedIndex(card) === container_dest.cards.length) ? elem.offsetWidth / 2 : -elem.offsetWidth / 2; + } + if (card.holder.controller instanceof ControllerAI) + x += elem.offsetWidth / 2; + if (container_source instanceof Row && container_dest instanceof Grave && !card.isSpecial()) { + let mid = trueOffset(container_source.elem, true) + container_source.elem.offsetWidth / 2; + x += trueOffset(elem, true) - mid; + } + if (container_source instanceof Row && container_dest === player_me.hand) + y *= 7 / 8; + await translate(elem, x, y); + + // Returns true if the element is visible in the viewport + function isInDocument(elem) { + return elem.getBoundingClientRect().width !== 0; + } + + // Returns the true offset of a nested element in the viewport + function trueOffset(elem, left) { + let total = 0; + let curr = elem; + while (curr) { + total += (left ? curr.offsetLeft : curr.offsetTop); + curr = curr.parentElement; + } + return total; + } + + function trueOffsetLeft(elem) { + return trueOffset(elem, true); + } + + function trueOffsetTop(elem) { + return trueOffset(elem, false); + } + + // Returns the source container's element to transition from + function getSourceElem(card, source, dest) { + if (source instanceof HandAI) + return source.hidden_elem; + if (source instanceof Deck) + return source.elem.children[source.elem.children.length - 2]; + return source.elem; + } + + // Returns the destination container's element to transition to + function getDestinationElem(card, source, dest) { + if (dest instanceof HandAI) + return dest.hidden_elem; + if (card.isSpecial() && dest instanceof Row) + //return dest.elem_special; + return dest.special.elem; + if (dest instanceof Row || dest instanceof Hand || dest instanceof Weather) { + if (dest.cards.length === 0) + return dest.elem; + let index = dest.getSortedIndex(card); + let dcard = dest.cards[index === dest.cards.length ? index - 1 : index]; + return dcard.elem; + } + return dest.elem; + } +} + +// Translates an element by x from the left and y from the top +async function translate(elem, x, y) { + let vw100 = 100 / document.getElementById("dimensions").offsetWidth; + x *= vw100; + y *= vw100; + elem.style.transform = "translate(" + x + "vw, " + y + "vw)"; + let margin = elem.style.marginLeft; + elem.style.marginRight = -elem.offsetWidth * vw100 + "vw"; + elem.style.marginLeft = ""; + await sleep(499); + elem.style.transform = ""; + elem.style.position = ""; + elem.style.marginLeft = margin; + elem.style.marginRight = margin; +} + +// Fades out an element until hidden over the duration +async function fadeOut(elem, duration, delay) { + await fade(false, elem, duration, delay); +} + +// Fades in an element until opaque over the duration +async function fadeIn(elem, duration, delay) { + await fade(true, elem, duration, delay); +} + +// Fades an element over a duration +async function fade(fadeIn, elem, dur, delay) { + if (delay) + await sleep(delay); + let op = fadeIn ? 0.1 : 1; + elem.style.opacity = op; + elem.style.filter = "alpha(opacity=" + (op * 100) + ")"; + if (fadeIn) + elem.classList.remove("hide"); + let timer = setInterval(async function () { + op += (fadeIn ? 0.1 : -0.1); + if (op >= 1) { + clearInterval(timer); + return; + } else if (op <= 0.1) { + elem.classList.add("hide"); + elem.style.opacity = ""; + elem.style.filter = ""; + clearInterval(timer); + return; + } + elem.style.opacity = op; + elem.style.filter = "alpha(opacity=" + (op * 100) + ")"; + }, dur / 10); +} + +// Get Image paths +function iconURL(name, ext = "png") { + return imgURL("icons/" + name, ext); +} + +function largeURL(name, ext = "jpg") { + return imgURL("lg/" + name, ext) +} + +function smallURL(name, ext = "jpg") { + return imgURL("sm/" + name, ext); +} + +function bottomBgURL() { + return imgURL("icons/gwent_bottom_bg", "png"); +} + +function imgURL(path, ext) { + return "url('img/" + path + "." + ext + "')"; +} + +function getPreviewElem(elem, card, nb = 0) { + // Cleaning existing child nodes + while (elem.hasChildNodes()) { + elem.removeChild(elem.lastChild); + } + elem.classList.remove("hero"); + elem.classList.remove("faction"); + + let c_abilities = ""; + if ("ability" in card) { + c_abilities = card.ability.split(" "); + } else { + c_abilities = card.abilities; + } + let faction = "" + if ("deck" in card) { + faction = card.deck.split(" ")[0]; // Cleaning in case of special/weather cards being faction specific + } else { + faction = card.faction; + } + + elem.style.backgroundImage = smallURL(faction + "_" + card.filename); + + if (faction == "faction") { + elem.classList.add("faction"); + return elem; + } + + if (card.row != "leader" && !faction.startsWith("special") && faction != "neutral" && !faction.startsWith("weather")) { + let factionBand = document.createElement("div"); + factionBand.style.backgroundImage = iconURL("faction-band-" + faction); + factionBand.classList.add("card-large-faction-band"); + elem.appendChild(factionBand); + } + + let cardbg = document.createElement("div"); + cardbg.style.backgroundImage = bottomBgURL(); + cardbg.classList.add("card-large-bg"); + elem.appendChild(cardbg); + + + let card_name = document.createElement("div"); + card_name.classList.add("card-large-name"); + card_name.appendChild(document.createTextNode(card.name)); + elem.appendChild(card_name); + + if ("quote" in card) { + let quote_elem = document.createElement("div"); + quote_elem.classList.add("card-large-quote"); + quote_elem.appendChild(document.createTextNode(card.quote)); + elem.appendChild(quote_elem); + } + + // Nothing else to display for leaders + if (card.row === "leader") { + return elem; + } + + let count = document.createElement("div"); + count.innerHTML = nb; + count.classList.add("card-count"); + cardbg.appendChild(count); + if (nb == 0) { + count.classList.add("hide"); + } + + let power = document.createElement("div"); + power.classList.add("card-large-power"); + elem.appendChild(power); + let bg; + if (c_abilities[0] === "hero" || ("hero" in card && card.hero)) { + bg = "power_hero"; + elem.classList.add("hero"); + } else if (faction.startsWith("weather")) { + bg = "power_" + c_abilities[0]; + } else if (faction.startsWith("special")) { + let str = c_abilities[0]; + if (str === "shield_c" || str == "shield_r" || str === "shield_s") + str = "shield"; + bg = "power_" + str; + elem.classList.add("special"); + } else { + bg = "power_normal"; + } + power.style.backgroundImage = iconURL(bg); + + let row = document.createElement("div"); + row.classList.add("card-large-row"); + elem.appendChild(row); + if (card.row === "close" || card.row === "ranged" || card.row === "siege" || card.row.includes("agile")) { + let num = document.createElement("div"); + if ("strength" in card) { + num.appendChild(document.createTextNode(card.strength)); + } else { + num.appendChild(document.createTextNode(card.basePower)); + } + num.classList.add("card-large-power-strength"); + power.appendChild(num); + row.style.backgroundImage = iconURL("card_row_" + card.row); + } + + if (c_abilities.length > 0) { + let abi = document.createElement("div"); + abi.classList.add("card-large-ability"); + elem.appendChild(abi); + + if (!faction.startsWith("special") && !faction.startsWith("weather") && c_abilities.length > 0 && c_abilities[c_abilities.length - 1] != "hero") { + let str = c_abilities[c_abilities.length - 1]; + if (str === "cerys") + str = "muster"; + if (str.startsWith("avenger")) + str = "avenger"; + if (str === "scorch_c" || str == "scorch_r" || str === "scorch_s") + str = "scorch_combat"; + if (str === "shield_c" || str == "shield_r" || str === "shield_s") + str = "shield"; + abi.style.backgroundImage = iconURL("card_ability_" + str); + } else if (card.row.includes("agile")) { + abi.style.backgroundImage = iconURL("card_ability_" + "agile"); + } + + // In case of double abilities + if ((c_abilities.length > 1 && !(c_abilities[0] === "hero")) || (c_abilities.length > 2 && c_abilities[0] === "hero")) { + let abi2 = document.createElement("div"); + abi2.classList.add("card-large-ability-2"); + elem.appendChild(abi2); + + let str = c_abilities[c_abilities.length - 2]; + if (str === "cerys") + str = "muster"; + if (str.startsWith("avenger")) + str = "avenger"; + if (str === "scorch_c" || str == "scorch_r" || str === "scorch_s") + str = "scorch_combat"; + if (str === "shield_c" || str == "shield_r" || str === "shield_s") + str = "shield"; + abi2.style.backgroundImage = iconURL("card_ability_" + str); + } + } + + return elem; +} + +// Returns true if n is an Number +function isNumber(n) { + return !isNaN(parseFloat(n)) && isFinite(n); +} + +// Returns true if s is a String +function isString(s) { + return typeof (s) === 'string' || s instanceof String; +} + +// Returns a random integer in the range [0,n) +function randomInt(n) { + return Math.floor(Math.random() * n); +} + +// Pauses execution until the passed number of milliseconds as expired +function sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); +} + +// Suspends execution until the predicate condition is met, checking every ms milliseconds +function sleepUntil(predicate, ms) { + return new Promise(resolve => { + let timer = setInterval(function () { + if (predicate()) { + clearInterval(timer); + resolve(); + } + }, ms) + }); +} + +// Initializes the interractive YouTube object +function onYouTubeIframeAPIReady() { + ui.initYouTube(); +} + +/*----------------------------------------------------*/ + +var ui = new UI(); +var board = new Board(); +var weather = new Weather(); +var game = new Game(); +var player_me, player_op; + +ui.enablePlayer(false); +let dm = new DeckMaker(); + +document.addEventListener('contextmenu', event => event.preventDefault()); + +document.onkeydown = function (e) { + if (e.keyCode != 123) { + if (document.getElementById("carousel").className != "hide") { + switch (e.keyCode) { + case 13: + Carousel.curr.select(e); + break; + case 37: + Carousel.curr.shift(e, -1); + break; + case 39: + Carousel.curr.shift(e, 1); + break; + } + } else if (document.getElementsByClassName("hover_un")[0].innerText.length > 1) { + switch (e.keyCode) { + case 69: + Popup.curr.selectYes(); + break; + case 81: + Popup.curr.selectNo(); + break; + } + } else if (!iniciou && isLoaded && (e.keyCode == 13 || e.keyCode == 69)) inicio(); + } else return false; +} + +var elem_principal = document.documentElement; + +function openFullscreen() { + try { + if (elem_principal.requestFullscreen) elem_principal.requestFullscreen(); + else if (elem_principal.webkitRequestFullscreen) elem_principal.webkitRequestFullscreen(); + else if (elem_principal.msRequestFullscreen) elem_principal.msRequestFullscreen(); + window.screen.orientation.lock("landscape"); + } catch (err) { } +} + +var lastSound = ""; + +function tocar(arquivo, pararMusica) { + if (arquivo != lastSound && arquivo != "") { + var s = new Audio("sfx/" + arquivo + ".mp3"); + if (pararMusica && ui.youtube && ui.youtube.getPlayerState() === YT.PlayerState.PLAYING) { + ui.youtube.pauseVideo(); + ui.toggleMusic_elem.classList.add("fade"); + } + lastSound = arquivo; + if (iniciou) s.play(); + setTimeout(function () { + lastSound = ""; + }, 50); + } +} + +function aviso(texto) { + tocar("warning", false); + setTimeout(function () { + alert(texto); + document.getElementById("start-game").blur(); + tocar("warning", false); + }, 150); +} + +function somCarta() { + var classes = ["card", "card-lg"]; + for (var i = 0; i < classes.length; i++) { + var cartas = document.getElementsByClassName(classes[i]); + for (var j = 0; j < cartas.length; j++) { + if (cartas[j].id != "no_sound" && cartas[j].id != "no_hover") cartas[j].addEventListener("mouseover", function () { + tocar("card", false); + }); + } + } + var tags = ["label", "a", "button"]; + for (var i = 0; i < tags.length; i++) { + var rec = document.getElementsByTagName(tags[i]); + for (var j = 0; j < rec.length; j++) rec[j].addEventListener("mouseover", function () { + tocar("card", false); + }); + } + var ids = ["pass-button", "toggle-music"]; + for (var i = 0; i < ids.length; i++) document.getElementById(ids[i]).addEventListener("mouseover", function () { + tocar("card", false); + }); +} + +function cartaNaLinha(id, carta) { + if (id.charAt(0) == "f") { + if (!carta.hero) { + if (carta.name != "Decoy") { + var linha = parseInt(id.charAt(1)); + if (linha == 1 || linha == 6) tocar("common3", false); + else if (linha == 2 || linha == 5) tocar("common2", false); + else if (linha == 3 || linha == 4) tocar("common1", false); + } else tocar("menu_buy", false); + } else tocar("hero", false); + } +} + +function inicio() { + var classe = document.getElementsByClassName("abs"); + for (var i = 0; i < classe.length; i++) classe[i].style.display = "none"; + iniciou = true; + tocar("menu_opening", false); + openFullscreen(); + iniciarMusica(); +} + +function iniciarMusica() { + try { + if (ui.youtube.getPlayerState() !== YT.PlayerState.PLAYING) { + ui.youtube.playVideo(); + ui.toggleMusic_elem.classList.remove("fade"); + } + } catch (err) { } +} + +function cancelaClima() { + if (carta_c) { + ui.cancel(); + hover_row = false; + setTimeout(function () { + hover_row = true; + }, 100); + } +} + +var iniciou = false, + isLoaded = false; + +var playingOnline; + +window.onload = function () { + dimensionar(); + playingOnline = window.location.href == "https://randompianist.github.io/gwent-classic-v2.0/"; + document.getElementById("load_text").style.display = "none"; + document.getElementById("button_start").style.display = "inline-block"; + document.getElementById("deck-customization").style.display = ""; + document.getElementById("toggle-music").style.display = ""; + document.getElementsByTagName("main")[0].style.display = ""; + document.getElementById("button_start").addEventListener("click", function () { + inicio(); + }); + isLoaded = true; +} + +window.onresize = function () { + dimensionar(); +} + +function dimensionar() { + var prop = window.innerWidth / window.innerHeight; + var dim = document.getElementById("dimensions").offsetHeight; + document.getElementById("very_start_bg2").style.height = prop < 1.8 ? (parseInt(dim * 0.94) - 8) + "px" : ""; + document.getElementById("very_start").style.paddingTop = ""; + document.getElementById("very_start").style.paddingTop = parseInt( + (document.getElementById("very_start_bg2").offsetHeight - document.getElementById("very_start").offsetHeight) / 2 + ) + "px"; +} + +setTimeout(dimensionar(), 300); + +function isMobile() { + if (navigator.userAgentData) + return navigator.userAgentData.mobile; + return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); +} \ No newline at end of file diff --git a/img/board.jpg b/img/board.jpg new file mode 100644 index 0000000..336cbbb Binary files /dev/null and b/img/board.jpg differ diff --git a/img/icons/anim_aerondight.png b/img/icons/anim_aerondight.png new file mode 100644 index 0000000..6ed54f6 Binary files /dev/null and b/img/icons/anim_aerondight.png differ diff --git a/img/icons/anim_ambush.png b/img/icons/anim_ambush.png new file mode 100644 index 0000000..a7e399a Binary files /dev/null and b/img/icons/anim_ambush.png differ diff --git a/img/icons/anim_bond.png b/img/icons/anim_bond.png new file mode 100644 index 0000000..b8fc321 Binary files /dev/null and b/img/icons/anim_bond.png differ diff --git a/img/icons/anim_comrade.png b/img/icons/anim_comrade.png new file mode 100644 index 0000000..2f4c97a Binary files /dev/null and b/img/icons/anim_comrade.png differ diff --git a/img/icons/anim_curse.png b/img/icons/anim_curse.png new file mode 100644 index 0000000..9f9a23c Binary files /dev/null and b/img/icons/anim_curse.png differ diff --git a/img/icons/anim_emissary.png b/img/icons/anim_emissary.png new file mode 100644 index 0000000..3161168 Binary files /dev/null and b/img/icons/anim_emissary.png differ diff --git a/img/icons/anim_goetia.png b/img/icons/anim_goetia.png new file mode 100644 index 0000000..20a3a8d Binary files /dev/null and b/img/icons/anim_goetia.png differ diff --git a/img/icons/anim_horn.png b/img/icons/anim_horn.png new file mode 100644 index 0000000..e753773 Binary files /dev/null and b/img/icons/anim_horn.png differ diff --git a/img/icons/anim_immortal.png b/img/icons/anim_immortal.png new file mode 100644 index 0000000..397e8f9 Binary files /dev/null and b/img/icons/anim_immortal.png differ diff --git a/img/icons/anim_invoke.png b/img/icons/anim_invoke.png new file mode 100644 index 0000000..cecbaf3 Binary files /dev/null and b/img/icons/anim_invoke.png differ diff --git a/img/icons/anim_knockback.png b/img/icons/anim_knockback.png new file mode 100644 index 0000000..c1d13f1 Binary files /dev/null and b/img/icons/anim_knockback.png differ diff --git a/img/icons/anim_lock.png b/img/icons/anim_lock.png new file mode 100644 index 0000000..58e4f72 Binary files /dev/null and b/img/icons/anim_lock.png differ diff --git a/img/icons/anim_mardroeme.png b/img/icons/anim_mardroeme.png new file mode 100644 index 0000000..6451a65 Binary files /dev/null and b/img/icons/anim_mardroeme.png differ diff --git a/img/icons/anim_medic.png b/img/icons/anim_medic.png new file mode 100644 index 0000000..ba34257 Binary files /dev/null and b/img/icons/anim_medic.png differ diff --git a/img/icons/anim_monster_toussaint.png b/img/icons/anim_monster_toussaint.png new file mode 100644 index 0000000..9f9927e Binary files /dev/null and b/img/icons/anim_monster_toussaint.png differ diff --git a/img/icons/anim_morale.png b/img/icons/anim_morale.png new file mode 100644 index 0000000..bdf326a Binary files /dev/null and b/img/icons/anim_morale.png differ diff --git a/img/icons/anim_muster.png b/img/icons/anim_muster.png new file mode 100644 index 0000000..87b4fed Binary files /dev/null and b/img/icons/anim_muster.png differ diff --git a/img/icons/anim_necrophage.png b/img/icons/anim_necrophage.png new file mode 100644 index 0000000..4bfd12c Binary files /dev/null and b/img/icons/anim_necrophage.png differ diff --git a/img/icons/anim_resilience.png b/img/icons/anim_resilience.png new file mode 100644 index 0000000..6e38906 Binary files /dev/null and b/img/icons/anim_resilience.png differ diff --git a/img/icons/anim_scorch.png b/img/icons/anim_scorch.png new file mode 100644 index 0000000..568fe28 Binary files /dev/null and b/img/icons/anim_scorch.png differ diff --git a/img/icons/anim_seize.png b/img/icons/anim_seize.png new file mode 100644 index 0000000..6a58f98 Binary files /dev/null and b/img/icons/anim_seize.png differ diff --git a/img/icons/anim_shield.png b/img/icons/anim_shield.png new file mode 100644 index 0000000..80f434e Binary files /dev/null and b/img/icons/anim_shield.png differ diff --git a/img/icons/anim_soothsayer.png b/img/icons/anim_soothsayer.png new file mode 100644 index 0000000..1c29241 Binary files /dev/null and b/img/icons/anim_soothsayer.png differ diff --git a/img/icons/anim_spy.png b/img/icons/anim_spy.png new file mode 100644 index 0000000..13197e2 Binary files /dev/null and b/img/icons/anim_spy.png differ diff --git a/img/icons/anim_summon_one_of.png b/img/icons/anim_summon_one_of.png new file mode 100644 index 0000000..24641c0 Binary files /dev/null and b/img/icons/anim_summon_one_of.png differ diff --git a/img/icons/card_ability_aerondight.png b/img/icons/card_ability_aerondight.png new file mode 100644 index 0000000..50eff5e Binary files /dev/null and b/img/icons/card_ability_aerondight.png differ diff --git a/img/icons/card_ability_agile.png b/img/icons/card_ability_agile.png new file mode 100644 index 0000000..9ce8d43 Binary files /dev/null and b/img/icons/card_ability_agile.png differ diff --git a/img/icons/card_ability_ambush.png b/img/icons/card_ability_ambush.png new file mode 100644 index 0000000..56f8cd4 Binary files /dev/null and b/img/icons/card_ability_ambush.png differ diff --git a/img/icons/card_ability_avenger.png b/img/icons/card_ability_avenger.png new file mode 100644 index 0000000..3f705d6 Binary files /dev/null and b/img/icons/card_ability_avenger.png differ diff --git a/img/icons/card_ability_bait.png b/img/icons/card_ability_bait.png new file mode 100644 index 0000000..65b1f56 Binary files /dev/null and b/img/icons/card_ability_bait.png differ diff --git a/img/icons/card_ability_bank.png b/img/icons/card_ability_bank.png new file mode 100644 index 0000000..a03a262 Binary files /dev/null and b/img/icons/card_ability_bank.png differ diff --git a/img/icons/card_ability_berserker.png b/img/icons/card_ability_berserker.png new file mode 100644 index 0000000..9e824ef Binary files /dev/null and b/img/icons/card_ability_berserker.png differ diff --git a/img/icons/card_ability_bond.png b/img/icons/card_ability_bond.png new file mode 100644 index 0000000..f2f4fa7 Binary files /dev/null and b/img/icons/card_ability_bond.png differ diff --git a/img/icons/card_ability_cintra_slaughter.png b/img/icons/card_ability_cintra_slaughter.png new file mode 100644 index 0000000..f0ae641 Binary files /dev/null and b/img/icons/card_ability_cintra_slaughter.png differ diff --git a/img/icons/card_ability_clear.png b/img/icons/card_ability_clear.png new file mode 100644 index 0000000..1eaa4d6 Binary files /dev/null and b/img/icons/card_ability_clear.png differ diff --git a/img/icons/card_ability_comrade.png b/img/icons/card_ability_comrade.png new file mode 100644 index 0000000..6183b58 Binary files /dev/null and b/img/icons/card_ability_comrade.png differ diff --git a/img/icons/card_ability_decoy.png b/img/icons/card_ability_decoy.png new file mode 100644 index 0000000..d23646b Binary files /dev/null and b/img/icons/card_ability_decoy.png differ diff --git a/img/icons/card_ability_emissary.png b/img/icons/card_ability_emissary.png new file mode 100644 index 0000000..19ca9aa Binary files /dev/null and b/img/icons/card_ability_emissary.png differ diff --git a/img/icons/card_ability_fog.png b/img/icons/card_ability_fog.png new file mode 100644 index 0000000..48d3782 Binary files /dev/null and b/img/icons/card_ability_fog.png differ diff --git a/img/icons/card_ability_fog_summoning.png b/img/icons/card_ability_fog_summoning.png new file mode 100644 index 0000000..48d3782 Binary files /dev/null and b/img/icons/card_ability_fog_summoning.png differ diff --git a/img/icons/card_ability_frost.png b/img/icons/card_ability_frost.png new file mode 100644 index 0000000..3a824f8 Binary files /dev/null and b/img/icons/card_ability_frost.png differ diff --git a/img/icons/card_ability_goetia.png b/img/icons/card_ability_goetia.png new file mode 100644 index 0000000..ac99b59 Binary files /dev/null and b/img/icons/card_ability_goetia.png differ diff --git a/img/icons/card_ability_horn.png b/img/icons/card_ability_horn.png new file mode 100644 index 0000000..c107927 Binary files /dev/null and b/img/icons/card_ability_horn.png differ diff --git a/img/icons/card_ability_immortal.png b/img/icons/card_ability_immortal.png new file mode 100644 index 0000000..a3af63a Binary files /dev/null and b/img/icons/card_ability_immortal.png differ diff --git a/img/icons/card_ability_inspire.png b/img/icons/card_ability_inspire.png new file mode 100644 index 0000000..aa0a5b2 Binary files /dev/null and b/img/icons/card_ability_inspire.png differ diff --git a/img/icons/card_ability_invoke.png b/img/icons/card_ability_invoke.png new file mode 100644 index 0000000..bc28032 Binary files /dev/null and b/img/icons/card_ability_invoke.png differ diff --git a/img/icons/card_ability_knockback.png b/img/icons/card_ability_knockback.png new file mode 100644 index 0000000..5371cc3 Binary files /dev/null and b/img/icons/card_ability_knockback.png differ diff --git a/img/icons/card_ability_lock.png b/img/icons/card_ability_lock.png new file mode 100644 index 0000000..c79261e Binary files /dev/null and b/img/icons/card_ability_lock.png differ diff --git a/img/icons/card_ability_mardroeme.png b/img/icons/card_ability_mardroeme.png new file mode 100644 index 0000000..4fa664e Binary files /dev/null and b/img/icons/card_ability_mardroeme.png differ diff --git a/img/icons/card_ability_medic.png b/img/icons/card_ability_medic.png new file mode 100644 index 0000000..f4d3790 Binary files /dev/null and b/img/icons/card_ability_medic.png differ diff --git a/img/icons/card_ability_monster_toussaint.png b/img/icons/card_ability_monster_toussaint.png new file mode 100644 index 0000000..fed299e Binary files /dev/null and b/img/icons/card_ability_monster_toussaint.png differ diff --git a/img/icons/card_ability_morale.png b/img/icons/card_ability_morale.png new file mode 100644 index 0000000..2e95c45 Binary files /dev/null and b/img/icons/card_ability_morale.png differ diff --git a/img/icons/card_ability_muster.png b/img/icons/card_ability_muster.png new file mode 100644 index 0000000..590a5fa Binary files /dev/null and b/img/icons/card_ability_muster.png differ diff --git a/img/icons/card_ability_necrophage.png b/img/icons/card_ability_necrophage.png new file mode 100644 index 0000000..56fc361 Binary files /dev/null and b/img/icons/card_ability_necrophage.png differ diff --git a/img/icons/card_ability_rain.png b/img/icons/card_ability_rain.png new file mode 100644 index 0000000..32f7d5a Binary files /dev/null and b/img/icons/card_ability_rain.png differ diff --git a/img/icons/card_ability_resilience.png b/img/icons/card_ability_resilience.png new file mode 100644 index 0000000..d5b45b8 Binary files /dev/null and b/img/icons/card_ability_resilience.png differ diff --git a/img/icons/card_ability_scorch.png b/img/icons/card_ability_scorch.png new file mode 100644 index 0000000..eb334d2 Binary files /dev/null and b/img/icons/card_ability_scorch.png differ diff --git a/img/icons/card_ability_scorch_combat.png b/img/icons/card_ability_scorch_combat.png new file mode 100644 index 0000000..985b6f1 Binary files /dev/null and b/img/icons/card_ability_scorch_combat.png differ diff --git a/img/icons/card_ability_seize.png b/img/icons/card_ability_seize.png new file mode 100644 index 0000000..94d419d Binary files /dev/null and b/img/icons/card_ability_seize.png differ diff --git a/img/icons/card_ability_shield.png b/img/icons/card_ability_shield.png new file mode 100644 index 0000000..091848c Binary files /dev/null and b/img/icons/card_ability_shield.png differ diff --git a/img/icons/card_ability_soothsayer.png b/img/icons/card_ability_soothsayer.png new file mode 100644 index 0000000..9de3725 Binary files /dev/null and b/img/icons/card_ability_soothsayer.png differ diff --git a/img/icons/card_ability_spy.png b/img/icons/card_ability_spy.png new file mode 100644 index 0000000..7c6a6f6 Binary files /dev/null and b/img/icons/card_ability_spy.png differ diff --git a/img/icons/card_ability_storm.png b/img/icons/card_ability_storm.png new file mode 100644 index 0000000..a666f87 Binary files /dev/null and b/img/icons/card_ability_storm.png differ diff --git a/img/icons/card_ability_summon_one_of.png b/img/icons/card_ability_summon_one_of.png new file mode 100644 index 0000000..c21d8f8 Binary files /dev/null and b/img/icons/card_ability_summon_one_of.png differ diff --git a/img/icons/card_ability_toussaint_wine.png b/img/icons/card_ability_toussaint_wine.png new file mode 100644 index 0000000..1d596b1 Binary files /dev/null and b/img/icons/card_ability_toussaint_wine.png differ diff --git a/img/icons/card_ability_whorshipped.png b/img/icons/card_ability_whorshipped.png new file mode 100644 index 0000000..36ed691 Binary files /dev/null and b/img/icons/card_ability_whorshipped.png differ diff --git a/img/icons/card_ability_whorshipper.png b/img/icons/card_ability_whorshipper.png new file mode 100644 index 0000000..b709e7c Binary files /dev/null and b/img/icons/card_ability_whorshipper.png differ diff --git a/img/icons/card_ability_witch_hunt.png b/img/icons/card_ability_witch_hunt.png new file mode 100644 index 0000000..83317d0 Binary files /dev/null and b/img/icons/card_ability_witch_hunt.png differ diff --git a/img/icons/card_ability_witcher_bear_school.png b/img/icons/card_ability_witcher_bear_school.png new file mode 100644 index 0000000..aa57c75 Binary files /dev/null and b/img/icons/card_ability_witcher_bear_school.png differ diff --git a/img/icons/card_ability_witcher_cat_school.png b/img/icons/card_ability_witcher_cat_school.png new file mode 100644 index 0000000..933a71c Binary files /dev/null and b/img/icons/card_ability_witcher_cat_school.png differ diff --git a/img/icons/card_ability_witcher_griffin_school.png b/img/icons/card_ability_witcher_griffin_school.png new file mode 100644 index 0000000..b9475e8 Binary files /dev/null and b/img/icons/card_ability_witcher_griffin_school.png differ diff --git a/img/icons/card_ability_witcher_viper_school.png b/img/icons/card_ability_witcher_viper_school.png new file mode 100644 index 0000000..a0b431c Binary files /dev/null and b/img/icons/card_ability_witcher_viper_school.png differ diff --git a/img/icons/card_ability_witcher_wolf_school.png b/img/icons/card_ability_witcher_wolf_school.png new file mode 100644 index 0000000..48748df Binary files /dev/null and b/img/icons/card_ability_witcher_wolf_school.png differ diff --git a/img/icons/card_row_agile.png b/img/icons/card_row_agile.png new file mode 100644 index 0000000..17763f7 Binary files /dev/null and b/img/icons/card_row_agile.png differ diff --git a/img/icons/card_row_agile_cr.png b/img/icons/card_row_agile_cr.png new file mode 100644 index 0000000..abbb05b Binary files /dev/null and b/img/icons/card_row_agile_cr.png differ diff --git a/img/icons/card_row_agile_crs.png b/img/icons/card_row_agile_crs.png new file mode 100644 index 0000000..c38b6c8 Binary files /dev/null and b/img/icons/card_row_agile_crs.png differ diff --git a/img/icons/card_row_agile_cs.png b/img/icons/card_row_agile_cs.png new file mode 100644 index 0000000..5441776 Binary files /dev/null and b/img/icons/card_row_agile_cs.png differ diff --git a/img/icons/card_row_agile_rs.png b/img/icons/card_row_agile_rs.png new file mode 100644 index 0000000..1c2853f Binary files /dev/null and b/img/icons/card_row_agile_rs.png differ diff --git a/img/icons/card_row_close.png b/img/icons/card_row_close.png new file mode 100644 index 0000000..d129d38 Binary files /dev/null and b/img/icons/card_row_close.png differ diff --git a/img/icons/card_row_ranged.png b/img/icons/card_row_ranged.png new file mode 100644 index 0000000..b03850b Binary files /dev/null and b/img/icons/card_row_ranged.png differ diff --git a/img/icons/card_row_siege.png b/img/icons/card_row_siege.png new file mode 100644 index 0000000..9933a6c Binary files /dev/null and b/img/icons/card_row_siege.png differ diff --git a/img/icons/card_skellige_fleet.png b/img/icons/card_skellige_fleet.png new file mode 100644 index 0000000..298a3fe Binary files /dev/null and b/img/icons/card_skellige_fleet.png differ diff --git a/img/icons/card_special_aerondight.png b/img/icons/card_special_aerondight.png new file mode 100644 index 0000000..8cf50ea Binary files /dev/null and b/img/icons/card_special_aerondight.png differ diff --git a/img/icons/card_special_ambush.png b/img/icons/card_special_ambush.png new file mode 100644 index 0000000..f72656f Binary files /dev/null and b/img/icons/card_special_ambush.png differ diff --git a/img/icons/card_special_bait.png b/img/icons/card_special_bait.png new file mode 100644 index 0000000..f954f5f Binary files /dev/null and b/img/icons/card_special_bait.png differ diff --git a/img/icons/card_special_bank.png b/img/icons/card_special_bank.png new file mode 100644 index 0000000..f6e9664 Binary files /dev/null and b/img/icons/card_special_bank.png differ diff --git a/img/icons/card_special_cintra_slaughter.png b/img/icons/card_special_cintra_slaughter.png new file mode 100644 index 0000000..c72d32c Binary files /dev/null and b/img/icons/card_special_cintra_slaughter.png differ diff --git a/img/icons/card_special_comrade.png b/img/icons/card_special_comrade.png new file mode 100644 index 0000000..1b99eff Binary files /dev/null and b/img/icons/card_special_comrade.png differ diff --git a/img/icons/card_special_curse.png b/img/icons/card_special_curse.png new file mode 100644 index 0000000..35155ab Binary files /dev/null and b/img/icons/card_special_curse.png differ diff --git a/img/icons/card_special_decoy.png b/img/icons/card_special_decoy.png new file mode 100644 index 0000000..aca65d8 Binary files /dev/null and b/img/icons/card_special_decoy.png differ diff --git a/img/icons/card_special_emissary.png b/img/icons/card_special_emissary.png new file mode 100644 index 0000000..cd09b5f Binary files /dev/null and b/img/icons/card_special_emissary.png differ diff --git a/img/icons/card_special_goetia.png b/img/icons/card_special_goetia.png new file mode 100644 index 0000000..ffa27e6 Binary files /dev/null and b/img/icons/card_special_goetia.png differ diff --git a/img/icons/card_special_horn.png b/img/icons/card_special_horn.png new file mode 100644 index 0000000..636bdf4 Binary files /dev/null and b/img/icons/card_special_horn.png differ diff --git a/img/icons/card_special_immortal.png b/img/icons/card_special_immortal.png new file mode 100644 index 0000000..629799e Binary files /dev/null and b/img/icons/card_special_immortal.png differ diff --git a/img/icons/card_special_invoke.png b/img/icons/card_special_invoke.png new file mode 100644 index 0000000..0e332b9 Binary files /dev/null and b/img/icons/card_special_invoke.png differ diff --git a/img/icons/card_special_knockback.png b/img/icons/card_special_knockback.png new file mode 100644 index 0000000..0e4f00c Binary files /dev/null and b/img/icons/card_special_knockback.png differ diff --git a/img/icons/card_special_lock.png b/img/icons/card_special_lock.png new file mode 100644 index 0000000..b04f017 Binary files /dev/null and b/img/icons/card_special_lock.png differ diff --git a/img/icons/card_special_mardroeme.png b/img/icons/card_special_mardroeme.png new file mode 100644 index 0000000..d617f03 Binary files /dev/null and b/img/icons/card_special_mardroeme.png differ diff --git a/img/icons/card_special_monster_toussaint.png b/img/icons/card_special_monster_toussaint.png new file mode 100644 index 0000000..c25f6d7 Binary files /dev/null and b/img/icons/card_special_monster_toussaint.png differ diff --git a/img/icons/card_special_necrophage.png b/img/icons/card_special_necrophage.png new file mode 100644 index 0000000..54be146 Binary files /dev/null and b/img/icons/card_special_necrophage.png differ diff --git a/img/icons/card_special_royal_decree.png b/img/icons/card_special_royal_decree.png new file mode 100644 index 0000000..37b12b2 Binary files /dev/null and b/img/icons/card_special_royal_decree.png differ diff --git a/img/icons/card_special_scorch.png b/img/icons/card_special_scorch.png new file mode 100644 index 0000000..1004275 Binary files /dev/null and b/img/icons/card_special_scorch.png differ diff --git a/img/icons/card_special_seize.png b/img/icons/card_special_seize.png new file mode 100644 index 0000000..40c9317 Binary files /dev/null and b/img/icons/card_special_seize.png differ diff --git a/img/icons/card_special_shield.png b/img/icons/card_special_shield.png new file mode 100644 index 0000000..681fc11 Binary files /dev/null and b/img/icons/card_special_shield.png differ diff --git a/img/icons/card_special_soothsayer.png b/img/icons/card_special_soothsayer.png new file mode 100644 index 0000000..5e70568 Binary files /dev/null and b/img/icons/card_special_soothsayer.png differ diff --git a/img/icons/card_special_summon_one_of.png b/img/icons/card_special_summon_one_of.png new file mode 100644 index 0000000..912df9f Binary files /dev/null and b/img/icons/card_special_summon_one_of.png differ diff --git a/img/icons/card_special_toussaint_wine.png b/img/icons/card_special_toussaint_wine.png new file mode 100644 index 0000000..f2b0006 Binary files /dev/null and b/img/icons/card_special_toussaint_wine.png differ diff --git a/img/icons/card_special_witch_hunt.png b/img/icons/card_special_witch_hunt.png new file mode 100644 index 0000000..1ce4b70 Binary files /dev/null and b/img/icons/card_special_witch_hunt.png differ diff --git a/img/icons/card_weather_clear.png b/img/icons/card_weather_clear.png new file mode 100644 index 0000000..020db9c Binary files /dev/null and b/img/icons/card_weather_clear.png differ diff --git a/img/icons/card_weather_fog.png b/img/icons/card_weather_fog.png new file mode 100644 index 0000000..d46f787 Binary files /dev/null and b/img/icons/card_weather_fog.png differ diff --git a/img/icons/card_weather_frost.png b/img/icons/card_weather_frost.png new file mode 100644 index 0000000..46bfb75 Binary files /dev/null and b/img/icons/card_weather_frost.png differ diff --git a/img/icons/card_weather_rain.png b/img/icons/card_weather_rain.png new file mode 100644 index 0000000..d949221 Binary files /dev/null and b/img/icons/card_weather_rain.png differ diff --git a/img/icons/card_weather_storm.png b/img/icons/card_weather_storm.png new file mode 100644 index 0000000..5bb4043 Binary files /dev/null and b/img/icons/card_weather_storm.png differ diff --git a/img/icons/cursor.png b/img/icons/cursor.png new file mode 100644 index 0000000..59bef73 Binary files /dev/null and b/img/icons/cursor.png differ diff --git a/img/icons/deck_back_lyria_rivia.jpg b/img/icons/deck_back_lyria_rivia.jpg new file mode 100644 index 0000000..c5a9219 Binary files /dev/null and b/img/icons/deck_back_lyria_rivia.jpg differ diff --git a/img/icons/deck_back_monsters.jpg b/img/icons/deck_back_monsters.jpg new file mode 100644 index 0000000..b60dae7 Binary files /dev/null and b/img/icons/deck_back_monsters.jpg differ diff --git a/img/icons/deck_back_nilfgaard.jpg b/img/icons/deck_back_nilfgaard.jpg new file mode 100644 index 0000000..d22b395 Binary files /dev/null and b/img/icons/deck_back_nilfgaard.jpg differ diff --git a/img/icons/deck_back_random.jpg b/img/icons/deck_back_random.jpg new file mode 100644 index 0000000..896b6bb Binary files /dev/null and b/img/icons/deck_back_random.jpg differ diff --git a/img/icons/deck_back_realms.jpg b/img/icons/deck_back_realms.jpg new file mode 100644 index 0000000..636d9d7 Binary files /dev/null and b/img/icons/deck_back_realms.jpg differ diff --git a/img/icons/deck_back_redania.jpg b/img/icons/deck_back_redania.jpg new file mode 100644 index 0000000..8377eb8 Binary files /dev/null and b/img/icons/deck_back_redania.jpg differ diff --git a/img/icons/deck_back_scoiatael.jpg b/img/icons/deck_back_scoiatael.jpg new file mode 100644 index 0000000..f13c61c Binary files /dev/null and b/img/icons/deck_back_scoiatael.jpg differ diff --git a/img/icons/deck_back_skellige.jpg b/img/icons/deck_back_skellige.jpg new file mode 100644 index 0000000..0769ea8 Binary files /dev/null and b/img/icons/deck_back_skellige.jpg differ diff --git a/img/icons/deck_back_syndicate.jpg b/img/icons/deck_back_syndicate.jpg new file mode 100644 index 0000000..c365d30 Binary files /dev/null and b/img/icons/deck_back_syndicate.jpg differ diff --git a/img/icons/deck_back_toussaint.jpg b/img/icons/deck_back_toussaint.jpg new file mode 100644 index 0000000..dd41149 Binary files /dev/null and b/img/icons/deck_back_toussaint.jpg differ diff --git a/img/icons/deck_back_velen.jpg b/img/icons/deck_back_velen.jpg new file mode 100644 index 0000000..395383c Binary files /dev/null and b/img/icons/deck_back_velen.jpg differ diff --git a/img/icons/deck_back_witcher_universe.jpg b/img/icons/deck_back_witcher_universe.jpg new file mode 100644 index 0000000..2c5fdad Binary files /dev/null and b/img/icons/deck_back_witcher_universe.jpg differ diff --git a/img/icons/deck_back_zerrikania.jpg b/img/icons/deck_back_zerrikania.jpg new file mode 100644 index 0000000..c6f3033 Binary files /dev/null and b/img/icons/deck_back_zerrikania.jpg differ diff --git a/img/icons/deck_shield_lyria_rivia.png b/img/icons/deck_shield_lyria_rivia.png new file mode 100644 index 0000000..1941c20 Binary files /dev/null and b/img/icons/deck_shield_lyria_rivia.png differ diff --git a/img/icons/deck_shield_monsters.png b/img/icons/deck_shield_monsters.png new file mode 100644 index 0000000..31334da Binary files /dev/null and b/img/icons/deck_shield_monsters.png differ diff --git a/img/icons/deck_shield_nilfgaard.png b/img/icons/deck_shield_nilfgaard.png new file mode 100644 index 0000000..f4553d9 Binary files /dev/null and b/img/icons/deck_shield_nilfgaard.png differ diff --git a/img/icons/deck_shield_realms.png b/img/icons/deck_shield_realms.png new file mode 100644 index 0000000..b6a09f5 Binary files /dev/null and b/img/icons/deck_shield_realms.png differ diff --git a/img/icons/deck_shield_redania.png b/img/icons/deck_shield_redania.png new file mode 100644 index 0000000..83039f8 Binary files /dev/null and b/img/icons/deck_shield_redania.png differ diff --git a/img/icons/deck_shield_scoiatael.png b/img/icons/deck_shield_scoiatael.png new file mode 100644 index 0000000..60a0cae Binary files /dev/null and b/img/icons/deck_shield_scoiatael.png differ diff --git a/img/icons/deck_shield_skellige.png b/img/icons/deck_shield_skellige.png new file mode 100644 index 0000000..81a0440 Binary files /dev/null and b/img/icons/deck_shield_skellige.png differ diff --git a/img/icons/deck_shield_syndicate.png b/img/icons/deck_shield_syndicate.png new file mode 100644 index 0000000..43a3467 Binary files /dev/null and b/img/icons/deck_shield_syndicate.png differ diff --git a/img/icons/deck_shield_toussaint.png b/img/icons/deck_shield_toussaint.png new file mode 100644 index 0000000..373ab6a Binary files /dev/null and b/img/icons/deck_shield_toussaint.png differ diff --git a/img/icons/deck_shield_velen.png b/img/icons/deck_shield_velen.png new file mode 100644 index 0000000..e8b83bc Binary files /dev/null and b/img/icons/deck_shield_velen.png differ diff --git a/img/icons/deck_shield_witcher_universe.png b/img/icons/deck_shield_witcher_universe.png new file mode 100644 index 0000000..6209123 Binary files /dev/null and b/img/icons/deck_shield_witcher_universe.png differ diff --git a/img/icons/deck_shield_zerrikania.png b/img/icons/deck_shield_zerrikania.png new file mode 100644 index 0000000..0b8d5fd Binary files /dev/null and b/img/icons/deck_shield_zerrikania.png differ diff --git a/img/icons/deck_stats_count.png b/img/icons/deck_stats_count.png new file mode 100644 index 0000000..0609a91 Binary files /dev/null and b/img/icons/deck_stats_count.png differ diff --git a/img/icons/deck_stats_hero.png b/img/icons/deck_stats_hero.png new file mode 100644 index 0000000..87f6334 Binary files /dev/null and b/img/icons/deck_stats_hero.png differ diff --git a/img/icons/deck_stats_special.png b/img/icons/deck_stats_special.png new file mode 100644 index 0000000..0575eb3 Binary files /dev/null and b/img/icons/deck_stats_special.png differ diff --git a/img/icons/deck_stats_strength.png b/img/icons/deck_stats_strength.png new file mode 100644 index 0000000..f168ffb Binary files /dev/null and b/img/icons/deck_stats_strength.png differ diff --git a/img/icons/deck_stats_unit.png b/img/icons/deck_stats_unit.png new file mode 100644 index 0000000..641117f Binary files /dev/null and b/img/icons/deck_stats_unit.png differ diff --git a/img/icons/end_draw.png b/img/icons/end_draw.png new file mode 100644 index 0000000..1197b2f Binary files /dev/null and b/img/icons/end_draw.png differ diff --git a/img/icons/end_lose.png b/img/icons/end_lose.png new file mode 100644 index 0000000..48cd901 Binary files /dev/null and b/img/icons/end_lose.png differ diff --git a/img/icons/end_win.png b/img/icons/end_win.png new file mode 100644 index 0000000..2a3ca79 Binary files /dev/null and b/img/icons/end_win.png differ diff --git a/img/icons/faction-ability.png b/img/icons/faction-ability.png new file mode 100644 index 0000000..2e25628 Binary files /dev/null and b/img/icons/faction-ability.png differ diff --git a/img/icons/faction-band-lyria_rivia.png b/img/icons/faction-band-lyria_rivia.png new file mode 100644 index 0000000..24c05b3 Binary files /dev/null and b/img/icons/faction-band-lyria_rivia.png differ diff --git a/img/icons/faction-band-monsters.png b/img/icons/faction-band-monsters.png new file mode 100644 index 0000000..0a6f939 Binary files /dev/null and b/img/icons/faction-band-monsters.png differ diff --git a/img/icons/faction-band-nilfgaard.png b/img/icons/faction-band-nilfgaard.png new file mode 100644 index 0000000..5110d3b Binary files /dev/null and b/img/icons/faction-band-nilfgaard.png differ diff --git a/img/icons/faction-band-realms.png b/img/icons/faction-band-realms.png new file mode 100644 index 0000000..342a262 Binary files /dev/null and b/img/icons/faction-band-realms.png differ diff --git a/img/icons/faction-band-redania.png b/img/icons/faction-band-redania.png new file mode 100644 index 0000000..7af8179 Binary files /dev/null and b/img/icons/faction-band-redania.png differ diff --git a/img/icons/faction-band-scoiatael.png b/img/icons/faction-band-scoiatael.png new file mode 100644 index 0000000..4a20231 Binary files /dev/null and b/img/icons/faction-band-scoiatael.png differ diff --git a/img/icons/faction-band-skellige.png b/img/icons/faction-band-skellige.png new file mode 100644 index 0000000..47a96f7 Binary files /dev/null and b/img/icons/faction-band-skellige.png differ diff --git a/img/icons/faction-band-syndicate.png b/img/icons/faction-band-syndicate.png new file mode 100644 index 0000000..367695a Binary files /dev/null and b/img/icons/faction-band-syndicate.png differ diff --git a/img/icons/faction-band-toussaint.png b/img/icons/faction-band-toussaint.png new file mode 100644 index 0000000..b57c113 Binary files /dev/null and b/img/icons/faction-band-toussaint.png differ diff --git a/img/icons/faction-band-velen.png b/img/icons/faction-band-velen.png new file mode 100644 index 0000000..ab5e060 Binary files /dev/null and b/img/icons/faction-band-velen.png differ diff --git a/img/icons/faction-band-witcher_universe.png b/img/icons/faction-band-witcher_universe.png new file mode 100644 index 0000000..6bde636 Binary files /dev/null and b/img/icons/faction-band-witcher_universe.png differ diff --git a/img/icons/faction-band-zerrikania.png b/img/icons/faction-band-zerrikania.png new file mode 100644 index 0000000..40bb172 Binary files /dev/null and b/img/icons/faction-band-zerrikania.png differ diff --git a/img/icons/gwent_bottom_bg.png b/img/icons/gwent_bottom_bg.png new file mode 100644 index 0000000..5cccdba Binary files /dev/null and b/img/icons/gwent_bottom_bg.png differ diff --git a/img/icons/icon_card_count.png b/img/icons/icon_card_count.png new file mode 100644 index 0000000..f1815bd Binary files /dev/null and b/img/icons/icon_card_count.png differ diff --git a/img/icons/icon_gem_off.png b/img/icons/icon_gem_off.png new file mode 100644 index 0000000..7d53de4 Binary files /dev/null and b/img/icons/icon_gem_off.png differ diff --git a/img/icons/icon_gem_on.png b/img/icons/icon_gem_on.png new file mode 100644 index 0000000..ccb6996 Binary files /dev/null and b/img/icons/icon_gem_on.png differ diff --git a/img/icons/icon_high_score.png b/img/icons/icon_high_score.png new file mode 100644 index 0000000..89a23d9 Binary files /dev/null and b/img/icons/icon_high_score.png differ diff --git a/img/icons/icon_leader_active.png b/img/icons/icon_leader_active.png new file mode 100644 index 0000000..6a02e71 Binary files /dev/null and b/img/icons/icon_leader_active.png differ diff --git a/img/icons/icon_player_border.png b/img/icons/icon_player_border.png new file mode 100644 index 0000000..0eaaabd Binary files /dev/null and b/img/icons/icon_player_border.png differ diff --git a/img/icons/notif_draw_round.png b/img/icons/notif_draw_round.png new file mode 100644 index 0000000..04b4e9d Binary files /dev/null and b/img/icons/notif_draw_round.png differ diff --git a/img/icons/notif_lose_round.png b/img/icons/notif_lose_round.png new file mode 100644 index 0000000..61d3aaa Binary files /dev/null and b/img/icons/notif_lose_round.png differ diff --git a/img/icons/notif_lyria_rivia.png b/img/icons/notif_lyria_rivia.png new file mode 100644 index 0000000..c1d2ed1 Binary files /dev/null and b/img/icons/notif_lyria_rivia.png differ diff --git a/img/icons/notif_me_coin.png b/img/icons/notif_me_coin.png new file mode 100644 index 0000000..39c9cda Binary files /dev/null and b/img/icons/notif_me_coin.png differ diff --git a/img/icons/notif_me_turn.png b/img/icons/notif_me_turn.png new file mode 100644 index 0000000..e5e4e92 Binary files /dev/null and b/img/icons/notif_me_turn.png differ diff --git a/img/icons/notif_monsters.png b/img/icons/notif_monsters.png new file mode 100644 index 0000000..3e5d838 Binary files /dev/null and b/img/icons/notif_monsters.png differ diff --git a/img/icons/notif_nilfgaard.png b/img/icons/notif_nilfgaard.png new file mode 100644 index 0000000..c7ea431 Binary files /dev/null and b/img/icons/notif_nilfgaard.png differ diff --git a/img/icons/notif_north.png b/img/icons/notif_north.png new file mode 100644 index 0000000..8815ec4 Binary files /dev/null and b/img/icons/notif_north.png differ diff --git a/img/icons/notif_op_coin.png b/img/icons/notif_op_coin.png new file mode 100644 index 0000000..3f1a708 Binary files /dev/null and b/img/icons/notif_op_coin.png differ diff --git a/img/icons/notif_op_turn.png b/img/icons/notif_op_turn.png new file mode 100644 index 0000000..d3fd02a Binary files /dev/null and b/img/icons/notif_op_turn.png differ diff --git a/img/icons/notif_redania.png b/img/icons/notif_redania.png new file mode 100644 index 0000000..1713927 Binary files /dev/null and b/img/icons/notif_redania.png differ diff --git a/img/icons/notif_round_passed.png b/img/icons/notif_round_passed.png new file mode 100644 index 0000000..eaf838d Binary files /dev/null and b/img/icons/notif_round_passed.png differ diff --git a/img/icons/notif_round_start.png b/img/icons/notif_round_start.png new file mode 100644 index 0000000..1ecaeb6 Binary files /dev/null and b/img/icons/notif_round_start.png differ diff --git a/img/icons/notif_scoiatael.png b/img/icons/notif_scoiatael.png new file mode 100644 index 0000000..0b4fd47 Binary files /dev/null and b/img/icons/notif_scoiatael.png differ diff --git a/img/icons/notif_skellige.png b/img/icons/notif_skellige.png new file mode 100644 index 0000000..136973a Binary files /dev/null and b/img/icons/notif_skellige.png differ diff --git a/img/icons/notif_syndicate.png b/img/icons/notif_syndicate.png new file mode 100644 index 0000000..94ba5ed Binary files /dev/null and b/img/icons/notif_syndicate.png differ diff --git a/img/icons/notif_toussaint.png b/img/icons/notif_toussaint.png new file mode 100644 index 0000000..c60ec9e Binary files /dev/null and b/img/icons/notif_toussaint.png differ diff --git a/img/icons/notif_velen.png b/img/icons/notif_velen.png new file mode 100644 index 0000000..8344955 Binary files /dev/null and b/img/icons/notif_velen.png differ diff --git a/img/icons/notif_win_round.png b/img/icons/notif_win_round.png new file mode 100644 index 0000000..918c1d2 Binary files /dev/null and b/img/icons/notif_win_round.png differ diff --git a/img/icons/notif_witcher_universe.png b/img/icons/notif_witcher_universe.png new file mode 100644 index 0000000..e8165ee Binary files /dev/null and b/img/icons/notif_witcher_universe.png differ diff --git a/img/icons/notif_zerrikania.png b/img/icons/notif_zerrikania.png new file mode 100644 index 0000000..1af84b3 Binary files /dev/null and b/img/icons/notif_zerrikania.png differ diff --git a/img/icons/overlay_fog.png b/img/icons/overlay_fog.png new file mode 100644 index 0000000..83701cb Binary files /dev/null and b/img/icons/overlay_fog.png differ diff --git a/img/icons/overlay_frost.png b/img/icons/overlay_frost.png new file mode 100644 index 0000000..5f0e87a Binary files /dev/null and b/img/icons/overlay_frost.png differ diff --git a/img/icons/overlay_rain.png b/img/icons/overlay_rain.png new file mode 100644 index 0000000..173145e Binary files /dev/null and b/img/icons/overlay_rain.png differ diff --git a/img/icons/power_bank.png b/img/icons/power_bank.png new file mode 100644 index 0000000..4b1ce56 Binary files /dev/null and b/img/icons/power_bank.png differ diff --git a/img/icons/power_cintra_slaughter.png b/img/icons/power_cintra_slaughter.png new file mode 100644 index 0000000..abf4624 Binary files /dev/null and b/img/icons/power_cintra_slaughter.png differ diff --git a/img/icons/power_clear.png b/img/icons/power_clear.png new file mode 100644 index 0000000..a30b52f Binary files /dev/null and b/img/icons/power_clear.png differ diff --git a/img/icons/power_curse.png b/img/icons/power_curse.png new file mode 100644 index 0000000..4f2f27d Binary files /dev/null and b/img/icons/power_curse.png differ diff --git a/img/icons/power_decoy.png b/img/icons/power_decoy.png new file mode 100644 index 0000000..896a13e Binary files /dev/null and b/img/icons/power_decoy.png differ diff --git a/img/icons/power_fog.png b/img/icons/power_fog.png new file mode 100644 index 0000000..5a7eb6e Binary files /dev/null and b/img/icons/power_fog.png differ diff --git a/img/icons/power_frost.png b/img/icons/power_frost.png new file mode 100644 index 0000000..8edc397 Binary files /dev/null and b/img/icons/power_frost.png differ diff --git a/img/icons/power_hero.png b/img/icons/power_hero.png new file mode 100644 index 0000000..cfb49ff Binary files /dev/null and b/img/icons/power_hero.png differ diff --git a/img/icons/power_horn.png b/img/icons/power_horn.png new file mode 100644 index 0000000..465af54 Binary files /dev/null and b/img/icons/power_horn.png differ diff --git a/img/icons/power_knockback.png b/img/icons/power_knockback.png new file mode 100644 index 0000000..5083000 Binary files /dev/null and b/img/icons/power_knockback.png differ diff --git a/img/icons/power_lock.png b/img/icons/power_lock.png new file mode 100644 index 0000000..22e7463 Binary files /dev/null and b/img/icons/power_lock.png differ diff --git a/img/icons/power_mardroeme.png b/img/icons/power_mardroeme.png new file mode 100644 index 0000000..5be4bee Binary files /dev/null and b/img/icons/power_mardroeme.png differ diff --git a/img/icons/power_normal.png b/img/icons/power_normal.png new file mode 100644 index 0000000..487820f Binary files /dev/null and b/img/icons/power_normal.png differ diff --git a/img/icons/power_rain.png b/img/icons/power_rain.png new file mode 100644 index 0000000..e7c4cb4 Binary files /dev/null and b/img/icons/power_rain.png differ diff --git a/img/icons/power_royal_decree.png b/img/icons/power_royal_decree.png new file mode 100644 index 0000000..406fa1b Binary files /dev/null and b/img/icons/power_royal_decree.png differ diff --git a/img/icons/power_scorch.png b/img/icons/power_scorch.png new file mode 100644 index 0000000..4acd97e Binary files /dev/null and b/img/icons/power_scorch.png differ diff --git a/img/icons/power_seize.png b/img/icons/power_seize.png new file mode 100644 index 0000000..43dbec2 Binary files /dev/null and b/img/icons/power_seize.png differ diff --git a/img/icons/power_shield.png b/img/icons/power_shield.png new file mode 100644 index 0000000..b7175b1 Binary files /dev/null and b/img/icons/power_shield.png differ diff --git a/img/icons/power_skellige_fleet.png b/img/icons/power_skellige_fleet.png new file mode 100644 index 0000000..38173ff Binary files /dev/null and b/img/icons/power_skellige_fleet.png differ diff --git a/img/icons/power_storm.png b/img/icons/power_storm.png new file mode 100644 index 0000000..a97cc17 Binary files /dev/null and b/img/icons/power_storm.png differ diff --git a/img/icons/power_toussaint_wine.png b/img/icons/power_toussaint_wine.png new file mode 100644 index 0000000..3e60294 Binary files /dev/null and b/img/icons/power_toussaint_wine.png differ diff --git a/img/icons/power_witch_hunt.png b/img/icons/power_witch_hunt.png new file mode 100644 index 0000000..b88320b Binary files /dev/null and b/img/icons/power_witch_hunt.png differ diff --git a/img/icons/preview_count.png b/img/icons/preview_count.png new file mode 100644 index 0000000..7464f30 Binary files /dev/null and b/img/icons/preview_count.png differ diff --git a/img/icons/profile.png b/img/icons/profile.png new file mode 100644 index 0000000..e689a58 Binary files /dev/null and b/img/icons/profile.png differ diff --git a/img/icons/score_total_me.png b/img/icons/score_total_me.png new file mode 100644 index 0000000..e75d1bb Binary files /dev/null and b/img/icons/score_total_me.png differ diff --git a/img/icons/score_total_op.png b/img/icons/score_total_op.png new file mode 100644 index 0000000..96e0872 Binary files /dev/null and b/img/icons/score_total_op.png differ diff --git a/img/lg/faction_monsters.jpg b/img/lg/faction_monsters.jpg new file mode 100644 index 0000000..b60dae7 Binary files /dev/null and b/img/lg/faction_monsters.jpg differ diff --git a/img/lg/faction_nilfgaard.jpg b/img/lg/faction_nilfgaard.jpg new file mode 100644 index 0000000..d22b395 Binary files /dev/null and b/img/lg/faction_nilfgaard.jpg differ diff --git a/img/lg/faction_realms.jpg b/img/lg/faction_realms.jpg new file mode 100644 index 0000000..636d9d7 Binary files /dev/null and b/img/lg/faction_realms.jpg differ diff --git a/img/lg/faction_scoiatael.jpg b/img/lg/faction_scoiatael.jpg new file mode 100644 index 0000000..f13c61c Binary files /dev/null and b/img/lg/faction_scoiatael.jpg differ diff --git a/img/lg/faction_skellige.jpg b/img/lg/faction_skellige.jpg new file mode 100644 index 0000000..0769ea8 Binary files /dev/null and b/img/lg/faction_skellige.jpg differ diff --git a/img/lg/monsters_arachas.jpg b/img/lg/monsters_arachas.jpg new file mode 100644 index 0000000..29ff00b Binary files /dev/null and b/img/lg/monsters_arachas.jpg differ diff --git a/img/lg/monsters_arachas_1.jpg b/img/lg/monsters_arachas_1.jpg new file mode 100644 index 0000000..2d87e1a Binary files /dev/null and b/img/lg/monsters_arachas_1.jpg differ diff --git a/img/lg/monsters_arachas_2.jpg b/img/lg/monsters_arachas_2.jpg new file mode 100644 index 0000000..2a1d67f Binary files /dev/null and b/img/lg/monsters_arachas_2.jpg differ diff --git a/img/lg/monsters_arachas_behemoth.jpg b/img/lg/monsters_arachas_behemoth.jpg new file mode 100644 index 0000000..8fb1c90 Binary files /dev/null and b/img/lg/monsters_arachas_behemoth.jpg differ diff --git a/img/lg/monsters_bruxa.jpg b/img/lg/monsters_bruxa.jpg new file mode 100644 index 0000000..1c72120 Binary files /dev/null and b/img/lg/monsters_bruxa.jpg differ diff --git a/img/lg/monsters_celaeno_harpy.jpg b/img/lg/monsters_celaeno_harpy.jpg new file mode 100644 index 0000000..149866b Binary files /dev/null and b/img/lg/monsters_celaeno_harpy.jpg differ diff --git a/img/lg/monsters_cockatrice.jpg b/img/lg/monsters_cockatrice.jpg new file mode 100644 index 0000000..2a6d8ce Binary files /dev/null and b/img/lg/monsters_cockatrice.jpg differ diff --git a/img/lg/monsters_draug.jpg b/img/lg/monsters_draug.jpg new file mode 100644 index 0000000..53011d1 Binary files /dev/null and b/img/lg/monsters_draug.jpg differ diff --git a/img/lg/monsters_earth_elemental.jpg b/img/lg/monsters_earth_elemental.jpg new file mode 100644 index 0000000..bc2a964 Binary files /dev/null and b/img/lg/monsters_earth_elemental.jpg differ diff --git a/img/lg/monsters_ekkima.jpg b/img/lg/monsters_ekkima.jpg new file mode 100644 index 0000000..e752c67 Binary files /dev/null and b/img/lg/monsters_ekkima.jpg differ diff --git a/img/lg/monsters_endrega.jpg b/img/lg/monsters_endrega.jpg new file mode 100644 index 0000000..0ebc986 Binary files /dev/null and b/img/lg/monsters_endrega.jpg differ diff --git a/img/lg/monsters_eredin_bringer_of_death.jpg b/img/lg/monsters_eredin_bringer_of_death.jpg new file mode 100644 index 0000000..56a5f09 Binary files /dev/null and b/img/lg/monsters_eredin_bringer_of_death.jpg differ diff --git a/img/lg/monsters_eredin_commander.jpg b/img/lg/monsters_eredin_commander.jpg new file mode 100644 index 0000000..b85d26a Binary files /dev/null and b/img/lg/monsters_eredin_commander.jpg differ diff --git a/img/lg/monsters_eredin_destroyer.jpg b/img/lg/monsters_eredin_destroyer.jpg new file mode 100644 index 0000000..d60b4d5 Binary files /dev/null and b/img/lg/monsters_eredin_destroyer.jpg differ diff --git a/img/lg/monsters_eredin_king.jpg b/img/lg/monsters_eredin_king.jpg new file mode 100644 index 0000000..c0f75a5 Binary files /dev/null and b/img/lg/monsters_eredin_king.jpg differ diff --git a/img/lg/monsters_eredin_the_treacherous.jpg b/img/lg/monsters_eredin_the_treacherous.jpg new file mode 100644 index 0000000..48e2b0c Binary files /dev/null and b/img/lg/monsters_eredin_the_treacherous.jpg differ diff --git a/img/lg/monsters_fiend.jpg b/img/lg/monsters_fiend.jpg new file mode 100644 index 0000000..3f86eb1 Binary files /dev/null and b/img/lg/monsters_fiend.jpg differ diff --git a/img/lg/monsters_fire_elemental.jpg b/img/lg/monsters_fire_elemental.jpg new file mode 100644 index 0000000..4912534 Binary files /dev/null and b/img/lg/monsters_fire_elemental.jpg differ diff --git a/img/lg/monsters_fleder.jpg b/img/lg/monsters_fleder.jpg new file mode 100644 index 0000000..5ff0a02 Binary files /dev/null and b/img/lg/monsters_fleder.jpg differ diff --git a/img/lg/monsters_fogling.jpg b/img/lg/monsters_fogling.jpg new file mode 100644 index 0000000..c5d43a2 Binary files /dev/null and b/img/lg/monsters_fogling.jpg differ diff --git a/img/lg/monsters_forktail.jpg b/img/lg/monsters_forktail.jpg new file mode 100644 index 0000000..751be29 Binary files /dev/null and b/img/lg/monsters_forktail.jpg differ diff --git a/img/lg/monsters_frightener.jpg b/img/lg/monsters_frightener.jpg new file mode 100644 index 0000000..26ec4ad Binary files /dev/null and b/img/lg/monsters_frightener.jpg differ diff --git a/img/lg/monsters_frost_giant.jpg b/img/lg/monsters_frost_giant.jpg new file mode 100644 index 0000000..65d8ff8 Binary files /dev/null and b/img/lg/monsters_frost_giant.jpg differ diff --git a/img/lg/monsters_gargoyle.jpg b/img/lg/monsters_gargoyle.jpg new file mode 100644 index 0000000..5f2856a Binary files /dev/null and b/img/lg/monsters_gargoyle.jpg differ diff --git a/img/lg/monsters_garkain.jpg b/img/lg/monsters_garkain.jpg new file mode 100644 index 0000000..3ee48d7 Binary files /dev/null and b/img/lg/monsters_garkain.jpg differ diff --git a/img/lg/monsters_ghoul.jpg b/img/lg/monsters_ghoul.jpg new file mode 100644 index 0000000..4310a07 Binary files /dev/null and b/img/lg/monsters_ghoul.jpg differ diff --git a/img/lg/monsters_ghoul_1.jpg b/img/lg/monsters_ghoul_1.jpg new file mode 100644 index 0000000..c45fcd5 Binary files /dev/null and b/img/lg/monsters_ghoul_1.jpg differ diff --git a/img/lg/monsters_ghoul_2.jpg b/img/lg/monsters_ghoul_2.jpg new file mode 100644 index 0000000..850f3da Binary files /dev/null and b/img/lg/monsters_ghoul_2.jpg differ diff --git a/img/lg/monsters_gravehag.jpg b/img/lg/monsters_gravehag.jpg new file mode 100644 index 0000000..2ad1987 Binary files /dev/null and b/img/lg/monsters_gravehag.jpg differ diff --git a/img/lg/monsters_gryffin.jpg b/img/lg/monsters_gryffin.jpg new file mode 100644 index 0000000..3233bcd Binary files /dev/null and b/img/lg/monsters_gryffin.jpg differ diff --git a/img/lg/monsters_harpy.jpg b/img/lg/monsters_harpy.jpg new file mode 100644 index 0000000..c6dd447 Binary files /dev/null and b/img/lg/monsters_harpy.jpg differ diff --git a/img/lg/monsters_imlerith.jpg b/img/lg/monsters_imlerith.jpg new file mode 100644 index 0000000..9a64173 Binary files /dev/null and b/img/lg/monsters_imlerith.jpg differ diff --git a/img/lg/monsters_katakan.jpg b/img/lg/monsters_katakan.jpg new file mode 100644 index 0000000..e24517a Binary files /dev/null and b/img/lg/monsters_katakan.jpg differ diff --git a/img/lg/monsters_kayran.jpg b/img/lg/monsters_kayran.jpg new file mode 100644 index 0000000..2a09f10 Binary files /dev/null and b/img/lg/monsters_kayran.jpg differ diff --git a/img/lg/monsters_leshen.jpg b/img/lg/monsters_leshen.jpg new file mode 100644 index 0000000..a28a442 Binary files /dev/null and b/img/lg/monsters_leshen.jpg differ diff --git a/img/lg/monsters_mighty_maiden.jpg b/img/lg/monsters_mighty_maiden.jpg new file mode 100644 index 0000000..91cabef Binary files /dev/null and b/img/lg/monsters_mighty_maiden.jpg differ diff --git a/img/lg/monsters_nekker.jpg b/img/lg/monsters_nekker.jpg new file mode 100644 index 0000000..1870c56 Binary files /dev/null and b/img/lg/monsters_nekker.jpg differ diff --git a/img/lg/monsters_nekker_1.jpg b/img/lg/monsters_nekker_1.jpg new file mode 100644 index 0000000..b46d2d1 Binary files /dev/null and b/img/lg/monsters_nekker_1.jpg differ diff --git a/img/lg/monsters_nekker_2.jpg b/img/lg/monsters_nekker_2.jpg new file mode 100644 index 0000000..0ea6517 Binary files /dev/null and b/img/lg/monsters_nekker_2.jpg differ diff --git a/img/lg/monsters_poroniec.jpg b/img/lg/monsters_poroniec.jpg new file mode 100644 index 0000000..0d8eb81 Binary files /dev/null and b/img/lg/monsters_poroniec.jpg differ diff --git a/img/lg/monsters_toad.jpg b/img/lg/monsters_toad.jpg new file mode 100644 index 0000000..b1e64be Binary files /dev/null and b/img/lg/monsters_toad.jpg differ diff --git a/img/lg/monsters_werewolf.jpg b/img/lg/monsters_werewolf.jpg new file mode 100644 index 0000000..5a8782f Binary files /dev/null and b/img/lg/monsters_werewolf.jpg differ diff --git a/img/lg/monsters_witch_velen.jpg b/img/lg/monsters_witch_velen.jpg new file mode 100644 index 0000000..06eb634 Binary files /dev/null and b/img/lg/monsters_witch_velen.jpg differ diff --git a/img/lg/monsters_witch_velen_1.jpg b/img/lg/monsters_witch_velen_1.jpg new file mode 100644 index 0000000..ed6d90d Binary files /dev/null and b/img/lg/monsters_witch_velen_1.jpg differ diff --git a/img/lg/monsters_witch_velen_2.jpg b/img/lg/monsters_witch_velen_2.jpg new file mode 100644 index 0000000..ab44753 Binary files /dev/null and b/img/lg/monsters_witch_velen_2.jpg differ diff --git a/img/lg/monsters_wyvern.jpg b/img/lg/monsters_wyvern.jpg new file mode 100644 index 0000000..1501110 Binary files /dev/null and b/img/lg/monsters_wyvern.jpg differ diff --git a/img/lg/neutral_chort.jpg b/img/lg/neutral_chort.jpg new file mode 100644 index 0000000..3b23dd1 Binary files /dev/null and b/img/lg/neutral_chort.jpg differ diff --git a/img/lg/neutral_ciri.jpg b/img/lg/neutral_ciri.jpg new file mode 100644 index 0000000..a9558d8 Binary files /dev/null and b/img/lg/neutral_ciri.jpg differ diff --git a/img/lg/neutral_cow.jpg b/img/lg/neutral_cow.jpg new file mode 100644 index 0000000..7d49404 Binary files /dev/null and b/img/lg/neutral_cow.jpg differ diff --git a/img/lg/neutral_dandelion.jpg b/img/lg/neutral_dandelion.jpg new file mode 100644 index 0000000..ea1e59b Binary files /dev/null and b/img/lg/neutral_dandelion.jpg differ diff --git a/img/lg/neutral_emiel.jpg b/img/lg/neutral_emiel.jpg new file mode 100644 index 0000000..4e0b70e Binary files /dev/null and b/img/lg/neutral_emiel.jpg differ diff --git a/img/lg/neutral_gaunter_odimm.jpg b/img/lg/neutral_gaunter_odimm.jpg new file mode 100644 index 0000000..4c121de Binary files /dev/null and b/img/lg/neutral_gaunter_odimm.jpg differ diff --git a/img/lg/neutral_gaunter_odimm_darkness.jpg b/img/lg/neutral_gaunter_odimm_darkness.jpg new file mode 100644 index 0000000..0741ec6 Binary files /dev/null and b/img/lg/neutral_gaunter_odimm_darkness.jpg differ diff --git a/img/lg/neutral_geralt.jpg b/img/lg/neutral_geralt.jpg new file mode 100644 index 0000000..4c6bba5 Binary files /dev/null and b/img/lg/neutral_geralt.jpg differ diff --git a/img/lg/neutral_mysterious_elf.jpg b/img/lg/neutral_mysterious_elf.jpg new file mode 100644 index 0000000..1fd74d1 Binary files /dev/null and b/img/lg/neutral_mysterious_elf.jpg differ diff --git a/img/lg/neutral_olgierd.jpg b/img/lg/neutral_olgierd.jpg new file mode 100644 index 0000000..e8fb000 Binary files /dev/null and b/img/lg/neutral_olgierd.jpg differ diff --git a/img/lg/neutral_triss.jpg b/img/lg/neutral_triss.jpg new file mode 100644 index 0000000..25f3d33 Binary files /dev/null and b/img/lg/neutral_triss.jpg differ diff --git a/img/lg/neutral_vesemir.jpg b/img/lg/neutral_vesemir.jpg new file mode 100644 index 0000000..c757548 Binary files /dev/null and b/img/lg/neutral_vesemir.jpg differ diff --git a/img/lg/neutral_villen.jpg b/img/lg/neutral_villen.jpg new file mode 100644 index 0000000..947b720 Binary files /dev/null and b/img/lg/neutral_villen.jpg differ diff --git a/img/lg/neutral_yennefer.jpg b/img/lg/neutral_yennefer.jpg new file mode 100644 index 0000000..21149da Binary files /dev/null and b/img/lg/neutral_yennefer.jpg differ diff --git a/img/lg/neutral_zoltan.jpg b/img/lg/neutral_zoltan.jpg new file mode 100644 index 0000000..088f27e Binary files /dev/null and b/img/lg/neutral_zoltan.jpg differ diff --git a/img/lg/nilfgaard_albrich.jpg b/img/lg/nilfgaard_albrich.jpg new file mode 100644 index 0000000..bac3a0b Binary files /dev/null and b/img/lg/nilfgaard_albrich.jpg differ diff --git a/img/lg/nilfgaard_archer_support.jpg b/img/lg/nilfgaard_archer_support.jpg new file mode 100644 index 0000000..f1eb0a2 Binary files /dev/null and b/img/lg/nilfgaard_archer_support.jpg differ diff --git a/img/lg/nilfgaard_archer_support_1.jpg b/img/lg/nilfgaard_archer_support_1.jpg new file mode 100644 index 0000000..a67c71c Binary files /dev/null and b/img/lg/nilfgaard_archer_support_1.jpg differ diff --git a/img/lg/nilfgaard_assire.jpg b/img/lg/nilfgaard_assire.jpg new file mode 100644 index 0000000..009854f Binary files /dev/null and b/img/lg/nilfgaard_assire.jpg differ diff --git a/img/lg/nilfgaard_black_archer.jpg b/img/lg/nilfgaard_black_archer.jpg new file mode 100644 index 0000000..9c2d484 Binary files /dev/null and b/img/lg/nilfgaard_black_archer.jpg differ diff --git a/img/lg/nilfgaard_black_archer_1.jpg b/img/lg/nilfgaard_black_archer_1.jpg new file mode 100644 index 0000000..b956b9f Binary files /dev/null and b/img/lg/nilfgaard_black_archer_1.jpg differ diff --git a/img/lg/nilfgaard_cahir.jpg b/img/lg/nilfgaard_cahir.jpg new file mode 100644 index 0000000..736299b Binary files /dev/null and b/img/lg/nilfgaard_cahir.jpg differ diff --git a/img/lg/nilfgaard_cynthia.jpg b/img/lg/nilfgaard_cynthia.jpg new file mode 100644 index 0000000..101cc09 Binary files /dev/null and b/img/lg/nilfgaard_cynthia.jpg differ diff --git a/img/lg/nilfgaard_emhyr_emperor.jpg b/img/lg/nilfgaard_emhyr_emperor.jpg new file mode 100644 index 0000000..9b089f9 Binary files /dev/null and b/img/lg/nilfgaard_emhyr_emperor.jpg differ diff --git a/img/lg/nilfgaard_emhyr_imperial.jpg b/img/lg/nilfgaard_emhyr_imperial.jpg new file mode 100644 index 0000000..e62836c Binary files /dev/null and b/img/lg/nilfgaard_emhyr_imperial.jpg differ diff --git a/img/lg/nilfgaard_emhyr_invader_of_the_north.jpg b/img/lg/nilfgaard_emhyr_invader_of_the_north.jpg new file mode 100644 index 0000000..bcb0279 Binary files /dev/null and b/img/lg/nilfgaard_emhyr_invader_of_the_north.jpg differ diff --git a/img/lg/nilfgaard_emhyr_relentless.jpg b/img/lg/nilfgaard_emhyr_relentless.jpg new file mode 100644 index 0000000..68c968d Binary files /dev/null and b/img/lg/nilfgaard_emhyr_relentless.jpg differ diff --git a/img/lg/nilfgaard_emhyr_whiteflame.jpg b/img/lg/nilfgaard_emhyr_whiteflame.jpg new file mode 100644 index 0000000..1d70839 Binary files /dev/null and b/img/lg/nilfgaard_emhyr_whiteflame.jpg differ diff --git a/img/lg/nilfgaard_fringilla.jpg b/img/lg/nilfgaard_fringilla.jpg new file mode 100644 index 0000000..1b925eb Binary files /dev/null and b/img/lg/nilfgaard_fringilla.jpg differ diff --git a/img/lg/nilfgaard_heavy_zerri.jpg b/img/lg/nilfgaard_heavy_zerri.jpg new file mode 100644 index 0000000..2514c80 Binary files /dev/null and b/img/lg/nilfgaard_heavy_zerri.jpg differ diff --git a/img/lg/nilfgaard_imperal_brigade_1.jpg b/img/lg/nilfgaard_imperal_brigade_1.jpg new file mode 100644 index 0000000..523a150 Binary files /dev/null and b/img/lg/nilfgaard_imperal_brigade_1.jpg differ diff --git a/img/lg/nilfgaard_imperal_brigade_2.jpg b/img/lg/nilfgaard_imperal_brigade_2.jpg new file mode 100644 index 0000000..523a150 Binary files /dev/null and b/img/lg/nilfgaard_imperal_brigade_2.jpg differ diff --git a/img/lg/nilfgaard_imperal_brigade_3.jpg b/img/lg/nilfgaard_imperal_brigade_3.jpg new file mode 100644 index 0000000..523a150 Binary files /dev/null and b/img/lg/nilfgaard_imperal_brigade_3.jpg differ diff --git a/img/lg/nilfgaard_imperal_brigade_4.jpg b/img/lg/nilfgaard_imperal_brigade_4.jpg new file mode 100644 index 0000000..523a150 Binary files /dev/null and b/img/lg/nilfgaard_imperal_brigade_4.jpg differ diff --git a/img/lg/nilfgaard_letho.jpg b/img/lg/nilfgaard_letho.jpg new file mode 100644 index 0000000..2b12db2 Binary files /dev/null and b/img/lg/nilfgaard_letho.jpg differ diff --git a/img/lg/nilfgaard_menno.jpg b/img/lg/nilfgaard_menno.jpg new file mode 100644 index 0000000..f2deef6 Binary files /dev/null and b/img/lg/nilfgaard_menno.jpg differ diff --git a/img/lg/nilfgaard_moorvran.jpg b/img/lg/nilfgaard_moorvran.jpg new file mode 100644 index 0000000..812f423 Binary files /dev/null and b/img/lg/nilfgaard_moorvran.jpg differ diff --git a/img/lg/nilfgaard_morteisen.jpg b/img/lg/nilfgaard_morteisen.jpg new file mode 100644 index 0000000..ff80b34 Binary files /dev/null and b/img/lg/nilfgaard_morteisen.jpg differ diff --git a/img/lg/nilfgaard_nauzicaa_1.jpg b/img/lg/nilfgaard_nauzicaa_1.jpg new file mode 100644 index 0000000..37704d5 Binary files /dev/null and b/img/lg/nilfgaard_nauzicaa_1.jpg differ diff --git a/img/lg/nilfgaard_nauzicaa_2.jpg b/img/lg/nilfgaard_nauzicaa_2.jpg new file mode 100644 index 0000000..37704d5 Binary files /dev/null and b/img/lg/nilfgaard_nauzicaa_2.jpg differ diff --git a/img/lg/nilfgaard_nauzicaa_3.jpg b/img/lg/nilfgaard_nauzicaa_3.jpg new file mode 100644 index 0000000..37704d5 Binary files /dev/null and b/img/lg/nilfgaard_nauzicaa_3.jpg differ diff --git a/img/lg/nilfgaard_puttkammer.jpg b/img/lg/nilfgaard_puttkammer.jpg new file mode 100644 index 0000000..87a5328 Binary files /dev/null and b/img/lg/nilfgaard_puttkammer.jpg differ diff --git a/img/lg/nilfgaard_rainfarn.jpg b/img/lg/nilfgaard_rainfarn.jpg new file mode 100644 index 0000000..d800223 Binary files /dev/null and b/img/lg/nilfgaard_rainfarn.jpg differ diff --git a/img/lg/nilfgaard_renuald.jpg b/img/lg/nilfgaard_renuald.jpg new file mode 100644 index 0000000..abe92ba Binary files /dev/null and b/img/lg/nilfgaard_renuald.jpg differ diff --git a/img/lg/nilfgaard_rotten.jpg b/img/lg/nilfgaard_rotten.jpg new file mode 100644 index 0000000..e519468 Binary files /dev/null and b/img/lg/nilfgaard_rotten.jpg differ diff --git a/img/lg/nilfgaard_shilard.jpg b/img/lg/nilfgaard_shilard.jpg new file mode 100644 index 0000000..61a67ce Binary files /dev/null and b/img/lg/nilfgaard_shilard.jpg differ diff --git a/img/lg/nilfgaard_siege_engineer.jpg b/img/lg/nilfgaard_siege_engineer.jpg new file mode 100644 index 0000000..312ee5d Binary files /dev/null and b/img/lg/nilfgaard_siege_engineer.jpg differ diff --git a/img/lg/nilfgaard_siege_support.jpg b/img/lg/nilfgaard_siege_support.jpg new file mode 100644 index 0000000..6c1f7e4 Binary files /dev/null and b/img/lg/nilfgaard_siege_support.jpg differ diff --git a/img/lg/nilfgaard_stefan.jpg b/img/lg/nilfgaard_stefan.jpg new file mode 100644 index 0000000..ea391f4 Binary files /dev/null and b/img/lg/nilfgaard_stefan.jpg differ diff --git a/img/lg/nilfgaard_sweers.jpg b/img/lg/nilfgaard_sweers.jpg new file mode 100644 index 0000000..969d74c Binary files /dev/null and b/img/lg/nilfgaard_sweers.jpg differ diff --git a/img/lg/nilfgaard_tibor.jpg b/img/lg/nilfgaard_tibor.jpg new file mode 100644 index 0000000..77458de Binary files /dev/null and b/img/lg/nilfgaard_tibor.jpg differ diff --git a/img/lg/nilfgaard_vanhemar.jpg b/img/lg/nilfgaard_vanhemar.jpg new file mode 100644 index 0000000..3ca6454 Binary files /dev/null and b/img/lg/nilfgaard_vanhemar.jpg differ diff --git a/img/lg/nilfgaard_vattier.jpg b/img/lg/nilfgaard_vattier.jpg new file mode 100644 index 0000000..cf603fa Binary files /dev/null and b/img/lg/nilfgaard_vattier.jpg differ diff --git a/img/lg/nilfgaard_vreemde.jpg b/img/lg/nilfgaard_vreemde.jpg new file mode 100644 index 0000000..1117d70 Binary files /dev/null and b/img/lg/nilfgaard_vreemde.jpg differ diff --git a/img/lg/nilfgaard_young_emissary_1.jpg b/img/lg/nilfgaard_young_emissary_1.jpg new file mode 100644 index 0000000..ca1dff3 Binary files /dev/null and b/img/lg/nilfgaard_young_emissary_1.jpg differ diff --git a/img/lg/nilfgaard_young_emissary_2.jpg b/img/lg/nilfgaard_young_emissary_2.jpg new file mode 100644 index 0000000..54a2462 Binary files /dev/null and b/img/lg/nilfgaard_young_emissary_2.jpg differ diff --git a/img/lg/nilfgaard_zerri.jpg b/img/lg/nilfgaard_zerri.jpg new file mode 100644 index 0000000..9c36f8e Binary files /dev/null and b/img/lg/nilfgaard_zerri.jpg differ diff --git a/img/lg/realms_ballista.jpg b/img/lg/realms_ballista.jpg new file mode 100644 index 0000000..e4363be Binary files /dev/null and b/img/lg/realms_ballista.jpg differ diff --git a/img/lg/realms_banner_nurse.jpg b/img/lg/realms_banner_nurse.jpg new file mode 100644 index 0000000..68213b1 Binary files /dev/null and b/img/lg/realms_banner_nurse.jpg differ diff --git a/img/lg/realms_blue_stripes_1.jpg b/img/lg/realms_blue_stripes_1.jpg new file mode 100644 index 0000000..79c480e Binary files /dev/null and b/img/lg/realms_blue_stripes_1.jpg differ diff --git a/img/lg/realms_blue_stripes_2.jpg b/img/lg/realms_blue_stripes_2.jpg new file mode 100644 index 0000000..79c480e Binary files /dev/null and b/img/lg/realms_blue_stripes_2.jpg differ diff --git a/img/lg/realms_blue_stripes_3.jpg b/img/lg/realms_blue_stripes_3.jpg new file mode 100644 index 0000000..79c480e Binary files /dev/null and b/img/lg/realms_blue_stripes_3.jpg differ diff --git a/img/lg/realms_catapult_1.jpg b/img/lg/realms_catapult_1.jpg new file mode 100644 index 0000000..e6675a1 Binary files /dev/null and b/img/lg/realms_catapult_1.jpg differ diff --git a/img/lg/realms_catapult_2.jpg b/img/lg/realms_catapult_2.jpg new file mode 100644 index 0000000..e6675a1 Binary files /dev/null and b/img/lg/realms_catapult_2.jpg differ diff --git a/img/lg/realms_crinfrid_1.jpg b/img/lg/realms_crinfrid_1.jpg new file mode 100644 index 0000000..f254f18 Binary files /dev/null and b/img/lg/realms_crinfrid_1.jpg differ diff --git a/img/lg/realms_crinfrid_2.jpg b/img/lg/realms_crinfrid_2.jpg new file mode 100644 index 0000000..f254f18 Binary files /dev/null and b/img/lg/realms_crinfrid_2.jpg differ diff --git a/img/lg/realms_crinfrid_3.jpg b/img/lg/realms_crinfrid_3.jpg new file mode 100644 index 0000000..f254f18 Binary files /dev/null and b/img/lg/realms_crinfrid_3.jpg differ diff --git a/img/lg/realms_dethmold.jpg b/img/lg/realms_dethmold.jpg new file mode 100644 index 0000000..d1c2915 Binary files /dev/null and b/img/lg/realms_dethmold.jpg differ diff --git a/img/lg/realms_dijkstra.jpg b/img/lg/realms_dijkstra.jpg new file mode 100644 index 0000000..b1dc7f9 Binary files /dev/null and b/img/lg/realms_dijkstra.jpg differ diff --git a/img/lg/realms_esterad.jpg b/img/lg/realms_esterad.jpg new file mode 100644 index 0000000..b495829 Binary files /dev/null and b/img/lg/realms_esterad.jpg differ diff --git a/img/lg/realms_foltest_king.jpg b/img/lg/realms_foltest_king.jpg new file mode 100644 index 0000000..176ca66 Binary files /dev/null and b/img/lg/realms_foltest_king.jpg differ diff --git a/img/lg/realms_foltest_lord.jpg b/img/lg/realms_foltest_lord.jpg new file mode 100644 index 0000000..ac49403 Binary files /dev/null and b/img/lg/realms_foltest_lord.jpg differ diff --git a/img/lg/realms_foltest_siegemaster.jpg b/img/lg/realms_foltest_siegemaster.jpg new file mode 100644 index 0000000..9086190 Binary files /dev/null and b/img/lg/realms_foltest_siegemaster.jpg differ diff --git a/img/lg/realms_foltest_son_of_medell.jpg b/img/lg/realms_foltest_son_of_medell.jpg new file mode 100644 index 0000000..b612b18 Binary files /dev/null and b/img/lg/realms_foltest_son_of_medell.jpg differ diff --git a/img/lg/realms_foltest_steelforged.jpg b/img/lg/realms_foltest_steelforged.jpg new file mode 100644 index 0000000..8c576c0 Binary files /dev/null and b/img/lg/realms_foltest_steelforged.jpg differ diff --git a/img/lg/realms_kaedwen_siege.jpg b/img/lg/realms_kaedwen_siege.jpg new file mode 100644 index 0000000..3832923 Binary files /dev/null and b/img/lg/realms_kaedwen_siege.jpg differ diff --git a/img/lg/realms_kaedwen_siege_1.jpg b/img/lg/realms_kaedwen_siege_1.jpg new file mode 100644 index 0000000..0270e2e Binary files /dev/null and b/img/lg/realms_kaedwen_siege_1.jpg differ diff --git a/img/lg/realms_kaedwen_siege_2.jpg b/img/lg/realms_kaedwen_siege_2.jpg new file mode 100644 index 0000000..ceb3bca Binary files /dev/null and b/img/lg/realms_kaedwen_siege_2.jpg differ diff --git a/img/lg/realms_keira.jpg b/img/lg/realms_keira.jpg new file mode 100644 index 0000000..f650e6d Binary files /dev/null and b/img/lg/realms_keira.jpg differ diff --git a/img/lg/realms_natalis.jpg b/img/lg/realms_natalis.jpg new file mode 100644 index 0000000..4679c0f Binary files /dev/null and b/img/lg/realms_natalis.jpg differ diff --git a/img/lg/realms_philippa.jpg b/img/lg/realms_philippa.jpg new file mode 100644 index 0000000..2e03d00 Binary files /dev/null and b/img/lg/realms_philippa.jpg differ diff --git a/img/lg/realms_poor_infantry_1.jpg b/img/lg/realms_poor_infantry_1.jpg new file mode 100644 index 0000000..aba9460 Binary files /dev/null and b/img/lg/realms_poor_infantry_1.jpg differ diff --git a/img/lg/realms_poor_infantry_2.jpg b/img/lg/realms_poor_infantry_2.jpg new file mode 100644 index 0000000..aba9460 Binary files /dev/null and b/img/lg/realms_poor_infantry_2.jpg differ diff --git a/img/lg/realms_poor_infantry_3.jpg b/img/lg/realms_poor_infantry_3.jpg new file mode 100644 index 0000000..aba9460 Binary files /dev/null and b/img/lg/realms_poor_infantry_3.jpg differ diff --git a/img/lg/realms_poor_infantry_4.jpg b/img/lg/realms_poor_infantry_4.jpg new file mode 100644 index 0000000..aba9460 Binary files /dev/null and b/img/lg/realms_poor_infantry_4.jpg differ diff --git a/img/lg/realms_redania.jpg b/img/lg/realms_redania.jpg new file mode 100644 index 0000000..cf8ffad Binary files /dev/null and b/img/lg/realms_redania.jpg differ diff --git a/img/lg/realms_redania_1.jpg b/img/lg/realms_redania_1.jpg new file mode 100644 index 0000000..6861a22 Binary files /dev/null and b/img/lg/realms_redania_1.jpg differ diff --git a/img/lg/realms_sabrina.jpg b/img/lg/realms_sabrina.jpg new file mode 100644 index 0000000..1e00a98 Binary files /dev/null and b/img/lg/realms_sabrina.jpg differ diff --git a/img/lg/realms_sheala.jpg b/img/lg/realms_sheala.jpg new file mode 100644 index 0000000..8e7501f Binary files /dev/null and b/img/lg/realms_sheala.jpg differ diff --git a/img/lg/realms_sheldon.jpg b/img/lg/realms_sheldon.jpg new file mode 100644 index 0000000..fef4993 Binary files /dev/null and b/img/lg/realms_sheldon.jpg differ diff --git a/img/lg/realms_siege_tower.jpg b/img/lg/realms_siege_tower.jpg new file mode 100644 index 0000000..155c826 Binary files /dev/null and b/img/lg/realms_siege_tower.jpg differ diff --git a/img/lg/realms_siegfried.jpg b/img/lg/realms_siegfried.jpg new file mode 100644 index 0000000..31dd2c8 Binary files /dev/null and b/img/lg/realms_siegfried.jpg differ diff --git a/img/lg/realms_stennis.jpg b/img/lg/realms_stennis.jpg new file mode 100644 index 0000000..9d65768 Binary files /dev/null and b/img/lg/realms_stennis.jpg differ diff --git a/img/lg/realms_thaler.jpg b/img/lg/realms_thaler.jpg new file mode 100644 index 0000000..293adcd Binary files /dev/null and b/img/lg/realms_thaler.jpg differ diff --git a/img/lg/realms_trebuchet.jpg b/img/lg/realms_trebuchet.jpg new file mode 100644 index 0000000..f9d461f Binary files /dev/null and b/img/lg/realms_trebuchet.jpg differ diff --git a/img/lg/realms_trebuchet_1.jpg b/img/lg/realms_trebuchet_1.jpg new file mode 100644 index 0000000..676f345 Binary files /dev/null and b/img/lg/realms_trebuchet_1.jpg differ diff --git a/img/lg/realms_vernon.jpg b/img/lg/realms_vernon.jpg new file mode 100644 index 0000000..8bf71a0 Binary files /dev/null and b/img/lg/realms_vernon.jpg differ diff --git a/img/lg/realms_ves.jpg b/img/lg/realms_ves.jpg new file mode 100644 index 0000000..033169f Binary files /dev/null and b/img/lg/realms_ves.jpg differ diff --git a/img/lg/realms_yarpen.jpg b/img/lg/realms_yarpen.jpg new file mode 100644 index 0000000..0ba8624 Binary files /dev/null and b/img/lg/realms_yarpen.jpg differ diff --git a/img/lg/scoiatael_barclay.jpg b/img/lg/scoiatael_barclay.jpg new file mode 100644 index 0000000..77fba49 Binary files /dev/null and b/img/lg/scoiatael_barclay.jpg differ diff --git a/img/lg/scoiatael_ciaran.jpg b/img/lg/scoiatael_ciaran.jpg new file mode 100644 index 0000000..aef1643 Binary files /dev/null and b/img/lg/scoiatael_ciaran.jpg differ diff --git a/img/lg/scoiatael_dennis.jpg b/img/lg/scoiatael_dennis.jpg new file mode 100644 index 0000000..8c9ce96 Binary files /dev/null and b/img/lg/scoiatael_dennis.jpg differ diff --git a/img/lg/scoiatael_dol_archer.jpg b/img/lg/scoiatael_dol_archer.jpg new file mode 100644 index 0000000..be385ba Binary files /dev/null and b/img/lg/scoiatael_dol_archer.jpg differ diff --git a/img/lg/scoiatael_dol_infantry.jpg b/img/lg/scoiatael_dol_infantry.jpg new file mode 100644 index 0000000..261de69 Binary files /dev/null and b/img/lg/scoiatael_dol_infantry.jpg differ diff --git a/img/lg/scoiatael_dol_infantry_1.jpg b/img/lg/scoiatael_dol_infantry_1.jpg new file mode 100644 index 0000000..551d021 Binary files /dev/null and b/img/lg/scoiatael_dol_infantry_1.jpg differ diff --git a/img/lg/scoiatael_dol_infantry_2.jpg b/img/lg/scoiatael_dol_infantry_2.jpg new file mode 100644 index 0000000..44be2f8 Binary files /dev/null and b/img/lg/scoiatael_dol_infantry_2.jpg differ diff --git a/img/lg/scoiatael_dwarf.jpg b/img/lg/scoiatael_dwarf.jpg new file mode 100644 index 0000000..e971a31 Binary files /dev/null and b/img/lg/scoiatael_dwarf.jpg differ diff --git a/img/lg/scoiatael_dwarf_1.jpg b/img/lg/scoiatael_dwarf_1.jpg new file mode 100644 index 0000000..05616ac Binary files /dev/null and b/img/lg/scoiatael_dwarf_1.jpg differ diff --git a/img/lg/scoiatael_dwarf_2.jpg b/img/lg/scoiatael_dwarf_2.jpg new file mode 100644 index 0000000..3e5e374 Binary files /dev/null and b/img/lg/scoiatael_dwarf_2.jpg differ diff --git a/img/lg/scoiatael_eithne.jpg b/img/lg/scoiatael_eithne.jpg new file mode 100644 index 0000000..541c7ba Binary files /dev/null and b/img/lg/scoiatael_eithne.jpg differ diff --git a/img/lg/scoiatael_elf_skirmisher.jpg b/img/lg/scoiatael_elf_skirmisher.jpg new file mode 100644 index 0000000..14b12af Binary files /dev/null and b/img/lg/scoiatael_elf_skirmisher.jpg differ diff --git a/img/lg/scoiatael_elf_skirmisher_1.jpg b/img/lg/scoiatael_elf_skirmisher_1.jpg new file mode 100644 index 0000000..94ccc50 Binary files /dev/null and b/img/lg/scoiatael_elf_skirmisher_1.jpg differ diff --git a/img/lg/scoiatael_elf_skirmisher_2.jpg b/img/lg/scoiatael_elf_skirmisher_2.jpg new file mode 100644 index 0000000..5ec99f2 Binary files /dev/null and b/img/lg/scoiatael_elf_skirmisher_2.jpg differ diff --git a/img/lg/scoiatael_filavandrel.jpg b/img/lg/scoiatael_filavandrel.jpg new file mode 100644 index 0000000..f79d4c5 Binary files /dev/null and b/img/lg/scoiatael_filavandrel.jpg differ diff --git a/img/lg/scoiatael_francesca_beautiful.jpg b/img/lg/scoiatael_francesca_beautiful.jpg new file mode 100644 index 0000000..d18272a Binary files /dev/null and b/img/lg/scoiatael_francesca_beautiful.jpg differ diff --git a/img/lg/scoiatael_francesca_daisy.jpg b/img/lg/scoiatael_francesca_daisy.jpg new file mode 100644 index 0000000..d7bc989 Binary files /dev/null and b/img/lg/scoiatael_francesca_daisy.jpg differ diff --git a/img/lg/scoiatael_francesca_hope_of_the_aen_seidhe.jpg b/img/lg/scoiatael_francesca_hope_of_the_aen_seidhe.jpg new file mode 100644 index 0000000..d88a7f6 Binary files /dev/null and b/img/lg/scoiatael_francesca_hope_of_the_aen_seidhe.jpg differ diff --git a/img/lg/scoiatael_francesca_pureblood.jpg b/img/lg/scoiatael_francesca_pureblood.jpg new file mode 100644 index 0000000..c57ce05 Binary files /dev/null and b/img/lg/scoiatael_francesca_pureblood.jpg differ diff --git a/img/lg/scoiatael_francesca_queen.jpg b/img/lg/scoiatael_francesca_queen.jpg new file mode 100644 index 0000000..9ef782c Binary files /dev/null and b/img/lg/scoiatael_francesca_queen.jpg differ diff --git a/img/lg/scoiatael_havekar_nurse.jpg b/img/lg/scoiatael_havekar_nurse.jpg new file mode 100644 index 0000000..25df659 Binary files /dev/null and b/img/lg/scoiatael_havekar_nurse.jpg differ diff --git a/img/lg/scoiatael_havekar_nurse_1.jpg b/img/lg/scoiatael_havekar_nurse_1.jpg new file mode 100644 index 0000000..cbdb7a0 Binary files /dev/null and b/img/lg/scoiatael_havekar_nurse_1.jpg differ diff --git a/img/lg/scoiatael_havekar_nurse_2.jpg b/img/lg/scoiatael_havekar_nurse_2.jpg new file mode 100644 index 0000000..cc39d19 Binary files /dev/null and b/img/lg/scoiatael_havekar_nurse_2.jpg differ diff --git a/img/lg/scoiatael_havekar_support.jpg b/img/lg/scoiatael_havekar_support.jpg new file mode 100644 index 0000000..f6b894d Binary files /dev/null and b/img/lg/scoiatael_havekar_support.jpg differ diff --git a/img/lg/scoiatael_havekar_support_1.jpg b/img/lg/scoiatael_havekar_support_1.jpg new file mode 100644 index 0000000..650bf37 Binary files /dev/null and b/img/lg/scoiatael_havekar_support_1.jpg differ diff --git a/img/lg/scoiatael_havekar_support_2.jpg b/img/lg/scoiatael_havekar_support_2.jpg new file mode 100644 index 0000000..73891e9 Binary files /dev/null and b/img/lg/scoiatael_havekar_support_2.jpg differ diff --git a/img/lg/scoiatael_ida.jpg b/img/lg/scoiatael_ida.jpg new file mode 100644 index 0000000..33b66d3 Binary files /dev/null and b/img/lg/scoiatael_ida.jpg differ diff --git a/img/lg/scoiatael_iorveth.jpg b/img/lg/scoiatael_iorveth.jpg new file mode 100644 index 0000000..cd00000 Binary files /dev/null and b/img/lg/scoiatael_iorveth.jpg differ diff --git a/img/lg/scoiatael_isengrim.jpg b/img/lg/scoiatael_isengrim.jpg new file mode 100644 index 0000000..ac83069 Binary files /dev/null and b/img/lg/scoiatael_isengrim.jpg differ diff --git a/img/lg/scoiatael_mahakam.jpg b/img/lg/scoiatael_mahakam.jpg new file mode 100644 index 0000000..5e4a7fb Binary files /dev/null and b/img/lg/scoiatael_mahakam.jpg differ diff --git a/img/lg/scoiatael_mahakam_1.jpg b/img/lg/scoiatael_mahakam_1.jpg new file mode 100644 index 0000000..bf6dbf7 Binary files /dev/null and b/img/lg/scoiatael_mahakam_1.jpg differ diff --git a/img/lg/scoiatael_mahakam_2.jpg b/img/lg/scoiatael_mahakam_2.jpg new file mode 100644 index 0000000..805a7f0 Binary files /dev/null and b/img/lg/scoiatael_mahakam_2.jpg differ diff --git a/img/lg/scoiatael_mahakam_3.jpg b/img/lg/scoiatael_mahakam_3.jpg new file mode 100644 index 0000000..1f2fcd8 Binary files /dev/null and b/img/lg/scoiatael_mahakam_3.jpg differ diff --git a/img/lg/scoiatael_mahakam_4.jpg b/img/lg/scoiatael_mahakam_4.jpg new file mode 100644 index 0000000..103aa9c Binary files /dev/null and b/img/lg/scoiatael_mahakam_4.jpg differ diff --git a/img/lg/scoiatael_milva.jpg b/img/lg/scoiatael_milva.jpg new file mode 100644 index 0000000..3927abe Binary files /dev/null and b/img/lg/scoiatael_milva.jpg differ diff --git a/img/lg/scoiatael_riordain.jpg b/img/lg/scoiatael_riordain.jpg new file mode 100644 index 0000000..d8b41f3 Binary files /dev/null and b/img/lg/scoiatael_riordain.jpg differ diff --git a/img/lg/scoiatael_saskia.jpg b/img/lg/scoiatael_saskia.jpg new file mode 100644 index 0000000..17b5244 Binary files /dev/null and b/img/lg/scoiatael_saskia.jpg differ diff --git a/img/lg/scoiatael_schirru.jpg b/img/lg/scoiatael_schirru.jpg new file mode 100644 index 0000000..861ece3 Binary files /dev/null and b/img/lg/scoiatael_schirru.jpg differ diff --git a/img/lg/scoiatael_toruviel.jpg b/img/lg/scoiatael_toruviel.jpg new file mode 100644 index 0000000..e304d56 Binary files /dev/null and b/img/lg/scoiatael_toruviel.jpg differ diff --git a/img/lg/scoiatael_vrihedd_brigade.jpg b/img/lg/scoiatael_vrihedd_brigade.jpg new file mode 100644 index 0000000..5a1ef87 Binary files /dev/null and b/img/lg/scoiatael_vrihedd_brigade.jpg differ diff --git a/img/lg/scoiatael_vrihedd_brigade_1.jpg b/img/lg/scoiatael_vrihedd_brigade_1.jpg new file mode 100644 index 0000000..669519d Binary files /dev/null and b/img/lg/scoiatael_vrihedd_brigade_1.jpg differ diff --git a/img/lg/scoiatael_vrihedd_cadet.jpg b/img/lg/scoiatael_vrihedd_cadet.jpg new file mode 100644 index 0000000..0e97d20 Binary files /dev/null and b/img/lg/scoiatael_vrihedd_cadet.jpg differ diff --git a/img/lg/scoiatael_yaevinn.jpg b/img/lg/scoiatael_yaevinn.jpg new file mode 100644 index 0000000..a32dab0 Binary files /dev/null and b/img/lg/scoiatael_yaevinn.jpg differ diff --git a/img/lg/skellige_berserker.jpg b/img/lg/skellige_berserker.jpg new file mode 100644 index 0000000..b84b6b3 Binary files /dev/null and b/img/lg/skellige_berserker.jpg differ diff --git a/img/lg/skellige_birna.jpg b/img/lg/skellige_birna.jpg new file mode 100644 index 0000000..b53cd33 Binary files /dev/null and b/img/lg/skellige_birna.jpg differ diff --git a/img/lg/skellige_blueboy.jpg b/img/lg/skellige_blueboy.jpg new file mode 100644 index 0000000..d6aeb2c Binary files /dev/null and b/img/lg/skellige_blueboy.jpg differ diff --git a/img/lg/skellige_brokva_archer.jpg b/img/lg/skellige_brokva_archer.jpg new file mode 100644 index 0000000..c02bab7 Binary files /dev/null and b/img/lg/skellige_brokva_archer.jpg differ diff --git a/img/lg/skellige_cerys.jpg b/img/lg/skellige_cerys.jpg new file mode 100644 index 0000000..3b45c77 Binary files /dev/null and b/img/lg/skellige_cerys.jpg differ diff --git a/img/lg/skellige_crach_an_craite.jpg b/img/lg/skellige_crach_an_craite.jpg new file mode 100644 index 0000000..f4cdb3f Binary files /dev/null and b/img/lg/skellige_crach_an_craite.jpg differ diff --git a/img/lg/skellige_craite_warrior_1.jpg b/img/lg/skellige_craite_warrior_1.jpg new file mode 100644 index 0000000..646e3d9 Binary files /dev/null and b/img/lg/skellige_craite_warrior_1.jpg differ diff --git a/img/lg/skellige_craite_warrior_2.jpg b/img/lg/skellige_craite_warrior_2.jpg new file mode 100644 index 0000000..646e3d9 Binary files /dev/null and b/img/lg/skellige_craite_warrior_2.jpg differ diff --git a/img/lg/skellige_craite_warrior_3.jpg b/img/lg/skellige_craite_warrior_3.jpg new file mode 100644 index 0000000..646e3d9 Binary files /dev/null and b/img/lg/skellige_craite_warrior_3.jpg differ diff --git a/img/lg/skellige_dimun_pirate.jpg b/img/lg/skellige_dimun_pirate.jpg new file mode 100644 index 0000000..bbfb2eb Binary files /dev/null and b/img/lg/skellige_dimun_pirate.jpg differ diff --git a/img/lg/skellige_donar.jpg b/img/lg/skellige_donar.jpg new file mode 100644 index 0000000..f35961a Binary files /dev/null and b/img/lg/skellige_donar.jpg differ diff --git a/img/lg/skellige_draig.jpg b/img/lg/skellige_draig.jpg new file mode 100644 index 0000000..bd3b9fb Binary files /dev/null and b/img/lg/skellige_draig.jpg differ diff --git a/img/lg/skellige_ermion.jpg b/img/lg/skellige_ermion.jpg new file mode 100644 index 0000000..63b34b3 Binary files /dev/null and b/img/lg/skellige_ermion.jpg differ diff --git a/img/lg/skellige_hemdall.jpg b/img/lg/skellige_hemdall.jpg new file mode 100644 index 0000000..5372877 Binary files /dev/null and b/img/lg/skellige_hemdall.jpg differ diff --git a/img/lg/skellige_heymaey.jpg b/img/lg/skellige_heymaey.jpg new file mode 100644 index 0000000..7cb075b Binary files /dev/null and b/img/lg/skellige_heymaey.jpg differ diff --git a/img/lg/skellige_hjalmar.jpg b/img/lg/skellige_hjalmar.jpg new file mode 100644 index 0000000..da33c5d Binary files /dev/null and b/img/lg/skellige_hjalmar.jpg differ diff --git a/img/lg/skellige_holger.jpg b/img/lg/skellige_holger.jpg new file mode 100644 index 0000000..ed39de6 Binary files /dev/null and b/img/lg/skellige_holger.jpg differ diff --git a/img/lg/skellige_kambi.jpg b/img/lg/skellige_kambi.jpg new file mode 100644 index 0000000..ec8415b Binary files /dev/null and b/img/lg/skellige_kambi.jpg differ diff --git a/img/lg/skellige_king_bran.jpg b/img/lg/skellige_king_bran.jpg new file mode 100644 index 0000000..f9710c8 Binary files /dev/null and b/img/lg/skellige_king_bran.jpg differ diff --git a/img/lg/skellige_light_longship.jpg b/img/lg/skellige_light_longship.jpg new file mode 100644 index 0000000..d27b834 Binary files /dev/null and b/img/lg/skellige_light_longship.jpg differ diff --git a/img/lg/skellige_madmad_lugos.jpg b/img/lg/skellige_madmad_lugos.jpg new file mode 100644 index 0000000..316e58e Binary files /dev/null and b/img/lg/skellige_madmad_lugos.jpg differ diff --git a/img/lg/skellige_olaf.jpg b/img/lg/skellige_olaf.jpg new file mode 100644 index 0000000..9c906df Binary files /dev/null and b/img/lg/skellige_olaf.jpg differ diff --git a/img/lg/skellige_shield_maiden_1.jpg b/img/lg/skellige_shield_maiden_1.jpg new file mode 100644 index 0000000..bb11fd9 Binary files /dev/null and b/img/lg/skellige_shield_maiden_1.jpg differ diff --git a/img/lg/skellige_shield_maiden_2.jpg b/img/lg/skellige_shield_maiden_2.jpg new file mode 100644 index 0000000..d9af66f Binary files /dev/null and b/img/lg/skellige_shield_maiden_2.jpg differ diff --git a/img/lg/skellige_shield_maiden_3.jpg b/img/lg/skellige_shield_maiden_3.jpg new file mode 100644 index 0000000..8ab34ad Binary files /dev/null and b/img/lg/skellige_shield_maiden_3.jpg differ diff --git a/img/lg/skellige_svanrige.jpg b/img/lg/skellige_svanrige.jpg new file mode 100644 index 0000000..984323b Binary files /dev/null and b/img/lg/skellige_svanrige.jpg differ diff --git a/img/lg/skellige_tordarroch.jpg b/img/lg/skellige_tordarroch.jpg new file mode 100644 index 0000000..3e2cde8 Binary files /dev/null and b/img/lg/skellige_tordarroch.jpg differ diff --git a/img/lg/skellige_udalryk.jpg b/img/lg/skellige_udalryk.jpg new file mode 100644 index 0000000..4ffb5ac Binary files /dev/null and b/img/lg/skellige_udalryk.jpg differ diff --git a/img/lg/skellige_vildkaarl.jpg b/img/lg/skellige_vildkaarl.jpg new file mode 100644 index 0000000..6103b2d Binary files /dev/null and b/img/lg/skellige_vildkaarl.jpg differ diff --git a/img/lg/skellige_war_longship_1.jpg b/img/lg/skellige_war_longship_1.jpg new file mode 100644 index 0000000..92de144 Binary files /dev/null and b/img/lg/skellige_war_longship_1.jpg differ diff --git a/img/lg/skellige_war_longship_2.jpg b/img/lg/skellige_war_longship_2.jpg new file mode 100644 index 0000000..92de144 Binary files /dev/null and b/img/lg/skellige_war_longship_2.jpg differ diff --git a/img/lg/skellige_young_berserker.jpg b/img/lg/skellige_young_berserker.jpg new file mode 100644 index 0000000..9e79326 Binary files /dev/null and b/img/lg/skellige_young_berserker.jpg differ diff --git a/img/lg/skellige_young_vildkaarl.jpg b/img/lg/skellige_young_vildkaarl.jpg new file mode 100644 index 0000000..9ece87d Binary files /dev/null and b/img/lg/skellige_young_vildkaarl.jpg differ diff --git a/img/lg/special_decoy.jpg b/img/lg/special_decoy.jpg new file mode 100644 index 0000000..93108ca Binary files /dev/null and b/img/lg/special_decoy.jpg differ diff --git a/img/lg/special_horn.jpg b/img/lg/special_horn.jpg new file mode 100644 index 0000000..83a5791 Binary files /dev/null and b/img/lg/special_horn.jpg differ diff --git a/img/lg/special_mardroeme.jpg b/img/lg/special_mardroeme.jpg new file mode 100644 index 0000000..41b26f5 Binary files /dev/null and b/img/lg/special_mardroeme.jpg differ diff --git a/img/lg/special_scorch.jpg b/img/lg/special_scorch.jpg new file mode 100644 index 0000000..f9d8052 Binary files /dev/null and b/img/lg/special_scorch.jpg differ diff --git a/img/lg/weather_clear.jpg b/img/lg/weather_clear.jpg new file mode 100644 index 0000000..682ff70 Binary files /dev/null and b/img/lg/weather_clear.jpg differ diff --git a/img/lg/weather_fog.jpg b/img/lg/weather_fog.jpg new file mode 100644 index 0000000..4fcd2e7 Binary files /dev/null and b/img/lg/weather_fog.jpg differ diff --git a/img/lg/weather_frost.jpg b/img/lg/weather_frost.jpg new file mode 100644 index 0000000..1307ff5 Binary files /dev/null and b/img/lg/weather_frost.jpg differ diff --git a/img/lg/weather_rain.jpg b/img/lg/weather_rain.jpg new file mode 100644 index 0000000..e91eb79 Binary files /dev/null and b/img/lg/weather_rain.jpg differ diff --git a/img/lg/weather_storm.jpg b/img/lg/weather_storm.jpg new file mode 100644 index 0000000..dbeaa62 Binary files /dev/null and b/img/lg/weather_storm.jpg differ diff --git a/img/rules/board_layout.jpg b/img/rules/board_layout.jpg new file mode 100644 index 0000000..a7198a2 Binary files /dev/null and b/img/rules/board_layout.jpg differ diff --git a/img/rules/gwent_card_legend.png b/img/rules/gwent_card_legend.png new file mode 100644 index 0000000..3ef8c39 Binary files /dev/null and b/img/rules/gwent_card_legend.png differ diff --git a/img/rules/gwent_card_legend_2.png b/img/rules/gwent_card_legend_2.png new file mode 100644 index 0000000..f323b36 Binary files /dev/null and b/img/rules/gwent_card_legend_2.png differ diff --git a/img/sm/faction_lyria_rivia.jpg b/img/sm/faction_lyria_rivia.jpg new file mode 100644 index 0000000..c5a9219 Binary files /dev/null and b/img/sm/faction_lyria_rivia.jpg differ diff --git a/img/sm/faction_monsters.jpg b/img/sm/faction_monsters.jpg new file mode 100644 index 0000000..b60dae7 Binary files /dev/null and b/img/sm/faction_monsters.jpg differ diff --git a/img/sm/faction_nilfgaard.jpg b/img/sm/faction_nilfgaard.jpg new file mode 100644 index 0000000..d22b395 Binary files /dev/null and b/img/sm/faction_nilfgaard.jpg differ diff --git a/img/sm/faction_random.jpg b/img/sm/faction_random.jpg new file mode 100644 index 0000000..896b6bb Binary files /dev/null and b/img/sm/faction_random.jpg differ diff --git a/img/sm/faction_realms.jpg b/img/sm/faction_realms.jpg new file mode 100644 index 0000000..636d9d7 Binary files /dev/null and b/img/sm/faction_realms.jpg differ diff --git a/img/sm/faction_redania.jpg b/img/sm/faction_redania.jpg new file mode 100644 index 0000000..8377eb8 Binary files /dev/null and b/img/sm/faction_redania.jpg differ diff --git a/img/sm/faction_scoiatael.jpg b/img/sm/faction_scoiatael.jpg new file mode 100644 index 0000000..f13c61c Binary files /dev/null and b/img/sm/faction_scoiatael.jpg differ diff --git a/img/sm/faction_skellige.jpg b/img/sm/faction_skellige.jpg new file mode 100644 index 0000000..0769ea8 Binary files /dev/null and b/img/sm/faction_skellige.jpg differ diff --git a/img/sm/faction_syndicate.jpg b/img/sm/faction_syndicate.jpg new file mode 100644 index 0000000..c365d30 Binary files /dev/null and b/img/sm/faction_syndicate.jpg differ diff --git a/img/sm/faction_toussaint.jpg b/img/sm/faction_toussaint.jpg new file mode 100644 index 0000000..dd41149 Binary files /dev/null and b/img/sm/faction_toussaint.jpg differ diff --git a/img/sm/faction_velen.jpg b/img/sm/faction_velen.jpg new file mode 100644 index 0000000..395383c Binary files /dev/null and b/img/sm/faction_velen.jpg differ diff --git a/img/sm/faction_witcher_universe.jpg b/img/sm/faction_witcher_universe.jpg new file mode 100644 index 0000000..2c5fdad Binary files /dev/null and b/img/sm/faction_witcher_universe.jpg differ diff --git a/img/sm/faction_zerrikania.jpg b/img/sm/faction_zerrikania.jpg new file mode 100644 index 0000000..c6f3033 Binary files /dev/null and b/img/sm/faction_zerrikania.jpg differ diff --git a/img/sm/monsters_arachas.jpg b/img/sm/monsters_arachas.jpg new file mode 100644 index 0000000..06627fc Binary files /dev/null and b/img/sm/monsters_arachas.jpg differ diff --git a/img/sm/monsters_arachas_1.jpg b/img/sm/monsters_arachas_1.jpg new file mode 100644 index 0000000..08bcc4a Binary files /dev/null and b/img/sm/monsters_arachas_1.jpg differ diff --git a/img/sm/monsters_arachas_2.jpg b/img/sm/monsters_arachas_2.jpg new file mode 100644 index 0000000..bcd01c2 Binary files /dev/null and b/img/sm/monsters_arachas_2.jpg differ diff --git a/img/sm/monsters_arachas_behemoth.jpg b/img/sm/monsters_arachas_behemoth.jpg new file mode 100644 index 0000000..5187f23 Binary files /dev/null and b/img/sm/monsters_arachas_behemoth.jpg differ diff --git a/img/sm/monsters_bovine_defense.jpg b/img/sm/monsters_bovine_defense.jpg new file mode 100644 index 0000000..9b278ba Binary files /dev/null and b/img/sm/monsters_bovine_defense.jpg differ diff --git a/img/sm/monsters_bruxa.jpg b/img/sm/monsters_bruxa.jpg new file mode 100644 index 0000000..6ea7a06 Binary files /dev/null and b/img/sm/monsters_bruxa.jpg differ diff --git a/img/sm/monsters_caranthir.jpg b/img/sm/monsters_caranthir.jpg new file mode 100644 index 0000000..05c9eeb Binary files /dev/null and b/img/sm/monsters_caranthir.jpg differ diff --git a/img/sm/monsters_celaeno_harpy.jpg b/img/sm/monsters_celaeno_harpy.jpg new file mode 100644 index 0000000..2a91485 Binary files /dev/null and b/img/sm/monsters_celaeno_harpy.jpg differ diff --git a/img/sm/monsters_cow.jpg b/img/sm/monsters_cow.jpg new file mode 100644 index 0000000..3ad6e7b Binary files /dev/null and b/img/sm/monsters_cow.jpg differ diff --git a/img/sm/monsters_draug.jpg b/img/sm/monsters_draug.jpg new file mode 100644 index 0000000..8abb155 Binary files /dev/null and b/img/sm/monsters_draug.jpg differ diff --git a/img/sm/monsters_ekkima.jpg b/img/sm/monsters_ekkima.jpg new file mode 100644 index 0000000..bf1452e Binary files /dev/null and b/img/sm/monsters_ekkima.jpg differ diff --git a/img/sm/monsters_eredin_bringer_of_death.jpg b/img/sm/monsters_eredin_bringer_of_death.jpg new file mode 100644 index 0000000..e984811 Binary files /dev/null and b/img/sm/monsters_eredin_bringer_of_death.jpg differ diff --git a/img/sm/monsters_eredin_commander.jpg b/img/sm/monsters_eredin_commander.jpg new file mode 100644 index 0000000..10c6ddb Binary files /dev/null and b/img/sm/monsters_eredin_commander.jpg differ diff --git a/img/sm/monsters_eredin_destroyer.jpg b/img/sm/monsters_eredin_destroyer.jpg new file mode 100644 index 0000000..0b110e9 Binary files /dev/null and b/img/sm/monsters_eredin_destroyer.jpg differ diff --git a/img/sm/monsters_eredin_king.jpg b/img/sm/monsters_eredin_king.jpg new file mode 100644 index 0000000..0947f46 Binary files /dev/null and b/img/sm/monsters_eredin_king.jpg differ diff --git a/img/sm/monsters_eredin_the_treacherous.jpg b/img/sm/monsters_eredin_the_treacherous.jpg new file mode 100644 index 0000000..3a487c2 Binary files /dev/null and b/img/sm/monsters_eredin_the_treacherous.jpg differ diff --git a/img/sm/monsters_fleder.jpg b/img/sm/monsters_fleder.jpg new file mode 100644 index 0000000..31366f5 Binary files /dev/null and b/img/sm/monsters_fleder.jpg differ diff --git a/img/sm/monsters_foglet.jpg b/img/sm/monsters_foglet.jpg new file mode 100644 index 0000000..698b748 Binary files /dev/null and b/img/sm/monsters_foglet.jpg differ diff --git a/img/sm/monsters_forktail.jpg b/img/sm/monsters_forktail.jpg new file mode 100644 index 0000000..1019f24 Binary files /dev/null and b/img/sm/monsters_forktail.jpg differ diff --git a/img/sm/monsters_garkain.jpg b/img/sm/monsters_garkain.jpg new file mode 100644 index 0000000..1faa481 Binary files /dev/null and b/img/sm/monsters_garkain.jpg differ diff --git a/img/sm/monsters_gaunter_odimm.jpg b/img/sm/monsters_gaunter_odimm.jpg new file mode 100644 index 0000000..fad682a Binary files /dev/null and b/img/sm/monsters_gaunter_odimm.jpg differ diff --git a/img/sm/monsters_gaunter_odimm_darkness.jpg b/img/sm/monsters_gaunter_odimm_darkness.jpg new file mode 100644 index 0000000..ad929a8 Binary files /dev/null and b/img/sm/monsters_gaunter_odimm_darkness.jpg differ diff --git a/img/sm/monsters_ghoul.jpg b/img/sm/monsters_ghoul.jpg new file mode 100644 index 0000000..b934cee Binary files /dev/null and b/img/sm/monsters_ghoul.jpg differ diff --git a/img/sm/monsters_gravehag.jpg b/img/sm/monsters_gravehag.jpg new file mode 100644 index 0000000..7f6586c Binary files /dev/null and b/img/sm/monsters_gravehag.jpg differ diff --git a/img/sm/monsters_gryffin.jpg b/img/sm/monsters_gryffin.jpg new file mode 100644 index 0000000..a0abd52 Binary files /dev/null and b/img/sm/monsters_gryffin.jpg differ diff --git a/img/sm/monsters_imlerith.jpg b/img/sm/monsters_imlerith.jpg new file mode 100644 index 0000000..235d7df Binary files /dev/null and b/img/sm/monsters_imlerith.jpg differ diff --git a/img/sm/monsters_katakan.jpg b/img/sm/monsters_katakan.jpg new file mode 100644 index 0000000..9778dc7 Binary files /dev/null and b/img/sm/monsters_katakan.jpg differ diff --git a/img/sm/monsters_kayran.jpg b/img/sm/monsters_kayran.jpg new file mode 100644 index 0000000..f5acb1b Binary files /dev/null and b/img/sm/monsters_kayran.jpg differ diff --git a/img/sm/monsters_leshen.jpg b/img/sm/monsters_leshen.jpg new file mode 100644 index 0000000..6225930 Binary files /dev/null and b/img/sm/monsters_leshen.jpg differ diff --git a/img/sm/monsters_nekker.jpg b/img/sm/monsters_nekker.jpg new file mode 100644 index 0000000..78c3fd9 Binary files /dev/null and b/img/sm/monsters_nekker.jpg differ diff --git a/img/sm/monsters_nekker_1.jpg b/img/sm/monsters_nekker_1.jpg new file mode 100644 index 0000000..c703b7d Binary files /dev/null and b/img/sm/monsters_nekker_1.jpg differ diff --git a/img/sm/monsters_nekker_2.jpg b/img/sm/monsters_nekker_2.jpg new file mode 100644 index 0000000..4ba2b60 Binary files /dev/null and b/img/sm/monsters_nekker_2.jpg differ diff --git a/img/sm/monsters_plague_maiden.jpg b/img/sm/monsters_plague_maiden.jpg new file mode 100644 index 0000000..3ce8f8c Binary files /dev/null and b/img/sm/monsters_plague_maiden.jpg differ diff --git a/img/sm/monsters_toad.jpg b/img/sm/monsters_toad.jpg new file mode 100644 index 0000000..c7d436d Binary files /dev/null and b/img/sm/monsters_toad.jpg differ diff --git a/img/sm/monsters_werewolf.jpg b/img/sm/monsters_werewolf.jpg new file mode 100644 index 0000000..b28d04b Binary files /dev/null and b/img/sm/monsters_werewolf.jpg differ diff --git a/img/sm/monsters_witch_velen.jpg b/img/sm/monsters_witch_velen.jpg new file mode 100644 index 0000000..4008135 Binary files /dev/null and b/img/sm/monsters_witch_velen.jpg differ diff --git a/img/sm/monsters_witch_velen_1.jpg b/img/sm/monsters_witch_velen_1.jpg new file mode 100644 index 0000000..8dbb979 Binary files /dev/null and b/img/sm/monsters_witch_velen_1.jpg differ diff --git a/img/sm/monsters_witch_velen_2.jpg b/img/sm/monsters_witch_velen_2.jpg new file mode 100644 index 0000000..4dbd0e2 Binary files /dev/null and b/img/sm/monsters_witch_velen_2.jpg differ diff --git a/img/sm/monsters_wyvern.jpg b/img/sm/monsters_wyvern.jpg new file mode 100644 index 0000000..39b18d8 Binary files /dev/null and b/img/sm/monsters_wyvern.jpg differ diff --git a/img/sm/nilfgaard_albrich.jpg b/img/sm/nilfgaard_albrich.jpg new file mode 100644 index 0000000..a68751c Binary files /dev/null and b/img/sm/nilfgaard_albrich.jpg differ diff --git a/img/sm/nilfgaard_archer_support.jpg b/img/sm/nilfgaard_archer_support.jpg new file mode 100644 index 0000000..79591f4 Binary files /dev/null and b/img/sm/nilfgaard_archer_support.jpg differ diff --git a/img/sm/nilfgaard_archer_support_1.jpg b/img/sm/nilfgaard_archer_support_1.jpg new file mode 100644 index 0000000..6d5d999 Binary files /dev/null and b/img/sm/nilfgaard_archer_support_1.jpg differ diff --git a/img/sm/nilfgaard_assire.jpg b/img/sm/nilfgaard_assire.jpg new file mode 100644 index 0000000..d1f5b5d Binary files /dev/null and b/img/sm/nilfgaard_assire.jpg differ diff --git a/img/sm/nilfgaard_black_archer.jpg b/img/sm/nilfgaard_black_archer.jpg new file mode 100644 index 0000000..a6340e0 Binary files /dev/null and b/img/sm/nilfgaard_black_archer.jpg differ diff --git a/img/sm/nilfgaard_black_archer_1.jpg b/img/sm/nilfgaard_black_archer_1.jpg new file mode 100644 index 0000000..482d1f7 Binary files /dev/null and b/img/sm/nilfgaard_black_archer_1.jpg differ diff --git a/img/sm/nilfgaard_cahir.jpg b/img/sm/nilfgaard_cahir.jpg new file mode 100644 index 0000000..ea747f7 Binary files /dev/null and b/img/sm/nilfgaard_cahir.jpg differ diff --git a/img/sm/nilfgaard_ciri.jpg b/img/sm/nilfgaard_ciri.jpg new file mode 100644 index 0000000..9c119a8 Binary files /dev/null and b/img/sm/nilfgaard_ciri.jpg differ diff --git a/img/sm/nilfgaard_cynthia.jpg b/img/sm/nilfgaard_cynthia.jpg new file mode 100644 index 0000000..e136c34 Binary files /dev/null and b/img/sm/nilfgaard_cynthia.jpg differ diff --git a/img/sm/nilfgaard_emhyr_emperor.jpg b/img/sm/nilfgaard_emhyr_emperor.jpg new file mode 100644 index 0000000..03fbe81 Binary files /dev/null and b/img/sm/nilfgaard_emhyr_emperor.jpg differ diff --git a/img/sm/nilfgaard_emhyr_imperial.jpg b/img/sm/nilfgaard_emhyr_imperial.jpg new file mode 100644 index 0000000..d832acd Binary files /dev/null and b/img/sm/nilfgaard_emhyr_imperial.jpg differ diff --git a/img/sm/nilfgaard_emhyr_invader_of_the_north.jpg b/img/sm/nilfgaard_emhyr_invader_of_the_north.jpg new file mode 100644 index 0000000..7140c45 Binary files /dev/null and b/img/sm/nilfgaard_emhyr_invader_of_the_north.jpg differ diff --git a/img/sm/nilfgaard_emhyr_relentless.jpg b/img/sm/nilfgaard_emhyr_relentless.jpg new file mode 100644 index 0000000..fd00c62 Binary files /dev/null and b/img/sm/nilfgaard_emhyr_relentless.jpg differ diff --git a/img/sm/nilfgaard_emhyr_whiteflame.jpg b/img/sm/nilfgaard_emhyr_whiteflame.jpg new file mode 100644 index 0000000..2c4b793 Binary files /dev/null and b/img/sm/nilfgaard_emhyr_whiteflame.jpg differ diff --git a/img/sm/nilfgaard_fringilla.jpg b/img/sm/nilfgaard_fringilla.jpg new file mode 100644 index 0000000..36d925c Binary files /dev/null and b/img/sm/nilfgaard_fringilla.jpg differ diff --git a/img/sm/nilfgaard_geralt.jpg b/img/sm/nilfgaard_geralt.jpg new file mode 100644 index 0000000..576912f Binary files /dev/null and b/img/sm/nilfgaard_geralt.jpg differ diff --git a/img/sm/nilfgaard_impera_brigade_1.jpg b/img/sm/nilfgaard_impera_brigade_1.jpg new file mode 100644 index 0000000..5683995 Binary files /dev/null and b/img/sm/nilfgaard_impera_brigade_1.jpg differ diff --git a/img/sm/nilfgaard_impera_brigade_2.jpg b/img/sm/nilfgaard_impera_brigade_2.jpg new file mode 100644 index 0000000..b3ef52a Binary files /dev/null and b/img/sm/nilfgaard_impera_brigade_2.jpg differ diff --git a/img/sm/nilfgaard_impera_brigade_3.jpg b/img/sm/nilfgaard_impera_brigade_3.jpg new file mode 100644 index 0000000..525f023 Binary files /dev/null and b/img/sm/nilfgaard_impera_brigade_3.jpg differ diff --git a/img/sm/nilfgaard_impera_brigade_4.jpg b/img/sm/nilfgaard_impera_brigade_4.jpg new file mode 100644 index 0000000..6ad2eab Binary files /dev/null and b/img/sm/nilfgaard_impera_brigade_4.jpg differ diff --git a/img/sm/nilfgaard_letho.jpg b/img/sm/nilfgaard_letho.jpg new file mode 100644 index 0000000..ff91b60 Binary files /dev/null and b/img/sm/nilfgaard_letho.jpg differ diff --git a/img/sm/nilfgaard_menno.jpg b/img/sm/nilfgaard_menno.jpg new file mode 100644 index 0000000..3b41ab8 Binary files /dev/null and b/img/sm/nilfgaard_menno.jpg differ diff --git a/img/sm/nilfgaard_moorvran.jpg b/img/sm/nilfgaard_moorvran.jpg new file mode 100644 index 0000000..c3e651a Binary files /dev/null and b/img/sm/nilfgaard_moorvran.jpg differ diff --git a/img/sm/nilfgaard_morteisen.jpg b/img/sm/nilfgaard_morteisen.jpg new file mode 100644 index 0000000..cf1fcb4 Binary files /dev/null and b/img/sm/nilfgaard_morteisen.jpg differ diff --git a/img/sm/nilfgaard_nauzicaa_1.jpg b/img/sm/nilfgaard_nauzicaa_1.jpg new file mode 100644 index 0000000..757776d Binary files /dev/null and b/img/sm/nilfgaard_nauzicaa_1.jpg differ diff --git a/img/sm/nilfgaard_nauzicaa_2.jpg b/img/sm/nilfgaard_nauzicaa_2.jpg new file mode 100644 index 0000000..5e42d84 Binary files /dev/null and b/img/sm/nilfgaard_nauzicaa_2.jpg differ diff --git a/img/sm/nilfgaard_nauzicaa_3.jpg b/img/sm/nilfgaard_nauzicaa_3.jpg new file mode 100644 index 0000000..93727a3 Binary files /dev/null and b/img/sm/nilfgaard_nauzicaa_3.jpg differ diff --git a/img/sm/nilfgaard_puttkammer.jpg b/img/sm/nilfgaard_puttkammer.jpg new file mode 100644 index 0000000..352c757 Binary files /dev/null and b/img/sm/nilfgaard_puttkammer.jpg differ diff --git a/img/sm/nilfgaard_renuald.jpg b/img/sm/nilfgaard_renuald.jpg new file mode 100644 index 0000000..6153bff Binary files /dev/null and b/img/sm/nilfgaard_renuald.jpg differ diff --git a/img/sm/nilfgaard_shilard.jpg b/img/sm/nilfgaard_shilard.jpg new file mode 100644 index 0000000..ce698ae Binary files /dev/null and b/img/sm/nilfgaard_shilard.jpg differ diff --git a/img/sm/nilfgaard_stefan.jpg b/img/sm/nilfgaard_stefan.jpg new file mode 100644 index 0000000..a41c4ea Binary files /dev/null and b/img/sm/nilfgaard_stefan.jpg differ diff --git a/img/sm/nilfgaard_tibor.jpg b/img/sm/nilfgaard_tibor.jpg new file mode 100644 index 0000000..f051196 Binary files /dev/null and b/img/sm/nilfgaard_tibor.jpg differ diff --git a/img/sm/nilfgaard_vattier.jpg b/img/sm/nilfgaard_vattier.jpg new file mode 100644 index 0000000..3c44af2 Binary files /dev/null and b/img/sm/nilfgaard_vattier.jpg differ diff --git a/img/sm/nilfgaard_vreemde.jpg b/img/sm/nilfgaard_vreemde.jpg new file mode 100644 index 0000000..0ea098b Binary files /dev/null and b/img/sm/nilfgaard_vreemde.jpg differ diff --git a/img/sm/nilfgaard_yennefer.jpg b/img/sm/nilfgaard_yennefer.jpg new file mode 100644 index 0000000..a62fae6 Binary files /dev/null and b/img/sm/nilfgaard_yennefer.jpg differ diff --git a/img/sm/nilfgaard_young_emissary_1.jpg b/img/sm/nilfgaard_young_emissary_1.jpg new file mode 100644 index 0000000..16ab675 Binary files /dev/null and b/img/sm/nilfgaard_young_emissary_1.jpg differ diff --git a/img/sm/nilfgaard_young_emissary_2.jpg b/img/sm/nilfgaard_young_emissary_2.jpg new file mode 100644 index 0000000..7a80678 Binary files /dev/null and b/img/sm/nilfgaard_young_emissary_2.jpg differ diff --git a/img/sm/realms_ballista_1.jpg b/img/sm/realms_ballista_1.jpg new file mode 100644 index 0000000..078efde Binary files /dev/null and b/img/sm/realms_ballista_1.jpg differ diff --git a/img/sm/realms_ballista_2.jpg b/img/sm/realms_ballista_2.jpg new file mode 100644 index 0000000..c9abb6f Binary files /dev/null and b/img/sm/realms_ballista_2.jpg differ diff --git a/img/sm/realms_banner_nurse.jpg b/img/sm/realms_banner_nurse.jpg new file mode 100644 index 0000000..c733cbd Binary files /dev/null and b/img/sm/realms_banner_nurse.jpg differ diff --git a/img/sm/realms_blue_stripes_1.jpg b/img/sm/realms_blue_stripes_1.jpg new file mode 100644 index 0000000..d53ac6f Binary files /dev/null and b/img/sm/realms_blue_stripes_1.jpg differ diff --git a/img/sm/realms_blue_stripes_2.jpg b/img/sm/realms_blue_stripes_2.jpg new file mode 100644 index 0000000..4dd51bd Binary files /dev/null and b/img/sm/realms_blue_stripes_2.jpg differ diff --git a/img/sm/realms_blue_stripes_3.jpg b/img/sm/realms_blue_stripes_3.jpg new file mode 100644 index 0000000..823cbf3 Binary files /dev/null and b/img/sm/realms_blue_stripes_3.jpg differ diff --git a/img/sm/realms_catapult_1.jpg b/img/sm/realms_catapult_1.jpg new file mode 100644 index 0000000..d05445e Binary files /dev/null and b/img/sm/realms_catapult_1.jpg differ diff --git a/img/sm/realms_catapult_2.jpg b/img/sm/realms_catapult_2.jpg new file mode 100644 index 0000000..778361d Binary files /dev/null and b/img/sm/realms_catapult_2.jpg differ diff --git a/img/sm/realms_ciri.jpg b/img/sm/realms_ciri.jpg new file mode 100644 index 0000000..9c119a8 Binary files /dev/null and b/img/sm/realms_ciri.jpg differ diff --git a/img/sm/realms_crinfrid_1.jpg b/img/sm/realms_crinfrid_1.jpg new file mode 100644 index 0000000..1ff34eb Binary files /dev/null and b/img/sm/realms_crinfrid_1.jpg differ diff --git a/img/sm/realms_crinfrid_2.jpg b/img/sm/realms_crinfrid_2.jpg new file mode 100644 index 0000000..8e97206 Binary files /dev/null and b/img/sm/realms_crinfrid_2.jpg differ diff --git a/img/sm/realms_crinfrid_3.jpg b/img/sm/realms_crinfrid_3.jpg new file mode 100644 index 0000000..666e4a9 Binary files /dev/null and b/img/sm/realms_crinfrid_3.jpg differ diff --git a/img/sm/realms_dandelion.jpg b/img/sm/realms_dandelion.jpg new file mode 100644 index 0000000..885583e Binary files /dev/null and b/img/sm/realms_dandelion.jpg differ diff --git a/img/sm/realms_dijkstra.jpg b/img/sm/realms_dijkstra.jpg new file mode 100644 index 0000000..c6cf524 Binary files /dev/null and b/img/sm/realms_dijkstra.jpg differ diff --git a/img/sm/realms_esterad.jpg b/img/sm/realms_esterad.jpg new file mode 100644 index 0000000..1916711 Binary files /dev/null and b/img/sm/realms_esterad.jpg differ diff --git a/img/sm/realms_foltest_king.jpg b/img/sm/realms_foltest_king.jpg new file mode 100644 index 0000000..991b95c Binary files /dev/null and b/img/sm/realms_foltest_king.jpg differ diff --git a/img/sm/realms_foltest_lord.jpg b/img/sm/realms_foltest_lord.jpg new file mode 100644 index 0000000..3c5ca62 Binary files /dev/null and b/img/sm/realms_foltest_lord.jpg differ diff --git a/img/sm/realms_foltest_siegemaster.jpg b/img/sm/realms_foltest_siegemaster.jpg new file mode 100644 index 0000000..ff4cad8 Binary files /dev/null and b/img/sm/realms_foltest_siegemaster.jpg differ diff --git a/img/sm/realms_foltest_son_of_medell.jpg b/img/sm/realms_foltest_son_of_medell.jpg new file mode 100644 index 0000000..de1b976 Binary files /dev/null and b/img/sm/realms_foltest_son_of_medell.jpg differ diff --git a/img/sm/realms_foltest_steelforged.jpg b/img/sm/realms_foltest_steelforged.jpg new file mode 100644 index 0000000..00ca2c3 Binary files /dev/null and b/img/sm/realms_foltest_steelforged.jpg differ diff --git a/img/sm/realms_geralt.jpg b/img/sm/realms_geralt.jpg new file mode 100644 index 0000000..576912f Binary files /dev/null and b/img/sm/realms_geralt.jpg differ diff --git a/img/sm/realms_kaedwen_siege_1.jpg b/img/sm/realms_kaedwen_siege_1.jpg new file mode 100644 index 0000000..10d25ee Binary files /dev/null and b/img/sm/realms_kaedwen_siege_1.jpg differ diff --git a/img/sm/realms_kaedwen_siege_2.jpg b/img/sm/realms_kaedwen_siege_2.jpg new file mode 100644 index 0000000..06519a6 Binary files /dev/null and b/img/sm/realms_kaedwen_siege_2.jpg differ diff --git a/img/sm/realms_keira.jpg b/img/sm/realms_keira.jpg new file mode 100644 index 0000000..08e6aa3 Binary files /dev/null and b/img/sm/realms_keira.jpg differ diff --git a/img/sm/realms_natalis.jpg b/img/sm/realms_natalis.jpg new file mode 100644 index 0000000..73c9d64 Binary files /dev/null and b/img/sm/realms_natalis.jpg differ diff --git a/img/sm/realms_olgierd.jpg b/img/sm/realms_olgierd.jpg new file mode 100644 index 0000000..a7a0719 Binary files /dev/null and b/img/sm/realms_olgierd.jpg differ diff --git a/img/sm/realms_philippa.jpg b/img/sm/realms_philippa.jpg new file mode 100644 index 0000000..a894271 Binary files /dev/null and b/img/sm/realms_philippa.jpg differ diff --git a/img/sm/realms_poor_infantry_1.jpg b/img/sm/realms_poor_infantry_1.jpg new file mode 100644 index 0000000..48d054c Binary files /dev/null and b/img/sm/realms_poor_infantry_1.jpg differ diff --git a/img/sm/realms_poor_infantry_2.jpg b/img/sm/realms_poor_infantry_2.jpg new file mode 100644 index 0000000..4a261f2 Binary files /dev/null and b/img/sm/realms_poor_infantry_2.jpg differ diff --git a/img/sm/realms_poor_infantry_3.jpg b/img/sm/realms_poor_infantry_3.jpg new file mode 100644 index 0000000..9d1901b Binary files /dev/null and b/img/sm/realms_poor_infantry_3.jpg differ diff --git a/img/sm/realms_sheala.jpg b/img/sm/realms_sheala.jpg new file mode 100644 index 0000000..5e5cab1 Binary files /dev/null and b/img/sm/realms_sheala.jpg differ diff --git a/img/sm/realms_sheldon.jpg b/img/sm/realms_sheldon.jpg new file mode 100644 index 0000000..b15f7e7 Binary files /dev/null and b/img/sm/realms_sheldon.jpg differ diff --git a/img/sm/realms_siege_tower.jpg b/img/sm/realms_siege_tower.jpg new file mode 100644 index 0000000..24451b5 Binary files /dev/null and b/img/sm/realms_siege_tower.jpg differ diff --git a/img/sm/realms_stennis.jpg b/img/sm/realms_stennis.jpg new file mode 100644 index 0000000..d12c965 Binary files /dev/null and b/img/sm/realms_stennis.jpg differ diff --git a/img/sm/realms_thaler.jpg b/img/sm/realms_thaler.jpg new file mode 100644 index 0000000..77119fd Binary files /dev/null and b/img/sm/realms_thaler.jpg differ diff --git a/img/sm/realms_trebuchet.jpg b/img/sm/realms_trebuchet.jpg new file mode 100644 index 0000000..0e1801e Binary files /dev/null and b/img/sm/realms_trebuchet.jpg differ diff --git a/img/sm/realms_triss.jpg b/img/sm/realms_triss.jpg new file mode 100644 index 0000000..67b090c Binary files /dev/null and b/img/sm/realms_triss.jpg differ diff --git a/img/sm/realms_vernon.jpg b/img/sm/realms_vernon.jpg new file mode 100644 index 0000000..39d7945 Binary files /dev/null and b/img/sm/realms_vernon.jpg differ diff --git a/img/sm/realms_ves.jpg b/img/sm/realms_ves.jpg new file mode 100644 index 0000000..7ee9e93 Binary files /dev/null and b/img/sm/realms_ves.jpg differ diff --git a/img/sm/realms_villen.jpg b/img/sm/realms_villen.jpg new file mode 100644 index 0000000..3e6ba1b Binary files /dev/null and b/img/sm/realms_villen.jpg differ diff --git a/img/sm/realms_yennefer.jpg b/img/sm/realms_yennefer.jpg new file mode 100644 index 0000000..a62fae6 Binary files /dev/null and b/img/sm/realms_yennefer.jpg differ diff --git a/img/sm/realms_zoltan.jpg b/img/sm/realms_zoltan.jpg new file mode 100644 index 0000000..2bd6615 Binary files /dev/null and b/img/sm/realms_zoltan.jpg differ diff --git a/img/sm/redania_black_cat_dog.jpg b/img/sm/redania_black_cat_dog.jpg new file mode 100644 index 0000000..4686e2f Binary files /dev/null and b/img/sm/redania_black_cat_dog.jpg differ diff --git a/img/sm/redania_caleb_menge.jpg b/img/sm/redania_caleb_menge.jpg new file mode 100644 index 0000000..ce37141 Binary files /dev/null and b/img/sm/redania_caleb_menge.jpg differ diff --git a/img/sm/redania_caretaker.jpg b/img/sm/redania_caretaker.jpg new file mode 100644 index 0000000..759dbbb Binary files /dev/null and b/img/sm/redania_caretaker.jpg differ diff --git a/img/sm/redania_carlo_varese.jpg b/img/sm/redania_carlo_varese.jpg new file mode 100644 index 0000000..ed77336 Binary files /dev/null and b/img/sm/redania_carlo_varese.jpg differ diff --git a/img/sm/redania_cyprian_wiley.jpg b/img/sm/redania_cyprian_wiley.jpg new file mode 100644 index 0000000..d6ca8c0 Binary files /dev/null and b/img/sm/redania_cyprian_wiley.jpg differ diff --git a/img/sm/redania_cyrus_hemmelfart.jpg b/img/sm/redania_cyrus_hemmelfart.jpg new file mode 100644 index 0000000..7832d42 Binary files /dev/null and b/img/sm/redania_cyrus_hemmelfart.jpg differ diff --git a/img/sm/redania_eternal_fire_priest.jpg b/img/sm/redania_eternal_fire_priest.jpg new file mode 100644 index 0000000..e1909f8 Binary files /dev/null and b/img/sm/redania_eternal_fire_priest.jpg differ diff --git a/img/sm/redania_ewald_borsodi.jpg b/img/sm/redania_ewald_borsodi.jpg new file mode 100644 index 0000000..acb38a8 Binary files /dev/null and b/img/sm/redania_ewald_borsodi.jpg differ diff --git a/img/sm/redania_francis_bedlam.jpg b/img/sm/redania_francis_bedlam.jpg new file mode 100644 index 0000000..a3544da Binary files /dev/null and b/img/sm/redania_francis_bedlam.jpg differ diff --git a/img/sm/redania_gaunter_odimm.jpg b/img/sm/redania_gaunter_odimm.jpg new file mode 100644 index 0000000..fad682a Binary files /dev/null and b/img/sm/redania_gaunter_odimm.jpg differ diff --git a/img/sm/redania_gaunter_odimm_darkness.jpg b/img/sm/redania_gaunter_odimm_darkness.jpg new file mode 100644 index 0000000..ad929a8 Binary files /dev/null and b/img/sm/redania_gaunter_odimm_darkness.jpg differ diff --git a/img/sm/redania_geralt.jpg b/img/sm/redania_geralt.jpg new file mode 100644 index 0000000..576912f Binary files /dev/null and b/img/sm/redania_geralt.jpg differ diff --git a/img/sm/redania_graden.jpg b/img/sm/redania_graden.jpg new file mode 100644 index 0000000..5bc2eeb Binary files /dev/null and b/img/sm/redania_graden.jpg differ diff --git a/img/sm/redania_horst_borsodi.jpg b/img/sm/redania_horst_borsodi.jpg new file mode 100644 index 0000000..1d51434 Binary files /dev/null and b/img/sm/redania_horst_borsodi.jpg differ diff --git a/img/sm/redania_iris_von_everec.jpg b/img/sm/redania_iris_von_everec.jpg new file mode 100644 index 0000000..b224faf Binary files /dev/null and b/img/sm/redania_iris_von_everec.jpg differ diff --git a/img/sm/redania_kurt.jpg b/img/sm/redania_kurt.jpg new file mode 100644 index 0000000..e341a32 Binary files /dev/null and b/img/sm/redania_kurt.jpg differ diff --git a/img/sm/redania_moreelse.jpg b/img/sm/redania_moreelse.jpg new file mode 100644 index 0000000..dc679ef Binary files /dev/null and b/img/sm/redania_moreelse.jpg differ diff --git a/img/sm/redania_nathaniel_pastodi.jpg b/img/sm/redania_nathaniel_pastodi.jpg new file mode 100644 index 0000000..af93ce3 Binary files /dev/null and b/img/sm/redania_nathaniel_pastodi.jpg differ diff --git a/img/sm/redania_olgierd.jpg b/img/sm/redania_olgierd.jpg new file mode 100644 index 0000000..b3f8b92 Binary files /dev/null and b/img/sm/redania_olgierd.jpg differ diff --git a/img/sm/redania_priscilla.jpg b/img/sm/redania_priscilla.jpg new file mode 100644 index 0000000..349c36b Binary files /dev/null and b/img/sm/redania_priscilla.jpg differ diff --git a/img/sm/redania_radovid_king_redania.jpg b/img/sm/redania_radovid_king_redania.jpg new file mode 100644 index 0000000..82651c1 Binary files /dev/null and b/img/sm/redania_radovid_king_redania.jpg differ diff --git a/img/sm/redania_radovid_mad_king.jpg b/img/sm/redania_radovid_mad_king.jpg new file mode 100644 index 0000000..07a7e0f Binary files /dev/null and b/img/sm/redania_radovid_mad_king.jpg differ diff --git a/img/sm/redania_radovid_strategist.jpg b/img/sm/redania_radovid_strategist.jpg new file mode 100644 index 0000000..efcf432 Binary files /dev/null and b/img/sm/redania_radovid_strategist.jpg differ diff --git a/img/sm/redania_redanian_elite.jpg b/img/sm/redania_redanian_elite.jpg new file mode 100644 index 0000000..714d766 Binary files /dev/null and b/img/sm/redania_redanian_elite.jpg differ diff --git a/img/sm/redania_redanian_knight_1.jpg b/img/sm/redania_redanian_knight_1.jpg new file mode 100644 index 0000000..781f1cc Binary files /dev/null and b/img/sm/redania_redanian_knight_1.jpg differ diff --git a/img/sm/redania_redanian_knight_2.jpg b/img/sm/redania_redanian_knight_2.jpg new file mode 100644 index 0000000..9af933d Binary files /dev/null and b/img/sm/redania_redanian_knight_2.jpg differ diff --git a/img/sm/redania_rico_meiersdorf.jpg b/img/sm/redania_rico_meiersdorf.jpg new file mode 100644 index 0000000..66bb95e Binary files /dev/null and b/img/sm/redania_rico_meiersdorf.jpg differ diff --git a/img/sm/redania_shani.jpg b/img/sm/redania_shani.jpg new file mode 100644 index 0000000..0367e0f Binary files /dev/null and b/img/sm/redania_shani.jpg differ diff --git a/img/sm/redania_sigi_reuven.jpg b/img/sm/redania_sigi_reuven.jpg new file mode 100644 index 0000000..994adad Binary files /dev/null and b/img/sm/redania_sigi_reuven.jpg differ diff --git a/img/sm/redania_trollololo.jpg b/img/sm/redania_trollololo.jpg new file mode 100644 index 0000000..7580492 Binary files /dev/null and b/img/sm/redania_trollololo.jpg differ diff --git a/img/sm/redania_vlodimir_von_everec.jpg b/img/sm/redania_vlodimir_von_everec.jpg new file mode 100644 index 0000000..dc7d14d Binary files /dev/null and b/img/sm/redania_vlodimir_von_everec.jpg differ diff --git a/img/sm/redania_witch_hunter.jpg b/img/sm/redania_witch_hunter.jpg new file mode 100644 index 0000000..c4804ea Binary files /dev/null and b/img/sm/redania_witch_hunter.jpg differ diff --git a/img/sm/scoiatael_barclay.jpg b/img/sm/scoiatael_barclay.jpg new file mode 100644 index 0000000..785861b Binary files /dev/null and b/img/sm/scoiatael_barclay.jpg differ diff --git a/img/sm/scoiatael_ciri.jpg b/img/sm/scoiatael_ciri.jpg new file mode 100644 index 0000000..9c119a8 Binary files /dev/null and b/img/sm/scoiatael_ciri.jpg differ diff --git a/img/sm/scoiatael_dennis.jpg b/img/sm/scoiatael_dennis.jpg new file mode 100644 index 0000000..cd24ae9 Binary files /dev/null and b/img/sm/scoiatael_dennis.jpg differ diff --git a/img/sm/scoiatael_dol_archer.jpg b/img/sm/scoiatael_dol_archer.jpg new file mode 100644 index 0000000..670c11b Binary files /dev/null and b/img/sm/scoiatael_dol_archer.jpg differ diff --git a/img/sm/scoiatael_dol_infantry_1.jpg b/img/sm/scoiatael_dol_infantry_1.jpg new file mode 100644 index 0000000..a239cc1 Binary files /dev/null and b/img/sm/scoiatael_dol_infantry_1.jpg differ diff --git a/img/sm/scoiatael_dol_infantry_2.jpg b/img/sm/scoiatael_dol_infantry_2.jpg new file mode 100644 index 0000000..17031b8 Binary files /dev/null and b/img/sm/scoiatael_dol_infantry_2.jpg differ diff --git a/img/sm/scoiatael_elf_skirmisher.jpg b/img/sm/scoiatael_elf_skirmisher.jpg new file mode 100644 index 0000000..9671e8d Binary files /dev/null and b/img/sm/scoiatael_elf_skirmisher.jpg differ diff --git a/img/sm/scoiatael_elf_skirmisher_1.jpg b/img/sm/scoiatael_elf_skirmisher_1.jpg new file mode 100644 index 0000000..628416b Binary files /dev/null and b/img/sm/scoiatael_elf_skirmisher_1.jpg differ diff --git a/img/sm/scoiatael_elf_skirmisher_2.jpg b/img/sm/scoiatael_elf_skirmisher_2.jpg new file mode 100644 index 0000000..555a12c Binary files /dev/null and b/img/sm/scoiatael_elf_skirmisher_2.jpg differ diff --git a/img/sm/scoiatael_filavandrel.jpg b/img/sm/scoiatael_filavandrel.jpg new file mode 100644 index 0000000..91b88e1 Binary files /dev/null and b/img/sm/scoiatael_filavandrel.jpg differ diff --git a/img/sm/scoiatael_francesca_beautiful.jpg b/img/sm/scoiatael_francesca_beautiful.jpg new file mode 100644 index 0000000..d31e30b Binary files /dev/null and b/img/sm/scoiatael_francesca_beautiful.jpg differ diff --git a/img/sm/scoiatael_francesca_daisy.jpg b/img/sm/scoiatael_francesca_daisy.jpg new file mode 100644 index 0000000..cfe0138 Binary files /dev/null and b/img/sm/scoiatael_francesca_daisy.jpg differ diff --git a/img/sm/scoiatael_francesca_hope_of_the_aen_seidhe.jpg b/img/sm/scoiatael_francesca_hope_of_the_aen_seidhe.jpg new file mode 100644 index 0000000..a10f749 Binary files /dev/null and b/img/sm/scoiatael_francesca_hope_of_the_aen_seidhe.jpg differ diff --git a/img/sm/scoiatael_francesca_pureblood.jpg b/img/sm/scoiatael_francesca_pureblood.jpg new file mode 100644 index 0000000..1a22a1b Binary files /dev/null and b/img/sm/scoiatael_francesca_pureblood.jpg differ diff --git a/img/sm/scoiatael_francesca_queen.jpg b/img/sm/scoiatael_francesca_queen.jpg new file mode 100644 index 0000000..45ae12c Binary files /dev/null and b/img/sm/scoiatael_francesca_queen.jpg differ diff --git a/img/sm/scoiatael_geralt.jpg b/img/sm/scoiatael_geralt.jpg new file mode 100644 index 0000000..576912f Binary files /dev/null and b/img/sm/scoiatael_geralt.jpg differ diff --git a/img/sm/scoiatael_havekar_nurse.jpg b/img/sm/scoiatael_havekar_nurse.jpg new file mode 100644 index 0000000..2ff70d3 Binary files /dev/null and b/img/sm/scoiatael_havekar_nurse.jpg differ diff --git a/img/sm/scoiatael_havekar_nurse_1.jpg b/img/sm/scoiatael_havekar_nurse_1.jpg new file mode 100644 index 0000000..c4218d9 Binary files /dev/null and b/img/sm/scoiatael_havekar_nurse_1.jpg differ diff --git a/img/sm/scoiatael_havekar_nurse_2.jpg b/img/sm/scoiatael_havekar_nurse_2.jpg new file mode 100644 index 0000000..154a377 Binary files /dev/null and b/img/sm/scoiatael_havekar_nurse_2.jpg differ diff --git a/img/sm/scoiatael_havekar_support.jpg b/img/sm/scoiatael_havekar_support.jpg new file mode 100644 index 0000000..7dc528b Binary files /dev/null and b/img/sm/scoiatael_havekar_support.jpg differ diff --git a/img/sm/scoiatael_havekar_support_1.jpg b/img/sm/scoiatael_havekar_support_1.jpg new file mode 100644 index 0000000..b0723c4 Binary files /dev/null and b/img/sm/scoiatael_havekar_support_1.jpg differ diff --git a/img/sm/scoiatael_havekar_support_2.jpg b/img/sm/scoiatael_havekar_support_2.jpg new file mode 100644 index 0000000..412340a Binary files /dev/null and b/img/sm/scoiatael_havekar_support_2.jpg differ diff --git a/img/sm/scoiatael_iorveth.jpg b/img/sm/scoiatael_iorveth.jpg new file mode 100644 index 0000000..10fcd97 Binary files /dev/null and b/img/sm/scoiatael_iorveth.jpg differ diff --git a/img/sm/scoiatael_isengrim.jpg b/img/sm/scoiatael_isengrim.jpg new file mode 100644 index 0000000..dd04794 Binary files /dev/null and b/img/sm/scoiatael_isengrim.jpg differ diff --git a/img/sm/scoiatael_mahakam.jpg b/img/sm/scoiatael_mahakam.jpg new file mode 100644 index 0000000..ecaca55 Binary files /dev/null and b/img/sm/scoiatael_mahakam.jpg differ diff --git a/img/sm/scoiatael_mahakam_1.jpg b/img/sm/scoiatael_mahakam_1.jpg new file mode 100644 index 0000000..4f2cf44 Binary files /dev/null and b/img/sm/scoiatael_mahakam_1.jpg differ diff --git a/img/sm/scoiatael_milva.jpg b/img/sm/scoiatael_milva.jpg new file mode 100644 index 0000000..f6cc3a4 Binary files /dev/null and b/img/sm/scoiatael_milva.jpg differ diff --git a/img/sm/scoiatael_mysterious_elf.jpg b/img/sm/scoiatael_mysterious_elf.jpg new file mode 100644 index 0000000..eae634c Binary files /dev/null and b/img/sm/scoiatael_mysterious_elf.jpg differ diff --git a/img/sm/scoiatael_riordain.jpg b/img/sm/scoiatael_riordain.jpg new file mode 100644 index 0000000..bc449b7 Binary files /dev/null and b/img/sm/scoiatael_riordain.jpg differ diff --git a/img/sm/scoiatael_saskia.jpg b/img/sm/scoiatael_saskia.jpg new file mode 100644 index 0000000..0b67677 Binary files /dev/null and b/img/sm/scoiatael_saskia.jpg differ diff --git a/img/sm/scoiatael_schirru.jpg b/img/sm/scoiatael_schirru.jpg new file mode 100644 index 0000000..b8832f0 Binary files /dev/null and b/img/sm/scoiatael_schirru.jpg differ diff --git a/img/sm/scoiatael_temptress.jpg b/img/sm/scoiatael_temptress.jpg new file mode 100644 index 0000000..05702ae Binary files /dev/null and b/img/sm/scoiatael_temptress.jpg differ diff --git a/img/sm/scoiatael_toruviel.jpg b/img/sm/scoiatael_toruviel.jpg new file mode 100644 index 0000000..4db6ca2 Binary files /dev/null and b/img/sm/scoiatael_toruviel.jpg differ diff --git a/img/sm/scoiatael_vrihedd_brigade.jpg b/img/sm/scoiatael_vrihedd_brigade.jpg new file mode 100644 index 0000000..08146f7 Binary files /dev/null and b/img/sm/scoiatael_vrihedd_brigade.jpg differ diff --git a/img/sm/scoiatael_vrihedd_brigade_1.jpg b/img/sm/scoiatael_vrihedd_brigade_1.jpg new file mode 100644 index 0000000..339dc27 Binary files /dev/null and b/img/sm/scoiatael_vrihedd_brigade_1.jpg differ diff --git a/img/sm/scoiatael_vrihedd_cadet.jpg b/img/sm/scoiatael_vrihedd_cadet.jpg new file mode 100644 index 0000000..a97d7f9 Binary files /dev/null and b/img/sm/scoiatael_vrihedd_cadet.jpg differ diff --git a/img/sm/scoiatael_yaevinn.jpg b/img/sm/scoiatael_yaevinn.jpg new file mode 100644 index 0000000..fe15124 Binary files /dev/null and b/img/sm/scoiatael_yaevinn.jpg differ diff --git a/img/sm/scoiatael_yennefer.jpg b/img/sm/scoiatael_yennefer.jpg new file mode 100644 index 0000000..a62fae6 Binary files /dev/null and b/img/sm/scoiatael_yennefer.jpg differ diff --git a/img/sm/skellige_arnvald.jpg b/img/sm/skellige_arnvald.jpg new file mode 100644 index 0000000..0ac3679 Binary files /dev/null and b/img/sm/skellige_arnvald.jpg differ diff --git a/img/sm/skellige_berserker.jpg b/img/sm/skellige_berserker.jpg new file mode 100644 index 0000000..298c112 Binary files /dev/null and b/img/sm/skellige_berserker.jpg differ diff --git a/img/sm/skellige_birna.jpg b/img/sm/skellige_birna.jpg new file mode 100644 index 0000000..8297f24 Binary files /dev/null and b/img/sm/skellige_birna.jpg differ diff --git a/img/sm/skellige_blueboy.jpg b/img/sm/skellige_blueboy.jpg new file mode 100644 index 0000000..ed8c1be Binary files /dev/null and b/img/sm/skellige_blueboy.jpg differ diff --git a/img/sm/skellige_brokva_archer.jpg b/img/sm/skellige_brokva_archer.jpg new file mode 100644 index 0000000..f10d41f Binary files /dev/null and b/img/sm/skellige_brokva_archer.jpg differ diff --git a/img/sm/skellige_cerys.jpg b/img/sm/skellige_cerys.jpg new file mode 100644 index 0000000..03d01de Binary files /dev/null and b/img/sm/skellige_cerys.jpg differ diff --git a/img/sm/skellige_ciri.jpg b/img/sm/skellige_ciri.jpg new file mode 100644 index 0000000..9c119a8 Binary files /dev/null and b/img/sm/skellige_ciri.jpg differ diff --git a/img/sm/skellige_crach_an_craite.jpg b/img/sm/skellige_crach_an_craite.jpg new file mode 100644 index 0000000..0082bb7 Binary files /dev/null and b/img/sm/skellige_crach_an_craite.jpg differ diff --git a/img/sm/skellige_craite_warrior_1.jpg b/img/sm/skellige_craite_warrior_1.jpg new file mode 100644 index 0000000..74f2877 Binary files /dev/null and b/img/sm/skellige_craite_warrior_1.jpg differ diff --git a/img/sm/skellige_craite_warrior_2.jpg b/img/sm/skellige_craite_warrior_2.jpg new file mode 100644 index 0000000..32ee143 Binary files /dev/null and b/img/sm/skellige_craite_warrior_2.jpg differ diff --git a/img/sm/skellige_donar.jpg b/img/sm/skellige_donar.jpg new file mode 100644 index 0000000..1a3de08 Binary files /dev/null and b/img/sm/skellige_donar.jpg differ diff --git a/img/sm/skellige_draig.jpg b/img/sm/skellige_draig.jpg new file mode 100644 index 0000000..aef8f6f Binary files /dev/null and b/img/sm/skellige_draig.jpg differ diff --git a/img/sm/skellige_ermion.jpg b/img/sm/skellige_ermion.jpg new file mode 100644 index 0000000..9ecc522 Binary files /dev/null and b/img/sm/skellige_ermion.jpg differ diff --git a/img/sm/skellige_geralt.jpg b/img/sm/skellige_geralt.jpg new file mode 100644 index 0000000..576912f Binary files /dev/null and b/img/sm/skellige_geralt.jpg differ diff --git a/img/sm/skellige_gremist.jpg b/img/sm/skellige_gremist.jpg new file mode 100644 index 0000000..f005585 Binary files /dev/null and b/img/sm/skellige_gremist.jpg differ diff --git a/img/sm/skellige_hemdall.jpg b/img/sm/skellige_hemdall.jpg new file mode 100644 index 0000000..dd2642d Binary files /dev/null and b/img/sm/skellige_hemdall.jpg differ diff --git a/img/sm/skellige_hjalmar.jpg b/img/sm/skellige_hjalmar.jpg new file mode 100644 index 0000000..c1c6336 Binary files /dev/null and b/img/sm/skellige_hjalmar.jpg differ diff --git a/img/sm/skellige_holger_blakhand.jpg b/img/sm/skellige_holger_blakhand.jpg new file mode 100644 index 0000000..4dabffa Binary files /dev/null and b/img/sm/skellige_holger_blakhand.jpg differ diff --git a/img/sm/skellige_kambi.jpg b/img/sm/skellige_kambi.jpg new file mode 100644 index 0000000..9a7b4eb Binary files /dev/null and b/img/sm/skellige_kambi.jpg differ diff --git a/img/sm/skellige_king_bran.jpg b/img/sm/skellige_king_bran.jpg new file mode 100644 index 0000000..0c596d9 Binary files /dev/null and b/img/sm/skellige_king_bran.jpg differ diff --git a/img/sm/skellige_light_longship_1.jpg b/img/sm/skellige_light_longship_1.jpg new file mode 100644 index 0000000..a826f51 Binary files /dev/null and b/img/sm/skellige_light_longship_1.jpg differ diff --git a/img/sm/skellige_light_longship_2.jpg b/img/sm/skellige_light_longship_2.jpg new file mode 100644 index 0000000..a826f51 Binary files /dev/null and b/img/sm/skellige_light_longship_2.jpg differ diff --git a/img/sm/skellige_light_longship_3.jpg b/img/sm/skellige_light_longship_3.jpg new file mode 100644 index 0000000..a826f51 Binary files /dev/null and b/img/sm/skellige_light_longship_3.jpg differ diff --git a/img/sm/skellige_longship_1.jpg b/img/sm/skellige_longship_1.jpg new file mode 100644 index 0000000..2bc34a5 Binary files /dev/null and b/img/sm/skellige_longship_1.jpg differ diff --git a/img/sm/skellige_longship_2.jpg b/img/sm/skellige_longship_2.jpg new file mode 100644 index 0000000..2bc34a5 Binary files /dev/null and b/img/sm/skellige_longship_2.jpg differ diff --git a/img/sm/skellige_longship_3.jpg b/img/sm/skellige_longship_3.jpg new file mode 100644 index 0000000..2bc34a5 Binary files /dev/null and b/img/sm/skellige_longship_3.jpg differ diff --git a/img/sm/skellige_madman_lugos.jpg b/img/sm/skellige_madman_lugos.jpg new file mode 100644 index 0000000..9e632f5 Binary files /dev/null and b/img/sm/skellige_madman_lugos.jpg differ diff --git a/img/sm/skellige_shield_maiden_1.jpg b/img/sm/skellige_shield_maiden_1.jpg new file mode 100644 index 0000000..65ac258 Binary files /dev/null and b/img/sm/skellige_shield_maiden_1.jpg differ diff --git a/img/sm/skellige_shield_maiden_2.jpg b/img/sm/skellige_shield_maiden_2.jpg new file mode 100644 index 0000000..46a9339 Binary files /dev/null and b/img/sm/skellige_shield_maiden_2.jpg differ diff --git a/img/sm/skellige_shield_maiden_3.jpg b/img/sm/skellige_shield_maiden_3.jpg new file mode 100644 index 0000000..5d7b1f8 Binary files /dev/null and b/img/sm/skellige_shield_maiden_3.jpg differ diff --git a/img/sm/skellige_transformed_berserker.jpg b/img/sm/skellige_transformed_berserker.jpg new file mode 100644 index 0000000..4cfe6c9 Binary files /dev/null and b/img/sm/skellige_transformed_berserker.jpg differ diff --git a/img/sm/skellige_transformed_vildkaarl.jpg b/img/sm/skellige_transformed_vildkaarl.jpg new file mode 100644 index 0000000..351a07c Binary files /dev/null and b/img/sm/skellige_transformed_vildkaarl.jpg differ diff --git a/img/sm/skellige_transformed_young_berserker.jpg b/img/sm/skellige_transformed_young_berserker.jpg new file mode 100644 index 0000000..35cb088 Binary files /dev/null and b/img/sm/skellige_transformed_young_berserker.jpg differ diff --git a/img/sm/skellige_vildkaarl.jpg b/img/sm/skellige_vildkaarl.jpg new file mode 100644 index 0000000..05b4a85 Binary files /dev/null and b/img/sm/skellige_vildkaarl.jpg differ diff --git a/img/sm/skellige_war_longship.jpg b/img/sm/skellige_war_longship.jpg new file mode 100644 index 0000000..29d2895 Binary files /dev/null and b/img/sm/skellige_war_longship.jpg differ diff --git a/img/sm/skellige_yennefer.jpg b/img/sm/skellige_yennefer.jpg new file mode 100644 index 0000000..a62fae6 Binary files /dev/null and b/img/sm/skellige_yennefer.jpg differ diff --git a/img/sm/skellige_young_berserker_1.jpg b/img/sm/skellige_young_berserker_1.jpg new file mode 100644 index 0000000..7c93235 Binary files /dev/null and b/img/sm/skellige_young_berserker_1.jpg differ diff --git a/img/sm/skellige_young_berserker_2.jpg b/img/sm/skellige_young_berserker_2.jpg new file mode 100644 index 0000000..5126f6b Binary files /dev/null and b/img/sm/skellige_young_berserker_2.jpg differ diff --git a/img/sm/skellige_young_berserker_3.jpg b/img/sm/skellige_young_berserker_3.jpg new file mode 100644 index 0000000..0cdef7c Binary files /dev/null and b/img/sm/skellige_young_berserker_3.jpg differ diff --git a/img/sm/special_curse.jpg b/img/sm/special_curse.jpg new file mode 100644 index 0000000..3a61f6a Binary files /dev/null and b/img/sm/special_curse.jpg differ diff --git a/img/sm/special_decoy.jpg b/img/sm/special_decoy.jpg new file mode 100644 index 0000000..5c0397b Binary files /dev/null and b/img/sm/special_decoy.jpg differ diff --git a/img/sm/special_execution.jpg b/img/sm/special_execution.jpg new file mode 100644 index 0000000..981e7b6 Binary files /dev/null and b/img/sm/special_execution.jpg differ diff --git a/img/sm/special_horn.jpg b/img/sm/special_horn.jpg new file mode 100644 index 0000000..4fae8d6 Binary files /dev/null and b/img/sm/special_horn.jpg differ diff --git a/img/sm/special_lyria_rivia_morale.jpg b/img/sm/special_lyria_rivia_morale.jpg new file mode 100644 index 0000000..0b48df2 Binary files /dev/null and b/img/sm/special_lyria_rivia_morale.jpg differ diff --git a/img/sm/special_mardroeme.jpg b/img/sm/special_mardroeme.jpg new file mode 100644 index 0000000..000fc69 Binary files /dev/null and b/img/sm/special_mardroeme.jpg differ diff --git a/img/sm/special_royal_decree.jpg b/img/sm/special_royal_decree.jpg new file mode 100644 index 0000000..48d8f1b Binary files /dev/null and b/img/sm/special_royal_decree.jpg differ diff --git a/img/sm/special_scorch.jpg b/img/sm/special_scorch.jpg new file mode 100644 index 0000000..8f586b0 Binary files /dev/null and b/img/sm/special_scorch.jpg differ diff --git a/img/sm/special_skellige_fleet.jpg b/img/sm/special_skellige_fleet.jpg new file mode 100644 index 0000000..3334bb9 Binary files /dev/null and b/img/sm/special_skellige_fleet.jpg differ diff --git a/img/sm/special_toussaint_wine.jpg b/img/sm/special_toussaint_wine.jpg new file mode 100644 index 0000000..dcdb7e7 Binary files /dev/null and b/img/sm/special_toussaint_wine.jpg differ diff --git a/img/sm/toussaint_anna_henrietta_duchess.jpg b/img/sm/toussaint_anna_henrietta_duchess.jpg new file mode 100644 index 0000000..75d2d4d Binary files /dev/null and b/img/sm/toussaint_anna_henrietta_duchess.jpg differ diff --git a/img/sm/toussaint_anna_henrietta_ladyship.jpg b/img/sm/toussaint_anna_henrietta_ladyship.jpg new file mode 100644 index 0000000..e5f9793 Binary files /dev/null and b/img/sm/toussaint_anna_henrietta_ladyship.jpg differ diff --git a/img/sm/toussaint_anna_henrietta_little_weasel.jpg b/img/sm/toussaint_anna_henrietta_little_weasel.jpg new file mode 100644 index 0000000..7e93ecd Binary files /dev/null and b/img/sm/toussaint_anna_henrietta_little_weasel.jpg differ diff --git a/img/sm/toussaint_artorius_vigo.jpg b/img/sm/toussaint_artorius_vigo.jpg new file mode 100644 index 0000000..51b94fc Binary files /dev/null and b/img/sm/toussaint_artorius_vigo.jpg differ diff --git a/img/sm/toussaint_barnabas.jpg b/img/sm/toussaint_barnabas.jpg new file mode 100644 index 0000000..742b84f Binary files /dev/null and b/img/sm/toussaint_barnabas.jpg differ diff --git a/img/sm/toussaint_bootblack.jpg b/img/sm/toussaint_bootblack.jpg new file mode 100644 index 0000000..24f39d1 Binary files /dev/null and b/img/sm/toussaint_bootblack.jpg differ diff --git a/img/sm/toussaint_champion.jpg b/img/sm/toussaint_champion.jpg new file mode 100644 index 0000000..eeeee71 Binary files /dev/null and b/img/sm/toussaint_champion.jpg differ diff --git a/img/sm/toussaint_damien_tour.jpg b/img/sm/toussaint_damien_tour.jpg new file mode 100644 index 0000000..3b963f6 Binary files /dev/null and b/img/sm/toussaint_damien_tour.jpg differ diff --git a/img/sm/toussaint_dettlaff.jpg b/img/sm/toussaint_dettlaff.jpg new file mode 100644 index 0000000..edfa655 Binary files /dev/null and b/img/sm/toussaint_dettlaff.jpg differ diff --git a/img/sm/toussaint_dettlaff_higher_vampire.jpg b/img/sm/toussaint_dettlaff_higher_vampire.jpg new file mode 100644 index 0000000..057327b Binary files /dev/null and b/img/sm/toussaint_dettlaff_higher_vampire.jpg differ diff --git a/img/sm/toussaint_duchess_informant.jpg b/img/sm/toussaint_duchess_informant.jpg new file mode 100644 index 0000000..b326f90 Binary files /dev/null and b/img/sm/toussaint_duchess_informant.jpg differ diff --git a/img/sm/toussaint_geralt.jpg b/img/sm/toussaint_geralt.jpg new file mode 100644 index 0000000..576912f Binary files /dev/null and b/img/sm/toussaint_geralt.jpg differ diff --git a/img/sm/toussaint_gregoire_gorgon.jpg b/img/sm/toussaint_gregoire_gorgon.jpg new file mode 100644 index 0000000..cb9cce6 Binary files /dev/null and b/img/sm/toussaint_gregoire_gorgon.jpg differ diff --git a/img/sm/toussaint_guillaume.jpg b/img/sm/toussaint_guillaume.jpg new file mode 100644 index 0000000..5bed4d2 Binary files /dev/null and b/img/sm/toussaint_guillaume.jpg differ diff --git a/img/sm/toussaint_knight_errant_1.jpg b/img/sm/toussaint_knight_errant_1.jpg new file mode 100644 index 0000000..05f18ae Binary files /dev/null and b/img/sm/toussaint_knight_errant_1.jpg differ diff --git a/img/sm/toussaint_knight_errant_2.jpg b/img/sm/toussaint_knight_errant_2.jpg new file mode 100644 index 0000000..87b702f Binary files /dev/null and b/img/sm/toussaint_knight_errant_2.jpg differ diff --git a/img/sm/toussaint_lady_lake.jpg b/img/sm/toussaint_lady_lake.jpg new file mode 100644 index 0000000..0f5215c Binary files /dev/null and b/img/sm/toussaint_lady_lake.jpg differ diff --git a/img/sm/toussaint_lui_alberni.jpg b/img/sm/toussaint_lui_alberni.jpg new file mode 100644 index 0000000..6fb2819 Binary files /dev/null and b/img/sm/toussaint_lui_alberni.jpg differ diff --git a/img/sm/toussaint_lui_alberni_golyat.jpg b/img/sm/toussaint_lui_alberni_golyat.jpg new file mode 100644 index 0000000..72a9f91 Binary files /dev/null and b/img/sm/toussaint_lui_alberni_golyat.jpg differ diff --git a/img/sm/toussaint_marlene.jpg b/img/sm/toussaint_marlene.jpg new file mode 100644 index 0000000..36846a0 Binary files /dev/null and b/img/sm/toussaint_marlene.jpg differ diff --git a/img/sm/toussaint_milton.jpg b/img/sm/toussaint_milton.jpg new file mode 100644 index 0000000..59ad925 Binary files /dev/null and b/img/sm/toussaint_milton.jpg differ diff --git a/img/sm/toussaint_minstrel.jpg b/img/sm/toussaint_minstrel.jpg new file mode 100644 index 0000000..418347d Binary files /dev/null and b/img/sm/toussaint_minstrel.jpg differ diff --git a/img/sm/toussaint_orianna.jpg b/img/sm/toussaint_orianna.jpg new file mode 100644 index 0000000..155a3a4 Binary files /dev/null and b/img/sm/toussaint_orianna.jpg differ diff --git a/img/sm/toussaint_orianna_bruxa.jpg b/img/sm/toussaint_orianna_bruxa.jpg new file mode 100644 index 0000000..f1d5a0c Binary files /dev/null and b/img/sm/toussaint_orianna_bruxa.jpg differ diff --git a/img/sm/toussaint_palmerin.jpg b/img/sm/toussaint_palmerin.jpg new file mode 100644 index 0000000..ff02989 Binary files /dev/null and b/img/sm/toussaint_palmerin.jpg differ diff --git a/img/sm/toussaint_prophet_lebioda.jpg b/img/sm/toussaint_prophet_lebioda.jpg new file mode 100644 index 0000000..0a1d80c Binary files /dev/null and b/img/sm/toussaint_prophet_lebioda.jpg differ diff --git a/img/sm/toussaint_regis.jpg b/img/sm/toussaint_regis.jpg new file mode 100644 index 0000000..0b58dbb Binary files /dev/null and b/img/sm/toussaint_regis.jpg differ diff --git a/img/sm/toussaint_regis_higher_vampire.jpg b/img/sm/toussaint_regis_higher_vampire.jpg new file mode 100644 index 0000000..da1fde9 Binary files /dev/null and b/img/sm/toussaint_regis_higher_vampire.jpg differ diff --git a/img/sm/toussaint_roderick.jpg b/img/sm/toussaint_roderick.jpg new file mode 100644 index 0000000..4945120 Binary files /dev/null and b/img/sm/toussaint_roderick.jpg differ diff --git a/img/sm/toussaint_syanna.jpg b/img/sm/toussaint_syanna.jpg new file mode 100644 index 0000000..0b87eb1 Binary files /dev/null and b/img/sm/toussaint_syanna.jpg differ diff --git a/img/sm/toussaint_toussaint_knight_1.jpg b/img/sm/toussaint_toussaint_knight_1.jpg new file mode 100644 index 0000000..758193e Binary files /dev/null and b/img/sm/toussaint_toussaint_knight_1.jpg differ diff --git a/img/sm/toussaint_toussaint_knight_2.jpg b/img/sm/toussaint_toussaint_knight_2.jpg new file mode 100644 index 0000000..361e3c2 Binary files /dev/null and b/img/sm/toussaint_toussaint_knight_2.jpg differ diff --git a/img/sm/toussaint_toussaint_knight_3.jpg b/img/sm/toussaint_toussaint_knight_3.jpg new file mode 100644 index 0000000..a59483a Binary files /dev/null and b/img/sm/toussaint_toussaint_knight_3.jpg differ diff --git a/img/sm/toussaint_unseen_elder.jpg b/img/sm/toussaint_unseen_elder.jpg new file mode 100644 index 0000000..2d13ba0 Binary files /dev/null and b/img/sm/toussaint_unseen_elder.jpg differ diff --git a/img/sm/toussaint_vivienne.jpg b/img/sm/toussaint_vivienne.jpg new file mode 100644 index 0000000..62fbc62 Binary files /dev/null and b/img/sm/toussaint_vivienne.jpg differ diff --git a/img/sm/toussaint_vivienne_oriole.jpg b/img/sm/toussaint_vivienne_oriole.jpg new file mode 100644 index 0000000..c91ad3a Binary files /dev/null and b/img/sm/toussaint_vivienne_oriole.jpg differ diff --git a/img/sm/toussaint_witch_lynx_crag.jpg b/img/sm/toussaint_witch_lynx_crag.jpg new file mode 100644 index 0000000..553bd98 Binary files /dev/null and b/img/sm/toussaint_witch_lynx_crag.jpg differ diff --git a/img/sm/velen_abandoned_girl.jpg b/img/sm/velen_abandoned_girl.jpg new file mode 100644 index 0000000..aa47f98 Binary files /dev/null and b/img/sm/velen_abandoned_girl.jpg differ diff --git a/img/sm/velen_allgod.jpg b/img/sm/velen_allgod.jpg new file mode 100644 index 0000000..3b240a5 Binary files /dev/null and b/img/sm/velen_allgod.jpg differ diff --git a/img/sm/velen_angry_peasants.jpg b/img/sm/velen_angry_peasants.jpg new file mode 100644 index 0000000..8d2f5f2 Binary files /dev/null and b/img/sm/velen_angry_peasants.jpg differ diff --git a/img/sm/velen_anna_strenger.jpg b/img/sm/velen_anna_strenger.jpg new file mode 100644 index 0000000..ca989cd Binary files /dev/null and b/img/sm/velen_anna_strenger.jpg differ diff --git a/img/sm/velen_bloody_baron.jpg b/img/sm/velen_bloody_baron.jpg new file mode 100644 index 0000000..de8473c Binary files /dev/null and b/img/sm/velen_bloody_baron.jpg differ diff --git a/img/sm/velen_chort.jpg b/img/sm/velen_chort.jpg new file mode 100644 index 0000000..cd13238 Binary files /dev/null and b/img/sm/velen_chort.jpg differ diff --git a/img/sm/velen_ciri.jpg b/img/sm/velen_ciri.jpg new file mode 100644 index 0000000..9c119a8 Binary files /dev/null and b/img/sm/velen_ciri.jpg differ diff --git a/img/sm/velen_cutthroat.jpg b/img/sm/velen_cutthroat.jpg new file mode 100644 index 0000000..e8e439c Binary files /dev/null and b/img/sm/velen_cutthroat.jpg differ diff --git a/img/sm/velen_deserter_1.jpg b/img/sm/velen_deserter_1.jpg new file mode 100644 index 0000000..638be3d Binary files /dev/null and b/img/sm/velen_deserter_1.jpg differ diff --git a/img/sm/velen_deserter_2.jpg b/img/sm/velen_deserter_2.jpg new file mode 100644 index 0000000..0599564 Binary files /dev/null and b/img/sm/velen_deserter_2.jpg differ diff --git a/img/sm/velen_drowner.jpg b/img/sm/velen_drowner.jpg new file mode 100644 index 0000000..50f5a13 Binary files /dev/null and b/img/sm/velen_drowner.jpg differ diff --git a/img/sm/velen_fiend.jpg b/img/sm/velen_fiend.jpg new file mode 100644 index 0000000..21f0426 Binary files /dev/null and b/img/sm/velen_fiend.jpg differ diff --git a/img/sm/velen_fugas.jpg b/img/sm/velen_fugas.jpg new file mode 100644 index 0000000..4659498 Binary files /dev/null and b/img/sm/velen_fugas.jpg differ diff --git a/img/sm/velen_geralt.jpg b/img/sm/velen_geralt.jpg new file mode 100644 index 0000000..576912f Binary files /dev/null and b/img/sm/velen_geralt.jpg differ diff --git a/img/sm/velen_ghost_tree.jpg b/img/sm/velen_ghost_tree.jpg new file mode 100644 index 0000000..4bb2473 Binary files /dev/null and b/img/sm/velen_ghost_tree.jpg differ diff --git a/img/sm/velen_ghoul_1.jpg b/img/sm/velen_ghoul_1.jpg new file mode 100644 index 0000000..384545a Binary files /dev/null and b/img/sm/velen_ghoul_1.jpg differ diff --git a/img/sm/velen_ghoul_2.jpg b/img/sm/velen_ghoul_2.jpg new file mode 100644 index 0000000..67c906d Binary files /dev/null and b/img/sm/velen_ghoul_2.jpg differ diff --git a/img/sm/velen_hungry_wolves_1.jpg b/img/sm/velen_hungry_wolves_1.jpg new file mode 100644 index 0000000..bf53361 Binary files /dev/null and b/img/sm/velen_hungry_wolves_1.jpg differ diff --git a/img/sm/velen_hungry_wolves_2.jpg b/img/sm/velen_hungry_wolves_2.jpg new file mode 100644 index 0000000..f3f3b5f Binary files /dev/null and b/img/sm/velen_hungry_wolves_2.jpg differ diff --git a/img/sm/velen_hungry_wolves_3.jpg b/img/sm/velen_hungry_wolves_3.jpg new file mode 100644 index 0000000..ada3d8e Binary files /dev/null and b/img/sm/velen_hungry_wolves_3.jpg differ diff --git a/img/sm/velen_hungry_wolves_4.jpg b/img/sm/velen_hungry_wolves_4.jpg new file mode 100644 index 0000000..da8c166 Binary files /dev/null and b/img/sm/velen_hungry_wolves_4.jpg differ diff --git a/img/sm/velen_johnny.jpg b/img/sm/velen_johnny.jpg new file mode 100644 index 0000000..6742d5c Binary files /dev/null and b/img/sm/velen_johnny.jpg differ diff --git a/img/sm/velen_lady_wood_brewess.jpg b/img/sm/velen_lady_wood_brewess.jpg new file mode 100644 index 0000000..4008135 Binary files /dev/null and b/img/sm/velen_lady_wood_brewess.jpg differ diff --git a/img/sm/velen_lady_wood_weavess.jpg b/img/sm/velen_lady_wood_weavess.jpg new file mode 100644 index 0000000..8dbb979 Binary files /dev/null and b/img/sm/velen_lady_wood_weavess.jpg differ diff --git a/img/sm/velen_lady_wood_whispess.jpg b/img/sm/velen_lady_wood_whispess.jpg new file mode 100644 index 0000000..4dbd0e2 Binary files /dev/null and b/img/sm/velen_lady_wood_whispess.jpg differ diff --git a/img/sm/velen_marauder_1.jpg b/img/sm/velen_marauder_1.jpg new file mode 100644 index 0000000..d388f8b Binary files /dev/null and b/img/sm/velen_marauder_1.jpg differ diff --git a/img/sm/velen_marauder_2.jpg b/img/sm/velen_marauder_2.jpg new file mode 100644 index 0000000..8200031 Binary files /dev/null and b/img/sm/velen_marauder_2.jpg differ diff --git a/img/sm/velen_nightwraith.jpg b/img/sm/velen_nightwraith.jpg new file mode 100644 index 0000000..90580c0 Binary files /dev/null and b/img/sm/velen_nightwraith.jpg differ diff --git a/img/sm/velen_noonwraith.jpg b/img/sm/velen_noonwraith.jpg new file mode 100644 index 0000000..dc14735 Binary files /dev/null and b/img/sm/velen_noonwraith.jpg differ diff --git a/img/sm/velen_pellar.jpg b/img/sm/velen_pellar.jpg new file mode 100644 index 0000000..468ae81 Binary files /dev/null and b/img/sm/velen_pellar.jpg differ diff --git a/img/sm/velen_penitent.jpg b/img/sm/velen_penitent.jpg new file mode 100644 index 0000000..8f2c660 Binary files /dev/null and b/img/sm/velen_penitent.jpg differ diff --git a/img/sm/velen_tamara_strenger.jpg b/img/sm/velen_tamara_strenger.jpg new file mode 100644 index 0000000..1dc6e68 Binary files /dev/null and b/img/sm/velen_tamara_strenger.jpg differ diff --git a/img/sm/velen_thecla.jpg b/img/sm/velen_thecla.jpg new file mode 100644 index 0000000..24c560b Binary files /dev/null and b/img/sm/velen_thecla.jpg differ diff --git a/img/sm/velen_vesemir.jpg b/img/sm/velen_vesemir.jpg new file mode 100644 index 0000000..eaaa5a0 Binary files /dev/null and b/img/sm/velen_vesemir.jpg differ diff --git a/img/sm/velen_water_hag.jpg b/img/sm/velen_water_hag.jpg new file mode 100644 index 0000000..ad0112a Binary files /dev/null and b/img/sm/velen_water_hag.jpg differ diff --git a/img/sm/weather_clear.jpg b/img/sm/weather_clear.jpg new file mode 100644 index 0000000..242c506 Binary files /dev/null and b/img/sm/weather_clear.jpg differ diff --git a/img/sm/weather_fog.jpg b/img/sm/weather_fog.jpg new file mode 100644 index 0000000..912ef67 Binary files /dev/null and b/img/sm/weather_fog.jpg differ diff --git a/img/sm/weather_frost.jpg b/img/sm/weather_frost.jpg new file mode 100644 index 0000000..e16aba4 Binary files /dev/null and b/img/sm/weather_frost.jpg differ diff --git a/img/sm/weather_rain.jpg b/img/sm/weather_rain.jpg new file mode 100644 index 0000000..2d32222 Binary files /dev/null and b/img/sm/weather_rain.jpg differ diff --git a/img/sm/weather_storm.jpg b/img/sm/weather_storm.jpg new file mode 100644 index 0000000..baedcf1 Binary files /dev/null and b/img/sm/weather_storm.jpg differ diff --git a/img/sm_old/faction_lyria_rivia.jpg b/img/sm_old/faction_lyria_rivia.jpg new file mode 100644 index 0000000..c5a9219 Binary files /dev/null and b/img/sm_old/faction_lyria_rivia.jpg differ diff --git a/img/sm_old/faction_monsters.jpg b/img/sm_old/faction_monsters.jpg new file mode 100644 index 0000000..b60dae7 Binary files /dev/null and b/img/sm_old/faction_monsters.jpg differ diff --git a/img/sm_old/faction_nilfgaard.jpg b/img/sm_old/faction_nilfgaard.jpg new file mode 100644 index 0000000..d22b395 Binary files /dev/null and b/img/sm_old/faction_nilfgaard.jpg differ diff --git a/img/sm_old/faction_random.jpg b/img/sm_old/faction_random.jpg new file mode 100644 index 0000000..896b6bb Binary files /dev/null and b/img/sm_old/faction_random.jpg differ diff --git a/img/sm_old/faction_realms.jpg b/img/sm_old/faction_realms.jpg new file mode 100644 index 0000000..636d9d7 Binary files /dev/null and b/img/sm_old/faction_realms.jpg differ diff --git a/img/sm_old/faction_scoiatael.jpg b/img/sm_old/faction_scoiatael.jpg new file mode 100644 index 0000000..f13c61c Binary files /dev/null and b/img/sm_old/faction_scoiatael.jpg differ diff --git a/img/sm_old/faction_skellige.jpg b/img/sm_old/faction_skellige.jpg new file mode 100644 index 0000000..0769ea8 Binary files /dev/null and b/img/sm_old/faction_skellige.jpg differ diff --git a/img/sm_old/faction_syndicate.jpg b/img/sm_old/faction_syndicate.jpg new file mode 100644 index 0000000..c365d30 Binary files /dev/null and b/img/sm_old/faction_syndicate.jpg differ diff --git a/img/sm_old/faction_toussaint.jpg b/img/sm_old/faction_toussaint.jpg new file mode 100644 index 0000000..dd41149 Binary files /dev/null and b/img/sm_old/faction_toussaint.jpg differ diff --git a/img/sm_old/faction_witcher_universe.jpg b/img/sm_old/faction_witcher_universe.jpg new file mode 100644 index 0000000..2c5fdad Binary files /dev/null and b/img/sm_old/faction_witcher_universe.jpg differ diff --git a/img/sm_old/faction_zerrikania.jpg b/img/sm_old/faction_zerrikania.jpg new file mode 100644 index 0000000..c6f3033 Binary files /dev/null and b/img/sm_old/faction_zerrikania.jpg differ diff --git a/img/sm_old/lyria_rivia_arbalest.jpg b/img/sm_old/lyria_rivia_arbalest.jpg new file mode 100644 index 0000000..dfb2891 Binary files /dev/null and b/img/sm_old/lyria_rivia_arbalest.jpg differ diff --git a/img/sm_old/lyria_rivia_artificer.jpg b/img/sm_old/lyria_rivia_artificer.jpg new file mode 100644 index 0000000..82e6841 Binary files /dev/null and b/img/sm_old/lyria_rivia_artificer.jpg differ diff --git a/img/sm_old/lyria_rivia_banner.jpg b/img/sm_old/lyria_rivia_banner.jpg new file mode 100644 index 0000000..22faf83 Binary files /dev/null and b/img/sm_old/lyria_rivia_banner.jpg differ diff --git a/img/sm_old/lyria_rivia_blacksmith.jpg b/img/sm_old/lyria_rivia_blacksmith.jpg new file mode 100644 index 0000000..140015b Binary files /dev/null and b/img/sm_old/lyria_rivia_blacksmith.jpg differ diff --git a/img/sm_old/lyria_rivia_caldwell.jpg b/img/sm_old/lyria_rivia_caldwell.jpg new file mode 100644 index 0000000..b87dc56 Binary files /dev/null and b/img/sm_old/lyria_rivia_caldwell.jpg differ diff --git a/img/sm_old/lyria_rivia_carroballista.jpg b/img/sm_old/lyria_rivia_carroballista.jpg new file mode 100644 index 0000000..fb33c01 Binary files /dev/null and b/img/sm_old/lyria_rivia_carroballista.jpg differ diff --git a/img/sm_old/lyria_rivia_eavesdrop.jpg b/img/sm_old/lyria_rivia_eavesdrop.jpg new file mode 100644 index 0000000..19fdfe7 Binary files /dev/null and b/img/sm_old/lyria_rivia_eavesdrop.jpg differ diff --git a/img/sm_old/lyria_rivia_forager.jpg b/img/sm_old/lyria_rivia_forager.jpg new file mode 100644 index 0000000..96555b5 Binary files /dev/null and b/img/sm_old/lyria_rivia_forager.jpg differ diff --git a/img/sm_old/lyria_rivia_gascon.jpg b/img/sm_old/lyria_rivia_gascon.jpg new file mode 100644 index 0000000..9db998d Binary files /dev/null and b/img/sm_old/lyria_rivia_gascon.jpg differ diff --git a/img/sm_old/lyria_rivia_grey_rider.jpg b/img/sm_old/lyria_rivia_grey_rider.jpg new file mode 100644 index 0000000..4d208ae Binary files /dev/null and b/img/sm_old/lyria_rivia_grey_rider.jpg differ diff --git a/img/sm_old/lyria_rivia_hajduk.jpg b/img/sm_old/lyria_rivia_hajduk.jpg new file mode 100644 index 0000000..76746a8 Binary files /dev/null and b/img/sm_old/lyria_rivia_hajduk.jpg differ diff --git a/img/sm_old/lyria_rivia_isbel_hagge.jpg b/img/sm_old/lyria_rivia_isbel_hagge.jpg new file mode 100644 index 0000000..a1d86b8 Binary files /dev/null and b/img/sm_old/lyria_rivia_isbel_hagge.jpg differ diff --git a/img/sm_old/lyria_rivia_knighthood.jpg b/img/sm_old/lyria_rivia_knighthood.jpg new file mode 100644 index 0000000..b66f817 Binary files /dev/null and b/img/sm_old/lyria_rivia_knighthood.jpg differ diff --git a/img/sm_old/lyria_rivia_landsknecht.jpg b/img/sm_old/lyria_rivia_landsknecht.jpg new file mode 100644 index 0000000..d6f4e61 Binary files /dev/null and b/img/sm_old/lyria_rivia_landsknecht.jpg differ diff --git a/img/sm_old/lyria_rivia_light_cavalry.jpg b/img/sm_old/lyria_rivia_light_cavalry.jpg new file mode 100644 index 0000000..39f4302 Binary files /dev/null and b/img/sm_old/lyria_rivia_light_cavalry.jpg differ diff --git a/img/sm_old/lyria_rivia_lyrian_cavalry.jpg b/img/sm_old/lyria_rivia_lyrian_cavalry.jpg new file mode 100644 index 0000000..7bf75ac Binary files /dev/null and b/img/sm_old/lyria_rivia_lyrian_cavalry.jpg differ diff --git a/img/sm_old/lyria_rivia_meve_princess.jpg b/img/sm_old/lyria_rivia_meve_princess.jpg new file mode 100644 index 0000000..75c7f20 Binary files /dev/null and b/img/sm_old/lyria_rivia_meve_princess.jpg differ diff --git a/img/sm_old/lyria_rivia_meve_white_queen.jpg b/img/sm_old/lyria_rivia_meve_white_queen.jpg new file mode 100644 index 0000000..fcfbe3c Binary files /dev/null and b/img/sm_old/lyria_rivia_meve_white_queen.jpg differ diff --git a/img/sm_old/lyria_rivia_onager.jpg b/img/sm_old/lyria_rivia_onager.jpg new file mode 100644 index 0000000..39ef65d Binary files /dev/null and b/img/sm_old/lyria_rivia_onager.jpg differ diff --git a/img/sm_old/lyria_rivia_peasant_militia.jpg b/img/sm_old/lyria_rivia_peasant_militia.jpg new file mode 100644 index 0000000..2382175 Binary files /dev/null and b/img/sm_old/lyria_rivia_peasant_militia.jpg differ diff --git a/img/sm_old/lyria_rivia_physician.jpg b/img/sm_old/lyria_rivia_physician.jpg new file mode 100644 index 0000000..6abf7d0 Binary files /dev/null and b/img/sm_old/lyria_rivia_physician.jpg differ diff --git a/img/sm_old/lyria_rivia_piercing_missile.jpg b/img/sm_old/lyria_rivia_piercing_missile.jpg new file mode 100644 index 0000000..9de06f7 Binary files /dev/null and b/img/sm_old/lyria_rivia_piercing_missile.jpg differ diff --git a/img/sm_old/lyria_rivia_pikeman.jpg b/img/sm_old/lyria_rivia_pikeman.jpg new file mode 100644 index 0000000..edf6fee Binary files /dev/null and b/img/sm_old/lyria_rivia_pikeman.jpg differ diff --git a/img/sm_old/lyria_rivia_prince_anseis.jpg b/img/sm_old/lyria_rivia_prince_anseis.jpg new file mode 100644 index 0000000..db043e8 Binary files /dev/null and b/img/sm_old/lyria_rivia_prince_anseis.jpg differ diff --git a/img/sm_old/lyria_rivia_pyrokinesis.jpg b/img/sm_old/lyria_rivia_pyrokinesis.jpg new file mode 100644 index 0000000..d6e44d1 Binary files /dev/null and b/img/sm_old/lyria_rivia_pyrokinesis.jpg differ diff --git a/img/sm_old/lyria_rivia_rayla.jpg b/img/sm_old/lyria_rivia_rayla.jpg new file mode 100644 index 0000000..f747b1c Binary files /dev/null and b/img/sm_old/lyria_rivia_rayla.jpg differ diff --git a/img/sm_old/lyria_rivia_reynard_odo.jpg b/img/sm_old/lyria_rivia_reynard_odo.jpg new file mode 100644 index 0000000..83bac14 Binary files /dev/null and b/img/sm_old/lyria_rivia_reynard_odo.jpg differ diff --git a/img/sm_old/lyria_rivia_rivian_mauler.jpg b/img/sm_old/lyria_rivia_rivian_mauler.jpg new file mode 100644 index 0000000..8a00440 Binary files /dev/null and b/img/sm_old/lyria_rivia_rivian_mauler.jpg differ diff --git a/img/sm_old/lyria_rivia_royal_guard.jpg b/img/sm_old/lyria_rivia_royal_guard.jpg new file mode 100644 index 0000000..014f871 Binary files /dev/null and b/img/sm_old/lyria_rivia_royal_guard.jpg differ diff --git a/img/sm_old/lyria_rivia_sapper.jpg b/img/sm_old/lyria_rivia_sapper.jpg new file mode 100644 index 0000000..88691a6 Binary files /dev/null and b/img/sm_old/lyria_rivia_sapper.jpg differ diff --git a/img/sm_old/lyria_rivia_scout.jpg b/img/sm_old/lyria_rivia_scout.jpg new file mode 100644 index 0000000..0599564 Binary files /dev/null and b/img/sm_old/lyria_rivia_scout.jpg differ diff --git a/img/sm_old/lyria_rivia_scytheman.jpg b/img/sm_old/lyria_rivia_scytheman.jpg new file mode 100644 index 0000000..fffa86d Binary files /dev/null and b/img/sm_old/lyria_rivia_scytheman.jpg differ diff --git a/img/sm_old/lyria_rivia_siege.jpg b/img/sm_old/lyria_rivia_siege.jpg new file mode 100644 index 0000000..062fad8 Binary files /dev/null and b/img/sm_old/lyria_rivia_siege.jpg differ diff --git a/img/sm_old/lyria_rivia_spellweaver.jpg b/img/sm_old/lyria_rivia_spellweaver.jpg new file mode 100644 index 0000000..b61eed2 Binary files /dev/null and b/img/sm_old/lyria_rivia_spellweaver.jpg differ diff --git a/img/sm_old/lyria_rivia_trebuchet.jpg b/img/sm_old/lyria_rivia_trebuchet.jpg new file mode 100644 index 0000000..1a679ad Binary files /dev/null and b/img/sm_old/lyria_rivia_trebuchet.jpg differ diff --git a/img/sm_old/lyria_rivia_villem.jpg b/img/sm_old/lyria_rivia_villem.jpg new file mode 100644 index 0000000..06d4597 Binary files /dev/null and b/img/sm_old/lyria_rivia_villem.jpg differ diff --git a/img/sm_old/lyria_rivia_wagenburg.jpg b/img/sm_old/lyria_rivia_wagenburg.jpg new file mode 100644 index 0000000..978786e Binary files /dev/null and b/img/sm_old/lyria_rivia_wagenburg.jpg differ diff --git a/img/sm_old/lyria_rivia_wagon.jpg b/img/sm_old/lyria_rivia_wagon.jpg new file mode 100644 index 0000000..57282fc Binary files /dev/null and b/img/sm_old/lyria_rivia_wagon.jpg differ diff --git a/img/sm_old/lyria_rivia_war_wagon.jpg b/img/sm_old/lyria_rivia_war_wagon.jpg new file mode 100644 index 0000000..7f5b275 Binary files /dev/null and b/img/sm_old/lyria_rivia_war_wagon.jpg differ diff --git a/img/sm_old/lyria_rivia_winch.jpg b/img/sm_old/lyria_rivia_winch.jpg new file mode 100644 index 0000000..186f594 Binary files /dev/null and b/img/sm_old/lyria_rivia_winch.jpg differ diff --git a/img/sm_old/monsters_aguara.jpg b/img/sm_old/monsters_aguara.jpg new file mode 100644 index 0000000..df83375 Binary files /dev/null and b/img/sm_old/monsters_aguara.jpg differ diff --git a/img/sm_old/monsters_alghoul.jpg b/img/sm_old/monsters_alghoul.jpg new file mode 100644 index 0000000..8dbaa82 Binary files /dev/null and b/img/sm_old/monsters_alghoul.jpg differ diff --git a/img/sm_old/monsters_alp.jpg b/img/sm_old/monsters_alp.jpg new file mode 100644 index 0000000..edc3875 Binary files /dev/null and b/img/sm_old/monsters_alp.jpg differ diff --git a/img/sm_old/monsters_arachas.jpg b/img/sm_old/monsters_arachas.jpg new file mode 100644 index 0000000..06627fc Binary files /dev/null and b/img/sm_old/monsters_arachas.jpg differ diff --git a/img/sm_old/monsters_arachas_1.jpg b/img/sm_old/monsters_arachas_1.jpg new file mode 100644 index 0000000..08bcc4a Binary files /dev/null and b/img/sm_old/monsters_arachas_1.jpg differ diff --git a/img/sm_old/monsters_arachas_2.jpg b/img/sm_old/monsters_arachas_2.jpg new file mode 100644 index 0000000..bcd01c2 Binary files /dev/null and b/img/sm_old/monsters_arachas_2.jpg differ diff --git a/img/sm_old/monsters_arachas_behemoth.jpg b/img/sm_old/monsters_arachas_behemoth.jpg new file mode 100644 index 0000000..5187f23 Binary files /dev/null and b/img/sm_old/monsters_arachas_behemoth.jpg differ diff --git a/img/sm_old/monsters_arachas_drone.jpg b/img/sm_old/monsters_arachas_drone.jpg new file mode 100644 index 0000000..940d49f Binary files /dev/null and b/img/sm_old/monsters_arachas_drone.jpg differ diff --git a/img/sm_old/monsters_arachas_queen.jpg b/img/sm_old/monsters_arachas_queen.jpg new file mode 100644 index 0000000..0236cc4 Binary files /dev/null and b/img/sm_old/monsters_arachas_queen.jpg differ diff --git a/img/sm_old/monsters_archgriffin.jpg b/img/sm_old/monsters_archgriffin.jpg new file mode 100644 index 0000000..7ceced8 Binary files /dev/null and b/img/sm_old/monsters_archgriffin.jpg differ diff --git a/img/sm_old/monsters_armoured_arachas.jpg b/img/sm_old/monsters_armoured_arachas.jpg new file mode 100644 index 0000000..ec1b48c Binary files /dev/null and b/img/sm_old/monsters_armoured_arachas.jpg differ diff --git a/img/sm_old/monsters_botchling.jpg b/img/sm_old/monsters_botchling.jpg new file mode 100644 index 0000000..21c7bf9 Binary files /dev/null and b/img/sm_old/monsters_botchling.jpg differ diff --git a/img/sm_old/monsters_bruxa.jpg b/img/sm_old/monsters_bruxa.jpg new file mode 100644 index 0000000..6ea7a06 Binary files /dev/null and b/img/sm_old/monsters_bruxa.jpg differ diff --git a/img/sm_old/monsters_caranthir.jpg b/img/sm_old/monsters_caranthir.jpg new file mode 100644 index 0000000..05c9eeb Binary files /dev/null and b/img/sm_old/monsters_caranthir.jpg differ diff --git a/img/sm_old/monsters_caretaker.jpg b/img/sm_old/monsters_caretaker.jpg new file mode 100644 index 0000000..759dbbb Binary files /dev/null and b/img/sm_old/monsters_caretaker.jpg differ diff --git a/img/sm_old/monsters_celaeno_harpy.jpg b/img/sm_old/monsters_celaeno_harpy.jpg new file mode 100644 index 0000000..2a91485 Binary files /dev/null and b/img/sm_old/monsters_celaeno_harpy.jpg differ diff --git a/img/sm_old/monsters_cockatrice.jpg b/img/sm_old/monsters_cockatrice.jpg new file mode 100644 index 0000000..c679da7 Binary files /dev/null and b/img/sm_old/monsters_cockatrice.jpg differ diff --git a/img/sm_old/monsters_cyclops.jpg b/img/sm_old/monsters_cyclops.jpg new file mode 100644 index 0000000..963b696 Binary files /dev/null and b/img/sm_old/monsters_cyclops.jpg differ diff --git a/img/sm_old/monsters_dagon.jpg b/img/sm_old/monsters_dagon.jpg new file mode 100644 index 0000000..6ebeb0d Binary files /dev/null and b/img/sm_old/monsters_dagon.jpg differ diff --git a/img/sm_old/monsters_dragon_fyresdal.jpg b/img/sm_old/monsters_dragon_fyresdal.jpg new file mode 100644 index 0000000..3dfd540 Binary files /dev/null and b/img/sm_old/monsters_dragon_fyresdal.jpg differ diff --git a/img/sm_old/monsters_draug.jpg b/img/sm_old/monsters_draug.jpg new file mode 100644 index 0000000..8abb155 Binary files /dev/null and b/img/sm_old/monsters_draug.jpg differ diff --git a/img/sm_old/monsters_earth_elemental.jpg b/img/sm_old/monsters_earth_elemental.jpg new file mode 100644 index 0000000..9372c42 Binary files /dev/null and b/img/sm_old/monsters_earth_elemental.jpg differ diff --git a/img/sm_old/monsters_ekkima.jpg b/img/sm_old/monsters_ekkima.jpg new file mode 100644 index 0000000..bf1452e Binary files /dev/null and b/img/sm_old/monsters_ekkima.jpg differ diff --git a/img/sm_old/monsters_endrega.jpg b/img/sm_old/monsters_endrega.jpg new file mode 100644 index 0000000..b300b24 Binary files /dev/null and b/img/sm_old/monsters_endrega.jpg differ diff --git a/img/sm_old/monsters_eredin_bringer_of_death.jpg b/img/sm_old/monsters_eredin_bringer_of_death.jpg new file mode 100644 index 0000000..e984811 Binary files /dev/null and b/img/sm_old/monsters_eredin_bringer_of_death.jpg differ diff --git a/img/sm_old/monsters_eredin_commander.jpg b/img/sm_old/monsters_eredin_commander.jpg new file mode 100644 index 0000000..10c6ddb Binary files /dev/null and b/img/sm_old/monsters_eredin_commander.jpg differ diff --git a/img/sm_old/monsters_eredin_destroyer.jpg b/img/sm_old/monsters_eredin_destroyer.jpg new file mode 100644 index 0000000..0b110e9 Binary files /dev/null and b/img/sm_old/monsters_eredin_destroyer.jpg differ diff --git a/img/sm_old/monsters_eredin_king.jpg b/img/sm_old/monsters_eredin_king.jpg new file mode 100644 index 0000000..0947f46 Binary files /dev/null and b/img/sm_old/monsters_eredin_king.jpg differ diff --git a/img/sm_old/monsters_eredin_the_treacherous.jpg b/img/sm_old/monsters_eredin_the_treacherous.jpg new file mode 100644 index 0000000..3a487c2 Binary files /dev/null and b/img/sm_old/monsters_eredin_the_treacherous.jpg differ diff --git a/img/sm_old/monsters_fiend.jpg b/img/sm_old/monsters_fiend.jpg new file mode 100644 index 0000000..21f0426 Binary files /dev/null and b/img/sm_old/monsters_fiend.jpg differ diff --git a/img/sm_old/monsters_fire_elemental.jpg b/img/sm_old/monsters_fire_elemental.jpg new file mode 100644 index 0000000..1d71b2d Binary files /dev/null and b/img/sm_old/monsters_fire_elemental.jpg differ diff --git a/img/sm_old/monsters_fleder.jpg b/img/sm_old/monsters_fleder.jpg new file mode 100644 index 0000000..31366f5 Binary files /dev/null and b/img/sm_old/monsters_fleder.jpg differ diff --git a/img/sm_old/monsters_fogling.jpg b/img/sm_old/monsters_fogling.jpg new file mode 100644 index 0000000..698b748 Binary files /dev/null and b/img/sm_old/monsters_fogling.jpg differ diff --git a/img/sm_old/monsters_forktail.jpg b/img/sm_old/monsters_forktail.jpg new file mode 100644 index 0000000..1019f24 Binary files /dev/null and b/img/sm_old/monsters_forktail.jpg differ diff --git a/img/sm_old/monsters_frightener.jpg b/img/sm_old/monsters_frightener.jpg new file mode 100644 index 0000000..195d952 Binary files /dev/null and b/img/sm_old/monsters_frightener.jpg differ diff --git a/img/sm_old/monsters_frost_giant.jpg b/img/sm_old/monsters_frost_giant.jpg new file mode 100644 index 0000000..8048e29 Binary files /dev/null and b/img/sm_old/monsters_frost_giant.jpg differ diff --git a/img/sm_old/monsters_gargoyle.jpg b/img/sm_old/monsters_gargoyle.jpg new file mode 100644 index 0000000..2d62fa2 Binary files /dev/null and b/img/sm_old/monsters_gargoyle.jpg differ diff --git a/img/sm_old/monsters_garkain.jpg b/img/sm_old/monsters_garkain.jpg new file mode 100644 index 0000000..1faa481 Binary files /dev/null and b/img/sm_old/monsters_garkain.jpg differ diff --git a/img/sm_old/monsters_geels.jpg b/img/sm_old/monsters_geels.jpg new file mode 100644 index 0000000..e46d063 Binary files /dev/null and b/img/sm_old/monsters_geels.jpg differ diff --git a/img/sm_old/monsters_ghoul.jpg b/img/sm_old/monsters_ghoul.jpg new file mode 100644 index 0000000..b934cee Binary files /dev/null and b/img/sm_old/monsters_ghoul.jpg differ diff --git a/img/sm_old/monsters_ghoul_1.jpg b/img/sm_old/monsters_ghoul_1.jpg new file mode 100644 index 0000000..384545a Binary files /dev/null and b/img/sm_old/monsters_ghoul_1.jpg differ diff --git a/img/sm_old/monsters_ghoul_2.jpg b/img/sm_old/monsters_ghoul_2.jpg new file mode 100644 index 0000000..67c906d Binary files /dev/null and b/img/sm_old/monsters_ghoul_2.jpg differ diff --git a/img/sm_old/monsters_glustyworp.jpg b/img/sm_old/monsters_glustyworp.jpg new file mode 100644 index 0000000..d3df51f Binary files /dev/null and b/img/sm_old/monsters_glustyworp.jpg differ diff --git a/img/sm_old/monsters_golem.jpg b/img/sm_old/monsters_golem.jpg new file mode 100644 index 0000000..7e0e0fc Binary files /dev/null and b/img/sm_old/monsters_golem.jpg differ diff --git a/img/sm_old/monsters_gravehag.jpg b/img/sm_old/monsters_gravehag.jpg new file mode 100644 index 0000000..7f6586c Binary files /dev/null and b/img/sm_old/monsters_gravehag.jpg differ diff --git a/img/sm_old/monsters_great_oak.jpg b/img/sm_old/monsters_great_oak.jpg new file mode 100644 index 0000000..052f646 Binary files /dev/null and b/img/sm_old/monsters_great_oak.jpg differ diff --git a/img/sm_old/monsters_gryffin.jpg b/img/sm_old/monsters_gryffin.jpg new file mode 100644 index 0000000..a0abd52 Binary files /dev/null and b/img/sm_old/monsters_gryffin.jpg differ diff --git a/img/sm_old/monsters_harpy.jpg b/img/sm_old/monsters_harpy.jpg new file mode 100644 index 0000000..2c976f8 Binary files /dev/null and b/img/sm_old/monsters_harpy.jpg differ diff --git a/img/sm_old/monsters_ice_troll.jpg b/img/sm_old/monsters_ice_troll.jpg new file mode 100644 index 0000000..fbd0511 Binary files /dev/null and b/img/sm_old/monsters_ice_troll.jpg differ diff --git a/img/sm_old/monsters_ifrit_1.jpg b/img/sm_old/monsters_ifrit_1.jpg new file mode 100644 index 0000000..02da8a5 Binary files /dev/null and b/img/sm_old/monsters_ifrit_1.jpg differ diff --git a/img/sm_old/monsters_ifrit_2.jpg b/img/sm_old/monsters_ifrit_2.jpg new file mode 100644 index 0000000..1ed1528 Binary files /dev/null and b/img/sm_old/monsters_ifrit_2.jpg differ diff --git a/img/sm_old/monsters_imlerith.jpg b/img/sm_old/monsters_imlerith.jpg new file mode 100644 index 0000000..235d7df Binary files /dev/null and b/img/sm_old/monsters_imlerith.jpg differ diff --git a/img/sm_old/monsters_jotunn.jpg b/img/sm_old/monsters_jotunn.jpg new file mode 100644 index 0000000..2f5983d Binary files /dev/null and b/img/sm_old/monsters_jotunn.jpg differ diff --git a/img/sm_old/monsters_katakan.jpg b/img/sm_old/monsters_katakan.jpg new file mode 100644 index 0000000..9778dc7 Binary files /dev/null and b/img/sm_old/monsters_katakan.jpg differ diff --git a/img/sm_old/monsters_kayran.jpg b/img/sm_old/monsters_kayran.jpg new file mode 100644 index 0000000..f5acb1b Binary files /dev/null and b/img/sm_old/monsters_kayran.jpg differ diff --git a/img/sm_old/monsters_lamia_1.jpg b/img/sm_old/monsters_lamia_1.jpg new file mode 100644 index 0000000..e717a38 Binary files /dev/null and b/img/sm_old/monsters_lamia_1.jpg differ diff --git a/img/sm_old/monsters_lamia_2.jpg b/img/sm_old/monsters_lamia_2.jpg new file mode 100644 index 0000000..2c525ce Binary files /dev/null and b/img/sm_old/monsters_lamia_2.jpg differ diff --git a/img/sm_old/monsters_lamia_3.jpg b/img/sm_old/monsters_lamia_3.jpg new file mode 100644 index 0000000..09a9dea Binary files /dev/null and b/img/sm_old/monsters_lamia_3.jpg differ diff --git a/img/sm_old/monsters_leshen.jpg b/img/sm_old/monsters_leshen.jpg new file mode 100644 index 0000000..6225930 Binary files /dev/null and b/img/sm_old/monsters_leshen.jpg differ diff --git a/img/sm_old/monsters_lubberkin.jpg b/img/sm_old/monsters_lubberkin.jpg new file mode 100644 index 0000000..609e01f Binary files /dev/null and b/img/sm_old/monsters_lubberkin.jpg differ diff --git a/img/sm_old/monsters_manticore.jpg b/img/sm_old/monsters_manticore.jpg new file mode 100644 index 0000000..ad47247 Binary files /dev/null and b/img/sm_old/monsters_manticore.jpg differ diff --git a/img/sm_old/monsters_manticore_venom.jpg b/img/sm_old/monsters_manticore_venom.jpg new file mode 100644 index 0000000..a6cc447 Binary files /dev/null and b/img/sm_old/monsters_manticore_venom.jpg differ diff --git a/img/sm_old/monsters_mighty_maiden.jpg b/img/sm_old/monsters_mighty_maiden.jpg new file mode 100644 index 0000000..3ce8f8c Binary files /dev/null and b/img/sm_old/monsters_mighty_maiden.jpg differ diff --git a/img/sm_old/monsters_moonlight.jpg b/img/sm_old/monsters_moonlight.jpg new file mode 100644 index 0000000..4f38ad7 Binary files /dev/null and b/img/sm_old/monsters_moonlight.jpg differ diff --git a/img/sm_old/monsters_morvudd.jpg b/img/sm_old/monsters_morvudd.jpg new file mode 100644 index 0000000..5c558df Binary files /dev/null and b/img/sm_old/monsters_morvudd.jpg differ diff --git a/img/sm_old/monsters_naglfar.jpg b/img/sm_old/monsters_naglfar.jpg new file mode 100644 index 0000000..2fe6f15 Binary files /dev/null and b/img/sm_old/monsters_naglfar.jpg differ diff --git a/img/sm_old/monsters_navigator.jpg b/img/sm_old/monsters_navigator.jpg new file mode 100644 index 0000000..4008be8 Binary files /dev/null and b/img/sm_old/monsters_navigator.jpg differ diff --git a/img/sm_old/monsters_nekker.jpg b/img/sm_old/monsters_nekker.jpg new file mode 100644 index 0000000..78c3fd9 Binary files /dev/null and b/img/sm_old/monsters_nekker.jpg differ diff --git a/img/sm_old/monsters_nekker_1.jpg b/img/sm_old/monsters_nekker_1.jpg new file mode 100644 index 0000000..c703b7d Binary files /dev/null and b/img/sm_old/monsters_nekker_1.jpg differ diff --git a/img/sm_old/monsters_nekker_2.jpg b/img/sm_old/monsters_nekker_2.jpg new file mode 100644 index 0000000..4ba2b60 Binary files /dev/null and b/img/sm_old/monsters_nekker_2.jpg differ diff --git a/img/sm_old/monsters_nithral.jpg b/img/sm_old/monsters_nithral.jpg new file mode 100644 index 0000000..08a573c Binary files /dev/null and b/img/sm_old/monsters_nithral.jpg differ diff --git a/img/sm_old/monsters_noonwraith.jpg b/img/sm_old/monsters_noonwraith.jpg new file mode 100644 index 0000000..dc14735 Binary files /dev/null and b/img/sm_old/monsters_noonwraith.jpg differ diff --git a/img/sm_old/monsters_old_speartip.jpg b/img/sm_old/monsters_old_speartip.jpg new file mode 100644 index 0000000..0dad9ac Binary files /dev/null and b/img/sm_old/monsters_old_speartip.jpg differ diff --git a/img/sm_old/monsters_poroniec.jpg b/img/sm_old/monsters_poroniec.jpg new file mode 100644 index 0000000..79f6418 Binary files /dev/null and b/img/sm_old/monsters_poroniec.jpg differ diff --git a/img/sm_old/monsters_queen_night.jpg b/img/sm_old/monsters_queen_night.jpg new file mode 100644 index 0000000..f86e105 Binary files /dev/null and b/img/sm_old/monsters_queen_night.jpg differ diff --git a/img/sm_old/monsters_ruehin.jpg b/img/sm_old/monsters_ruehin.jpg new file mode 100644 index 0000000..1f6208a Binary files /dev/null and b/img/sm_old/monsters_ruehin.jpg differ diff --git a/img/sm_old/monsters_striga.jpg b/img/sm_old/monsters_striga.jpg new file mode 100644 index 0000000..8245940 Binary files /dev/null and b/img/sm_old/monsters_striga.jpg differ diff --git a/img/sm_old/monsters_succubus.jpg b/img/sm_old/monsters_succubus.jpg new file mode 100644 index 0000000..d5dc807 Binary files /dev/null and b/img/sm_old/monsters_succubus.jpg differ diff --git a/img/sm_old/monsters_therazane.jpg b/img/sm_old/monsters_therazane.jpg new file mode 100644 index 0000000..08acd41 Binary files /dev/null and b/img/sm_old/monsters_therazane.jpg differ diff --git a/img/sm_old/monsters_toad.jpg b/img/sm_old/monsters_toad.jpg new file mode 100644 index 0000000..c7d436d Binary files /dev/null and b/img/sm_old/monsters_toad.jpg differ diff --git a/img/sm_old/monsters_vran_warrior.jpg b/img/sm_old/monsters_vran_warrior.jpg new file mode 100644 index 0000000..c5bfab3 Binary files /dev/null and b/img/sm_old/monsters_vran_warrior.jpg differ diff --git a/img/sm_old/monsters_werewolf.jpg b/img/sm_old/monsters_werewolf.jpg new file mode 100644 index 0000000..b28d04b Binary files /dev/null and b/img/sm_old/monsters_werewolf.jpg differ diff --git a/img/sm_old/monsters_wild_hunt_rider_1.jpg b/img/sm_old/monsters_wild_hunt_rider_1.jpg new file mode 100644 index 0000000..b75bc97 Binary files /dev/null and b/img/sm_old/monsters_wild_hunt_rider_1.jpg differ diff --git a/img/sm_old/monsters_wild_hunt_rider_2.jpg b/img/sm_old/monsters_wild_hunt_rider_2.jpg new file mode 100644 index 0000000..98ce294 Binary files /dev/null and b/img/sm_old/monsters_wild_hunt_rider_2.jpg differ diff --git a/img/sm_old/monsters_wild_hunt_rider_3.jpg b/img/sm_old/monsters_wild_hunt_rider_3.jpg new file mode 100644 index 0000000..925277e Binary files /dev/null and b/img/sm_old/monsters_wild_hunt_rider_3.jpg differ diff --git a/img/sm_old/monsters_witch_velen.jpg b/img/sm_old/monsters_witch_velen.jpg new file mode 100644 index 0000000..4008135 Binary files /dev/null and b/img/sm_old/monsters_witch_velen.jpg differ diff --git a/img/sm_old/monsters_witch_velen_1.jpg b/img/sm_old/monsters_witch_velen_1.jpg new file mode 100644 index 0000000..8dbb979 Binary files /dev/null and b/img/sm_old/monsters_witch_velen_1.jpg differ diff --git a/img/sm_old/monsters_witch_velen_2.jpg b/img/sm_old/monsters_witch_velen_2.jpg new file mode 100644 index 0000000..4dbd0e2 Binary files /dev/null and b/img/sm_old/monsters_witch_velen_2.jpg differ diff --git a/img/sm_old/monsters_wyvern.jpg b/img/sm_old/monsters_wyvern.jpg new file mode 100644 index 0000000..39b18d8 Binary files /dev/null and b/img/sm_old/monsters_wyvern.jpg differ diff --git a/img/sm_old/neutral_chort.jpg b/img/sm_old/neutral_chort.jpg new file mode 100644 index 0000000..9b278ba Binary files /dev/null and b/img/sm_old/neutral_chort.jpg differ diff --git a/img/sm_old/neutral_ciri.jpg b/img/sm_old/neutral_ciri.jpg new file mode 100644 index 0000000..9c119a8 Binary files /dev/null and b/img/sm_old/neutral_ciri.jpg differ diff --git a/img/sm_old/neutral_cow.jpg b/img/sm_old/neutral_cow.jpg new file mode 100644 index 0000000..3ad6e7b Binary files /dev/null and b/img/sm_old/neutral_cow.jpg differ diff --git a/img/sm_old/neutral_dandelion.jpg b/img/sm_old/neutral_dandelion.jpg new file mode 100644 index 0000000..885583e Binary files /dev/null and b/img/sm_old/neutral_dandelion.jpg differ diff --git a/img/sm_old/neutral_emiel.jpg b/img/sm_old/neutral_emiel.jpg new file mode 100644 index 0000000..150ddf9 Binary files /dev/null and b/img/sm_old/neutral_emiel.jpg differ diff --git a/img/sm_old/neutral_gaunter_odimm.jpg b/img/sm_old/neutral_gaunter_odimm.jpg new file mode 100644 index 0000000..fad682a Binary files /dev/null and b/img/sm_old/neutral_gaunter_odimm.jpg differ diff --git a/img/sm_old/neutral_gaunter_odimm_darkness.jpg b/img/sm_old/neutral_gaunter_odimm_darkness.jpg new file mode 100644 index 0000000..ad929a8 Binary files /dev/null and b/img/sm_old/neutral_gaunter_odimm_darkness.jpg differ diff --git a/img/sm_old/neutral_geralt.jpg b/img/sm_old/neutral_geralt.jpg new file mode 100644 index 0000000..576912f Binary files /dev/null and b/img/sm_old/neutral_geralt.jpg differ diff --git a/img/sm_old/neutral_mysterious_elf.jpg b/img/sm_old/neutral_mysterious_elf.jpg new file mode 100644 index 0000000..eae634c Binary files /dev/null and b/img/sm_old/neutral_mysterious_elf.jpg differ diff --git a/img/sm_old/neutral_olgierd.jpg b/img/sm_old/neutral_olgierd.jpg new file mode 100644 index 0000000..a7a0719 Binary files /dev/null and b/img/sm_old/neutral_olgierd.jpg differ diff --git a/img/sm_old/neutral_triss.jpg b/img/sm_old/neutral_triss.jpg new file mode 100644 index 0000000..67b090c Binary files /dev/null and b/img/sm_old/neutral_triss.jpg differ diff --git a/img/sm_old/neutral_vesemir.jpg b/img/sm_old/neutral_vesemir.jpg new file mode 100644 index 0000000..eaaa5a0 Binary files /dev/null and b/img/sm_old/neutral_vesemir.jpg differ diff --git a/img/sm_old/neutral_villen.jpg b/img/sm_old/neutral_villen.jpg new file mode 100644 index 0000000..3e6ba1b Binary files /dev/null and b/img/sm_old/neutral_villen.jpg differ diff --git a/img/sm_old/neutral_yennefer.jpg b/img/sm_old/neutral_yennefer.jpg new file mode 100644 index 0000000..a62fae6 Binary files /dev/null and b/img/sm_old/neutral_yennefer.jpg differ diff --git a/img/sm_old/neutral_zoltan.jpg b/img/sm_old/neutral_zoltan.jpg new file mode 100644 index 0000000..2bd6615 Binary files /dev/null and b/img/sm_old/neutral_zoltan.jpg differ diff --git a/img/sm_old/nilfgaard_affan_hillergrand.jpg b/img/sm_old/nilfgaard_affan_hillergrand.jpg new file mode 100644 index 0000000..81ea45d Binary files /dev/null and b/img/sm_old/nilfgaard_affan_hillergrand.jpg differ diff --git a/img/sm_old/nilfgaard_alba_armored_cavalry.jpg b/img/sm_old/nilfgaard_alba_armored_cavalry.jpg new file mode 100644 index 0000000..01ea7dd Binary files /dev/null and b/img/sm_old/nilfgaard_alba_armored_cavalry.jpg differ diff --git a/img/sm_old/nilfgaard_alba_pikeman_1.jpg b/img/sm_old/nilfgaard_alba_pikeman_1.jpg new file mode 100644 index 0000000..a489b24 Binary files /dev/null and b/img/sm_old/nilfgaard_alba_pikeman_1.jpg differ diff --git a/img/sm_old/nilfgaard_alba_spearman.jpg b/img/sm_old/nilfgaard_alba_spearman.jpg new file mode 100644 index 0000000..8431eaa Binary files /dev/null and b/img/sm_old/nilfgaard_alba_spearman.jpg differ diff --git a/img/sm_old/nilfgaard_albrich.jpg b/img/sm_old/nilfgaard_albrich.jpg new file mode 100644 index 0000000..a68751c Binary files /dev/null and b/img/sm_old/nilfgaard_albrich.jpg differ diff --git a/img/sm_old/nilfgaard_archer_support.jpg b/img/sm_old/nilfgaard_archer_support.jpg new file mode 100644 index 0000000..79591f4 Binary files /dev/null and b/img/sm_old/nilfgaard_archer_support.jpg differ diff --git a/img/sm_old/nilfgaard_archer_support_1.jpg b/img/sm_old/nilfgaard_archer_support_1.jpg new file mode 100644 index 0000000..6d5d999 Binary files /dev/null and b/img/sm_old/nilfgaard_archer_support_1.jpg differ diff --git a/img/sm_old/nilfgaard_ard_feainn_crossbowman.jpg b/img/sm_old/nilfgaard_ard_feainn_crossbowman.jpg new file mode 100644 index 0000000..bc7149e Binary files /dev/null and b/img/sm_old/nilfgaard_ard_feainn_crossbowman.jpg differ diff --git a/img/sm_old/nilfgaard_ard_feainn_heavy_cavalry.jpg b/img/sm_old/nilfgaard_ard_feainn_heavy_cavalry.jpg new file mode 100644 index 0000000..b5ded4a Binary files /dev/null and b/img/sm_old/nilfgaard_ard_feainn_heavy_cavalry.jpg differ diff --git a/img/sm_old/nilfgaard_ard_feainn_light_cavalry.jpg b/img/sm_old/nilfgaard_ard_feainn_light_cavalry.jpg new file mode 100644 index 0000000..7aee50b Binary files /dev/null and b/img/sm_old/nilfgaard_ard_feainn_light_cavalry.jpg differ diff --git a/img/sm_old/nilfgaard_ard_feainn_tortoise.jpg b/img/sm_old/nilfgaard_ard_feainn_tortoise.jpg new file mode 100644 index 0000000..c8b96b9 Binary files /dev/null and b/img/sm_old/nilfgaard_ard_feainn_tortoise.jpg differ diff --git a/img/sm_old/nilfgaard_ardal_aep_dahy.jpg b/img/sm_old/nilfgaard_ardal_aep_dahy.jpg new file mode 100644 index 0000000..9f9ae99 Binary files /dev/null and b/img/sm_old/nilfgaard_ardal_aep_dahy.jpg differ diff --git a/img/sm_old/nilfgaard_assire.jpg b/img/sm_old/nilfgaard_assire.jpg new file mode 100644 index 0000000..d1f5b5d Binary files /dev/null and b/img/sm_old/nilfgaard_assire.jpg differ diff --git a/img/sm_old/nilfgaard_black_archer.jpg b/img/sm_old/nilfgaard_black_archer.jpg new file mode 100644 index 0000000..a6340e0 Binary files /dev/null and b/img/sm_old/nilfgaard_black_archer.jpg differ diff --git a/img/sm_old/nilfgaard_black_archer_1.jpg b/img/sm_old/nilfgaard_black_archer_1.jpg new file mode 100644 index 0000000..482d1f7 Binary files /dev/null and b/img/sm_old/nilfgaard_black_archer_1.jpg differ diff --git a/img/sm_old/nilfgaard_bribery.jpg b/img/sm_old/nilfgaard_bribery.jpg new file mode 100644 index 0000000..bbc022e Binary files /dev/null and b/img/sm_old/nilfgaard_bribery.jpg differ diff --git a/img/sm_old/nilfgaard_cahir.jpg b/img/sm_old/nilfgaard_cahir.jpg new file mode 100644 index 0000000..ea747f7 Binary files /dev/null and b/img/sm_old/nilfgaard_cahir.jpg differ diff --git a/img/sm_old/nilfgaard_cantarella.jpg b/img/sm_old/nilfgaard_cantarella.jpg new file mode 100644 index 0000000..6a1608e Binary files /dev/null and b/img/sm_old/nilfgaard_cantarella.jpg differ diff --git a/img/sm_old/nilfgaard_combat_engineer.jpg b/img/sm_old/nilfgaard_combat_engineer.jpg new file mode 100644 index 0000000..0ee8a2b Binary files /dev/null and b/img/sm_old/nilfgaard_combat_engineer.jpg differ diff --git a/img/sm_old/nilfgaard_cynthia.jpg b/img/sm_old/nilfgaard_cynthia.jpg new file mode 100644 index 0000000..e136c34 Binary files /dev/null and b/img/sm_old/nilfgaard_cynthia.jpg differ diff --git a/img/sm_old/nilfgaard_daerlan_soldier.jpg b/img/sm_old/nilfgaard_daerlan_soldier.jpg new file mode 100644 index 0000000..7b3c88c Binary files /dev/null and b/img/sm_old/nilfgaard_daerlan_soldier.jpg differ diff --git a/img/sm_old/nilfgaard_deithwen_arbalest.jpg b/img/sm_old/nilfgaard_deithwen_arbalest.jpg new file mode 100644 index 0000000..c04d8ec Binary files /dev/null and b/img/sm_old/nilfgaard_deithwen_arbalest.jpg differ diff --git a/img/sm_old/nilfgaard_dunny.jpg b/img/sm_old/nilfgaard_dunny.jpg new file mode 100644 index 0000000..ea43b5b Binary files /dev/null and b/img/sm_old/nilfgaard_dunny.jpg differ diff --git a/img/sm_old/nilfgaard_emhyr_emperor.jpg b/img/sm_old/nilfgaard_emhyr_emperor.jpg new file mode 100644 index 0000000..03fbe81 Binary files /dev/null and b/img/sm_old/nilfgaard_emhyr_emperor.jpg differ diff --git a/img/sm_old/nilfgaard_emhyr_imperial.jpg b/img/sm_old/nilfgaard_emhyr_imperial.jpg new file mode 100644 index 0000000..d832acd Binary files /dev/null and b/img/sm_old/nilfgaard_emhyr_imperial.jpg differ diff --git a/img/sm_old/nilfgaard_emhyr_invader_of_the_north.jpg b/img/sm_old/nilfgaard_emhyr_invader_of_the_north.jpg new file mode 100644 index 0000000..7140c45 Binary files /dev/null and b/img/sm_old/nilfgaard_emhyr_invader_of_the_north.jpg differ diff --git a/img/sm_old/nilfgaard_emhyr_relentless.jpg b/img/sm_old/nilfgaard_emhyr_relentless.jpg new file mode 100644 index 0000000..fd00c62 Binary files /dev/null and b/img/sm_old/nilfgaard_emhyr_relentless.jpg differ diff --git a/img/sm_old/nilfgaard_emhyr_whiteflame.jpg b/img/sm_old/nilfgaard_emhyr_whiteflame.jpg new file mode 100644 index 0000000..2c4b793 Binary files /dev/null and b/img/sm_old/nilfgaard_emhyr_whiteflame.jpg differ diff --git a/img/sm_old/nilfgaard_emissary.jpg b/img/sm_old/nilfgaard_emissary.jpg new file mode 100644 index 0000000..2772eaf Binary files /dev/null and b/img/sm_old/nilfgaard_emissary.jpg differ diff --git a/img/sm_old/nilfgaard_epidemic.jpg b/img/sm_old/nilfgaard_epidemic.jpg new file mode 100644 index 0000000..ed5f606 Binary files /dev/null and b/img/sm_old/nilfgaard_epidemic.jpg differ diff --git a/img/sm_old/nilfgaard_fake_ciri.jpg b/img/sm_old/nilfgaard_fake_ciri.jpg new file mode 100644 index 0000000..d72fbed Binary files /dev/null and b/img/sm_old/nilfgaard_fake_ciri.jpg differ diff --git a/img/sm_old/nilfgaard_fergus_emreis.jpg b/img/sm_old/nilfgaard_fergus_emreis.jpg new file mode 100644 index 0000000..d888032 Binary files /dev/null and b/img/sm_old/nilfgaard_fergus_emreis.jpg differ diff --git a/img/sm_old/nilfgaard_ffion_gaernel.jpg b/img/sm_old/nilfgaard_ffion_gaernel.jpg new file mode 100644 index 0000000..9421f10 Binary files /dev/null and b/img/sm_old/nilfgaard_ffion_gaernel.jpg differ diff --git a/img/sm_old/nilfgaard_fringilla.jpg b/img/sm_old/nilfgaard_fringilla.jpg new file mode 100644 index 0000000..36d925c Binary files /dev/null and b/img/sm_old/nilfgaard_fringilla.jpg differ diff --git a/img/sm_old/nilfgaard_glynnis_loernach.jpg b/img/sm_old/nilfgaard_glynnis_loernach.jpg new file mode 100644 index 0000000..cf83591 Binary files /dev/null and b/img/sm_old/nilfgaard_glynnis_loernach.jpg differ diff --git a/img/sm_old/nilfgaard_guardian.jpg b/img/sm_old/nilfgaard_guardian.jpg new file mode 100644 index 0000000..785b527 Binary files /dev/null and b/img/sm_old/nilfgaard_guardian.jpg differ diff --git a/img/sm_old/nilfgaard_heavy_zerri.jpg b/img/sm_old/nilfgaard_heavy_zerri.jpg new file mode 100644 index 0000000..3bc11ed Binary files /dev/null and b/img/sm_old/nilfgaard_heavy_zerri.jpg differ diff --git a/img/sm_old/nilfgaard_hefty_helge.jpg b/img/sm_old/nilfgaard_hefty_helge.jpg new file mode 100644 index 0000000..4455abb Binary files /dev/null and b/img/sm_old/nilfgaard_hefty_helge.jpg differ diff --git a/img/sm_old/nilfgaard_illusionist.jpg b/img/sm_old/nilfgaard_illusionist.jpg new file mode 100644 index 0000000..c6ac73e Binary files /dev/null and b/img/sm_old/nilfgaard_illusionist.jpg differ diff --git a/img/sm_old/nilfgaard_impera_brigade_1.jpg b/img/sm_old/nilfgaard_impera_brigade_1.jpg new file mode 100644 index 0000000..5683995 Binary files /dev/null and b/img/sm_old/nilfgaard_impera_brigade_1.jpg differ diff --git a/img/sm_old/nilfgaard_impera_brigade_2.jpg b/img/sm_old/nilfgaard_impera_brigade_2.jpg new file mode 100644 index 0000000..b3ef52a Binary files /dev/null and b/img/sm_old/nilfgaard_impera_brigade_2.jpg differ diff --git a/img/sm_old/nilfgaard_impera_brigade_3.jpg b/img/sm_old/nilfgaard_impera_brigade_3.jpg new file mode 100644 index 0000000..525f023 Binary files /dev/null and b/img/sm_old/nilfgaard_impera_brigade_3.jpg differ diff --git a/img/sm_old/nilfgaard_impera_brigade_4.jpg b/img/sm_old/nilfgaard_impera_brigade_4.jpg new file mode 100644 index 0000000..6ad2eab Binary files /dev/null and b/img/sm_old/nilfgaard_impera_brigade_4.jpg differ diff --git a/img/sm_old/nilfgaard_impera_brigade_5.jpg b/img/sm_old/nilfgaard_impera_brigade_5.jpg new file mode 100644 index 0000000..2a42072 Binary files /dev/null and b/img/sm_old/nilfgaard_impera_brigade_5.jpg differ diff --git a/img/sm_old/nilfgaard_impera_enforcers.jpg b/img/sm_old/nilfgaard_impera_enforcers.jpg new file mode 100644 index 0000000..70e513b Binary files /dev/null and b/img/sm_old/nilfgaard_impera_enforcers.jpg differ diff --git a/img/sm_old/nilfgaard_imperial_diviner.jpg b/img/sm_old/nilfgaard_imperial_diviner.jpg new file mode 100644 index 0000000..65d3035 Binary files /dev/null and b/img/sm_old/nilfgaard_imperial_diviner.jpg differ diff --git a/img/sm_old/nilfgaard_imperial_golem.jpg b/img/sm_old/nilfgaard_imperial_golem.jpg new file mode 100644 index 0000000..73158a9 Binary files /dev/null and b/img/sm_old/nilfgaard_imperial_golem.jpg differ diff --git a/img/sm_old/nilfgaard_imperial_practitioner.jpg b/img/sm_old/nilfgaard_imperial_practitioner.jpg new file mode 100644 index 0000000..d8321e9 Binary files /dev/null and b/img/sm_old/nilfgaard_imperial_practitioner.jpg differ diff --git a/img/sm_old/nilfgaard_infiltrator.jpg b/img/sm_old/nilfgaard_infiltrator.jpg new file mode 100644 index 0000000..07078ed Binary files /dev/null and b/img/sm_old/nilfgaard_infiltrator.jpg differ diff --git a/img/sm_old/nilfgaard_jan_calveit.jpg b/img/sm_old/nilfgaard_jan_calveit.jpg new file mode 100644 index 0000000..76a7da4 Binary files /dev/null and b/img/sm_old/nilfgaard_jan_calveit.jpg differ diff --git a/img/sm_old/nilfgaard_joachim_de_wett.jpg b/img/sm_old/nilfgaard_joachim_de_wett.jpg new file mode 100644 index 0000000..59f4815 Binary files /dev/null and b/img/sm_old/nilfgaard_joachim_de_wett.jpg differ diff --git a/img/sm_old/nilfgaard_knight.jpg b/img/sm_old/nilfgaard_knight.jpg new file mode 100644 index 0000000..447771a Binary files /dev/null and b/img/sm_old/nilfgaard_knight.jpg differ diff --git a/img/sm_old/nilfgaard_letho.jpg b/img/sm_old/nilfgaard_letho.jpg new file mode 100644 index 0000000..ff91b60 Binary files /dev/null and b/img/sm_old/nilfgaard_letho.jpg differ diff --git a/img/sm_old/nilfgaard_magne_division.jpg b/img/sm_old/nilfgaard_magne_division.jpg new file mode 100644 index 0000000..0e5a690 Binary files /dev/null and b/img/sm_old/nilfgaard_magne_division.jpg differ diff --git a/img/sm_old/nilfgaard_mangonel.jpg b/img/sm_old/nilfgaard_mangonel.jpg new file mode 100644 index 0000000..fd63c41 Binary files /dev/null and b/img/sm_old/nilfgaard_mangonel.jpg differ diff --git a/img/sm_old/nilfgaard_master_disguise.jpg b/img/sm_old/nilfgaard_master_disguise.jpg new file mode 100644 index 0000000..dd15692 Binary files /dev/null and b/img/sm_old/nilfgaard_master_disguise.jpg differ diff --git a/img/sm_old/nilfgaard_menno.jpg b/img/sm_old/nilfgaard_menno.jpg new file mode 100644 index 0000000..3b41ab8 Binary files /dev/null and b/img/sm_old/nilfgaard_menno.jpg differ diff --git a/img/sm_old/nilfgaard_moorvran.jpg b/img/sm_old/nilfgaard_moorvran.jpg new file mode 100644 index 0000000..c3e651a Binary files /dev/null and b/img/sm_old/nilfgaard_moorvran.jpg differ diff --git a/img/sm_old/nilfgaard_morteisen.jpg b/img/sm_old/nilfgaard_morteisen.jpg new file mode 100644 index 0000000..cf1fcb4 Binary files /dev/null and b/img/sm_old/nilfgaard_morteisen.jpg differ diff --git a/img/sm_old/nilfgaard_nausicaa_brigade.jpg b/img/sm_old/nilfgaard_nausicaa_brigade.jpg new file mode 100644 index 0000000..09a072e Binary files /dev/null and b/img/sm_old/nilfgaard_nausicaa_brigade.jpg differ diff --git a/img/sm_old/nilfgaard_nausicaa_standard_bearer.jpg b/img/sm_old/nilfgaard_nausicaa_standard_bearer.jpg new file mode 100644 index 0000000..467ef78 Binary files /dev/null and b/img/sm_old/nilfgaard_nausicaa_standard_bearer.jpg differ diff --git a/img/sm_old/nilfgaard_nauzicaa_1.jpg b/img/sm_old/nilfgaard_nauzicaa_1.jpg new file mode 100644 index 0000000..757776d Binary files /dev/null and b/img/sm_old/nilfgaard_nauzicaa_1.jpg differ diff --git a/img/sm_old/nilfgaard_nauzicaa_2.jpg b/img/sm_old/nilfgaard_nauzicaa_2.jpg new file mode 100644 index 0000000..5e42d84 Binary files /dev/null and b/img/sm_old/nilfgaard_nauzicaa_2.jpg differ diff --git a/img/sm_old/nilfgaard_nauzicaa_3.jpg b/img/sm_old/nilfgaard_nauzicaa_3.jpg new file mode 100644 index 0000000..93727a3 Binary files /dev/null and b/img/sm_old/nilfgaard_nauzicaa_3.jpg differ diff --git a/img/sm_old/nilfgaard_peter_saar_gwynleve.jpg b/img/sm_old/nilfgaard_peter_saar_gwynleve.jpg new file mode 100644 index 0000000..ac86ee5 Binary files /dev/null and b/img/sm_old/nilfgaard_peter_saar_gwynleve.jpg differ diff --git a/img/sm_old/nilfgaard_puttkammer.jpg b/img/sm_old/nilfgaard_puttkammer.jpg new file mode 100644 index 0000000..352c757 Binary files /dev/null and b/img/sm_old/nilfgaard_puttkammer.jpg differ diff --git a/img/sm_old/nilfgaard_rainfarn.jpg b/img/sm_old/nilfgaard_rainfarn.jpg new file mode 100644 index 0000000..33e582b Binary files /dev/null and b/img/sm_old/nilfgaard_rainfarn.jpg differ diff --git a/img/sm_old/nilfgaard_ramon_tyrconnel.jpg b/img/sm_old/nilfgaard_ramon_tyrconnel.jpg new file mode 100644 index 0000000..04004f2 Binary files /dev/null and b/img/sm_old/nilfgaard_ramon_tyrconnel.jpg differ diff --git a/img/sm_old/nilfgaard_renuald.jpg b/img/sm_old/nilfgaard_renuald.jpg new file mode 100644 index 0000000..6153bff Binary files /dev/null and b/img/sm_old/nilfgaard_renuald.jpg differ diff --git a/img/sm_old/nilfgaard_rot_tosser.jpg b/img/sm_old/nilfgaard_rot_tosser.jpg new file mode 100644 index 0000000..c7371a8 Binary files /dev/null and b/img/sm_old/nilfgaard_rot_tosser.jpg differ diff --git a/img/sm_old/nilfgaard_rotten.jpg b/img/sm_old/nilfgaard_rotten.jpg new file mode 100644 index 0000000..81396a2 Binary files /dev/null and b/img/sm_old/nilfgaard_rotten.jpg differ diff --git a/img/sm_old/nilfgaard_shilard.jpg b/img/sm_old/nilfgaard_shilard.jpg new file mode 100644 index 0000000..ce698ae Binary files /dev/null and b/img/sm_old/nilfgaard_shilard.jpg differ diff --git a/img/sm_old/nilfgaard_siege_engineer.jpg b/img/sm_old/nilfgaard_siege_engineer.jpg new file mode 100644 index 0000000..8b5a7ce Binary files /dev/null and b/img/sm_old/nilfgaard_siege_engineer.jpg differ diff --git a/img/sm_old/nilfgaard_siege_support.jpg b/img/sm_old/nilfgaard_siege_support.jpg new file mode 100644 index 0000000..969f1f9 Binary files /dev/null and b/img/sm_old/nilfgaard_siege_support.jpg differ diff --git a/img/sm_old/nilfgaard_slave_infantry_1.jpg b/img/sm_old/nilfgaard_slave_infantry_1.jpg new file mode 100644 index 0000000..470e6d1 Binary files /dev/null and b/img/sm_old/nilfgaard_slave_infantry_1.jpg differ diff --git a/img/sm_old/nilfgaard_slave_infantry_2.jpg b/img/sm_old/nilfgaard_slave_infantry_2.jpg new file mode 100644 index 0000000..af8a7f6 Binary files /dev/null and b/img/sm_old/nilfgaard_slave_infantry_2.jpg differ diff --git a/img/sm_old/nilfgaard_spotter.jpg b/img/sm_old/nilfgaard_spotter.jpg new file mode 100644 index 0000000..7c94eed Binary files /dev/null and b/img/sm_old/nilfgaard_spotter.jpg differ diff --git a/img/sm_old/nilfgaard_standard_bearer.jpg b/img/sm_old/nilfgaard_standard_bearer.jpg new file mode 100644 index 0000000..e841361 Binary files /dev/null and b/img/sm_old/nilfgaard_standard_bearer.jpg differ diff --git a/img/sm_old/nilfgaard_stefan.jpg b/img/sm_old/nilfgaard_stefan.jpg new file mode 100644 index 0000000..a41c4ea Binary files /dev/null and b/img/sm_old/nilfgaard_stefan.jpg differ diff --git a/img/sm_old/nilfgaard_sweers.jpg b/img/sm_old/nilfgaard_sweers.jpg new file mode 100644 index 0000000..74edd27 Binary files /dev/null and b/img/sm_old/nilfgaard_sweers.jpg differ diff --git a/img/sm_old/nilfgaard_tibor.jpg b/img/sm_old/nilfgaard_tibor.jpg new file mode 100644 index 0000000..f051196 Binary files /dev/null and b/img/sm_old/nilfgaard_tibor.jpg differ diff --git a/img/sm_old/nilfgaard_traheaern_vdyffir.jpg b/img/sm_old/nilfgaard_traheaern_vdyffir.jpg new file mode 100644 index 0000000..e59b955 Binary files /dev/null and b/img/sm_old/nilfgaard_traheaern_vdyffir.jpg differ diff --git a/img/sm_old/nilfgaard_treason.jpg b/img/sm_old/nilfgaard_treason.jpg new file mode 100644 index 0000000..4eff7fd Binary files /dev/null and b/img/sm_old/nilfgaard_treason.jpg differ diff --git a/img/sm_old/nilfgaard_usurper.jpg b/img/sm_old/nilfgaard_usurper.jpg new file mode 100644 index 0000000..82bb8e6 Binary files /dev/null and b/img/sm_old/nilfgaard_usurper.jpg differ diff --git a/img/sm_old/nilfgaard_vanhemar.jpg b/img/sm_old/nilfgaard_vanhemar.jpg new file mode 100644 index 0000000..52ae929 Binary files /dev/null and b/img/sm_old/nilfgaard_vanhemar.jpg differ diff --git a/img/sm_old/nilfgaard_vattier.jpg b/img/sm_old/nilfgaard_vattier.jpg new file mode 100644 index 0000000..3c44af2 Binary files /dev/null and b/img/sm_old/nilfgaard_vattier.jpg differ diff --git a/img/sm_old/nilfgaard_venendal_elite.jpg b/img/sm_old/nilfgaard_venendal_elite.jpg new file mode 100644 index 0000000..a2c6a6b Binary files /dev/null and b/img/sm_old/nilfgaard_venendal_elite.jpg differ diff --git a/img/sm_old/nilfgaard_vicovaro_medic.jpg b/img/sm_old/nilfgaard_vicovaro_medic.jpg new file mode 100644 index 0000000..e6fbbc9 Binary files /dev/null and b/img/sm_old/nilfgaard_vicovaro_medic.jpg differ diff --git a/img/sm_old/nilfgaard_vreemde.jpg b/img/sm_old/nilfgaard_vreemde.jpg new file mode 100644 index 0000000..0ea098b Binary files /dev/null and b/img/sm_old/nilfgaard_vreemde.jpg differ diff --git a/img/sm_old/nilfgaard_vrygheff.jpg b/img/sm_old/nilfgaard_vrygheff.jpg new file mode 100644 index 0000000..f300ea0 Binary files /dev/null and b/img/sm_old/nilfgaard_vrygheff.jpg differ diff --git a/img/sm_old/nilfgaard_xarthisius.jpg b/img/sm_old/nilfgaard_xarthisius.jpg new file mode 100644 index 0000000..9610af3 Binary files /dev/null and b/img/sm_old/nilfgaard_xarthisius.jpg differ diff --git a/img/sm_old/nilfgaard_young_emissary_1.jpg b/img/sm_old/nilfgaard_young_emissary_1.jpg new file mode 100644 index 0000000..16ab675 Binary files /dev/null and b/img/sm_old/nilfgaard_young_emissary_1.jpg differ diff --git a/img/sm_old/nilfgaard_young_emissary_2.jpg b/img/sm_old/nilfgaard_young_emissary_2.jpg new file mode 100644 index 0000000..7a80678 Binary files /dev/null and b/img/sm_old/nilfgaard_young_emissary_2.jpg differ diff --git a/img/sm_old/nilfgaard_zerri.jpg b/img/sm_old/nilfgaard_zerri.jpg new file mode 100644 index 0000000..48ed0f9 Binary files /dev/null and b/img/sm_old/nilfgaard_zerri.jpg differ diff --git a/img/sm_old/realms_aretuza_adept.jpg b/img/sm_old/realms_aretuza_adept.jpg new file mode 100644 index 0000000..4061bd9 Binary files /dev/null and b/img/sm_old/realms_aretuza_adept.jpg differ diff --git a/img/sm_old/realms_ballista.jpg b/img/sm_old/realms_ballista.jpg new file mode 100644 index 0000000..511ef00 Binary files /dev/null and b/img/sm_old/realms_ballista.jpg differ diff --git a/img/sm_old/realms_ban_ard_tutor.jpg b/img/sm_old/realms_ban_ard_tutor.jpg new file mode 100644 index 0000000..c1210ef Binary files /dev/null and b/img/sm_old/realms_ban_ard_tutor.jpg differ diff --git a/img/sm_old/realms_banner_nurse.jpg b/img/sm_old/realms_banner_nurse.jpg new file mode 100644 index 0000000..c733cbd Binary files /dev/null and b/img/sm_old/realms_banner_nurse.jpg differ diff --git a/img/sm_old/realms_battering_ram.jpg b/img/sm_old/realms_battering_ram.jpg new file mode 100644 index 0000000..49c668c Binary files /dev/null and b/img/sm_old/realms_battering_ram.jpg differ diff --git a/img/sm_old/realms_black_rayla.jpg b/img/sm_old/realms_black_rayla.jpg new file mode 100644 index 0000000..f747b1c Binary files /dev/null and b/img/sm_old/realms_black_rayla.jpg differ diff --git a/img/sm_old/realms_blue_stripes_1.jpg b/img/sm_old/realms_blue_stripes_1.jpg new file mode 100644 index 0000000..d53ac6f Binary files /dev/null and b/img/sm_old/realms_blue_stripes_1.jpg differ diff --git a/img/sm_old/realms_blue_stripes_2.jpg b/img/sm_old/realms_blue_stripes_2.jpg new file mode 100644 index 0000000..4dd51bd Binary files /dev/null and b/img/sm_old/realms_blue_stripes_2.jpg differ diff --git a/img/sm_old/realms_blue_stripes_3.jpg b/img/sm_old/realms_blue_stripes_3.jpg new file mode 100644 index 0000000..823cbf3 Binary files /dev/null and b/img/sm_old/realms_blue_stripes_3.jpg differ diff --git a/img/sm_old/realms_blue_stripes_skirmisher_1.jpg b/img/sm_old/realms_blue_stripes_skirmisher_1.jpg new file mode 100644 index 0000000..4ae3ee6 Binary files /dev/null and b/img/sm_old/realms_blue_stripes_skirmisher_1.jpg differ diff --git a/img/sm_old/realms_blue_stripes_skirmisher_2.jpg b/img/sm_old/realms_blue_stripes_skirmisher_2.jpg new file mode 100644 index 0000000..3d518d8 Binary files /dev/null and b/img/sm_old/realms_blue_stripes_skirmisher_2.jpg differ diff --git a/img/sm_old/realms_blue_stripes_skirmisher_3.jpg b/img/sm_old/realms_blue_stripes_skirmisher_3.jpg new file mode 100644 index 0000000..8220c4d Binary files /dev/null and b/img/sm_old/realms_blue_stripes_skirmisher_3.jpg differ diff --git a/img/sm_old/realms_catapult_1.jpg b/img/sm_old/realms_catapult_1.jpg new file mode 100644 index 0000000..d05445e Binary files /dev/null and b/img/sm_old/realms_catapult_1.jpg differ diff --git a/img/sm_old/realms_catapult_2.jpg b/img/sm_old/realms_catapult_2.jpg new file mode 100644 index 0000000..778361d Binary files /dev/null and b/img/sm_old/realms_catapult_2.jpg differ diff --git a/img/sm_old/realms_cintrian_envoy.jpg b/img/sm_old/realms_cintrian_envoy.jpg new file mode 100644 index 0000000..0bb1836 Binary files /dev/null and b/img/sm_old/realms_cintrian_envoy.jpg differ diff --git a/img/sm_old/realms_cintrian_knight.jpg b/img/sm_old/realms_cintrian_knight.jpg new file mode 100644 index 0000000..581c4e2 Binary files /dev/null and b/img/sm_old/realms_cintrian_knight.jpg differ diff --git a/img/sm_old/realms_cintrian_peasants.jpg b/img/sm_old/realms_cintrian_peasants.jpg new file mode 100644 index 0000000..6a9db80 Binary files /dev/null and b/img/sm_old/realms_cintrian_peasants.jpg differ diff --git a/img/sm_old/realms_cintrian_royal_guard.jpg b/img/sm_old/realms_cintrian_royal_guard.jpg new file mode 100644 index 0000000..014f871 Binary files /dev/null and b/img/sm_old/realms_cintrian_royal_guard.jpg differ diff --git a/img/sm_old/realms_crinfrid_1.jpg b/img/sm_old/realms_crinfrid_1.jpg new file mode 100644 index 0000000..1ff34eb Binary files /dev/null and b/img/sm_old/realms_crinfrid_1.jpg differ diff --git a/img/sm_old/realms_crinfrid_2.jpg b/img/sm_old/realms_crinfrid_2.jpg new file mode 100644 index 0000000..8e97206 Binary files /dev/null and b/img/sm_old/realms_crinfrid_2.jpg differ diff --git a/img/sm_old/realms_crinfrid_3.jpg b/img/sm_old/realms_crinfrid_3.jpg new file mode 100644 index 0000000..666e4a9 Binary files /dev/null and b/img/sm_old/realms_crinfrid_3.jpg differ diff --git a/img/sm_old/realms_demavend.jpg b/img/sm_old/realms_demavend.jpg new file mode 100644 index 0000000..691a8cb Binary files /dev/null and b/img/sm_old/realms_demavend.jpg differ diff --git a/img/sm_old/realms_dethmold.jpg b/img/sm_old/realms_dethmold.jpg new file mode 100644 index 0000000..f924ebb Binary files /dev/null and b/img/sm_old/realms_dethmold.jpg differ diff --git a/img/sm_old/realms_dijkstra.jpg b/img/sm_old/realms_dijkstra.jpg new file mode 100644 index 0000000..c6cf524 Binary files /dev/null and b/img/sm_old/realms_dijkstra.jpg differ diff --git a/img/sm_old/realms_donimir_troy.jpg b/img/sm_old/realms_donimir_troy.jpg new file mode 100644 index 0000000..d71dc67 Binary files /dev/null and b/img/sm_old/realms_donimir_troy.jpg differ diff --git a/img/sm_old/realms_dorregaray.jpg b/img/sm_old/realms_dorregaray.jpg new file mode 100644 index 0000000..f94be3b Binary files /dev/null and b/img/sm_old/realms_dorregaray.jpg differ diff --git a/img/sm_old/realms_dun_banner_heavy_cavalry_1.jpg b/img/sm_old/realms_dun_banner_heavy_cavalry_1.jpg new file mode 100644 index 0000000..2ca3536 Binary files /dev/null and b/img/sm_old/realms_dun_banner_heavy_cavalry_1.jpg differ diff --git a/img/sm_old/realms_dun_banner_heavy_cavalry_2.jpg b/img/sm_old/realms_dun_banner_heavy_cavalry_2.jpg new file mode 100644 index 0000000..7802531 Binary files /dev/null and b/img/sm_old/realms_dun_banner_heavy_cavalry_2.jpg differ diff --git a/img/sm_old/realms_dun_banner_light_cavalry.jpg b/img/sm_old/realms_dun_banner_light_cavalry.jpg new file mode 100644 index 0000000..4ec3b52 Binary files /dev/null and b/img/sm_old/realms_dun_banner_light_cavalry.jpg differ diff --git a/img/sm_old/realms_egmund.jpg b/img/sm_old/realms_egmund.jpg new file mode 100644 index 0000000..f2d8ed7 Binary files /dev/null and b/img/sm_old/realms_egmund.jpg differ diff --git a/img/sm_old/realms_eist_tuirseach.jpg b/img/sm_old/realms_eist_tuirseach.jpg new file mode 100644 index 0000000..dea13b1 Binary files /dev/null and b/img/sm_old/realms_eist_tuirseach.jpg differ diff --git a/img/sm_old/realms_esterad.jpg b/img/sm_old/realms_esterad.jpg new file mode 100644 index 0000000..1916711 Binary files /dev/null and b/img/sm_old/realms_esterad.jpg differ diff --git a/img/sm_old/realms_ethain_cidaris.jpg b/img/sm_old/realms_ethain_cidaris.jpg new file mode 100644 index 0000000..3974a83 Binary files /dev/null and b/img/sm_old/realms_ethain_cidaris.jpg differ diff --git a/img/sm_old/realms_ewald_borsodi.jpg b/img/sm_old/realms_ewald_borsodi.jpg new file mode 100644 index 0000000..acb38a8 Binary files /dev/null and b/img/sm_old/realms_ewald_borsodi.jpg differ diff --git a/img/sm_old/realms_eyck_denesle.jpg b/img/sm_old/realms_eyck_denesle.jpg new file mode 100644 index 0000000..68c3296 Binary files /dev/null and b/img/sm_old/realms_eyck_denesle.jpg differ diff --git a/img/sm_old/realms_eylembert_tigg.jpg b/img/sm_old/realms_eylembert_tigg.jpg new file mode 100644 index 0000000..1e76c84 Binary files /dev/null and b/img/sm_old/realms_eylembert_tigg.jpg differ diff --git a/img/sm_old/realms_fake_ciri.jpg b/img/sm_old/realms_fake_ciri.jpg new file mode 100644 index 0000000..d72fbed Binary files /dev/null and b/img/sm_old/realms_fake_ciri.jpg differ diff --git a/img/sm_old/realms_falibor.jpg b/img/sm_old/realms_falibor.jpg new file mode 100644 index 0000000..a857619 Binary files /dev/null and b/img/sm_old/realms_falibor.jpg differ diff --git a/img/sm_old/realms_flying_redanian.jpg b/img/sm_old/realms_flying_redanian.jpg new file mode 100644 index 0000000..51eeb8d Binary files /dev/null and b/img/sm_old/realms_flying_redanian.jpg differ diff --git a/img/sm_old/realms_foltest_king.jpg b/img/sm_old/realms_foltest_king.jpg new file mode 100644 index 0000000..991b95c Binary files /dev/null and b/img/sm_old/realms_foltest_king.jpg differ diff --git a/img/sm_old/realms_foltest_lord.jpg b/img/sm_old/realms_foltest_lord.jpg new file mode 100644 index 0000000..3c5ca62 Binary files /dev/null and b/img/sm_old/realms_foltest_lord.jpg differ diff --git a/img/sm_old/realms_foltest_pride.jpg b/img/sm_old/realms_foltest_pride.jpg new file mode 100644 index 0000000..a867cd6 Binary files /dev/null and b/img/sm_old/realms_foltest_pride.jpg differ diff --git a/img/sm_old/realms_foltest_siegemaster.jpg b/img/sm_old/realms_foltest_siegemaster.jpg new file mode 100644 index 0000000..ff4cad8 Binary files /dev/null and b/img/sm_old/realms_foltest_siegemaster.jpg differ diff --git a/img/sm_old/realms_foltest_son_of_medell.jpg b/img/sm_old/realms_foltest_son_of_medell.jpg new file mode 100644 index 0000000..de1b976 Binary files /dev/null and b/img/sm_old/realms_foltest_son_of_medell.jpg differ diff --git a/img/sm_old/realms_foltest_steelforged.jpg b/img/sm_old/realms_foltest_steelforged.jpg new file mode 100644 index 0000000..00ca2c3 Binary files /dev/null and b/img/sm_old/realms_foltest_steelforged.jpg differ diff --git a/img/sm_old/realms_freixenet.jpg b/img/sm_old/realms_freixenet.jpg new file mode 100644 index 0000000..e0429ce Binary files /dev/null and b/img/sm_old/realms_freixenet.jpg differ diff --git a/img/sm_old/realms_hedwig_malleore.jpg b/img/sm_old/realms_hedwig_malleore.jpg new file mode 100644 index 0000000..4c48338 Binary files /dev/null and b/img/sm_old/realms_hedwig_malleore.jpg differ diff --git a/img/sm_old/realms_henry_attre.jpg b/img/sm_old/realms_henry_attre.jpg new file mode 100644 index 0000000..b81d5ea Binary files /dev/null and b/img/sm_old/realms_henry_attre.jpg differ diff --git a/img/sm_old/realms_henselt.jpg b/img/sm_old/realms_henselt.jpg new file mode 100644 index 0000000..5ca77ad Binary files /dev/null and b/img/sm_old/realms_henselt.jpg differ diff --git a/img/sm_old/realms_horst_borsodi.jpg b/img/sm_old/realms_horst_borsodi.jpg new file mode 100644 index 0000000..1d51434 Binary files /dev/null and b/img/sm_old/realms_horst_borsodi.jpg differ diff --git a/img/sm_old/realms_ildiko_breckl.jpg b/img/sm_old/realms_ildiko_breckl.jpg new file mode 100644 index 0000000..de8f5c0 Binary files /dev/null and b/img/sm_old/realms_ildiko_breckl.jpg differ diff --git a/img/sm_old/realms_isbel_hagge.jpg b/img/sm_old/realms_isbel_hagge.jpg new file mode 100644 index 0000000..a1d86b8 Binary files /dev/null and b/img/sm_old/realms_isbel_hagge.jpg differ diff --git a/img/sm_old/realms_joachim_gratz.jpg b/img/sm_old/realms_joachim_gratz.jpg new file mode 100644 index 0000000..30c47aa Binary files /dev/null and b/img/sm_old/realms_joachim_gratz.jpg differ diff --git a/img/sm_old/realms_kaedwen_siege.jpg b/img/sm_old/realms_kaedwen_siege.jpg new file mode 100644 index 0000000..10d25ee Binary files /dev/null and b/img/sm_old/realms_kaedwen_siege.jpg differ diff --git a/img/sm_old/realms_kaedwen_siege_1.jpg b/img/sm_old/realms_kaedwen_siege_1.jpg new file mode 100644 index 0000000..0dca858 Binary files /dev/null and b/img/sm_old/realms_kaedwen_siege_1.jpg differ diff --git a/img/sm_old/realms_kaedwen_siege_2.jpg b/img/sm_old/realms_kaedwen_siege_2.jpg new file mode 100644 index 0000000..06519a6 Binary files /dev/null and b/img/sm_old/realms_kaedwen_siege_2.jpg differ diff --git a/img/sm_old/realms_kaedweni_knight.jpg b/img/sm_old/realms_kaedweni_knight.jpg new file mode 100644 index 0000000..f767045 Binary files /dev/null and b/img/sm_old/realms_kaedweni_knight.jpg differ diff --git a/img/sm_old/realms_kaedweni_reinforcement.jpg b/img/sm_old/realms_kaedweni_reinforcement.jpg new file mode 100644 index 0000000..1b9da15 Binary files /dev/null and b/img/sm_old/realms_kaedweni_reinforcement.jpg differ diff --git a/img/sm_old/realms_kaedweni_sergeant.jpg b/img/sm_old/realms_kaedweni_sergeant.jpg new file mode 100644 index 0000000..6b810cc Binary files /dev/null and b/img/sm_old/realms_kaedweni_sergeant.jpg differ diff --git a/img/sm_old/realms_kaedweni_siege_support_1.jpg b/img/sm_old/realms_kaedweni_siege_support_1.jpg new file mode 100644 index 0000000..89e1187 Binary files /dev/null and b/img/sm_old/realms_kaedweni_siege_support_1.jpg differ diff --git a/img/sm_old/realms_kaedweni_siege_support_2.jpg b/img/sm_old/realms_kaedweni_siege_support_2.jpg new file mode 100644 index 0000000..ebb7da5 Binary files /dev/null and b/img/sm_old/realms_kaedweni_siege_support_2.jpg differ diff --git a/img/sm_old/realms_keira.jpg b/img/sm_old/realms_keira.jpg new file mode 100644 index 0000000..08e6aa3 Binary files /dev/null and b/img/sm_old/realms_keira.jpg differ diff --git a/img/sm_old/realms_keira_old.jpg b/img/sm_old/realms_keira_old.jpg new file mode 100644 index 0000000..ec01007 Binary files /dev/null and b/img/sm_old/realms_keira_old.jpg differ diff --git a/img/sm_old/realms_kerack_city_guard.jpg b/img/sm_old/realms_kerack_city_guard.jpg new file mode 100644 index 0000000..80027d0 Binary files /dev/null and b/img/sm_old/realms_kerack_city_guard.jpg differ diff --git a/img/sm_old/realms_kerack_fleet_frigate.jpg b/img/sm_old/realms_kerack_fleet_frigate.jpg new file mode 100644 index 0000000..b375456 Binary files /dev/null and b/img/sm_old/realms_kerack_fleet_frigate.jpg differ diff --git a/img/sm_old/realms_kerack_fleet_marine_1.jpg b/img/sm_old/realms_kerack_fleet_marine_1.jpg new file mode 100644 index 0000000..be6d7d8 Binary files /dev/null and b/img/sm_old/realms_kerack_fleet_marine_1.jpg differ diff --git a/img/sm_old/realms_kerack_fleet_marine_2.jpg b/img/sm_old/realms_kerack_fleet_marine_2.jpg new file mode 100644 index 0000000..8a6c5db Binary files /dev/null and b/img/sm_old/realms_kerack_fleet_marine_2.jpg differ diff --git a/img/sm_old/realms_king_belohun.jpg b/img/sm_old/realms_king_belohun.jpg new file mode 100644 index 0000000..2a0ca6a Binary files /dev/null and b/img/sm_old/realms_king_belohun.jpg differ diff --git a/img/sm_old/realms_kistrin_verden.jpg b/img/sm_old/realms_kistrin_verden.jpg new file mode 100644 index 0000000..ec91040 Binary files /dev/null and b/img/sm_old/realms_kistrin_verden.jpg differ diff --git a/img/sm_old/realms_kraken.jpg b/img/sm_old/realms_kraken.jpg new file mode 100644 index 0000000..f3df075 Binary files /dev/null and b/img/sm_old/realms_kraken.jpg differ diff --git a/img/sm_old/realms_letande_lavet.jpg b/img/sm_old/realms_letande_lavet.jpg new file mode 100644 index 0000000..955cbce Binary files /dev/null and b/img/sm_old/realms_letande_lavet.jpg differ diff --git a/img/sm_old/realms_lyrian_arbalest.jpg b/img/sm_old/realms_lyrian_arbalest.jpg new file mode 100644 index 0000000..dfb2891 Binary files /dev/null and b/img/sm_old/realms_lyrian_arbalest.jpg differ diff --git a/img/sm_old/realms_lyrian_heavy_cavalry.jpg b/img/sm_old/realms_lyrian_heavy_cavalry.jpg new file mode 100644 index 0000000..7bf75ac Binary files /dev/null and b/img/sm_old/realms_lyrian_heavy_cavalry.jpg differ diff --git a/img/sm_old/realms_lyrian_landsknecht.jpg b/img/sm_old/realms_lyrian_landsknecht.jpg new file mode 100644 index 0000000..edf6fee Binary files /dev/null and b/img/sm_old/realms_lyrian_landsknecht.jpg differ diff --git a/img/sm_old/realms_mage_infiltrator.jpg b/img/sm_old/realms_mage_infiltrator.jpg new file mode 100644 index 0000000..7f70e1c Binary files /dev/null and b/img/sm_old/realms_mage_infiltrator.jpg differ diff --git a/img/sm_old/realms_marching_orders.jpg b/img/sm_old/realms_marching_orders.jpg new file mode 100644 index 0000000..43e2d35 Binary files /dev/null and b/img/sm_old/realms_marching_orders.jpg differ diff --git a/img/sm_old/realms_milo_vanderbeck.jpg b/img/sm_old/realms_milo_vanderbeck.jpg new file mode 100644 index 0000000..3147d53 Binary files /dev/null and b/img/sm_old/realms_milo_vanderbeck.jpg differ diff --git a/img/sm_old/realms_mousesack.jpg b/img/sm_old/realms_mousesack.jpg new file mode 100644 index 0000000..7ac7f62 Binary files /dev/null and b/img/sm_old/realms_mousesack.jpg differ diff --git a/img/sm_old/realms_nastrog_beady_eyes.jpg b/img/sm_old/realms_nastrog_beady_eyes.jpg new file mode 100644 index 0000000..bc62034 Binary files /dev/null and b/img/sm_old/realms_nastrog_beady_eyes.jpg differ diff --git a/img/sm_old/realms_nastrog_brick.jpg b/img/sm_old/realms_nastrog_brick.jpg new file mode 100644 index 0000000..2ab67b0 Binary files /dev/null and b/img/sm_old/realms_nastrog_brick.jpg differ diff --git a/img/sm_old/realms_nastrog_junghans.jpg b/img/sm_old/realms_nastrog_junghans.jpg new file mode 100644 index 0000000..3d3ebb7 Binary files /dev/null and b/img/sm_old/realms_nastrog_junghans.jpg differ diff --git a/img/sm_old/realms_nastrog_levecque.jpg b/img/sm_old/realms_nastrog_levecque.jpg new file mode 100644 index 0000000..f0cb5c4 Binary files /dev/null and b/img/sm_old/realms_nastrog_levecque.jpg differ diff --git a/img/sm_old/realms_natalis.jpg b/img/sm_old/realms_natalis.jpg new file mode 100644 index 0000000..73c9d64 Binary files /dev/null and b/img/sm_old/realms_natalis.jpg differ diff --git a/img/sm_old/realms_northern_wind.jpg b/img/sm_old/realms_northern_wind.jpg new file mode 100644 index 0000000..fc6c4a6 Binary files /dev/null and b/img/sm_old/realms_northern_wind.jpg differ diff --git a/img/sm_old/realms_odrin.jpg b/img/sm_old/realms_odrin.jpg new file mode 100644 index 0000000..ac97f5f Binary files /dev/null and b/img/sm_old/realms_odrin.jpg differ diff --git a/img/sm_old/realms_pavetta.jpg b/img/sm_old/realms_pavetta.jpg new file mode 100644 index 0000000..0a89b7c Binary files /dev/null and b/img/sm_old/realms_pavetta.jpg differ diff --git a/img/sm_old/realms_philippa.jpg b/img/sm_old/realms_philippa.jpg new file mode 100644 index 0000000..a894271 Binary files /dev/null and b/img/sm_old/realms_philippa.jpg differ diff --git a/img/sm_old/realms_poor_infantry_1.jpg b/img/sm_old/realms_poor_infantry_1.jpg new file mode 100644 index 0000000..48d054c Binary files /dev/null and b/img/sm_old/realms_poor_infantry_1.jpg differ diff --git a/img/sm_old/realms_poor_infantry_2.jpg b/img/sm_old/realms_poor_infantry_2.jpg new file mode 100644 index 0000000..4a261f2 Binary files /dev/null and b/img/sm_old/realms_poor_infantry_2.jpg differ diff --git a/img/sm_old/realms_poor_infantry_3.jpg b/img/sm_old/realms_poor_infantry_3.jpg new file mode 100644 index 0000000..9d1901b Binary files /dev/null and b/img/sm_old/realms_poor_infantry_3.jpg differ diff --git a/img/sm_old/realms_poor_infantry_4.jpg b/img/sm_old/realms_poor_infantry_4.jpg new file mode 100644 index 0000000..18f1248 Binary files /dev/null and b/img/sm_old/realms_poor_infantry_4.jpg differ diff --git a/img/sm_old/realms_poor_infantry_5.jpg b/img/sm_old/realms_poor_infantry_5.jpg new file mode 100644 index 0000000..4f28287 Binary files /dev/null and b/img/sm_old/realms_poor_infantry_5.jpg differ diff --git a/img/sm_old/realms_poor_infantry_6.jpg b/img/sm_old/realms_poor_infantry_6.jpg new file mode 100644 index 0000000..9e75614 Binary files /dev/null and b/img/sm_old/realms_poor_infantry_6.jpg differ diff --git a/img/sm_old/realms_prince_anseis.jpg b/img/sm_old/realms_prince_anseis.jpg new file mode 100644 index 0000000..db043e8 Binary files /dev/null and b/img/sm_old/realms_prince_anseis.jpg differ diff --git a/img/sm_old/realms_queen_adalia.jpg b/img/sm_old/realms_queen_adalia.jpg new file mode 100644 index 0000000..a4141d8 Binary files /dev/null and b/img/sm_old/realms_queen_adalia.jpg differ diff --git a/img/sm_old/realms_queen_calanthe.jpg b/img/sm_old/realms_queen_calanthe.jpg new file mode 100644 index 0000000..aeb6ed2 Binary files /dev/null and b/img/sm_old/realms_queen_calanthe.jpg differ diff --git a/img/sm_old/realms_queen_meve.jpg b/img/sm_old/realms_queen_meve.jpg new file mode 100644 index 0000000..bd3d3d9 Binary files /dev/null and b/img/sm_old/realms_queen_meve.jpg differ diff --git a/img/sm_old/realms_radovid_royal_guards.jpg b/img/sm_old/realms_radovid_royal_guards.jpg new file mode 100644 index 0000000..288df5a Binary files /dev/null and b/img/sm_old/realms_radovid_royal_guards.jpg differ diff --git a/img/sm_old/realms_radovid_ruthless.jpg b/img/sm_old/realms_radovid_ruthless.jpg new file mode 100644 index 0000000..07a7e0f Binary files /dev/null and b/img/sm_old/realms_radovid_ruthless.jpg differ diff --git a/img/sm_old/realms_radovid_stern.jpg b/img/sm_old/realms_radovid_stern.jpg new file mode 100644 index 0000000..82651c1 Binary files /dev/null and b/img/sm_old/realms_radovid_stern.jpg differ diff --git a/img/sm_old/realms_rainfarn.jpg b/img/sm_old/realms_rainfarn.jpg new file mode 100644 index 0000000..99bc11d Binary files /dev/null and b/img/sm_old/realms_rainfarn.jpg differ diff --git a/img/sm_old/realms_reaver_scout.jpg b/img/sm_old/realms_reaver_scout.jpg new file mode 100644 index 0000000..970426a Binary files /dev/null and b/img/sm_old/realms_reaver_scout.jpg differ diff --git a/img/sm_old/realms_redania.jpg b/img/sm_old/realms_redania.jpg new file mode 100644 index 0000000..b07d2b7 Binary files /dev/null and b/img/sm_old/realms_redania.jpg differ diff --git a/img/sm_old/realms_redania_1.jpg b/img/sm_old/realms_redania_1.jpg new file mode 100644 index 0000000..d5b9bde Binary files /dev/null and b/img/sm_old/realms_redania_1.jpg differ diff --git a/img/sm_old/realms_redanian_archer.jpg b/img/sm_old/realms_redanian_archer.jpg new file mode 100644 index 0000000..0a920f1 Binary files /dev/null and b/img/sm_old/realms_redanian_archer.jpg differ diff --git a/img/sm_old/realms_redanian_elite.jpg b/img/sm_old/realms_redanian_elite.jpg new file mode 100644 index 0000000..714d766 Binary files /dev/null and b/img/sm_old/realms_redanian_elite.jpg differ diff --git a/img/sm_old/realms_redanian_knight.jpg b/img/sm_old/realms_redanian_knight.jpg new file mode 100644 index 0000000..dee3c15 Binary files /dev/null and b/img/sm_old/realms_redanian_knight.jpg differ diff --git a/img/sm_old/realms_reinforced_ballista_1.jpg b/img/sm_old/realms_reinforced_ballista_1.jpg new file mode 100644 index 0000000..078efde Binary files /dev/null and b/img/sm_old/realms_reinforced_ballista_1.jpg differ diff --git a/img/sm_old/realms_reinforced_ballista_2.jpg b/img/sm_old/realms_reinforced_ballista_2.jpg new file mode 100644 index 0000000..c9abb6f Binary files /dev/null and b/img/sm_old/realms_reinforced_ballista_2.jpg differ diff --git a/img/sm_old/realms_reinforced_tower.jpg b/img/sm_old/realms_reinforced_tower.jpg new file mode 100644 index 0000000..ef8d11c Binary files /dev/null and b/img/sm_old/realms_reinforced_tower.jpg differ diff --git a/img/sm_old/realms_reinforced_trebuchet_1.jpg b/img/sm_old/realms_reinforced_trebuchet_1.jpg new file mode 100644 index 0000000..5b75658 Binary files /dev/null and b/img/sm_old/realms_reinforced_trebuchet_1.jpg differ diff --git a/img/sm_old/realms_reinforced_trebuchet_2.jpg b/img/sm_old/realms_reinforced_trebuchet_2.jpg new file mode 100644 index 0000000..bbe352c Binary files /dev/null and b/img/sm_old/realms_reinforced_trebuchet_2.jpg differ diff --git a/img/sm_old/realms_rivian_onager.jpg b/img/sm_old/realms_rivian_onager.jpg new file mode 100644 index 0000000..91095a5 Binary files /dev/null and b/img/sm_old/realms_rivian_onager.jpg differ diff --git a/img/sm_old/realms_roegner.jpg b/img/sm_old/realms_roegner.jpg new file mode 100644 index 0000000..57b683a Binary files /dev/null and b/img/sm_old/realms_roegner.jpg differ diff --git a/img/sm_old/realms_royal_decree.jpg b/img/sm_old/realms_royal_decree.jpg new file mode 100644 index 0000000..48d8f1b Binary files /dev/null and b/img/sm_old/realms_royal_decree.jpg differ diff --git a/img/sm_old/realms_sabrina.jpg b/img/sm_old/realms_sabrina.jpg new file mode 100644 index 0000000..040b774 Binary files /dev/null and b/img/sm_old/realms_sabrina.jpg differ diff --git a/img/sm_old/realms_seltkirk.jpg b/img/sm_old/realms_seltkirk.jpg new file mode 100644 index 0000000..105ed7a Binary files /dev/null and b/img/sm_old/realms_seltkirk.jpg differ diff --git a/img/sm_old/realms_sha.jpg b/img/sm_old/realms_sha.jpg new file mode 100644 index 0000000..290c824 Binary files /dev/null and b/img/sm_old/realms_sha.jpg differ diff --git a/img/sm_old/realms_shani.jpg b/img/sm_old/realms_shani.jpg new file mode 100644 index 0000000..0367e0f Binary files /dev/null and b/img/sm_old/realms_shani.jpg differ diff --git a/img/sm_old/realms_sheala.jpg b/img/sm_old/realms_sheala.jpg new file mode 100644 index 0000000..5e5cab1 Binary files /dev/null and b/img/sm_old/realms_sheala.jpg differ diff --git a/img/sm_old/realms_sheldon.jpg b/img/sm_old/realms_sheldon.jpg new file mode 100644 index 0000000..b15f7e7 Binary files /dev/null and b/img/sm_old/realms_sheldon.jpg differ diff --git a/img/sm_old/realms_siege_tower.jpg b/img/sm_old/realms_siege_tower.jpg new file mode 100644 index 0000000..24451b5 Binary files /dev/null and b/img/sm_old/realms_siege_tower.jpg differ diff --git a/img/sm_old/realms_siegfried.jpg b/img/sm_old/realms_siegfried.jpg new file mode 100644 index 0000000..3eca781 Binary files /dev/null and b/img/sm_old/realms_siegfried.jpg differ diff --git a/img/sm_old/realms_skellige_fleet_1.jpg b/img/sm_old/realms_skellige_fleet_1.jpg new file mode 100644 index 0000000..e9c6ae8 Binary files /dev/null and b/img/sm_old/realms_skellige_fleet_1.jpg differ diff --git a/img/sm_old/realms_skellige_fleet_2.jpg b/img/sm_old/realms_skellige_fleet_2.jpg new file mode 100644 index 0000000..e51b713 Binary files /dev/null and b/img/sm_old/realms_skellige_fleet_2.jpg differ diff --git a/img/sm_old/realms_skellige_fleet_3.jpg b/img/sm_old/realms_skellige_fleet_3.jpg new file mode 100644 index 0000000..29d2895 Binary files /dev/null and b/img/sm_old/realms_skellige_fleet_3.jpg differ diff --git a/img/sm_old/realms_stennis.jpg b/img/sm_old/realms_stennis.jpg new file mode 100644 index 0000000..d12c965 Binary files /dev/null and b/img/sm_old/realms_stennis.jpg differ diff --git a/img/sm_old/realms_stripes_scout.jpg b/img/sm_old/realms_stripes_scout.jpg new file mode 100644 index 0000000..d3f198f Binary files /dev/null and b/img/sm_old/realms_stripes_scout.jpg differ diff --git a/img/sm_old/realms_temerian_drummer.jpg b/img/sm_old/realms_temerian_drummer.jpg new file mode 100644 index 0000000..9d5a030 Binary files /dev/null and b/img/sm_old/realms_temerian_drummer.jpg differ diff --git a/img/sm_old/realms_temerian_soldier_1.jpg b/img/sm_old/realms_temerian_soldier_1.jpg new file mode 100644 index 0000000..a9e75ae Binary files /dev/null and b/img/sm_old/realms_temerian_soldier_1.jpg differ diff --git a/img/sm_old/realms_temerian_soldier_2.jpg b/img/sm_old/realms_temerian_soldier_2.jpg new file mode 100644 index 0000000..0f4beaa Binary files /dev/null and b/img/sm_old/realms_temerian_soldier_2.jpg differ diff --git a/img/sm_old/realms_temerian_soldier_3.jpg b/img/sm_old/realms_temerian_soldier_3.jpg new file mode 100644 index 0000000..67ef2ca Binary files /dev/null and b/img/sm_old/realms_temerian_soldier_3.jpg differ diff --git a/img/sm_old/realms_thaler.jpg b/img/sm_old/realms_thaler.jpg new file mode 100644 index 0000000..77119fd Binary files /dev/null and b/img/sm_old/realms_thaler.jpg differ diff --git a/img/sm_old/realms_trebuchet.jpg b/img/sm_old/realms_trebuchet.jpg new file mode 100644 index 0000000..0e1801e Binary files /dev/null and b/img/sm_old/realms_trebuchet.jpg differ diff --git a/img/sm_old/realms_trebuchet_1.jpg b/img/sm_old/realms_trebuchet_1.jpg new file mode 100644 index 0000000..6a82b5c Binary files /dev/null and b/img/sm_old/realms_trebuchet_1.jpg differ diff --git a/img/sm_old/realms_tridam_infantry.jpg b/img/sm_old/realms_tridam_infantry.jpg new file mode 100644 index 0000000..8114aec Binary files /dev/null and b/img/sm_old/realms_tridam_infantry.jpg differ diff --git a/img/sm_old/realms_trollololo.jpg b/img/sm_old/realms_trollololo.jpg new file mode 100644 index 0000000..7580492 Binary files /dev/null and b/img/sm_old/realms_trollololo.jpg differ diff --git a/img/sm_old/realms_urcheon.jpg b/img/sm_old/realms_urcheon.jpg new file mode 100644 index 0000000..9852b0b Binary files /dev/null and b/img/sm_old/realms_urcheon.jpg differ diff --git a/img/sm_old/realms_valdo_marx.jpg b/img/sm_old/realms_valdo_marx.jpg new file mode 100644 index 0000000..56e9a8b Binary files /dev/null and b/img/sm_old/realms_valdo_marx.jpg differ diff --git a/img/sm_old/realms_vandergrift.jpg b/img/sm_old/realms_vandergrift.jpg new file mode 100644 index 0000000..55725de Binary files /dev/null and b/img/sm_old/realms_vandergrift.jpg differ diff --git a/img/sm_old/realms_vernon.jpg b/img/sm_old/realms_vernon.jpg new file mode 100644 index 0000000..39d7945 Binary files /dev/null and b/img/sm_old/realms_vernon.jpg differ diff --git a/img/sm_old/realms_ves.jpg b/img/sm_old/realms_ves.jpg new file mode 100644 index 0000000..7ee9e93 Binary files /dev/null and b/img/sm_old/realms_ves.jpg differ diff --git a/img/sm_old/realms_viraxas.jpg b/img/sm_old/realms_viraxas.jpg new file mode 100644 index 0000000..267bac1 Binary files /dev/null and b/img/sm_old/realms_viraxas.jpg differ diff --git a/img/sm_old/realms_vissegerd.jpg b/img/sm_old/realms_vissegerd.jpg new file mode 100644 index 0000000..c9d858f Binary files /dev/null and b/img/sm_old/realms_vissegerd.jpg differ diff --git a/img/sm_old/realms_vizimir.jpg b/img/sm_old/realms_vizimir.jpg new file mode 100644 index 0000000..be2431d Binary files /dev/null and b/img/sm_old/realms_vizimir.jpg differ diff --git a/img/sm_old/realms_voymir.jpg b/img/sm_old/realms_voymir.jpg new file mode 100644 index 0000000..4e4259c Binary files /dev/null and b/img/sm_old/realms_voymir.jpg differ diff --git a/img/sm_old/realms_windhalm.jpg b/img/sm_old/realms_windhalm.jpg new file mode 100644 index 0000000..58efbf5 Binary files /dev/null and b/img/sm_old/realms_windhalm.jpg differ diff --git a/img/sm_old/realms_yarpen.jpg b/img/sm_old/realms_yarpen.jpg new file mode 100644 index 0000000..f3252bf Binary files /dev/null and b/img/sm_old/realms_yarpen.jpg differ diff --git a/img/sm_old/realms_young_ciri.jpg b/img/sm_old/realms_young_ciri.jpg new file mode 100644 index 0000000..7754fdd Binary files /dev/null and b/img/sm_old/realms_young_ciri.jpg differ diff --git a/img/sm_old/scoiatael_aelirenn.jpg b/img/sm_old/scoiatael_aelirenn.jpg new file mode 100644 index 0000000..6098dfb Binary files /dev/null and b/img/sm_old/scoiatael_aelirenn.jpg differ diff --git a/img/sm_old/scoiatael_aglais.jpg b/img/sm_old/scoiatael_aglais.jpg new file mode 100644 index 0000000..f52512d Binary files /dev/null and b/img/sm_old/scoiatael_aglais.jpg differ diff --git a/img/sm_old/scoiatael_barclay.jpg b/img/sm_old/scoiatael_barclay.jpg new file mode 100644 index 0000000..785861b Binary files /dev/null and b/img/sm_old/scoiatael_barclay.jpg differ diff --git a/img/sm_old/scoiatael_braenn.jpg b/img/sm_old/scoiatael_braenn.jpg new file mode 100644 index 0000000..f6dff7d Binary files /dev/null and b/img/sm_old/scoiatael_braenn.jpg differ diff --git a/img/sm_old/scoiatael_brouver_hoog.jpg b/img/sm_old/scoiatael_brouver_hoog.jpg new file mode 100644 index 0000000..1e88afb Binary files /dev/null and b/img/sm_old/scoiatael_brouver_hoog.jpg differ diff --git a/img/sm_old/scoiatael_ciaran.jpg b/img/sm_old/scoiatael_ciaran.jpg new file mode 100644 index 0000000..074b9da Binary files /dev/null and b/img/sm_old/scoiatael_ciaran.jpg differ diff --git a/img/sm_old/scoiatael_dennis.jpg b/img/sm_old/scoiatael_dennis.jpg new file mode 100644 index 0000000..cd24ae9 Binary files /dev/null and b/img/sm_old/scoiatael_dennis.jpg differ diff --git a/img/sm_old/scoiatael_dol_archer.jpg b/img/sm_old/scoiatael_dol_archer.jpg new file mode 100644 index 0000000..670c11b Binary files /dev/null and b/img/sm_old/scoiatael_dol_archer.jpg differ diff --git a/img/sm_old/scoiatael_dol_blathanna_guard_1.jpg b/img/sm_old/scoiatael_dol_blathanna_guard_1.jpg new file mode 100644 index 0000000..6d47ec7 Binary files /dev/null and b/img/sm_old/scoiatael_dol_blathanna_guard_1.jpg differ diff --git a/img/sm_old/scoiatael_dol_blathanna_guard_2.jpg b/img/sm_old/scoiatael_dol_blathanna_guard_2.jpg new file mode 100644 index 0000000..79464aa Binary files /dev/null and b/img/sm_old/scoiatael_dol_blathanna_guard_2.jpg differ diff --git a/img/sm_old/scoiatael_dol_blathanna_guard_3.jpg b/img/sm_old/scoiatael_dol_blathanna_guard_3.jpg new file mode 100644 index 0000000..baa37b0 Binary files /dev/null and b/img/sm_old/scoiatael_dol_blathanna_guard_3.jpg differ diff --git a/img/sm_old/scoiatael_dol_blathanna_sentry.jpg b/img/sm_old/scoiatael_dol_blathanna_sentry.jpg new file mode 100644 index 0000000..a795aa9 Binary files /dev/null and b/img/sm_old/scoiatael_dol_blathanna_sentry.jpg differ diff --git a/img/sm_old/scoiatael_dol_blathanna_trapper.jpg b/img/sm_old/scoiatael_dol_blathanna_trapper.jpg new file mode 100644 index 0000000..aed7338 Binary files /dev/null and b/img/sm_old/scoiatael_dol_blathanna_trapper.jpg differ diff --git a/img/sm_old/scoiatael_dol_infantry.jpg b/img/sm_old/scoiatael_dol_infantry.jpg new file mode 100644 index 0000000..bac8d6a Binary files /dev/null and b/img/sm_old/scoiatael_dol_infantry.jpg differ diff --git a/img/sm_old/scoiatael_dol_infantry_1.jpg b/img/sm_old/scoiatael_dol_infantry_1.jpg new file mode 100644 index 0000000..a239cc1 Binary files /dev/null and b/img/sm_old/scoiatael_dol_infantry_1.jpg differ diff --git a/img/sm_old/scoiatael_dol_infantry_2.jpg b/img/sm_old/scoiatael_dol_infantry_2.jpg new file mode 100644 index 0000000..17031b8 Binary files /dev/null and b/img/sm_old/scoiatael_dol_infantry_2.jpg differ diff --git a/img/sm_old/scoiatael_dryads_1.jpg b/img/sm_old/scoiatael_dryads_1.jpg new file mode 100644 index 0000000..380d5ec Binary files /dev/null and b/img/sm_old/scoiatael_dryads_1.jpg differ diff --git a/img/sm_old/scoiatael_dryads_2.jpg b/img/sm_old/scoiatael_dryads_2.jpg new file mode 100644 index 0000000..ba453fd Binary files /dev/null and b/img/sm_old/scoiatael_dryads_2.jpg differ diff --git a/img/sm_old/scoiatael_dryads_3.jpg b/img/sm_old/scoiatael_dryads_3.jpg new file mode 100644 index 0000000..9e95624 Binary files /dev/null and b/img/sm_old/scoiatael_dryads_3.jpg differ diff --git a/img/sm_old/scoiatael_dryads_4.jpg b/img/sm_old/scoiatael_dryads_4.jpg new file mode 100644 index 0000000..e9305ff Binary files /dev/null and b/img/sm_old/scoiatael_dryads_4.jpg differ diff --git a/img/sm_old/scoiatael_dwarf.jpg b/img/sm_old/scoiatael_dwarf.jpg new file mode 100644 index 0000000..d6332d5 Binary files /dev/null and b/img/sm_old/scoiatael_dwarf.jpg differ diff --git a/img/sm_old/scoiatael_dwarf_1.jpg b/img/sm_old/scoiatael_dwarf_1.jpg new file mode 100644 index 0000000..74a1c6b Binary files /dev/null and b/img/sm_old/scoiatael_dwarf_1.jpg differ diff --git a/img/sm_old/scoiatael_dwarf_2.jpg b/img/sm_old/scoiatael_dwarf_2.jpg new file mode 100644 index 0000000..1af2a72 Binary files /dev/null and b/img/sm_old/scoiatael_dwarf_2.jpg differ diff --git a/img/sm_old/scoiatael_dwarven_agitator.jpg b/img/sm_old/scoiatael_dwarven_agitator.jpg new file mode 100644 index 0000000..56450cc Binary files /dev/null and b/img/sm_old/scoiatael_dwarven_agitator.jpg differ diff --git a/img/sm_old/scoiatael_dwarven_mercenary_1.jpg b/img/sm_old/scoiatael_dwarven_mercenary_1.jpg new file mode 100644 index 0000000..0d57031 Binary files /dev/null and b/img/sm_old/scoiatael_dwarven_mercenary_1.jpg differ diff --git a/img/sm_old/scoiatael_dwarven_mercenary_2.jpg b/img/sm_old/scoiatael_dwarven_mercenary_2.jpg new file mode 100644 index 0000000..12b8cb4 Binary files /dev/null and b/img/sm_old/scoiatael_dwarven_mercenary_2.jpg differ diff --git a/img/sm_old/scoiatael_eithne.jpg b/img/sm_old/scoiatael_eithne.jpg new file mode 100644 index 0000000..7175d94 Binary files /dev/null and b/img/sm_old/scoiatael_eithne.jpg differ diff --git a/img/sm_old/scoiatael_eldain.jpg b/img/sm_old/scoiatael_eldain.jpg new file mode 100644 index 0000000..4dc7f93 Binary files /dev/null and b/img/sm_old/scoiatael_eldain.jpg differ diff --git a/img/sm_old/scoiatael_eleyas.jpg b/img/sm_old/scoiatael_eleyas.jpg new file mode 100644 index 0000000..d900be8 Binary files /dev/null and b/img/sm_old/scoiatael_eleyas.jpg differ diff --git a/img/sm_old/scoiatael_elf_skirmisher.jpg b/img/sm_old/scoiatael_elf_skirmisher.jpg new file mode 100644 index 0000000..9671e8d Binary files /dev/null and b/img/sm_old/scoiatael_elf_skirmisher.jpg differ diff --git a/img/sm_old/scoiatael_elf_skirmisher_1.jpg b/img/sm_old/scoiatael_elf_skirmisher_1.jpg new file mode 100644 index 0000000..628416b Binary files /dev/null and b/img/sm_old/scoiatael_elf_skirmisher_1.jpg differ diff --git a/img/sm_old/scoiatael_elf_skirmisher_2.jpg b/img/sm_old/scoiatael_elf_skirmisher_2.jpg new file mode 100644 index 0000000..555a12c Binary files /dev/null and b/img/sm_old/scoiatael_elf_skirmisher_2.jpg differ diff --git a/img/sm_old/scoiatael_elven_deadeye.jpg b/img/sm_old/scoiatael_elven_deadeye.jpg new file mode 100644 index 0000000..1cf0581 Binary files /dev/null and b/img/sm_old/scoiatael_elven_deadeye.jpg differ diff --git a/img/sm_old/scoiatael_elven_mercenary_1.jpg b/img/sm_old/scoiatael_elven_mercenary_1.jpg new file mode 100644 index 0000000..6866796 Binary files /dev/null and b/img/sm_old/scoiatael_elven_mercenary_1.jpg differ diff --git a/img/sm_old/scoiatael_elven_mercenary_2.jpg b/img/sm_old/scoiatael_elven_mercenary_2.jpg new file mode 100644 index 0000000..71f42ec Binary files /dev/null and b/img/sm_old/scoiatael_elven_mercenary_2.jpg differ diff --git a/img/sm_old/scoiatael_elven_scout.jpg b/img/sm_old/scoiatael_elven_scout.jpg new file mode 100644 index 0000000..9fa423c Binary files /dev/null and b/img/sm_old/scoiatael_elven_scout.jpg differ diff --git a/img/sm_old/scoiatael_elven_swordmaster.jpg b/img/sm_old/scoiatael_elven_swordmaster.jpg new file mode 100644 index 0000000..5745ad2 Binary files /dev/null and b/img/sm_old/scoiatael_elven_swordmaster.jpg differ diff --git a/img/sm_old/scoiatael_farseer.jpg b/img/sm_old/scoiatael_farseer.jpg new file mode 100644 index 0000000..0a95a53 Binary files /dev/null and b/img/sm_old/scoiatael_farseer.jpg differ diff --git a/img/sm_old/scoiatael_fauve.jpg b/img/sm_old/scoiatael_fauve.jpg new file mode 100644 index 0000000..6273df3 Binary files /dev/null and b/img/sm_old/scoiatael_fauve.jpg differ diff --git a/img/sm_old/scoiatael_filavandrel.jpg b/img/sm_old/scoiatael_filavandrel.jpg new file mode 100644 index 0000000..91b88e1 Binary files /dev/null and b/img/sm_old/scoiatael_filavandrel.jpg differ diff --git a/img/sm_old/scoiatael_francesca_beautiful.jpg b/img/sm_old/scoiatael_francesca_beautiful.jpg new file mode 100644 index 0000000..d31e30b Binary files /dev/null and b/img/sm_old/scoiatael_francesca_beautiful.jpg differ diff --git a/img/sm_old/scoiatael_francesca_daisy.jpg b/img/sm_old/scoiatael_francesca_daisy.jpg new file mode 100644 index 0000000..cfe0138 Binary files /dev/null and b/img/sm_old/scoiatael_francesca_daisy.jpg differ diff --git a/img/sm_old/scoiatael_francesca_hope_of_the_aen_seidhe.jpg b/img/sm_old/scoiatael_francesca_hope_of_the_aen_seidhe.jpg new file mode 100644 index 0000000..a10f749 Binary files /dev/null and b/img/sm_old/scoiatael_francesca_hope_of_the_aen_seidhe.jpg differ diff --git a/img/sm_old/scoiatael_francesca_pureblood.jpg b/img/sm_old/scoiatael_francesca_pureblood.jpg new file mode 100644 index 0000000..1a22a1b Binary files /dev/null and b/img/sm_old/scoiatael_francesca_pureblood.jpg differ diff --git a/img/sm_old/scoiatael_francesca_queen.jpg b/img/sm_old/scoiatael_francesca_queen.jpg new file mode 100644 index 0000000..45ae12c Binary files /dev/null and b/img/sm_old/scoiatael_francesca_queen.jpg differ diff --git a/img/sm_old/scoiatael_gabor_zigrin.jpg b/img/sm_old/scoiatael_gabor_zigrin.jpg new file mode 100644 index 0000000..be585bf Binary files /dev/null and b/img/sm_old/scoiatael_gabor_zigrin.jpg differ diff --git a/img/sm_old/scoiatael_giantslayer.jpg b/img/sm_old/scoiatael_giantslayer.jpg new file mode 100644 index 0000000..93ca40a Binary files /dev/null and b/img/sm_old/scoiatael_giantslayer.jpg differ diff --git a/img/sm_old/scoiatael_havekar_nurse.jpg b/img/sm_old/scoiatael_havekar_nurse.jpg new file mode 100644 index 0000000..2ff70d3 Binary files /dev/null and b/img/sm_old/scoiatael_havekar_nurse.jpg differ diff --git a/img/sm_old/scoiatael_havekar_nurse_1.jpg b/img/sm_old/scoiatael_havekar_nurse_1.jpg new file mode 100644 index 0000000..c4218d9 Binary files /dev/null and b/img/sm_old/scoiatael_havekar_nurse_1.jpg differ diff --git a/img/sm_old/scoiatael_havekar_nurse_2.jpg b/img/sm_old/scoiatael_havekar_nurse_2.jpg new file mode 100644 index 0000000..154a377 Binary files /dev/null and b/img/sm_old/scoiatael_havekar_nurse_2.jpg differ diff --git a/img/sm_old/scoiatael_havekar_support.jpg b/img/sm_old/scoiatael_havekar_support.jpg new file mode 100644 index 0000000..7dc528b Binary files /dev/null and b/img/sm_old/scoiatael_havekar_support.jpg differ diff --git a/img/sm_old/scoiatael_havekar_support_1.jpg b/img/sm_old/scoiatael_havekar_support_1.jpg new file mode 100644 index 0000000..b0723c4 Binary files /dev/null and b/img/sm_old/scoiatael_havekar_support_1.jpg differ diff --git a/img/sm_old/scoiatael_havekar_support_2.jpg b/img/sm_old/scoiatael_havekar_support_2.jpg new file mode 100644 index 0000000..412340a Binary files /dev/null and b/img/sm_old/scoiatael_havekar_support_2.jpg differ diff --git a/img/sm_old/scoiatael_hawker_smuggler.jpg b/img/sm_old/scoiatael_hawker_smuggler.jpg new file mode 100644 index 0000000..cc4c198 Binary files /dev/null and b/img/sm_old/scoiatael_hawker_smuggler.jpg differ diff --git a/img/sm_old/scoiatael_hawker_support.jpg b/img/sm_old/scoiatael_hawker_support.jpg new file mode 100644 index 0000000..c7c3e2d Binary files /dev/null and b/img/sm_old/scoiatael_hawker_support.jpg differ diff --git a/img/sm_old/scoiatael_ida.jpg b/img/sm_old/scoiatael_ida.jpg new file mode 100644 index 0000000..05702ae Binary files /dev/null and b/img/sm_old/scoiatael_ida.jpg differ diff --git a/img/sm_old/scoiatael_iorveth.jpg b/img/sm_old/scoiatael_iorveth.jpg new file mode 100644 index 0000000..10fcd97 Binary files /dev/null and b/img/sm_old/scoiatael_iorveth.jpg differ diff --git a/img/sm_old/scoiatael_isengrim.jpg b/img/sm_old/scoiatael_isengrim.jpg new file mode 100644 index 0000000..dd04794 Binary files /dev/null and b/img/sm_old/scoiatael_isengrim.jpg differ diff --git a/img/sm_old/scoiatael_ithlinne.jpg b/img/sm_old/scoiatael_ithlinne.jpg new file mode 100644 index 0000000..e50b050 Binary files /dev/null and b/img/sm_old/scoiatael_ithlinne.jpg differ diff --git a/img/sm_old/scoiatael_mahakam.jpg b/img/sm_old/scoiatael_mahakam.jpg new file mode 100644 index 0000000..ecaca55 Binary files /dev/null and b/img/sm_old/scoiatael_mahakam.jpg differ diff --git a/img/sm_old/scoiatael_mahakam_1.jpg b/img/sm_old/scoiatael_mahakam_1.jpg new file mode 100644 index 0000000..4f2cf44 Binary files /dev/null and b/img/sm_old/scoiatael_mahakam_1.jpg differ diff --git a/img/sm_old/scoiatael_mahakam_2.jpg b/img/sm_old/scoiatael_mahakam_2.jpg new file mode 100644 index 0000000..1ac5f90 Binary files /dev/null and b/img/sm_old/scoiatael_mahakam_2.jpg differ diff --git a/img/sm_old/scoiatael_mahakam_3.jpg b/img/sm_old/scoiatael_mahakam_3.jpg new file mode 100644 index 0000000..2c5cdb3 Binary files /dev/null and b/img/sm_old/scoiatael_mahakam_3.jpg differ diff --git a/img/sm_old/scoiatael_mahakam_4.jpg b/img/sm_old/scoiatael_mahakam_4.jpg new file mode 100644 index 0000000..ea0fc48 Binary files /dev/null and b/img/sm_old/scoiatael_mahakam_4.jpg differ diff --git a/img/sm_old/scoiatael_mahakam_ale.jpg b/img/sm_old/scoiatael_mahakam_ale.jpg new file mode 100644 index 0000000..40e5535 Binary files /dev/null and b/img/sm_old/scoiatael_mahakam_ale.jpg differ diff --git a/img/sm_old/scoiatael_mahakam_guard_1.jpg b/img/sm_old/scoiatael_mahakam_guard_1.jpg new file mode 100644 index 0000000..9d7836b Binary files /dev/null and b/img/sm_old/scoiatael_mahakam_guard_1.jpg differ diff --git a/img/sm_old/scoiatael_mahakam_guard_2.jpg b/img/sm_old/scoiatael_mahakam_guard_2.jpg new file mode 100644 index 0000000..061e31f Binary files /dev/null and b/img/sm_old/scoiatael_mahakam_guard_2.jpg differ diff --git a/img/sm_old/scoiatael_mahakam_marauder.jpg b/img/sm_old/scoiatael_mahakam_marauder.jpg new file mode 100644 index 0000000..019484f Binary files /dev/null and b/img/sm_old/scoiatael_mahakam_marauder.jpg differ diff --git a/img/sm_old/scoiatael_mahakam_pyrotechnician.jpg b/img/sm_old/scoiatael_mahakam_pyrotechnician.jpg new file mode 100644 index 0000000..cde664b Binary files /dev/null and b/img/sm_old/scoiatael_mahakam_pyrotechnician.jpg differ diff --git a/img/sm_old/scoiatael_malena.jpg b/img/sm_old/scoiatael_malena.jpg new file mode 100644 index 0000000..bdf290f Binary files /dev/null and b/img/sm_old/scoiatael_malena.jpg differ diff --git a/img/sm_old/scoiatael_milva.jpg b/img/sm_old/scoiatael_milva.jpg new file mode 100644 index 0000000..f6cc3a4 Binary files /dev/null and b/img/sm_old/scoiatael_milva.jpg differ diff --git a/img/sm_old/scoiatael_morenn.jpg b/img/sm_old/scoiatael_morenn.jpg new file mode 100644 index 0000000..2facb2c Binary files /dev/null and b/img/sm_old/scoiatael_morenn.jpg differ diff --git a/img/sm_old/scoiatael_neophyte.jpg b/img/sm_old/scoiatael_neophyte.jpg new file mode 100644 index 0000000..d737aa8 Binary files /dev/null and b/img/sm_old/scoiatael_neophyte.jpg differ diff --git a/img/sm_old/scoiatael_riordain.jpg b/img/sm_old/scoiatael_riordain.jpg new file mode 100644 index 0000000..bc449b7 Binary files /dev/null and b/img/sm_old/scoiatael_riordain.jpg differ diff --git a/img/sm_old/scoiatael_saesenthessis_dragon.jpg b/img/sm_old/scoiatael_saesenthessis_dragon.jpg new file mode 100644 index 0000000..b5ac697 Binary files /dev/null and b/img/sm_old/scoiatael_saesenthessis_dragon.jpg differ diff --git a/img/sm_old/scoiatael_saesenthessis_saskia.jpg b/img/sm_old/scoiatael_saesenthessis_saskia.jpg new file mode 100644 index 0000000..ec01628 Binary files /dev/null and b/img/sm_old/scoiatael_saesenthessis_saskia.jpg differ diff --git a/img/sm_old/scoiatael_saskia.jpg b/img/sm_old/scoiatael_saskia.jpg new file mode 100644 index 0000000..0b67677 Binary files /dev/null and b/img/sm_old/scoiatael_saskia.jpg differ diff --git a/img/sm_old/scoiatael_schirru.jpg b/img/sm_old/scoiatael_schirru.jpg new file mode 100644 index 0000000..b8832f0 Binary files /dev/null and b/img/sm_old/scoiatael_schirru.jpg differ diff --git a/img/sm_old/scoiatael_sirssa.jpg b/img/sm_old/scoiatael_sirssa.jpg new file mode 100644 index 0000000..a73c25a Binary files /dev/null and b/img/sm_old/scoiatael_sirssa.jpg differ diff --git a/img/sm_old/scoiatael_toruviel.jpg b/img/sm_old/scoiatael_toruviel.jpg new file mode 100644 index 0000000..4db6ca2 Binary files /dev/null and b/img/sm_old/scoiatael_toruviel.jpg differ diff --git a/img/sm_old/scoiatael_vrihedd_brigade.jpg b/img/sm_old/scoiatael_vrihedd_brigade.jpg new file mode 100644 index 0000000..08146f7 Binary files /dev/null and b/img/sm_old/scoiatael_vrihedd_brigade.jpg differ diff --git a/img/sm_old/scoiatael_vrihedd_brigade_1.jpg b/img/sm_old/scoiatael_vrihedd_brigade_1.jpg new file mode 100644 index 0000000..339dc27 Binary files /dev/null and b/img/sm_old/scoiatael_vrihedd_brigade_1.jpg differ diff --git a/img/sm_old/scoiatael_vrihedd_cadet.jpg b/img/sm_old/scoiatael_vrihedd_cadet.jpg new file mode 100644 index 0000000..a97d7f9 Binary files /dev/null and b/img/sm_old/scoiatael_vrihedd_cadet.jpg differ diff --git a/img/sm_old/scoiatael_vrihedd_dragoon_1.jpg b/img/sm_old/scoiatael_vrihedd_dragoon_1.jpg new file mode 100644 index 0000000..f8de18d Binary files /dev/null and b/img/sm_old/scoiatael_vrihedd_dragoon_1.jpg differ diff --git a/img/sm_old/scoiatael_vrihedd_dragoon_2.jpg b/img/sm_old/scoiatael_vrihedd_dragoon_2.jpg new file mode 100644 index 0000000..8eaf089 Binary files /dev/null and b/img/sm_old/scoiatael_vrihedd_dragoon_2.jpg differ diff --git a/img/sm_old/scoiatael_vrihedd_dragoon_3.jpg b/img/sm_old/scoiatael_vrihedd_dragoon_3.jpg new file mode 100644 index 0000000..a5ad703 Binary files /dev/null and b/img/sm_old/scoiatael_vrihedd_dragoon_3.jpg differ diff --git a/img/sm_old/scoiatael_vrihedd_officer.jpg b/img/sm_old/scoiatael_vrihedd_officer.jpg new file mode 100644 index 0000000..8f40ab9 Binary files /dev/null and b/img/sm_old/scoiatael_vrihedd_officer.jpg differ diff --git a/img/sm_old/scoiatael_vrihedd_saboteur.jpg b/img/sm_old/scoiatael_vrihedd_saboteur.jpg new file mode 100644 index 0000000..84c08e6 Binary files /dev/null and b/img/sm_old/scoiatael_vrihedd_saboteur.jpg differ diff --git a/img/sm_old/scoiatael_vrihedd_sapper.jpg b/img/sm_old/scoiatael_vrihedd_sapper.jpg new file mode 100644 index 0000000..f78840b Binary files /dev/null and b/img/sm_old/scoiatael_vrihedd_sapper.jpg differ diff --git a/img/sm_old/scoiatael_yaevinn.jpg b/img/sm_old/scoiatael_yaevinn.jpg new file mode 100644 index 0000000..fe15124 Binary files /dev/null and b/img/sm_old/scoiatael_yaevinn.jpg differ diff --git a/img/sm_old/scoiatael_yannick_brass.jpg b/img/sm_old/scoiatael_yannick_brass.jpg new file mode 100644 index 0000000..4db24bc Binary files /dev/null and b/img/sm_old/scoiatael_yannick_brass.jpg differ diff --git a/img/sm_old/skellige_an_craite_blacksmith.jpg b/img/sm_old/skellige_an_craite_blacksmith.jpg new file mode 100644 index 0000000..eefd3e6 Binary files /dev/null and b/img/sm_old/skellige_an_craite_blacksmith.jpg differ diff --git a/img/sm_old/skellige_an_craite_greatsword.jpg b/img/sm_old/skellige_an_craite_greatsword.jpg new file mode 100644 index 0000000..8ad7c50 Binary files /dev/null and b/img/sm_old/skellige_an_craite_greatsword.jpg differ diff --git a/img/sm_old/skellige_an_craite_raiders.jpg b/img/sm_old/skellige_an_craite_raiders.jpg new file mode 100644 index 0000000..f7e9590 Binary files /dev/null and b/img/sm_old/skellige_an_craite_raiders.jpg differ diff --git a/img/sm_old/skellige_arnjolf.jpg b/img/sm_old/skellige_arnjolf.jpg new file mode 100644 index 0000000..b1b1f94 Binary files /dev/null and b/img/sm_old/skellige_arnjolf.jpg differ diff --git a/img/sm_old/skellige_berserker.jpg b/img/sm_old/skellige_berserker.jpg new file mode 100644 index 0000000..05b4a85 Binary files /dev/null and b/img/sm_old/skellige_berserker.jpg differ diff --git a/img/sm_old/skellige_birna.jpg b/img/sm_old/skellige_birna.jpg new file mode 100644 index 0000000..8297f24 Binary files /dev/null and b/img/sm_old/skellige_birna.jpg differ diff --git a/img/sm_old/skellige_blue_whale.jpg b/img/sm_old/skellige_blue_whale.jpg new file mode 100644 index 0000000..636af53 Binary files /dev/null and b/img/sm_old/skellige_blue_whale.jpg differ diff --git a/img/sm_old/skellige_blueboy.jpg b/img/sm_old/skellige_blueboy.jpg new file mode 100644 index 0000000..ed8c1be Binary files /dev/null and b/img/sm_old/skellige_blueboy.jpg differ diff --git a/img/sm_old/skellige_brokva_archer.jpg b/img/sm_old/skellige_brokva_archer.jpg new file mode 100644 index 0000000..f10d41f Binary files /dev/null and b/img/sm_old/skellige_brokva_archer.jpg differ diff --git a/img/sm_old/skellige_brokvar_hunter.jpg b/img/sm_old/skellige_brokvar_hunter.jpg new file mode 100644 index 0000000..d20dc49 Binary files /dev/null and b/img/sm_old/skellige_brokvar_hunter.jpg differ diff --git a/img/sm_old/skellige_cerys.jpg b/img/sm_old/skellige_cerys.jpg new file mode 100644 index 0000000..03d01de Binary files /dev/null and b/img/sm_old/skellige_cerys.jpg differ diff --git a/img/sm_old/skellige_champion_svalblod.jpg b/img/sm_old/skellige_champion_svalblod.jpg new file mode 100644 index 0000000..351a07c Binary files /dev/null and b/img/sm_old/skellige_champion_svalblod.jpg differ diff --git a/img/sm_old/skellige_chosen_berserker.jpg b/img/sm_old/skellige_chosen_berserker.jpg new file mode 100644 index 0000000..298c112 Binary files /dev/null and b/img/sm_old/skellige_chosen_berserker.jpg differ diff --git a/img/sm_old/skellige_crach_an_craite.jpg b/img/sm_old/skellige_crach_an_craite.jpg new file mode 100644 index 0000000..0082bb7 Binary files /dev/null and b/img/sm_old/skellige_crach_an_craite.jpg differ diff --git a/img/sm_old/skellige_craite_warrior_1.jpg b/img/sm_old/skellige_craite_warrior_1.jpg new file mode 100644 index 0000000..74f2877 Binary files /dev/null and b/img/sm_old/skellige_craite_warrior_1.jpg differ diff --git a/img/sm_old/skellige_craite_warrior_2.jpg b/img/sm_old/skellige_craite_warrior_2.jpg new file mode 100644 index 0000000..74f2877 Binary files /dev/null and b/img/sm_old/skellige_craite_warrior_2.jpg differ diff --git a/img/sm_old/skellige_craite_warrior_3.jpg b/img/sm_old/skellige_craite_warrior_3.jpg new file mode 100644 index 0000000..74f2877 Binary files /dev/null and b/img/sm_old/skellige_craite_warrior_3.jpg differ diff --git a/img/sm_old/skellige_dagur.jpg b/img/sm_old/skellige_dagur.jpg new file mode 100644 index 0000000..10daa85 Binary files /dev/null and b/img/sm_old/skellige_dagur.jpg differ diff --git a/img/sm_old/skellige_dimun_pirate.jpg b/img/sm_old/skellige_dimun_pirate.jpg new file mode 100644 index 0000000..ccf067f Binary files /dev/null and b/img/sm_old/skellige_dimun_pirate.jpg differ diff --git a/img/sm_old/skellige_dimun_pirate_captain.jpg b/img/sm_old/skellige_dimun_pirate_captain.jpg new file mode 100644 index 0000000..68d45c8 Binary files /dev/null and b/img/sm_old/skellige_dimun_pirate_captain.jpg differ diff --git a/img/sm_old/skellige_djenge_frett.jpg b/img/sm_old/skellige_djenge_frett.jpg new file mode 100644 index 0000000..c3ffc8e Binary files /dev/null and b/img/sm_old/skellige_djenge_frett.jpg differ diff --git a/img/sm_old/skellige_donar.jpg b/img/sm_old/skellige_donar.jpg new file mode 100644 index 0000000..1a3de08 Binary files /dev/null and b/img/sm_old/skellige_donar.jpg differ diff --git a/img/sm_old/skellige_draig.jpg b/img/sm_old/skellige_draig.jpg new file mode 100644 index 0000000..aef8f6f Binary files /dev/null and b/img/sm_old/skellige_draig.jpg differ diff --git a/img/sm_old/skellige_drummond_berserker.jpg b/img/sm_old/skellige_drummond_berserker.jpg new file mode 100644 index 0000000..bf84267 Binary files /dev/null and b/img/sm_old/skellige_drummond_berserker.jpg differ diff --git a/img/sm_old/skellige_drummond_warmonger.jpg b/img/sm_old/skellige_drummond_warmonger.jpg new file mode 100644 index 0000000..0166724 Binary files /dev/null and b/img/sm_old/skellige_drummond_warmonger.jpg differ diff --git a/img/sm_old/skellige_eist_tuirseach.jpg b/img/sm_old/skellige_eist_tuirseach.jpg new file mode 100644 index 0000000..dea13b1 Binary files /dev/null and b/img/sm_old/skellige_eist_tuirseach.jpg differ diff --git a/img/sm_old/skellige_ermion.jpg b/img/sm_old/skellige_ermion.jpg new file mode 100644 index 0000000..9ecc522 Binary files /dev/null and b/img/sm_old/skellige_ermion.jpg differ diff --git a/img/sm_old/skellige_giant_boar.jpg b/img/sm_old/skellige_giant_boar.jpg new file mode 100644 index 0000000..5fb2dbe Binary files /dev/null and b/img/sm_old/skellige_giant_boar.jpg differ diff --git a/img/sm_old/skellige_gremist.jpg b/img/sm_old/skellige_gremist.jpg new file mode 100644 index 0000000..f005585 Binary files /dev/null and b/img/sm_old/skellige_gremist.jpg differ diff --git a/img/sm_old/skellige_harald_cripple.jpg b/img/sm_old/skellige_harald_cripple.jpg new file mode 100644 index 0000000..de9c5a9 Binary files /dev/null and b/img/sm_old/skellige_harald_cripple.jpg differ diff --git a/img/sm_old/skellige_harald_houndsnout.jpg b/img/sm_old/skellige_harald_houndsnout.jpg new file mode 100644 index 0000000..a751cee Binary files /dev/null and b/img/sm_old/skellige_harald_houndsnout.jpg differ diff --git a/img/sm_old/skellige_hemdall.jpg b/img/sm_old/skellige_hemdall.jpg new file mode 100644 index 0000000..dd2642d Binary files /dev/null and b/img/sm_old/skellige_hemdall.jpg differ diff --git a/img/sm_old/skellige_heymaey.jpg b/img/sm_old/skellige_heymaey.jpg new file mode 100644 index 0000000..757a111 Binary files /dev/null and b/img/sm_old/skellige_heymaey.jpg differ diff --git a/img/sm_old/skellige_heymaey_flaminica.jpg b/img/sm_old/skellige_heymaey_flaminica.jpg new file mode 100644 index 0000000..02aaafa Binary files /dev/null and b/img/sm_old/skellige_heymaey_flaminica.jpg differ diff --git a/img/sm_old/skellige_heymaey_herbalist.jpg b/img/sm_old/skellige_heymaey_herbalist.jpg new file mode 100644 index 0000000..c51fe76 Binary files /dev/null and b/img/sm_old/skellige_heymaey_herbalist.jpg differ diff --git a/img/sm_old/skellige_hjalmar.jpg b/img/sm_old/skellige_hjalmar.jpg new file mode 100644 index 0000000..c1c6336 Binary files /dev/null and b/img/sm_old/skellige_hjalmar.jpg differ diff --git a/img/sm_old/skellige_holger.jpg b/img/sm_old/skellige_holger.jpg new file mode 100644 index 0000000..4dabffa Binary files /dev/null and b/img/sm_old/skellige_holger.jpg differ diff --git a/img/sm_old/skellige_holger_blackhand.jpg b/img/sm_old/skellige_holger_blackhand.jpg new file mode 100644 index 0000000..13cf185 Binary files /dev/null and b/img/sm_old/skellige_holger_blackhand.jpg differ diff --git a/img/sm_old/skellige_hym.jpg b/img/sm_old/skellige_hym.jpg new file mode 100644 index 0000000..6bedd75 Binary files /dev/null and b/img/sm_old/skellige_hym.jpg differ diff --git a/img/sm_old/skellige_jutta.jpg b/img/sm_old/skellige_jutta.jpg new file mode 100644 index 0000000..e874d7f Binary files /dev/null and b/img/sm_old/skellige_jutta.jpg differ diff --git a/img/sm_old/skellige_kambi.jpg b/img/sm_old/skellige_kambi.jpg new file mode 100644 index 0000000..9a7b4eb Binary files /dev/null and b/img/sm_old/skellige_kambi.jpg differ diff --git a/img/sm_old/skellige_king_bran.jpg b/img/sm_old/skellige_king_bran.jpg new file mode 100644 index 0000000..0c596d9 Binary files /dev/null and b/img/sm_old/skellige_king_bran.jpg differ diff --git a/img/sm_old/skellige_light_longship.jpg b/img/sm_old/skellige_light_longship.jpg new file mode 100644 index 0000000..a826f51 Binary files /dev/null and b/img/sm_old/skellige_light_longship.jpg differ diff --git a/img/sm_old/skellige_madman_lugos.jpg b/img/sm_old/skellige_madman_lugos.jpg new file mode 100644 index 0000000..9e632f5 Binary files /dev/null and b/img/sm_old/skellige_madman_lugos.jpg differ diff --git a/img/sm_old/skellige_morkvarg.jpg b/img/sm_old/skellige_morkvarg.jpg new file mode 100644 index 0000000..5499f72 Binary files /dev/null and b/img/sm_old/skellige_morkvarg.jpg differ diff --git a/img/sm_old/skellige_olaf.jpg b/img/sm_old/skellige_olaf.jpg new file mode 100644 index 0000000..bac83d3 Binary files /dev/null and b/img/sm_old/skellige_olaf.jpg differ diff --git a/img/sm_old/skellige_otkell.jpg b/img/sm_old/skellige_otkell.jpg new file mode 100644 index 0000000..937e88b Binary files /dev/null and b/img/sm_old/skellige_otkell.jpg differ diff --git a/img/sm_old/skellige_shield_maiden_1.jpg b/img/sm_old/skellige_shield_maiden_1.jpg new file mode 100644 index 0000000..65ac258 Binary files /dev/null and b/img/sm_old/skellige_shield_maiden_1.jpg differ diff --git a/img/sm_old/skellige_shield_maiden_2.jpg b/img/sm_old/skellige_shield_maiden_2.jpg new file mode 100644 index 0000000..46a9339 Binary files /dev/null and b/img/sm_old/skellige_shield_maiden_2.jpg differ diff --git a/img/sm_old/skellige_shield_maiden_3.jpg b/img/sm_old/skellige_shield_maiden_3.jpg new file mode 100644 index 0000000..5d7b1f8 Binary files /dev/null and b/img/sm_old/skellige_shield_maiden_3.jpg differ diff --git a/img/sm_old/skellige_sigrdrifa.jpg b/img/sm_old/skellige_sigrdrifa.jpg new file mode 100644 index 0000000..a3012de Binary files /dev/null and b/img/sm_old/skellige_sigrdrifa.jpg differ diff --git a/img/sm_old/skellige_skjall.jpg b/img/sm_old/skellige_skjall.jpg new file mode 100644 index 0000000..6a7149f Binary files /dev/null and b/img/sm_old/skellige_skjall.jpg differ diff --git a/img/sm_old/skellige_svalblod.jpg b/img/sm_old/skellige_svalblod.jpg new file mode 100644 index 0000000..7f922a1 Binary files /dev/null and b/img/sm_old/skellige_svalblod.jpg differ diff --git a/img/sm_old/skellige_svalblod_fanatic.jpg b/img/sm_old/skellige_svalblod_fanatic.jpg new file mode 100644 index 0000000..e514719 Binary files /dev/null and b/img/sm_old/skellige_svalblod_fanatic.jpg differ diff --git a/img/sm_old/skellige_svanrige.jpg b/img/sm_old/skellige_svanrige.jpg new file mode 100644 index 0000000..598c3d4 Binary files /dev/null and b/img/sm_old/skellige_svanrige.jpg differ diff --git a/img/sm_old/skellige_tordarroch.jpg b/img/sm_old/skellige_tordarroch.jpg new file mode 100644 index 0000000..4e2e715 Binary files /dev/null and b/img/sm_old/skellige_tordarroch.jpg differ diff --git a/img/sm_old/skellige_troll_errant.jpg b/img/sm_old/skellige_troll_errant.jpg new file mode 100644 index 0000000..3280ea7 Binary files /dev/null and b/img/sm_old/skellige_troll_errant.jpg differ diff --git a/img/sm_old/skellige_tuirseach_bearmaster.jpg b/img/sm_old/skellige_tuirseach_bearmaster.jpg new file mode 100644 index 0000000..20955e0 Binary files /dev/null and b/img/sm_old/skellige_tuirseach_bearmaster.jpg differ diff --git a/img/sm_old/skellige_tuirseach_veteran.jpg b/img/sm_old/skellige_tuirseach_veteran.jpg new file mode 100644 index 0000000..4c9a9ea Binary files /dev/null and b/img/sm_old/skellige_tuirseach_veteran.jpg differ diff --git a/img/sm_old/skellige_tuirseach_warrior_1.jpg b/img/sm_old/skellige_tuirseach_warrior_1.jpg new file mode 100644 index 0000000..f7028a4 Binary files /dev/null and b/img/sm_old/skellige_tuirseach_warrior_1.jpg differ diff --git a/img/sm_old/skellige_tuirseach_warrior_2.jpg b/img/sm_old/skellige_tuirseach_warrior_2.jpg new file mode 100644 index 0000000..8e4c6a6 Binary files /dev/null and b/img/sm_old/skellige_tuirseach_warrior_2.jpg differ diff --git a/img/sm_old/skellige_udalryk.jpg b/img/sm_old/skellige_udalryk.jpg new file mode 100644 index 0000000..59109d4 Binary files /dev/null and b/img/sm_old/skellige_udalryk.jpg differ diff --git a/img/sm_old/skellige_vabjorn.jpg b/img/sm_old/skellige_vabjorn.jpg new file mode 100644 index 0000000..5126f6b Binary files /dev/null and b/img/sm_old/skellige_vabjorn.jpg differ diff --git a/img/sm_old/skellige_vigi_loon.jpg b/img/sm_old/skellige_vigi_loon.jpg new file mode 100644 index 0000000..afaec13 Binary files /dev/null and b/img/sm_old/skellige_vigi_loon.jpg differ diff --git a/img/sm_old/skellige_vildkaarl.jpg b/img/sm_old/skellige_vildkaarl.jpg new file mode 100644 index 0000000..4cfe6c9 Binary files /dev/null and b/img/sm_old/skellige_vildkaarl.jpg differ diff --git a/img/sm_old/skellige_war_longship_1.jpg b/img/sm_old/skellige_war_longship_1.jpg new file mode 100644 index 0000000..2bc34a5 Binary files /dev/null and b/img/sm_old/skellige_war_longship_1.jpg differ diff --git a/img/sm_old/skellige_war_longship_2.jpg b/img/sm_old/skellige_war_longship_2.jpg new file mode 100644 index 0000000..2bc34a5 Binary files /dev/null and b/img/sm_old/skellige_war_longship_2.jpg differ diff --git a/img/sm_old/skellige_war_longship_3.jpg b/img/sm_old/skellige_war_longship_3.jpg new file mode 100644 index 0000000..2bc34a5 Binary files /dev/null and b/img/sm_old/skellige_war_longship_3.jpg differ diff --git a/img/sm_old/skellige_whale_harpooner.jpg b/img/sm_old/skellige_whale_harpooner.jpg new file mode 100644 index 0000000..a218099 Binary files /dev/null and b/img/sm_old/skellige_whale_harpooner.jpg differ diff --git a/img/sm_old/skellige_wild_boar.jpg b/img/sm_old/skellige_wild_boar.jpg new file mode 100644 index 0000000..8af9e4a Binary files /dev/null and b/img/sm_old/skellige_wild_boar.jpg differ diff --git a/img/sm_old/skellige_young_berserker.jpg b/img/sm_old/skellige_young_berserker.jpg new file mode 100644 index 0000000..7c93235 Binary files /dev/null and b/img/sm_old/skellige_young_berserker.jpg differ diff --git a/img/sm_old/skellige_young_vildkaarl.jpg b/img/sm_old/skellige_young_vildkaarl.jpg new file mode 100644 index 0000000..35cb088 Binary files /dev/null and b/img/sm_old/skellige_young_vildkaarl.jpg differ diff --git a/img/sm_old/special_decoy.jpg b/img/sm_old/special_decoy.jpg new file mode 100644 index 0000000..5c0397b Binary files /dev/null and b/img/sm_old/special_decoy.jpg differ diff --git a/img/sm_old/special_dimeritium_shackles.jpg b/img/sm_old/special_dimeritium_shackles.jpg new file mode 100644 index 0000000..20516cc Binary files /dev/null and b/img/sm_old/special_dimeritium_shackles.jpg differ diff --git a/img/sm_old/special_garrison.jpg b/img/sm_old/special_garrison.jpg new file mode 100644 index 0000000..095eb98 Binary files /dev/null and b/img/sm_old/special_garrison.jpg differ diff --git a/img/sm_old/special_horn.jpg b/img/sm_old/special_horn.jpg new file mode 100644 index 0000000..4fae8d6 Binary files /dev/null and b/img/sm_old/special_horn.jpg differ diff --git a/img/sm_old/special_lyria_rivia_morale.jpg b/img/sm_old/special_lyria_rivia_morale.jpg new file mode 100644 index 0000000..0b48df2 Binary files /dev/null and b/img/sm_old/special_lyria_rivia_morale.jpg differ diff --git a/img/sm_old/special_mantlet.jpg b/img/sm_old/special_mantlet.jpg new file mode 100644 index 0000000..9dac64f Binary files /dev/null and b/img/sm_old/special_mantlet.jpg differ diff --git a/img/sm_old/special_mardroeme.jpg b/img/sm_old/special_mardroeme.jpg new file mode 100644 index 0000000..000fc69 Binary files /dev/null and b/img/sm_old/special_mardroeme.jpg differ diff --git a/img/sm_old/special_scorch.jpg b/img/sm_old/special_scorch.jpg new file mode 100644 index 0000000..8f586b0 Binary files /dev/null and b/img/sm_old/special_scorch.jpg differ diff --git a/img/sm_old/special_sign_aard.jpg b/img/sm_old/special_sign_aard.jpg new file mode 100644 index 0000000..b3b90bb Binary files /dev/null and b/img/sm_old/special_sign_aard.jpg differ diff --git a/img/sm_old/special_sign_axii.jpg b/img/sm_old/special_sign_axii.jpg new file mode 100644 index 0000000..8a7ab6b Binary files /dev/null and b/img/sm_old/special_sign_axii.jpg differ diff --git a/img/sm_old/special_sign_igni.jpg b/img/sm_old/special_sign_igni.jpg new file mode 100644 index 0000000..be451d1 Binary files /dev/null and b/img/sm_old/special_sign_igni.jpg differ diff --git a/img/sm_old/special_sign_quen.jpg b/img/sm_old/special_sign_quen.jpg new file mode 100644 index 0000000..5befebc Binary files /dev/null and b/img/sm_old/special_sign_quen.jpg differ diff --git a/img/sm_old/special_sign_yrden.jpg b/img/sm_old/special_sign_yrden.jpg new file mode 100644 index 0000000..e56de46 Binary files /dev/null and b/img/sm_old/special_sign_yrden.jpg differ diff --git a/img/sm_old/special_slaughter_cintra_1.jpg b/img/sm_old/special_slaughter_cintra_1.jpg new file mode 100644 index 0000000..046e619 Binary files /dev/null and b/img/sm_old/special_slaughter_cintra_1.jpg differ diff --git a/img/sm_old/special_slaughter_cintra_2.jpg b/img/sm_old/special_slaughter_cintra_2.jpg new file mode 100644 index 0000000..76bbf8a Binary files /dev/null and b/img/sm_old/special_slaughter_cintra_2.jpg differ diff --git a/img/sm_old/special_slaughter_cintra_3.jpg b/img/sm_old/special_slaughter_cintra_3.jpg new file mode 100644 index 0000000..387f670 Binary files /dev/null and b/img/sm_old/special_slaughter_cintra_3.jpg differ diff --git a/img/sm_old/special_toussaint_wine.jpg b/img/sm_old/special_toussaint_wine.jpg new file mode 100644 index 0000000..dcdb7e7 Binary files /dev/null and b/img/sm_old/special_toussaint_wine.jpg differ diff --git a/img/sm_old/special_vivaldi_bank.jpg b/img/sm_old/special_vivaldi_bank.jpg new file mode 100644 index 0000000..02d6338 Binary files /dev/null and b/img/sm_old/special_vivaldi_bank.jpg differ diff --git a/img/sm_old/special_watchman.jpg b/img/sm_old/special_watchman.jpg new file mode 100644 index 0000000..b4af28c Binary files /dev/null and b/img/sm_old/special_watchman.jpg differ diff --git a/img/sm_old/special_wyvern_shield.jpg b/img/sm_old/special_wyvern_shield.jpg new file mode 100644 index 0000000..3fac4e8 Binary files /dev/null and b/img/sm_old/special_wyvern_shield.jpg differ diff --git a/img/sm_old/syndicate_adriano_mink.jpg b/img/sm_old/syndicate_adriano_mink.jpg new file mode 100644 index 0000000..a5d63fe Binary files /dev/null and b/img/sm_old/syndicate_adriano_mink.jpg differ diff --git a/img/sm_old/syndicate_arena_endrega.jpg b/img/sm_old/syndicate_arena_endrega.jpg new file mode 100644 index 0000000..317c4de Binary files /dev/null and b/img/sm_old/syndicate_arena_endrega.jpg differ diff --git a/img/sm_old/syndicate_arena_ghoul.jpg b/img/sm_old/syndicate_arena_ghoul.jpg new file mode 100644 index 0000000..b2d3f8e Binary files /dev/null and b/img/sm_old/syndicate_arena_ghoul.jpg differ diff --git a/img/sm_old/syndicate_azar_javed.jpg b/img/sm_old/syndicate_azar_javed.jpg new file mode 100644 index 0000000..d8413e4 Binary files /dev/null and b/img/sm_old/syndicate_azar_javed.jpg differ diff --git a/img/sm_old/syndicate_bare_knuckle_brawler.jpg b/img/sm_old/syndicate_bare_knuckle_brawler.jpg new file mode 100644 index 0000000..8c85523 Binary files /dev/null and b/img/sm_old/syndicate_bare_knuckle_brawler.jpg differ diff --git a/img/sm_old/syndicate_beggar.jpg b/img/sm_old/syndicate_beggar.jpg new file mode 100644 index 0000000..f36a889 Binary files /dev/null and b/img/sm_old/syndicate_beggar.jpg differ diff --git a/img/sm_old/syndicate_bincy_blumerholdt.jpg b/img/sm_old/syndicate_bincy_blumerholdt.jpg new file mode 100644 index 0000000..3fe5b0f Binary files /dev/null and b/img/sm_old/syndicate_bincy_blumerholdt.jpg differ diff --git a/img/sm_old/syndicate_boris.jpg b/img/sm_old/syndicate_boris.jpg new file mode 100644 index 0000000..9528a06 Binary files /dev/null and b/img/sm_old/syndicate_boris.jpg differ diff --git a/img/sm_old/syndicate_caesar_bilzen.jpg b/img/sm_old/syndicate_caesar_bilzen.jpg new file mode 100644 index 0000000..e581669 Binary files /dev/null and b/img/sm_old/syndicate_caesar_bilzen.jpg differ diff --git a/img/sm_old/syndicate_caleb_menge.jpg b/img/sm_old/syndicate_caleb_menge.jpg new file mode 100644 index 0000000..ce37141 Binary files /dev/null and b/img/sm_old/syndicate_caleb_menge.jpg differ diff --git a/img/sm_old/syndicate_carlo_varese.jpg b/img/sm_old/syndicate_carlo_varese.jpg new file mode 100644 index 0000000..ed77336 Binary files /dev/null and b/img/sm_old/syndicate_carlo_varese.jpg differ diff --git a/img/sm_old/syndicate_casino_bouncers.jpg b/img/sm_old/syndicate_casino_bouncers.jpg new file mode 100644 index 0000000..ae5a74b Binary files /dev/null and b/img/sm_old/syndicate_casino_bouncers.jpg differ diff --git a/img/sm_old/syndicate_cleaver_gang_1.jpg b/img/sm_old/syndicate_cleaver_gang_1.jpg new file mode 100644 index 0000000..fa5f6a0 Binary files /dev/null and b/img/sm_old/syndicate_cleaver_gang_1.jpg differ diff --git a/img/sm_old/syndicate_cleaver_gang_2.jpg b/img/sm_old/syndicate_cleaver_gang_2.jpg new file mode 100644 index 0000000..f948826 Binary files /dev/null and b/img/sm_old/syndicate_cleaver_gang_2.jpg differ diff --git a/img/sm_old/syndicate_cleaver_gang_3.jpg b/img/sm_old/syndicate_cleaver_gang_3.jpg new file mode 100644 index 0000000..97410b7 Binary files /dev/null and b/img/sm_old/syndicate_cleaver_gang_3.jpg differ diff --git a/img/sm_old/syndicate_cleaver_gang_4.jpg b/img/sm_old/syndicate_cleaver_gang_4.jpg new file mode 100644 index 0000000..874608d Binary files /dev/null and b/img/sm_old/syndicate_cleaver_gang_4.jpg differ diff --git a/img/sm_old/syndicate_cleric_flaming_rose.jpg b/img/sm_old/syndicate_cleric_flaming_rose.jpg new file mode 100644 index 0000000..29c6e98 Binary files /dev/null and b/img/sm_old/syndicate_cleric_flaming_rose.jpg differ diff --git a/img/sm_old/syndicate_cyprian_wiley.jpg b/img/sm_old/syndicate_cyprian_wiley.jpg new file mode 100644 index 0000000..d6ca8c0 Binary files /dev/null and b/img/sm_old/syndicate_cyprian_wiley.jpg differ diff --git a/img/sm_old/syndicate_cyrus_hemmelfart.jpg b/img/sm_old/syndicate_cyrus_hemmelfart.jpg new file mode 100644 index 0000000..7832d42 Binary files /dev/null and b/img/sm_old/syndicate_cyrus_hemmelfart.jpg differ diff --git a/img/sm_old/syndicate_dudu_biberveldt.jpg b/img/sm_old/syndicate_dudu_biberveldt.jpg new file mode 100644 index 0000000..3f1f35b Binary files /dev/null and b/img/sm_old/syndicate_dudu_biberveldt.jpg differ diff --git a/img/sm_old/syndicate_eibhear_hattori.jpg b/img/sm_old/syndicate_eibhear_hattori.jpg new file mode 100644 index 0000000..01eebdb Binary files /dev/null and b/img/sm_old/syndicate_eibhear_hattori.jpg differ diff --git a/img/sm_old/syndicate_eternal_fire_disciple.jpg b/img/sm_old/syndicate_eternal_fire_disciple.jpg new file mode 100644 index 0000000..359c832 Binary files /dev/null and b/img/sm_old/syndicate_eternal_fire_disciple.jpg differ diff --git a/img/sm_old/syndicate_eternal_fire_inquisitor.jpg b/img/sm_old/syndicate_eternal_fire_inquisitor.jpg new file mode 100644 index 0000000..5a7a517 Binary files /dev/null and b/img/sm_old/syndicate_eternal_fire_inquisitor.jpg differ diff --git a/img/sm_old/syndicate_eternal_fire_priest_1.jpg b/img/sm_old/syndicate_eternal_fire_priest_1.jpg new file mode 100644 index 0000000..46910ed Binary files /dev/null and b/img/sm_old/syndicate_eternal_fire_priest_1.jpg differ diff --git a/img/sm_old/syndicate_eternal_fire_priest_2.jpg b/img/sm_old/syndicate_eternal_fire_priest_2.jpg new file mode 100644 index 0000000..a033956 Binary files /dev/null and b/img/sm_old/syndicate_eternal_fire_priest_2.jpg differ diff --git a/img/sm_old/syndicate_eternal_fire_priest_3.jpg b/img/sm_old/syndicate_eternal_fire_priest_3.jpg new file mode 100644 index 0000000..b67a07c Binary files /dev/null and b/img/sm_old/syndicate_eternal_fire_priest_3.jpg differ diff --git a/img/sm_old/syndicate_fabian_hale.jpg b/img/sm_old/syndicate_fabian_hale.jpg new file mode 100644 index 0000000..420f73d Binary files /dev/null and b/img/sm_old/syndicate_fabian_hale.jpg differ diff --git a/img/sm_old/syndicate_failed_experiment.jpg b/img/sm_old/syndicate_failed_experiment.jpg new file mode 100644 index 0000000..204eb4e Binary files /dev/null and b/img/sm_old/syndicate_failed_experiment.jpg differ diff --git a/img/sm_old/syndicate_fallen_knight.jpg b/img/sm_old/syndicate_fallen_knight.jpg new file mode 100644 index 0000000..607d495 Binary files /dev/null and b/img/sm_old/syndicate_fallen_knight.jpg differ diff --git a/img/sm_old/syndicate_fallen_rayla.jpg b/img/sm_old/syndicate_fallen_rayla.jpg new file mode 100644 index 0000000..75d1757 Binary files /dev/null and b/img/sm_old/syndicate_fallen_rayla.jpg differ diff --git a/img/sm_old/syndicate_fence.jpg b/img/sm_old/syndicate_fence.jpg new file mode 100644 index 0000000..5e8a182 Binary files /dev/null and b/img/sm_old/syndicate_fence.jpg differ diff --git a/img/sm_old/syndicate_ferko.jpg b/img/sm_old/syndicate_ferko.jpg new file mode 100644 index 0000000..32be3cb Binary files /dev/null and b/img/sm_old/syndicate_ferko.jpg differ diff --git a/img/sm_old/syndicate_fisstech.jpg b/img/sm_old/syndicate_fisstech.jpg new file mode 100644 index 0000000..fefdc6d Binary files /dev/null and b/img/sm_old/syndicate_fisstech.jpg differ diff --git a/img/sm_old/syndicate_fisstech_trafficker.jpg b/img/sm_old/syndicate_fisstech_trafficker.jpg new file mode 100644 index 0000000..d99eb5b Binary files /dev/null and b/img/sm_old/syndicate_fisstech_trafficker.jpg differ diff --git a/img/sm_old/syndicate_flaming_rose_footman.jpg b/img/sm_old/syndicate_flaming_rose_footman.jpg new file mode 100644 index 0000000..a4a59cd Binary files /dev/null and b/img/sm_old/syndicate_flaming_rose_footman.jpg differ diff --git a/img/sm_old/syndicate_flyndr_crew.jpg b/img/sm_old/syndicate_flyndr_crew.jpg new file mode 100644 index 0000000..16dc28b Binary files /dev/null and b/img/sm_old/syndicate_flyndr_crew.jpg differ diff --git a/img/sm_old/syndicate_francis_bedlam.jpg b/img/sm_old/syndicate_francis_bedlam.jpg new file mode 100644 index 0000000..a3544da Binary files /dev/null and b/img/sm_old/syndicate_francis_bedlam.jpg differ diff --git a/img/sm_old/syndicate_freak_show_1.jpg b/img/sm_old/syndicate_freak_show_1.jpg new file mode 100644 index 0000000..849a39c Binary files /dev/null and b/img/sm_old/syndicate_freak_show_1.jpg differ diff --git a/img/sm_old/syndicate_freak_show_2.jpg b/img/sm_old/syndicate_freak_show_2.jpg new file mode 100644 index 0000000..6eeb542 Binary files /dev/null and b/img/sm_old/syndicate_freak_show_2.jpg differ diff --git a/img/sm_old/syndicate_freak_show_3.jpg b/img/sm_old/syndicate_freak_show_3.jpg new file mode 100644 index 0000000..7c9f26e Binary files /dev/null and b/img/sm_old/syndicate_freak_show_3.jpg differ diff --git a/img/sm_old/syndicate_freak_show_4.jpg b/img/sm_old/syndicate_freak_show_4.jpg new file mode 100644 index 0000000..9a87430 Binary files /dev/null and b/img/sm_old/syndicate_freak_show_4.jpg differ diff --git a/img/sm_old/syndicate_frightener.jpg b/img/sm_old/syndicate_frightener.jpg new file mode 100644 index 0000000..6787a7c Binary files /dev/null and b/img/sm_old/syndicate_frightener.jpg differ diff --git a/img/sm_old/syndicate_gellert_bleinheim.jpg b/img/sm_old/syndicate_gellert_bleinheim.jpg new file mode 100644 index 0000000..e9bc3aa Binary files /dev/null and b/img/sm_old/syndicate_gellert_bleinheim.jpg differ diff --git a/img/sm_old/syndicate_graden.jpg b/img/sm_old/syndicate_graden.jpg new file mode 100644 index 0000000..5bc2eeb Binary files /dev/null and b/img/sm_old/syndicate_graden.jpg differ diff --git a/img/sm_old/syndicate_greater_brothers.jpg b/img/sm_old/syndicate_greater_brothers.jpg new file mode 100644 index 0000000..96f2d1d Binary files /dev/null and b/img/sm_old/syndicate_greater_brothers.jpg differ diff --git a/img/sm_old/syndicate_gudrun_bjornsdottir.jpg b/img/sm_old/syndicate_gudrun_bjornsdottir.jpg new file mode 100644 index 0000000..1547aed Binary files /dev/null and b/img/sm_old/syndicate_gudrun_bjornsdottir.jpg differ diff --git a/img/sm_old/syndicate_halfling_safecracker.jpg b/img/sm_old/syndicate_halfling_safecracker.jpg new file mode 100644 index 0000000..f719157 Binary files /dev/null and b/img/sm_old/syndicate_halfling_safecracker.jpg differ diff --git a/img/sm_old/syndicate_hammond.jpg b/img/sm_old/syndicate_hammond.jpg new file mode 100644 index 0000000..85fa882 Binary files /dev/null and b/img/sm_old/syndicate_hammond.jpg differ diff --git a/img/sm_old/syndicate_hvitr_aelydia.jpg b/img/sm_old/syndicate_hvitr_aelydia.jpg new file mode 100644 index 0000000..4cd3597 Binary files /dev/null and b/img/sm_old/syndicate_hvitr_aelydia.jpg differ diff --git a/img/sm_old/syndicate_ignatius_hale.jpg b/img/sm_old/syndicate_ignatius_hale.jpg new file mode 100644 index 0000000..372ef1b Binary files /dev/null and b/img/sm_old/syndicate_ignatius_hale.jpg differ diff --git a/img/sm_old/syndicate_igor_hook.jpg b/img/sm_old/syndicate_igor_hook.jpg new file mode 100644 index 0000000..df833b4 Binary files /dev/null and b/img/sm_old/syndicate_igor_hook.jpg differ diff --git a/img/sm_old/syndicate_imke.jpg b/img/sm_old/syndicate_imke.jpg new file mode 100644 index 0000000..9bbd20d Binary files /dev/null and b/img/sm_old/syndicate_imke.jpg differ diff --git a/img/sm_old/syndicate_inquisitional_pyres.jpg b/img/sm_old/syndicate_inquisitional_pyres.jpg new file mode 100644 index 0000000..4a31c5b Binary files /dev/null and b/img/sm_old/syndicate_inquisitional_pyres.jpg differ diff --git a/img/sm_old/syndicate_inquisitor_helveed.jpg b/img/sm_old/syndicate_inquisitor_helveed.jpg new file mode 100644 index 0000000..b2a8c5d Binary files /dev/null and b/img/sm_old/syndicate_inquisitor_helveed.jpg differ diff --git a/img/sm_old/syndicate_jacques_aldersberg.jpg b/img/sm_old/syndicate_jacques_aldersberg.jpg new file mode 100644 index 0000000..cbba792 Binary files /dev/null and b/img/sm_old/syndicate_jacques_aldersberg.jpg differ diff --git a/img/sm_old/syndicate_kurt.jpg b/img/sm_old/syndicate_kurt.jpg new file mode 100644 index 0000000..e341a32 Binary files /dev/null and b/img/sm_old/syndicate_kurt.jpg differ diff --git a/img/sm_old/syndicate_lieutenant_herst.jpg b/img/sm_old/syndicate_lieutenant_herst.jpg new file mode 100644 index 0000000..da3395e Binary files /dev/null and b/img/sm_old/syndicate_lieutenant_herst.jpg differ diff --git a/img/sm_old/syndicate_lonely_champion.jpg b/img/sm_old/syndicate_lonely_champion.jpg new file mode 100644 index 0000000..24ee267 Binary files /dev/null and b/img/sm_old/syndicate_lonely_champion.jpg differ diff --git a/img/sm_old/syndicate_madame_luiza.jpg b/img/sm_old/syndicate_madame_luiza.jpg new file mode 100644 index 0000000..45daeca Binary files /dev/null and b/img/sm_old/syndicate_madame_luiza.jpg differ diff --git a/img/sm_old/syndicate_moreelse.jpg b/img/sm_old/syndicate_moreelse.jpg new file mode 100644 index 0000000..dc679ef Binary files /dev/null and b/img/sm_old/syndicate_moreelse.jpg differ diff --git a/img/sm_old/syndicate_mutant.jpg b/img/sm_old/syndicate_mutant.jpg new file mode 100644 index 0000000..c47b35e Binary files /dev/null and b/img/sm_old/syndicate_mutant.jpg differ diff --git a/img/sm_old/syndicate_mutant_killer.jpg b/img/sm_old/syndicate_mutant_killer.jpg new file mode 100644 index 0000000..1b2aa0d Binary files /dev/null and b/img/sm_old/syndicate_mutant_killer.jpg differ diff --git a/img/sm_old/syndicate_mutant_maker.jpg b/img/sm_old/syndicate_mutant_maker.jpg new file mode 100644 index 0000000..2c67caa Binary files /dev/null and b/img/sm_old/syndicate_mutant_maker.jpg differ diff --git a/img/sm_old/syndicate_mutated_hound_1.jpg b/img/sm_old/syndicate_mutated_hound_1.jpg new file mode 100644 index 0000000..5af2908 Binary files /dev/null and b/img/sm_old/syndicate_mutated_hound_1.jpg differ diff --git a/img/sm_old/syndicate_mutated_hound_2.jpg b/img/sm_old/syndicate_mutated_hound_2.jpg new file mode 100644 index 0000000..f1d0336 Binary files /dev/null and b/img/sm_old/syndicate_mutated_hound_2.jpg differ diff --git a/img/sm_old/syndicate_nathaniel_pastodi.jpg b/img/sm_old/syndicate_nathaniel_pastodi.jpg new file mode 100644 index 0000000..af93ce3 Binary files /dev/null and b/img/sm_old/syndicate_nathaniel_pastodi.jpg differ diff --git a/img/sm_old/syndicate_octavia_hale.jpg b/img/sm_old/syndicate_octavia_hale.jpg new file mode 100644 index 0000000..7b3c700 Binary files /dev/null and b/img/sm_old/syndicate_octavia_hale.jpg differ diff --git a/img/sm_old/syndicate_passiflora.jpg b/img/sm_old/syndicate_passiflora.jpg new file mode 100644 index 0000000..f473c2f Binary files /dev/null and b/img/sm_old/syndicate_passiflora.jpg differ diff --git a/img/sm_old/syndicate_passiflora_peaches.jpg b/img/sm_old/syndicate_passiflora_peaches.jpg new file mode 100644 index 0000000..a780ea2 Binary files /dev/null and b/img/sm_old/syndicate_passiflora_peaches.jpg differ diff --git a/img/sm_old/syndicate_payroll_specialist.jpg b/img/sm_old/syndicate_payroll_specialist.jpg new file mode 100644 index 0000000..9821b7b Binary files /dev/null and b/img/sm_old/syndicate_payroll_specialist.jpg differ diff --git a/img/sm_old/syndicate_professor.jpg b/img/sm_old/syndicate_professor.jpg new file mode 100644 index 0000000..7b42145 Binary files /dev/null and b/img/sm_old/syndicate_professor.jpg differ diff --git a/img/sm_old/syndicate_rico_meiersdorf.jpg b/img/sm_old/syndicate_rico_meiersdorf.jpg new file mode 100644 index 0000000..66bb95e Binary files /dev/null and b/img/sm_old/syndicate_rico_meiersdorf.jpg differ diff --git a/img/sm_old/syndicate_robber_1.jpg b/img/sm_old/syndicate_robber_1.jpg new file mode 100644 index 0000000..e45c393 Binary files /dev/null and b/img/sm_old/syndicate_robber_1.jpg differ diff --git a/img/sm_old/syndicate_robber_2.jpg b/img/sm_old/syndicate_robber_2.jpg new file mode 100644 index 0000000..8dde8c6 Binary files /dev/null and b/img/sm_old/syndicate_robber_2.jpg differ diff --git a/img/sm_old/syndicate_robber_3.jpg b/img/sm_old/syndicate_robber_3.jpg new file mode 100644 index 0000000..2362721 Binary files /dev/null and b/img/sm_old/syndicate_robber_3.jpg differ diff --git a/img/sm_old/syndicate_robber_4.jpg b/img/sm_old/syndicate_robber_4.jpg new file mode 100644 index 0000000..74cc57a Binary files /dev/null and b/img/sm_old/syndicate_robber_4.jpg differ diff --git a/img/sm_old/syndicate_roderick_wett.jpg b/img/sm_old/syndicate_roderick_wett.jpg new file mode 100644 index 0000000..f6a29eb Binary files /dev/null and b/img/sm_old/syndicate_roderick_wett.jpg differ diff --git a/img/sm_old/syndicate_roland_bleinheim.jpg b/img/sm_old/syndicate_roland_bleinheim.jpg new file mode 100644 index 0000000..b8d1020 Binary files /dev/null and b/img/sm_old/syndicate_roland_bleinheim.jpg differ diff --git a/img/sm_old/syndicate_salamandra_assassin.jpg b/img/sm_old/syndicate_salamandra_assassin.jpg new file mode 100644 index 0000000..7b734c8 Binary files /dev/null and b/img/sm_old/syndicate_salamandra_assassin.jpg differ diff --git a/img/sm_old/syndicate_salamandra_assassin_2.jpg b/img/sm_old/syndicate_salamandra_assassin_2.jpg new file mode 100644 index 0000000..23522f1 Binary files /dev/null and b/img/sm_old/syndicate_salamandra_assassin_2.jpg differ diff --git a/img/sm_old/syndicate_salamandra_lackey.jpg b/img/sm_old/syndicate_salamandra_lackey.jpg new file mode 100644 index 0000000..2d7b681 Binary files /dev/null and b/img/sm_old/syndicate_salamandra_lackey.jpg differ diff --git a/img/sm_old/syndicate_salamandra_mage.jpg b/img/sm_old/syndicate_salamandra_mage.jpg new file mode 100644 index 0000000..c1a2ce2 Binary files /dev/null and b/img/sm_old/syndicate_salamandra_mage.jpg differ diff --git a/img/sm_old/syndicate_saul_navarette.jpg b/img/sm_old/syndicate_saul_navarette.jpg new file mode 100644 index 0000000..aef4b38 Binary files /dev/null and b/img/sm_old/syndicate_saul_navarette.jpg differ diff --git a/img/sm_old/syndicate_sausage_maker.jpg b/img/sm_old/syndicate_sausage_maker.jpg new file mode 100644 index 0000000..7e944bc Binary files /dev/null and b/img/sm_old/syndicate_sausage_maker.jpg differ diff --git a/img/sm_old/syndicate_savolla.jpg b/img/sm_old/syndicate_savolla.jpg new file mode 100644 index 0000000..2080177 Binary files /dev/null and b/img/sm_old/syndicate_savolla.jpg differ diff --git a/img/sm_old/syndicate_sea_jackal.jpg b/img/sm_old/syndicate_sea_jackal.jpg new file mode 100644 index 0000000..a104b4e Binary files /dev/null and b/img/sm_old/syndicate_sea_jackal.jpg differ diff --git a/img/sm_old/syndicate_sewer_raider.jpg b/img/sm_old/syndicate_sewer_raider.jpg new file mode 100644 index 0000000..9e08631 Binary files /dev/null and b/img/sm_old/syndicate_sewer_raider.jpg differ diff --git a/img/sm_old/syndicate_sigi_reuven.jpg b/img/sm_old/syndicate_sigi_reuven.jpg new file mode 100644 index 0000000..994adad Binary files /dev/null and b/img/sm_old/syndicate_sigi_reuven.jpg differ diff --git a/img/sm_old/syndicate_sir_skewertooth.jpg b/img/sm_old/syndicate_sir_skewertooth.jpg new file mode 100644 index 0000000..e961c86 Binary files /dev/null and b/img/sm_old/syndicate_sir_skewertooth.jpg differ diff --git a/img/sm_old/syndicate_sly_seductress.jpg b/img/sm_old/syndicate_sly_seductress.jpg new file mode 100644 index 0000000..aa22f10 Binary files /dev/null and b/img/sm_old/syndicate_sly_seductress.jpg differ diff --git a/img/sm_old/syndicate_stolen_mutagens.jpg b/img/sm_old/syndicate_stolen_mutagens.jpg new file mode 100644 index 0000000..fb0c1e9 Binary files /dev/null and b/img/sm_old/syndicate_stolen_mutagens.jpg differ diff --git a/img/sm_old/syndicate_sukrus.jpg b/img/sm_old/syndicate_sukrus.jpg new file mode 100644 index 0000000..9bff60b Binary files /dev/null and b/img/sm_old/syndicate_sukrus.jpg differ diff --git a/img/sm_old/syndicate_tatterwing.jpg b/img/sm_old/syndicate_tatterwing.jpg new file mode 100644 index 0000000..808009d Binary files /dev/null and b/img/sm_old/syndicate_tatterwing.jpg differ diff --git a/img/sm_old/syndicate_temple_guard.jpg b/img/sm_old/syndicate_temple_guard.jpg new file mode 100644 index 0000000..f92b692 Binary files /dev/null and b/img/sm_old/syndicate_temple_guard.jpg differ diff --git a/img/sm_old/syndicate_tidecloak_ransacker.jpg b/img/sm_old/syndicate_tidecloak_ransacker.jpg new file mode 100644 index 0000000..b770f84 Binary files /dev/null and b/img/sm_old/syndicate_tidecloak_ransacker.jpg differ diff --git a/img/sm_old/syndicate_tramara_strenger.jpg b/img/sm_old/syndicate_tramara_strenger.jpg new file mode 100644 index 0000000..1dc6e68 Binary files /dev/null and b/img/sm_old/syndicate_tramara_strenger.jpg differ diff --git a/img/sm_old/syndicate_ulrich.jpg b/img/sm_old/syndicate_ulrich.jpg new file mode 100644 index 0000000..c657019 Binary files /dev/null and b/img/sm_old/syndicate_ulrich.jpg differ diff --git a/img/sm_old/syndicate_walter_veritas.jpg b/img/sm_old/syndicate_walter_veritas.jpg new file mode 100644 index 0000000..36af36c Binary files /dev/null and b/img/sm_old/syndicate_walter_veritas.jpg differ diff --git a/img/sm_old/syndicate_whoreson_senior.jpg b/img/sm_old/syndicate_whoreson_senior.jpg new file mode 100644 index 0000000..bd89ece Binary files /dev/null and b/img/sm_old/syndicate_whoreson_senior.jpg differ diff --git a/img/sm_old/syndicate_witch_hunter.jpg b/img/sm_old/syndicate_witch_hunter.jpg new file mode 100644 index 0000000..c4804ea Binary files /dev/null and b/img/sm_old/syndicate_witch_hunter.jpg differ diff --git a/img/sm_old/syndicate_witch_hunter_executioner.jpg b/img/sm_old/syndicate_witch_hunter_executioner.jpg new file mode 100644 index 0000000..e1eef9f Binary files /dev/null and b/img/sm_old/syndicate_witch_hunter_executioner.jpg differ diff --git a/img/sm_old/toussaint_alchemist.jpg b/img/sm_old/toussaint_alchemist.jpg new file mode 100644 index 0000000..5a40bd8 Binary files /dev/null and b/img/sm_old/toussaint_alchemist.jpg differ diff --git a/img/sm_old/toussaint_alpha_garkain.jpg b/img/sm_old/toussaint_alpha_garkain.jpg new file mode 100644 index 0000000..8b4a8a1 Binary files /dev/null and b/img/sm_old/toussaint_alpha_garkain.jpg differ diff --git a/img/sm_old/toussaint_anna_henrietta_duchess.jpg b/img/sm_old/toussaint_anna_henrietta_duchess.jpg new file mode 100644 index 0000000..75d2d4d Binary files /dev/null and b/img/sm_old/toussaint_anna_henrietta_duchess.jpg differ diff --git a/img/sm_old/toussaint_anna_henrietta_grace.jpg b/img/sm_old/toussaint_anna_henrietta_grace.jpg new file mode 100644 index 0000000..e5f9793 Binary files /dev/null and b/img/sm_old/toussaint_anna_henrietta_grace.jpg differ diff --git a/img/sm_old/toussaint_anna_henrietta_ladyship.jpg b/img/sm_old/toussaint_anna_henrietta_ladyship.jpg new file mode 100644 index 0000000..7e93ecd Binary files /dev/null and b/img/sm_old/toussaint_anna_henrietta_ladyship.jpg differ diff --git a/img/sm_old/toussaint_archespore.jpg b/img/sm_old/toussaint_archespore.jpg new file mode 100644 index 0000000..cbbf9fb Binary files /dev/null and b/img/sm_old/toussaint_archespore.jpg differ diff --git a/img/sm_old/toussaint_artorius_vigo.jpg b/img/sm_old/toussaint_artorius_vigo.jpg new file mode 100644 index 0000000..51b94fc Binary files /dev/null and b/img/sm_old/toussaint_artorius_vigo.jpg differ diff --git a/img/sm_old/toussaint_barghest_1.jpg b/img/sm_old/toussaint_barghest_1.jpg new file mode 100644 index 0000000..6da00a2 Binary files /dev/null and b/img/sm_old/toussaint_barghest_1.jpg differ diff --git a/img/sm_old/toussaint_barghest_2.jpg b/img/sm_old/toussaint_barghest_2.jpg new file mode 100644 index 0000000..06f783f Binary files /dev/null and b/img/sm_old/toussaint_barghest_2.jpg differ diff --git a/img/sm_old/toussaint_barghest_3.jpg b/img/sm_old/toussaint_barghest_3.jpg new file mode 100644 index 0000000..6a7264c Binary files /dev/null and b/img/sm_old/toussaint_barghest_3.jpg differ diff --git a/img/sm_old/toussaint_barnabas.jpg b/img/sm_old/toussaint_barnabas.jpg new file mode 100644 index 0000000..742b84f Binary files /dev/null and b/img/sm_old/toussaint_barnabas.jpg differ diff --git a/img/sm_old/toussaint_beauclair_cavalry_1.jpg b/img/sm_old/toussaint_beauclair_cavalry_1.jpg new file mode 100644 index 0000000..361e3c2 Binary files /dev/null and b/img/sm_old/toussaint_beauclair_cavalry_1.jpg differ diff --git a/img/sm_old/toussaint_beauclair_cavalry_2.jpg b/img/sm_old/toussaint_beauclair_cavalry_2.jpg new file mode 100644 index 0000000..a59483a Binary files /dev/null and b/img/sm_old/toussaint_beauclair_cavalry_2.jpg differ diff --git a/img/sm_old/toussaint_benoit.jpg b/img/sm_old/toussaint_benoit.jpg new file mode 100644 index 0000000..bb1e8e7 Binary files /dev/null and b/img/sm_old/toussaint_benoit.jpg differ diff --git a/img/sm_old/toussaint_bootblack.jpg b/img/sm_old/toussaint_bootblack.jpg new file mode 100644 index 0000000..24f39d1 Binary files /dev/null and b/img/sm_old/toussaint_bootblack.jpg differ diff --git a/img/sm_old/toussaint_bruxa_corvo_bianco.jpg b/img/sm_old/toussaint_bruxa_corvo_bianco.jpg new file mode 100644 index 0000000..7ff4927 Binary files /dev/null and b/img/sm_old/toussaint_bruxa_corvo_bianco.jpg differ diff --git a/img/sm_old/toussaint_caed_myrkvid_druid_1.jpg b/img/sm_old/toussaint_caed_myrkvid_druid_1.jpg new file mode 100644 index 0000000..ee87371 Binary files /dev/null and b/img/sm_old/toussaint_caed_myrkvid_druid_1.jpg differ diff --git a/img/sm_old/toussaint_caed_myrkvid_druid_2.jpg b/img/sm_old/toussaint_caed_myrkvid_druid_2.jpg new file mode 100644 index 0000000..aeb9777 Binary files /dev/null and b/img/sm_old/toussaint_caed_myrkvid_druid_2.jpg differ diff --git a/img/sm_old/toussaint_champion.jpg b/img/sm_old/toussaint_champion.jpg new file mode 100644 index 0000000..eeeee71 Binary files /dev/null and b/img/sm_old/toussaint_champion.jpg differ diff --git a/img/sm_old/toussaint_cloud_giant.jpg b/img/sm_old/toussaint_cloud_giant.jpg new file mode 100644 index 0000000..32ee7ec Binary files /dev/null and b/img/sm_old/toussaint_cloud_giant.jpg differ diff --git a/img/sm_old/toussaint_damien_tour.jpg b/img/sm_old/toussaint_damien_tour.jpg new file mode 100644 index 0000000..3b963f6 Binary files /dev/null and b/img/sm_old/toussaint_damien_tour.jpg differ diff --git a/img/sm_old/toussaint_dettlaff.jpg b/img/sm_old/toussaint_dettlaff.jpg new file mode 100644 index 0000000..4cced28 Binary files /dev/null and b/img/sm_old/toussaint_dettlaff.jpg differ diff --git a/img/sm_old/toussaint_dettlaff_ghastly_beast.jpg b/img/sm_old/toussaint_dettlaff_ghastly_beast.jpg new file mode 100644 index 0000000..edfa655 Binary files /dev/null and b/img/sm_old/toussaint_dettlaff_ghastly_beast.jpg differ diff --git a/img/sm_old/toussaint_dettlaff_higher_vampire.jpg b/img/sm_old/toussaint_dettlaff_higher_vampire.jpg new file mode 100644 index 0000000..057327b Binary files /dev/null and b/img/sm_old/toussaint_dettlaff_higher_vampire.jpg differ diff --git a/img/sm_old/toussaint_ducal_guard_1.jpg b/img/sm_old/toussaint_ducal_guard_1.jpg new file mode 100644 index 0000000..4ef3742 Binary files /dev/null and b/img/sm_old/toussaint_ducal_guard_1.jpg differ diff --git a/img/sm_old/toussaint_ducal_guard_2.jpg b/img/sm_old/toussaint_ducal_guard_2.jpg new file mode 100644 index 0000000..7eb884c Binary files /dev/null and b/img/sm_old/toussaint_ducal_guard_2.jpg differ diff --git a/img/sm_old/toussaint_duchess_informant.jpg b/img/sm_old/toussaint_duchess_informant.jpg new file mode 100644 index 0000000..b326f90 Binary files /dev/null and b/img/sm_old/toussaint_duchess_informant.jpg differ diff --git a/img/sm_old/toussaint_dun_tynne_infantry.jpg b/img/sm_old/toussaint_dun_tynne_infantry.jpg new file mode 100644 index 0000000..590dda1 Binary files /dev/null and b/img/sm_old/toussaint_dun_tynne_infantry.jpg differ diff --git a/img/sm_old/toussaint_field_medic.jpg b/img/sm_old/toussaint_field_medic.jpg new file mode 100644 index 0000000..f7881bd Binary files /dev/null and b/img/sm_old/toussaint_field_medic.jpg differ diff --git a/img/sm_old/toussaint_fisher_king.jpg b/img/sm_old/toussaint_fisher_king.jpg new file mode 100644 index 0000000..a263872 Binary files /dev/null and b/img/sm_old/toussaint_fisher_king.jpg differ diff --git a/img/sm_old/toussaint_fleder.jpg b/img/sm_old/toussaint_fleder.jpg new file mode 100644 index 0000000..fe62885 Binary files /dev/null and b/img/sm_old/toussaint_fleder.jpg differ diff --git a/img/sm_old/toussaint_fringilla_vigo.jpg b/img/sm_old/toussaint_fringilla_vigo.jpg new file mode 100644 index 0000000..a916b6d Binary files /dev/null and b/img/sm_old/toussaint_fringilla_vigo.jpg differ diff --git a/img/sm_old/toussaint_garkain.jpg b/img/sm_old/toussaint_garkain.jpg new file mode 100644 index 0000000..20b9691 Binary files /dev/null and b/img/sm_old/toussaint_garkain.jpg differ diff --git a/img/sm_old/toussaint_golyat.jpg b/img/sm_old/toussaint_golyat.jpg new file mode 100644 index 0000000..72a9f91 Binary files /dev/null and b/img/sm_old/toussaint_golyat.jpg differ diff --git a/img/sm_old/toussaint_gregoire_gorgon.jpg b/img/sm_old/toussaint_gregoire_gorgon.jpg new file mode 100644 index 0000000..cb9cce6 Binary files /dev/null and b/img/sm_old/toussaint_gregoire_gorgon.jpg differ diff --git a/img/sm_old/toussaint_guillaume.jpg b/img/sm_old/toussaint_guillaume.jpg new file mode 100644 index 0000000..5bed4d2 Binary files /dev/null and b/img/sm_old/toussaint_guillaume.jpg differ diff --git a/img/sm_old/toussaint_jousting_champion.jpg b/img/sm_old/toussaint_jousting_champion.jpg new file mode 100644 index 0000000..be9b1ba Binary files /dev/null and b/img/sm_old/toussaint_jousting_champion.jpg differ diff --git a/img/sm_old/toussaint_knight_errant_1.jpg b/img/sm_old/toussaint_knight_errant_1.jpg new file mode 100644 index 0000000..758193e Binary files /dev/null and b/img/sm_old/toussaint_knight_errant_1.jpg differ diff --git a/img/sm_old/toussaint_knight_errant_2.jpg b/img/sm_old/toussaint_knight_errant_2.jpg new file mode 100644 index 0000000..87b702f Binary files /dev/null and b/img/sm_old/toussaint_knight_errant_2.jpg differ diff --git a/img/sm_old/toussaint_knight_errant_3.jpg b/img/sm_old/toussaint_knight_errant_3.jpg new file mode 100644 index 0000000..05f18ae Binary files /dev/null and b/img/sm_old/toussaint_knight_errant_3.jpg differ diff --git a/img/sm_old/toussaint_lacerate.jpg b/img/sm_old/toussaint_lacerate.jpg new file mode 100644 index 0000000..ee316a8 Binary files /dev/null and b/img/sm_old/toussaint_lacerate.jpg differ diff --git a/img/sm_old/toussaint_lady_lake.jpg b/img/sm_old/toussaint_lady_lake.jpg new file mode 100644 index 0000000..0f5215c Binary files /dev/null and b/img/sm_old/toussaint_lady_lake.jpg differ diff --git a/img/sm_old/toussaint_menagerie_keeper.jpg b/img/sm_old/toussaint_menagerie_keeper.jpg new file mode 100644 index 0000000..cf364fc Binary files /dev/null and b/img/sm_old/toussaint_menagerie_keeper.jpg differ diff --git a/img/sm_old/toussaint_milton.jpg b/img/sm_old/toussaint_milton.jpg new file mode 100644 index 0000000..59ad925 Binary files /dev/null and b/img/sm_old/toussaint_milton.jpg differ diff --git a/img/sm_old/toussaint_orianna.jpg b/img/sm_old/toussaint_orianna.jpg new file mode 100644 index 0000000..f1d5a0c Binary files /dev/null and b/img/sm_old/toussaint_orianna.jpg differ diff --git a/img/sm_old/toussaint_palmerin.jpg b/img/sm_old/toussaint_palmerin.jpg new file mode 100644 index 0000000..ff02989 Binary files /dev/null and b/img/sm_old/toussaint_palmerin.jpg differ diff --git a/img/sm_old/toussaint_panther_1.jpg b/img/sm_old/toussaint_panther_1.jpg new file mode 100644 index 0000000..95a2e9b Binary files /dev/null and b/img/sm_old/toussaint_panther_1.jpg differ diff --git a/img/sm_old/toussaint_panther_2.jpg b/img/sm_old/toussaint_panther_2.jpg new file mode 100644 index 0000000..77bbfd1 Binary files /dev/null and b/img/sm_old/toussaint_panther_2.jpg differ diff --git a/img/sm_old/toussaint_panther_3.jpg b/img/sm_old/toussaint_panther_3.jpg new file mode 100644 index 0000000..381e7c4 Binary files /dev/null and b/img/sm_old/toussaint_panther_3.jpg differ diff --git a/img/sm_old/toussaint_poisoner.jpg b/img/sm_old/toussaint_poisoner.jpg new file mode 100644 index 0000000..9d60c26 Binary files /dev/null and b/img/sm_old/toussaint_poisoner.jpg differ diff --git a/img/sm_old/toussaint_protofleder.jpg b/img/sm_old/toussaint_protofleder.jpg new file mode 100644 index 0000000..23bd658 Binary files /dev/null and b/img/sm_old/toussaint_protofleder.jpg differ diff --git a/img/sm_old/toussaint_roderick.jpg b/img/sm_old/toussaint_roderick.jpg new file mode 100644 index 0000000..4945120 Binary files /dev/null and b/img/sm_old/toussaint_roderick.jpg differ diff --git a/img/sm_old/toussaint_seditious_aristocrats.jpg b/img/sm_old/toussaint_seditious_aristocrats.jpg new file mode 100644 index 0000000..4277207 Binary files /dev/null and b/img/sm_old/toussaint_seditious_aristocrats.jpg differ diff --git a/img/sm_old/toussaint_shaelmaar.jpg b/img/sm_old/toussaint_shaelmaar.jpg new file mode 100644 index 0000000..a4a69bf Binary files /dev/null and b/img/sm_old/toussaint_shaelmaar.jpg differ diff --git a/img/sm_old/toussaint_syanna.jpg b/img/sm_old/toussaint_syanna.jpg new file mode 100644 index 0000000..0b87eb1 Binary files /dev/null and b/img/sm_old/toussaint_syanna.jpg differ diff --git a/img/sm_old/toussaint_tufo_monster.jpg b/img/sm_old/toussaint_tufo_monster.jpg new file mode 100644 index 0000000..06ca8fe Binary files /dev/null and b/img/sm_old/toussaint_tufo_monster.jpg differ diff --git a/img/sm_old/toussaint_unseen_elder.jpg b/img/sm_old/toussaint_unseen_elder.jpg new file mode 100644 index 0000000..2d13ba0 Binary files /dev/null and b/img/sm_old/toussaint_unseen_elder.jpg differ diff --git a/img/sm_old/toussaint_vampire_invasion.jpg b/img/sm_old/toussaint_vampire_invasion.jpg new file mode 100644 index 0000000..3cb06e1 Binary files /dev/null and b/img/sm_old/toussaint_vampire_invasion.jpg differ diff --git a/img/sm_old/toussaint_vivienne.jpg b/img/sm_old/toussaint_vivienne.jpg new file mode 100644 index 0000000..62fbc62 Binary files /dev/null and b/img/sm_old/toussaint_vivienne.jpg differ diff --git a/img/sm_old/toussaint_vivienne_oriole.jpg b/img/sm_old/toussaint_vivienne_oriole.jpg new file mode 100644 index 0000000..c91ad3a Binary files /dev/null and b/img/sm_old/toussaint_vivienne_oriole.jpg differ diff --git a/img/sm_old/toussaint_wicked_witch.jpg b/img/sm_old/toussaint_wicked_witch.jpg new file mode 100644 index 0000000..3b9accc Binary files /dev/null and b/img/sm_old/toussaint_wicked_witch.jpg differ diff --git a/img/sm_old/toussaint_wolves_1.jpg b/img/sm_old/toussaint_wolves_1.jpg new file mode 100644 index 0000000..f3f3b5f Binary files /dev/null and b/img/sm_old/toussaint_wolves_1.jpg differ diff --git a/img/sm_old/toussaint_wolves_2.jpg b/img/sm_old/toussaint_wolves_2.jpg new file mode 100644 index 0000000..bf53361 Binary files /dev/null and b/img/sm_old/toussaint_wolves_2.jpg differ diff --git a/img/sm_old/toussaint_yghern.jpg b/img/sm_old/toussaint_yghern.jpg new file mode 100644 index 0000000..9766b4e Binary files /dev/null and b/img/sm_old/toussaint_yghern.jpg differ diff --git a/img/sm_old/weather_clear.jpg b/img/sm_old/weather_clear.jpg new file mode 100644 index 0000000..242c506 Binary files /dev/null and b/img/sm_old/weather_clear.jpg differ diff --git a/img/sm_old/weather_dragon_wrath.jpg b/img/sm_old/weather_dragon_wrath.jpg new file mode 100644 index 0000000..3cb0137 Binary files /dev/null and b/img/sm_old/weather_dragon_wrath.jpg differ diff --git a/img/sm_old/weather_fog.jpg b/img/sm_old/weather_fog.jpg new file mode 100644 index 0000000..912ef67 Binary files /dev/null and b/img/sm_old/weather_fog.jpg differ diff --git a/img/sm_old/weather_frost.jpg b/img/sm_old/weather_frost.jpg new file mode 100644 index 0000000..e16aba4 Binary files /dev/null and b/img/sm_old/weather_frost.jpg differ diff --git a/img/sm_old/weather_giant_spider_web.jpg b/img/sm_old/weather_giant_spider_web.jpg new file mode 100644 index 0000000..93fdee9 Binary files /dev/null and b/img/sm_old/weather_giant_spider_web.jpg differ diff --git a/img/sm_old/weather_rain.jpg b/img/sm_old/weather_rain.jpg new file mode 100644 index 0000000..2d32222 Binary files /dev/null and b/img/sm_old/weather_rain.jpg differ diff --git a/img/sm_old/weather_storm.jpg b/img/sm_old/weather_storm.jpg new file mode 100644 index 0000000..baedcf1 Binary files /dev/null and b/img/sm_old/weather_storm.jpg differ diff --git a/img/sm_old/weather_tse_tse_flies.jpg b/img/sm_old/weather_tse_tse_flies.jpg new file mode 100644 index 0000000..8de1469 Binary files /dev/null and b/img/sm_old/weather_tse_tse_flies.jpg differ diff --git a/img/sm_old/witcher_universe_alzur_maker.jpg b/img/sm_old/witcher_universe_alzur_maker.jpg new file mode 100644 index 0000000..e14f674 Binary files /dev/null and b/img/sm_old/witcher_universe_alzur_maker.jpg differ diff --git a/img/sm_old/witcher_universe_angouleme.jpg b/img/sm_old/witcher_universe_angouleme.jpg new file mode 100644 index 0000000..fd71c20 Binary files /dev/null and b/img/sm_old/witcher_universe_angouleme.jpg differ diff --git a/img/sm_old/witcher_universe_arnaghad.jpg b/img/sm_old/witcher_universe_arnaghad.jpg new file mode 100644 index 0000000..d6fa594 Binary files /dev/null and b/img/sm_old/witcher_universe_arnaghad.jpg differ diff --git a/img/sm_old/witcher_universe_artaud_terranova.jpg b/img/sm_old/witcher_universe_artaud_terranova.jpg new file mode 100644 index 0000000..7c4b99a Binary files /dev/null and b/img/sm_old/witcher_universe_artaud_terranova.jpg differ diff --git a/img/sm_old/witcher_universe_auckes.jpg b/img/sm_old/witcher_universe_auckes.jpg new file mode 100644 index 0000000..9e75d35 Binary files /dev/null and b/img/sm_old/witcher_universe_auckes.jpg differ diff --git a/img/sm_old/witcher_universe_azar_javed.jpg b/img/sm_old/witcher_universe_azar_javed.jpg new file mode 100644 index 0000000..d8413e4 Binary files /dev/null and b/img/sm_old/witcher_universe_azar_javed.jpg differ diff --git a/img/sm_old/witcher_universe_barnabas.jpg b/img/sm_old/witcher_universe_barnabas.jpg new file mode 100644 index 0000000..f960f2b Binary files /dev/null and b/img/sm_old/witcher_universe_barnabas.jpg differ diff --git a/img/sm_old/witcher_universe_berengar.jpg b/img/sm_old/witcher_universe_berengar.jpg new file mode 100644 index 0000000..404cecc Binary files /dev/null and b/img/sm_old/witcher_universe_berengar.jpg differ diff --git a/img/sm_old/witcher_universe_bloody_baron.jpg b/img/sm_old/witcher_universe_bloody_baron.jpg new file mode 100644 index 0000000..de8473c Binary files /dev/null and b/img/sm_old/witcher_universe_bloody_baron.jpg differ diff --git a/img/sm_old/witcher_universe_bomb_heaver.jpg b/img/sm_old/witcher_universe_bomb_heaver.jpg new file mode 100644 index 0000000..cf98ba8 Binary files /dev/null and b/img/sm_old/witcher_universe_bomb_heaver.jpg differ diff --git a/img/sm_old/witcher_universe_boris.jpg b/img/sm_old/witcher_universe_boris.jpg new file mode 100644 index 0000000..9528a06 Binary files /dev/null and b/img/sm_old/witcher_universe_boris.jpg differ diff --git a/img/sm_old/witcher_universe_brehen.jpg b/img/sm_old/witcher_universe_brehen.jpg new file mode 100644 index 0000000..9f31b13 Binary files /dev/null and b/img/sm_old/witcher_universe_brehen.jpg differ diff --git a/img/sm_old/witcher_universe_cicada.jpg b/img/sm_old/witcher_universe_cicada.jpg new file mode 100644 index 0000000..2c4db30 Binary files /dev/null and b/img/sm_old/witcher_universe_cicada.jpg differ diff --git a/img/sm_old/witcher_universe_coen.jpg b/img/sm_old/witcher_universe_coen.jpg new file mode 100644 index 0000000..db9ae4c Binary files /dev/null and b/img/sm_old/witcher_universe_coen.jpg differ diff --git a/img/sm_old/witcher_universe_coral.jpg b/img/sm_old/witcher_universe_coral.jpg new file mode 100644 index 0000000..dcd1cb6 Binary files /dev/null and b/img/sm_old/witcher_universe_coral.jpg differ diff --git a/img/sm_old/witcher_universe_cosimo_malaspina.jpg b/img/sm_old/witcher_universe_cosimo_malaspina.jpg new file mode 100644 index 0000000..cbd7499 Binary files /dev/null and b/img/sm_old/witcher_universe_cosimo_malaspina.jpg differ diff --git a/img/sm_old/witcher_universe_dana_meadbh.jpg b/img/sm_old/witcher_universe_dana_meadbh.jpg new file mode 100644 index 0000000..7113a37 Binary files /dev/null and b/img/sm_old/witcher_universe_dana_meadbh.jpg differ diff --git a/img/sm_old/witcher_universe_deserter_1.jpg b/img/sm_old/witcher_universe_deserter_1.jpg new file mode 100644 index 0000000..7ef7cf7 Binary files /dev/null and b/img/sm_old/witcher_universe_deserter_1.jpg differ diff --git a/img/sm_old/witcher_universe_deserter_2.jpg b/img/sm_old/witcher_universe_deserter_2.jpg new file mode 100644 index 0000000..7985d60 Binary files /dev/null and b/img/sm_old/witcher_universe_deserter_2.jpg differ diff --git a/img/sm_old/witcher_universe_deserter_3.jpg b/img/sm_old/witcher_universe_deserter_3.jpg new file mode 100644 index 0000000..d7f4903 Binary files /dev/null and b/img/sm_old/witcher_universe_deserter_3.jpg differ diff --git a/img/sm_old/witcher_universe_djinn.jpg b/img/sm_old/witcher_universe_djinn.jpg new file mode 100644 index 0000000..b7e4068 Binary files /dev/null and b/img/sm_old/witcher_universe_djinn.jpg differ diff --git a/img/sm_old/witcher_universe_doppler_1.jpg b/img/sm_old/witcher_universe_doppler_1.jpg new file mode 100644 index 0000000..c42071b Binary files /dev/null and b/img/sm_old/witcher_universe_doppler_1.jpg differ diff --git a/img/sm_old/witcher_universe_doppler_2.jpg b/img/sm_old/witcher_universe_doppler_2.jpg new file mode 100644 index 0000000..3f1f35b Binary files /dev/null and b/img/sm_old/witcher_universe_doppler_2.jpg differ diff --git a/img/sm_old/witcher_universe_dorregaray.jpg b/img/sm_old/witcher_universe_dorregaray.jpg new file mode 100644 index 0000000..f94be3b Binary files /dev/null and b/img/sm_old/witcher_universe_dorregaray.jpg differ diff --git a/img/sm_old/witcher_universe_erland.jpg b/img/sm_old/witcher_universe_erland.jpg new file mode 100644 index 0000000..ca0667f Binary files /dev/null and b/img/sm_old/witcher_universe_erland.jpg differ diff --git a/img/sm_old/witcher_universe_eskel.jpg b/img/sm_old/witcher_universe_eskel.jpg new file mode 100644 index 0000000..313cf91 Binary files /dev/null and b/img/sm_old/witcher_universe_eskel.jpg differ diff --git a/img/sm_old/witcher_universe_eskel_2.jpg b/img/sm_old/witcher_universe_eskel_2.jpg new file mode 100644 index 0000000..49a15a8 Binary files /dev/null and b/img/sm_old/witcher_universe_eskel_2.jpg differ diff --git a/img/sm_old/witcher_universe_essi_daven.jpg b/img/sm_old/witcher_universe_essi_daven.jpg new file mode 100644 index 0000000..d26c6f0 Binary files /dev/null and b/img/sm_old/witcher_universe_essi_daven.jpg differ diff --git a/img/sm_old/witcher_universe_fercart.jpg b/img/sm_old/witcher_universe_fercart.jpg new file mode 100644 index 0000000..377c411 Binary files /dev/null and b/img/sm_old/witcher_universe_fercart.jpg differ diff --git a/img/sm_old/witcher_universe_field_marshal_duda.jpg b/img/sm_old/witcher_universe_field_marshal_duda.jpg new file mode 100644 index 0000000..877a9e2 Binary files /dev/null and b/img/sm_old/witcher_universe_field_marshal_duda.jpg differ diff --git a/img/sm_old/witcher_universe_fugas.jpg b/img/sm_old/witcher_universe_fugas.jpg new file mode 100644 index 0000000..4659498 Binary files /dev/null and b/img/sm_old/witcher_universe_fugas.jpg differ diff --git a/img/sm_old/witcher_universe_gaetan.jpg b/img/sm_old/witcher_universe_gaetan.jpg new file mode 100644 index 0000000..9466565 Binary files /dev/null and b/img/sm_old/witcher_universe_gaetan.jpg differ diff --git a/img/sm_old/witcher_universe_gascon.jpg b/img/sm_old/witcher_universe_gascon.jpg new file mode 100644 index 0000000..56d8332 Binary files /dev/null and b/img/sm_old/witcher_universe_gascon.jpg differ diff --git a/img/sm_old/witcher_universe_gascon_infiltrator.jpg b/img/sm_old/witcher_universe_gascon_infiltrator.jpg new file mode 100644 index 0000000..445d736 Binary files /dev/null and b/img/sm_old/witcher_universe_gascon_infiltrator.jpg differ diff --git a/img/sm_old/witcher_universe_gascon_light_cavalry.jpg b/img/sm_old/witcher_universe_gascon_light_cavalry.jpg new file mode 100644 index 0000000..c360dbf Binary files /dev/null and b/img/sm_old/witcher_universe_gascon_light_cavalry.jpg differ diff --git a/img/sm_old/witcher_universe_gascon_slinger.jpg b/img/sm_old/witcher_universe_gascon_slinger.jpg new file mode 100644 index 0000000..7f832c8 Binary files /dev/null and b/img/sm_old/witcher_universe_gascon_slinger.jpg differ diff --git a/img/sm_old/witcher_universe_george_kagen.jpg b/img/sm_old/witcher_universe_george_kagen.jpg new file mode 100644 index 0000000..4f73296 Binary files /dev/null and b/img/sm_old/witcher_universe_george_kagen.jpg differ diff --git a/img/sm_old/witcher_universe_geralt_1.jpg b/img/sm_old/witcher_universe_geralt_1.jpg new file mode 100644 index 0000000..03b5588 Binary files /dev/null and b/img/sm_old/witcher_universe_geralt_1.jpg differ diff --git a/img/sm_old/witcher_universe_gerd.jpg b/img/sm_old/witcher_universe_gerd.jpg new file mode 100644 index 0000000..c453ed8 Binary files /dev/null and b/img/sm_old/witcher_universe_gerd.jpg differ diff --git a/img/sm_old/witcher_universe_gerd_2.jpg b/img/sm_old/witcher_universe_gerd_2.jpg new file mode 100644 index 0000000..c453ed8 Binary files /dev/null and b/img/sm_old/witcher_universe_gerd_2.jpg differ diff --git a/img/sm_old/witcher_universe_gerhart_aelle.jpg b/img/sm_old/witcher_universe_gerhart_aelle.jpg new file mode 100644 index 0000000..138d09d Binary files /dev/null and b/img/sm_old/witcher_universe_gerhart_aelle.jpg differ diff --git a/img/sm_old/witcher_universe_gezras.jpg b/img/sm_old/witcher_universe_gezras.jpg new file mode 100644 index 0000000..0a8c99c Binary files /dev/null and b/img/sm_old/witcher_universe_gezras.jpg differ diff --git a/img/sm_old/witcher_universe_gimpy_gerwin.jpg b/img/sm_old/witcher_universe_gimpy_gerwin.jpg new file mode 100644 index 0000000..c0b48ec Binary files /dev/null and b/img/sm_old/witcher_universe_gimpy_gerwin.jpg differ diff --git a/img/sm_old/witcher_universe_gorthur_gvaed.jpg b/img/sm_old/witcher_universe_gorthur_gvaed.jpg new file mode 100644 index 0000000..3df3bb5 Binary files /dev/null and b/img/sm_old/witcher_universe_gorthur_gvaed.jpg differ diff --git a/img/sm_old/witcher_universe_haern_caduch.jpg b/img/sm_old/witcher_universe_haern_caduch.jpg new file mode 100644 index 0000000..69b687a Binary files /dev/null and b/img/sm_old/witcher_universe_haern_caduch.jpg differ diff --git a/img/sm_old/witcher_universe_idarran_ulivo.jpg b/img/sm_old/witcher_universe_idarran_ulivo.jpg new file mode 100644 index 0000000..e65eb3f Binary files /dev/null and b/img/sm_old/witcher_universe_idarran_ulivo.jpg differ diff --git a/img/sm_old/witcher_universe_idr.jpg b/img/sm_old/witcher_universe_idr.jpg new file mode 100644 index 0000000..6b126d4 Binary files /dev/null and b/img/sm_old/witcher_universe_idr.jpg differ diff --git a/img/sm_old/witcher_universe_iola.jpg b/img/sm_old/witcher_universe_iola.jpg new file mode 100644 index 0000000..dba4c67 Binary files /dev/null and b/img/sm_old/witcher_universe_iola.jpg differ diff --git a/img/sm_old/witcher_universe_iris_companions.jpg b/img/sm_old/witcher_universe_iris_companions.jpg new file mode 100644 index 0000000..4686e2f Binary files /dev/null and b/img/sm_old/witcher_universe_iris_companions.jpg differ diff --git a/img/sm_old/witcher_universe_iris_von_everec.jpg b/img/sm_old/witcher_universe_iris_von_everec.jpg new file mode 100644 index 0000000..b224faf Binary files /dev/null and b/img/sm_old/witcher_universe_iris_von_everec.jpg differ diff --git a/img/sm_old/witcher_universe_istredd.jpg b/img/sm_old/witcher_universe_istredd.jpg new file mode 100644 index 0000000..c5398c4 Binary files /dev/null and b/img/sm_old/witcher_universe_istredd.jpg differ diff --git a/img/sm_old/witcher_universe_ivar.jpg b/img/sm_old/witcher_universe_ivar.jpg new file mode 100644 index 0000000..5381b35 Binary files /dev/null and b/img/sm_old/witcher_universe_ivar.jpg differ diff --git a/img/sm_old/witcher_universe_ivo_belhaven.jpg b/img/sm_old/witcher_universe_ivo_belhaven.jpg new file mode 100644 index 0000000..6a3916b Binary files /dev/null and b/img/sm_old/witcher_universe_ivo_belhaven.jpg differ diff --git a/img/sm_old/witcher_universe_johnny.jpg b/img/sm_old/witcher_universe_johnny.jpg new file mode 100644 index 0000000..6742d5c Binary files /dev/null and b/img/sm_old/witcher_universe_johnny.jpg differ diff --git a/img/sm_old/witcher_universe_junod.jpg b/img/sm_old/witcher_universe_junod.jpg new file mode 100644 index 0000000..c928742 Binary files /dev/null and b/img/sm_old/witcher_universe_junod.jpg differ diff --git a/img/sm_old/witcher_universe_kaer_morhen.jpg b/img/sm_old/witcher_universe_kaer_morhen.jpg new file mode 100644 index 0000000..b358334 Binary files /dev/null and b/img/sm_old/witcher_universe_kaer_morhen.jpg differ diff --git a/img/sm_old/witcher_universe_kaer_seren.jpg b/img/sm_old/witcher_universe_kaer_seren.jpg new file mode 100644 index 0000000..0ec5104 Binary files /dev/null and b/img/sm_old/witcher_universe_kaer_seren.jpg differ diff --git a/img/sm_old/witcher_universe_kalkstein.jpg b/img/sm_old/witcher_universe_kalkstein.jpg new file mode 100644 index 0000000..b93565b Binary files /dev/null and b/img/sm_old/witcher_universe_kalkstein.jpg differ diff --git a/img/sm_old/witcher_universe_keldar.jpg b/img/sm_old/witcher_universe_keldar.jpg new file mode 100644 index 0000000..3d140cc Binary files /dev/null and b/img/sm_old/witcher_universe_keldar.jpg differ diff --git a/img/sm_old/witcher_universe_kelpie.jpg b/img/sm_old/witcher_universe_kelpie.jpg new file mode 100644 index 0000000..ae9bc1e Binary files /dev/null and b/img/sm_old/witcher_universe_kelpie.jpg differ diff --git a/img/sm_old/witcher_universe_kolgrim.jpg b/img/sm_old/witcher_universe_kolgrim.jpg new file mode 100644 index 0000000..ba6b3ff Binary files /dev/null and b/img/sm_old/witcher_universe_kolgrim.jpg differ diff --git a/img/sm_old/witcher_universe_koshchey.jpg b/img/sm_old/witcher_universe_koshchey.jpg new file mode 100644 index 0000000..4e7a5e1 Binary files /dev/null and b/img/sm_old/witcher_universe_koshchey.jpg differ diff --git a/img/sm_old/witcher_universe_lambert.jpg b/img/sm_old/witcher_universe_lambert.jpg new file mode 100644 index 0000000..75d5a25 Binary files /dev/null and b/img/sm_old/witcher_universe_lambert.jpg differ diff --git a/img/sm_old/witcher_universe_lambert_2.jpg b/img/sm_old/witcher_universe_lambert_2.jpg new file mode 100644 index 0000000..520eae8 Binary files /dev/null and b/img/sm_old/witcher_universe_lambert_2.jpg differ diff --git a/img/sm_old/witcher_universe_leo.jpg b/img/sm_old/witcher_universe_leo.jpg new file mode 100644 index 0000000..aaacc02 Binary files /dev/null and b/img/sm_old/witcher_universe_leo.jpg differ diff --git a/img/sm_old/witcher_universe_leo_bonhart.jpg b/img/sm_old/witcher_universe_leo_bonhart.jpg new file mode 100644 index 0000000..57053a5 Binary files /dev/null and b/img/sm_old/witcher_universe_leo_bonhart.jpg differ diff --git a/img/sm_old/witcher_universe_letho.jpg b/img/sm_old/witcher_universe_letho.jpg new file mode 100644 index 0000000..002c4cb Binary files /dev/null and b/img/sm_old/witcher_universe_letho.jpg differ diff --git a/img/sm_old/witcher_universe_lydia_bredevoort.jpg b/img/sm_old/witcher_universe_lydia_bredevoort.jpg new file mode 100644 index 0000000..d6b1f90 Binary files /dev/null and b/img/sm_old/witcher_universe_lydia_bredevoort.jpg differ diff --git a/img/sm_old/witcher_universe_mad_kiyan.jpg b/img/sm_old/witcher_universe_mad_kiyan.jpg new file mode 100644 index 0000000..cadd6b9 Binary files /dev/null and b/img/sm_old/witcher_universe_mad_kiyan.jpg differ diff --git a/img/sm_old/witcher_universe_marlene_trastamara.jpg b/img/sm_old/witcher_universe_marlene_trastamara.jpg new file mode 100644 index 0000000..36846a0 Binary files /dev/null and b/img/sm_old/witcher_universe_marlene_trastamara.jpg differ diff --git a/img/sm_old/witcher_universe_myrgtabrakke.jpg b/img/sm_old/witcher_universe_myrgtabrakke.jpg new file mode 100644 index 0000000..c70efe3 Binary files /dev/null and b/img/sm_old/witcher_universe_myrgtabrakke.jpg differ diff --git a/img/sm_old/witcher_universe_nenneke.jpg b/img/sm_old/witcher_universe_nenneke.jpg new file mode 100644 index 0000000..68bb24d Binary files /dev/null and b/img/sm_old/witcher_universe_nenneke.jpg differ diff --git a/img/sm_old/witcher_universe_nivellen.jpg b/img/sm_old/witcher_universe_nivellen.jpg new file mode 100644 index 0000000..80068be Binary files /dev/null and b/img/sm_old/witcher_universe_nivellen.jpg differ diff --git a/img/sm_old/witcher_universe_operator.jpg b/img/sm_old/witcher_universe_operator.jpg new file mode 100644 index 0000000..a1be1ad Binary files /dev/null and b/img/sm_old/witcher_universe_operator.jpg differ diff --git a/img/sm_old/witcher_universe_ortolan.jpg b/img/sm_old/witcher_universe_ortolan.jpg new file mode 100644 index 0000000..4c07a80 Binary files /dev/null and b/img/sm_old/witcher_universe_ortolan.jpg differ diff --git a/img/sm_old/witcher_universe_pellar.jpg b/img/sm_old/witcher_universe_pellar.jpg new file mode 100644 index 0000000..468ae81 Binary files /dev/null and b/img/sm_old/witcher_universe_pellar.jpg differ diff --git a/img/sm_old/witcher_universe_phoenix.jpg b/img/sm_old/witcher_universe_phoenix.jpg new file mode 100644 index 0000000..9ccdae3 Binary files /dev/null and b/img/sm_old/witcher_universe_phoenix.jpg differ diff --git a/img/sm_old/witcher_universe_prophet_lebioda.jpg b/img/sm_old/witcher_universe_prophet_lebioda.jpg new file mode 100644 index 0000000..0a1d80c Binary files /dev/null and b/img/sm_old/witcher_universe_prophet_lebioda.jpg differ diff --git a/img/sm_old/witcher_universe_raging_bear.jpg b/img/sm_old/witcher_universe_raging_bear.jpg new file mode 100644 index 0000000..1f3d82a Binary files /dev/null and b/img/sm_old/witcher_universe_raging_bear.jpg differ diff --git a/img/sm_old/witcher_universe_ralf_blunden.jpg b/img/sm_old/witcher_universe_ralf_blunden.jpg new file mode 100644 index 0000000..d1435c9 Binary files /dev/null and b/img/sm_old/witcher_universe_ralf_blunden.jpg differ diff --git a/img/sm_old/witcher_universe_rats_asse.jpg b/img/sm_old/witcher_universe_rats_asse.jpg new file mode 100644 index 0000000..d5a9fb8 Binary files /dev/null and b/img/sm_old/witcher_universe_rats_asse.jpg differ diff --git a/img/sm_old/witcher_universe_rats_giselher.jpg b/img/sm_old/witcher_universe_rats_giselher.jpg new file mode 100644 index 0000000..e607675 Binary files /dev/null and b/img/sm_old/witcher_universe_rats_giselher.jpg differ diff --git a/img/sm_old/witcher_universe_rats_iskra.jpg b/img/sm_old/witcher_universe_rats_iskra.jpg new file mode 100644 index 0000000..a524309 Binary files /dev/null and b/img/sm_old/witcher_universe_rats_iskra.jpg differ diff --git a/img/sm_old/witcher_universe_rats_kayleigh.jpg b/img/sm_old/witcher_universe_rats_kayleigh.jpg new file mode 100644 index 0000000..4fa59b5 Binary files /dev/null and b/img/sm_old/witcher_universe_rats_kayleigh.jpg differ diff --git a/img/sm_old/witcher_universe_rats_mistle.jpg b/img/sm_old/witcher_universe_rats_mistle.jpg new file mode 100644 index 0000000..dda7623 Binary files /dev/null and b/img/sm_old/witcher_universe_rats_mistle.jpg differ diff --git a/img/sm_old/witcher_universe_rats_reef.jpg b/img/sm_old/witcher_universe_rats_reef.jpg new file mode 100644 index 0000000..9b3af24 Binary files /dev/null and b/img/sm_old/witcher_universe_rats_reef.jpg differ diff --git a/img/sm_old/witcher_universe_renew.jpg b/img/sm_old/witcher_universe_renew.jpg new file mode 100644 index 0000000..ab7b84c Binary files /dev/null and b/img/sm_old/witcher_universe_renew.jpg differ diff --git a/img/sm_old/witcher_universe_renfri.jpg b/img/sm_old/witcher_universe_renfri.jpg new file mode 100644 index 0000000..c3f3fc7 Binary files /dev/null and b/img/sm_old/witcher_universe_renfri.jpg differ diff --git a/img/sm_old/witcher_universe_rhapsodic_melody.jpg b/img/sm_old/witcher_universe_rhapsodic_melody.jpg new file mode 100644 index 0000000..8e8f2f7 Binary files /dev/null and b/img/sm_old/witcher_universe_rhapsodic_melody.jpg differ diff --git a/img/sm_old/witcher_universe_rience.jpg b/img/sm_old/witcher_universe_rience.jpg new file mode 100644 index 0000000..a94d030 Binary files /dev/null and b/img/sm_old/witcher_universe_rience.jpg differ diff --git a/img/sm_old/witcher_universe_roach.jpg b/img/sm_old/witcher_universe_roach.jpg new file mode 100644 index 0000000..1b4a136 Binary files /dev/null and b/img/sm_old/witcher_universe_roach.jpg differ diff --git a/img/sm_old/witcher_universe_salma.jpg b/img/sm_old/witcher_universe_salma.jpg new file mode 100644 index 0000000..031d55a Binary files /dev/null and b/img/sm_old/witcher_universe_salma.jpg differ diff --git a/img/sm_old/witcher_universe_sarah.jpg b/img/sm_old/witcher_universe_sarah.jpg new file mode 100644 index 0000000..d8d8acb Binary files /dev/null and b/img/sm_old/witcher_universe_sarah.jpg differ diff --git a/img/sm_old/witcher_universe_serrit.jpg b/img/sm_old/witcher_universe_serrit.jpg new file mode 100644 index 0000000..2694e60 Binary files /dev/null and b/img/sm_old/witcher_universe_serrit.jpg differ diff --git a/img/sm_old/witcher_universe_sheenaz.jpg b/img/sm_old/witcher_universe_sheenaz.jpg new file mode 100644 index 0000000..c6348c8 Binary files /dev/null and b/img/sm_old/witcher_universe_sheenaz.jpg differ diff --git a/img/sm_old/witcher_universe_strays_spalla.jpg b/img/sm_old/witcher_universe_strays_spalla.jpg new file mode 100644 index 0000000..187c5af Binary files /dev/null and b/img/sm_old/witcher_universe_strays_spalla.jpg differ diff --git a/img/sm_old/witcher_universe_stregobor.jpg b/img/sm_old/witcher_universe_stregobor.jpg new file mode 100644 index 0000000..b5d3f58 Binary files /dev/null and b/img/sm_old/witcher_universe_stregobor.jpg differ diff --git a/img/sm_old/witcher_universe_stygga_castle.jpg b/img/sm_old/witcher_universe_stygga_castle.jpg new file mode 100644 index 0000000..be54a3d Binary files /dev/null and b/img/sm_old/witcher_universe_stygga_castle.jpg differ diff --git a/img/sm_old/witcher_universe_swallow_potion.jpg b/img/sm_old/witcher_universe_swallow_potion.jpg new file mode 100644 index 0000000..39cddfb Binary files /dev/null and b/img/sm_old/witcher_universe_swallow_potion.jpg differ diff --git a/img/sm_old/witcher_universe_tea_vea_1.jpg b/img/sm_old/witcher_universe_tea_vea_1.jpg new file mode 100644 index 0000000..75105ee Binary files /dev/null and b/img/sm_old/witcher_universe_tea_vea_1.jpg differ diff --git a/img/sm_old/witcher_universe_tea_vea_2.jpg b/img/sm_old/witcher_universe_tea_vea_2.jpg new file mode 100644 index 0000000..c297231 Binary files /dev/null and b/img/sm_old/witcher_universe_tea_vea_2.jpg differ diff --git a/img/sm_old/witcher_universe_tissaia.jpg b/img/sm_old/witcher_universe_tissaia.jpg new file mode 100644 index 0000000..59a6b91 Binary files /dev/null and b/img/sm_old/witcher_universe_tissaia.jpg differ diff --git a/img/sm_old/witcher_universe_torque.jpg b/img/sm_old/witcher_universe_torque.jpg new file mode 100644 index 0000000..677f774 Binary files /dev/null and b/img/sm_old/witcher_universe_torque.jpg differ diff --git a/img/sm_old/witcher_universe_vesemir.jpg b/img/sm_old/witcher_universe_vesemir.jpg new file mode 100644 index 0000000..05ab932 Binary files /dev/null and b/img/sm_old/witcher_universe_vesemir.jpg differ diff --git a/img/sm_old/witcher_universe_vilgefortz_magician_kovir.jpg b/img/sm_old/witcher_universe_vilgefortz_magician_kovir.jpg new file mode 100644 index 0000000..4036530 Binary files /dev/null and b/img/sm_old/witcher_universe_vilgefortz_magician_kovir.jpg differ diff --git a/img/sm_old/witcher_universe_vilgefortz_sorcerer.jpg b/img/sm_old/witcher_universe_vilgefortz_sorcerer.jpg new file mode 100644 index 0000000..69710d6 Binary files /dev/null and b/img/sm_old/witcher_universe_vilgefortz_sorcerer.jpg differ diff --git a/img/sm_old/witcher_universe_vincent_meis.jpg b/img/sm_old/witcher_universe_vincent_meis.jpg new file mode 100644 index 0000000..94becca Binary files /dev/null and b/img/sm_old/witcher_universe_vincent_meis.jpg differ diff --git a/img/sm_old/witcher_universe_visenna.jpg b/img/sm_old/witcher_universe_visenna.jpg new file mode 100644 index 0000000..ee74ac7 Binary files /dev/null and b/img/sm_old/witcher_universe_visenna.jpg differ diff --git a/img/sm_old/witcher_universe_vlodimir_von_everec.jpg b/img/sm_old/witcher_universe_vlodimir_von_everec.jpg new file mode 100644 index 0000000..dc7d14d Binary files /dev/null and b/img/sm_old/witcher_universe_vlodimir_von_everec.jpg differ diff --git a/img/sm_old/witcher_universe_vysogota.jpg b/img/sm_old/witcher_universe_vysogota.jpg new file mode 100644 index 0000000..0f615d2 Binary files /dev/null and b/img/sm_old/witcher_universe_vysogota.jpg differ diff --git a/img/sm_old/witcher_universe_warrit.jpg b/img/sm_old/witcher_universe_warrit.jpg new file mode 100644 index 0000000..8a47bd9 Binary files /dev/null and b/img/sm_old/witcher_universe_warrit.jpg differ diff --git a/img/sm_old/zerrikania_alchemist.jpg b/img/sm_old/zerrikania_alchemist.jpg new file mode 100644 index 0000000..58eff83 Binary files /dev/null and b/img/sm_old/zerrikania_alchemist.jpg differ diff --git a/img/sm_old/zerrikania_apucunpture_healer.jpg b/img/sm_old/zerrikania_apucunpture_healer.jpg new file mode 100644 index 0000000..5a21767 Binary files /dev/null and b/img/sm_old/zerrikania_apucunpture_healer.jpg differ diff --git a/img/sm_old/zerrikania_azar_javed.jpg b/img/sm_old/zerrikania_azar_javed.jpg new file mode 100644 index 0000000..cf920fa Binary files /dev/null and b/img/sm_old/zerrikania_azar_javed.jpg differ diff --git a/img/sm_old/zerrikania_baal_zebuth.jpg b/img/sm_old/zerrikania_baal_zebuth.jpg new file mode 100644 index 0000000..a8174ff Binary files /dev/null and b/img/sm_old/zerrikania_baal_zebuth.jpg differ diff --git a/img/sm_old/zerrikania_balladeer.jpg b/img/sm_old/zerrikania_balladeer.jpg new file mode 100644 index 0000000..6a08650 Binary files /dev/null and b/img/sm_old/zerrikania_balladeer.jpg differ diff --git a/img/sm_old/zerrikania_bart.jpg b/img/sm_old/zerrikania_bart.jpg new file mode 100644 index 0000000..92150ea Binary files /dev/null and b/img/sm_old/zerrikania_bart.jpg differ diff --git a/img/sm_old/zerrikania_behemoth.jpg b/img/sm_old/zerrikania_behemoth.jpg new file mode 100644 index 0000000..b9615a3 Binary files /dev/null and b/img/sm_old/zerrikania_behemoth.jpg differ diff --git a/img/sm_old/zerrikania_boa.jpg b/img/sm_old/zerrikania_boa.jpg new file mode 100644 index 0000000..feee3e2 Binary files /dev/null and b/img/sm_old/zerrikania_boa.jpg differ diff --git a/img/sm_old/zerrikania_bomb_maker_1.jpg b/img/sm_old/zerrikania_bomb_maker_1.jpg new file mode 100644 index 0000000..ae98892 Binary files /dev/null and b/img/sm_old/zerrikania_bomb_maker_1.jpg differ diff --git a/img/sm_old/zerrikania_bomb_maker_2.jpg b/img/sm_old/zerrikania_bomb_maker_2.jpg new file mode 100644 index 0000000..a1c8938 Binary files /dev/null and b/img/sm_old/zerrikania_bomb_maker_2.jpg differ diff --git a/img/sm_old/zerrikania_canyon_herbalist.jpg b/img/sm_old/zerrikania_canyon_herbalist.jpg new file mode 100644 index 0000000..8a04648 Binary files /dev/null and b/img/sm_old/zerrikania_canyon_herbalist.jpg differ diff --git a/img/sm_old/zerrikania_collective_trance.jpg b/img/sm_old/zerrikania_collective_trance.jpg new file mode 100644 index 0000000..7b0429d Binary files /dev/null and b/img/sm_old/zerrikania_collective_trance.jpg differ diff --git a/img/sm_old/zerrikania_dragon_priestess_lua.jpg b/img/sm_old/zerrikania_dragon_priestess_lua.jpg new file mode 100644 index 0000000..03502d4 Binary files /dev/null and b/img/sm_old/zerrikania_dragon_priestess_lua.jpg differ diff --git a/img/sm_old/zerrikania_emetouka.jpg b/img/sm_old/zerrikania_emetouka.jpg new file mode 100644 index 0000000..f44c883 Binary files /dev/null and b/img/sm_old/zerrikania_emetouka.jpg differ diff --git a/img/sm_old/zerrikania_faithel_1.jpg b/img/sm_old/zerrikania_faithel_1.jpg new file mode 100644 index 0000000..d8f33ba Binary files /dev/null and b/img/sm_old/zerrikania_faithel_1.jpg differ diff --git a/img/sm_old/zerrikania_faithel_2.jpg b/img/sm_old/zerrikania_faithel_2.jpg new file mode 100644 index 0000000..ba27299 Binary files /dev/null and b/img/sm_old/zerrikania_faithel_2.jpg differ diff --git a/img/sm_old/zerrikania_faithel_3.jpg b/img/sm_old/zerrikania_faithel_3.jpg new file mode 100644 index 0000000..0ee5d9b Binary files /dev/null and b/img/sm_old/zerrikania_faithel_3.jpg differ diff --git a/img/sm_old/zerrikania_first_faithel_kia.jpg b/img/sm_old/zerrikania_first_faithel_kia.jpg new file mode 100644 index 0000000..d153144 Binary files /dev/null and b/img/sm_old/zerrikania_first_faithel_kia.jpg differ diff --git a/img/sm_old/zerrikania_free_warrior_1.jpg b/img/sm_old/zerrikania_free_warrior_1.jpg new file mode 100644 index 0000000..989c1b7 Binary files /dev/null and b/img/sm_old/zerrikania_free_warrior_1.jpg differ diff --git a/img/sm_old/zerrikania_free_warrior_2.jpg b/img/sm_old/zerrikania_free_warrior_2.jpg new file mode 100644 index 0000000..033f7d5 Binary files /dev/null and b/img/sm_old/zerrikania_free_warrior_2.jpg differ diff --git a/img/sm_old/zerrikania_free_warrior_3.jpg b/img/sm_old/zerrikania_free_warrior_3.jpg new file mode 100644 index 0000000..84e1bae Binary files /dev/null and b/img/sm_old/zerrikania_free_warrior_3.jpg differ diff --git a/img/sm_old/zerrikania_free_warrior_4.jpg b/img/sm_old/zerrikania_free_warrior_4.jpg new file mode 100644 index 0000000..fa6e41d Binary files /dev/null and b/img/sm_old/zerrikania_free_warrior_4.jpg differ diff --git a/img/sm_old/zerrikania_free_warrior_5.jpg b/img/sm_old/zerrikania_free_warrior_5.jpg new file mode 100644 index 0000000..c89e1e1 Binary files /dev/null and b/img/sm_old/zerrikania_free_warrior_5.jpg differ diff --git a/img/sm_old/zerrikania_germinus.jpg b/img/sm_old/zerrikania_germinus.jpg new file mode 100644 index 0000000..6483cf3 Binary files /dev/null and b/img/sm_old/zerrikania_germinus.jpg differ diff --git a/img/sm_old/zerrikania_giant_spotted_spider.jpg b/img/sm_old/zerrikania_giant_spotted_spider.jpg new file mode 100644 index 0000000..e84fb43 Binary files /dev/null and b/img/sm_old/zerrikania_giant_spotted_spider.jpg differ diff --git a/img/sm_old/zerrikania_heavy_fire_scorpion.jpg b/img/sm_old/zerrikania_heavy_fire_scorpion.jpg new file mode 100644 index 0000000..c6ff89a Binary files /dev/null and b/img/sm_old/zerrikania_heavy_fire_scorpion.jpg differ diff --git a/img/sm_old/zerrikania_high_priestess_nia.jpg b/img/sm_old/zerrikania_high_priestess_nia.jpg new file mode 100644 index 0000000..895a53d Binary files /dev/null and b/img/sm_old/zerrikania_high_priestess_nia.jpg differ diff --git a/img/sm_old/zerrikania_hippotoxotai_1.jpg b/img/sm_old/zerrikania_hippotoxotai_1.jpg new file mode 100644 index 0000000..0016dd6 Binary files /dev/null and b/img/sm_old/zerrikania_hippotoxotai_1.jpg differ diff --git a/img/sm_old/zerrikania_hippotoxotai_2.jpg b/img/sm_old/zerrikania_hippotoxotai_2.jpg new file mode 100644 index 0000000..e927510 Binary files /dev/null and b/img/sm_old/zerrikania_hippotoxotai_2.jpg differ diff --git a/img/sm_old/zerrikania_hippotoxotai_3.jpg b/img/sm_old/zerrikania_hippotoxotai_3.jpg new file mode 100644 index 0000000..0db889f Binary files /dev/null and b/img/sm_old/zerrikania_hippotoxotai_3.jpg differ diff --git a/img/sm_old/zerrikania_hyenas.jpg b/img/sm_old/zerrikania_hyenas.jpg new file mode 100644 index 0000000..e9459b9 Binary files /dev/null and b/img/sm_old/zerrikania_hyenas.jpg differ diff --git a/img/sm_old/zerrikania_jackals.jpg b/img/sm_old/zerrikania_jackals.jpg new file mode 100644 index 0000000..15ab261 Binary files /dev/null and b/img/sm_old/zerrikania_jackals.jpg differ diff --git a/img/sm_old/zerrikania_keltullis.jpg b/img/sm_old/zerrikania_keltullis.jpg new file mode 100644 index 0000000..72f1a79 Binary files /dev/null and b/img/sm_old/zerrikania_keltullis.jpg differ diff --git a/img/sm_old/zerrikania_leopard_2.jpg b/img/sm_old/zerrikania_leopard_2.jpg new file mode 100644 index 0000000..6c1b535 Binary files /dev/null and b/img/sm_old/zerrikania_leopard_2.jpg differ diff --git a/img/sm_old/zerrikania_leopoard_1.jpg b/img/sm_old/zerrikania_leopoard_1.jpg new file mode 100644 index 0000000..aad158e Binary files /dev/null and b/img/sm_old/zerrikania_leopoard_1.jpg differ diff --git a/img/sm_old/zerrikania_lilit_niya.jpg b/img/sm_old/zerrikania_lilit_niya.jpg new file mode 100644 index 0000000..44a5f30 Binary files /dev/null and b/img/sm_old/zerrikania_lilit_niya.jpg differ diff --git a/img/sm_old/zerrikania_merineaevelth.jpg b/img/sm_old/zerrikania_merineaevelth.jpg new file mode 100644 index 0000000..f47b67b Binary files /dev/null and b/img/sm_old/zerrikania_merineaevelth.jpg differ diff --git a/img/sm_old/zerrikania_myrgot.jpg b/img/sm_old/zerrikania_myrgot.jpg new file mode 100644 index 0000000..b62f541 Binary files /dev/null and b/img/sm_old/zerrikania_myrgot.jpg differ diff --git a/img/sm_old/zerrikania_myrgtabrakke.jpg b/img/sm_old/zerrikania_myrgtabrakke.jpg new file mode 100644 index 0000000..c70efe3 Binary files /dev/null and b/img/sm_old/zerrikania_myrgtabrakke.jpg differ diff --git a/img/sm_old/zerrikania_ocvist.jpg b/img/sm_old/zerrikania_ocvist.jpg new file mode 100644 index 0000000..c90d3d5 Binary files /dev/null and b/img/sm_old/zerrikania_ocvist.jpg differ diff --git a/img/sm_old/zerrikania_ostreverg.jpg b/img/sm_old/zerrikania_ostreverg.jpg new file mode 100644 index 0000000..c0d8ca0 Binary files /dev/null and b/img/sm_old/zerrikania_ostreverg.jpg differ diff --git a/img/sm_old/zerrikania_python.jpg b/img/sm_old/zerrikania_python.jpg new file mode 100644 index 0000000..a3fb499 Binary files /dev/null and b/img/sm_old/zerrikania_python.jpg differ diff --git a/img/sm_old/zerrikania_rainforest_pathfinder.jpg b/img/sm_old/zerrikania_rainforest_pathfinder.jpg new file mode 100644 index 0000000..cfb62a9 Binary files /dev/null and b/img/sm_old/zerrikania_rainforest_pathfinder.jpg differ diff --git a/img/sm_old/zerrikania_rarog.jpg b/img/sm_old/zerrikania_rarog.jpg new file mode 100644 index 0000000..9ccdae3 Binary files /dev/null and b/img/sm_old/zerrikania_rarog.jpg differ diff --git a/img/sm_old/zerrikania_sandworm.jpg b/img/sm_old/zerrikania_sandworm.jpg new file mode 100644 index 0000000..75e4726 Binary files /dev/null and b/img/sm_old/zerrikania_sandworm.jpg differ diff --git a/img/sm_old/zerrikania_saulrenith.jpg b/img/sm_old/zerrikania_saulrenith.jpg new file mode 100644 index 0000000..91e9d35 Binary files /dev/null and b/img/sm_old/zerrikania_saulrenith.jpg differ diff --git a/img/sm_old/zerrikania_skuda_amazon_1.jpg b/img/sm_old/zerrikania_skuda_amazon_1.jpg new file mode 100644 index 0000000..6492aa9 Binary files /dev/null and b/img/sm_old/zerrikania_skuda_amazon_1.jpg differ diff --git a/img/sm_old/zerrikania_skuda_amazon_2.jpg b/img/sm_old/zerrikania_skuda_amazon_2.jpg new file mode 100644 index 0000000..b0a0eae Binary files /dev/null and b/img/sm_old/zerrikania_skuda_amazon_2.jpg differ diff --git a/img/sm_old/zerrikania_steppes_nomad_1.jpg b/img/sm_old/zerrikania_steppes_nomad_1.jpg new file mode 100644 index 0000000..ed4365d Binary files /dev/null and b/img/sm_old/zerrikania_steppes_nomad_1.jpg differ diff --git a/img/sm_old/zerrikania_steppes_nomad_2.jpg b/img/sm_old/zerrikania_steppes_nomad_2.jpg new file mode 100644 index 0000000..5ac7e13 Binary files /dev/null and b/img/sm_old/zerrikania_steppes_nomad_2.jpg differ diff --git a/img/sm_old/zerrikania_tea_vea_1.jpg b/img/sm_old/zerrikania_tea_vea_1.jpg new file mode 100644 index 0000000..75105ee Binary files /dev/null and b/img/sm_old/zerrikania_tea_vea_1.jpg differ diff --git a/img/sm_old/zerrikania_tea_vea_2.jpg b/img/sm_old/zerrikania_tea_vea_2.jpg new file mode 100644 index 0000000..c297231 Binary files /dev/null and b/img/sm_old/zerrikania_tea_vea_2.jpg differ diff --git a/img/sm_old/zerrikania_tiger_1.jpg b/img/sm_old/zerrikania_tiger_1.jpg new file mode 100644 index 0000000..a21a706 Binary files /dev/null and b/img/sm_old/zerrikania_tiger_1.jpg differ diff --git a/img/sm_old/zerrikania_tiger_2.jpg b/img/sm_old/zerrikania_tiger_2.jpg new file mode 100644 index 0000000..5fad257 Binary files /dev/null and b/img/sm_old/zerrikania_tiger_2.jpg differ diff --git a/img/sm_old/zerrikania_venomous_basilisk.jpg b/img/sm_old/zerrikania_venomous_basilisk.jpg new file mode 100644 index 0000000..a9045c8 Binary files /dev/null and b/img/sm_old/zerrikania_venomous_basilisk.jpg differ diff --git a/img/sm_old/zerrikania_villentretenmerth.jpg b/img/sm_old/zerrikania_villentretenmerth.jpg new file mode 100644 index 0000000..0edc11a Binary files /dev/null and b/img/sm_old/zerrikania_villentretenmerth.jpg differ diff --git a/img/sm_old/zerrikania_viper.jpg b/img/sm_old/zerrikania_viper.jpg new file mode 100644 index 0000000..c0fe2ae Binary files /dev/null and b/img/sm_old/zerrikania_viper.jpg differ diff --git a/img/sm_old/zerrikania_war_elephant.jpg b/img/sm_old/zerrikania_war_elephant.jpg new file mode 100644 index 0000000..fe7092c Binary files /dev/null and b/img/sm_old/zerrikania_war_elephant.jpg differ diff --git a/img/sm_old/zerrikania_yellow_witch_korath.jpg b/img/sm_old/zerrikania_yellow_witch_korath.jpg new file mode 100644 index 0000000..5b17c89 Binary files /dev/null and b/img/sm_old/zerrikania_yellow_witch_korath.jpg differ diff --git a/img/sm_old/zerrikania_zerrikanterment.jpg b/img/sm_old/zerrikania_zerrikanterment.jpg new file mode 100644 index 0000000..2762fd5 Binary files /dev/null and b/img/sm_old/zerrikania_zerrikanterment.jpg differ diff --git a/img/start.jpg b/img/start.jpg new file mode 100644 index 0000000..cb43946 Binary files /dev/null and b/img/start.jpg differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..d739ffc --- /dev/null +++ b/index.html @@ -0,0 +1,297 @@ + + + + Gwent 4.0 + + + + + + + + +

+
+
+ UP FOR +
+ A FEW ROUNDS +
+ OF GWENT? +

+ Loading... + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
0
+
+
+
+
+
+
+
Opponent
+
+
6
+
+
+
+
0
+
+
Passed
+
+
+
+
Board arrangement enabled
+
Moves left:
+
4
+
+
+
+
+
0
+
+
+
+
+
+
+
Passed
+
5
+
+
+
+
+
+
0
+
+
+
+
+
+
+
+
+
Pass
+
+
+
+
+
0
+
+
+
+
+
+
0
+
+
+
+
+
+
0
+
+
+
+
+
+
+
+
0
+
+
+
+
+
+
0
+
+
+
+
+
+
0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+

+
+
+ +
+
+
Reorder cards in deck
+
+
Bank
+
+
+
Deck top
+
+
+
Deck bottom
+
+
+
+ +
+
+

+

+
+ + +
+
+
+
+
+
+
+
+ This is a test message. + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Round 1Round 2Round 3
You000
Opponent000
+

The battle cannot end in a draw. You can play a rematch using the same decks or surrender.

+ + +
+
+
+
+ + + + + + + + + diff --git a/pure.min.css b/pure.min.css new file mode 100644 index 0000000..e0cc408 --- /dev/null +++ b/pure.min.css @@ -0,0 +1,11 @@ +/*! +Pure v2.1.0 +Copyright 2013 Yahoo! +Licensed under the BSD License. +https://github.com/pure-css/pure/blob/master/LICENSE +*/ +/*! +normalize.css v | MIT License | git.io/normalize +Copyright (c) Nicolas Gallagher and Jonathan Neal +*/ +/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}html{font-family:sans-serif}.hidden,[hidden]{display:none!important}.pure-img{max-width:100%;height:auto;display:block}.pure-g{letter-spacing:-.31em;text-rendering:optimizespeed;font-family:FreeSans,Arimo,"Droid Sans",Helvetica,Arial,sans-serif;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-line-pack:start;align-content:flex-start}@media all and (-ms-high-contrast:none),(-ms-high-contrast:active){table .pure-g{display:block}}.opera-only :-o-prefocus,.pure-g{word-spacing:-0.43em}.pure-u{display:inline-block;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-g [class*=pure-u]{font-family:sans-serif}.pure-u-1,.pure-u-1-1,.pure-u-1-12,.pure-u-1-2,.pure-u-1-24,.pure-u-1-3,.pure-u-1-4,.pure-u-1-5,.pure-u-1-6,.pure-u-1-8,.pure-u-10-24,.pure-u-11-12,.pure-u-11-24,.pure-u-12-24,.pure-u-13-24,.pure-u-14-24,.pure-u-15-24,.pure-u-16-24,.pure-u-17-24,.pure-u-18-24,.pure-u-19-24,.pure-u-2-24,.pure-u-2-3,.pure-u-2-5,.pure-u-20-24,.pure-u-21-24,.pure-u-22-24,.pure-u-23-24,.pure-u-24-24,.pure-u-3-24,.pure-u-3-4,.pure-u-3-5,.pure-u-3-8,.pure-u-4-24,.pure-u-4-5,.pure-u-5-12,.pure-u-5-24,.pure-u-5-5,.pure-u-5-6,.pure-u-5-8,.pure-u-6-24,.pure-u-7-12,.pure-u-7-24,.pure-u-7-8,.pure-u-8-24,.pure-u-9-24{display:inline-block;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-u-1-24{width:4.1667%}.pure-u-1-12,.pure-u-2-24{width:8.3333%}.pure-u-1-8,.pure-u-3-24{width:12.5%}.pure-u-1-6,.pure-u-4-24{width:16.6667%}.pure-u-1-5{width:20%}.pure-u-5-24{width:20.8333%}.pure-u-1-4,.pure-u-6-24{width:25%}.pure-u-7-24{width:29.1667%}.pure-u-1-3,.pure-u-8-24{width:33.3333%}.pure-u-3-8,.pure-u-9-24{width:37.5%}.pure-u-2-5{width:40%}.pure-u-10-24,.pure-u-5-12{width:41.6667%}.pure-u-11-24{width:45.8333%}.pure-u-1-2,.pure-u-12-24{width:50%}.pure-u-13-24{width:54.1667%}.pure-u-14-24,.pure-u-7-12{width:58.3333%}.pure-u-3-5{width:60%}.pure-u-15-24,.pure-u-5-8{width:62.5%}.pure-u-16-24,.pure-u-2-3{width:66.6667%}.pure-u-17-24{width:70.8333%}.pure-u-18-24,.pure-u-3-4{width:75%}.pure-u-19-24{width:79.1667%}.pure-u-4-5{width:80%}.pure-u-20-24,.pure-u-5-6{width:83.3333%}.pure-u-21-24,.pure-u-7-8{width:87.5%}.pure-u-11-12,.pure-u-22-24{width:91.6667%}.pure-u-23-24{width:95.8333%}.pure-u-1,.pure-u-1-1,.pure-u-24-24,.pure-u-5-5{width:100%}.pure-button{display:inline-block;line-height:normal;white-space:nowrap;vertical-align:middle;text-align:center;cursor:pointer;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-box-sizing:border-box;box-sizing:border-box}.pure-button::-moz-focus-inner{padding:0;border:0}.pure-button-group{letter-spacing:-.31em;text-rendering:optimizespeed}.opera-only :-o-prefocus,.pure-button-group{word-spacing:-0.43em}.pure-button-group .pure-button{letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-button{font-family:inherit;font-size:100%;padding:.5em 1em;color:rgba(0,0,0,.8);border:none transparent;background-color:#e6e6e6;text-decoration:none;border-radius:2px}.pure-button-hover,.pure-button:focus,.pure-button:hover{background-image:-webkit-gradient(linear,left top,left bottom,from(transparent),color-stop(40%,rgba(0,0,0,.05)),to(rgba(0,0,0,.1)));background-image:linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.1))}.pure-button:focus{outline:0}.pure-button-active,.pure-button:active{-webkit-box-shadow:0 0 0 1px rgba(0,0,0,.15) inset,0 0 6px rgba(0,0,0,.2) inset;box-shadow:0 0 0 1px rgba(0,0,0,.15) inset,0 0 6px rgba(0,0,0,.2) inset;border-color:#000}.pure-button-disabled,.pure-button-disabled:active,.pure-button-disabled:focus,.pure-button-disabled:hover,.pure-button[disabled]{border:none;background-image:none;opacity:.4;cursor:not-allowed;-webkit-box-shadow:none;box-shadow:none;pointer-events:none}.pure-button-hidden{display:none}.pure-button-primary,.pure-button-selected,a.pure-button-primary,a.pure-button-selected{background-color:#0078e7;color:#fff}.pure-button-group .pure-button{margin:0;border-radius:0;border-right:1px solid rgba(0,0,0,.2)}.pure-button-group .pure-button:first-child{border-top-left-radius:2px;border-bottom-left-radius:2px}.pure-button-group .pure-button:last-child{border-top-right-radius:2px;border-bottom-right-radius:2px;border-right:none}.pure-form input[type=color],.pure-form input[type=date],.pure-form input[type=datetime-local],.pure-form input[type=datetime],.pure-form input[type=email],.pure-form input[type=month],.pure-form input[type=number],.pure-form input[type=password],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=text],.pure-form input[type=time],.pure-form input[type=url],.pure-form input[type=week],.pure-form select,.pure-form textarea{padding:.5em .6em;display:inline-block;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 3px #ddd;box-shadow:inset 0 1px 3px #ddd;border-radius:4px;vertical-align:middle;-webkit-box-sizing:border-box;box-sizing:border-box}.pure-form input:not([type]){padding:.5em .6em;display:inline-block;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 3px #ddd;box-shadow:inset 0 1px 3px #ddd;border-radius:4px;-webkit-box-sizing:border-box;box-sizing:border-box}.pure-form input[type=color]{padding:.2em .5em}.pure-form input[type=color]:focus,.pure-form input[type=date]:focus,.pure-form input[type=datetime-local]:focus,.pure-form input[type=datetime]:focus,.pure-form input[type=email]:focus,.pure-form input[type=month]:focus,.pure-form input[type=number]:focus,.pure-form input[type=password]:focus,.pure-form input[type=search]:focus,.pure-form input[type=tel]:focus,.pure-form input[type=text]:focus,.pure-form input[type=time]:focus,.pure-form input[type=url]:focus,.pure-form input[type=week]:focus,.pure-form select:focus,.pure-form textarea:focus{outline:0;border-color:#129fea}.pure-form input:not([type]):focus{outline:0;border-color:#129fea}.pure-form input[type=checkbox]:focus,.pure-form input[type=file]:focus,.pure-form input[type=radio]:focus{outline:thin solid #129FEA;outline:1px auto #129FEA}.pure-form .pure-checkbox,.pure-form .pure-radio{margin:.5em 0;display:block}.pure-form input[type=color][disabled],.pure-form input[type=date][disabled],.pure-form input[type=datetime-local][disabled],.pure-form input[type=datetime][disabled],.pure-form input[type=email][disabled],.pure-form input[type=month][disabled],.pure-form input[type=number][disabled],.pure-form input[type=password][disabled],.pure-form input[type=search][disabled],.pure-form input[type=tel][disabled],.pure-form input[type=text][disabled],.pure-form input[type=time][disabled],.pure-form input[type=url][disabled],.pure-form input[type=week][disabled],.pure-form select[disabled],.pure-form textarea[disabled]{cursor:not-allowed;background-color:#eaeded;color:#cad2d3}.pure-form input:not([type])[disabled]{cursor:not-allowed;background-color:#eaeded;color:#cad2d3}.pure-form input[readonly],.pure-form select[readonly],.pure-form textarea[readonly]{background-color:#eee;color:#777;border-color:#ccc}.pure-form input:focus:invalid,.pure-form select:focus:invalid,.pure-form textarea:focus:invalid{color:#b94a48;border-color:#e9322d}.pure-form input[type=checkbox]:focus:invalid:focus,.pure-form input[type=file]:focus:invalid:focus,.pure-form input[type=radio]:focus:invalid:focus{outline-color:#e9322d}.pure-form select{height:2.25em;border:1px solid #ccc;background-color:#fff}.pure-form select[multiple]{height:auto}.pure-form label{margin:.5em 0 .2em}.pure-form fieldset{margin:0;padding:.35em 0 .75em;border:0}.pure-form legend{display:block;width:100%;padding:.3em 0;margin-bottom:.3em;color:#333;border-bottom:1px solid #e5e5e5}.pure-form-stacked input[type=color],.pure-form-stacked input[type=date],.pure-form-stacked input[type=datetime-local],.pure-form-stacked input[type=datetime],.pure-form-stacked input[type=email],.pure-form-stacked input[type=file],.pure-form-stacked input[type=month],.pure-form-stacked input[type=number],.pure-form-stacked input[type=password],.pure-form-stacked input[type=search],.pure-form-stacked input[type=tel],.pure-form-stacked input[type=text],.pure-form-stacked input[type=time],.pure-form-stacked input[type=url],.pure-form-stacked input[type=week],.pure-form-stacked label,.pure-form-stacked select,.pure-form-stacked textarea{display:block;margin:.25em 0}.pure-form-stacked input:not([type]){display:block;margin:.25em 0}.pure-form-aligned input,.pure-form-aligned select,.pure-form-aligned textarea,.pure-form-message-inline{display:inline-block;vertical-align:middle}.pure-form-aligned textarea{vertical-align:top}.pure-form-aligned .pure-control-group{margin-bottom:.5em}.pure-form-aligned .pure-control-group label{text-align:right;display:inline-block;vertical-align:middle;width:10em;margin:0 1em 0 0}.pure-form-aligned .pure-controls{margin:1.5em 0 0 11em}.pure-form .pure-input-rounded,.pure-form input.pure-input-rounded{border-radius:2em;padding:.5em 1em}.pure-form .pure-group fieldset{margin-bottom:10px}.pure-form .pure-group input,.pure-form .pure-group textarea{display:block;padding:10px;margin:0 0 -1px;border-radius:0;position:relative;top:-1px}.pure-form .pure-group input:focus,.pure-form .pure-group textarea:focus{z-index:3}.pure-form .pure-group input:first-child,.pure-form .pure-group textarea:first-child{top:1px;border-radius:4px 4px 0 0;margin:0}.pure-form .pure-group input:first-child:last-child,.pure-form .pure-group textarea:first-child:last-child{top:1px;border-radius:4px;margin:0}.pure-form .pure-group input:last-child,.pure-form .pure-group textarea:last-child{top:-2px;border-radius:0 0 4px 4px;margin:0}.pure-form .pure-group button{margin:.35em 0}.pure-form .pure-input-1{width:100%}.pure-form .pure-input-3-4{width:75%}.pure-form .pure-input-2-3{width:66%}.pure-form .pure-input-1-2{width:50%}.pure-form .pure-input-1-3{width:33%}.pure-form .pure-input-1-4{width:25%}.pure-form-message-inline{display:inline-block;padding-left:.3em;color:#666;vertical-align:middle;font-size:.875em}.pure-form-message{display:block;color:#666;font-size:.875em}@media only screen and (max-width :480px){.pure-form button[type=submit]{margin:.7em 0 0}.pure-form input:not([type]),.pure-form input[type=color],.pure-form input[type=date],.pure-form input[type=datetime-local],.pure-form input[type=datetime],.pure-form input[type=email],.pure-form input[type=month],.pure-form input[type=number],.pure-form input[type=password],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=text],.pure-form input[type=time],.pure-form input[type=url],.pure-form input[type=week],.pure-form label{margin-bottom:.3em;display:block}.pure-group input:not([type]),.pure-group input[type=color],.pure-group input[type=date],.pure-group input[type=datetime-local],.pure-group input[type=datetime],.pure-group input[type=email],.pure-group input[type=month],.pure-group input[type=number],.pure-group input[type=password],.pure-group input[type=search],.pure-group input[type=tel],.pure-group input[type=text],.pure-group input[type=time],.pure-group input[type=url],.pure-group input[type=week]{margin-bottom:0}.pure-form-aligned .pure-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.pure-form-aligned .pure-controls{margin:1.5em 0 0 0}.pure-form-message,.pure-form-message-inline{display:block;font-size:.75em;padding:.2em 0 .8em}}.pure-menu{-webkit-box-sizing:border-box;box-sizing:border-box}.pure-menu-fixed{position:fixed;left:0;top:0;z-index:3}.pure-menu-item,.pure-menu-list{position:relative}.pure-menu-list{list-style:none;margin:0;padding:0}.pure-menu-item{padding:0;margin:0;height:100%}.pure-menu-heading,.pure-menu-link{display:block;text-decoration:none;white-space:nowrap}.pure-menu-horizontal{width:100%;white-space:nowrap}.pure-menu-horizontal .pure-menu-list{display:inline-block}.pure-menu-horizontal .pure-menu-heading,.pure-menu-horizontal .pure-menu-item,.pure-menu-horizontal .pure-menu-separator{display:inline-block;vertical-align:middle}.pure-menu-item .pure-menu-item{display:block}.pure-menu-children{display:none;position:absolute;left:100%;top:0;margin:0;padding:0;z-index:3}.pure-menu-horizontal .pure-menu-children{left:0;top:auto;width:inherit}.pure-menu-active>.pure-menu-children,.pure-menu-allow-hover:hover>.pure-menu-children{display:block;position:absolute}.pure-menu-has-children>.pure-menu-link:after{padding-left:.5em;content:"\25B8";font-size:small}.pure-menu-horizontal .pure-menu-has-children>.pure-menu-link:after{content:"\25BE"}.pure-menu-scrollable{overflow-y:scroll;overflow-x:hidden}.pure-menu-scrollable .pure-menu-list{display:block}.pure-menu-horizontal.pure-menu-scrollable .pure-menu-list{display:inline-block}.pure-menu-horizontal.pure-menu-scrollable{white-space:nowrap;overflow-y:hidden;overflow-x:auto;padding:.5em 0}.pure-menu-horizontal .pure-menu-children .pure-menu-separator,.pure-menu-separator{background-color:#ccc;height:1px;margin:.3em 0}.pure-menu-horizontal .pure-menu-separator{width:1px;height:1.3em;margin:0 .3em}.pure-menu-horizontal .pure-menu-children .pure-menu-separator{display:block;width:auto}.pure-menu-heading{text-transform:uppercase;color:#565d64}.pure-menu-link{color:#777}.pure-menu-children{background-color:#fff}.pure-menu-heading,.pure-menu-link{padding:.5em 1em}.pure-menu-disabled{opacity:.5}.pure-menu-disabled .pure-menu-link:hover{background-color:transparent;cursor:default}.pure-menu-active>.pure-menu-link,.pure-menu-link:focus,.pure-menu-link:hover{background-color:#eee}.pure-menu-selected>.pure-menu-link,.pure-menu-selected>.pure-menu-link:visited{color:#000}.pure-table{border-collapse:collapse;border-spacing:0;empty-cells:show;border:1px solid #cbcbcb}.pure-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.pure-table td,.pure-table th{border-left:1px solid #cbcbcb;border-width:0 0 0 1px;font-size:inherit;margin:0;overflow:visible;padding:.5em 1em}.pure-table thead{background-color:#e0e0e0;color:#000;text-align:left;vertical-align:bottom}.pure-table td{background-color:transparent}.pure-table-odd td{background-color:#f2f2f2}.pure-table-striped tr:nth-child(2n-1) td{background-color:#f2f2f2}.pure-table-bordered td{border-bottom:1px solid #cbcbcb}.pure-table-bordered tbody>tr:last-child>td{border-bottom-width:0}.pure-table-horizontal td,.pure-table-horizontal th{border-width:0 0 1px 0;border-bottom:1px solid #cbcbcb}.pure-table-horizontal tbody>tr:last-child>td{border-bottom-width:0} \ No newline at end of file diff --git a/rules.css b/rules.css new file mode 100644 index 0000000..0434df3 --- /dev/null +++ b/rules.css @@ -0,0 +1,380 @@ +body { + color: #555; + background-color: #ccc; +} + +.pure-img-responsive { + max-width: 100%; + height: auto; +} + +#main p { + margin-left: 10px; +} + +/* +Add transition to containers so they can push in and out. +*/ +#layout, +#menu, +.menu-link { + -webkit-transition: all 0.2s ease-out; + -moz-transition: all 0.2s ease-out; + -ms-transition: all 0.2s ease-out; + -o-transition: all 0.2s ease-out; + transition: all 0.2s ease-out; +} + +/* +This is the parent `
` that contains the menu and the content area. +*/ +#layout { + position: relative; + left: 0; + padding-left: 0; +} + +#layout.active #menu { + left: 150px; + width: 150px; +} + +#layout.active .menu-link { + left: 150px; +} +/* +The content `
` is where all your content goes. +*/ +.content { + margin: 0 auto; + padding: 0 2em; + max-width: 800px; + margin-bottom: 50px; + line-height: 1.6em; +} + +.header { + margin: 0; + color: #333; + text-align: center; + padding: 2.5em 2em 0; + border-bottom: 1px solid #444; + background-color: #bbb; +} + +.header h1 { + margin: 0.2em 0; + font-size: 3em; + font-weight: 300; +} + +.header h2 { + font-weight: 300; + color: #444; + padding: 0; + margin-top: 0; +} + +.content-subhead { + margin: 50px 0 20px 0; + font-weight: 300; + color: #666; +} + +.content h2 { + font-size: 2.5em; +} + +.content h3 { + font-size: 1.8em; +} + +.content h4 { + font-size: 1.5em; +} + + + +/* +The `#menu` `
` is the parent `
` that contains the `.pure-menu` that +appears on the left side of the page. +*/ + +#menu { + margin-left: -150px; /* "#menu" width */ + width: 150px; + position: fixed; + top: 0; + left: 0; + bottom: 0; + z-index: 1000; /* so the menu or its navicon stays above all content */ + background: #191818; + overflow-y: auto; +} +/* +All anchors inside the menu should be styled like this. +*/ +#menu a { + color: #999; + border: none; + padding: 0.6em 0 0.6em 0.6em; +} + +/* +Remove all background/borders, since we are applying them to #menu. +*/ +#menu .pure-menu, +#menu .pure-menu ul { + border: none; + background: transparent; +} + +/* +Add that light border to separate items into groups. +*/ +#menu .pure-menu ul, +#menu .pure-menu .menu-item-divided { + border-top: 1px solid #333; +} +/* +Change color of the anchor links on hover/focus. +*/ +#menu .pure-menu li a:hover, +#menu .pure-menu li a:focus { + background: #333; +} + +/* +This styles the selected menu item `
  • `. +*/ +#menu .pure-menu-selected, +#menu .pure-menu-heading { + background: #5a2323; +} +/* +This styles a link within a selected menu item `
  • `. +*/ +#menu .pure-menu-selected a { + color: #fff; +} + +/* +This styles the menu heading. +*/ +#menu .pure-menu-heading { + font-size: 110%; + color: #fff; + margin: 0; +} + +/* -- Dynamic Button For Responsive Menu -------------------------------------*/ + +/* +The button to open/close the Menu is custom-made and not part of Pure. Here's +how it works: +*/ + +/* +`.menu-link` represents the responsive menu toggle that shows/hides on +small screens. +*/ +.menu-link { + position: fixed; + display: block; /* show this only on small screens */ + top: 0; + left: 0; /* "#menu width" */ + background: #000; + background: rgba(0,0,0,0.7); + font-size: 10px; /* change this value to increase/decrease button size */ + z-index: 10; + width: 2em; + height: auto; + padding: 2.1em 1.6em; +} + +.menu-link:hover, +.menu-link:focus { + background: #000; +} + +.menu-link span { + position: relative; + display: block; +} + +.menu-link span, +.menu-link span:before, +.menu-link span:after { + background-color: #fff; + pointer-events: none; + width: 100%; + height: 0.2em; +} + +.menu-link span:before, +.menu-link span:after { + position: absolute; + margin-top: -0.6em; + content: " "; +} + +.menu-link span:after { + margin-top: 0.6em; +} + +.menu-other-page { + background-color: #553c2e; +} + + +/* -- Responsive Styles (Media Queries) ------------------------------------- */ + +/* +Hides the menu at `48em`, but modify this based on your app's needs. +*/ +@media (min-width: 48em) { + + .header, + .content { + padding-left: 2em; + padding-right: 2em; + } + + #layout { + padding-left: 150px; /* left col width "#menu" */ + left: 0; + } + + #menu { + left: 150px; + } + + .menu-link { + position: fixed; + left: 150px; + display: none; + } + + #layout.active .menu-link { + left: 150px; + } +} + +@media (max-width: 48em) { + /* Only apply this when the window is small. Otherwise, the following + case results in extra padding on the left: + * Make the window small. + * Tap the menu to trigger the active state. + * Make the window large again. + */ + #layout.active { + position: relative; + left: 150px; + } +} + +/* + Factions list +*/ + +.faction-list-name { + font-weight: bold; + font-size: 24px; + margin-left: 20px; +} + +.faction-list-description { + margin-left: 30px; +} + +/* + Abilities list +*/ + +.ability-list-name { + font-weight: bold; + font-size: 24px; + margin-left: 20px; +} + +.ability-list-description { + margin-left: 30px; +} + +/* + Decks list +*/ + +.deck-list-name { + font-weight: bold; + font-size: 24px; + margin-left: 20px; +} + +.deck-list-description { + margin-left: 30px; +} + +.faction-realms { + background-color: #1b205c; + color: #fff; + padding: 5px; +} + +.faction-nilfgaard { + background-color: #111; + color: #c68a10; + padding: 5px; +} + +.faction-monsters { + background-color: #421616; + color: #fff; + padding: 5px; +} + +.faction-scoiatael { + background-color: #214f11; + color: #fff; + padding: 5px; +} + +.faction-skellige { + background-color: #3b1b57; + color: #fff; + padding: 5px; +} + +.faction-witcher_universe { + background-color: #2e4b87; + color: #fff; + padding: 5px; +} + +.faction-toussaint { + background-color: #d5a710; + color: #000; + padding: 5px; +} + +.faction-lyria_rivia { + background-color: #15b08f; + color: #000; + padding: 5px; +} + +.faction-syndicate { + background-color: #ac600d; + color: #000; + padding: 5px; +} + +.faction-zerrikania { + background-color: #6e9646; + color: #000; + padding: 5px; +} + +.card-preview { + border-radius: 0.5vw; +} \ No newline at end of file diff --git a/rules.html b/rules.html new file mode 100644 index 0000000..ee42a8c --- /dev/null +++ b/rules.html @@ -0,0 +1,998 @@ + + + + Gwent 4.0 + + + + + + + + + +
    + + + + + + + + +
    +
    +

    Gwent 4.0

    +

    The Witcher 3 minigame pulled to the browser and pushed further

    +
    + +
    + +

    What is Gwent?

    +

    + Gwent (a.k.a Gwynt) used to be a minigame in the video game The Witcher 3 developed by CD Project. + It was designed to be a collection card game in which you could play your cards against the computer. + You would start with a basic starting deck which you could improve in parallel of the game story and quests by buying more cards here and there or by defeating characters in the game. +

    + +

    + It was never designed to be a balanced game. NPCs don't complain, so the idea was to build a deck with all the strongest cards possible to try to always win. + Adapting Gwent to be multiplayer is consequently not an easy task. Furthermore, the game could grow boring because there are obvious optimal decks and optimal ways to play the game. + Players would usually do the same things over and over. + Fortunately, it does not stop the game from being very interesting and full of potential, which is why we wanted to push it even further, especially with a vast universe like The Witcher. +

    + +

    But how does it play?

    +

    + Gwent is played with 2 players. They start with the same number of cards and take turns to play these cards one by one until both players pass or are out of cards. + At the end of each round the strength of each player's cards is summed to calculate their score. The player with the highest score wins the round. + First player to win two rounds wins the game. +

    + +

    + Gwent is sometimes compared to poker because bluff plays an important role. + Usually you want to win a round with as few cards as possible but since each player can lose a round, you might want to convince your opponent you are trying to win the round and push him/her to play more of his/her best cards, while saving yours. + Cards are a limited resource in the game, so winning requires to make a better use of them. +

    + +

    Board layout

    + +
    +
    Gwent board layout
    +
    +

    + In Gwent, the board is a battlefied divided in two parts, the side of each player. + Each side is made of three distinct rows: + +

      +
    • Melee (or Close Combat)
    • +
    • Ranged
    • +
    • Siege
    • +
    +

    +

    + Most cards can be played in only one of these rows. Some special cards can affect only one row at a time. + Concentrating cards in a row or on the contrary spreading them across your side of the battlefield will be important strategic decisions. +

    +

    + This division of the board in three rows and the effects which can apply to them are an important factor in the specificity and elegance of Gwent. + For many players, this is a crucial part missing in the more recent standalone official Gwent game. +

    +
    +
    + +

    So, what are these cards?

    + +

    + In Gwent, there are 3 major kinds of cards: + +

      +
    • Leader cards
    • +
    • Unit cards
    • +
    • Special cards
    • +
    +

    + +

    Leader cards

    + +
    +
    Example of leader card
    +
    +

    + Each player has one and only one leader card, which is chosen before the start of the game. It is not part of the deck. + This card is not played on the battlefield, it remains face up on the side until the end. + It does not have a strength value but it has a strong ability which can affect the board and cards. +

    +
    +
    + + + +

    Unit cards

    + +
    +
    + Example of unit card + Example of hero card +
    +
    +

    + This is the main category of cards, these are the ones with a strength value and which allow to increase the player's score in the round. + Some units have an ability (some even have two), allowing them to affect the board or combine with other cards in order to further increase (or decrease) the scores of players. + These abilities allow to increase the strength of some of your units, summon more cards or remove some other cards from the boad. + Unit abilities is most likely the most important part of the game because it is what brings variety and unpredictability, forcing players to read the opponent strategy and style and react to it approprietly. +

    +

    + A small portion of these units are Hero units, their visual is slightly different than the others. Hero units are not affected by any ability, yours or the opponents. + This means that these cards cannot be removed before the end of the round and their strength cannot be changed. Exceptions to this rule are very very rare. +

    +

    + Unit cards can usually be played in only one of the three rows, which is indicated on the card. Some can be placed in one of two rows. +

    +
    +
    + +

    Special cards

    + +
    +
    + Example of special card + Example of weather card +
    +
    +

    + Special cards have no strength but have a powerfull ability which can have a significant effect on the board. They usually either affect a specific or the entire board. +

    +

    + Some special cards have a direct effect and are discarded right after use. + Some provide a durable effect on a row until the end of the round or before another ability removes it. These cards are not played on the battlefield but in a dedicated slot on its side. +

    +

    + A category of these special cards is worth a specific mention, they are called Weather Cards. + These cards apply a malus in a specific row but for both players at the same time (all unit cards strength is lowered to 1). + They are a powerfull tool which can change the course of a game. Fortunately, there is one special cards allowing to cancel these weather effects, when you have one in your, that is. +

    +

    + These cards play an important role in the strategy of Gwent and in its elegance. They are simple but deadly, it is crucial to anticipate the possibility of the opponent playing them. +

    +
    +
    + +

    How to read the cards

    + +
    +
    + Gwent card legend + Gwent special card legend +
    +
    +

    +

      +
    • 1: Strength of the cards to contributes to the player score. What initially on the card is considered the "base strength", since the strength of unit cards can be increased/decreased by other cards. Special cards will have their ability indicated here, instead of the strength.
    • +
    • 2: Card's row. This icon indicate to which row(s) the card can be placed. Sword means Melee row, Bow means Ranged row and Catapult means Siege row. In some cases, the icon while contain 2 elements, indicating that the card can be placed in several rows, at choice.
    • +
    • 3: Card's ability, when the card has one. Sometimes a card will have two abilities, the second will similarly be placed bellow this position. Abilities will be explained elsewhere.
    • +
    • 4: The icon and the coloured ribbon are an indication of the faction the card is part of. Factions will be explained later. If there is no such icon/ribbon, this means the card is neutral and compatible with all factions.
    • +
    • 5: Name of the card. Most cards also have a custom quote bellow the name, which relates to the character/unit/effect.
    • +
    +

    +
    +
    + + +

    Abilities

    + +

    + This card game revolves a lot around a set of abilities, they allow to develop strategies and adapt/react to the opponent's. + The beauty of Gwent is that the number of abilities remains rather low and easy to grasp. + Unlike the official modern Gwent game where each card has a unique effect, the original Gwent has multiple cards having the same ability. + Consequently, it is much easier to understand what a card does (a quick look at the card is usually enough) and what a deck can do. +

    + +

    Abilities available

    + +

    Original game

    + + +
    +
    + Scorch unit ability + Scorch special ability +
    +
    +
    Scorch
    +
    +

    + This ability is quite simple, it destroys (removes from the board and sends to the graveyard/discard pile) all the unit cards (not heroes) having the highest strength. + It affects the entire board, for both players, so it means you can destroy your own cards. +

    +

    + It is best used when the opponent has several units with the same value (and no other units on the board is stronger) or when a single unit represents a big part of the total strength of the player. +

    +

    + Note that when using this ability from a card, the card is excluded from the effect, it cannot destroy itself and it doesn't count in what the strongest units are. +

    +
    +
    +
    + +
    +
    + Scorch combat unit ability +
    +
    +
    Scorch Combat
    +
    +

    + This ability is a slight variation of Scorch. Instead of affecting the entire board for both players, it affects only one of the opponent row. + If the total strength present in that row is 10 or higher (heroes included), it destroys the strongest units of the row (but not heroes). +

    +

    + Originally, the target row of this effect was the opposite row the card is played in. + However, we have changed it to always target the Melee row to make this ability a little more usable/effective and predictable, because most factions have a lot more Melee units than the other rows. + Also, we believe that having this ability affect only the first enemy line seems more "realistic". +

    +
    +
    +
    + + +
    +
    + Muster ability +
    +
    +
    Muster
    +
    +

    + When a card with the Muster ability is played on the board, it summons as well all the other cards in your deck and hand with the same name. + In reality, they do not always have the same name but they share a common element which is easily distinguishable. +

    +

    + The power of this ability resides in the fact it can quickly add several cards to the board and increase your total score. + Its weakness is that the cards often have the same strength and can consequently be destroyed all at the same time if not played carefully. + Also, keep in mind that if you have several Muster cards of the same familly in hand, playing one of them will play all the copies in hand, putting you at a disadvantage. +

    +
    +
    +
    + + +
    +
    + Tight Bond ability +
    +
    +
    Tight Bond
    +
    +

    + In a way, the Tight Bond ability behaves similarly to the Muster ability. These cards are part of a "familly" and are stronger together. + For each card of the same familly (same or similar name) with the Tight Bond ability, the base strength of the card is multiplied by the number of copies in the same row. + So if you have managed to play 3 copies, each card will have its value tripled. All combined, the total will be 9 times higher than without the ability. +

    +

    + The power of this ability is that you can reach a very high strength on the row, so high that it will be very difficult for your opponent to match it (with 3 cards you have the strength of 9 cards). + However, this very strength is also its main weakness. Since these cards are copies, they share the same strength and tend to be the strongest cards on the board, easy target for Scorch. + Also, a single copy of such a card isn't very strong, the most important part is managing to gather several copies. +

    +
    +
    +
    + + +
    +
    + Morale Boost ability +
    +
    +
    Morale Boost
    +
    +

    + Now let's get into row boosting. Morale boost increases the base strength of all units of the row by 1, except on itself. It is obviously more effective if you have many units concentrated in the same row. +

    +
    +
    +
    + + +
    +
    + Commander' Horn unit ability + Commander' Horn special ability +
    +
    +
    Commander' Horn
    +
    +

    + A stronger boost now. Commander' Horn doubles the strength of all units (not heroes then) in the row. It applies last, so it combines well with other boosts. + Here as well, it is more effective in a row with many cards, but the number of cards isn't has important as for Morale Boost. A couple Tight Bond cards might have a larger boost potential than 5 weak cards. + While this ability hold a huge potential, it also makes yourself very vulnerable to Scorch. +

    +

    + When this ability is played through a unit, the unit does not boost itself. + Also, only one Commander' Horn can be effective at the same time in a row. If several cards in the row have it, it will aply only once. +

    +
    +
    +
    + + +
    +
    + Medic ability +
    +
    +
    Medic
    +
    +

    + When a card is removed from the board (destroyed or at the end of a round), it goes into the graveyard (aka discard pile). + The Medic ability allows to restore a unit card (not a hero) from the grave. + When a card is restored on the board, its abilities apply again. +

    +

    + This ability is very powerfull because it effectively gives you an additional card on the long term. It also allows you to use again some important abilities, which can be very decisive. + This card is like wine, it gets better with time. The later you play it, the more options of cards you have. If your graveyard is empty, this ability isn't very useful. + A medic can even restore another medic, allowing you to restore yet another card. +

    +
    +
    +
    + + +
    +
    + Spy ability +
    +
    +
    Spy
    +
    +

    + Probably the most infamous ability of the game. We said earlier that cards are the most important resource of the game and that's the aim of this ability, give a card advantage (meaning getting more cards than your opponen). + When this card is played, it goes in the side of your opponent and will contribute to increase his/her total score. + In return, you will draw two cards from your deck. The aftermath is that you gave a card to your opponent but you know have one more card in your card than before, and 2 more options to play later. +

    +

    + In addition to the card advantage this card gives you, having drawn more cards than initially possible gives you more options and more chances to get good combos. + Be careful though, once on the opponent side of the board, the spy is under his/control and it can be played back against you. +

    +
    +
    +
    + + +
    +
    + Decoy unit ability + Decoy special ability +
    +
    +
    Decoy
    +
    +

    + This ability is often summarized as the counter to spies. It allows to swap one unit on the board with this card (in other words, take the targert card back into your hand). +

    +

    + The Decoy ability has many advantages. Obviously, this is a great counter to spies, because you can restore the balance by playing the spy back and draw cards as well. + But it can also be used on other cards with important abilities, such as Scorch or Medic. + Also, keep in mind that effectively when you play a Decoy, it is almost like skipping a round because your hand size does not reduce, this is often underestimated. +

    +
    +
    +
    + + +
    +
    + Agile ability +
    +
    +
    Agile
    +
    +

    + This ability is rarely used and thus rarely has a visible effect after the card is played. + Basicaly, it goes in combination with cards which can be played on the Melee or Ranged row (which is the most useful part). + Under some limited circumpstances, agile cards can be moved later in the round to a more favourable row. +

    +
    +
    +
    + + +
    +
    + Summon Avenger ability +
    +
    +
    Summon Avenger
    +
    +

    + A bit like Medic, the Summon Avenger ability takes longer to show its effects. + When a card with this ability is removed from the board (either destroyed or at the end of the round), it is replaced by another more powerful card. + More often than not, this other card will enter battle at the begining of the next round. +

    +

    + Usually a unit with the Summon Avenger will be very weak. Playing it is like investing on the future because it will allow yourself to start the next round with an advantage (provided the card wasn't destroyed before the end of the round). + This ability combines very well with Medic. + Note that if the card that should be summoned is in your hand or deck, it will be taken from there. Otherwise, it will be "created" but it will not go into your graveyard when removed. +

    +
    +
    +
    + + +
    +
    + Berserker unit ability + Mardroeme special ability +
    +
    +
    Berserker / Mardroeme
    +
    +

    + These two abilities need to be presented together. They are specific to the Skellige faction. + Unit cards with the Berserker ability can be transformed into their more savage form when a card with the Mardroeme ability is played in their row. +

    +

    + Berserker units are initially not very strong, and thus not very interesting if not combined with Mardroeme. + However, their transformed versions are very strong but also very vulnerable to scorch. + Using this ability well isn't easy. +

    +
    +
    +
    + +

    Original game - Weather cards

    + +

    + Like mentioned earlier, Weather Cards are a more specific kind of special cards (and thus special amongst abilities). + Their effect is more global and will affect both players. In some rare cases, a unit card might have a weather ability, but these are exceptions. +

    + + +
    +
    + Biting Frost Weather +
    +
    +
    Biting Frost
    +
    +

    + Reduce the base strength of all units in the Melee row (not heroes) to 1, for both players. This applies before any other ability/effect. +

    +
    +
    +
    + + +
    +
    + Impenetrable Fog Weather +
    +
    +
    Impenetrable Fog
    +
    +

    + Reduce the base strength of all units in the Ranged row (not heroes) to 1, for both players. This applies before any other ability/effect. +

    +
    +
    +
    + + +
    +
    + Torrential Rain Weather +
    +
    +
    Torrential Rain
    +
    +

    + Reduce the base strength of all units in the Siege row (not heroes) to 1, for both players. This applies before any other ability/effect. +

    +
    +
    +
    + + +
    +
    + Skellige Storm Weather +
    +
    +
    Skellige Storm
    +
    +

    + Reduce the base strength of all units in both the Ranged and Siege rows (not heroes) to 1, for both players. This applies before any other ability/effect. +

    +
    +
    +
    + + +
    +
    + Clear Weather +
    +
    +
    Clear Weather
    +
    +

    + Remove all other weather effects currently effective on the board, this applies to all players. +

    +
    +
    +
    + +

    New custom abilities

    + +

    + To extend the game with more cards and factions, additional abilities have been added. Otherwise most decks would look and play similarly. + This might make the game a little more complex, since there are more concepts to assimilate, but these abilities have been designed to keep the spirit of the original game and remain simple. +

    + + +
    +
    + Slaughter of Cintra unit ability + Slaughter of Cintra special ability +
    +
    +
    Slaughter of Cintra
    +
    +

    + Like the name suggest, the Slaughter of Cintra ability applies to some Cintrian units. Some units have this ability, they are marked for slaugther. + When the corresponding special card is played, all of your cards on the board being marked (having the ability) are destroyed and move to the discard pile. + In return, you draw a card from the deck for each of the removed cards. This gives you a potential card advantage. +

    +

    + The trick is that you are not forced to use the special ability, the marked units can stay on the board and you can keep their strength for your total score. + So your opponent does not know whether you are planning to throw the round for card advantage or if you will keep the units. +

    +
    +
    +
    + + +
    +
    + Toussaint wine ability +
    +
    +
    Toussaint Wine
    +
    +

    + Toussaint Wine ability is like the cross of a Commander's Horn and Morale Boost. The ability will be played and stay on a row and boost all unit cards (not heroes) by 2 (instead of 1 like Morale Boost). +

    +
    +
    +
    + + +
    +
    + Bank ability +
    +
    +
    Bank
    +
    +

    + Bank ability is quite simple. You play it and you draw a card from your deck. No complication. + It is a little like skipping a round (you keep the same number of cards in your hand), except you do not know with which card you'll end up. +

    +
    +
    +
    + + +
    +
    + Lock ability +
    +
    +
    Lock
    +
    +

    + This ability is actually shared by several special cards. This card is played in one of the opponent's row. + If he/she plays a unit card (not a hero) in that row and that the units has an ability, the card will be locked and this special card will go to the graveyard. + A locked card cannot use its ability until it is removed from the board. +

    +

    + This ability requires a good understanding of the opponent deck and anticipation of the cards it can have. + It is very powerfull at preventing Muster and Tight Bond from working as intended. + Be careful though not to play your spy in this row while a lock is pending. +

    +
    +
    +
    + + +
    +
    + Knockback ability +
    +
    +
    Knockback
    +
    +

    + This ability is quite straight-forward. It is played in either the enemy Melee or Ranged row. All unit cards (not heroes) are moved 1 row backward towards the Siege row. +

    +

    + The purpose of this ability is mostly to break some effective row bonuses (like a Commander's Horn) or to push units into bad weather. +

    +
    +
    +
    + + +
    +
    + Seize ability +
    +
    +
    Seize
    +
    +

    + When using this ability, you will take control of the units with the lower strength in the enemy Melee row. If there are several, take all. +

    +

    + This ability can be very strong on Muster units or when the enemy Melee row is under bad weather. Be careful though that the timing is key. + Good targets this round might not be available next round because the opponent will have played a weaker card. +

    +
    +
    +
    + + +
    +
    + Shield ability +
    +
    +
    Shield
    +
    +

    + This ability protects an entire row from all abilities of the opponent, except weather, until the end of the round. + The main purpose is to protect the row from Scorch. Note that consequently cards in this row do not count in the definition of the highest strength on the board. +

    +
    +
    +
    + + +
    +
    + Witch Hunt ability +
    +
    +
    Witch Hunt
    +
    +

    + This ability is the mirror effect of Scorch Combat, it destroys the weakest units (not heroes) in the opposite row this card is playing on. + It is a very powerfull counter to Muster. +

    +
    +
    +
    + + +
    +
    + Witcher Wolf School ability + Witcher Viper School ability +
    +
    +
    Witcher School(s)
    +
    +

    + This Witcher School ability is actually 5 identical abilities. + There is one variation of the ability for each Witcher School (Wolf, Viper, Cat, Bear and Griffin). + When there is more than one unit card of a same Witcher School, boost all of these by 2 for each other members of the school (e.g. there are 3 cards of the School of the Wolf, boost all units by 4). +

    +

    + This ability seems difficult to exploit, but it works in combination with another ability. +

    +
    +
    +
    + + +
    +
    + Resilience ability +
    +
    +
    Resilience
    +
    +

    + If at the end of the round you have a card with the Resilience ability on the board and that it shares a second ability with another card on the board, keep the card with Resilience on the board for the next round. +

    +

    + For now, cards with the Resilience ability are Witchers Keeps. They stay on the board if a witcher of the corresponding school was also here. + This card will also contribute to boost witchers of the same school. +

    +
    +
    +
    + + +
    +
    + Whorshipper ability + Whorshipped ability +
    +
    +
    Whorshipper/Whorshipped
    +
    +

    + Whorshipped units are boosted by the amount of Whorshipper units on the board. +

    +

    + This ability requires to combine two type of cards for a powerful result. + Medic units can help to prolongate this combo into later rounds. + Be careful that it exposes a lot Whorshipped units to scorch. +

    +
    +
    +
    + + +
    +
    + Inspire ability +
    +
    +
    Inspire
    +
    +

    + All units with Inspire ability take the highest base strength of the Inspire units on your side of the board. Still affected by weather. +

    +

    + Basically, if you have several units on the board with the Inspire ability, they will align to the highest base strength among them (base strength, meaning before any effect, positive or negative). + Consequently playing late a stronger Inspire unit will boost all others on the board, which can bring an unpleasant and unnexpected surprise to the opponent. + Be aware though that since all Inspire units will have the same strength (prior to effects), they are vulnerable to scorch and can all be destroyed at the same time. + Providing a boost to some of them can help remediate this effect. +

    +
    +
    +
    + + +

    Factions

    + +

    + The Witcher universe is vast, so to bring more variety and fun to the game, it is divided into several factions. + Factions usually represent a realm or a group/faction of people. Each faction has its own set of cards along with a faction ability, and thus its own playstyle. + A faction ability, often passive (triggered at a specific moment of the game) but sometimes active as well (used at the discretion of the player), will have a significant influence on the way to play the game because you need to adapt to it to make the best of it. +

    + +

    + Before to start the game, a player must chose the faction to play, which will define the set of leaders and units that can be used to build the deck. + Some unit and special cards are Neutral, this means that they can be played in any faction. +

    + +

    Factions available

    + +

    Original game

    + +
    +
    + Northern Realms Faction +
    +
    +
    Northern Realms
    +
    +

    Faction Ability: Draw a card from your deck when you win a round.

    +

    This faction relies mostly on Tight Bond units, along with Spies and Siege units.

    +
    +
    +
    + +
    +
    + Nilfgaard Faction +
    +
    +
    Nilfgaard
    +
    +

    Faction Ability: If a round ends in a draw, Nilfgaard wins the round.

    +

    This faction relies mostly on Tight Bond units, Spies, Medics and Strong cards.

    +
    +
    +
    + +
    +
    + Monsters Faction +
    +
    +
    Monsters
    +
    +

    Faction Ability: At the end of each round, a random unit card stays on the board.

    +

    This faction relies heavily on the Muster ability, it can quickly swarm the board.

    +
    +
    +
    + +
    +
    + Scoia'Tael Faction +
    +
    +
    Scoia'Tael
    +
    +

    Faction Ability: Before the game starts, this faction decides who plays first.

    +

    This faction relies mostly on Muster and Medic units and some Morale Boost.

    +
    +
    +
    + +
    +
    + Skellige Faction +
    +
    +
    Skellige
    +
    +

    Faction Ability: On the third round, restores two random unit cards from the graveyard.

    +

    This faction has a balance of Tight Bond, Muster and Medic, but its specificity is the Berserker/Mardroeme combo.

    +
    +
    +
    + +

    Custom new factions

    + +
    +
    + Witcher Universe Faction +
    +
    +
    Witcher Universe
    +
    +

    Faction Ability: Once per round, the player can skip a round.

    +

    This faction has a variety of cards of all kinds, but its specificity is the witchers and their corresponding abilities and signs.

    +
    +
    +
    + +
    +
    + Toussaint Faction +
    +
    +
    Toussaint
    +
    +

    Faction Ability: Draw a card from your deck whenever you lose a round.

    +

    This faction has a balance of Tight Bond, Muster and Scorch units and many strong cards.

    +
    +
    +
    + +
    +
    + Lyria & Rivia Faction +
    +
    +
    Lyria & Rivia
    +
    +

    Faction Ability: Once per game, apply a Morale Boost to a row of your choice.

    +

    This faction relies mostly on Muster and Medic cards but also has the specificity of having decoy units and shield special cards.

    +
    +
    +
    + +
    +
    + Syndicate Faction +
    +
    +
    Syndicate
    +
    +

    Faction Ability: Start the game with the hero Sigi Reuven on the board.

    +

    This faction relies mostly on Spies, Muster and Tight Bond units but also has the specificity of having the Bank special card and some Witch Hunt units.

    +
    +
    +
    + +
    +
    + Zerrikania Faction +
    +
    +
    Zerrikania
    +
    +

    Faction Ability: Restore a unit card of your choice whenever you lose a round.

    +

    + This faction brings in some new abilities. On one side the dragon cult has the combination of Whorshippers and Whorshipped units. + On the other side, Free Warriors have the Inspire ability, allowing them to have the strength of the strongest of them on board. +

    +
    +
    +
    + + +

    Setup

    + +

    Building your deck

    + +

    + To play, each player must chose a faction, a leader and select or prepare a deck of the selected faction. + We have prepared a selection of decks which we think are interesting to play and reasonably balanced. + However, you can constitute your own, the only rules are the following: + +

      +
    • Minumum 22 unit cards (heroes included) from the selected faction or neutral cards.
    • +
    • Maximum 10 special cards
    • +
    +

    + +

    + Tips: +

      +
    • The more cards you have in your deck, the less likely you are to draw the best cards and make the combos work. Chose wisely, here less is more.
    • +
    • + Hero cards might look powerfull at first, but in the end they are boring and are not the cards that win games because most of them have a limited impact. + Consequently, don't take too many of those. +
    • +
    +

    + +

    Start

    + +

    + A coin toss decides who starts first. Each player shuffles his/her deck and draws 10 cards. Before starting the game, each player can discard up to 2 cards and draw a replacement (aka Mulligan). + The remaining 10 cards will constitute the starting hand of the players, and most likely all the cards the players will have for the game. +

    + +

    Rounds

    + +

    + Players take turns either playing a card or using the active ability of their leader or faction (when available). + A player can instead chose to pass and sit out of the rest of the round (not play any hard), while the other player is free to play more cards. + When both players have passed or cannot play any other card, the round ends. The player with the lowest total strength loses a round and a life point. + Each player starts with 2 life points and thus loses the game when losing 2 rounds. +

    + +

    Note that in case of a draw, both players have the lowest strength and lose a life point. Unless you play as Nilfgaard (wins in case of draws), this is not a desirable situation.

    + +

    The players that wins the round plays first in the next round.

    + +

    + Counting the total score can be really bothersome, good thing that here the computer is doing it for us. + But it remains important to understand how it's done in order to anticipate the changes when playing certain cards. + Here are the principles to count the scores. +

    + +

    + For each row: +

      +
    • Weather effects always apply first, before anything else. They change the base strength of the unit cards.
    • +
    • Some rare faction/leader abilities also affect the base strength. Weather takes precedence over them, but if no weather effect is active, apply these changes first.
    • +
    • From this point, consider that the strength is calculated from the most specific ability of the card to the more global effects.
    • +
    • First we apply the Tight Bond effects.
    • +
    • Then we apply the various boosts (Morale, Witcher School, Toussaint Wine etc), which simply add up one another, order does not matter.
    • +
    • Last, always last, we apply the row multipler, being the Commander's Horn.
    • +
    +

    + +

    That's it, now you know everything you need to play a round of Gwent!

    + +
    +
    +
    + + + + + \ No newline at end of file diff --git a/rules.js b/rules.js new file mode 100644 index 0000000..112c5af --- /dev/null +++ b/rules.js @@ -0,0 +1,54 @@ +(function (window, document) { + + // we fetch the elements each time because docusaurus removes the previous + // element references on page navigation + function getElements() { + return { + layout: document.getElementById('layout'), + menu: document.getElementById('menu'), + menuLink: document.getElementById('menuLink') + }; + } + + function toggleClass(element, className) { + var classes = element.className.split(/\s+/); + var length = classes.length; + var i = 0; + + for (; i < length; i++) { + if (classes[i] === className) { + classes.splice(i, 1); + break; + } + } + // The className is not found + if (length === classes.length) { + classes.push(className); + } + + element.className = classes.join(' '); + } + + function toggleAll() { + var active = 'active'; + var elements = getElements(); + + toggleClass(elements.layout, active); + toggleClass(elements.menu, active); + toggleClass(elements.menuLink, active); + } + + function handleEvent(e) { + var elements = getElements(); + + if (e.target.id === elements.menuLink.id) { + toggleAll(); + e.preventDefault(); + } else if (elements.menu.className.indexOf('active') !== -1) { + toggleAll(); + } + } + + document.addEventListener('click', handleEvent); + +}(this, this.document)); \ No newline at end of file diff --git a/sfx/ally.mp3 b/sfx/ally.mp3 new file mode 100644 index 0000000..ff26a90 Binary files /dev/null and b/sfx/ally.mp3 differ diff --git a/sfx/card.mp3 b/sfx/card.mp3 new file mode 100644 index 0000000..9c8d0e7 Binary files /dev/null and b/sfx/card.mp3 differ diff --git a/sfx/clear.mp3 b/sfx/clear.mp3 new file mode 100644 index 0000000..84d77d0 Binary files /dev/null and b/sfx/clear.mp3 differ diff --git a/sfx/cold.mp3 b/sfx/cold.mp3 new file mode 100644 index 0000000..ed0b952 Binary files /dev/null and b/sfx/cold.mp3 differ diff --git a/sfx/common1.mp3 b/sfx/common1.mp3 new file mode 100644 index 0000000..040bfdb Binary files /dev/null and b/sfx/common1.mp3 differ diff --git a/sfx/common2.mp3 b/sfx/common2.mp3 new file mode 100644 index 0000000..4e07b0a Binary files /dev/null and b/sfx/common2.mp3 differ diff --git a/sfx/common3.mp3 b/sfx/common3.mp3 new file mode 100644 index 0000000..982353e Binary files /dev/null and b/sfx/common3.mp3 differ diff --git a/sfx/discard.mp3 b/sfx/discard.mp3 new file mode 100644 index 0000000..15f3ffd Binary files /dev/null and b/sfx/discard.mp3 differ diff --git a/sfx/explaining.mp3 b/sfx/explaining.mp3 new file mode 100644 index 0000000..783877e Binary files /dev/null and b/sfx/explaining.mp3 differ diff --git a/sfx/fog.mp3 b/sfx/fog.mp3 new file mode 100644 index 0000000..65ef8a2 Binary files /dev/null and b/sfx/fog.mp3 differ diff --git a/sfx/game_buy.mp3 b/sfx/game_buy.mp3 new file mode 100644 index 0000000..7d55fc2 Binary files /dev/null and b/sfx/game_buy.mp3 differ diff --git a/sfx/game_lose.mp3 b/sfx/game_lose.mp3 new file mode 100644 index 0000000..e2a9d5e Binary files /dev/null and b/sfx/game_lose.mp3 differ diff --git a/sfx/game_opening.mp3 b/sfx/game_opening.mp3 new file mode 100644 index 0000000..cb5b3a2 Binary files /dev/null and b/sfx/game_opening.mp3 differ diff --git a/sfx/game_start.mp3 b/sfx/game_start.mp3 new file mode 100644 index 0000000..5829751 Binary files /dev/null and b/sfx/game_start.mp3 differ diff --git a/sfx/game_win.mp3 b/sfx/game_win.mp3 new file mode 100644 index 0000000..8f7118c Binary files /dev/null and b/sfx/game_win.mp3 differ diff --git a/sfx/hero.mp3 b/sfx/hero.mp3 new file mode 100644 index 0000000..fe0dcbd Binary files /dev/null and b/sfx/hero.mp3 differ diff --git a/sfx/horn.mp3 b/sfx/horn.mp3 new file mode 100644 index 0000000..5760924 Binary files /dev/null and b/sfx/horn.mp3 differ diff --git a/sfx/knockback.mp3 b/sfx/knockback.mp3 new file mode 100644 index 0000000..44b2e7a Binary files /dev/null and b/sfx/knockback.mp3 differ diff --git a/sfx/lock.mp3 b/sfx/lock.mp3 new file mode 100644 index 0000000..02be81a Binary files /dev/null and b/sfx/lock.mp3 differ diff --git a/sfx/med.mp3 b/sfx/med.mp3 new file mode 100644 index 0000000..5da9e03 Binary files /dev/null and b/sfx/med.mp3 differ diff --git a/sfx/menu_buy.mp3 b/sfx/menu_buy.mp3 new file mode 100644 index 0000000..557ee2b Binary files /dev/null and b/sfx/menu_buy.mp3 differ diff --git a/sfx/menu_opening.mp3 b/sfx/menu_opening.mp3 new file mode 100644 index 0000000..e3cb39c Binary files /dev/null and b/sfx/menu_opening.mp3 differ diff --git a/sfx/moral.mp3 b/sfx/moral.mp3 new file mode 100644 index 0000000..a4f1851 Binary files /dev/null and b/sfx/moral.mp3 differ diff --git a/sfx/pass.mp3 b/sfx/pass.mp3 new file mode 100644 index 0000000..ab81288 Binary files /dev/null and b/sfx/pass.mp3 differ diff --git a/sfx/rain.mp3 b/sfx/rain.mp3 new file mode 100644 index 0000000..d3126bb Binary files /dev/null and b/sfx/rain.mp3 differ diff --git a/sfx/redraw.mp3 b/sfx/redraw.mp3 new file mode 100644 index 0000000..cbda71b Binary files /dev/null and b/sfx/redraw.mp3 differ diff --git a/sfx/resilience.mp3 b/sfx/resilience.mp3 new file mode 100644 index 0000000..7f141ff Binary files /dev/null and b/sfx/resilience.mp3 differ diff --git a/sfx/round1_start.mp3 b/sfx/round1_start.mp3 new file mode 100644 index 0000000..e1659d1 Binary files /dev/null and b/sfx/round1_start.mp3 differ diff --git a/sfx/round_lose.mp3 b/sfx/round_lose.mp3 new file mode 100644 index 0000000..fa1e088 Binary files /dev/null and b/sfx/round_lose.mp3 differ diff --git a/sfx/round_win.mp3 b/sfx/round_win.mp3 new file mode 100644 index 0000000..fae67c5 Binary files /dev/null and b/sfx/round_win.mp3 differ diff --git a/sfx/scorch.mp3 b/sfx/scorch.mp3 new file mode 100644 index 0000000..cda5525 Binary files /dev/null and b/sfx/scorch.mp3 differ diff --git a/sfx/seize.mp3 b/sfx/seize.mp3 new file mode 100644 index 0000000..1ee4edc Binary files /dev/null and b/sfx/seize.mp3 differ diff --git a/sfx/shield.mp3 b/sfx/shield.mp3 new file mode 100644 index 0000000..b347704 Binary files /dev/null and b/sfx/shield.mp3 differ diff --git a/sfx/spy.mp3 b/sfx/spy.mp3 new file mode 100644 index 0000000..5b2885c Binary files /dev/null and b/sfx/spy.mp3 differ diff --git a/sfx/turn_me.mp3 b/sfx/turn_me.mp3 new file mode 100644 index 0000000..7ae8cf1 Binary files /dev/null and b/sfx/turn_me.mp3 differ diff --git a/sfx/turn_op.mp3 b/sfx/turn_op.mp3 new file mode 100644 index 0000000..dbaf52f Binary files /dev/null and b/sfx/turn_op.mp3 differ diff --git a/sfx/warning.mp3 b/sfx/warning.mp3 new file mode 100644 index 0000000..7f6c6fb Binary files /dev/null and b/sfx/warning.mp3 differ diff --git a/sim.html b/sim.html new file mode 100644 index 0000000..9deb20a --- /dev/null +++ b/sim.html @@ -0,0 +1,23 @@ + + + + + +
    +
    + + + + + +
    +
    +
    + + + + + + + + \ No newline at end of file diff --git a/sim.js b/sim.js new file mode 100644 index 0000000..09d8733 --- /dev/null +++ b/sim.js @@ -0,0 +1,2602 @@ +"use strict" + +class Controller { } + +var nilfgaard_wins_draws = false; + +// Makes decisions for the AI opponent player +class ControllerAI { + constructor(player) { + this.player = player; + } + + // Collects data and weighs options before taking a weighted random action + async startTurn(player) { + game.gameTracker.startTurn(player); + if (player.opponent().passed && (player.winning || player.deck.faction === "nilfgaard" && player.total === player.opponent().total)) { + nilfgaard_wins_draws = player.deck.faction === "nilfgaard" && player.total === player.opponent().total; + await player.passRound(); + return; + } + let data_max = this.getMaximums(); + let data_board = this.getBoardData(); + let weights = player.hand.cards.map(c => + ({ + weight: this.weightCard(c, data_max, data_board), + action: async () => await this.playCard(c, data_max, data_board), + card: c + })); + // If the opponent has passed and is not too far ahead, let's try to take the win + let diff = player.opponent().total - player.total; + if (player.opponent().passed && diff < 16) { + // Looking for a one shot that isn't overkill + let oneshot = weights.filter(w => (w.card.basePower > diff && w.card.basePower < diff + 5) || (w.weight > diff && w.weight > diff + 5)); + if (oneshot.length > 0) { + let oneshot_card = oneshot.sort((a, b) => (a.weight - b.weight))[0]; + await oneshot_card.action(); + return; + } + // Can we catch up in 2 plays? + let playable = weights.filter(w => w.weight > 0).sort((a, b) => (b.weight - a.weight)); + if (playable.length > 2) + playable = playable.slice(0, 2); + let weightTotal = playable.reduce((a, c) => a + c.weight, 0); + if (weightTotal > diff) { + await playable[0].action(); + return; + } + } + if (player.leaderAvailable) + weights.push({ + name: "Leader Ability", + weight: this.weightLeader(player.leader, data_max, data_board), + action: async () => { + await player.activateLeader(); + } + }); + if (player.factionAbilityUses > 0) { + let factionAbility = factions[player.deck.faction]; + weights.push({ + name: "Faction ability", + weight: factionAbility.weight(player), + action: async () => { + await player.useFactionAbility(); + } + }); + } + weights.push({ + name: "Pass", + weight: this.weightPass(), + action: async () => await player.passRound() + }); + let weightTotal = weights.reduce((a, c) => a + c.weight, 0); + if (weightTotal === 0) { + for (let i = 0; i < player.hand.cards.length; ++i) { + let card = player.hand.cards[i]; + if (card.row === "weather" && this.weightWeather(card) > -1 || card.abilities.includes("avenger")) { + await weights[i].action(); + return; + } + } + await player.passRound(); + } else { + /*console.log(this.player.tag); + for (var i = 0; i < weights.length; ++i) { + if (weights[i].card) + console.log("[" + weights[i].card.name + "] Weight: " + weights[i].weight); + else + console.log("[" + weights[i].name + "] Weight: " + weights[i].weight); + }*/ + let rand = randomInt(weightTotal); + //console.log("Chosen weight: " + rand); + for (var i = 0; i < weights.length; ++i) { + rand -= weights[i].weight; + if (rand < 0) + break; + } + //console.log(weights[i]); + await weights[i].action(); + } + } + + isSelfRowIndex(i) { + return (this.player === player_me && i > 2) || (this.player === player_op && i < 3); + } + + getSelfRowIndexes() { + if (this.player === player_me) + return [3, 4, 5]; + return [0, 1, 2]; + } + + // Collects data about card with the hightest power on the board + getMaximums() { + let rmax = board.row.map(r => ({ + row: r, + cards: r.cards.filter(c => c.isUnit()).reduce((a, c) => + (!a.length || a[0].power < c.power) ? [c] : a[0].power === c.power ? a.concat([c]) : a, []) + })); + + let max = rmax.filter((r, i) => r.cards.length && this.isSelfRowIndex(i)).reduce((a, r) => Math.max(a, r.cards[0].power), 0); + let max_me = rmax.filter((r, i) => this.isSelfRowIndex(i) && r.cards.length && r.cards[0].power === max).reduce((a, r) => + a.concat(r.cards.map(c => ({ + row: r, + card: c + }))), []); + + max = rmax.filter((r, i) => r.cards.length && !this.isSelfRowIndex(i)).reduce((a, r) => Math.max(a, r.cards[0].power), 0); + let max_op = rmax.filter((r, i) => !this.isSelfRowIndex(i) && r.cards.length && r.cards[0].power === max).reduce((a, r) => + a.concat(r.cards.map(c => ({ + row: r, + card: c + }))), []); + + // Also compute for rows without a shield + let rmax_noshield = rmax.filter((r, i) => !r.row.isShielded()); + let max_noshield = rmax_noshield.filter((r, i) => r.cards.length && this.isSelfRowIndex(i)).reduce((a, r) => Math.max(a, r.cards[0].power), 0); + let max_me_noshield = rmax_noshield.filter((r, i) => this.isSelfRowIndex(i) && r.cards.length && r.cards[0].power === max_noshield).reduce((a, r) => + a.concat(r.cards.map(c => ({ + row: r, + card: c + }))), []); + + max_noshield = rmax_noshield.filter((r, i) => r.cards.length && !this.isSelfRowIndex(i)).reduce((a, r) => Math.max(a, r.cards[0].power), 0); + let max_op_noshield = rmax_noshield.filter((r, i) => !this.isSelfRowIndex(i) && r.cards.length && r.cards[0].power === max_noshield).reduce((a, r) => + a.concat(r.cards.map(c => ({ + row: r, + card: c + }))), []); + + return { + rmax: rmax, + me: max_me, + op: max_op, + rmax_noshield: rmax_noshield, + me_noshield: max_me_noshield, + op_noshield: max_op_noshield + }; + } + + // Collects data about the types of cards on the board and in each player's graves + getBoardData() { + let data = this.countCards(new CardContainer()); + this.player.getAllRows().forEach(r => this.countCards(r, data)); + data.grave_me = this.countCards(this.player.grave); + data.grave_op = this.countCards(this.player.opponent().grave); + return data; + } + + // Catalogs the kinds of cards in a given CardContainer + countCards(container, data) { + data = data ? data : { + spy: [], + medic: [], + bond: {}, + scorch: [] + }; + container.cards.filter(c => c.isUnit()).forEach(c => { + for (let x of c.abilities) { + if (!c.isLocked()) { + switch (x) { + case "spy": + case "medic": + data[x].push(c); + break; + case "scorch_r": + case "scorch_c": + case "scorch_s": + data["scorch"].push(c); + break; + case "bond": + if (!data.bond[c.target]) + data.bond[c.target] = 0; + data.bond[c.target]++; + } + } + } + }); + return data; + } + + // Swaps a card from the hand with the deck if beneficial + redraw() { + let card = this.discardOrder({ + holder: this.player + }).shift(); + if (card && card.power < 15) { + this.player.deck.swap(this.player.hand, this.player.hand.removeCard(card)); + } + } + + // Orders discardable cards from most to least discardable + discardOrder(card, src = null) { + let cards = []; + let groups = {}; + let source = src ? src : card.holder.hand; + + let musters = source.cards.filter(c => c.abilities.includes("muster")); + // Grouping Musters together + musters.forEach(curr => { + let name = curr.target; + if (!groups[name]) + groups[name] = []; + groups[name].push(curr); + }); + // Keeping one in hand for each muster group + for (let group of Object.values(groups)) { + group.sort(Card.compare); + group.pop(); + cards.push(...group); + } + + // Targets of muster that do not have the ability themselves for which we already have the "summoner" + let tmusters = source.cards.filter(c => Object.keys(groups).includes(c.target) && !c.abilities.includes("muster")); + cards.push(...tmusters); + + // Discarding randomly weather cards to keep only 1 in hand + let weathers = source.cards.filter(c => c.row === "weather"); + if (weathers.length > 1) { + weathers.splice(randomInt(weathers.length), 1); + cards.push(...weathers); + } + // Discarding cards with no abilities by order of strength, unless they are of 7+ + let normal = source.cards.filter(c => c.abilities.length === 0 && c.basePower < 7); + normal.sort(Card.compare); + cards.push(...normal); + + // Grouping bonds together + let bonds = source.cards.filter(c => c.abilities.includes("bond")); + groups = {}; + bonds.forEach(curr => { + let name = curr.target; + if (!groups[name]) + groups[name] = []; + groups[name].push(curr); + }); + // Discarding those that are alone and weak (< 6) + for (let group of Object.values(groups)) { + if (group.length === 1 && group[0].basePower < 6) { + cards.push(group[0]); + } + } + + return cards; + } + + // Tells the Player that this object controls to play a card + async playCard(c, max, data) { + if (c.key === "spe_horn") + await this.horn(c); + else if (c.key === "spe_mardroeme") + await this.mardroeme(c); + else if (c.abilities.includes("decoy")) + await this.decoy(c, max, data); + else if (c.faction === "special" && c.abilities.includes("scorch")) + await this.scorch(c, max, data); + else if (c.faction === "special" && c.abilities.includes("cintra_slaughter")) + await this.slaughterCintra(c); + else if (c.faction === "special" && c.abilities.includes("seize")) + await this.seizeCards(c); + else if (c.faction === "special" && (c.abilities.includes("shield") || c.abilities.includes("shield_c") || c.abilities.includes("shield_r") || c.abilities.includes("shield_s"))) + await this.shieldCards(c); + else if (c.faction === "special" && c.abilities.includes("lock")) + await this.lock(c); + else if (c.faction === "special" && c.abilities.includes("knockback")) + await this.knockback(c); + else if (c.faction === "special" && c.abilities.includes("toussaint_wine")) + await this.toussaintWine(c); + else if ((c.isUnit() || c.hero) && c.abilities.includes("witch_hunt")) + await this.witchHunt(c); + else if (c.faction === "special" && c.abilities.includes("bank")) + await this.bank(c); + else if ((c.isUnit() || c.hero) && c.row === "agile" && (c.abilities.includes("morale") || c.abilities.includes("horn") || c.abilities.includes("bond"))) + await this.player.playCardToRow(c, this.bestAgileRowChange(c).row); + else + await this.player.playCard(c); + } + + // Plays a Commander's Horn to the most beneficial row. Assumes at least one viable row. + async horn(card) { + let rows = this.player.getAllRows().filter(r => !r.special.containsCardByKey("spe_horn")); + let max_row; + let max = 0; + for (let i = 0; i < rows.length; ++i) { + let r = rows[i]; + let dif = [0, 0]; + this.calcRowPower(r, dif, true); + r.effects.horn++; + this.calcRowPower(r, dif, false); + r.effects.horn--; + let score = dif[1] - dif[0]; + if (max < score) { + max = score; + max_row = r; + } + } + await this.player.playCardToRow(card, max_row); + } + + // Plays a Mardroeme to the most beneficial row. Assumes at least one viable row. + async mardroeme(card) { + let row, max = 0; + this.getSelfRowIndexes().forEach(i => { + let curr = this.weightMardroemeRow(card, board.row[i]); + if (curr > max) { + max = curr; + row = board.row[i]; + } + }); + await this.player.playCardToRow(card, row); + } + + // Selects a card to remove from a Grave. Assumes at least one valid card. + medic(card, grave) { + let data = this.countCards(grave); + let targ; + if (data.spy.length) { + let min = data.spy.reduce((a, c) => Math.min(a, c.power), Number.MAX_VALUE); + targ = data.spy.filter(c => c.power === min)[0]; + } else if (data.medic.length) { + let max = data.medic.reduce((a, c) => Math.max(a, c.power), 0); + targ = data.medic.filter(c => c.power === max)[0]; + } else if (data.scorch.length) { + targ = data.scorch[randomInt(data.scorch.length)]; + } else { + let units = grave.findCards(c => c.isUnit()); + targ = units.reduce((a, c) => a.power < c.power ? c : a, units[0]); + } + return targ; + } + + // Selects a card to return to the Hand and replaces it with a Decoy. Assumes at least one valid card. + async decoy(card, max, data) { + let targ, row; + if (game.decoyCancelled) + return; + let usable_data; + if (card.row.length > 0) { + // Units with decoy ability only work on a specific row + if (card.row === "close" || card.row === "agile") + usable_data = this.countCards(board.getRow(card, "close", this.player), usable_data); + if (card.row === "ranged" || card.row === "agile") + usable_data = this.countCards(board.getRow(card, "ranged", this.player), usable_data); + if (card.row === "siege") + usable_data = this.countCards(board.getRow(card, "siege", this.player), usable_data); + } else { + usable_data = data; + } + if (usable_data.spy.length) { + let min = usable_data.spy.reduce((a, c) => Math.min(a, c.power), Number.MAX_VALUE); + targ = usable_data.spy.filter(c => c.power === min)[0]; + } else if (usable_data.medic.length) { + targ = usable_data.medic[randomInt(usable_data.medic.length)]; + } else if (usable_data.scorch.length) { + targ = usable_data.scorch[randomInt(usable_data.scorch.length)]; + } else { + let pairs = max.rmax.filter((r, i) => this.isSelfRowIndex(i) && r.cards.length) + .filter((r, i) => card.row.length === 0 || (["close", "agile"].includes(card.row) && (i === 2 || i === 3)) || (["ranged", "agile"].includes(card.row) && (i === 1 || i === 4)) || (card.row === "siege" && (i === 0 || i === 5))) + .reduce((a, r) => + r.cards.map(c => ({ + r: r.row, + c: c + })).concat(a), []); + + if (pairs.length) { + let pair = pairs[randomInt(pairs.length)]; + targ = pair.c; + row = pair.r; + } + } + + if (targ) { + for (let i = 0; !row; ++i) { + if (board.row[i].cards.indexOf(targ) !== -1) { + row = board.row[i]; + break; + } + } + targ.decoyTarget = true; + board.toHand(targ, row); + } else { + row = ["close", "agile"].includes(card.row) ? board.getRow(card, "close", this.player) : card.row === "ranged" ? board.getRow(card, "ranged", this.player) : board.getRow(card, "siege", this.player); + } + await this.player.playCardToRow(card, row); + } + + // Tells the controlled Player to play the Scorch card + async scorch(card, max, data) { + await this.player.playScorch(card); + } + + // Tells the controlled Player to play the Scorch card + async slaughterCintra(card) { + await this.player.playSlaughterCintra(card); + } + + // Tells the controlled Player to play the seize special card + async seizeCards(card) { + await this.player.playSeize(card); + } + + // Plays a shield special card to the most beneficial row. Assumes at least one viable row. + // Also applicable for shield cards which affect only one row. + async shieldCards(card) { + if (card.abilities.includes("shield_c")) { + await this.player.playCardToRow(card, board.getRow(card, "close", this.player)); + return; + } else if (card.abilities.includes("shield_r")) { + await this.player.playCardToRow(card, board.getRow(card, "ranged", this.player)); + return; + } if (card.abilities.includes("shield_s")) { + await this.player.playCardToRow(card, board.getRow(card, "siege", this.player)); + return; + } + + let units = card.holder.getAllRowCards().concat(card.holder.hand.cards).filter(c => c.isUnit()).filter(c => !c.abilities.includes("spy")); + let rowStats = { "close": 0, "ranged": 0, "siege": 0, "agile": 0 }; + units.forEach(c => { + rowStats[c.row] += c.power; + }); + rowStats["close"] += rowStats["agile"]; + let max_row; + if (rowStats["close"] >= rowStats["ranged"] && rowStats["close"] >= rowStats["siege"]) + max_row = board.getRow(card, "close", this.player); + else if (rowStats["ranged"] > rowStats["close"] && rowStats["ranged"] >= rowStats["siege"]) + max_row = board.getRow(card, "ranged", this.player); + else + max_row = board.getRow(card, "siege", this.player); + await this.player.playCardToRow(card, max_row); + } + + // Plays the lock special card in the enemy melee row + async lock(card) { + await this.player.playCardToRow(card, board.getRow(card, "close", this.player.opponent())); + } + + // Plays the knockback special card in the most beneficial row - by default enemy melee row + async knockback(card) { + await this.player.playKnockback(card); + } + + // Play special wine card to the most beneficial row. + async toussaintWine(card) { + await this.player.playCardToRow(card, this.bestRowToussaintWine(card)); + } + + // Play special wine card to the most beneficial row. + async witchHunt(card) { + await this.player.playCardToRow(card, this.bestWitchHuntRow(card).getOppositeRow()); + } + + // Plays the bank special card + async bank(card) { + await this.player.playBank(card); + } + + bestWitchHuntRow(card) { + if (card.row == "agile") { + let r = [board.getRow(card, "close", this.player.opponent()), board.getRow(card, "ranged", this.player.opponent())]; + let rows = r.filter(r => !r.isShielded() && !game.scorchCancelled).map(r => ({ + row: r, + value: r.minUnits().reduce((a, c) => a + c.power, 0) + })); + if (rows.length > 0) + return rows.sort((a, b) => b.value - a.value)[0].row; + else + return board.getRow(card, "close", card.holder.opponent()) + } else { + return board.getRow(card, card.row, card.holder.opponent()); + } + } + + bestRowToussaintWine(card) { + let units = card.holder.getAllRowCards().concat(card.holder.hand.cards).filter(c => c.isUnit()).filter(c => !c.abilities.includes("spy")); + let rowStats = { "close": 0, "ranged": 0, "siege": 0, "agile": 0 }; + units.forEach(c => { + rowStats[c.row] += 1; + }); + rowStats["close"] += rowStats["agile"]; + let rows = card.holder.getAllRows(); + rowStats["close"] = board.getRow(card, "close", this.player).effects.toussaint_wine > 0 ? 0 : rowStats["close"]; + rowStats["ranged"] = board.getRow(card, "ranged", this.player).effects.toussaint_wine > 0 ? 0 : rowStats["ranged"]; + rowStats["siege"] = board.getRow(card, "siege", this.player).effects.toussaint_wine > 0 ? 0 : rowStats["siege"]; + let max_row; + if (rowStats["close"] >= rowStats["ranged"] && rowStats["close"] >= rowStats["siege"]) + max_row = board.getRow(card, "close", this.player); + else if (rowStats["ranged"] > rowStats["close"] && rowStats["ranged"] >= rowStats["siege"]) + max_row = board.getRow(card, "ranged", this.player); + else + max_row = board.getRow(card, "siege", this.player); + return max_row; + } + + // Assigns a weight for how likely the conroller is to Pass the round + weightPass() { + if (this.player.health === 1) + return 0; + let dif = this.player.opponent().total - this.player.total; + if (dif > 30) + return 100; + if (dif < -30 && this.player.opponent().handsize - this.player.handsize > 2) + return 100; + return Math.floor(Math.abs(dif)); + } + + // Assigns a weight for how likely the controller is to activate its leader ability + weightLeader(card, max, data) { + let w = ability_dict[card.abilities[0]].weight; + if (ability_dict[card.abilities[0]].weight) { + let score = w(card, this, max, data); + return score; + } + return 10 + (game.roundCount - 1) * 15; + } + + // Assigns a weight for how likely the controller will use a scorch-row card + weightScorchRow(card, max, row_name) { + if (game.scorchCancelled) + return 0; + let index = 3 + (row_name === "close" ? 0 : row_name === "ranged" ? 1 : 2); + if (this.player === player_me) + index = 2 - (row_name === "close" ? 0 : row_name === "ranged" ? 1 : 2); + if (board.row[index].total < 10 || board.row[index].isShielded()) + return 0; + let score = max.rmax[index].cards.reduce((a, c) => a + c.power, 0); + return score; + } + + // Calculates a weight for how likely the controller will use horn on this row + weightHornRow(card, row) { + return row.effects.horn ? 0 : this.weightRowChange(card, row); + } + + // Calculates weight for playing a card on a given row, min 0 + weightRowChange(card, row) { + return Math.max(0, this.weightRowChangeTrue(card, row)); + } + + bestAgileRowChange(card) { + let rows = [{ row: board.getRow(card, "close", card.holder), score: 0 }, { row: board.getRow(card, "ranged", card.holder), score: 0 }]; + for (var i = 0; i < 2; i++) { + rows[i].score = this.weightRowChange(card, rows[i].row); + } + return rows.sort((a, b) => b.score - a.score)[0]; + } + + // Calculates weight for playing a card on the given row + weightRowChangeTrue(card, row) { + let dif = [0, 0]; + this.calcRowPower(row, dif, true); + row.updateState(card, true); + this.calcRowPower(row, dif, false); + if (!card.isSpecial()) + dif[0] -= row.calcCardScore(card); + row.updateState(card, false); + return dif[1] - dif[0]; + } + + // Calculates the weight for playing a weather card + weightWeather(card) { + let rows; + if (card.abilities) { + if (card.key === "spe_clear") + rows = Object.values(weather.types).filter(t => t.count > 0).flatMap(t => t.rows); + else + rows = Object.values(weather.types).filter(t => t.count === 0 && t.name === card.abilities[0]).flatMap(t => t.rows); + } else { + if (card.ability == "clear") + rows = Object.values(weather.types).filter(t => t.count > 0).flatMap(t => t.rows); + else + rows = Object.values(weather.types).filter(t => t.count === 0 && t.name === card.ability).flatMap(t => t.rows); + } + + if (!rows.length) + return 1; + let dif = [0, 0]; + rows.forEach(r => { + let state = r.effects.weather; + this.calcRowPower(r, dif, true); + r.effects.weather = !state; + this.calcRowPower(r, dif, false); + r.effects.weather = state; + }); + return dif[1] - dif[0]; + } + + // Calculates the weight for playing a mardroeme card + weightMardroemeRow(card, row) { + if (card.key === "spe_mardroeme" && row.special.containsCardByKey("spe_mardroeme")) + return 0; + let ermion = card.holder.hand.cards.filter(c => c.key === "sk_ermion").length > 0; + if (ermion && card.key !== "sk_ermion" && row === board.getRow(card, "ranged", this.player)) + return 0; + let bers_cards = row.cards.filter(c => c.abilities.includes("berserker")); + let weightData = { bond: {}, strength: 0, scorch: 0 }; + + for (var i = 0; i < bers_cards.length; i++) { + let c = bers_cards[i]; + let ctarget = card_dict[c.target]; + weightData.strength -= c.power; + if (ctarget.ability.includes("morale")) + weightData.strength += Number(ctarget["strength"]) + row.cards.filter(c => c.isUnit()).length - 1; + if (ctarget.ability.includes("bond")) { + if (!weightData.bond[c.target]) + weightData.bond[c.target] = [0, Number(ctarget["strength"])]; + weightData.bond[c.target][0]++; + } + if (ctarget.ability.includes("scorch_c")) + weightData.scorch += this.weightScorchRow(card, this.getMaximums(), "close"); + } + let weight = weightData.strength + Object.keys(weightData.bond).reduce((s, c) => s + Math.pow(weightData.bond[c][0], 2) * weightData.bond[c][1], 0) + weightData.scorch; + return Math.max(1, weight); + } + + // Calculates the weight for cards with the medic ability + weightMedic(data, score, owner) { + let units = owner.grave.findCards(c => c.isUnit()); + let grave = data["grave_" + owner.opponent().tag]; + return !units.length ? Math.min(1, score) : score + (grave.spy.length ? 50 : grave.medic.length ? 15 : grave.scorch.length ? 10 : this.player.health === 1 ? 1 : 0); + } + + // Calculates the weight for cards with the berserker ability + weightBerserker(card, row, score) { + if (card.holder.hand.cards.filter(c => c.abilities.includes("mardroeme")).length < 1 && !row.effects.mardroeme > 0) + return score; + score -= card.basePower; + let ctarget = card_dict[card.target]; + if (ctarget.ability.includes("morale")) { + score += Number(ctarget["strength"]) + row.cards.filter(c => c.isUnit()).length - 1; + } + else if (ctarget.ability.includes("bond")) { + let n = 1; + if (!row.effects.mardroeme) + n += row.cards.filter(c => c.key === card.key).filter(c => !c.isLocked()).length; + else + n += row.cards.filter(c => c.key === card.target).filter(c => !c.isLocked()).length; + score += Number(ctarget["strength"]) * (n * n); + } else if (ctarget.ability.includes("scorch_c")) { + score += this.weightScorchRow(card, this.getMaximums(), "close"); + } else { + score += Number(ctarget["strength"]); + } + return Math.max(1, score); + } + + // Calculates the weight for a weather card if played from the deck + weightWeatherFromDeck(card, weather_id) { + if (card.holder.deck.findCard(c => c.abilities.includes(weather_id)) === undefined) + return 0; + return this.weightCard({ + abilities: [weather_id], + row: "weather" + }); + } + + // Assigns a weights for how likely the controller with play a card from its hand + weightCard(card, max, data) { + let abi + if (card.abilities) { + abi = card.abilities; + } else if (card["ability"]) { + abi = card["ability"].split(" "); + } else { + abi = []; + console.log("Missing abilities for card:"); + console.log(card); + } + if (abi.includes("decoy")) { + if (card.row.length > 0) { + let row_data; + if (card.row === "close" || card.row === "agile") + row_data = this.countCards(board.getRow(card, "close", this.player), row_data); + if (card.row === "ranged" || card.row === "agile") + row_data = this.countCards(board.getRow(card, "ranged", this.player), row_data); + if (card.row === "siege") + row_data = this.countCards(board.getRow(card, "siege", this.player), row_data); + return game.decoyCancelled ? 0 : row_data.spy.length ? 50 : row_data.medic.length ? 15 : row_data.scorch.length ? 10 : max.me.length ? card.power : 0; + } else + return game.decoyCancelled ? 0 : data.spy.length ? 50 : data.medic.length ? 15 : data.scorch.length ? 10 : max.me.length ? 1 : 0; + } + if (abi.includes("horn")) { + let rows = this.player.getAllRows().filter(r => !r.special.containsCardByKey("spe_horn")); + if (!rows.length) + return 0; + rows = rows.map(r => this.weightHornRow(card, r)); + return Math.max(...rows) / 2; + } + + if (abi) { + if (abi.includes("scorch")) { + if (game.scorchCancelled) + return Math.max(0, card.power); + let power_op = max.op_noshield.length ? max.op_noshield[0].card.power : 0; + let power_me = max.me_noshield.length ? max.me_noshield[0].card.power : 0; + let total_op = power_op * max.op_noshield.length; + let total_me = power_me * max.me_noshield.length; + return power_me > power_op ? 0 : power_me < power_op ? total_op : Math.max(0, total_op - total_me); + } + if (abi.includes("decoy")) { + return game.decoyCancelled ? 0 : data.spy.length ? 50 : data.medic.length ? 15 : data.scorch.length ? 10 : max.me.length ? 1 : 0; + } + if (abi.includes("mardroeme")) { + let rows = this.player.getAllRows(); + return Math.max(...rows.map(r => this.weightMardroemeRow(card, r))); + } + if (["cintra_slaughter", "seize", "lock", "shield", "knockback", "shield_c", "shield_r", "shield_s","bank"].includes(abi.at(-1))) { + return ability_dict[abi.at(-1)].weight(card); + } + if (abi.includes("witch_hunt")) { + if (game.scorchCancelled) + return card.power; + let best_row = this.bestWitchHuntRow(card) + if (best_row) { + let dmg = best_row.minUnits().reduce((a, c) => a + c.power, 0); + if (dmg < 6) // Let's not waste it on isolated weak units + dmg = 0; + return dmg + card.power; + } + return card.power + } + if (abi.includes("toussaint_wine")) { + let units = card.holder.getAllRowCards().concat(card.holder.hand.cards).filter(c => c.isUnit()).filter(c => !c.abilities.includes("spy")); + let rowStats = { "close": 0, "ranged": 0, "siege": 0, "agile": 0 }; + units.forEach(c => { + rowStats[c.row] += 1; + }); + rowStats["close"] += rowStats["agile"]; + let rows = card.holder.getAllRows(); + rowStats["close"] = board.getRow(card, "close", this.player).effects.toussaint_wine > 0 ? 0 : rowStats["close"]; + rowStats["ranged"] = board.getRow(card, "ranged", this.player).effects.toussaint_wine > 0 ? 0 : rowStats["ranged"]; + rowStats["siege"] = board.getRow(card, "siege", this.player).effects.toussaint_wine > 0 ? 0 : rowStats["siege"]; + return 2 * Math.max(rowStats["close"], rowStats["ranged"], rowStats["siege"]); + } + if (abi.at(-1) && abi.at(-1).startsWith("witcher_")) { + let witchers = card.holder.getAllRowCards().filter(c => c.abilities.includes(abi.at(-1))); + let keep = witchers.filter(c => c.hero); + return card.power + (2 * witchers.length * 2) + (keep.length > 0 ? keep[0].power : 0); + } + if (abi.includes("inspire")) { + let insp = card.holder.getAllRowCards().filter(c => c.abilities.includes("inspire")); + let best_power = 0; + if (insp.length > 0) + best_power = insp.sort((a, b) => b.power - a.power)[0].power; + let max_power = Math.max(card.power, best_power); + if (card.power === max_power) + return max_power + insp.map(c => max_power - c.power).reduce((a, c) => a + c, 0); + return max_power; + } + } + + if (card.row === "weather" || (card.deck && card.deck.startsWith("weather"))) { + return Math.max(0, this.weightWeather(card)); + } + + let row = board.getRow(card, card.row === "agile" ? "close" : card.row, this.player); + let score = row.calcCardScore(card); + switch (abi[abi.length - 1]) { + case "bond": + case "morale": + case "horn": + score = card.row === "agile" ? this.bestAgileRowChange(card).score : this.weightRowChange(card, row); + break; + case "medic": + score = this.weightMedic(data, score, card.holder); + break; + case "spy": + score = 15 + score; + break; + case "muster": + let pred = c => c.target === card.target; + let units = card.holder.hand.cards.filter(pred).concat(card.holder.deck.cards.filter(pred)); + score *= units.length; + break; + case "scorch_c": + score = Math.max(1, this.weightScorchRow(card, max, "close")); + break; + case "scorch_r": + score = Math.max(1, this.weightScorchRow(card, max, "ranged")); + break; + case "scorch_s": + score = Math.max(1, this.weightScorchRow(card, max, "siege")); + break; + case "berserker": + score = this.weightBerserker(card, row, score); + break; + case "avenger": + case "avenger_kambi": + case "whorshipper": + return score + ability_dict[abi.at(-1)].weight(card); + } + + return score; + } + + // Calculates the current power of a row associated with each Player + calcRowPower(r, dif, add) { + r.findCards(c => c.isUnit()).forEach(c => { + let p = r.calcCardScore(c); + c.holder === this.player ? (dif[0] += add ? p : -p) : (dif[1] += add ? p : -p); + }); + } +} + +var may_leader = true, + exibindo_lider = false; + +// Can make actions during turns like playing cards that it owns +class Player { + constructor(id, name, deck, isAI = true) { + this.id = id; + this.tag = (id === 0) ? "me" : "op"; + //this.controller = (id === 0) ? new Controller() : new ControllerAI(this); + if (isAI) { + this.controller = new ControllerAI(this); + } else { + this.controller = new Controller(); + } + + if (game.fullAI) { + this.hand = (id === 0) ? new Hand(null, this.tag) : new Hand(null, this.tag); + } else { + this.hand = (id === 0) ? new Hand(null, this.tag) : new HandAI(this.tag); + } + this.grave = new Grave(document.getElementById("grave-" + this.tag)); + this.deck = new Deck(deck.faction, document.getElementById("deck-" + this.tag)); + this.deck_data = deck; + this.leader = new Card(deck.leader.index, deck.leader.card, this); + + this.reset(); + + this.name = name; + } + + // Sets default values + reset() { + this.grave.reset(); + this.hand.reset(); + this.deck.reset(); + this.deck.initializeFromID(this.deck_data.cards, this); + + this.health = 2; + this.total = 0; + this.passed = false; + this.handsize = 10; + this.winning = false; + this.factionAbilityUses = 0; + this.effects = { + "witchers": {}, + "whorshippers": 0, + "inspire": 0 + }; + + // Handling Faction abilities: active or passive + let factionAbility = factions[this.deck.faction]; + if (factionAbility["activeAbility"]) { + // Init ability if need be + if (factionAbility.factionAbilityInit) { + factionAbility.factionAbilityInit(this); + } + this.updateFactionAbilityUses(factionAbility["abilityUses"]); + } + + this.enableLeader(); + this.setPassed(false); + } + + roundStartReset() { + this.effects = { + "witchers": {}, + "whorshippers": 0, + "inspire": 0 + }; + } + + // Returns the opponent Player + opponent() { + return board.opponent(this); + } + + // Updates the player's total score and notifies the gamee + updateTotal(n) { + this.total += n; + board.updateLeader(); + } + + // Puts the player in the winning state + setWinning(isWinning) { + this.winning = isWinning; + } + + // Puts the player in the passed state + setPassed(hasPassed) { + this.passed = hasPassed; + } + + // Sets up board for turn + async startTurn() { + if (this.controller instanceof ControllerAI) { + await this.controller.startTurn(this); + } + } + + // Passes the round and ends the turn + async passRound() { + this.setPassed(true); + game.gameTracker.getCurrentTurn().passAction(); + await this.endTurn(); + } + + // Plays a scorch card + async playScorch(card) { + if (!game.scorchCancelled) { + game.gameTracker.getCurrentTurn().playSpecialCardBoard(card); + await this.playCardAction(card, async () => await ability_dict["scorch"].activated(card)); + } + } + + // Plays a Slaughter of Cintra card + async playSlaughterCintra(card) { + game.gameTracker.getCurrentTurn().playSpecialCardBoard(card); + await this.playCardAction(card, async () => await ability_dict["cintra_slaughter"].activated(card)); + } + + // Plays a Seize special card card + async playSeize(card) { + game.gameTracker.getCurrentTurn().playSpecialCard(card, board.getRow(card, "close", this.opponent())); + await this.playCardAction(card, async () => await ability_dict["seize"].activated(card)); + } + + // Plays a Knockback special card card, assuming 1 valid + async playKnockback(card) { + let best_row = board.getRow(card, "close", this.opponent()); + //If melee row is empty, better target ranged + if (board.getRow(card, "close", this.opponent()).cards.length === 0) + best_row = board.getRow(card, "ranged", this.opponent()); + // If siege has an active weather effect, better target ranged + if (board.getRow(card, "ranged", this.opponent()).cards.length > 1 && board.getRow(card, "siege", this.opponent()).effects.weather) + best_row = board.getRow(card, "ranged", this.opponent()); + // If ranged has a horn or shield effect, better target it + if ((board.getRow(card, "ranged", this.opponent()).isShielded() || board.getRow(card, "ranged", this.opponent()).effects.horn > 0) && board.getRow(card, "ranged", this.opponent()).cards.length > 0) + best_row = board.getRow(card, "ranged", this.opponent()); + // If there are some bond units in the ranged row, better try to break it before it grows + if (Object.keys(board.getRow(card, "ranged", this.opponent()).effects.bond).length > 0 && board.getRow(card, "siege", this.opponent()).effects.horn === 0) + best_row = board.getRow(card, "ranged", this.opponent()); + game.gameTracker.getCurrentTurn().playSpecialCard(card, best_row); + await this.playCardAction(card, async () => await ability_dict["knockback"].activated(card, best_row)); + } + + // Play the bank card + async playBank(card) { + game.gameTracker.getCurrentTurn().playSpecialCardBoard(card); + await this.playCardAction(card, async () => await ability_dict["bank"].activated(card)); + } + + // Plays a card to a specific row + async playCardToRow(card, row) { + if (row instanceof Weather) + game.gameTracker.getCurrentTurn().playWeatherCard(card); + else if (card.isUnit() || card.hero) + game.gameTracker.getCurrentTurn().playUnitCard(card, row); + else + game.gameTracker.getCurrentTurn().playSpecialCard(card, row); + await this.playCardAction(card, async () => await board.moveTo(card, row, this.hand)); + } + + // Plays a card to the board + async playCard(card) { + let rowType = (card.row === "agile") ? "close" : card.row ? card.row : "close"; + let row = board.getRow(card, rowType, this); + if (row instanceof Weather) + game.gameTracker.getCurrentTurn().playWeatherCard(card); + else if (card.isUnit() || card.hero) + game.gameTracker.getCurrentTurn().playUnitCard(card, row); + else + game.gameTracker.getCurrentTurn().playSpecialCard(card, row); + await this.playCardAction(card, async () => await card.autoplay(this.hand)); + } + + // Shows a preview of the card being played, plays it to the board and ends the turn + async playCardAction(card, action) { + ui.showPreviewVisuals(card); + ui.hidePreview(card); + await action(); + await this.endTurn(); + } + + // Handles end of turn visuals and behavior the notifies the game + async endTurn() { + if (!this.passed && !this.canPlay()) { + this.setPassed(true); + } + await game.endTurn(); + } + + // Tells the the Player if it won the round. May damage health. + endRound(win) { + if (!win) { + if (this.health < 1) + return; + this.health--; + } + this.setPassed(false); + this.setWinning(false); + } + + // Returns true if the Player can make any action other than passing + canPlay() { + return this.hand.cards.length > 0 || this.leaderAvailable || this.factionAbilityUses > 0; + } + + // Use a leader's Activate ability, then disable the leader + async activateLeader() { + if (this.leaderAvailable) { + this.endTurnAfterAbilityUse = true; + await this.leader.activated[0](this.leader, this); + this.disableLeader(); + // Some abilities require further actions before ending the turn, such as selecting a card + if (this.endTurnAfterAbilityUse) { + game.gameTracker.getCurrentTurn().useLeader(this.leader); + await this.endTurn(); + } else { + // Make selections for AI player + if (this.controller instanceof ControllerAI) { + if (this.leader.key === "wu_alzur_maker") { + let worse_unit = this.getAllRowCards().filter(c => c.isUnit()).sort((a, b) => a.power - b.power)[0]; + game.gameTracker.getCurrentTurn().useLeader(this.leader,worse_unit); + await ui.selectCard(worse_unit); + } else if (this.leader.key === "to_anna_henrietta_duchess") { + let horns = player_me.getAllRows().filter(r => r.special.findCards(c => c.abilities.includes("horn")).length > 0).sort((a, b) => b.total - a.total); + if (horns[0]) { + game.gameTracker.getCurrentTurn().useLeader(this.leader, horns[0]); + await ui.selectRow(horns[0]); + } + } else if (this.leader.key === "lr_meve_princess" || this.leader.key === "sy_carlo_varese") { + let max = this.controller.getMaximums(); + let rows = [this.controller.weightScorchRow(this.leader, max, "close"), this.controller.weightScorchRow(this.leader, max, "ranged"), this.controller.weightScorchRow(this.leader, max, "siege")]; + let maxv = 0, max_row; + let offset = 3; + if (this === player_me) { + offset = 0; + rows = rows.reverse(); + } + for (var i = 0; i < 3; i++) { + if (rows[i] > maxv) { + maxv = rows[i]; + max_row = board.row[offset + i]; + } + } + if (max_row) { + game.gameTracker.getCurrentTurn().useLeader(this.leader, max_row); + await ui.selectRow(max_row); + } + } else if (this.leader.key === "sy_cyrus_hemmelfart") { + // We select a random row to put shackles on + let offset = 3; + if (this === player_me) + offset = 0; + let r = board.row[offset + randomInt(2)]; + game.gameTracker.getCurrentTurn().useLeader(this.leader,r); + await ui.selectRow(r); + } + } + } + } + } + + // Disable access to leader ability and toggles leader visuals to off state + disableLeader() { + this.leaderAvailable = false; + } + + // Enable access to leader ability and toggles leader visuals to on state + enableLeader() { + this.leaderAvailable = this.leader.activated.length > 0; + } + + async useFactionAbility() { + let factionData = factions[this.deck.faction]; + if (factionData.activeAbility && this.factionAbilityUses > 0) { + this.endTurnAfterAbilityUse = true; + await factionData.factionAbility(this); + this.updateFactionAbilityUses(this.factionAbilityUses - 1); + // Some faction abilities require extra interractions + if (this.endTurnAfterAbilityUse) { + await this.endTurn(); + } else { + if (this.controller instanceof ControllerAI) { + if (this.deck.faction === "lyria_rivia") { + let best_row = this.controller.bestRowToussaintWine(ui.previewCard); // Reusing bestRowToussaintWine because it is nearly the same principle + await ui.selectRow(best_row, true); + } + } + } + } + return; + } + + updateFactionAbilityUses(count) { + this.factionAbilityUses = Math.max(0, count); + } + + // Get all rows for this player, sorted to have close > ranged > siege + getAllRows() { + if (this === player_me) { + return board.row.filter((r, i) => i > 2); + } + return board.row.filter((r, i) => i < 3).reverse(); + } + + //Get all cards in rows for this player + getAllRowCards() { + return this.getAllRows().reduce((a, r) => r.cards.concat(a), []); + } +} + +// Handles the adding, removing and formatting of cards in a container +class CardContainer { + constructor() { + this.cards = []; + } + + // Indicates whether or not this container contains any card + isEmpty() { + return this.cards.length === 0; + } + + // Returns the first card that satisfies the predcicate. Does not modify container. + findCard(predicate) { + for (let i = this.cards.length - 1; i >= 0; --i) + if (predicate(this.cards[i])) + return this.cards[i]; + } + + // Returns a list of cards that satisfy the predicate. Does not modify container. + findCards(predicate) { + return this.cards.filter(predicate); + } + + // Indicates whether or not the card with given Key can be found in container + containsCardByKey(key) { + return (this.findCards(c => c.key === key).length) > 0; + } + + // Returns a list of up to n cards that satisfy the predicate. Does not modify container. + findCardsRandom(predicate, n) { + let valid = predicate ? this.cards.filter(predicate) : this.cards; + if (valid.length === 0) + return []; + if (!n || n === 1) + return [valid[randomInt(valid.length)]]; + let out = []; + for (let i = Math.min(n, valid.length); i > 0; --i) { + let index = randomInt(valid.length); + out.push(valid.splice(index, 1)[0]); + } + return out; + } + + // Removes and returns a list of cards that satisy the predicate. + getCards(predicate) { + return this.cards.reduce((a, c, i) => (predicate(c, i) ? [i] : []).concat(a), []).map(i => this.removeCard(i)); + } + + // Removes and returns a card that satisfies the predicate. + getCard(predicate) { + for (let i = this.cards.length - 1; i >= 0; --i) + if (predicate(this.cards[i])) + return this.removeCard(i); + } + + // Removes and returns any cards up to n that satisfy the predicate. + getCardsRandom(predicate, n) { + return this.findCardsRandom(predicate, n).map(c => this.removeCard(c)); + } + + // Adds a card to the container along with its associated HTML element. + addCard(card, index) { + this.cards.push(card); + card.currentLocation = this; + } + + // Removes a card from the container along with its associated HTML element. + removeCard(card, index) { + if (this.cards.length === 0) + return card; + card = this.cards.splice(isNumber(card) ? card : this.cards.indexOf(card), 1)[0]; + return card; + } + + // Adds a card to a pre-sorted CardContainer + addCardSorted(card) { + let i = this.getSortedIndex(card); + this.cards.splice(i, 0, card); + return i; + } + + // Returns the expected index of a card in a sorted CardContainer + getSortedIndex(card) { + for (var i = 0; i < this.cards.length; ++i) + if (Card.compare(card, this.cards[i]) < 0) + break; + return i; + } + + // Adds a card to a random index of the CardContainer + addCardRandom(card) { + this.cards.push(card); + let index = randomInt(this.cards.length); + if (index !== this.cards.length - 1) { + let t = this.cards[this.cards.length - 1]; + this.cards[this.cards.length - 1] = this.cards[index]; + this.cards[index] = t; + } + return index; + } + + // Empty function to be overried by subclasses that resize their content + resize() { } + + // Returns the container to its default, empty state + reset() { + while (this.cards.length) + this.removeCard(0); + this.cards = []; + } + +} + +// Contians all used cards in the order that they were discarded +class Grave extends CardContainer { + constructor() { + super() + } + + // Override + addCard(card) { + super.addCard(card, this.cards.length); + } + + // Override + removeCard(card) { + let n = isNumber(card) ? card : this.cards.indexOf(card); + return super.removeCard(card, n); + } +} + +// Contians all special cards for a given row +class RowSpecial extends CardContainer { + constructor(elem, row) { + super() + this.row = row; + } + + // Override + addCard(card) { + super.addCard(card, this.cards.length); + } + + // Override + removeCard(card) { + let n = isNumber(card) ? card : this.cards.indexOf(card); + if (card.removed) { + for (let x of card.removed) + x(card); + } + return super.removeCard(card, n); + } + +} + +// Contains a randomized set of cards to be drawn from +class Deck extends CardContainer { + constructor(faction) { + super(); + this.faction = faction; + } + + // Creates duplicates of cards with a count of more than one, then initializes deck + initializeFromID(card_id_list, player) { + this.initialize(card_id_list.reduce((a, c) => a.concat(clone(c.count, c)), []), player); + + function clone(n, elem) { + for (var i = 0, a = []; i < n; ++i) a.push(elem); + return a; + } + } + + // Populates a this deck with a list of card data and associated those cards with the owner of this deck. + initialize(card_data_list, player) { + for (let i = 0; i < card_data_list.length; ++i) { + let card = new Card(card_data_list[i].index, card_dict[card_data_list[i].index], player); + card.holder = player; + this.addCardRandom(card); + } + } + + // Override + addCard(card) { + this.addCardRandom(card); + } + + // Sends the top card to the passed hand + async draw(hand) { + if (hand === player_op.hand) + hand.addCard(this.removeCard(0)); + else + await board.toHand(this.cards[0], this); + } + + // Draws a card and sends it to the container before adding a card from the container back to the deck. + swap(container, card) { + container.addCard(this.removeCard(0)); + this.addCard(card); + } + + // Override + resize() { + + } + + // Override + reset() { + super.reset(); + } +} + +// Hand used by computer AI. Has an offscreen HTML element for card transitions. +class HandAI extends CardContainer { + constructor(tag) { + super(undefined, tag); + } + resize() { + + } +} + +// Hand used by current player +class Hand extends CardContainer { + constructor(elem, tag) { + super(); + this.tag = tag; + } + + // Override + addCard(card) { + let i = this.addCardSorted(card); + } + + // Override + resize() { + + } +} + +// Contains active cards and effects. Calculates the current score of each card and the row. +class Row extends CardContainer { + constructor() { + super(); + this.special = new RowSpecial(null, this); + this.total = 0; + this.effects = { + weather: false, + bond: {}, + morale: 0, + horn: 0, + mardroeme: 0, + shield: 0, + lock: 0, + toussaint_wine: 0 + }; + this.halfWeather = false; + } + + // Override + async addCard(card, runEffect = true) { + if (card.isSpecial()) { + this.special.addCard(card); + } else { + let index = this.addCardSorted(card); + this.resize(); + } + card.currentLocation = this; + if (this.effects.lock && card.isUnit() && card.abilities.length) { + card.locked = true; + this.effects.lock = Math.max(this.effects.lock - 1, 0); + let lock_card = this.special.findCard(c => c.abilities.includes("lock")); + // If several units arrive at the same time, it can be triggered several times, so we first remove the lock before doing animations + if (lock_card) + await board.toGrave(lock_card, this.special); + } + if (runEffect && !card.isLocked()) { + this.updateState(card, true); + for (let x of card.placed) + await x(card, this); + } + //this.updateScore(); + // Let's update all rows for better accuracy + board.updateScores(); + } + + // Override + removeCard(card, runEffect = true) { + if (isNumber(card) && card === -1) { + card = this.special.cards[0]; + this.special.reset(); + return card; + } + card = isNumber(card) ? this.cards[card] : card; + if (card.isSpecial()) { + this.special.removeCard(card); + } else { + super.removeCard(card); + card.resetPower(); + card.locked = false; + } + this.updateState(card, false); + if (runEffect) { + if (!card.decoyTarget) { + for (let x of card.removed) + x(card); + } else { + card.decoyTarget = false; + } + + } + this.updateScore(); + return card; + } + + // Updates a card's effect on the row + updateState(card, activate) { + for (let x of card.abilities) { + if (!card.isLocked()) { + switch (x) { + case "morale": + case "horn": + case "mardroeme": + case "lock": + case "toussaint_wine": + this.effects[x] += activate ? 1 : -1; + break; + case "shield": + case "shield_c": + case "shield_r": + case "shield_s": + this.effects["shield"] += activate ? 1 : -1; + break; + case "bond": + if (!this.effects.bond[card.target]) + this.effects.bond[card.target] = 0; + this.effects.bond[card.target] += activate ? 1 : -1; + break; + } + } + } + } + + // Activates weather effect and visuals + addOverlay(overlay) { + this.effects.weather = true; + this.updateScore(); + } + + // Deactivates weather effect and visuals + removeOverlay(overlay) { + this.effects.weather = false; + this.updateScore(); + } + + // Override + resize() { + + } + + // Updates the row's score by summing the current power of its cards + updateScore() { + let total = 0; + for (let card of this.cards) { + total += this.cardScore(card); + } + + let player = this.getRowIndex() < 3 ? player_op : player_me; + player.updateTotal(total - this.total); + this.total = total; + } + + // Calculates and set the card's current power + cardScore(card) { + let total = this.calcCardScore(card); + card.setPower(total); + return total; + } + + // Calculates the current power of a card affected by row affects + calcCardScore(card) { + if (card.key === "spe_decoy") + return 0; + let total = card.basePower; + if (card.hero) + return total; + if (card.abilities.includes("spy")) + total = Math.floor(game.spyPowerMult * total); + // Inspire - changes base strength, before weather + if (card.abilities.includes("inspire") && !card.isLocked()) { + let inspires = card.holder.getAllRowCards().filter(c => !c.isLocked() && c.abilities.includes("inspire")); + if (inspires.length > 1) { + let maxBase = inspires.reduce((a, b) => a.basePower > b.basePower ? a : b); + total = maxBase.basePower; + } + } + if (this.effects.weather) + if (this.halfWeather) + total = Math.max(Math.min(1, total), Math.floor(total / 2)); // 2 special cases, if intially 1, we want to keep one, not 0 (floor(0.5)). If 0, we want to keep 0, not 1 + else + total = Math.min(1, total); + // Bond + let bond = this.effects.bond[card.target]; + if (isNumber(bond) && bond > 1 && !card.isLocked()) + total *= Number(bond); + // Morale + total += Math.max(0, this.effects.morale + (card.abilities.includes("morale") ? -1 : 0)); + // Toussiant Wine + total += Math.max(0, 2 * this.effects.toussaint_wine); + // Witcher Schools + if (card.abilities.at(-1) && card.abilities.at(-1).startsWith("witcher_") && !card.isLocked()) { + let school = card.abilities.at(-1); + if (card.holder.effects["witchers"][school]) { + total += (card.holder.effects["witchers"][school] - 1) * 2; + } + } + // Whorshipped + if (card.abilities.includes("whorshipped") && card.holder.effects["whorshippers"] > 0 && !card.isLocked()) + total += card.holder.effects["whorshippers"] * game.whorshipBoost; + // Horn + if (this.effects.horn - (card.abilities.includes("horn") ? 1 : 0) > 0) + total *= 2; + return total; + } + + // Applies a temporary leader horn affect that is removed at the end of the round + async leaderHorn(card) { + if (this.special.containsCardByKey("spe_horn")) + return; + let horn = new Card("spe_horn", card_dict["spe_horn"], card.holder); + await this.addCard(horn); + game.roundEnd.push(() => this.removeCard(horn)); + } + + // Applies a local scorch effect to this row + async scorch() { + if (this.total >= 10 && !this.isShielded() && !game.scorchCancelled) + await Promise.all(this.maxUnits().map(async c => { + await board.toGrave(c, this); + })); + } + + // Removes all cards and effects from this row + clear() { + this.special.cards.filter(c => !c.noRemove).forEach(async c => await board.toGrave(c, this)); + this.cards.filter(c => !c.noRemove).forEach(async c => await board.toGrave(c, this)); + } + + // Returns all regular unit cards with the heighest power + maxUnits() { + let max = []; + for (let i = 0; i < this.cards.length; ++i) { + let card = this.cards[i]; + if (!card.isUnit()) + continue; + if (!max[0] || max[0].power < card.power) + max = [card]; + else if (max[0].power === card.power) + max.push(card); + } + return max; + } + + minUnits() { + let min = []; + for (let i = 0; i < this.cards.length; ++i) { + let card = this.cards[i]; + if (!card.isUnit()) + continue; + if (!min[0] || min[0].power > card.power) + min = [card]; + else if (min[0].power === card.power) + min.push(card); + } + return min; + } + + // Override + reset() { + super.reset(); + this.special.reset(); + this.total = 0; + this.effects = { + weather: false, + bond: {}, + morale: 0, + horn: 0, + mardroeme: 0, + shield: 0, + lock: 0, + toussaint_wine: 0 + }; + } + + // Indicates whether or not a shield is protecting that row from abilities (does not protect from weather effects though) + isShielded() { + return (this.effects.shield > 0); + } + + // True if at least 1 unit and total of power >= 10 + canBeScorched() { + if (game.scorchCancelled) + return false; + return (this.cards.reduce((a, c) => a + c.power, 0) >= 10) && (this.cards.filter(c => c.isUnit()).length > 0); + } + + // Return the index of the current row in the list of rows on the board + getRowIndex() { + for (let i = 0; i < board.row.length; i++) { + if (board.row[i] === this) + return i; + } + return -1; + } + + // Returns the opposite Row object - the one on the opponent's side of the field + getOppositeRow() { + let index = 5 - this.getRowIndex(); + if (index >= 0 && index < board.row.length) + return board.row[index] + return null; + } + + // Returns the row type as one of "close" / "ranged" / "siege" + getRowType() { + let idx = this.getRowIndex(); + switch (idx) { + case 0: + case 5: + return "siege"; + case 1: + case 4: + return "ranged"; + case 2: + case 3: + return "close"; + } + return "unknown"; + } +} + +// Handles how weather effects are added and removed +class Weather extends CardContainer { + constructor() { + super(); + this.types = { + rain: { + name: "rain", + count: 0, + rows: [] + }, + fog: { + name: "fog", + count: 0, + rows: [] + }, + frost: { + name: "frost", + count: 0, + rows: [] + } + } + let i = 0; + for (let key of Object.keys(this.types)) + this.types[key].rows = [board.row[i], board.row[5 - i++]]; + } + + // Adds a card if unique and clears all weather if 'clear weather' card added + async addCard(card, withEffects = true) { + super.addCard(card); + if (!withEffects) + return; + if (card.key === "spe_clear") { + this.clearWeather(); + } else { + this.changeWeather(card, x => ++this.types[x].count === 1, (r, t) => r.addOverlay(t.name)); + for (let i = this.cards.length - 2; i >= 0; --i) { + if (card.abilities.at(-1) === this.cards[i].abilities.at(-1)) { + await board.toGrave(card, this); + break; + } + } + } + } + + // Override + removeCard(card, withEffects = true) { + card = super.removeCard(card); + if (withEffects) + this.changeWeather(card, x => --this.types[x].count === 0, (r, t) => r.removeOverlay(t.name)); + return card; + } + + // Checks if a card's abilities are a weather type. If the predicate is met, perfom the action + // on the type's associated rows + changeWeather(card, predicate, action) { + for (let x of card.abilities) { + if (x in this.types && predicate(x)) { + for (let r of this.types[x].rows) + action(r, this.types[x]); + } + } + } + + // Removes all weather effects and cards + async clearWeather() { + await Promise.all(this.cards.map((c, i) => this.cards[this.cards.length - i - 1]).map(c => board.toGrave(c, this))); + } + + // Override + reset() { + super.reset(); + Object.keys(this.types).map(t => this.types[t].count = 0); + } +} + +// +class Board { + constructor() { + this.op_score = 0; + this.me_score = 0; + this.row = []; + for (let x = 0; x < 6; ++x) { + this.row[x] = new Row(); + } + } + + // Get the opponent of this Player + opponent(player) { + return player === player_me ? player_op : player_me; + } + + // Sends and translates a card from the source to the Deck of the card's holder + async toDeck(card, source) { + await this.moveTo(card, "deck", source); + } + + // Sends and translates a card from the source to the Grave of the card's holder + async toGrave(card, source) { + await this.moveTo(card, "grave", source); + } + + // Sends and translates a card from the source to the Hand of the card's holder + async toHand(card, source) { + await this.moveTo(card, "hand", source); + } + + // Sends and translates a card from the source to Weather + async toWeather(card, source) { + await this.moveTo(card, weather, source); + } + + // Sends and translates a card from the source to the Deck of the card's combat row + async toRow(card, source) { + let row = (card.row === "agile") ? "close" : card.row ? card.row : "close"; + await this.moveTo(card, row, source); + } + + // Sends and translates a card from the source to a specified row name or CardContainer + async moveTo(card, dest, source=null) { + if (isString(dest)) dest = this.getRow(card, dest); + if (dest instanceof Row || dest instanceof Weather) + await dest.addCard(source ? source.removeCard(card) : card); //Only the override in the Row/Weather classes are asynchronous + else + dest.addCard(source ? source.removeCard(card) : card); + } + + // Sends and translates a card from the source to a specified row name or CardContainer - NO EFFECTS/ABILITIES + async moveToNoEffects(card, dest, source=null) { + if (isString(dest)) dest = this.getRow(card, dest); + if (dest instanceof Row || dest instanceof Weather) + await dest.addCard(source ? source.removeCard(card, false) : card, false); //Only the override in the Row/Weather classes are asynchronous + else + dest.addCard(source ? source.removeCard(card) : card); + } + + // Sends and translates a card from the source to a row name associated with the passed player + async addCardToRow(card, row_name, player, source) { + let row; + if (row_name instanceof Row) { + row = row_name; + } else { + row = this.getRow(card, row_name, player); + } + await row.addCard(card); + } + + // Returns the Card associated with the row name that the card would be sent to + getRow(card, row_name, player) { + player = player ? player : card ? card.holder : player_me; + let isMe = player === player_me; + let isSpy = card.abilities.includes("spy"); + switch (row_name) { + case "weather": + return weather; + break; + case "close": + return this.row[isMe ^ isSpy ? 3 : 2]; + case "ranged": + return this.row[isMe ^ isSpy ? 4 : 1]; + case "siege": + return this.row[isMe ^ isSpy ? 5 : 0]; + case "grave": + return player.grave; + case "deck": + return player.deck; + case "hand": + return player.hand; + default: + console.error(card.name + " sent to incorrect row \"" + row_name + "\" by " + card.holder.name); + } + } + + // Updates which player currently is in the lead + updateLeader() { + let dif = player_me.total - player_op.total; + player_me.setWinning(dif > 0); + player_op.setWinning(dif < 0); + } + + updateScores() { + //this.row.map(r => r.cards.map(c => r.cardScore(c))); + this.row.map(r => r.updateScore()); + } +} + +class Game { + constructor() { + this.reset(); + this.randomOPDeck = true; + this.fullAI = false; + } + + reset() { + this.firstPlayer; + this.currPlayer = null; + + this.gameStart = []; + this.roundStart = []; + this.roundEnd = []; + this.turnStart = []; + this.turnEnd = []; + + this.roundCount = 0; + this.roundHistory = []; + this.over = false; + + this.randomRespawn = false; + this.medicCount = 1; + this.whorshipBoost = 1; + this.spyPowerMult = 1; + this.decoyCancelled = false; + this.scorchCancelled = false; + + // Also resetting some board/row properties affected during the course of a game + if (board) { + if (board.row) { + board.row.forEach(r => { + r.halfWeather = false; + }); + } + } + + weather.reset(); + board.row.forEach(r => r.reset()); + } + + // Sets up player faction abilities and psasive leader abilities + initPlayers(p1, p2) { + let l1 = ability_dict[p1.leader.abilities[0]]; + let l2 = ability_dict[p2.leader.abilities[0]]; + let special_abilities = { + emhyr_whiteflame: false, + meve_white_queen: false + }; + if (l1 === ability_dict["emhyr_whiteflame"] || l2 === ability_dict["emhyr_whiteflame"]) { + p1.disableLeader(); + p2.disableLeader(); + special_abilities["emhyr_whiteflame"] = true; + } else { + initLeader(p1, l1); + initLeader(p2, l2); + if (l1 === ability_dict["meve_white_queen"] || l2 === ability_dict["meve_white_queen"]) + special_abilities["meve_white_queen"] = true; + } + if (p1.deck.faction === p2.deck.faction && p1.deck.faction === "scoiatael") + return special_abilities; + initFaction(p1); + initFaction(p2); + + function initLeader(player, leader) { + if (leader.placed) + leader.placed(player.leader); + Object.keys(leader).filter(key => game[key]).map(key => game[key].push(leader[key])); + } + + function initFaction(player) { + //Only passive faction abilities + if (factions[player.deck.faction] && factions[player.deck.faction].factionAbility && !factions[player.deck.faction].activeAbility) + factions[player.deck.faction].factionAbility(player); + } + + return special_abilities; + } + + // Sets initializes player abilities, player hands and redraw + async startGame() { + this.gameTracker = new GameTracker(player_me, player_op); + let special_abilities = this.initPlayers(player_me, player_op); + await Promise.all([...Array(10).keys()].map(async () => { + await player_me.deck.draw(player_me.hand); + await player_op.deck.draw(player_op.hand); + })); + + await this.runEffects(this.gameStart); + if (!this.firstPlayer) + this.firstPlayer = await this.coinToss(); + await this.initialRedraw(); + return this.gameTracker; + } + + // Simulated coin toss to determine who starts game + async coinToss() { + this.firstPlayer = (Math.random() < 0.5) ? player_me : player_op; + return this.firstPlayer; + } + + // Allows the player to swap out up to two cards from their iniitial hand + async initialRedraw() { + for (let i = 0; i < 2; i++) { + player_op.controller.redraw(); + player_me.controller.redraw(); + } + await game.startRound(); + } + + // Initiates a new round of the game + async startRound(verdict = false) { + this.roundCount++; + if (verdict && verdict.winner) { + //Last round winner starts the round + this.currPlayer = verdict.winner.opponent(); + } else { + this.currPlayer = (this.roundCount % 2 === 0) ? this.firstPlayer : this.firstPlayer.opponent(); + } + player_me.roundStartReset(); + player_op.roundStartReset(); + + await this.runEffects(this.roundStart); + + board.row.map(r => r.updateScore()); + + if (!player_me.canPlay()) + player_me.setPassed(true); + if (!player_op.canPlay()) + player_op.setPassed(true); + + this.gameTracker.startRound(); + + if (player_op.passed && player_me.passed) + return await this.endRound(); + + if (this.currPlayer.passed) + this.currPlayer = this.currPlayer.opponent(); + + await this.startTurn(); + } + + // Starts a new turn. Enables client interraction in client's turn. + async startTurn() { + await this.runEffects(this.turnStart); + if (!this.currPlayer.opponent().passed) { + this.currPlayer = this.currPlayer.opponent(); + } + await this.currPlayer.startTurn(); + } + + // Ends the current turn and may end round. Disables client interraction in client's turn. + async endTurn() { + await this.runEffects(this.turnEnd); + board.updateScores(); + this.gameTracker.endTurn(); + if (player_op.passed && player_me.passed) { + await this.endRound(); + } else { + await this.startTurn(); + } + } + + // Ends the round and may end the game. Determines final scores and the round winner. + async endRound() { + let dif = player_me.total - player_op.total; + if (dif === 0) { + let nilf_me = player_me.deck.faction === "nilfgaard", + nilf_op = player_op.deck.faction === "nilfgaard"; + dif = nilf_me ^ nilf_op ? nilf_me ? 1 : -1 : 0; + } + let winner = dif > 0 ? player_me : dif < 0 ? player_op : null; + let verdict = { + winner: winner, + score_me: player_me.total, + score_op: player_op.total + } + + this.roundHistory.push(verdict); + + this.gameTracker.endRound(winner); + + await this.runEffects(this.roundEnd); + + player_me.endRound(dif > 0); + player_op.endRound(dif < 0); + if (player_me.health === 0 || player_op.health === 0) + this.over = true; + + board.row.forEach(row => row.clear()); + weather.clearWeather(); + + if (dif > 0) { + } else if (dif < 0) { + if (nilfgaard_wins_draws) { + nilfgaard_wins_draws = false; + } + } + + if (player_me.health === 0 || player_op.health === 0) + await this.endGame(); + else + await this.startRound(verdict); + } + + // Sets up and displays the end-game screen + async endGame() { + + if (player_op.health <= 0 && player_me.health <= 0) { + this.gameTracker.endGame(null); + } else if (player_op.health === 0) { + this.gameTracker.endGame(player_me); + } else { + this.gameTracker.endGame(player_op); + } + } + + // Returns the client to the deck customization screen + returnToCustomization() { + this.reset(); + player_me.reset(); + player_op.reset(); + } + + // Restarts the last game with the same decks + async restartGame() { + this.reset(); + player_me.reset(); + player_op.reset(); + await this.startGame(); + return this.gameTracker; + } + + // Executes effects in list. If effect returns true, effect is removed. + async runEffects(effects) { + for (let i = effects.length - 1; i >= 0; --i) { + let effect = effects[i]; + if (await effect()) + effects.splice(i, 1) + } + } + +} + +// Contians information and behavior of a Card +class Card { + + constructor(key, card_data, player) { + if (!card_data) { + console.log("Invalid card data for: " + key); + } + this.id; + if (card_data.id) + this.id = Number(card_data.id); + this.key = key; + this.name = card_data.name; + this.basePower = this.power = Number(card_data.strength); + this.faction = card_data.deck; + // To clean the field in case it is a faction specific weather/special card + if (this.faction.startsWith("weather") || this.faction.startsWith("special")) { + this.faction = this.faction.split(" ")[0]; + } + this.abilities = (card_data.ability === "") ? [] : card_data.ability.split(" "); + this.row = (this.faction === "weather") ? this.faction : card_data.row; + this.filename = card_data.filename; + this.placed = []; + this.removed = []; + this.activated = []; + this.holder = player; + this.locked = false; + this.decoyTarget = false; + this.target = ""; + this.currentLocation = board; // By default, updated later + if ("target" in card_data) { + this.target = card_data.target; + } + this.quote = ""; + if ("quote" in card_data) { + this.quote = card_data.quote; + } + + this.hero = false; + if (this.abilities.length > 0) { + if (this.abilities[0] === "hero") { + this.hero = true; + this.abilities.splice(0, 1); + } + for (let x of this.abilities) { + let ab = ability_dict[x]; + if ("placed" in ab) this.placed.push(ab.placed); + if ("removed" in ab) this.removed.push(ab.removed); + if ("activated" in ab) this.activated.push(ab.activated); + } + } + } + + // Returns the identifier for this type of card + getId() { + return this.key; + } + + // Sets and displays the current power of this card + setPower(n) { + if (this.key === "spe_decoy") + return; + if (n !== this.power) { + this.power = n; + } + } + + // Resets the power of this card to default + resetPower() { + this.setPower(this.basePower); + } + + // Automatically sends and translates this card to its apropriate row from the passed source + async autoplay(source) { + await board.toRow(this, source); + } + + // Animates an ability effect + async animate(name, bFade = true, bExpand = true) { + + } + + // Animates the scorch effect + async scorch(name) { + + } + + // Returns true if this is a combat card that is not a Hero + isUnit() { + return !this.hero && (this.row === "close" || this.row === "ranged" || this.row === "siege" || this.row === "agile"); + } + + // Returns true if card is sent to a Row's special slot + isSpecial() { + return ["spe_horn", "spe_mardroeme", "spe_sign_quen", "spe_sign_yrden", "spe_toussaint_wine", "spe_lyria_rivia_morale", "spe_wyvern_shield", "spe_mantlet", "spe_garrison", "spe_dimeritium_shackles"].includes(this.key); + } + + // Compares by type then power then name + static compare(a, b) { + let dif = factionRank(a) - factionRank(b); + if (dif !== 0) + return dif; + // Muster/Bond cards + if (a.target && b.target && a.target === b.target) { + if (a.id && b.id) + return Number(a.id) - Number(b.id); + if (a.key && b.key) + return a.key.localeCompare(b.key); + } + dif = a.basePower - b.basePower; + if (dif && dif !== 0) + return dif; + + return a.name.localeCompare(b.name); + + function factionRank(c) { + return c.faction === "special" ? -2 : (c.faction === "weather") ? -1 : 0; + } + } + + // Indicates whether or not the abilities of this card are locked + isLocked() { + return this.locked; + } +} + +// Handles notifications and client interration with menus +class UI { + constructor() { + this.previewCard = null; + this.lastRow = null; + } + + + // Enables or disables client interration + enablePlayer(enable) { + + } + + + // Called when the player selects a selectable card + async selectCard(card) { + let row = this.lastRow; + let pCard = this.previewCard; + if (card === pCard) + return; + if (pCard === null || card.holder.hand.cards.includes(card)) { + this.showPreview(card); + } else if (pCard.abilities.includes("decoy")) { + this.hidePreview(card); + card.decoyTarget = true; + board.toHand(card, row); + await board.moveTo(pCard, row, pCard.holder.hand); + await pCard.holder.endTurn(); + } else if (pCard.abilities.includes("alzur_maker")) { + this.hidePreview(card); + await board.toGrave(card, row); + let target = new Card(ability_dict["alzur_maker"].target, card_dict[ability_dict["alzur_maker"].target], card.holder); + await board.addCardToRow(target, target.row, card.holder); + await pCard.holder.endTurn(); + } + } + + // Called when the player selects a selectable CardContainer + async selectRow(row, isSpecial = false) { + this.lastRow = row; + if (this.previewCard === null) { + return; + } + if (this.previewCard.key === "spe_decoy" || this.previewCard.abilities.includes("alzur_maker")) + return; + if (this.previewCard.abilities.includes("decoy") && row.cards.filter(c => c.isUnit()).length > 0) + return; // If a unit can be selected, we cannot select the whole row + let card = this.previewCard; + let holder = card.holder; + this.hidePreview(); + if (card.faction === "special" && card.abilities.includes("scorch")) { + this.hidePreview(); + if (!game.scorchCancelled) + await ability_dict["scorch"].activated(card); + } else if (card.faction === "special" && card.abilities.includes("cintra_slaughter")) { + this.hidePreview(); + await ability_dict["cintra_slaughter"].activated(card); + } else if (card.faction === "special" && card.abilities.includes("seize")) { + this.hidePreview(); + await ability_dict[card.abilities.at(-1)].activated(card); + } else if (card.faction === "special" && card.abilities.includes("knockback")) { + this.hidePreview(); + await ability_dict[card.abilities.at(-1)].activated(card, row); + } else if (card.key === "spe_decoy" || card.abilities.includes("alzur_maker")) { + return; + } else if (card.abilities.includes("decoy") && row.cards.filter(c => c.isUnit()).length > 0) { + return; // If a unit can be selected, we cannot select the whole row + } else if (card.abilities.includes("anna_henrietta_duchess")) { + this.hidePreview(card); + let horn = row.special.cards.filter(c => c.abilities.includes("horn"))[0]; + if (horn) + await board.toGrave(horn, row); + } else if (card.key === "spe_lyria_rivia_morale") { + await board.moveTo(card, row); + } else if (card.abilities.includes("meve_princess") || card.abilities.includes("carlo_varese")) { + this.hidePreview(card); + if (!game.scorchCancelled) + await row.scorch(); + } else if (card.abilities.includes("cyrus_hemmelfart")) { + this.hidePreview(card); + let new_card = new Card("spe_dimeritium_shackles", card_dict["spe_dimeritium_shackles"], card.holder); + await board.moveTo(new_card, row); + } else if (card.faction === "special" && card.abilities.includes("bank")) { + this.hidePreview(); + await ability_dict["bank"].activated(card); + } else { + await board.moveTo(card, row, card.holder.hand); + } + await holder.endTurn(); + } + + // Called when the client cancels out of a card-preview + cancel() { + this.hidePreview(); + } + + // Displays a card preview then enables and highlights potential card destinations + showPreview(card) { + this.showPreviewVisuals(card); + } + + // Sets up the graphics and description for a card preview + showPreviewVisuals(card) { + this.previewCard = card; + } + + // Hides the card preview then disables and removes highlighting from card destinations + hidePreview() { + this.previewCard = null; + this.lastRow = null; + } + + // Displayed a timed notification to the client + async notification(name, duration) { + + } + + async queueCarousel(container, count, action, predicate, bSort, bQuit, title) { + + } + +} + +// Screen used to customize, import and export deck contents +class DeckMaker { + constructor() { + this.start_me_deck; + this.start_op_deck; + this.me_deck_index = 0; + this.op_deck_index = 0; + } + + + // Verifies current deck, creates the players and their decks, then starts a new game + async startNewGame(deck1, deck2) { + this.selectDeck(deck1); + this.selectOPDeck(deck2); + + player_me = new Player(0, "Player 1", this.start_me_deck, true); + player_op = new Player(1, "Player 2", this.start_op_deck, true); + if (game.gameTracker) + return await game.restartGame(); + return await game.startGame(); + } + + // Select a premade deck + selectDeck(deck) { + this.start_me_deck = JSON.parse(JSON.stringify(deck)); + this.start_me_deck.cards = this.start_me_deck.cards.map(c => ({ + index: c[0], + count: c[1] + })); + this.start_me_deck.leader = { index: this.start_me_deck.leader, card: card_dict[this.start_me_deck.leader] }; + } + + selectOPDeck(deck) { + //this.start_op_deck = JSON.parse(JSON.stringify(premade_deck[i - 1])); + this.start_op_deck = JSON.parse(JSON.stringify(deck)); + this.start_op_deck.cards = this.start_op_deck.cards.map(c => ({ + index: c[0], + count: c[1] + })); + this.start_op_deck.leader = { index: this.start_op_deck.leader, card: card_dict[this.start_op_deck.leader] }; + } +} + +// Returns true if n is an Number +function isNumber(n) { + return !isNaN(parseFloat(n)) && isFinite(n); +} + +// Returns true if s is a String +function isString(s) { + return typeof (s) === 'string' || s instanceof String; +} + +// Returns a random integer in the range [0,n) +function randomInt(n) { + return Math.floor(Math.random() * n); +} + +// Pauses execution until the passed number of milliseconds as expired +function sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); +} + +// Suspends execution until the predicate condition is met, checking every ms milliseconds +function sleepUntil(predicate, ms) { + return new Promise(resolve => { + let timer = setInterval(function () { + if (predicate()) { + clearInterval(timer); + resolve(); + } + }, ms) + }); +} + +function tocar() { + +} + +/*----------------------------------------------------*/ +function setTimeout(callback, time) { + try { + callback(); + } catch (e) { } +} + +function simulateGame() { + +} +/*----------------------------------------------------*/ + +var ui = new UI(); +var board = new Board(); +var weather = new Weather(); +var game = new Game(); +var player_me, player_op; + +let dm = new DeckMaker(); + +window.onload = function () { + // Init decks list + for (var i = 0; i < premade_deck.length; i++) { + let el1 = document.createElement("option"); + el1.setAttribute("value",String(i)); + el1.innerText = premade_deck[i]["title"]; + document.getElementById("deck-1").appendChild(el1); + + let el2 = document.createElement("option"); + el2.setAttribute("value",String(i)); + el2.innerText = premade_deck[i]["title"]; + document.getElementById("deck-2").appendChild(el2); + } + + document.getElementById("launch").addEventListener("click", async function () { + let d1 = document.getElementById("deck-1").value; + let d2 = document.getElementById("deck-2").value; + let nbSims = parseInt(document.getElementById("nb-sims").value); + + let res_list = []; + let stats = { "me": 0, "op": 0, "draw": 0 }; + let abStats = {}; + for (var i = 0; i < nbSims; i++) { + res_list.push(await dm.startNewGame(premade_deck[d1], premade_deck[d2])); + let res = res_list.at(-1); + let resElem = document.createElement("div"); + if (res.winner) { + stats[res.winner.tag]++; + resElem.innerHTML = `(${res.player1.deck_data.title} vs ${res.player2.deck_data.title}) Winner: Player "${res.winner.tag}" - Scores: ${res.getScores()}`; + } else { + stats["draw"]++; + resElem.innerHTML = `(${res.player1.deck_data.title} vs ${res.player2.deck_data.title}) Draw - Scores: ${res.getScores()}`; + } + document.getElementById("sim-results").appendChild(resElem); + if (i === 0) { + res.rounds.forEach(r => { + r.turns.forEach(t => { + console.log(t.summary()); + }); + }); + console.log(res); + + //console.log(res.getCardImpacts()); + } + let imp_stats = res.getAbilitiesImpact(); + Object.keys(imp_stats).forEach(key => { + if (!abStats[key]) + abStats[key] = []; + abStats[key] = abStats[key].concat(imp_stats[key]); + }); + } + let resElem = document.createElement("div"); + resElem.innerHTML = `Total: Player 1: ${stats["me"]} wins (${100 * (stats["me"] / nbSims)}%) - Player 2: ${stats["op"]} wins (${100 * (stats["op"] / nbSims)}%) - Draws: ${stats["draw"]}` + document.getElementById("sim-results").appendChild(resElem); + + Object.keys(abStats).forEach(key => { + if (abStats[key].length > 0) + console.log(key + " => " + (abStats[key].reduce((a, b) => a + b) / abStats[key].length)); + }); + + /*res.rounds.forEach(r => { + r.turns.forEach(t => { + console.log(t.summary()); + }); + });*/ + //console.log(res); + }); + + document.getElementById("launch-all").addEventListener("click", async function () { + let nbSims = parseInt(document.getElementById("nb-sims").value); + + let stats = []; + let deck_stats = []; + let abStats = {}; + for (var d1 = 0; d1 < premade_deck.length; d1++) { + let row_stats = []; + for (var d2 = 0; d2 < premade_deck.length; d2++) { + let curr_stats = { "me": 0, "op": 0, "draw": 0 }; + for (var i = 0; i < nbSims; i++) { + console.log(premade_deck[d1]["title"] + " vs " + premade_deck[d2]["title"]); + let res = await dm.startNewGame(premade_deck[d1], premade_deck[d2]) + try { + if (res.winner) { + curr_stats[res.winner.tag]++; + } else { + curr_stats["draw"]++; + } + let imp_stats = res.getAbilitiesImpact(); + Object.keys(imp_stats).forEach(key => { + if (!abStats[key]) + abStats[key] = []; + abStats[key] = abStats[key].concat(imp_stats[key]); + }); + } catch (e) { + console.log(e); + } + } + row_stats.push(curr_stats); + } + stats.push(row_stats); + } + + let table = document.createElement("table"); + table.setAttribute("id", "all-table-results"); + let row = document.createElement("tr"); + + // Corner cell + let th = document.createElement("th"); + th.innerText = "/"; + row.appendChild(th); + for (var i = 0; i < premade_deck.length; i++) { + let th = document.createElement("th"); + th.innerText = premade_deck[i]["title"]; + deck_stats.push(0); + row.appendChild(th); + } + table.appendChild(row); + for (var i = 0; i < premade_deck.length; i++) { + row = document.createElement("tr"); + // Deck name + let td = document.createElement("td"); + td.innerText = premade_deck[i]["title"]; + row.appendChild(td); + for (var j = 0; j < premade_deck.length; j++) { + let td = document.createElement("td"); + let st = stats[i][j]; + td.innerText = `${st["me"]} wins (${100 * (st["me"] / nbSims)}%)`; + deck_stats[i] += st["me"]; + deck_stats[j] += st["op"]; + row.appendChild(td); + } + table.appendChild(row); + } + row = document.createElement("tr"); + let td = document.createElement("td"); + td.innerText = "TOTAL"; + row.appendChild(td); + for (var i = 0; i < premade_deck.length; i++) { + let th = document.createElement("th"); + th.innerText = `${deck_stats[i]} wins (${100 * (deck_stats[i] / (2 * nbSims * premade_deck.length - nbSims))}%)`; + row.appendChild(th); + } + table.appendChild(row); + document.getElementById("sim-results").appendChild(table); + + Object.keys(abStats).forEach(key => { + if (abStats[key].length > 0) + console.log(key + " => " + (abStats[key].reduce((a, b) => a + b) / abStats[key].length)); + }); + + }); +} diff --git a/style.css b/style.css new file mode 100644 index 0000000..a6d4f97 --- /dev/null +++ b/style.css @@ -0,0 +1,2462 @@ +* { + box-sizing: border-box; + cursor: url(img/icons/cursor.png), auto; +} + +html, +body { + width: 100%; + height: 100%; + margin: 0; + padding: 0; + overflow-X: visible; + scrollbar-width: none; +} + +body { + font-size: 0; + font-family: Arial Narrow, sans-serif; + color: goldenrod; + background-color: #000; +} + +body::-webkit-scrollbar { + display: none; +} + +main { + position: absolute; + width: 100%; + height: calc(100vw * 1080 / 1920); + background-image: url(img/board.jpg); + background-size: 100% auto; + background-repeat: no-repeat; +} + +a:hover, label:hover, .hover_un:hover { + text-decoration:underline; +} + +div.abs { + position:fixed; + width: 100%; + height: 100%; + z-index: 2000; +} + +#very_start_bg1 { + background-image: url(img/start.jpg); + background-size: 100% auto; + background-repeat: no-repeat; +} + +#very_start_bg2 { + top: 3%; + left: 2%; + width: 32%; + height: 94%; + border: solid 4px white; +} + +#very_start { + position:absolute; + height:auto; + font-size: 20px; + color: #FFF; + z-index: 3000; + text-align: center; + font-weight: bold; +} + +::selection { + background: transparent; +} + +::-moz-selection { + background: transparent; +} + +::-webkit-scrollbar { + width: 1.5vw; +} + +::-webkit-scrollbar-thumb { + background: #5559; + border-radius: .5vw; + height: 3vw; + border: .35vw double #000; +} + +::-webkit-scrollbar-track { + background: #131313; +} + +html { + scrollbar-color: #5559 #131313; +} + +#click-background { + position: fixed; + width: 100%; + height: 100%; + z-index: 1; +} + +#hand-op { + position: absolute; + height: 6.35vw; + width: 4.45vw; + top: -7vw; + left: 33vw; + border: 1px solid blue; +} + +#hand-op .card { + position: absolute; +} + +#youtube { + position: fixed; + height: 10px; + width: 10px; + display: hidden; + z-index: -100; +} + +#toggle-music { + position: absolute; + top: 45.6vw; + left: 26vw; + width: 2vw; + height: 3vw; + font-size: 3vw; + color: goldenrod; + text-shadow: 0 0 2vw #000; + z-index: 86; +} + +.music-customization { + transform: translate(22.5vw, -.5vw); +} + +#notification-bar { + position: absolute; + width: 100%; + height: 14%; + top: 43%; + background-color: rgba(10, 10, 10, .95); + z-index: 100; +} + +#notification-bar>div { + width: 22.1%; + height: 207.25%; + top: -66.6%; + left: 22.55%; + position: absolute; + background-repeat: no-repeat; + background-size: contain; + background-position: center; +} + +#notification-bar>div::after { + position: absolute; + left: 100.5%; + top: 32.1%; + width: 205%; + height: 47.25%; + color: goldenrod; + font-size: 1.6vw; + text-align: left; + font-weight: 700; + display: flex; + align-items: center; + white-space: pre; +} + +#notif-nilfgaard-wins-draws { + background-image: url(img/icons/notif_nilfgaard.png); +} + +#notif-nilfgaard-wins-draws::after { + content: "Nilfgaard wins draws"; +} + +#notif-op-leader::after { + content: "Opponent uses leader"; +} + +#notif-op-white-flame { + background-image: url(img/icons/notif_nilfgaard.png); +} + +#notif-op-white-flame::after { + content: "The opponent's leader cancel \A your opponent's Leader Ability"; +} + +#notif-meve_white_queen { + background-image: url(img/icons/notif_lyria_rivia.png); +} + +#notif-meve_white_queen::after { + content: "Lyria & Rivia leader allows both players to restore \A 2 units when using the medic ability."; +} + +#notif-me-first::after { + content: "You will go first"; +} + +#notif-op-first::after { + content: "Your opponent will go first"; +} + +#notif-me-coin { + background-image: url(img/icons/notif_me_coin.png); +} + +#notif-me-coin::after { + content: "You will go first"; +} + +#notif-op-coin { + background-image: url(img/icons/notif_op_coin.png); +} + +#notif-op-coin::after { + content: "Your opponent will go first"; +} + +#notif-round-start { + background-image: url(img/icons/notif_round_start.png); +} + +#notif-round-start::after { + content: "Round Start"; +} + +#notif-me-pass { + background-image: url(img/icons/notif_round_passed.png); +} + +#notif-me-pass::after { + content: "Round passed"; +} + +#notif-op-pass { + background-image: url(img/icons/notif_round_passed.png); +} + +#notif-op-pass::after { + content: "Your opponent has passed"; +} + +#notif-win-round { + background-image: url(img/icons/notif_win_round.png); +} + +#notif-win-round::after { + content: "You won the round!"; +} + +#notif-lose-round { + background-image: url(img/icons/notif_lose_round.png); +} + +#notif-lose-round::after { + content: "Your opponent won the round"; +} + +#notif-draw-round { + background-image: url(img/icons/notif_draw_round.png); +} + +#notif-draw-round::after { + content: "The round ended in a draw"; +} + +#notif-me-turn { + background-image: url(img/icons/notif_me_turn.png); +} + +#notif-me-turn::after { + content: "Your turn!"; +} + +#notif-op-turn { + background-image: url(img/icons/notif_op_turn.png); +} + +#notif-op-turn::after { + content: "Opponent's turn"; +} + +#notif-north, #notif-north-scorch-cancelled { + background-image: url(img/icons/notif_north.png); +} + +#notif-north::after { + content: "Northern Realms faction ability triggered: \A North draws an additional card."; +} + +#notif-north-scorch-cancelled::after { + content: "Northern Realms leader ability used: \A Scorch ability cancelled for the rest of the round."; +} + +#notif-monsters { + background-image: url(img/icons/notif_monsters.png); +} + +#notif-monsters::after { + content: "Monsters faction ability triggered \A monsters retake one card to their hand"; +} + +#notif-scoiatael { + background-image: url(img/icons/notif_scoiatael.png); +} + +#notif-scoiatael::after { + content: "Opponent used the Scoia'tael faction perk to go first."; +} + +#notif-skellige-op { + background-image: url(img/icons/notif_skellige.png); +} + +#notif-skellige-op::after { + content: "Opponent Skellige Ability Triggered!"; +} + +#notif-skellige-me { + background-image: url(img/icons/notif_skellige.png); +} + +#notif-skellige-me::after { + content: "Skellige Ability Triggered!"; +} + +#notif-witcher_universe { + background-image: url(img/icons/notif_witcher_universe.png); +} + +#notif-witcher_universe::after { + content: "Witcher Universe faction ability used: \A Turn skipped."; +} + +#notif-toussaint, #notif-toussaint-decoy-cancelled { + background-image: url(img/icons/notif_toussaint.png); +} + +#notif-toussaint::after{ + content: "Toussaint faction ability used: \A Toussaint draws an additional card."; +} + +#notif-toussaint-decoy-cancelled::after { + content: "Toussaint leader ability used: \A Decoy ability cancelled for the rest of the round."; +} + +#notif-lyria_rivia { + background-image: url(img/icons/notif_lyria_rivia.png); +} + +#notif-lyria_rivia::after { + content: "Lyria & Rivia faction ability used: \A Morale Boost effect applied to a row."; +} + +#notif-zerrikania { + background-image: url(img/icons/notif_zerrikania.png); +} + +#notif-zerrikania::after { + content: "Zerrikania faction ability used: \A Unit restored from the discard pile."; +} + +#notif-redenia { + background-image: url(img/icons/notif_redania.png); +} + +#notif-redania::after { + content: "Redania faction ability used: \A Turn skipped."; +} + +#notif-velen { + background-image: url(img/icons/notif_velen.png); +} + +#notif-velen::after { + content: "Velen faction ability triggered: \A Player draws a card."; +} + +.card-preview { + position: relative; + z-index: 80; +} + +.card-preview>.card-lg { + position: absolute; + top: 11.95vw; + left: 80.3vw; +} + +.card-preview>.card-description { + top: 43.1vw; + left: 67.95vw; +} + +.card-lg { + height: 30.4vw; + width: 16.1vw; + border-radius: 1.5vw; + background-size: contain; + background-position: top; + background-repeat: no-repeat; +} + +.card-description { + position: absolute; + height: 11vw; + /*width: 29.12vw;*/ + width: 40vw; + background-color: rgba(20, 20, 20, .95); + color: tan; + text-align: center; + pointer-events: none; + border: .1vw solid #ffffff57; + border-width: .1vw 0; +} + +.card-description>* { + position: relative; +} + +.card-description>div { + top: 1vw; + left: .9vw; + width: 1.95vw; + height: 1.95vw; + margin-bottom: -1.9vw; + background-size: cover; + background-position: center; +} + +.card-description>h1 { + font-weight: 700; + top: .5vw; + left: 16%; + height: 16%; + width: 70%; + margin-bottom: -2.1vw; + text-transform: capitalize; + font-size: 1vw; +} + +.card-description>p { + top: 16%; + left: 5%; + width: 90%; + height: 50%; + font-size: .9vw; +} + +#carousel { + position: absolute; + width: 100%; + height: calc(100vw * 1080 / 1920); + z-index: 90; +} + +#carousel>:nth-child(1) { + wdith: 100%; + heigth: 100%; + padding: 11.5% 10%; + display: flex; + align-items: flex-start; + justify-content: space-between; +} + +#carousel>:nth-child(1)>:nth-child(3) { + border: .3vw solid goldenrod; + box-shadow: 0 0 4vw goldenrod; + background-origin: border-box; +} + +#carousel>:nth-child(1)>:nth-child(3):hover { + border: .3vw solid goldenrod; + box-shadow: 0 0 4vw goldenrod; + background-origin: border-box; +} + +#carousel>:nth-child(1)>:nth-child(2n) { + width: 13.75vw; + height: 25.9vw; +} + +#carousel>:nth-child(1)>:nth-child(4n - 3) { + width: 11.3vw; + height: 21.3vw; + margin: 0 2.75%; +} + +#carousel .card-lg { + display: inline-block; + background-repeat: no-repeat; + background-size: contain; + background-position: top; + position: relative; +} + +#carousel .faction { + display: inline-block; + background-repeat: no-repeat; + background-size: cover; + background-position: top; + position: relative; +} + +#carousel .selection { + border: .3vw solid green; + box-shadow: 0 0 4vw green; + background-origin: border-box; +} + +.card-lg { + border: .1vw solid transparent; +} + +.card-lg:hover { + border: .1vw solid goldenrod; + box-shadow: 0 0 1vw goldenrod; +} + +.start-game_class:hover { + border: .1vw solid white; + box-shadow: 0 0 .1vw white; +} + +#no_hover:hover { + border: .1vw solid transparent; + box-shadow: none; +} + +#carousel .card-lg:hover { + background-origin: border-box; +} + +#carousel .card-description { + /*left: 35.35%;*/ + left: 30%; + top: 77%; +} + +#carousel>:nth-child(3) { + position: absolute; + width: 100%; + height: 7.5%; + top: 12%; + font-size: 1.75vw; + line-height: 250%; + background-color: rgba(10, 10, 10, .95); + text-align: center; + box-shadow: 0 0 1vw #ffffff54; +} + +/* Modal helpers */ + +#helper-box { + position: absolute; + top: 1vw; + width: 100%; + z-index: 1000; +} + +#helper-box>div { + border: .2vw ridge rgb(40, 40, 40); + padding: 0.7vw 1vw; + background-color: rgb(20, 20, 20); + color: gray; +} + +#helper-box-message { + text-align: center; + font-size: 1.5vw; + padding-top: .6vw; + color: lightgray; +} + +#help-box-close { + position: relative; + right: -0.4vw; + border: .2vw ridge rgb(40, 40, 40); + background-color: rgb(40, 40, 40); + color: gray; +} + +#help-box-close:hover { + background-color: rgb(60, 60, 60); +} +/* Popup */ +#popup, #number-popup { + position: absolute; + width: 100%; + height: calc(100vw * 1080 / 1920); + background-color: rgba(10, 10, 10, .95); + z-index: 1000; +} + +#popup>div, #number-popup>div { + margin-top: -89px; + width: 26.5%; + border: .2vw ridge rgb(40, 40, 40); + padding: 0 .5vw; + background-color: rgb(20, 20, 20); +} + +#popup h3, #number-popup h3 { + display: block; + font-size: 1.05vw; + text-transform: uppercase; + color: grey; + text-align: center; + line-height: 100%; +} + +#popup p, #number-popup p { + text-align: center; + font-size: 1.23vw; + padding-top: .6vw; + color: tan; +} + +#popup>div>div, #number-popup>div>div { + position: relative; + display: flex; + align-items: center; + justify-content: space-between; + padding: .2vw; + min-width: 10%; + width: fit-content; + margin: -1.4vw auto 0; + border: .2vw ridge rgb(25, 25, 25); + background-color: #000; + top: 1.3vw; +} + +#popup button, #number-popup button,input { + display: inline-block; + width: auto; + height: 1.8vw; + border: .2vw ridge rgb(20, 20, 20); + background-color: rgb(20, 20, 20); + font-size: 1vw; + text-shadow: 1vw 1vw 1vw #000; + text-transform: capitalize; + margin: 0 .3vw; +} + +#popup button:first-child, #number-popup button:last-child { + color: green; +} + +#popup button:last-child { + color: darkred; +} + +#number-popup-value { + width: 5vw; + color: white; +} + +#end-screen { + width: 100%; + height: calc(100vw * 1080 / 1920); + position: absolute; + z-index: 1000; + background-color: rgba(10, 10, 10, .95); +} + +#end-screen * { + position: relative; +} + +#end-screen>:nth-child(1) { + top: 12.6%; + left: 32.9%; + width: calc(100% * 656 / 1920); + height: calc(100% * 416 / 1080); + margin-bottom: -21.65%; + background-size: contain; +} + +.end-draw { + background-image: url(img/icons/end_draw.png); +} + +.end-win { + background-image: url(img/icons/end_win.png); +} + +.end-lose { + background-image: url(img/icons/end_lose.png); +} + +#end-screen>table { + top: 55%; + left: 7.6%; + width: 74%; + height: 22%; + margin-bottom: -12.3%; + table-layout: fixed; +} + +#end-screen tbody :first-child th { + font-size: .9vw; + text-align: center; + color: darkslategrey; + color: rgb(100, 100, 100); +} + +#end-screen td { + font-size: 1.7vw; + text-align: center; + color: rgb(180, 180, 180); +} + +#end-screen tr :first-child { + font-size: 1.2vw; + text-align: right; + color: darkorange; + padding-right: 5%; +} + +#end-screen>p { + top: 80%; + left: 30.1%; + width: 41%; + height: 3%; + font-size: 1.21vw; + color: rgb(180, 180, 180); +} + +#end-screen button { + position: absolute; + height: 3vw; + width: 10vw; + top: 87%; + font-family: Arial Narrow; + font-size: 1.5vw; + color: goldenrod; + background-color: #4c390a66; + border: .2vw solid #1d180b; + border-radius: 1vw; + box-shadow: 0 0 1vw #6d5210; +} + +#pass-button:hover, #toggle-music:hover { + text-shadow: 0 0 1vw #6d5210; +} + +#end-screen button:hover { + box-shadow: 0 0 2vw #6d5210; +} + +#end-screen button:nth-of-type(1) { + left: 35%; +} + +#end-screen button:nth-of-type(2) { + left: 55%; +} + +.panel { + display: inline-block; + height: 100%; + box-sizing: border-box; + overflow-y: hidden; + overflow-x: visible; + overflow-y: visible; + position: absolute; + height: calc(100vw * 1080 / 1920); +} + +.panel div, +.panel section, +.panel span { + position: relative; +} + +#panel-left { + width: 26.5%; +} + +#panel-mid { + width: 52.5%; + left: 26.5%; +} + +#panel-right { + width: 21%; + left: 79%; +} + +#weather { + top: 41.6%; + left: 27.8%; + width: 54.9%; + height: 12.75%; + margin-bottom: -27%; + z-index: 1; +} + +#arrangementWindow { + top: 41.6%; + left: 27.8%; + width: 54.9%; + height: 12.75%; + margin-bottom: -27%; + z-index: 10; + background-color: rgba(20, 20, 20, .9); + color: tan; +} + +#arrangementWindow-title { + top: 5%; + left: 0%; + width: 100%; + height: 25%; + text-align: center; + font-weight: bold; + font-size: 1.2vw; +} + +#arrangementWindow-movesTitle { + top: 0%; + left: 0%; + width: 100%; + height: 30%; + text-align: center; + font-weight: bold; + font-size: 1.6vw; +} + +#arrangementWindow-counter { + top: 0%; + left: 0%; + width: 100%; + height: 50%; + text-align: center; + font-weight: bold; + font-size: 2.6vw; +} + +#arrangementWindow-button { + bottom: 35%; + right: -88%; + width: 5%; + height: 5%; + text-align: center; + color: tan; + font-weight: bold; + font-size: 1.6vw; +} + +#arrangementWindow-button:hover { + color: green; +} + +.leader-box { + left: 27.5%; + width: 31.4%; + height: 12.5%; + margin-bottom: -26.25%; +} + +.leader-box .card { + pointer-events: none; +} + +.leader-box>.leader-container { + height: 100%; + width: 63%; + margin-bottom: -80%; + display: flex; + flex-items: center; + justify-content: center; +} + +.leader-box>div>.card { + position: absolute; + height: 98%; + width: 95%; + border-radius: .6vw; +} + +.leader-active { + top: 33%; + left: 75%; + height: 28%; + width: 24%; +} + +.leader-active>div { + background-image: url(img/icons/icon_leader_active.png); + background-size: cover; + background-repeat: no-repeat; + width: 100%; + height: 100%; +} + +#leader-op { + top: 7.55%; +} + +#leader-me { + top: 77.5%; +} + +.stats { + height: 12.5%; + width: 88.5%; + margin-bottom: -27%; + background-color: rgba(20, 20, 20, .6); +} + +.current-turn { + box-shadow: -3vw 0 1vw .1vw goldenrod; +} + +#stats-op { + top: 24.25%; +} + +#stats-me { + top: 61.75%; +} + +.profile-img { + left: 28.4%; + top: 9.6%; + width: 21.9%; + height: 80%; + margin-bottom: -24%; + background-image: url(img/icons/profile.png); + background-size: contain; + background-repeat: no-repeat; + background-position: center; + border-radius: 100%; +} + +.profile-img>div { + left: -10%; + top: -6%; + height: 118%; + width: 118%; + background-image: url(img/icons/icon_player_border.png); + background-size: contain; + background-repeat: no-repeat; + background-position: center; + overflow: visible; +} + +.profile-img>div>div { + width: 43%; + height: 43%; + left: -10.5%; + top: .5%; + background-size: contain; + background-repeat: no-repeat; + background-position: center; +} + +.faction-ability { + background-image: url('img/icons/faction-ability.png'); + left: 5%; + top: 9.6%; + width: 15%; + height: 80%; + margin-bottom: -24%; + background-size: contain; + background-repeat: no-repeat; + background-position: center; +} + +.faction-ability .faction-ability-count{ + left: 40%; + top: 17%; + width: 100%; + height: 100%; + margin-bottom: -24%; + position: relative; + color: #dddddd; + font-size: 1.5vw; + font-weight: bold; +} + +#stats-me > div > div > div { + top: 59%; +} + +.score-total { + top: 21%; + left: 94.8%; + height: 40%; + width: 12%; + margin-bottom: -12%; + color: #000; + text-shadow: 0 0 5px #fff; + font-size: 2.3vw; + font-weight: 700; + background-size: contain; + background-repeat: no-repeat; + background-position: center; +} + +#score-total-me { + background-image: url(img/icons/score_total_me.png); +} + +#score-total-op { + background-image: url(img/icons/score_total_op.png); +} + +.score-leader>div { + background-image: url(img/icons/icon_high_score.png); + background-repeat: no-repeat; + background-size: contain; + background-position: bottom; + left: -46%; + top: -32%; + width: 195%; + height: 170%; +} + +.hand-count { + top: 58.5%; + left: 53.25%; + height: 29.5%; + width: 17%; + margin-bottom: -9%; + font-size: 1.7vw; + font-weight: 700; + padding-left: 7%; + background-image: url(img/icons/icon_card_count.png); + background-size: contain; + background-repeat: no-repeat; + background-position: left; +} + +#hand-count-me { + top: 10%; +} + +.gem { + width: 9%; + height: 31%; + margin-bottom: -9.25%; + background-image: url(img/icons/icon_gem_off.png); +} + +.gem-on { + background-image: url(img/icons/icon_gem_on.png); +} + +#gem2-op { + top: 56.25%; + left: 70.75%; +} + +#gem1-op { + top: 56%; + left: 80%; +} + +#gem2-me { + top: 9%; + left: 70.75%; +} + +#gem1-me { + top: 9%; + left: 80%; +} + +.name { + left: 53%; + top: 6%; + width: 41.5%; + height: 20%; + margin-bottom: -6%; + overflow: hidden; + white-space: nowrap; + font-size: 1.1vw; + font-weight: 700; +} + +#name-me { + top: 46%; +} + +.deck-name { + left: 53%; + top: 25%; + width: 41.5%; + height: 30%; + margin-bottom: -6%; + overflow: hidden; + text-transform: capitalize; + color: tan; + font-size: .9vw; +} + +#deck-name-me { + top: 64%; +} + +.passed { + height: 0%; + width: 0%; + left: 90%; + top: 87%; + color: tan; + font-size: 1.5vw; + font-weight: 700; + text-shadow: 1px 1px 2px #000; +} + +#passed-me { + top: -3% +} + +#pass-button { + top: 82%; + left: 63%; + width: 20%; + height: 4%; + font-size: 2vw; + font-weight: 700; + border: .1vw solid goldenrod; + border-radius: .5vw; + background-color: rgba(20, 20, 20, .9); +} + +.field { + width: 100%; + height: 38.5%; +} + +.field .hero { + /*pointer-events: none;*/ +} + +#field-op { + top: -1.1%; +} + +/* +#field-op .card { + pointer-events: none; +} +*/ + +#field-me { + top: -1%; +} + +#field-hand { + width: 100%; + height: 13%; +} + +.field-row { + height: 32%; + top: 4%; + display: flex; + z-index: 1; +} + +.field-row>div { + position: absolute; +} + +.row-score { + width: 5.1%; + top: 7%; + height: 95%; + margin-bottom: -12.65%; + font-size: 1.8vw; + color: #000; + text-shadow: 0 0 5px #fff; +} + +.row-special { + width: 14.25%; + height: 100%; + left: 5.1%; + margin-bottom: -12.65%; +} + +.row-cards { + height: 100%; + width: 80.65%; + left: 19.35%; + left: 20%; + width: 79.7%; +} + +.row-weather { + position: absolute; + top: 5%; + left: 5.75%; + width: 94.25%; + height: 100%; + pointer-events: none; + background-size: cover; + background-position: bottom; + background-repeat: no-repeat; +} + +.frost { + background-image: url(img/icons/overlay_frost.png); +} + +.rain { + background-image: url(img/icons/overlay_rain.png); +} + +.fog { + background-image: url(img/icons/overlay_fog.png); +} + +#hand-row { + top: 8%; + height: 91%; + left: 7.1%; + width: 92.5%; + z-index: 1; +} + +#op-hand-row { + top: 9%; + height: 91%; + left: 7.1%; + width: 92.5%; + z-index: 1; +} + +#op-hand-row.human-op { + top: -83%; + height: 91%; + left: 7.1%; + width: 92.5%; + z-index: 2; +} + +.row-selectable { + background-color: rgba(255, 255, 0, .08); +} + +.row-selectable:hover { + box-shadow: 0 0 .25vw rgba(255, 255, 0, 1); + box-sizing: border-box; +} + +.card-selectable>.card:hover { + border: .12vw outset goldenrod; + border-radius: .3vw; + margin-bottom: 1vw; + z-index: 1; +} + +.cardpile { + width: 27.6%; + height: 13.5%; + margin-bottom: -36.25%; + display: flex; + flex-direction: column-reverse; + align-items: center; + overflow: visible; + z-index: 1; +} + +.cardpile .card { + pointer-events: none; +} + +/* + Special cards cardpile +*/ + +.field-row .cardpile { + width: 14.25%; + height: 100%; + left: 5.1%; + margin-bottom: -12.65%; + flex: none; + position: relative; +} + +.field-row .cardpile .special { + top: -1.7vw; + margin-top: 2.2vw; + position: absolute; +} + +#grave-op { + top: 6.5%; + left: 6.5%; +} + +#deck-op { + top: 6.5%; + left: 51%; +} + +#grave-me { + top: 76.5%; + left: 6.5%; +} + +#deck-me { + top: 76.5%; + left: 51%; +} + +.deck-card { + position: relative; + display: inline-block; + height: 6.675vw; + width: 4.45vw; + background-size: contain; + background-repeat: no-repeat; + box-shadow: -.1vw -.1vw .5vw rgba(20, 20, 20, .5); +} + +.deck-counter { + position: relative; + background-color: rgba(20, 20, 20, .8); + width: 3vw; + height: 2vw; + z-index: 1; + color: tan; + font-size: 1.3vw; +} + +.cardpile .deck-card { + top: -5%; + margin-top: -114.5%; +} + +.cardpile>.card { + top: -5%; + margin-top: -108.5%; +} + +#deck-customization { + position: absolute; + width: 100%; + height: calc(100vw * 1080 / 1920); + background-color: rgba(10, 10, 10, .95); + z-index: 85; +} + +#faction-title { + position: absolute; + height: 5%; + width: 100%; + top: 6%; +} + +#deck-customization h1 { + position: absolute; + font-size: 1.45vw; + color: #dedede; + line-height: 220%; + text-transform: capitalize; + padding: 0 3%; + top: -60%; + background-size: contain; + background-repeat: no-repeat; +} + +#faction-description { + position: absolute; + font-size: 1.14vw; + color: #ab977c; + top: 9.45%; + left: 20.2%; + width: 60%; + text-align: center; +} + +.deck-options { + position: absolute; + font-size: 1vw; + color: #fff; + top: 15%; +} + +#select-deck { + left: 30%; +} + +#upload-deck { + left: 39%; +} + +#change-faction { + left: 46%; +} + +#download-deck { + left: 54%; +} + +#select-op-deck { + left: 62%; +} + +#op-deck-name { + left: 72%; + color: #cccccc; + font-style: italic; +} + +#site-links { + right: 5%; + top: 5%; + position: absolute; + font-size: 1vw; + color: #ccc; +} + +#site-links a { + color: #aaa; +} + +.card-array { + position: absolute; + width: 34.4%; + height: 68%; + overflow-y: scroll; + padding: .1vw 1.1vw; + display: flex; + flex-wrap: wrap; + justify-content: space-between; +} + +#card-bank { + top: 22.5%; + left: 8.275%; +} + +#card-deck { + top: 22.5%; + left: 58.4%; +} + +/* + Custom display of cards in Array in customization window +*/ + +.card-array .card-lg { + width: 9.88vw; + height: 18.45vw; + border-radius: 1vw; + margin-bottom: .75vw; + position: relative; +} + +.card-array .card-lg .card-large-bg { + width: 9.88vw; + height: 18.45vw; + border-radius: 1vw; + margin-bottom: .75vw; + background-repeat: no-repeat; + background-size: contain; + background-position: top; + margin-left: -0.05vw; +} + +.card-array .card-lg .card-large-faction-band { + left: -0.05vw; + top: 0.55vw; + width: 2.5vw; + height: 12.8vw; + margin-bottom: .75vw; + background-repeat: no-repeat; + background-size: contain; + background-position: bottom; + position: absolute; +} + +.card-array .card-lg div.card-count { + position: relative; + top: 91%; + left: 74%; + width: 20%; + height: 7%; + font-size: 1.2vw; + color: #5f4923; + padding-left: 1.7vw; + background-image: url(img/icons/preview_count.png); + background-position: left; + background-repeat: no-repeat; + background-size: contain; +} + +.card-array .card-lg .card-large-name { + display: flex; + justify-content: center; + text-align: center; + position: absolute; + top: 75.5%; + left: 0%; + width: 100%; + height: 5vw; + font-size: 1vw; + background-position: left; + background-repeat: no-repeat; + background-size: contain; + color: #000; + line-height: 0.8vw; +} + +.card-array .card-lg .card-large-quote { + display: flex; + justify-content: center; + text-align: center; + position: absolute; + top: 83%; + left: 0%; + width: 98%; + height: 5vw; + font-size: 0.7vw; + background-position: left; + background-repeat: no-repeat; + background-size: contain; + color: #000; +} + +.card-array .card-lg .card-large-power { + position: absolute; + top: -2%; + left: -4%; + width: 5vw; + height: 5vw; + font-size: 1.2vw; + background-position: left; + background-repeat: no-repeat; + background-size: contain; +} + +.card-array .card-lg .card-large-power .card-large-power-strength { + display: flex; + justify-content: center; + align-items: center; + color: #000; + font-weight: bold; + font-size: 1.4vw; + margin-left: -1.8vw; + margin-top: 0.8vw; +} + +.card-array .hero .card-large-power { + top: -2%; + left: -4%; +} + +.card-array .hero .card-large-power .card-large-power-strength { + color: #fff; +} + +.card-array .card-lg .card-large-row { + position: absolute; + top: 22%; + left: 0vw; + width: 3.5vw; + height: 2.5vw; + font-size: 1.2vw; + background-position: left; + background-repeat: no-repeat; + background-size: contain; +} + +.card-array .card-lg .card-large-ability { + position: absolute; + top: 40%; + left: 0vw; + width: 3.5vw; + height: 2.5vw; + font-size: 1.2vw; + background-position: left; + background-repeat: no-repeat; + background-size: contain; +} + +.card-array .card-lg .card-large-ability-2 { + position: absolute; + top: 56%; + left: 0vw; + width: 3.5vw; + height: 2.5vw; + font-size: 1.2vw; + background-position: left; + background-repeat: no-repeat; + background-size: contain; +} + +/* + Custom display of cards in Preview +*/ + + +.card-preview .card-lg .card-large-bg { + width: 100%; + height: 100%; + border-radius: 1vw; + margin-bottom: .75vw; + background-repeat: no-repeat; + background-size: contain; + background-position: top; +} + +.card-preview .card-lg .card-large-faction-band { + left: 0.15vw; + top: 1.15vw; + width: 4.5vw; + height: 20.5vw; + margin-bottom: .75vw; + background-repeat: no-repeat; + background-size: contain; + background-position: bottom; + position: absolute; +} + +.card-preview .card-lg .card-large-name { + display: flex; + justify-content: center; + text-align: center; + position: absolute; + top: 75%; + left: 0%; + width: 100%; + height: 5vw; + font-size: 1.4vw; + background-position: left; + background-repeat: no-repeat; + background-size: contain; + color: #000; + line-height: 1.1vw; +} + +.card-preview .card-lg .card-large-quote { + display: flex; + justify-content: center; + text-align: center; + position: absolute; + top: 84%; + left: 0%; + width: 96%; + height: 5vw; + font-size: 0.9vw; + background-position: left; + background-repeat: no-repeat; + background-size: contain; + color: #000; +} + +.card-preview .card-lg .card-large-power { + position: absolute; + top: -2%; + left: -4%; + width: 10vw; + height: 10vw; + font-size: 1.2vw; + background-position: left; + background-repeat: no-repeat; + background-size: contain; +} +.card-preview .card-lg .card-large-power .card-large-power-strength { + display: flex; + justify-content: center; + align-items: center; + color: #000; + font-weight: bold; + font-size: 2.5vw; + margin-left: -3.6vw; + margin-top: 1.7vw; +} + +.card-preview .hero .card-large-power { + top: -3%; + left: -6%; +} + +.card-preview .hero .card-large-power .card-large-power-strength { + color: #fff; +} + +.card-preview .card-lg .card-large-row { + position: absolute; + top: 25%; + left: 2%; + width: 10vw; + height: 4vw; + font-size: 1.2vw; + background-position: left; + background-repeat: no-repeat; + background-size: contain; +} + +.card-preview .card-lg .card-large-ability { + position: absolute; + top: 40%; + left: 2%; + width: 10vw; + height: 4vw; + font-size: 1.2vw; + background-position: left; + background-repeat: no-repeat; + background-size: contain; +} + +.card-preview .card-lg .card-large-ability-2 { + position: absolute; + top: 55%; + left: 2%; + width: 10vw; + height: 4vw; + font-size: 1.2vw; + background-position: left; + background-repeat: no-repeat; + background-size: contain; +} + +/* + Custom display of carousel cards +*/ + +#carousel .card-lg .card-large-bg { + height: 100%; + width: 100%; + border-radius: 1vw; + margin-bottom: .75vw; + background-repeat: no-repeat; + background-size: contain; + background-position: bottom; +} + +#carousel .card-lg .card-large-faction-band { + left: 0.15vw; + top: 1.15vw; + width: 4.5vw; + height: 20.5vw; + margin-bottom: .75vw; + background-repeat: no-repeat; + background-size: contain; + background-position: bottom; + position: absolute; +} + +#carousel > :nth-child(1) > :nth-child(2n) .card-large-faction-band { + left: 0.5vw; + top: 0.6vw; + width: 3vw; + height: 18vw; +} + +#carousel > :nth-child(1) > :nth-child(4n - 3) .card-large-faction-band { + left: 0.5vw; + top: 0.5vw; + width: 2.5vw; + height: 14.7vw; +} + +#carousel .card-lg .card-large-name { + display: flex; + justify-content: center; + text-align: center; + position: absolute; + top: 75%; + left: 0%; + width: 100%; + height: 5vw; + font-size: 1.4vw; + background-position: left; + background-repeat: no-repeat; + background-size: contain; + color: #000; +} + +#carousel .card-lg .card-large-quote { + display: flex; + justify-content: center; + text-align: center; + position: absolute; + top: 86%; + left: 0%; + width: 96%; + height: 5vw; + font-size: 0.9vw; + background-position: left; + background-repeat: no-repeat; + background-size: contain; + color: #000; +} + + +#carousel > :nth-child(1) > :nth-child(2n) .card-large-name { + font-size: 1.3vw; +} + +#carousel > :nth-child(1) > :nth-child(2n) .card-large-quote { + font-size: 0.8vw; +} + + +#carousel > :nth-child(1) > :nth-child(4n - 3) .card-large-name { + font-size: 1.1vw; +} + +#carousel > :nth-child(1) > :nth-child(4n - 3) .card-large-quote { + font-size: 0.7vw; +} + +#carousel .card-lg .card-large-power { + position: absolute; + top: -2%; + left: -4%; + width: 10vw; + height: 10vw; + font-size: 1.2vw; + background-position: left; + background-repeat: no-repeat; + background-size: contain; +} + +#carousel .card-lg .card-large-power .card-large-power-strength { + display: flex; + justify-content: center; + align-items: center; + color: #000; + font-weight: bold; + font-size: 2.5vw; + margin-left: -3.6vw; + margin-top: 1.7vw; +} + +#carousel > :nth-child(1) > :nth-child(2n) .card-large-power { + top: -2%; + left: -4%; + width: 8vw; + height: 8vw; +} + +#carousel > :nth-child(1) > :nth-child(2n) .card-large-power .card-large-power-strength { + margin-left: -2.8vw; + margin-top: 1.1vw; +} + +#carousel > :nth-child(1) > :nth-child(4n - 3) .card-large-power { + top: -2%; + left: -4%; + width: 7vw; + height: 7vw; +} + +#carousel > :nth-child(1) > :nth-child(4n - 3) .card-large-power .card-large-power-strength { + margin-left: -2.7vw; + margin-top: 0.9vw; + font-size: 2.3vw; +} + +#carousel .hero .card-large-power { + top: -3%; + left: -6%; +} + +#carousel .hero .card-large-power .card-large-power-strength { + color: #fff; +} + +#carousel .card-lg .card-large-row { + position: absolute; + top: 25%; + left: 2%; + width: 10vw; + height: 4vw; + font-size: 1.2vw; + background-position: left; + background-repeat: no-repeat; + background-size: contain; +} + +#carousel > :nth-child(1) > :nth-child(2n) .card-large-row { + height: 3.8vw; + left: 0%; +} + +#carousel > :nth-child(1) > :nth-child(4n - 3) .card-large-row { + height: 3.4vw; + left: 0%; +} + +#carousel .card-lg .card-large-ability { + position: absolute; + top: 41%; + left: 2%; + width: 10vw; + height: 4vw; + font-size: 1.2vw; + background-position: left; + background-repeat: no-repeat; + background-size: contain; +} + +#carousel .card-lg .card-large-ability-2 { + position: absolute; + top: 56%; + left: 2%; + width: 10vw; + height: 4vw; + font-size: 1.2vw; + background-position: left; + background-repeat: no-repeat; + background-size: contain; +} + +#carousel > :nth-child(1) > :nth-child(2n) .card-large-ability { + height: 3.4vw; + top: 41%; + left: 2.5%; +} + +#carousel > :nth-child(1) > :nth-child(4n - 3) .card-large-ability { + height: 3vw; + top: 42%; + left: 2.5%; +} + +#carousel > :nth-child(1) > :nth-child(2n) .card-large-ability-2 { + height: 3.4vw; + top: 56%; + left: 2.5%; +} + +#carousel > :nth-child(1) > :nth-child(4n - 3) .card-large-ability-2 { + height: 3vw; + top: 57%; + left: 2.5%; +} + +#carousel .hide .card-large-bg, #carousel .hide .card-large-faction-band, #carousel .hide .card-large-name, #carousel .hide .card-large-power, +#carousel .hide .card-large-power-strength, #carousel .hide .card-large-row, #carousel .hide .card-large-ability, #carousel .hide .card-large-ability-2, #carousel .hide .card-large-quote { + display: none; +} +/* + Custom display of leader card +*/ +#card-leader .card-large-bg { + width: 100%; + height: 100%; + border-radius: 1vw; + margin-bottom: .75vw; + background-repeat: no-repeat; + background-size: contain; + background-position: top; +} + +#card-leader .card-large-name { + display: flex; + justify-content: center; + text-align: center; + position: absolute; + top: 75%; + left: 0%; + width: 100%; + height: 5vw; + font-size: 0.9vw; + background-position: left; + background-repeat: no-repeat; + background-size: contain; + color: #000; +} + +#card-leader .card-large-quote { + display: none; +} +/* + --- +*/ +#card-leader { + position: absolute; + height: 27%; + width: 6.9%; + top: 20.8%; + left: 46.6%; +} + +#card-leader p { + font-size: 1.1vw; + text-align: center; + color: #8f6c36; + line-height: 0%; + margin: 9%; +} + +#card-leader > div { + position: relative; + height: 84.5%; + margin-top: 24.5%; + background-size: contain; + border-radius: .5vw; + background-repeat: no-repeat; +} + +#deck-stats { + position: absolute; + width: 12%; + height: 30%; + top: 49.5%; + left: 44.05%; +} + +#deck-stats>p:nth-child(odd) { + color: #82735f; + font-size: 1.05vw; + text-align: center; + margin-bottom: -6.75%; +} + +#deck-stats>p:nth-child(even) { + font-size: 1.2vw; + text-align: left; + color: #9f7d3e; + padding-left: 2.3vw; + margin-left: 3.95vw; + margin-bottom: -6.75%; + background-repeat: no-repeat; + background-position: left; + background-size: 2.5vw; +} + +#deck-stats>p:nth-child(2) { + background-image: url(img/icons/deck_stats_count.png); +} + +#deck-stats>p:nth-child(4) { + background-image: url(img/icons/deck_stats_unit.png); +} + +#deck-stats>p:nth-child(6) { + background-image: url(img/icons/deck_stats_special.png); +} + +#deck-stats>p:nth-child(8) { + background-image: url(img/icons/deck_stats_strength.png); +} + +#deck-stats>p:nth-child(10) { + background-image: url(img/icons/deck_stats_hero.png); +} + +#start-game { + position: absolute; + top: 86%; + left: 46.65%; + width: 6%; + height: 3%; + font-size: .98vw; +} + +#start-ai-game { + position: absolute; + top: 90%; + left: 46.2%; + width: 7%; + height: 3%; + font-size: .98vw; +} + +#start-pvp-game { + position: absolute; + top: 94%; + left: 45.7%; + width: 8%; + height: 3%; + font-size: .98vw; +} + +.start-game_class { + white-space: nowrap; + color: #fff; + background-color: rgb(20, 20, 20); + border: .1vw ridge rgb(30, 30, 30); +} + +.card-contianer-title { + position: absolute; + width: 10%; + height: 3%; + font-size: 1.3vw; + color: #959595; +} + +#card-bank-title { + top: 7.45%; + left: 8.5%; +} + +#card-deck-title { + top: 7.8%; + left: 84.45%; +} + +.card { + height: 6.35vw; + width: 4.45vw; + background-size: contain; + background-repeat: no-repeat; + box-shadow: -.1vw -.1vw .5vw rgba(20, 20, 20, .5); + display: inline-block; + position: relative; + transition: margin-bottom 0.05s, margin-left .25s, margin-right .25s, transform 0.5s; + z-index=1; +} + +.deck-card .card { + position: absolute; +} + +.card>div { + background-size: contain; + background-position: center; + background-repeat: no-repeat; +} + +.card>div:nth-child(1) { + top: -4%; + left: -4%; + width: 70%; + height: 50%; + margin-bottom: -71%; + background-position: 0 0; +} + +.card>div:nth-child(1)>div { + top: 13%; + left: 7%; + width: 50%; + heighth: 50%; + font-size: 1vw; + font-weight: 700; + color: #000; + text-shadow: 0 0 .1vw #fff; +} + +.hero>div:nth-child(1)>div { + color: #fff; + text-shadow: 0 0 .1vw #000; +} + +.card>div:nth-child(2) { + top: 75%; + left: 65%; + width: 33%; + height: 22%; + margin-bottom: -32%; +} + +.card>div:nth-child(3) { + top: 75%; + left: 32%; + width: 33%; + height: 22%; + margin-bottom: -32%; + font-size: 1vw; +} + +.card > .card-ability-2:nth-child(4) { + top: 75%; + left: 0%; + width: 33%; + height: 22%; + margin-bottom: -32%; + font-size: 1vw; +} + +.card > div:last-child { + width: 100%; + height: 100%; + background-position: center; + background-size: 40% auto; + opacity: 0; + filter: alpha(opacity=0); + transition: background-size 0.25s; +} + +.card-container { + display: flex; + justify-content: center; + align-items: flex-end; +} + +.card-container .card { + margin: 0 1px; + flex-shrink: 0; +} + +.center { + display: flex; + justify-content: center; + align-items: center; +} + +.bg-contain { + background-size: contain; + background-repeat: no-repeat; +} + +.visible { + display: visible; +} + +.hide { + display: none; +} + +.fade { + opacity: .2; + filter: alpha(opacity=20); +} + +.noclick { + pointer-events: none; +} + +/* + DECK SORTER +*/ + +#deck-sorter { + position: absolute; + width: 100%; + height: calc(100vw * 1080 / 1920); + z-index: 150; + background-color: rgba(0,0,0,0.8); +} + +#deck-sorter-title { + position: absolute; + width: 100%; + height: 4vw; + top: 1%; + font-size: 1.75vw; + line-height: 4vw; + background-color: rgba(10, 10, 10, .95); + text-align: center; + box-shadow: 0 0 1vw #ffffff54; +} + +.drop-container { + height: 100vh; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + margin: 20px; +} + +.drop-targets { + display: flex; + flex-direction: row; + justify-content: space-around; + align-items: center; +} + +.drop-line-title { + display: flex; + flex-direction: row; + justify-content: space-around; + align-items: center; + padding: 2px; + font-weight: bold; + width: 1vw; + text-orientation: upright; + writing-mode: vertical-rl; + text-transform: uppercase; + color: #666; + font-size: 1.2vw; +} + +.drop-box { + width: 8.5vw; + height: 15.5vw; + border: solid 1px #ccc; + margin: 10px; + /* align items in the box */ + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + border-radius: 0.7vw; +} + +.drop-susp { + width: 8.5vw; + height: 15.5vw; + border: solid 3px #ccc; + margin: 10px; + /* align items in the box */ + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + font-size: 60px; + line-height: 60px; + color: #ccc; + background-color: rgba(200,200,200,.3); + border-radius: 0.7vw; +} + + +.drop-item.drag-over, .drop-box.drag-over { + border: dashed 1px green; + border-radius: 0.7vw; +} + +.drop-item, .drop-item .card-lg { + width: 8vw; + height: 15vw; + border-radius: 0.7vw; + /*background-color: #F0DB4F;*/ +} + +#deck-sorter .card-lg { + display: inline-block; + background-repeat: no-repeat; + background-size: contain; + background-position: top; + position: relative; +} + +#deck-sorter .card-lg .card-large-bg { + height: 100%; + width: 100%; + border-radius: 0.7vw; + margin-bottom: .75vw; + background-repeat: no-repeat; + background-size: contain; + background-position: bottom; +} + +#deck-sorter .card-lg .card-large-faction-band { + left: 0.5vw; + top: 0.25vw; + width: 2vw; + height: 10.5vw; + margin-bottom: .75vw; + background-repeat: no-repeat; + background-size: contain; + background-position: bottom; + position: absolute; +} + +#deck-sorter .card-lg .card-large-name { + display: flex; + justify-content: center; + text-align: center; + position: absolute; + top: 75%; + left: 0%; + width: 100%; + height: 5vw; + font-size: 1.1vw; + background-position: left; + background-repeat: no-repeat; + background-size: contain; + color: #000; +} + +#deck-sorter .card-lg .card-large-quote { + display: none; +} + +#deck-sorter .card-lg .card-large-power { + position: absolute; + top: -3%; + left: -5%; + width: 6vw; + height: 6vw; + font-size: 1.2vw; + background-position: left; + background-repeat: no-repeat; + background-size: contain; +} + +#deck-sorter .card-lg .card-large-power .card-large-power-strength { + display: flex; + justify-content: center; + align-items: center; + color: #000; + font-weight: bold; + font-size: 2vw; + margin-left: -2.2vw; + margin-top: 0.7vw; +} + +#deck-sorter .hero .card-large-power { + top: -3%; + left: -5%; +} + +#deck-sorter .hero .card-large-power .card-large-power-strength { + color: #fff; +} + +#deck-sorter .card-lg .card-large-row { + position: absolute; + top: 22%; + left: 5%; + width: 2.5vw; + height: 2.5vw; + font-size: 1.2vw; + background-position: left; + background-repeat: no-repeat; + background-size: contain; +} + +#deck-sorter .card-lg .card-large-ability { + position: absolute; + top: 41%; + left: 5%; + width: 2.5vw; + height: 2.5vw; + font-size: 1.2vw; + background-position: left; + background-repeat: no-repeat; + background-size: contain; +} + +#deck-sorter .card-lg .card-large-ability-2 { + position: absolute; + top: 60%; + left: 5%; + width: 2.5vw; + height: 2.5vw; + font-size: 1.2vw; + background-position: left; + background-repeat: no-repeat; + background-size: contain; +} + +#drop-submit { + white-space: nowrap; + color: #222; + background-color: #567956; + width: 100%; + height: 100%; + font-weight: bold; +} + +#drop-submit:disabled { + background-color: #8e8c6b; +} \ No newline at end of file