Example #1
0
 public void DrawNextCard()
 {
     if (Stats.Coal == 0)
     {
         SpawnCard(cardStorage.SpecialCard("gameover_coal"));
     }
     else if (Stats.Food == 0)
     {
         SpawnCard(cardStorage.SpecialCard("gameover_food"));
     }
     else if (Stats.Health == 0)
     {
         SpawnCard(cardStorage.SpecialCard("gameover_health"));
     }
     else if (Stats.Hope == 0)
     {
         SpawnCard(cardStorage.SpecialCard("gameover_hope"));
     }
     else
     {
         IFollowup followup = cardDrawQueue.Next();
         ICard     card     = followup?.Fetch(cardStorage) ?? cardStorage.Random();
         SpawnCard(card);
     }
     saveIntervalCounter = (saveIntervalCounter - 1) % _saveInterval;
     if (saveIntervalCounter == 0)
     {
         progressStorage.Save();
     }
 }
Example #2
0
 public IFollowup Next()
 {
     if (queue.Count > 0)
     {
         if (--queue[0].Delay == 0)
         {
             IFollowup followup = queue[0];
             queue.RemoveAt(0);
             return(followup);
         }
     }
     return(null);
 }
Example #3
0
        public void Insert(IFollowup followup)
        {
            int i           = 0;
            int delayBefore = 0;

            while (i < queue.Count && (delayBefore < followup.Delay || queue[i].Delay == 1))
            {
                delayBefore += queue[i].Delay;
                i++;
            }
            queue.Insert(i, followup.Clone());

            queue[i].Delay -= delayBefore;
            if (queue[i].Delay < 1)
            {
                queue[i].Delay = 1;
            }

            if (i + 1 < queue.Count)
            {
                queue[i + 1].Delay -= queue[i].Delay;
            }
        }
Example #4
0
 public ActionOutcome(StatsModification statsModification, IFollowup followup)
 {
     this.statsModification = statsModification;
     this.followup          = followup;
 }
Example #5
0
 public ActionOutcome(int coalMod, int foodMod, int healthMod, int hopeMod, IFollowup followup)
 {
     statsModification = new StatsModification(coalMod, foodMod, healthMod, hopeMod);
     this.followup     = followup;
 }
Example #6
0
        public async Task <ImportedCards> FetchCards()
        {
            // Fetch spreadsheet from Google Sheet API V4
            Debug.Log("[GoogleSheetsImporter] Fetching cards from Google Sheet " + _spreadsheetId + " ...");
            HttpWebResponse response;

            try {
                HttpWebRequest request = WebRequest.CreateHttp(
                    "https://sheets.googleapis.com/v4/spreadsheets/"
                    + _spreadsheetId
                    + "?includeGridData=true&key="
                    + _apiKey);
                response = (HttpWebResponse)await request.GetResponseAsync();
            }
            catch (WebException e) {
                Debug.LogError("[GoogleSheetsImporter] Request failed: " + e.Message);
                return(new ImportedCards());
            }
            Debug.Log("[GoogleSheetsImporter] " + (int)response.StatusCode + " " + response.StatusDescription);

            if (!response.ContentType.Contains("application/json"))
            {
                Debug.LogError("[GoogleSheetsImporter] Google Sheets API returned unrecognised data format");
                return(new ImportedCards());
            }

            Stream responseStream;

            if ((responseStream = response.GetResponseStream()) == null)
            {
                Debug.LogError("[GoogleSheetsImporter] Google Sheets API returned empty response");
                return(new ImportedCards());
            }

            Spreadsheet spreadsheet = JsonUtility.FromJson <Spreadsheet>(
                new StreamReader(responseStream).ReadToEnd());

            // Parse Metadata sheet
            RowData[] metaRowData = spreadsheet.sheets[0].data[0].rowData;
            Dictionary <string, CellData> metadata = new Dictionary <string, CellData>();

            foreach (RowData row in metaRowData)
            {
                if (row.values[0].StringValue != null)
                {
                    if (metadata.ContainsKey(row.values[0].StringValue))
                    {
                        Debug.LogWarning("[GoogleSheetsImporter] Duplicate key found in Metadata sheet");
                    }
                    else
                    {
                        metadata.Add(row.values[0].StringValue, row.values[1]);
                    }
                }
            }

            // Check sheet format version
            if (!RequireMetadata("majorFormatVersion", metadata))
            {
                return(new ImportedCards());
            }
            if (!RequireMetadata("minorFormatVersion", metadata))
            {
                return(new ImportedCards());
            }
            int sheetMajorVersion = metadata["majorFormatVersion"].IntValue;

            if (sheetMajorVersion != _majorFormatVersion)
            {
                Debug.LogError("[GoogleSheetsImporter] Incompatible sheet format major version (required: " + _majorFormatVersion + ", found: " + sheetMajorVersion + ")");
                return(new ImportedCards());
            }
            int sheetMinorVersion = metadata["minorFormatVersion"].IntValue;

            if (sheetMinorVersion < _minorFormatVersion)
            {
                Debug.LogError("[GoogleSheetsImporter] Incompatible sheet format minor version (required min: " + _minorFormatVersion + ", found: " + sheetMinorVersion + ")");
                return(new ImportedCards());
            }

            // Get sheet indices from metadata
            if (!RequireMetadata("cardSheetIndex", metadata))
            {
                return(new ImportedCards());
            }
            if (!RequireMetadata("specialCardSheetIndex", metadata))
            {
                return(new ImportedCards());
            }
            if (!RequireMetadata("characterSheetIndex", metadata))
            {
                return(new ImportedCards());
            }
            if (!RequireMetadata("imageSheetIndex", metadata))
            {
                return(new ImportedCards());
            }
            int cardSheetIndex        = metadata["cardSheetIndex"].IntValue;
            int specialCardSheetIndex = metadata["specialCardSheetIndex"].IntValue;
            int characterSheetIndex   = metadata["characterSheetIndex"].IntValue;
            int imageSheetIndex       = metadata["imageSheetIndex"].IntValue;

            // Sanity-check sheet formats
            Sheet cardSheet = spreadsheet.sheets[cardSheetIndex];

            if (!CheckCardSheetFormat(cardSheet))
            {
                return(new ImportedCards());
            }
            Sheet specialCardSheet = spreadsheet.sheets[specialCardSheetIndex];

            if (!CheckCardSheetFormat(specialCardSheet))
            {
                return(new ImportedCards());
            }
            Sheet characterSheet = spreadsheet.sheets[characterSheetIndex];

            if (!CheckCharacterSheetFormat(characterSheet))
            {
                return(new ImportedCards());
            }
            Sheet imageSheet = spreadsheet.sheets[imageSheetIndex];

            if (!CheckImageSheetFormat(imageSheet))
            {
                return(new ImportedCards());
            }

            // Parse Images sheet
            Dictionary <int, Sprite> sprites = new Dictionary <int, Sprite>();

            RowData[] imageRowData = imageSheet.data[0].rowData;
            for (int i = 1; i < imageRowData.Length; i++)
            {
                int    id       = imageRowData[i].values[0].IntValue;
                string imageUrl = imageRowData[i].values[1].hyperlink;
                if (sprites.ContainsKey(id))
                {
                    Debug.LogWarning("[GoogleSheetsImporter] Duplicate id found in Images sheet");
                }
                else if (imageUrl == null)
                {
                    Debug.LogWarning("[GoogleSheetsImporter] Image (id: " + id + ") has a null URL");
                }
                else
                {
                    Debug.Log("[GoogleSheetsImporter] Fetching image from " + imageUrl + " ...");
                    HttpWebRequest  imageRequest  = WebRequest.CreateHttp(imageUrl);
                    HttpWebResponse imageResponse = (HttpWebResponse)await imageRequest.GetResponseAsync();

                    Debug.Log("[GoogleSheetsImporter] " + (int)imageResponse.StatusCode + " " + imageResponse.StatusDescription);

                    Stream imageStream;
                    if ((imageStream = imageResponse.GetResponseStream()) == null)
                    {
                        Debug.LogWarning("[GoogleSheetsImporter] Remote host returned no image in response");
                    }
                    else
                    {
                        byte[]    imageData = Util.BytesFromStream(imageStream);
                        Texture2D texture   = new Texture2D(1, 1);
                        if (!texture.LoadImage(imageData))
                        {
                            Debug.LogWarning("[GoogleSheetsImporter] Could not create sprite texture from image");
                        }
                        else
                        {
                            Sprite sprite = Sprite.Create(texture, new Rect(0.0f, 0.0f, texture.width, texture.height),
                                                          new Vector2(0.5f, 0.5f));
                            sprites.Add(id, sprite);
                        }
                    }
                }
            }

            // Parse Characters sheet
            Dictionary <int, Character> characters = new Dictionary <int, Character>();

            RowData[] characterRowData = characterSheet.data[0].rowData;
            for (int i = 1; i < characterRowData.Length; i++)
            {
                int id = characterRowData[i].values[0].IntValue;
                if (characters.ContainsKey(id))
                {
                    Debug.LogWarning("[GoogleSheetsImporter] Duplicate id found in Images sheet");
                }
                else
                {
                    Character character = new Character(characterRowData[i].values[1].GetStringValue(""),
                                                        defaultSprite);
                    sprites.TryGetValue(characterRowData[i].values[2].IntValue,
                                        out character.sprite);
                    characters.Add(id, character);
                }
            }

            // Parse Cards sheet
            Dictionary <int, Card> cards = new Dictionary <int, Card>();

            RowData[] cardRowData = cardSheet.data[0].rowData;
            for (int i = 1; i < cardRowData.Length; i++)
            {
                int id = cardRowData[i].values[0].IntValue;
                if (cards.ContainsKey(id))
                {
                    Debug.LogWarning("[GoogleSheetsImporter] Duplicate id found in Cards sheet");
                }
                else
                {
                    JsonArray <CardPrerequisite> cardPrerequisites =
                        JsonUtility.FromJson <JsonArray <CardPrerequisite> >(cardRowData[i].values[13].StringValue);
                    JsonArray <SpecialCardPrerequisite> specialCardPrerequisites =
                        JsonUtility.FromJson <JsonArray <SpecialCardPrerequisite> >(cardRowData[i].values[14].StringValue);
                    List <ICardPrerequisite> prerequisites = new List <ICardPrerequisite>();
                    if (cardPrerequisites?.array != null)
                    {
                        prerequisites.AddRange(cardPrerequisites.array);
                    }
                    if (specialCardPrerequisites?.array != null)
                    {
                        prerequisites.AddRange(specialCardPrerequisites.array);
                    }

                    IFollowup leftActionFollowup  = null;
                    IFollowup rightActionFollowup = null;
                    if (cardRowData[i].values[16].IntValue > 0)
                    {
                        if (cardRowData[i].values[15].StringValue == null)
                        {
                            leftActionFollowup = new Followup(
                                cardRowData[i].values[15].IntValue,
                                cardRowData[i].values[16].IntValue);
                        }
                        else
                        {
                            leftActionFollowup = new SpecialFollowup(
                                cardRowData[i].values[15].StringValue,
                                cardRowData[i].values[16].IntValue);
                        }
                    }
                    if (cardRowData[i].values[18].IntValue > 0)
                    {
                        if (cardRowData[i].values[17].StringValue == null)
                        {
                            rightActionFollowup = new Followup(
                                cardRowData[i].values[17].IntValue,
                                cardRowData[i].values[18].IntValue);
                        }
                        else
                        {
                            rightActionFollowup = new SpecialFollowup(
                                cardRowData[i].values[17].StringValue,
                                cardRowData[i].values[18].IntValue);
                        }
                    }

                    Card card = new Card(
                        cardRowData[i].values[2].GetStringValue(""),
                        cardRowData[i].values[3].GetStringValue(""),
                        cardRowData[i].values[8].GetStringValue(""),
                        null,
                        new ActionOutcome(
                            cardRowData[i].values[4].IntValue,
                            cardRowData[i].values[5].IntValue,
                            cardRowData[i].values[6].IntValue,
                            cardRowData[i].values[7].IntValue,
                            leftActionFollowup),
                        new ActionOutcome(
                            cardRowData[i].values[9].IntValue,
                            cardRowData[i].values[10].IntValue,
                            cardRowData[i].values[11].IntValue,
                            cardRowData[i].values[12].IntValue,
                            rightActionFollowup),
                        prerequisites);

                    characters.TryGetValue(cardRowData[i].values[1].IntValue,
                                           out card.character);

                    cards.Add(id, card);
                }
            }

            // Parse SpecialCards sheet
            Dictionary <string, Card> specialCards = new Dictionary <string, Card>();

            RowData[] specialCardRowData = specialCardSheet.data[0].rowData;
            for (int i = 1; i < specialCardRowData.Length; i++)
            {
                string id = specialCardRowData[i].values[0].StringValue;
                if (id == null)
                {
                    Debug.LogWarning("[GoogleSheetsImporter] Null id found in SpecialCards sheet");
                }
                else if (specialCards.ContainsKey(id))
                {
                    Debug.LogWarning("[GoogleSheetsImporter] Duplicate id found in SpecialCards sheet");
                }
                else
                {
                    Card card = new Card(
                        specialCardRowData[i].values[2].GetStringValue(""),
                        specialCardRowData[i].values[3].GetStringValue(""),
                        specialCardRowData[i].values[8].GetStringValue(""),
                        null,
                        new GameOverOutcome(),
                        new GameOverOutcome(),
                        null);
                    characters.TryGetValue(specialCardRowData[i].values[1].IntValue,
                                           out card.character);
                    specialCards.Add(id, card);
                }
            }

            Debug.Log("[GoogleSheetsImporter] Cards imported successfully");
            return(new ImportedCards(cards, specialCards));
        }
Example #7
0
 public void AddFollowupCard(IFollowup followup)
 {
     cardDrawQueue.Insert(followup);
 }
Example #8
0
        public async Task <ImportedCards> Import()
        {
            ProtoCollection collection;

            if (remoteCollectionFirst)
            {
                try {
                    collection = await new GoogleSheetsCollection().Fetch();
                }
                catch (Exception e) when(e is WebException || e is FormatException)
                {
                    Debug.LogError("[CollectionImporter] Import from Google Sheets failed: " + e.Message);
                    Debug.LogWarning("[CollectionImporter] Trying local collection...");
                    collection = LocalCollection.Fetch();
                    if (collection.cards.Count == 0)
                    {
                        Debug.LogWarning("[CollectionImporter] Import from local collection returned 0 cards");
                    }
                }
            }
            else
            {
                collection = LocalCollection.Fetch();
                if (collection.cards.Count == 0)
                {
                    Debug.LogWarning("[CollectionImporter] Import from local collection returned 0 cards, "
                                     + "trying Google Sheets...");
                    try {
                        collection = await new GoogleSheetsCollection().Fetch();
                    }
                    catch (Exception e) when(e is WebException || e is FormatException)
                    {
                        Debug.LogError("[CollectionImporter] Import from Google Sheets failed: " + e.Message);
                    }
                }
            }

            Dictionary <int, Sprite> sprites = new Dictionary <int, Sprite>();

            foreach (ProtoImage image in collection.images)
            {
                if (sprites.ContainsKey(image.id))
                {
                    Debug.LogWarning("[CollectionImporter] Duplicate id found in Images");
                    continue;
                }
                if (image.url == null)
                {
                    Debug.LogWarning("[CollectionImporter] Image (id: " + image.id + ") has a null URL");
                    continue;
                }

                Debug.Log("[CollectionImporter] Fetching image from " + image.url + " ...");
                HttpWebResponse imageResponse;
                try {
                    HttpWebRequest imageRequest = WebRequest.CreateHttp(image.url);
                    imageResponse = (HttpWebResponse)await imageRequest.GetResponseAsync();
                }
                catch (WebException e) {
                    Debug.LogError("[CollectionImporter] Request failed: " + e.Message);
                    continue;
                }

                if (imageResponse.StatusCode != HttpStatusCode.OK)
                {
                    Debug.LogWarning(
                        "[CollectionImporter] "
                        + image.url
                        + ": "
                        + (int)imageResponse.StatusCode
                        + " "
                        + imageResponse.StatusDescription);
                    continue;
                }

                Stream imageStream;
                if ((imageStream = imageResponse.GetResponseStream()) == null)
                {
                    Debug.LogWarning(
                        "[CollectionImporter] Remote host returned no image in response (URL: "
                        + image.url
                        + ")");
                    continue;
                }

                byte[]    imageData = Util.BytesFromStream(imageStream);
                Texture2D texture   = new Texture2D(1, 1);
                if (!texture.LoadImage(imageData))
                {
                    Debug.LogWarning(
                        "[CollectionImporter] Could not create sprite texture from image (URL: "
                        + image.url
                        + ")");
                    continue;
                }

                Sprite sprite = Sprite.Create(
                    texture,
                    new Rect(0.0f, 0.0f, texture.width, texture.height),
                    new Vector2(0.5f, 0.5f));
                sprites.Add(image.id, sprite);
            }

            Dictionary <int, Character> characters = new Dictionary <int, Character>();

            foreach (ProtoCharacter protoCharacter in collection.characters)
            {
                if (characters.ContainsKey(protoCharacter.id))
                {
                    Debug.LogWarning("[CollectionImporter] Duplicate id found in Characters");
                    continue;
                }
                Character character = new Character(protoCharacter.name, defaultSprite);
                sprites.TryGetValue(protoCharacter.imageId, out character.sprite);
                characters.Add(protoCharacter.id, character);
            }

            Dictionary <int, Card> cards = new Dictionary <int, Card>();

            foreach (ProtoCard protoCard in collection.cards)
            {
                if (cards.ContainsKey(protoCard.id))
                {
                    Debug.LogWarning("[CollectionImporter] Duplicate id found in Cards");
                    continue;
                }

                IFollowup   leftActionFollowup = null;
                ProtoAction leftAction         = protoCard.leftAction;
                if (leftAction.followup != null && leftAction.followup.Count > 0)
                {
                    if (leftAction.followup.Count > 1)
                    {
                        Debug.LogWarning(
                            "[CollectionImporter] Card (id: "
                            + protoCard.id
                            + ") left action has more than one Followup");
                        continue;
                    }
                    leftActionFollowup = leftAction.followup[0];
                }
                if (leftAction.specialFollowup != null && leftAction.specialFollowup.Count > 0)
                {
                    if (leftAction.specialFollowup.Count > 1)
                    {
                        Debug.LogWarning(
                            "[CollectionImporter] Card (id: "
                            + protoCard.id
                            + ") left action has more than one SpecialFollowup");
                        continue;
                    }
                    if (leftActionFollowup != null)
                    {
                        Debug.LogWarning(
                            "[CollectionImporter] Card (id: "
                            + protoCard.id
                            + ") left action has both types of followups");
                        continue;
                    }
                    leftActionFollowup = leftAction.specialFollowup[0];
                }

                IFollowup   rightActionFollowup = null;
                ProtoAction rightAction         = protoCard.rightAction;
                if (rightAction.followup != null && rightAction.followup.Count > 0)
                {
                    if (rightAction.followup.Count > 1)
                    {
                        Debug.LogWarning(
                            "[CollectionImporter] Card (id: "
                            + protoCard.id
                            + ") right action has more than one Followup");
                        continue;
                    }
                    rightActionFollowup = rightAction.followup[0];
                }
                if (rightAction.specialFollowup != null && rightAction.specialFollowup.Count > 0)
                {
                    if (rightAction.specialFollowup.Count > 1)
                    {
                        Debug.LogWarning(
                            "[CollectionImporter] Card (id: "
                            + protoCard.id
                            + ") right action has more than one SpecialFollowup");
                        continue;
                    }
                    if (rightActionFollowup != null)
                    {
                        Debug.LogWarning(
                            "[CollectionImporter] Card (id: "
                            + protoCard.id
                            + ") right action has both types of followups");
                        continue;
                    }
                    rightActionFollowup = rightAction.specialFollowup[0];
                }

                ActionOutcome leftActionOutcome  = new ActionOutcome(leftAction.statsModification, leftActionFollowup);
                ActionOutcome rightActionOutcome = new ActionOutcome(rightAction.statsModification, rightActionFollowup);

                List <ICardPrerequisite> prerequisites = new List <ICardPrerequisite>();

                bool failed = false;
                foreach (ProtoCardPrerequisite prereq in protoCard.cardPrerequisites)
                {
                    CardPrerequisite cardPrerequisite = new CardPrerequisite(prereq.id);
                    try {
                        foreach (string s in prereq.status)
                        {
                            cardPrerequisite.Status |= CardStatusFor(s);
                        }
                    }
                    catch (ArgumentException e) {
                        Debug.LogWarning("[CollectionImporter] Card (id: " + protoCard.id + "): " + e.Message);
                        failed = true;
                        break;
                    }
                    prerequisites.Add(cardPrerequisite);
                }
                if (failed)
                {
                    continue;
                }

                foreach (ProtoSpecialCardPrerequisite prereq in protoCard.specialCardPrerequisites)
                {
                    SpecialCardPrerequisite cardPrerequisite = new SpecialCardPrerequisite(prereq.id);
                    try {
                        foreach (string s in prereq.status)
                        {
                            cardPrerequisite.Status |= CardStatusFor(s);
                        }
                    }
                    catch (ArgumentException e) {
                        Debug.LogWarning("[CollectionImporter] Card (id: " + protoCard.id + "): " + e.Message);
                        failed = true;
                        break;
                    }
                    prerequisites.Add(cardPrerequisite);
                }
                if (failed)
                {
                    continue;
                }

                Card card = new Card(
                    protoCard.cardText,
                    leftAction.text,
                    rightAction.text,
                    null,
                    leftActionOutcome,
                    rightActionOutcome,
                    prerequisites);

                characters.TryGetValue(protoCard.characterId, out card.character);

                cards.Add(protoCard.id, card);
            }

            Dictionary <string, SpecialCard> specialCards = new Dictionary <string, SpecialCard>();

            foreach (ProtoSpecialCard protoSpecialCard in collection.specialCards)
            {
                if (protoSpecialCard.id == null)
                {
                    Debug.LogWarning("[CollectionImporter] Null id found in SpecialCards");
                    continue;
                }
                if (specialCards.ContainsKey(protoSpecialCard.id))
                {
                    Debug.LogWarning("[CollectionImporter] Duplicate id found in SpecialCards");
                    continue;
                }

                IFollowup          leftActionFollowup = null;
                ProtoSpecialAction leftAction         = protoSpecialCard.leftAction;
                if (leftAction.followup != null && leftAction.followup.Count > 0)
                {
                    if (leftAction.followup.Count > 1)
                    {
                        Debug.LogWarning(
                            "[CollectionImporter] SpecialCard (id: "
                            + protoSpecialCard.id
                            + ") left action has more than one Followup");
                        continue;
                    }
                    leftActionFollowup = leftAction.followup[0];
                }
                if (leftAction.specialFollowup != null && leftAction.specialFollowup.Count > 0)
                {
                    if (leftAction.specialFollowup.Count > 1)
                    {
                        Debug.LogWarning(
                            "[CollectionImporter] SpecialCard (id: "
                            + protoSpecialCard.id
                            + ") left action has more than one SpecialFollowup");
                        continue;
                    }
                    if (leftActionFollowup != null)
                    {
                        Debug.LogWarning(
                            "[CollectionImporter] SpecialCard (id: "
                            + protoSpecialCard.id
                            + ") left action has both types of followups");
                        continue;
                    }
                    leftActionFollowup = leftAction.specialFollowup[0];
                }

                IFollowup          rightActionFollowup = null;
                ProtoSpecialAction rightAction         = protoSpecialCard.rightAction;
                if (rightAction.followup != null && rightAction.followup.Count > 0)
                {
                    if (rightAction.followup.Count > 1)
                    {
                        Debug.LogWarning(
                            "[CollectionImporter] SpecialCard (id: "
                            + protoSpecialCard.id
                            + ") right action has more than one Followup");
                        continue;
                    }
                    rightActionFollowup = rightAction.followup[0];
                }
                if (rightAction.specialFollowup != null && rightAction.specialFollowup.Count > 0)
                {
                    if (rightAction.specialFollowup.Count > 1)
                    {
                        Debug.LogWarning(
                            "[CollectionImporter] SpecialCard (id: "
                            + protoSpecialCard.id
                            + ") right action has more than one SpecialFollowup");
                        continue;
                    }
                    if (rightActionFollowup != null)
                    {
                        Debug.LogWarning(
                            "[CollectionImporter] SpecialCard (id: "
                            + protoSpecialCard.id
                            + ") right action has both types of followups");
                        continue;
                    }
                    rightActionFollowup = rightAction.specialFollowup[0];
                }

                IActionOutcome leftActionOutcome  = null;
                IActionOutcome rightActionOutcome = null;

                if (protoSpecialCard.id == "gameover_coal" ||
                    protoSpecialCard.id == "gameover_food" ||
                    protoSpecialCard.id == "gameover_health" ||
                    protoSpecialCard.id == "gameover_hope")
                {
                    leftActionOutcome  = new GameOverOutcome();
                    rightActionOutcome = new GameOverOutcome();
                }

                SpecialCard specialCard = new SpecialCard(
                    protoSpecialCard.cardText,
                    leftAction.text,
                    rightAction.text,
                    null,
                    leftActionOutcome,
                    rightActionOutcome);

                characters.TryGetValue(protoSpecialCard.characterId, out specialCard.character);

                specialCards.Add(protoSpecialCard.id, specialCard);
            }

            return(new ImportedCards(cards, specialCards));
        }