// 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); }
private static bool StrikeOnce(MapEvent mapEvent, IBattleObserver battleObserver, MapEventSide strikerSide, MapEventSide strikedSide, PartyAttackComposition attack, out float totalDamageDone) { int strikerNumber = strikerSide.NumRemainingSimulationTroops; int strikedNumber = strikedSide.NumRemainingSimulationTroops; totalDamageDone = 0; if (strikerNumber == 0 || strikedNumber == 0) { return(true); } MapEventState mapEventState = MapEventState.GetMapEventState(mapEvent); bool finishedAnyone = false; for (int index = strikedNumber - 1; index >= 0; index--) { UniqueTroopDescriptor strikerTroopDescriptor = strikerSide.SelectRandomSimulationTroop(); CharacterObject strikerTroop = strikerSide.GetAllocatedTroop(strikerTroopDescriptor); PartyBase strikerTroopParty = strikerSide.GetAllocatedTroopParty(strikerTroopDescriptor); UniqueTroopDescriptor strikedTroopDescriptor = MapEventSideHelper.SelectSimulationTroopAtIndex(strikedSide, index, out List <UniqueTroopDescriptor> strikedTroopList); CharacterObject strikedTroop = strikedSide.GetAllocatedTroop(strikedTroopDescriptor); PartyBase strikedTroopParty = strikedSide.GetAllocatedTroopParty(strikedTroopDescriptor); // MapEvents.GetSimulatedDamage and CombatSimulationModel.SimulateHit if (mapEvent.IsPlayerSimulation && strikedTroopParty == PartyBase.MainParty) { float damageMultiplier = Campaign.Current.Models.DifficultyModel.GetPlayerTroopsReceivedDamageMultiplier(); attack *= damageMultiplier; } DamageTypes damageType = (double)MBRandom.RandomFloat < 0.15 ? DamageTypes.Blunt : DamageTypes.Cut; bool isFinishingStrike = MapEventSideHelper.ApplySimulationDamageToSelectedTroop( strikedSide, strikedTroop, strikedTroopParty, strikedTroopDescriptor, index, strikedTroopList, attack, damageType, strikerTroopParty, mapEventState, battleObserver, out float damage); totalDamageDone += damage; strikerSide.ApplySimulatedHitRewardToSelectedTroop(strikedTroop, 0, isFinishingStrike); finishedAnyone = finishedAnyone || isFinishingStrike; } return(finishedAnyone); }
public void SetObserver(IBattleObserver observer) { this.BattleObserver = observer; }
public void registerObserver(IBattleObserver observer) { this.observer = observer; }
public void start() { observer = null; pokemonBattleManager = new PokemonBattleManager(); state = BattleState.Inactive; }
/// <summary> /// Remove an observer that no longer wants to be notified about events /// </summary> /// <param name="battleObserver"></param> public void UnSubscribe(IBattleObserver battleObserver) { observers.Remove(battleObserver); }
/// <summary> /// Adds an observer that wants to be notified about events /// </summary> /// <param name="battleObserver"></param> public void Subscribe(IBattleObserver battleObserver) { observers.Add(battleObserver); }
/// <summary> /// Remove an observer that no longer wants to be notified about events /// </summary> /// <param name="battleObserver"></param> public void UnSubscribe(IBattleObserver battleObserver) { observers.Remove(battleObserver); }
/// <summary> /// Adds an observer that wants to be notified about events /// </summary> /// <param name="battleObserver"></param> public void Subscribe(IBattleObserver battleObserver) { observers.Add(battleObserver); }
public static bool Prefix(ref bool __result, MapEvent __instance, float strikerAdvantage) { MapEventSide attackerSide = __instance.AttackerSide; MapEventSide defenderSide = __instance.DefenderSide; MapEventState mapEventState = MapEventState.GetMapEventState(__instance); IBattleObserver battleObserver = (IBattleObserver)MapEvent_BattleObserver.GetValue(__instance); int attackerNumber = attackerSide.NumRemainingSimulationTroops; int defenderNumber = defenderSide.NumRemainingSimulationTroops; float strengthOfNumber; if (mapEventState.IsSiege) { strengthOfNumber = SubModule.Settings.Battle_SendAllTroops_SiegeStrengthOfNumber; //if (SubModule.Settings.Battle_SendAllTroops_DetailedCombatModel) //{ // if (mapEventState.GateBreached) // { // strengthOfNumber = (SubModule.Settings.Battle_SendAllTroops_SiegeStrengthOfNumber // + SubModule.Settings.Battle_SendAllTroops_StrengthOfNumber) / 2; // } // else // { // strengthOfNumber = SubModule.Settings.Battle_SendAllTroops_SiegeStrengthOfNumber; // } //} //else //{ // strengthOfNumber = SubModule.Settings.Battle_SendAllTroops_SiegeStrengthOfNumber; //} } else { strengthOfNumber = SubModule.Settings.Battle_SendAllTroops_StrengthOfNumber; } float battleSpeedMultiplier = DamageMultiplier; if (strengthOfNumber != 0.6f) { // Normalized battle speed to that of 0.6 double biggerPartyNumber = Math.Max(attackerNumber, defenderNumber); battleSpeedMultiplier *= (float)Math.Pow(biggerPartyNumber, 0.6 - strengthOfNumber); } float attackerNumberPenalty = (float)Math.Pow((double)attackerNumber, strengthOfNumber - 1.0); float defenderNumberPenalty = (float)Math.Pow((double)defenderNumber, strengthOfNumber - 1.0); PartyAttackComposition attackerTotalAttack = new PartyAttackComposition(); PartyAttackComposition defenderTotalAttack = new PartyAttackComposition(); foreach (var party in attackerSide.Parties) { attackerTotalAttack += mapEventState.MakePartyAttack(party, battleSpeedMultiplier * attackerNumberPenalty / RangedAverageDamagePerHit); } foreach (var party in defenderSide.Parties) { defenderTotalAttack += mapEventState.MakePartyAttack(party, battleSpeedMultiplier * defenderNumberPenalty / RangedAverageDamagePerHit); } float attackerAdvantage = BattleAdvantageModel.PartyBattleAdvantage(attackerSide.LeaderParty); float defenderAdvantage = BattleAdvantageModel.PartyBattleAdvantage(defenderSide.LeaderParty); PartyAttackComposition attackerDistributedAttack = attackerTotalAttack * (battleSpeedMultiplier * attackerNumberPenalty * attackerAdvantage * mapEventState.SettlementPenalty / defenderNumber); PartyAttackComposition defenderDistributedAttack = defenderTotalAttack * (battleSpeedMultiplier * defenderNumberPenalty * defenderAdvantage / attackerNumber); bool finishedAnyone = false; finishedAnyone |= StrikeOnce(__instance, battleObserver, attackerSide, defenderSide, attackerDistributedAttack, out float attackerTotalDamageDone); finishedAnyone |= StrikeOnce(__instance, battleObserver, defenderSide, attackerSide, defenderDistributedAttack, out float defenderTotalDamageDone); // Distribute XP among all living int AttackerAverageDamageDone = (int)Math.Round(Math.Min(attackerTotalDamageDone / attackerNumber, 1)); try { for (int index = 0; index < attackerSide.NumRemainingSimulationTroops; index++) { MapEventSideHelper.SelectSimulationTroopAtIndex(attackerSide, index, out _); attackerSide.ApplySimulatedHitRewardToSelectedTroop(null, AttackerAverageDamageDone, false); } int DefenderAverageDamageDone = (int)Math.Round(Math.Min(defenderTotalDamageDone / defenderNumber, 1)); for (int index = 0; index < attackerSide.NumRemainingSimulationTroops; index++) { MapEventSideHelper.SelectSimulationTroopAtIndex(attackerSide, index, out _); attackerSide.ApplySimulatedHitRewardToSelectedTroop(null, DefenderAverageDamageDone, false); } } catch (NullReferenceException) { // CombatXpModel.GetXpFromHit is changed by other mod and not accepting attackedTroop == null } __result = finishedAnyone; return(false); }