// MapEventSide.ApplySimulationDamageToSelectedTroop
        public static bool ApplySimulationDamageToSelectedTroop(MapEventSide side,
                                                                CharacterObject strikedTroop,
                                                                PartyBase strikedTroopParty,
                                                                UniqueTroopDescriptor strikedTroopDescriptor,
                                                                int selectedSimulationTroopIndex,
                                                                List <UniqueTroopDescriptor> strikedTroopList,
                                                                PartyAttackComposition attack,
                                                                DamageTypes damageType,
                                                                PartyBase strikerParty,
                                                                MapEventState mapEventState,
                                                                IBattleObserver battleObserver,
                                                                out float damage)
        {
            bool IsFinishingStrike = mapEventState.ApplyDamageToPartyTroop(attack, strikedTroopParty, strikedTroop, out damage);

            if (IsFinishingStrike)
            {
                if (strikedTroop.IsHero)
                {
                    battleObserver?.TroopNumberChanged(side.MissionSide, (IBattleCombatant)strikedTroopParty, (BasicCharacterObject)strikedTroop, -1, 0, 1, 0, 0, 0);
                }
                else
                {
                    float survivalChance = Campaign.Current.Models.PartyHealingModel.GetSurvivalChance(strikedTroopParty, strikedTroop, damageType, strikerParty);
                    if (MBRandom.RandomFloat < survivalChance)
                    {
                        side.OnTroopWounded(strikedTroopDescriptor);
                        battleObserver?.TroopNumberChanged(side.MissionSide, (IBattleCombatant)strikedTroopParty, (BasicCharacterObject)strikedTroop, -1, 0, 1, 0, 0, 0);
                        if (strikedTroopParty.MobileParty != null)
                        {
                            SkillLevelingManager.OnSurgeryApplied(strikedTroopParty.MobileParty, 1f);
                        }
                    }
                    else
                    {
                        side.OnTroopKilled(strikedTroopDescriptor);
                        battleObserver?.TroopNumberChanged(side.MissionSide, (IBattleCombatant)strikedTroopParty, (BasicCharacterObject)strikedTroop, -1, 1, 0, 0, 0, 0);
                        if (strikedTroopParty.MobileParty != null)
                        {
                            SkillLevelingManager.OnSurgeryApplied(strikedTroopParty.MobileParty, 0.5f);
                        }
                    }
                }

                // side.RemoveSelectedTroopFromSimulationList();
                RemoveSelectedTroopFromSimulationList(side, selectedSimulationTroopIndex, strikedTroopList);
            }
            return(IsFinishingStrike);
        }
        public override void OnScoreHit(Agent affectedAgent, Agent affectorAgent, int affectorWeaponKind, bool isBlocked, float damage, float movementSpeedDamageModifier, float hitDistance, AgentAttackType attackType, float shotDifficulty, int weaponCurrentUsageIndex)
        {
            try
            {
                //Check to see if the affector is a hero
                if (affectedAgent == null || affectedAgent.Character == null || affectorAgent == null || affectorAgent.Character == null || !affectorAgent.IsHero)
                {
                    return;
                }

                Hero affectorHero = ((CharacterObject)affectorAgent.Character).HeroObject;
                //If the hero is not the player or in the player's party, don't do anything
                if (affectorHero != null && (affectorHero == Hero.MainHero ||
                                             affectorHero.PartyBelongedTo != null && affectorHero.PartyBelongedTo == Hero.MainHero.PartyBelongedTo))
                {
                    Hero captainHero   = null;
                    Hero commanderHero = null;
                    //If the affector is the player's companion, set the commander and captain as the player.
                    if (affectorHero != Hero.MainHero)
                    {
                        CharacterObject leaderCharacter = (CharacterObject)affectorAgent.Team.Leader.Character;
                        if (leaderCharacter.HeroObject == Hero.MainHero)
                        {
                            captainHero   = Hero.MainHero;
                            commanderHero = Hero.MainHero;
                        }
                    }
                    float hitPointRatio = (Math.Min(damage, affectedAgent.HealthLimit) / affectedAgent.HealthLimit) * 0.5f;
                    bool  isTeamKill    = affectorAgent.Team == affectedAgent.Team;
                    bool  isFatal       = affectedAgent.Health <= 0;

                    SkillLevelingManager.OnCombatHit(affectorAgent.Character as CharacterObject, affectedAgent.Character as CharacterObject,
                                                     captainHero, commanderHero, movementSpeedDamageModifier, shotDifficulty, affectorWeaponKind, hitPointRatio, false, affectorAgent.HasMount,
                                                     isTeamKill, false, weaponCurrentUsageIndex, damage, isFatal);
                    //MessageBox.Show($"Did this!\nAffector:{affectorAgent.Character.Name}\nAffected:{affectedAgent.Character.Name}");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"An error occurred during Tournament experience logic:\n\n{ex.ToStringFull()}");
            }
        }
        public override void OnScoreHit(Agent affectedAgent, Agent affectorAgent, int affectorWeaponKind, bool isBlocked, float damage, float movementSpeedDamageModifier, float hitDistance, AgentAttackType attackType, float shotDifficulty, int weaponCurrentUsageIndex)
        {
            try
            {
                Hero affectorHero;

                if (!IsValidAffected(affectedAgent) || !IsValidAffector(affectorAgent, out affectorHero))
                {
                    return;
                }

                if (affectorHero != null)
                {
                    Hero captainHero   = null;
                    Hero commanderHero = null;
                    //If the affector is the player's companion, set the commander and captain as the player.
                    if (affectorHero != Hero.MainHero)
                    {
                        CharacterObject leaderCharacter = (CharacterObject)affectorAgent.Team.Leader.Character;
                        if (leaderCharacter.HeroObject == Hero.MainHero)
                        {
                            captainHero   = Hero.MainHero;
                            commanderHero = Hero.MainHero;
                        }
                    }
                    float hitPointRatio = (Math.Min(damage, affectedAgent.HealthLimit) / affectedAgent.HealthLimit) * 0.5f;
                    bool  isTeamKill    = affectorAgent.Team == affectedAgent.Team;
                    bool  isFatal       = affectedAgent.Health <= 0;

                    //MessageBox.Show($"Giving experience to {affectorAgent.Character.Name} in tournament.\nAffected:{affectedAgent.Character.Name}\nCaptain: {captainHero?.Name?.ToString()}");

                    SkillLevelingManager.OnCombatHit(affectorAgent.Character as CharacterObject, affectedAgent.Character as CharacterObject,
                                                     captainHero, commanderHero, movementSpeedDamageModifier, shotDifficulty, affectorWeaponKind, hitPointRatio, false, affectorAgent.HasMount,
                                                     isTeamKill, false, weaponCurrentUsageIndex, damage, isFatal);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"An error occurred during Tournament experience logic:\n\n{ex.ToStringFull()}");
            }
        }
Beispiel #4
0
        // TODO: track total cost, and only upgrade if player can afford X number of this upgrade to prevent spending all their money.
        public static void UpgradeParty(PartyBase party)
        {
            var memberRoster = party.MemberRoster;
            var troopUpgradeMetadataCollection = new List <TroopUpgradeMetadata>();

            for (var memberIndex = 0; memberIndex < memberRoster.Count; ++memberIndex)
            {
                var elementCopyAtIndex = memberRoster.GetElementCopyAtIndex(memberIndex);
                if (!elementCopyAtIndex.HasHigherTierToUpgradeTo())
                {
                    continue;
                }

                var upgradeXpCostPerUnit = elementCopyAtIndex.Character.UpgradeXpCost;
                var totalUnitsReadyToUpgradeInElement = elementCopyAtIndex.NumberReadyToUpgrade;
                for (var upgradeTargetIndex = 0; upgradeTargetIndex < elementCopyAtIndex.Character.UpgradeTargets.Length; ++upgradeTargetIndex)
                {
                    var totalUnitsToUpgradeInElement = totalUnitsReadyToUpgradeInElement;
                    var upgradeTarget = elementCopyAtIndex.Character.UpgradeTargets[upgradeTargetIndex]; // the higher tier unit type to upgrade to
                    var costToUpgradeToHigherTierPerUnit = elementCopyAtIndex.Character.UpgradeCost(party, upgradeTargetIndex);
                    var totalCostToUpgradeToHigherTier   = totalUnitsToUpgradeInElement * costToUpgradeToHigherTierPerUnit;
                    if (party.LeaderHero != null && costToUpgradeToHigherTierPerUnit != 0 && totalCostToUpgradeToHigherTier > party.LeaderHero.Gold)
                    {
                        totalUnitsToUpgradeInElement = party.LeaderHero.Gold / costToUpgradeToHigherTierPerUnit;
                    }
                    var canUpgrade = true;
                    if (elementCopyAtIndex.Character.UpgradeTargets[upgradeTargetIndex].UpgradeRequiresItemFromCategory != null)
                    {
                        canUpgrade = false;
                        var totalItemsAvailableToSupplyTroopUpgrade = 0;
                        foreach (var itemRosterElement in party.ItemRoster)
                        {
                            if (itemRosterElement.EquipmentElement.Item.ItemCategory == upgradeTarget.UpgradeRequiresItemFromCategory)
                            {
                                totalItemsAvailableToSupplyTroopUpgrade += itemRosterElement.Amount;
                                canUpgrade = true;
                                if (totalItemsAvailableToSupplyTroopUpgrade >= totalUnitsToUpgradeInElement)
                                {
                                    break;
                                }
                            }
                        }
                        if (canUpgrade)
                        {
                            totalUnitsToUpgradeInElement = Math.Min(totalItemsAvailableToSupplyTroopUpgrade, totalUnitsToUpgradeInElement);
                        }
                    }
                    if (party.Culture.IsBandit)
                    {
                        canUpgrade = elementCopyAtIndex.Character.UpgradeTargets[upgradeTargetIndex].Culture.IsBandit;
                    }
                    if (canUpgrade && totalUnitsToUpgradeInElement > 0)
                    {
                        troopUpgradeMetadataCollection.Add(
                            new TroopUpgradeMetadata(
                                memberIndex,
                                elementCopyAtIndex.Character.UpgradeTargets[upgradeTargetIndex],
                                totalUnitsToUpgradeInElement,
                                costToUpgradeToHigherTierPerUnit
                                )
                            );
                    }
                }
                if (troopUpgradeMetadataCollection.Any())
                {
                    var randomElement = troopUpgradeMetadataCollection.GetRandomElement();
                    var upgradedTierCharacterObject      = randomElement.CharacterUpgradeTarget;
                    var totalUnitsToUpgradeInElement     = randomElement.TotalUnitsToUpgradeInElement;
                    var costToUpgradeToHigherTierPerUnit = randomElement.CostToUpgradeToHigherTierPerUnit;
                    var totalUpgradeXpCost = upgradeXpCostPerUnit * totalUnitsToUpgradeInElement;
                    memberRoster.SetElementXp(memberIndex, memberRoster.GetElementXp(memberIndex) - totalUpgradeXpCost);
                    memberRoster.AddToCounts(elementCopyAtIndex.Character, -totalUnitsToUpgradeInElement);
                    memberRoster.AddToCounts(upgradedTierCharacterObject, totalUnitsToUpgradeInElement);
                    if (upgradedTierCharacterObject.UpgradeRequiresItemFromCategory != null)
                    {
                        var newTotalUnitsToUpgradeInElement = totalUnitsToUpgradeInElement;
                        foreach (var itemRosterElement in party.ItemRoster)
                        {
                            if (itemRosterElement.EquipmentElement.Item.ItemCategory == upgradedTierCharacterObject.UpgradeRequiresItemFromCategory)
                            {
                                var totalUnitsToUpgradeInElementDueToItemRequirements = Math.Min(newTotalUnitsToUpgradeInElement, itemRosterElement.Amount);
                                party.ItemRoster.AddToCounts(itemRosterElement.EquipmentElement.Item, -totalUnitsToUpgradeInElementDueToItemRequirements);
                                newTotalUnitsToUpgradeInElement -= totalUnitsToUpgradeInElementDueToItemRequirements;
                                if (newTotalUnitsToUpgradeInElement == 0)
                                {
                                    break;
                                }
                            }
                        }
                    }
                    var totalCostToUpgradeUnitsInElement = costToUpgradeToHigherTierPerUnit * totalUnitsToUpgradeInElement;
                    if (party.Owner.Gold < totalCostToUpgradeUnitsInElement)
                    {
                        totalUnitsToUpgradeInElement = party.Owner.Gold / costToUpgradeToHigherTierPerUnit;
                    }
                    if (totalUnitsToUpgradeInElement > 0)
                    {
                        if (party.Owner != null)
                        {
                            SkillLevelingManager.OnUpgradeTroops(party, upgradedTierCharacterObject, totalUnitsToUpgradeInElement);
                            GiveGoldAction.ApplyBetweenCharacters(party.Owner, null, totalCostToUpgradeUnitsInElement, true);
                        }
                        else if (party.LeaderHero != null)
                        {
                            SkillLevelingManager.OnUpgradeTroops(party, upgradedTierCharacterObject, totalUnitsToUpgradeInElement);
                            GiveGoldAction.ApplyBetweenCharacters(party.LeaderHero, null, totalCostToUpgradeUnitsInElement, true);
                        }
                    }
                }
            }
        }
        public static void UpgradeReadyTroops(PartyBase party)
        {
            var memberRoster        = party.MemberRoster;
            var troopUpgradeModel   = Campaign.Current.Models.PartyTroopUpgradeModel;
            var cavalryRatioAtParty = party.MobileParty == null || party.MobileParty.IsGarrison || party.MobileParty.IsMilitia || party.MobileParty.IsVillager ? 1f : party.NumberOfMenWithHorse / (party.NumberOfAllMembers + 0.1f);

            for (var index1 = 0; index1 < memberRoster.Count; ++index1)
            {
                var elementCopyAtIndex = memberRoster.GetElementCopyAtIndex(index1);
                if (troopUpgradeModel.IsTroopUpgradeable(party, elementCopyAtIndex.Character))
                {
                    var characterObjects     = new List <Tuple <CharacterObject, int, int> >();
                    var numberReadyToUpgrade = elementCopyAtIndex.NumberReadyToUpgrade;
                    var upgradeXpCost        = elementCopyAtIndex.Character.UpgradeXpCost;
                    if (numberReadyToUpgrade > elementCopyAtIndex.Number - elementCopyAtIndex.WoundedNumber)
                    {
                        numberReadyToUpgrade = elementCopyAtIndex.Number - elementCopyAtIndex.WoundedNumber;
                    }

                    if (numberReadyToUpgrade > 0)
                    {
                        for (var index2 = 0; index2 < elementCopyAtIndex.Character.UpgradeTargets.Length; ++index2)
                        {
                            var upgradeTarget   = elementCopyAtIndex.Character.UpgradeTargets[index2];
                            var upgradeGoldCost = elementCopyAtIndex.Character.UpgradeCost(party, index2);
                            if (party.LeaderHero != null && upgradeGoldCost != 0 && numberReadyToUpgrade * upgradeGoldCost > party.LeaderHero.Gold)
                            {
                                numberReadyToUpgrade = party.LeaderHero.Gold / upgradeGoldCost;
                            }

                            if (party.Owner != null && elementCopyAtIndex.Character.UpgradeTargets[index2].UpgradeRequiresItemFromCategory != null)
                            {
                                var flag      = false;
                                var itemCount = 0;
                                foreach (var itemRosterElement in party.ItemRoster)
                                {
                                    if (itemRosterElement.EquipmentElement.Item.ItemCategory == upgradeTarget.UpgradeRequiresItemFromCategory)
                                    {
                                        itemCount += itemRosterElement.Amount;
                                        flag       = true;
                                        if (itemCount >= numberReadyToUpgrade)
                                        {
                                            break;
                                        }
                                    }
                                }

                                if (flag)
                                {
                                    numberReadyToUpgrade = Math.Min(itemCount, numberReadyToUpgrade);
                                }
                            }

                            //if (party.Culture.IsBandit)
                            //  flag = elementCopyAtIndex.Character.UpgradeTargets[index2].Culture.IsBandit;
                            //if (elementCopyAtIndex.Character.Occupation == Occupation.Bandit)
                            //  flag = troopUpgradeModel.CanPartyUpgradeTroopToTarget(party, elementCopyAtIndex.Character, elementCopyAtIndex.Character.UpgradeTargets[index2]);
                            if (numberReadyToUpgrade > 0)
                            {
                                characterObjects.Add(new Tuple <CharacterObject, int, int>(elementCopyAtIndex.Character.UpgradeTargets[index2], numberReadyToUpgrade, upgradeGoldCost));
                            }
                        }

                        if (characterObjects.Count > 0)
                        {
                            var character = characterObjects.GetRandomElement();
                            if (party.IsMobile && party.LeaderHero != null && cavalryRatioAtParty < 0.360000014305115)
                            {
                                var num2 = 0f;
                                foreach (var tuple2 in characterObjects)
                                {
                                    num2 += CalculateUpgradeChance(tuple2.Item1, 1f, cavalryRatioAtParty);
                                }

                                var num3 = num2 * MBRandom.RandomFloat;
                                foreach (var tuple2 in characterObjects)
                                {
                                    num3 -= CalculateUpgradeChance(tuple2.Item1, 1f, cavalryRatioAtParty);
                                    if (num3 < 0.0)
                                    {
                                        character = tuple2;
                                        break;
                                    }
                                }
                            }

                            var characterObject = character.Item1;
                            var numberToUpgrade = character.Item2;
                            var upgradeGoldCost = character.Item3;
                            var totalXpCost     = upgradeXpCost * numberToUpgrade;
                            memberRoster.SetElementXp(index1, memberRoster.GetElementXp(index1) - totalXpCost);
                            memberRoster.AddToCounts(elementCopyAtIndex.Character, -numberToUpgrade);
                            memberRoster.AddToCounts(characterObject, numberToUpgrade);
                            var gold          = party.Owner?.Gold;
                            var totalGoldCost = upgradeGoldCost * numberToUpgrade;
                            if ((gold.GetValueOrDefault() < totalGoldCost) & gold.HasValue)
                            {
                                numberToUpgrade = party.Owner.Gold / upgradeGoldCost;
                            }

                            if (numberToUpgrade > 0)
                            {
                                if (party.Owner != null)
                                {
                                    SkillLevelingManager.OnUpgradeTroops(party, characterObject, numberToUpgrade);
                                    GiveGoldAction.ApplyBetweenCharacters(party.Owner, null, upgradeGoldCost * numberToUpgrade, true);
                                }
                                else if (party.LeaderHero != null)
                                {
                                    SkillLevelingManager.OnUpgradeTroops(party, characterObject, numberToUpgrade);
                                    GiveGoldAction.ApplyBetweenCharacters(party.LeaderHero, null, upgradeGoldCost * numberToUpgrade, true);
                                }
                            }
                        }
                    }
                }
            }
        }
        internal static bool Prefix(ref bool __result, ref MapEventSide __instance, ref CharacterObject ____selectedSimulationTroop, ref UniqueTroopDescriptor ____selectedSimulationTroopDescriptor, int damage, DamageTypes damageType, out int troopState, PartyBase strikerParty)
        {
            if (strikerParty.MapEvent != null && SimulationModel.IsValidEventType(strikerParty.MapEvent.EventType))
            {
                if (SimulationsPool.TryGetSimulationModel(strikerParty.MapEvent.Id, out var simulationModel))
                {
                    SimulationTroopState simulationTroopState = SimulationTroopState.Alive;
                    __result = false;

                    // try to find the attacked troop in our model. Id doesn't exist call vanilla method
                    var troopId = ____selectedSimulationTroop.Id;
                    var troop   = simulationModel.Parties[(int)__instance.MissionSide].Troops.Find(t => t.CharacterObject.Id == troopId);
                    if (troop == null)
                    {
                        troopState = (int)simulationTroopState;
                        return(true);
                    }

                    var battleObserver  = MapEventSideAccessTools.GetBattleObserver(__instance);
                    var allocatedTroops = MapEventSideAccessTools.GetAllocatedTroops(__instance);

                    // troop is a Hero logic
                    if (____selectedSimulationTroop.IsHero)
                    {
                        __instance.AddHeroDamage(____selectedSimulationTroop.HeroObject, damage);
                        if (____selectedSimulationTroop.HeroObject.IsWounded)
                        {
                            __result             = true;
                            simulationTroopState = SimulationTroopState.Wounded;
                            if (battleObserver != null)
                            {
                                battleObserver.TroopNumberChanged(__instance.MissionSide, __instance.GetAllocatedTroopParty(____selectedSimulationTroopDescriptor), ____selectedSimulationTroop, -1, 0, 1, 0, 0, 0);
                            }
                        }
                    }
                    // regular logic
                    else if (troop.ApplyDamage(damage))
                    {
                        PartyBase party          = allocatedTroops[____selectedSimulationTroopDescriptor].Party;
                        float     survivalChance = Campaign.Current.Models.PartyHealingModel.GetSurvivalChance(party, ____selectedSimulationTroop, damageType, strikerParty);

                        if (MBRandom.RandomFloat < survivalChance)
                        {
                            __instance.OnTroopWounded(____selectedSimulationTroopDescriptor);
                            simulationTroopState = SimulationTroopState.Wounded;
                            if (battleObserver != null)
                            {
                                battleObserver.TroopNumberChanged(__instance.MissionSide, __instance.GetAllocatedTroopParty(____selectedSimulationTroopDescriptor), ____selectedSimulationTroop, -1, 0, 1, 0, 0, 0);
                            }
                            SkillLevelingManager.OnSurgeryApplied(party.MobileParty, 1f);
                        }
                        else
                        {
                            __instance.OnTroopKilled(____selectedSimulationTroopDescriptor);
                            simulationTroopState = SimulationTroopState.Kille;

                            if (battleObserver != null)
                            {
                                battleObserver.TroopNumberChanged(__instance.MissionSide, __instance.GetAllocatedTroopParty(____selectedSimulationTroopDescriptor), ____selectedSimulationTroop, -1, 1, 0, 0, 0, 0);
                            }
                            SkillLevelingManager.OnSurgeryApplied(party.MobileParty, 0.5f);
                        }
                        __result = true;
                    }

                    if (__result)
                    {
                        __instance.RemoveSelectedTroopFromSimulationList();
                    }

                    troopState = (int)simulationTroopState;
                    return(false);
                }
            }
            troopState = 1;
            return(true);
        }