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(); } }
public IFollowup Next() { if (queue.Count > 0) { if (--queue[0].Delay == 0) { IFollowup followup = queue[0]; queue.RemoveAt(0); return(followup); } } return(null); }
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; } }
public ActionOutcome(StatsModification statsModification, IFollowup followup) { this.statsModification = statsModification; this.followup = followup; }
public ActionOutcome(int coalMod, int foodMod, int healthMod, int hopeMod, IFollowup followup) { statsModification = new StatsModification(coalMod, foodMod, healthMod, hopeMod); this.followup = followup; }
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)); }
public void AddFollowupCard(IFollowup followup) { cardDrawQueue.Insert(followup); }
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)); }