// Update is called once per frame void Update() { if (Input.GetKeyDown(KeyCode.Space)) { results = GameManager.instance.DetermineBattleOutcome(heroes, quest); Debug.Log(results); } if (Input.GetKeyDown(KeyCode.A)) { GameManager.instance.uiManager.UpdateCharacterWindow(heroes[0]); } if (Input.GetKeyDown(KeyCode.Q)) { StartCoroutine(TestMove()); } }
public QuestOutcome DetermineBattleOutcome(List <HeroPawn> heroes, QuestData quest) { // Takes in party and quest, determines battle outcomes QuestOutcome results = new QuestOutcome(); // Aggregate total party float heroAggregateHealth = 0; float heroAggregateAttack = 0; float heroAggregateDefense = 0; foreach (HeroPawn hero in heroes) { heroAggregateAttack += ValueBasedOnDurability(hero.heroData.attack, hero.weaponCondition); heroAggregateDefense += ValueBasedOnDurability(hero.heroData.defense, hero.armorCondition); heroAggregateHealth += hero.heroData.health; // Since durability hits EVERY fight, We can reduce durability here, and save us another iteration through heroes hero.weaponCondition -= Random.Range(quest.minDurabilityDamage, quest.maxDurabilityDamage); hero.armorCondition -= Random.Range(quest.minDurabilityDamage, quest.maxDurabilityDamage); } // Add advantages -- be sure to check for monster changes foreach (HeroPawn hero in heroes) { float bonusModifier = 1.0f; // Start at full bonus // iterate through disadvantages bool foundDisadvantage = false; foreach (Disadvantage disadvantage in hero.heroData.disadvantages) { // iterate through monsters foreach (MonsterData monster in quest.monsters) { // Iterate through each monsters set of types foreach (MonsterTag tag in monster.modifiers) { // if we find one of those types in our disadvantage, note it and quit if (disadvantage.against.Contains(tag)) { // TODO: Add event about the disadvantage Debug.Log(hero.heroData.displayName + " is terrified of the " + tag.displayName + " " + monster.displayName); foundDisadvantage = true; break; } } // If I found a disadvantage, I don't need to look at other monsters if (foundDisadvantage) { break; } } // If I found a disadvantage, I don't need to look at other disadvantages if (foundDisadvantage) { break; } } // If we found a disadvantage if (foundDisadvantage) { // create a bonus modifier based on average relationships bonusModifier = bonusEffectByRelationshipAverageCurve.Evaluate(AveragePartyRelationship(heroes) / maxRelationshipLevel); } // Otherwise, our bonus modifier is still 1.0 else { bonusModifier = 1.0f; } // iterate through advantages foreach (Advantage advantage in hero.heroData.advantages) { //Apply "advantage.amount * modifier* and add to aggregates if (advantage.statistic == Stat.Attack) { heroAggregateAttack += advantage.bonusAmount * bonusModifier; Debug.Log("The power of friendship adds " + (advantage.bonusAmount * bonusModifier) + " | " + bonusModifier + " / " + advantage.bonusAmount + " attack."); } if (advantage.statistic == Stat.Health) { heroAggregateHealth += advantage.bonusAmount * bonusModifier; Debug.Log("The power of friendship adds " + (advantage.bonusAmount * bonusModifier) + " | " + bonusModifier + " / " + advantage.bonusAmount + " health."); } if (advantage.statistic == Stat.Defense) { heroAggregateDefense += advantage.bonusAmount * bonusModifier; Debug.Log("The power of friendship adds " + (advantage.bonusAmount * bonusModifier) + " | " + bonusModifier + " / " + advantage.bonusAmount + " defense."); } } } // NOTE: DO NOT CHANGE MONSTERS. Make temp monsters and change the temp ones float monsterAggregateHealth = 0; float monsterAggregateAttack = 0; float monsterAggregateDefense = 0; foreach (MonsterData monster in quest.monsters) { monsterAggregateAttack += monster.attack; monsterAggregateDefense += monster.defense; monsterAggregateHealth += monster.health; } // Track number of rounds int numberOfRounds = 0; // As long as the monsters are alive while (monsterAggregateHealth > 0) { // Increase round count numberOfRounds++; // Damage monsters float damageDone = Mathf.Max(1, (heroAggregateAttack * Random.Range(minHeroBattleChance, maxHeroBattleChance)) - (monsterAggregateDefense * Random.Range(minMonsterBattleChance, maxMonsterBattleChance))); monsterAggregateHealth -= damageDone; Debug.Log("The party does " + damageDone + " damage. The monster party has a total of " + monsterAggregateHealth + " health left!"); // If monster dead, break. if (monsterAggregateHealth <= 0) { break; } // Damage players damageDone = Mathf.Max(1, (monsterAggregateAttack * Random.Range(minMonsterBattleChance, maxMonsterBattleChance)) - (heroAggregateDefense * Random.Range(minHeroBattleChance, maxHeroBattleChance))); heroAggregateHealth -= damageDone; Debug.Log("The monster party does " + damageDone + " damage. The party has a total of " + heroAggregateHealth + " health left!"); // If players dead, break if (heroAggregateHealth <= 0) { break; } } // If monsters are dead, success. if (monsterAggregateHealth <= 0) { // Add gold to all players foreach (HeroPawn hero in heroes) { // Divide gold among heroes, leftovers are destroyed into the ether hero.gold += (int)(quest.goldReward / heroes.Count); //Update relationships foreach (HeroPawn otherHero in heroes) { if (otherHero != hero) { // Find where they are in the main heroes list int heroID = 0; for (int i = 0; i < GameManager.instance.heroes.Count; i++) { if (otherHero != hero && otherHero == GameManager.instance.heroes[i]) { heroID = i; break; } } hero.relationships[heroID] += increaseToRelationshipPerMission; Debug.Log(hero.heroData.displayName + " and " + GameManager.instance.heroes[heroID].heroData.displayName + " high five."); } } } // Add success events to the event list // TODO: Don't do one per round, that's too many. Maybe one per person. for (int i = 0; i < numberOfRounds; i++) { // Pick a random hero HeroPawn chosenOne = heroes[Random.Range(0, heroes.Count)]; // TODO: Pick a random string from the hero's success events string eventString = chosenOne.name + " stabs the vile beast in the face."; // TODO: Add the finalized (no variables) version of that string to the list of outcome events. results.events.Add(eventString); } } // Else failed mission else { // No change to relationships // No change to gold // Add fail events to the event list // TODO: Don't do one per round, that's too many. Maybe one per person. for (int i = 0; i < numberOfRounds; i++) { // Pick a random hero HeroPawn chosenOne = heroes[Random.Range(0, heroes.Count)]; // TODO: Pick a random string from the hero's success events string eventString = chosenOne.name + " stumbles."; // TODO: Add the finalized (no variables) version of that string to the list of outcome events. results.events.Add(eventString); } } return(results); }
public IEnumerator DoRunQuests() { Debug.Log("Starting to Run Quests"); // Turn on the results screen uiManager.OpenWindow(uiManager.QuestOutcomeDisplay); uiManager.OpenWindow(uiManager.MainGameButton); List <QuestObject> questsToRemove = new List <QuestObject>(); // For each quest that were available today foreach (QuestObject quest in shop.todaysQuests) { // If it has people assigned if (quest.heroes != null && quest.heroes.Count > 0) { // Disable the button nextStepButton.interactable = false; nextStepButtonText.text = "... Fighting! ..."; isWaitingForButton = true; // Calculate the results QuestOutcome results = DetermineBattleOutcome(quest.heroes, quest.questData); // TODO: coroutine to Update the quest screen to show results over time. uiManager.combatQuestTitleBox.text = "Results: " + quest.questData.displayName; uiManager.combatEventsLog.text = ""; foreach (string outcomeEvent in results.events) { // Wait some time. yield return(new WaitForSeconds(0.5f)); // Display the text uiManager.combatEventsLog.text += outcomeEvent + "\n"; } yield return(new WaitForSeconds(0.5f)); if (results.success) { uiManager.outcomeSummaryLineBox.text = "The party was victorious!"; } else { uiManager.outcomeSummaryLineBox.text = "The party was defeated!"; } isWaitingForButton = true; nextStepButtonText.text = "Continue"; nextStepButton.interactable = true; nextStepButton.onClick.RemoveAllListeners(); nextStepButton.onClick.AddListener(StopWaitingForButton); // Queue to Remove from today's quests questsToRemove.Add(quest); // Wait for button while (isWaitingForButton) { yield return(null); } } } // Actually handle the removals foreach (QuestObject quest in questsToRemove) { shop.todaysQuests.Remove(quest); } // ACTUALLY THE END OF THE DAY turnsRemaining--; if (turnsRemaining > 0) { // TODO: SHOW THE END OF DAY IMAGE // Turn on the results screen uiManager.CloseCurrentWindow(); uiManager.OpenWindow(uiManager.EndOfDayScreen); uiManager.OpenWindow(uiManager.MainGameButton); // TODO: Set text to say "DAYS REMAINING..." + days uiManager.endOfDayText.text = "Another day has ended... " + turnsRemaining + "days remain..."; // Enable the button nextStepButton.interactable = true; nextStepButtonText.text = "Start Next Day"; // Wait for button isWaitingForButton = true; while (isWaitingForButton) { yield return(null); } // Turn off the end of day text uiManager.CloseCurrentWindow(); // Move all characters offscreen on right side foreach (HeroPawn hero in heroes) { hero.transform.position = new Vector3(10, 0, 0); } // TODO: FIX THIS HARDCODING! THIS IS BAD! uiManager.EndOfDayScreen.SetActive(false); uiManager.QuestOutcomeDisplay.SetActive(false); uiManager.OpenWindow(uiManager.MainGameButton); // Start the day StartDay(); } yield return(null); }