// public override Card[] nextBid(ActiveQuest quest) { Card[] submit = null; if (quest.getHighestBid() > hand.Length) { Debug.Log("Cannot place bid"); //quest.deletePlayer(player); return(submit); } for (int i = 0; i < hand.Length; i++) { if (hand [i].getType().Equals("foe") && hand[i].getBP() <= 20) { submit = hp.addCard(submit, hand [i]); if (submit.Length > quest.getHighestBid()) { return(submit); } else { Debug.Log("Bid too low"); //quest.deletePlayer(player); return(null); } } } return(null); }
public void askForCards(Player player, ActiveQuest newQuest, state newState, string instructions, string button1, string button2, bool getFoes, bool getWeap, bool getAlly, bool getAmour, bool getTest, bool getMordred, int n = -1) { if (newQuest != null) { activeQuest = newQuest; } clearGameObjectArray(cardsToShow); clearGameObjectArray(currButtons); if (gm.getUserInputState() == state.ASKINGFORCARDSTODISCARD) { clearGameObjectArray(currIcons); } multipleCardInputMaxNum = n; activePlayer = player; Card [] cards = getOnlyTypeFromDeck(player.getHand(), getFoes, getWeap, getAlly, getAmour, getTest, getMordred); if (cards == null) { return; } cardsToShow = showHand(cards); //Display the cards gm.setUserInputState(newState); //Debug.Log(gm.getUserInputState()); multipleCardInput = null; //Get multipleCardInput ready to hold the new card choices changeHeaderMessage(instructions, instructionHeader); changeHeaderMessage(activePlayer.getName() + "'s turn", headerCurrPlayer); if (!button1.Equals("null")) { createButtonMessage(panelPosX, panelPosY - panelHeight / 20, button1); } if (!button2.Equals("null")) { createButtonMessage(panelPosX - panelWidth / 5, panelPosY + panelHeight / 5, button2); } return; }
public void SetQuest(ActiveQuestBase currentQuest) { RemoveListeners(previous); if (currentQuest is ActiveWalkingQuest) { ActiveWalkingQuest awq = currentQuest as ActiveWalkingQuest; awq.AmountSoFar.OnChange.AddListener(OnChange); } else if (currentQuest is ActiveQuest <int, IntVariable, UnityEventInt> ) { ActiveQuest <int, IntVariable, UnityEventInt> awq = currentQuest as ActiveQuest <int, IntVariable, UnityEventInt>; awq.AmountSoFar.OnChange.AddListener(OnChange); } else if (currentQuest is ReachValueQuest) { var awq = currentQuest as ReachValueQuest; awq.TotalAmount.OnChange.AddListener(OnChange); } var prog = currentQuest.GetProgress(); ProgressText.text = $"{prog.current} / {prog.max}"; ProgressFill.rectTransform.anchorMax = ProgressFill.rectTransform.anchorMax.SetX(Mathf.Clamp01((float)(prog.current / prog.max))); QuestTitle.text = currentQuest.DisplayName; previous = currentQuest; }
// public override Card[] nextBid(ActiveQuest quest) { Card[] submit = null; if (quest.getHighestBid() > hand.Length) { return(submit); } for (int i = 0; i < hand.Length; i++) { if (hand [i].getType().Equals("foe") && hand[i].getBP() <= 20) { submit = hp.addCard(submit, hand [i]); if (submit.Length > quest.getHighestBid()) { return(submit); } else { //quest.deletePlayer(player); return(null); } } else { if (quest.getCurrentTestPhase() == 1 && hp.numberOfCardInstancesInHand(hand, hand[i]) > 1) { submit = hp.addCard(submit, hand [i]); } } } return(null); }
public static void AddQuest(int id) { if (activeQuests.ContainsKey(id)) { return; } Quest quest = QuestManager.instance.questsDictionary[id]; ActiveQuest newActiveQuest = new ActiveQuest(); newActiveQuest.id = id; newActiveQuest.dateTaken = DateTime.Now.ToLongDateString(); if (quest.task.kills.Length > 0) { //set the kills of the new active quest as a new array of length of the kills in the quest newActiveQuest.kills = new Quest.QuestKill[quest.task.kills.Length]; //for every kill in our quest.task, foreach (Quest.QuestKill questKill in quest.task.kills) { //Set each quest kill to a new instance of questKill newActiveQuest.kills[questKill.id] = new Quest.QuestKill(); //set the player current amount of kills of the new active quest based on the actual amount of monsters that player has killed if (!monstersKilled.ContainsKey(questKill.id)) { monstersKilled.Add(questKill.id, new PlayerData.MonsterKills()); } newActiveQuest.kills[questKill.id].initialAmount = monstersKilled[questKill.id].amount; } } activeQuests.Add(id, newActiveQuest); }
//public static Dictionary<int, MonsterKills> monstersKilled = new Dictionary<int, MonsterKills>(); public static void AddQuest(int id) { if (activeQuests.ContainsKey(id)) { return; } Quest quest = QuestManager.instance.questDictionary [id]; ActiveQuest newActiveQuest = new ActiveQuest(); newActiveQuest.id = id; newActiveQuest.dateTaken = DateTime.Now.ToLongDateString(); if (quest.task.kills.Length > 0) { newActiveQuest.kills = new Quest.QuestKill[quest.task.kills.Length]; foreach (Quest.QuestKill questKill in quest.task.kills) { newActiveQuest.kills [questKill.id] = new Quest.QuestKill(); if (!monsterKilled.ContainsKey(questKill.id)) { monsterKilled.Add(questKill.id, new PlayerData.MonsterKills()); } newActiveQuest.kills [questKill.id].playerCurrent = monsterKilled [questKill.id].amount; } } // Otherwise, add new active Quest activeQuests.Add(id, newActiveQuest); }
private void Start() { initialQuest = GetComponent <InitialQuest>(); prerequisite = initialQuest.returnInitial(); successive = prerequisite.getNextQuest(); activeQuest = GetComponent <ActiveQuest>(); }
public void TryOutQuest(ActiveQuest activeQuest) { Type model = activeQuest.Quest.GetViewModelToTry(); if (model != null) { ShowViewModel(model); } }
public void SetupScenario() { if (ActiveQuest.HasEffect <ISetupEffect>()) { foreach (var setupEffect in ActiveQuest.Card.Text.Effects.OfType <ISetupEffect>()) { Game.AddEffect(setupEffect); } } }
public void showStage(ActiveQuest activeQuest) { clearGameObjectArray(cardsToShow); clearGameObjectArray(currButtons); if (activeQuest.getQuest() == null) { gm.setUserInputState(state.STANDBY); clearGameObjectArray(cardsToShow); } changeHeaderMessage(activePlayer.getName() + "'s turn", headerCurrPlayer); if (Object.ReferenceEquals(activeQuest.getCurrentStage().GetType(), typeof(Foe))) { showCard(activeQuest.getQuest()); Destroy(currentBid); Destroy(highestBid); if (playerBP == null) { playerBP = createHeaderMessage(panelPosX - panelWidth / 3, panelHeight / 2, new Vector3(0, 0, 0), " "); } if (activeQuest != null) { changeHeaderMessage("Player BP: " + activePlayer.getBP(activeQuest.getQuest().getName()), playerBP); } else { changeHeaderMessage("Player BP: " + activePlayer.getBP("null"), playerBP); } changeHeaderMessage("Select the cards you wish to play in this stage", instructionHeader); //createButtonMessage(panelPosX, panelPosY - panelHeight/10, "FIGHT"); gm.setUserInputState(state.ASKINGFORCARDSINQUEST); } else if (Object.ReferenceEquals(activeQuest.getCurrentStage().GetType(), typeof(Test))) { showCard(activeQuest.getCurrentStage()); if (currentBid == null) { currentBid = createHeaderMessage(panelPosX - panelWidth / 3, panelHeight / 2, new Vector3(0, 0, 0), " "); } if (highestBid == null) { highestBid = createHeaderMessage(panelPosX + panelWidth / 3, panelHeight / 2, new Vector3(0, 0, 0), " "); } changeHeaderMessage("Current bid: " + activeQuest.getCurrentPlayerFreeBids(), currentBid); changeHeaderMessage("Highest bid: " + activeQuest.getHighestBid(), highestBid); gm.setUserInputState(state.ASKINGFORCARDSINBID); } createButtonMessage(panelPosX - panelWidth / 5, panelPosY + panelHeight / 5, "Give up"); }
private void Start() { /*buildManager = BuildManager.instance; * if (!GameControl.control.loaded) * { * OpenQuestWindow(); * * }*/ activeQuest = activeQuestPanel.GetComponent <ActiveQuest>(); Invoke("ReloadActiveQuest", 1f); }
public void ExchangeQuest(ActiveQuest activeQuest) { if (ExchangeIsPossible) { var newQuest = Quest.SpawnRandomQuest(_gameSettings.Quests.ActiveQuests.Select(q => q.QuestID)); _gameSettings.Quests.LoseQuest(activeQuest); ActiveQuests.Remove(activeQuest); _gameSettings.Quests.AddQuest(newQuest); ActiveQuests.Add(newQuest); _gameSettings.Quests.LastQuestExchangedWhen = DateTime.Now; } RaisePropertyChanged(() => ExchangeIsPossible); }
public void StartQuests() { CompletedAllQuests = false; Quests = GetComponentsInChildren <Quest>(); if (Quests[0] == null) { Debug.Log("No quests found"); CompletedAllQuests = true; return; } ActiveQuest = Quests[0]; ActiveQuest.OnBeginQuest(); }
public Vector3 GetClosestTargetPosition() { Vector3 closestPosition = Vector3.zero; if (QuestsActive()) { Vector3 playerPos = Core.instance.GetPlayer().transform.position; ActiveQuest closestTarget = null; float closestDistance = -1; foreach (ActiveQuest aq in _activeQuests) { float distance = Vector3.Distance(playerPos, aq.transform.position); if (distance < closestDistance || closestDistance < 0) { closestTarget = aq; closestDistance = distance; } } closestPosition = closestTarget.transform.position; } else if (QuestsOpen()) { Vector3 playerPos = Core.instance.GetPlayer().transform.position; OpenQuest closestTarget = null; float closestDistance = -1; foreach (OpenQuest oq in _openQuests) { float distance = Vector3.Distance(playerPos, oq.transform.position); if (distance < closestDistance || closestDistance < 0) { closestTarget = oq; closestDistance = distance; } } closestPosition = closestTarget.transform.position; } return(closestPosition); }
public void CompleteQuest(Quest quest) { int nextIndex = Array.IndexOf <Quest>(Quests, quest) + 1; quest.OnEndQuest(); // we've completed all quests if (Quests.Length == nextIndex) { CompletedAllQuests = true; ActiveQuest = null; } else { ActiveQuest = Quests[nextIndex]; ActiveQuest.OnBeginQuest(); } }
//Track splitter that evaluates based on card type. public void evaluateStory(Card storyCard) { //log.log("Drew a " + storyCard.getName()); counter = 0; switch (storyCard.getType()) { case "quest": if (recognitionActive) { activeQuest = new ActiveQuest((QuestCard)storyCard, 2); recognitionActive = false; } else { activeQuest = new ActiveQuest((QuestCard)storyCard, 0); } activePlayerSub = activePlayerMeta; cyclingThroughPlayers = false; userInputState = state.ASKINGFORSPONSORS; getSponsor(); break; case "tourney": activePlayerSub = activePlayerMeta; userInputState = state.ASKINGFORPLAYERSTOURNEY; createTourney(storyCard); break; case "event": //Event handling. Pretty much done because events are handled in the cards themselves. storyCard.runEvent(players, activePlayerMeta, players.Length, advDeck, this); break; default: drawQuestCard(); break; } }
/// <summary> /// Static function for using in all quests (for smaller code) /// changed: 01.10.05, need mod /// </summary> public static DialogStatus QDS(Mobile questOwner, Character c, BaseQuest bq) { DialogStatus result = DialogStatus.ChatUnAvailable; if (questOwner.Reputation(c) > bq.MinReputation) { if (!c.QuestDone(bq)) // этот квест уже пройден { if (!c.HaveQuest(bq)) // у чара нету этого квеста { if (AllowedTo(bq, c)) // разрешено выдать, подходит ( расса, класс, скилл ) { if (bq.PreviousQuest > 0) // этот квест из серии, необходимо закончить предыдущий { BaseQuest q = World.CreateQuestById(bq.PreviousQuest); if (q != null && c.QuestDone(q)) { result = DialogStatus.SingleQuestAvailable; //предыдущий закончен, этот можно получить } } else // квест одиночный или начальный для серии { result = DialogStatus.SingleQuestAvailable; } } } else // Character have this quest already { ActiveQuest aq = c.FindPlayerQuest(bq); if (aq.Completed) // закончен квест, нужно наградить { result = aq.Repeatable ? DialogStatus.RepeatQuestCompleate : DialogStatus.SingleQuestCompleate; } else if (!QuestForNPC(bq, (BaseNPC)questOwner)) // квест не для этого нпс? { result = DialogStatus.QuestUnCompleate; } } } } return(result); }
// Quest System public static void AddQuest(int id) { // If we already accepted this quest, we won't accept it again if (activeQuests.ContainsKey(id)) { return; } // Otherwise, we create a new ActiveQuest. Quest quest = QuestManager.instance.questDictionary[id]; // reference to our quest ActiveQuest newActiveQuest = new ActiveQuest(); newActiveQuest.id = id; newActiveQuest.dateTaken = DateTime.Now.ToLongDateString(); // If we need to kill monsters on this quest... if (quest.task.kills.Length > 0) { // set the kills of the new active quest as new array of the kills newActiveQuest.kills = new Quest.QuestKill[quest.task.kills.Length]; //for every kill in our quest.task foreach (Quest.QuestKill questKill in quest.task.kills) { // set each quest kill to a new instance of questKill newActiveQuest.kills[questKill.id] = new Quest.QuestKill(); // set the player current amount of kills of the new active quest based on the if (!monstersKilled.ContainsKey(questKill.id)) { monstersKilled.Add(questKill.id, new Character.MonsterKills()); } newActiveQuest.kills[questKill.id].initialAmount = monstersKilled[questKill.id].amount; } } if (quest.task.talkTo.Length > 0) { // TODO newActiveQuest.npcId = quest.task.talkTo[0]; Debug.Log("Talk to " + newActiveQuest.npcId); } activeQuests.Add(id, newActiveQuest); }
public void startQuest() { Debug.Log("startQuest"); if (activeQuest.getPlayerNum() == 0) { storyDeck.discardCard(new Card[] { activeQuest.getQuest() }); activeQuest = null; drawQuestCard(); return; } gameState = state.QUESTSTARTING; drawXNumberOfCards(1); if (userInputState != state.ASKINGFORCARDSTODISCARD) { log.log("Starting quest " + activeQuest.getQuest().getName()); gameState = state.QUESTINPROGRESS; activeQuest.setQuestAsInProgress(); startStage(); } }
public void getSponsor() { if (counter == players.Length && cyclingThroughPlayers == true) { log.log("Sponsor not found"); storyDeck.discardCard(new Card[] { activeQuest.getQuest() }); activeQuest = null; drawQuestCard(); } else { if (activePlayerSub == activePlayerMeta && cyclingThroughPlayers == false) { cyclingThroughPlayers = true; counter = 1; } else { activePlayerSub = nextPlayer(activePlayerSub); counter++; } ui.showCard(activeQuest.getQuest()); log.log("Getting sponsor"); if (players[activePlayerSub].isHuman()) { ui.askYesOrNo(players[activePlayerSub], "Do you want to sponsor this quest?", GameState.state.ASKINGFORSPONSORS); } else { if (players[activePlayerSub].getAI().doISponsorAQuest(players, (QuestCard)activeQuest.getQuest())) { startQuestSetup(); } else { getSponsor(); } } } }
public void Pressed() { if (!BulletinBoardScript.Instance.inUse) { return; } if (BulletinBoardScript.Instance.CurrentSlime == null) { BulletinBoardScript.Instance.ZoomForCreature(); return; } DisableButton(); ActiveQuest newQuest = new ActiveQuest { name = questText.text, elapsedTime = questTime }; QuestManager.instance.activeQuests.Add(newQuest); QuestManager.instance.availableQuests.Remove(questText.text); questingSlime = BulletinBoardScript.Instance.CurrentSlime; BulletinBoardScript.Instance.CurrentSlime = null; questingSlime.GetComponent <CreatureScript>().WaitingForQuest = false; questingSlime.SetActive(false); }
void RemoveListeners(ActiveQuestBase previousQuest) { if (previousQuest == null) { return; } if (previousQuest is ActiveWalkingQuest) { ActiveWalkingQuest awq = previousQuest as ActiveWalkingQuest; awq.AmountSoFar.OnChange.RemoveListener(OnChange); } else if (previousQuest is ActiveEnemySlayerQuest) { ActiveEnemySlayerQuest awq = previousQuest as ActiveEnemySlayerQuest; awq.AmountSoFar.OnChange.RemoveListener(OnChange); } else if (previousQuest is ActiveItemCollectQuest) { ActiveItemCollectQuest awq = previousQuest as ActiveItemCollectQuest; awq.AmountSoFar.OnChange.RemoveListener(OnChange); } if (previousQuest is ActiveWalkingQuest) { ActiveWalkingQuest awq = previousQuest as ActiveWalkingQuest; awq.AmountSoFar.OnChange.RemoveListener(OnChange); } else if (previousQuest is ActiveQuest <int, IntVariable, UnityEventInt> ) { ActiveQuest <int, IntVariable, UnityEventInt> awq = previousQuest as ActiveQuest <int, IntVariable, UnityEventInt>; awq.AmountSoFar.OnChange.RemoveListener(OnChange); } else if (previousQuest is ReachValueQuest) { var q = previousQuest as ReachValueQuest; q.TotalAmount.OnChange.RemoveListener(OnChange); } }
public void foeReveal(ActiveQuest activeQuest) { if (enemyBP == null) { enemyBP = createHeaderMessage(panelPosX + panelWidth / 3, panelHeight / 2, new Vector3(0, 0, 0), " "); } Destroy(playerBP); clearGameObjectArray(cardsToShow); clearGameObjectArray(currButtons); showCards(activeQuest.getStageWeapons(activeQuest.getCurrentStageNum()), new Vector2(panelPosX + panelWidth / 10, panelPosY), new Vector2(10, 10)); showCard(activeQuest.getCurrentStage()); stageWinners = new GameObject[activeQuest.getPlayerNum() + 1]; stageWinners[0] = createHeaderMessage(panelPosX - panelWidth / 3, panelHeight / 2, new Vector3(0, 0, 0), "Winners"); createButtonMessage(panelPosX, panelPosY - panelHeight / 10, "OK"); for (int i = 1; i < activeQuest.getPlayerNum() + 1; i++) { stageWinners[i] = createHeaderMessage(panelPosX - panelWidth / 3, panelHeight / 2 - i * (panelHeight / 15), new Vector3(0, 0, 0), activeQuest.getPlayer(i - 1).getName()); } }
/// <summary> /// Adds the quest to "activeQuests" List /// </summary> /// <param name="id">Identifier.</param> public static void AddQuest(int id) { //If we already accepted this quest, we won't accept it again. if (activeQuests.ContainsKey(id)) { return; } //Otherwise, we create a new ActiveQuest. Quest quest = QuestManager.instance.questDictionary[id]; //Set a reference to the quest we want to add. ActiveQuest newActiveQuest = new ActiveQuest(); newActiveQuest.id = id; newActiveQuest.dateTaken = DateTime.Now.ToLongDateString(); //If we need to kill monsters on this quest... if (quest.task.kills.Length > 0) { //set the kills of the new active quest as a new array of length of the kills in the quest newActiveQuest.kills = new Quest.QuestKill[quest.task.kills.Length]; //for every kill in our quest.task, int killIndex = 0; foreach (Quest.QuestKill questKill in quest.task.kills) { //Set each quest kill to a new instance of questKill newActiveQuest.kills[killIndex] = new Quest.QuestKill(); //set the player current amount of kills of the new active quest based on the actual amount of monsters that player has killed if (!monstersKilled.ContainsKey(questKill.id)) { monstersKilled.Add(questKill.id, new PlayerData.MonsterKills()); } newActiveQuest.kills[killIndex].initialAmount = monstersKilled[questKill.id].amount; killIndex++; } } activeQuests.Add(id, newActiveQuest); }
void NotifyQuestSucceeded(ActiveQuest quest) { messages.Enqueue(FormatMessage("QUEST COMPLETED", quest.Name)); }
void NotifyQuestStarted(ActiveQuest quest) { messages.Enqueue(FormatMessage("QUEST STARTED", quest.Name)); }
void NotifyQuestFailed(ActiveQuest quest) { messages.Enqueue(FormatMessage("QUEST FAILED", quest.Name)); }
void NotifyObjectiveSucceeded(ActiveQuest quest, ActiveQuest.Objective objective) { var optionalTag = objective.isOptional ? "(OPTIONAL) " : ""; messages.Enqueue(FormatMessage(quest.Name, "COMPLETED" + Environment.NewLine + optionalTag + objective.Description)); }
void NotifyObjectiveStarted(ActiveQuest quest, ActiveQuest.Objective objective) { var optionalTag = objective.isOptional ? "(OPTIONAL) " : ""; messages.Enqueue(FormatMessage(quest.Name, optionalTag + objective.Description)); }
public void RemoveActiveQuest(ActiveQuest aq) { _activeQuests.Remove(aq); }
public void AddActiveQuest(ActiveQuest aq) { _activeQuests.Add(aq); }
public static void AddQuest(int id) { if (activeQuests.ContainsKey(id)) { return; } Quest quest = QuestManager.instance.questDictionary[id]; ActiveQuest newActiveQuests = new ActiveQuest(); newActiveQuests.id = id; newActiveQuests.dateTaken = DateTime.Now.ToLongDateString(); if (quest.task.kills.Length > 0) { newActiveQuests.kills = new Quest.QuestKill[quest.task.kills.Length]; foreach (Quest.QuestKill questKill in quest.task.kills) { newActiveQuests.kills[questKill.id] = new Quest.QuestKill(); if (!monsterKilled.ContainsKey(questKill.id)) { monsterKilled.Add(questKill.id, new PlayerData.MonsterKills()); } newActiveQuests.kills[questKill.id].initialAmount = monsterKilled[questKill.id].amount; } } if (quest.task.contacts.Length > 0) { newActiveQuests.contacts = new Quest.QuestContact[quest.task.contacts.Length]; foreach (Quest.QuestContact questContact in quest.task.contacts) { newActiveQuests.contacts[questContact.id] = new Quest.QuestContact(); if (!npcContacted.ContainsKey(questContact.id)) { npcContacted.Add(questContact.id, new PlayerData.NpcContact()); } newActiveQuests.contacts[questContact.id].initialAmount = npcContacted[questContact.id].amount; } } if (quest.task.locations.Length > 0) { newActiveQuests.locations = new Quest.QuestLocation[quest.task.locations.Length]; foreach (Quest.QuestLocation questLocation in quest.task.locations) { newActiveQuests.locations[questLocation.id] = new Quest.QuestLocation(); if (!getDestination.ContainsKey(questLocation.id)) { getDestination.Add(questLocation.id, new PlayerData.Destination()); } newActiveQuests.locations[questLocation.id].initialAmount = getDestination[questLocation.id].amount; } } if (quest.task.items.Length > 0) { newActiveQuests.items = new Quest.QuestItem[quest.task.items.Length]; foreach (Quest.QuestItem questItem in quest.task.items) { newActiveQuests.items[questItem.id] = new Quest.QuestItem(); if (!playerItem.ContainsKey(questItem.id)) { playerItem.Add(questItem.id, new Item()); } newActiveQuests.items[questItem.id].initialAmount = playerItem[questItem.id].amount; } } activeQuests.Add(id, newActiveQuests); }
//NB Because of how bidding is handled, this method is redundant - nextBid handles that for us. /* * public void discardAfterWinningTest(Card[] hand, ActiveQuest quest){ * Card[] disco = new Card[1]; * switch (strategy) { * case 1: * break; * * case 2: * if (quest.getCurrentStageNum () == 0) { * for (int i = 0; i < hand.Length; i++) { * if (hand [i].getType () == "foe" && hand [i].getBP () < 25) { * disco [0] = hand [i]; * player.discardCard (disco); * } * } * } else { * for (int i = 0; i < hand.Length; i++) { * for (int j = 0; j < hand.Length; j++) { * if (i == j) { * continue; * } * if (hand [i].getName () == hand [j].getName ()) { * disco [0] = hand [j]; * player.discardCard (disco); * hand [j] = new AdvCard (null, -1); * } * } * } * } * break; * } * * } */ //AI submits cards for current quest stage (as a sponsor). public abstract void sponsorQuestSetup(ActiveQuest quest);
void AddNewQuest(ActiveQuest quest) { quests.Add(quest); UpdateQuestsText(); }
//AI submits cards for current quest stage (as a player). public abstract Card[] playQuestStage(ActiveQuest quest);
void UpdateQuestsText(ActiveQuest quest) { UpdateQuestsText(); }
void UpdateQuestsText(ActiveQuest quest, ActiveQuest.Objective objective) { UpdateQuestsText(); }
abstract public Card[] nextBid(ActiveQuest quest);