Exemple #1
0
        public override bool CheckWinner(Player candidate = null)
        {
            TurnDirector ins = TurnDirector.Ins;

            if (candidate == null)
            {
                return(ins.ListPlayer.Count(item => !item.HasLost) <= 1);
            }
            else
            {
                return(ins.ListPlayer.Count(item => !item.HasLost) == 1 && !candidate.HasLost);
            }
        }
Exemple #2
0
 public static bool Prefix(TurnDirector __instance, VisibilityLevel contactLevel)
 {
     Mod.Log.Trace?.Write($"TD:NC - entered.");
     if (__instance.IsInterleaved && contactLevel == VisibilityLevel.None && !__instance.DoAnyUnitsHaveContactWithEnemy)
     {
         Mod.Log.Info?.Write("Intercepting lostContact state, allowing remainder of actors to move.");
         return(false);
     }
     else
     {
         return(true);
     }
 }
Exemple #3
0
 static void Postfix(TurnDirector __instance)
 {
     if (MissionControl.Instance.AllowMissionControl() && Main.Settings.HotDrop.Enable)
     {
         Main.LogDebug($"[TurnDirectorOnFirstContactPatch Postfix] Patching OnFirstContact");
         Main.LogDebug($"[TurnDirectorOnFirstContactPatch Postfix] Current round is '{__instance.CurrentRound}'");
         Main.LogDebug($"[TurnDirectorOnFirstContactPatch Postfix] DoAnyUnitsHaveContactWithEnemy '{__instance.DoAnyUnitsHaveContactWithEnemy}'");
         if (__instance.CurrentRound == 0 && __instance.DoAnyUnitsHaveContactWithEnemy)
         {
             ProtectHotDroppedLances();
         }
     }
 }
Exemple #4
0
    void Start()
    {
        //instantiating other scripts to access them.
        PMTimeManager   = GameObject.Find("Canvas").GetComponent <TimeManager>();
        PMTextManager   = GameObject.Find("Canvas").GetComponent <TextManager>();
        PMTurnDirector  = GameObject.Find("TurnDirector").GetComponent <TurnDirector>();
        PMTouchControls = GameObject.Find("TouchControls").GetComponent <TouchControls>();

        //initializing the touches lists
        mainPattern   = new List <PlayerTouch>();
        repeatPattern = new List <PlayerTouch>();

        //instantiating the temporary player
        me = new Player(1, "Andre`", 2);
    }
Exemple #5
0
        public static void Postfix(TurnDirector __instance)
        {
            Mod.Log.Debug?.Write("TD:ctor:post - entered.");
            Mod.Log.Debug?.Write($" TurnDirector init with phases: {__instance.FirstPhase} / {__instance.LastPhase}");

            Traverse firstT = Traverse.Create(__instance).Property("FirstPhase");

            firstT.SetValue(Mod.MinPhase);

            Traverse lastT = Traverse.Create(__instance).Property("LastPhase");

            lastT.SetValue(Mod.MaxPhase);

            Mod.Log.Debug?.Write($" TurnDirector updated to phases: {__instance.FirstPhase} / {__instance.LastPhase}");
        }
Exemple #6
0
 //public static bool Prepare() { return false; }
 public static void Postfix(TurnDirector __instance)
 {
     foreach (AbstractActor unit in __instance.Combat.AllActors)
     {
         if (unit.IsShutDown)
         {
             continue;
         }
         ;
         if (unit.IsDead)
         {
             continue;
         }
         unit.UpdateAurasWithSensors();
     }
 }
 public static void Postfix(TurnDirector __instance, int newPhase)
 {
     if (CACCombatState.IsInDeployManualState)
     {
         return;
     }
     Log.Debug?.TWL(0, "BeginNewPhase round:" + __instance.CurrentRound + " phase:" + newPhase);
     foreach (AbstractActor unit in __instance.Combat.AllActors)
     {
         if (unit.isActivated())
         {
             continue;
         }
         unit.ActiveDefaultComponents();
         unit.UpdateAurasWithSensors();
     }
 }
        static void Postfix(TurnDirector __instance)
        {
            Mod.Log.Info?.Write($"Protecting lances on firstContact during first round:{__instance.CurrentRound}");
            if (__instance.CurrentRound == 1)
            {
                Mod.Log.Info?.Write($"Protecting units on first turn");
                CombatGameState combatState = UnityGameInstance.BattleTechGame.Combat;
                HostilityMatrix hm          = combatState.HostilityMatrix;
                Team            playerTeam  = combatState.LocalPlayerTeam;

                // Includes player units
                List <AbstractActor> actors = new List <AbstractActor>();
                foreach (AbstractActor actor in combatState.AllActors)
                {
                    if (hm.IsLocalPlayerEnemy(actor.TeamId) && Mod.Config.Combat.SpawnProtection.ApplyToEnemies)
                    {
                        Mod.Log.Info?.Write($" -- adding enemy actor: {actor.DistinctId()}");
                        actors.Add(actor);
                    }
                    else if (hm.IsLocalPlayerNeutral(actor.TeamId) && Mod.Config.Combat.SpawnProtection.ApplyToNeutrals)
                    {
                        Mod.Log.Info?.Write($" -- adding neutral actor: {actor.DistinctId()}");
                        actors.Add(actor);
                    }
                    else if (hm.IsLocalPlayerFriendly(actor.TeamId) && Mod.Config.Combat.SpawnProtection.ApplyToAllies)
                    {
                        Mod.Log.Info?.Write($" -- adding allied actor: {actor.DistinctId()}");
                        actors.Add(actor);
                    }
                    else if (actor.team.IsLocalPlayer)
                    {
                        Mod.Log.Info?.Write($" -- adding player actor: {actor.DistinctId()}");
                        actors.Add(actor);
                    }
                    else
                    {
                        Mod.Log.Info?.Write($" -- skipping unknown actor: {actor.DistinctId()}");
                    }
                }

                List <AbstractActor> actorsToProtect = actors.Distinct().ToList();

                ProtectionHelper.ProtectActors(actorsToProtect);
            }
        }
Exemple #9
0
        public static void Prefix(TurnDirector __instance)
        {
            Mod.Log.Debug?.Write($"TD:OCGD entered");
            // Remove all combat state
            CombatHUD_SubscribeToMessages.OnCombatGameDestroyed(__instance.Combat);

            // Unsubscribe from actor selected messages
            __instance.Combat.MessageCenter.Subscribe(MessageCenterMessageType.ActorSelectedMessage,
                                                      new ReceiveMessageCenterMessage(SelectedActorHelper.OnActorSelectedMessage), false);
            __instance.Combat.MessageCenter.Subscribe(MessageCenterMessageType.OnAuraAdded,
                                                      new ReceiveMessageCenterMessage(SelectedActorHelper.OnAuraAddedMessage), false);
            __instance.Combat.MessageCenter.Subscribe(MessageCenterMessageType.OnAuraRemoved,
                                                      new ReceiveMessageCenterMessage(SelectedActorHelper.OnAuraRemovedMessage), false);
            SelectedActorHelper.Combat = null;

            // Reset state
            ModState.Reset();
        }
        public static void Prefix(TurnDirector __instance, int round)
        {
            Mod.Log.Trace?.Write($"TD:BNR entered");
            Mod.Log.Info?.Write($"=== Turn Director is beginning round: {round}");

            // Update the current vision for all allied and friendly units
            foreach (AbstractActor actor in __instance.Combat.AllActors)
            {
                Mod.Log.Info?.Write($" -- Updating actor: {actor.DistinctId()}");

                // If our sensors are offline, re-enable them
                if (actor.StatCollection.ContainsStatistic(ModStats.DisableSensors))
                {
                    if (round >= actor.StatCollection.GetValue <int>(ModStats.DisableSensors))
                    {
                        Mod.Log.Info?.Write($"Re-enabling sensors for {CombatantUtils.Label(actor)}");
                        actor.StatCollection.RemoveStatistic(ModStats.DisableSensors);
                    }
                    else
                    {
                        Mod.Log.Info?.Write($"Actor: {CombatantUtils.Label(actor)} sensors are offline until: {actor.StatCollection.GetValue<int>(ModStats.DisableSensors)}");
                    }
                }

                // Update our sensors check
                ActorHelper.UpdateSensorCheck(actor, true);

                // Print the current state of the actor
                EWState actorState = new EWState(actor);
                Mod.Log.Info?.Write(actorState.ToString());
            }

            // Now that all sensor checks are updated, refresh visiblity for all actors
            foreach (AbstractActor actor in __instance.Combat.AllActors)
            {
                if (actor.TeamId == __instance.Combat.LocalPlayerTeamGuid)
                {
                    actor.VisibilityCache.RebuildCache(actor.Combat.GetAllImporantCombatants());
                    CombatHUDHelper.ForceNameRefresh(actor.Combat);
                }
            }
        }
            public static void Postfix(TurnDirector __instance)
            {
                try
                {
                    Logger.Debug($"[TurnDirector_StartFirstRound_POSTFIX] Protecting units on combat round one");

                    List <AbstractActor> actors = new List <AbstractActor>();
                    foreach (AbstractActor actor in __instance.Combat.AllActors)
                    {
                        if (actor is Mech mech)
                        {
                            Logger.Debug($"[TurnDirector_StartFirstRound_POSTFIX] Applying braced state to mech: {mech.DisplayName}");
                            mech.ApplyBraced();
                        }
                    }
                }
                catch (Exception e)
                {
                    Logger.Error(e);
                }
            }
Exemple #12
0
        public static void Postfix(TurnDirector __instance)
        {
            Mod.Log.Trace?.Write($"TD:ECR - entered.");

            Mod.Log.Info?.Write($"ON ROUND END: isInterleaved: {__instance.Combat.TurnDirector.IsInterleaved}  " +
                                $"isInterleavePending: {__instance.Combat.TurnDirector.IsInterleavePending}  " +
                                $"isNonInterleavePending: {__instance.Combat.TurnDirector.IsNonInterleavePending}");
            if (__instance.IsInterleaved && !__instance.DoAnyUnitsHaveContactWithEnemy)
            {
                bool hasContact = __instance.DoAnyUnitsHaveContactWithEnemy;
                if (!hasContact)
                {
                    Mod.Log.Info?.Write("No actors have contact, returning to non-interleaved mode.");

                    Traverse turnDirectorT = Traverse.Create(__instance).Property("IsInterleaved");
                    turnDirectorT.SetValue(false);

                    __instance.Combat.MessageCenter.PublishMessage(new LostContactMessage());
                    return;
                }
            }
        }
Exemple #13
0
        public static void Postfix(TurnDirector __instance, MessageCenterMessage message)
        {
            // Remain interleaved until the end of the round. This prevents the case where you immediately get dropped out of combat, then get forced back into it.
            if (__instance != null && __instance.Combat.EncounterLayerData != null)
            {
                __instance.Combat.EncounterLayerData.turnDirectorBehavior = TurnDirectorBehaviorType.RemainInterleaved;
                Mod.Log.Info?.Write("Interleaved mode set to: REMAIN_INTERLEAVED");
            }
            else
            {
                Mod.Log.Warn?.Write("COULD NOT FIND ENCOUNTER_LAYER_DATA - INTERLEAVED FIX CANNOT BE APPLIED!");
            }

            // Check for hull breach biomes
            if (__instance.Combat.MapMetaData == null)
            {
                Mod.Log.Warn?.Write("MAP Metadata WAS NULL, SKIPPING BREACH CHECK");
            }
            else
            {
                switch (__instance.Combat.MapMetaData.biomeSkin)
                {
                case Biome.BIOMESKIN.lunarVacuum:
                    ModState.BreachCheck = Mod.Config.Breaches.VacuumCheck;
                    Mod.Log.Debug?.Write($"Lunar biome detected - setting breach chance to: {ModState.BreachCheck}");
                    break;

                case Biome.BIOMESKIN.martianVacuum:
                    ModState.BreachCheck = Mod.Config.Breaches.ThinAtmoCheck;
                    Mod.Log.Debug?.Write($"Martian biome detected - setting breach chance to: {ModState.BreachCheck}");
                    break;

                default:
                    Mod.Log.Debug?.Write($"Biome of {__instance.Combat.MapMetaData.biomeSkin} detected. No special behaviors.");
                    return;
                }
            }
        }
Exemple #14
0
            static void Postfix(TurnDirector __instance, int round)
            {
                Mod.Log.Trace?.Write("TD:BNR entered");
                Mod.Log.Debug?.Write($" OnNewRound -> withdrawStarted:{ModState.WithdrawStarted} canWithdrawOn:{ModState.CanWithdrawOnRound}");

                if (ModState.WithdrawStarted)
                {
                    if (round == ModState.CanWithdrawOnRound)
                    {
                        int readyIn = ModState.CanApproachOnRound - round;
                        GenericPopupBuilder genericPopupBuilder =
                            GenericPopupBuilder.Create(GenericPopupType.Info,
                                                       $"Sumire is overhead. If you don't withdraw on this round, she will retreat. She will be unavailable for another {readyIn} rounds!")
                            .AddButton("Continue", new Action(OnContinue), true, null);
                        genericPopupBuilder.IsNestedPopupWithBuiltInFade = true;
                        ModState.HUD.SelectionHandler.GenericPopup       = genericPopupBuilder.Render();

                        ModState.RetreatButton.SetState(ButtonState.Enabled, true);
                        ModState.RetreatButtonText.SetText($"Withdraw Now");
                    }
                    else if (round == ModState.CanApproachOnRound)
                    {
                        ModState.WithdrawStarted    = false;
                        ModState.CanApproachOnRound = -1;
                        ModState.CanWithdrawOnRound = -1;

                        ModState.RetreatButton.SetState(ButtonState.Enabled, false);
                        ModState.RetreatButtonText.SetText($"Withdraw");
                    }
                    else
                    {
                        int roundsToWait = ModState.CanWithdrawOnRound - round;
                        Mod.Log.Info?.Write($" -- Player must wait:{roundsToWait} rounds for pickup.");
                        ModState.RetreatButtonText.SetText($"In { roundsToWait } Rounds");
                    }
                }
            }
Exemple #15
0
        public static void Postfix(TurnDirector __instance, MessageCenterMessage message)
        {
            Mod.Log.Trace?.Write("TD:OICC - entered.");

            ModState.IsUrbanBiome = ModState.Combat.ActiveContract.ContractBiome == Biome.BIOMESKIN.urbanHighTech;
            if (!ModState.IsUrbanBiome)
            {
                Mod.Log.Info?.Write($"Contract has non-urban biome ({ModState.Combat.ActiveContract.ContractBiome}). Skipping processing.");
                return;
            }
            Mod.Log.Info?.Write($"Contract has Urban High Tech biome, enabling mod features.");

            // Check contract exclusions
            foreach (string overrrideId in Mod.Config.Ambush.BlacklistedContracts)
            {
                if (overrrideId.Equals(ModState.Combat.ActiveContract.Override.ID, StringComparison.InvariantCultureIgnoreCase))
                {
                    Mod.Log.Info?.Write($"Contract with override ID '{overrrideId}' is excluded, skipping processing.");
                    ModState.IsUrbanBiome = false;
                    return;
                }
            }
            Mod.Log.Info?.Write($"Contract with override ID: {ModState.Combat.ActiveContract.Override.ID} is not blacklisted, enabling ambushes.");

            ModState.ContractDifficulty = ModState.Combat.ActiveContract.Override.finalDifficulty;
            Mod.Log.Info?.Write($"Using contractOverride finalDifficulty of: {ModState.ContractDifficulty}");

            foreach (Team team in ModState.Combat.Teams)
            {
                if (team.GUID == TeamDefinition.TargetsTeamDefinitionGuid)
                {
                    ModState.TargetTeam = team;
                }
                else if (team.GUID == TeamDefinition.TargetsAllyTeamDefinitionGuid)
                {
                    ModState.TargetAllyTeam = team;
                }
                else if (team.GUID == TeamDefinition.HostileToAllTeamDefinitionGuid)
                {
                    ModState.HostileToAllTeam = team;
                }
            }
            Mod.Log.Info?.Write($"" +
                                $"TargetTeam identified as: {ModState.TargetTeam?.DisplayName}  " +
                                $"TargetAllyTeam identified as: {ModState.TargetAllyTeam?.DisplayName}  " +
                                $"HostileToAllTeam identified as: {ModState.HostileToAllTeam?.DisplayName}.");

            // TODO: Make this much more powerful and varied.
            ModState.AmbushTeam = ModState.TargetTeam;
            Mod.Log.Info?.Write($"Using team: {ModState.AmbushTeam.DisplayName} as Ambush team.");

            // Filter the AmbushDefs by contract difficulty. If we don't have ambushes for our contract difficulty,
            //   there's a configuration error - abort! This has to come before data loading as it sets
            //   the AmbushDefs for the current contract
            bool haveAmbushes = FilterAmbushes();

            if (!haveAmbushes)
            {
                ModState.IsUrbanBiome = false;
                Mod.Log.Warn?.Write("Incorrect filter configuration - disabling ambushes!");
                return;
            }

            // Load any resources necessary for our ambush
            try
            {
                DataLoadHelper.LoadAmbushResources(ModState.Combat);
            }
            catch (Exception e)
            {
                Mod.Log.Error?.Write(e, "Failed to load ambush resources due to exception!");
                ModState.IsUrbanBiome = false;
            }

            // Find candidate buildings
            CandidateBuildingsHelper.DoInitialFilter(__instance.Combat);
            Mod.Log.Info?.Write($"Contract initially has: {ModState.CandidateBuildings.Count} candidate buildings");

            // Devestate buildings
            DevestationHelper.DevestateBuildings();

            Mod.Log.Info?.Write($"After devestation, map has {ModState.CandidateBuildings.Count} candidate buildings.");
        }
Exemple #16
0
            public static void Postfix(TurnDirector __instance)
            {
                Logger.LogDebug("Armor Repair Start First Round Patch");
                foreach (var team in __instance.Combat.Teams)
                {
                    Logger.LogDebug(team.Name);
                    Logger.LogDebug(team.IsLocalPlayer.ToString());

                    //if (!team.IsLocalPlayer)
                    //    return;


                    Core.tempMechLabQueue.Clear();
                    Core.CombatMechs.Clear();

                    foreach (var actor in team.units)
                    {
                        if (!(actor is Mech mech))
                        {
                            continue;
                        }

                        Logger.LogDebug("ARMOR REPAIR: " + actor.DisplayName);
                        bool  correctArmor = false;
                        var   tags         = mech.GetTags();
                        float armorLoss    = 1;
                        Logger.LogDebug("Tags:");
                        foreach (var tag in tags)
                        {
                            Logger.LogDebug(tag);
                            if (tag.StartsWith($"XLRPArmor"))
                            {
                                string[] parsedString = tag.Split('_');
                                armorLoss    = float.Parse(parsedString[1]);
                                correctArmor = true;
                            }
                        }
                        if (correctArmor)
                        {
                            Logger.LogDebug("Correcting Armor");
                            Logger.LogDebug("Armor Before: " + actor.CurrentArmor);
                            var HeadArmor = actor.StatCollection.GetValue <float>("Head.Armor");
                            HeadArmor *= armorLoss;
                            actor.StatCollection.Set <float>("Head.Armor", HeadArmor);

                            var LeftArmArmor = actor.StatCollection.GetValue <float>("LeftArm.Armor");
                            LeftArmArmor *= armorLoss;
                            actor.StatCollection.Set <float>("LeftArm.Armor", LeftArmArmor);

                            var LeftTorsoArmor = actor.StatCollection.GetValue <float>("LeftTorso.Armor");
                            LeftTorsoArmor *= armorLoss;
                            actor.StatCollection.Set <float>("LeftTorso.Armor", LeftTorsoArmor);

                            var CenterTorsoArmor = actor.StatCollection.GetValue <float>("CenterTorso.Armor");
                            CenterTorsoArmor *= armorLoss;
                            actor.StatCollection.Set <float>("CenterTorso.Armor", CenterTorsoArmor);

                            var RightTorsoArmor = actor.StatCollection.GetValue <float>("RightTorso.Armor");
                            RightTorsoArmor *= armorLoss;
                            actor.StatCollection.Set <float>("RightTorso.Armor", RightTorsoArmor);

                            var RightArmArmor = actor.StatCollection.GetValue <float>("RightArm.Armor");
                            RightArmArmor *= armorLoss;
                            actor.StatCollection.Set <float>("RightArm.Armor", RightArmArmor);

                            var LeftLegArmor = actor.StatCollection.GetValue <float>("LeftLeg.Armor");
                            LeftLegArmor *= armorLoss;
                            actor.StatCollection.Set <float>("LeftLeg.Armor", LeftLegArmor);

                            var RightLegArmor = actor.StatCollection.GetValue <float>("RightLeg.Armor");
                            RightLegArmor *= armorLoss;
                            actor.StatCollection.Set <float>("RightLeg.Armor", RightLegArmor);

                            var LeftTorsoRearArmor = actor.StatCollection.GetValue <float>("LeftTorso.RearArmor");
                            LeftTorsoRearArmor *= armorLoss;
                            actor.StatCollection.Set <float>("LeftTorso.RearArmor", LeftTorsoRearArmor);

                            var CenterTorsoRearArmor = actor.StatCollection.GetValue <float>("CenterTorso.RearArmor");
                            CenterTorsoRearArmor *= armorLoss;
                            actor.StatCollection.Set <float>("CenterTorso.RearArmor", CenterTorsoRearArmor);

                            var RightTorsoRearArmor = actor.StatCollection.GetValue <float>("RightTorso.RearArmor");
                            RightTorsoRearArmor *= armorLoss;
                            actor.StatCollection.Set <float>("RightTorso.RearArmor", RightTorsoRearArmor);

                            Logger.LogDebug("Armor After: " + actor.CurrentArmor);
                        }
                    }
                }
            }
Exemple #17
0
 public static void Postfix(TurnDirector __instance)
 {
     // Reset the attack penalty in case we've flipped actors.
     ModState.InjuryResistPenalty = -1;
 }
Exemple #18
0
        public void EndGame()
        {
            if (TurnDirector.Ins.GetMyPlayer().HasLost)
            {
                ExitGame();
            }

            TurnDirector ins = TurnDirector.Ins;

            List <Player> wonPlayers   = new List <Player>();
            WinCondition  wonCondition = null;

            foreach (var winCondition in winConditions)
            {
                bool hasPlayerWon = false;

                foreach (var player in TurnDirector.Ins.ListPlayer)
                {
                    if (player.HasLost)
                    {
                        continue;
                    }

                    bool won = winCondition.CheckWinner(player);

                    if (won)
                    {
                        wonPlayers.Add(player);
                        hasPlayerWon = true;
                    }
                }

                if (hasPlayerWon)
                {
                    wonCondition = winCondition;
                    break;
                }
            }

            foreach (var player in wonPlayers)
            {
                player.Rank = 1;
            }


            int currentRank = TurnDirector.Ins.ListPlayer.Count;

            if (listPlayerEndTurn.Count > 0)
            {
                // Set rank for player lost

                listPlayerEndTurn.OrderBy(x => x.Item1); // Sort list player lose by the turn count they pass

                int currentTurnCount = listPlayerEndTurn[0].Item1;

                foreach (var playerEndTurn in listPlayerEndTurn)
                {
                    if (playerEndTurn.Item1 > currentTurnCount)
                    {
                        currentRank--;
                        currentTurnCount = playerEndTurn.Item1;
                    }

                    playerEndTurn.Item2.Rank = currentRank;
                }
                currentRank--;
            }

            // Set rank for player that hasn't lost but the winner appear
            foreach (var player in TurnDirector.Ins.ListPlayer)
            {
                if (wonPlayers.Contains(player) || player.HasLost)
                {
                    continue;
                }

                player.Rank = currentRank;
            }

            wonCondition.ShowWinScreen();

            //ExitGame();
        }
Exemple #19
0
 private void Start()
 {
     TMTextManager  = GameObject.Find("Canvas").GetComponent <TextManager>();
     TMTurnDirector = GameObject.Find("TurnDirector").GetComponent <TurnDirector>();
 }
Exemple #20
0
 private static void Postfix(TurnDirector __instance)
 {
     CBTMovement.inInterleaved = __instance.IsInterleaved;
 }
Exemple #21
0
 private static void Postfix(TurnDirector __instance, bool value)
 {
     CBTMovement.inInterleaved = value;
 }
Exemple #22
0
        public static void Postfix(TurnDirector __instance, ref bool __result)
        {
            try
            {
                if (__result == true)
                {
                    return;
                }

                Logger.Debug("---");
                Logger.Debug($"[TurnDirector_DoAnyUnitsHaveContactWithEnemy_POSTFIX] Examine current result({__result}) and try to intercept interleaved drop out bug on escort missions...");

                /*
                 * // Debug
                 * StackTrace stackTrace = new StackTrace();
                 * for (var i = 0; i < stackTrace.FrameCount; i++)
                 * {
                 *  MethodBase methodBase = stackTrace.GetFrame(i).GetMethod();
                 *  Type declaringType = methodBase.DeclaringType;
                 *  Logger.Info($"[TurnDirector_DoAnyUnitsHaveContactWithEnemy_POSTFIX] StackTraceMethodName: {declaringType.Name}.{methodBase.Name}");
                 * }
                 */


                bool HasAnyContactWithEnemy      = false;
                bool HasAnyActorDetectedAnyEnemy = false;

                List <AbstractActor> allActors = __instance.Combat.AllActors;
                allActors.RemoveAll((AbstractActor x) => x.IsDead || x.IsFlaggedForDeath);
                for (int i = 0; i < allActors.Count; i++)
                {
                    // Checking all *living* detected enemies to compare with with current result. For unknown reasons this won't match when convoys are extracted
                    List <AbstractActor> detectedEnemyUnits = allActors[i].GetDetectedEnemyUnits();
                    detectedEnemyUnits.RemoveAll((AbstractActor a) => a.IsDead || a.IsFlaggedForDeath);

                    //Logger.Info($"[TurnDirector_DoAnyUnitsHaveContactWithEnemy_POSTFIX] ({allActors[i].DisplayName}) HasAnyContactWithEnemy: {allActors[i].HasAnyContactWithEnemy}");
                    //Logger.Info($"[TurnDirector_DoAnyUnitsHaveContactWithEnemy_POSTFIX] ({allActors[i].DisplayName}) DetectedEnemyUnits: {detectedEnemyUnits.Count}");

                    // This is a copy of what is checked in original method
                    if (allActors[i].HasAnyContactWithEnemy)
                    {
                        HasAnyContactWithEnemy = true;
                    }

                    // Custom check to verify result
                    if (detectedEnemyUnits.Count > 0)
                    {
                        HasAnyActorDetectedAnyEnemy = true;
                    }
                }
                Logger.Info($"[TurnDirector_DoAnyUnitsHaveContactWithEnemy_POSTFIX] HasAnyContactWithEnemy: {HasAnyContactWithEnemy}");
                Logger.Info($"[TurnDirector_DoAnyUnitsHaveContactWithEnemy_POSTFIX] HasAnyActorDetectedAnyEnemy: {HasAnyActorDetectedAnyEnemy}");

                // If there's a mismatch the VisibilityCache probably wasn't updated properly??
                // Nevertheless, this fixes the "Exit/Re-Enter Combat" scenario which happens in escort missions when the convoy is extracted.
                if (__result == false && HasAnyActorDetectedAnyEnemy == true)
                {
                    Logger.Debug($"[TurnDirector_DoAnyUnitsHaveContactWithEnemy_POSTFIX] MISMATCH! DoAnyUnitsHaveContactWithEnemy: {__result}, HasAnyActorDetectedAnyEnemy: {HasAnyActorDetectedAnyEnemy}");
                    Logger.Debug($"[TurnDirector_DoAnyUnitsHaveContactWithEnemy_POSTFIX] FORCING return value to true");
                    Logger.Debug("---");

                    __result = true;
                }
            }
            catch (Exception e)
            {
                Logger.Error(e);
            }
        }
Exemple #23
0
        private static bool Prefix(TurnDirector __instance)
        {
            Mod.Log.Trace?.Write($"TD:OTAAC invoked");

            if (__instance.IsMissionOver)
            {
                return(false);
            }

            Mod.Log.Debug?.Write($"TD isInterleaved: {__instance.Combat.TurnDirector.IsInterleaved}  isInterleavePending: {__instance.Combat.TurnDirector.IsInterleavePending}" +
                                 $"  isNonInterleavePending: {__instance.Combat.TurnDirector.IsNonInterleavePending}");

            foreach (TurnActor turnActor in __instance.TurnActors)
            {
                if (turnActor is Team teamActor)
                {
                    Mod.Log.Debug?.Write($" -- TEAM: {teamActor.Name} --");
                    foreach (AbstractActor actor in teamActor.units)
                    {
                        Mod.Log.Debug?.Write($" ---- UNIT: {actor}");
                    }
                }
                else if (turnActor is AITeam aiTeam)
                {
                    Mod.Log.Debug?.Write($" -- AI TEAM: {aiTeam.Name} --");
                    foreach (AbstractActor actor in aiTeam.units)
                    {
                        Mod.Log.Debug?.Write($" ---- UNIT: {actor}");
                    }
                }
                else if ("EFFECT MANAGER SINGLETON".Equals(turnActor.GUID, StringComparison.InvariantCultureIgnoreCase))
                {
                    Mod.Log.Debug?.Write($" -- TEAM: Effect Manager --");
                }
                else
                {
                    Mod.Log.Debug?.Write($" -- TEAM: Unknown team activated! {turnActor.GUID} --");
                }
            }

            List <ITaggedItem> objectsOfType = __instance.Combat.ItemRegistry.GetObjectsOfType(TaggedObjectType.Unit);

            for (int i = 0; i < objectsOfType.Count; i++)
            {
                AbstractActor abstractActor = objectsOfType[i] as AbstractActor;
                if (abstractActor != null && abstractActor.team == null)
                {
                    Mod.Log.Error?.Write($"Unit {CombatantUtils.Label(abstractActor)} has no assigned team!");
                }
            }

            int numUnusedUnitsForCurrentPhase = __instance.TurnActors[__instance.ActiveTurnActorIndex].GetNumUnusedUnitsForCurrentPhase();

            Mod.Log.Info?.Write($"There are {numUnusedUnitsForCurrentPhase} unusedUnits in the current phase");

            // If we are in non-interleaved mode, and there are additional units to active, do so.
            if (!__instance.IsInterleavePending && !__instance.IsInterleaved && numUnusedUnitsForCurrentPhase > 0)
            {
                Mod.Log.Info?.Write("Sending TurnActorActivateMessage");
                Traverse staamT = Traverse.Create(__instance).Method("SendTurnActorActivateMessage", new object[] { __instance.ActiveTurnActorIndex });
                staamT.GetValue();
            }
            else
            {
                Mod.Log.Debug?.Write("Incrementing ActiveTurnActor");
                Traverse iataT = Traverse.Create(__instance).Method("IncrementActiveTurnActor");
                iataT.GetValue();
            }

            return(false);
        }
Exemple #24
0
        static void Prefix(TurnDirector __instance)
        {
            if (!__instance.IsInterleaved && !__instance.IsInterleavePending &&
                __instance.CurrentRound >= Mod.Config.Ambush.EnableOnRound &&
                ModState.PotentialAmbushOrigins.Count != 0 &&
                __instance.ActiveTurnActor is Team activeTeam && activeTeam.IsLocalPlayer)
            {
                // Re-Filter the candidates to try to catch buildings that were marked contract objectives
                CandidateBuildingsHelper.FilterOnTurnActorIncrement(__instance.Combat);


                // Determine potential ambush sites based upon the origins
                Dictionary <Vector3, List <BattleTech.Building> > ambushSites = new Dictionary <Vector3, List <BattleTech.Building> >();
                foreach (Vector3 origin in ModState.PotentialAmbushOrigins)
                {
                    // For the given origin, find how many potential buildings there are.
                    List <BattleTech.Building> originCandidates = CandidateBuildingsHelper.ClosestCandidatesToPosition(origin, Mod.Config.Ambush.SearchRadius);
                    Mod.Log.Debug?.Write($" Found {originCandidates.Count} candidate buildings for originPos: {origin}");
                    ambushSites.Add(origin, originCandidates);
                }
                ModState.PotentialAmbushOrigins.Clear(); // reset potential origins for next round

                // Determine if the unit was ambushed this turn
                bool wasAmbushed = false;
                if (ModState.Ambushes < Mod.Config.Ambush.MaxPerMap && ambushSites.Count > 0)
                {
                    float roll      = Mod.Random.Next(1, 100);
                    int   threshold = (int)Math.Ceiling(ModState.CurrentAmbushChance * 100f);
                    if (roll <= threshold)
                    {
                        Mod.Log.Info?.Write($" Roll: {roll} is under current threshold: {threshold}, enabling possible ambush");
                        wasAmbushed = true;
                    }
                    else
                    {
                        ModState.CurrentAmbushChance += Mod.Config.Ambush.ChancePerActor;
                        Mod.Log.Info?.Write($" Roll: {roll} was over threshold: {threshold}, increasing ambush chance to: {ModState.CurrentAmbushChance} for next position.");
                    }
                }

                if (wasAmbushed)
                {
                    // Sort the ambushSites by number of buildings to maximize ambush success
                    Mod.Log.Debug?.Write("Sorting sites by potential buildings.");
                    List <KeyValuePair <Vector3, List <BattleTech.Building> > > sortedSites = ambushSites.ToList();
                    sortedSites.Sort((x, y) => x.Value.Count.CompareTo(y.Value.Count));

                    Vector3 ambushOrigin = sortedSites[0].Key;
                    Mod.Log.Debug?.Write($"Spawning an ambush at position: {ambushOrigin}");

                    // Randomly determine an ambush type by weight
                    List <AmbushType> shuffledTypes = new List <AmbushType>();
                    shuffledTypes.AddRange(Mod.Config.Ambush.AmbushTypes);
                    shuffledTypes.Shuffle <AmbushType>();
                    AmbushType ambushType = shuffledTypes[0];
                    Mod.Log.Info?.Write($"Ambush type of: {ambushType} will be applied at position: {ambushOrigin}");

                    switch (ambushType)
                    {
                    case AmbushType.Explosion:
                        ExplosionAmbushHelper.SpawnAmbush(ambushOrigin);
                        break;

                    case AmbushType.Infantry:
                        InfantryAmbushHelper.SpawnAmbush(ambushOrigin);
                        break;

                    case AmbushType.BattleArmor:
                        SpawnAmbushHelper.SpawnAmbush(ambushOrigin, AmbushType.BattleArmor);
                        break;

                    case AmbushType.Mech:
                        SpawnAmbushHelper.SpawnAmbush(ambushOrigin, AmbushType.Mech);
                        break;

                    case AmbushType.Vehicle:
                        SpawnAmbushHelper.SpawnAmbush(ambushOrigin, AmbushType.Vehicle);
                        break;

                    default:
                        Mod.Log.Error?.Write($"UNKNOWN AMBUSH TYPE: {ambushType} - CANNOT PROCEED!");
                        break;
                    }

                    // Record a successful ambush and reset the weighting
                    ModState.AmbushOrigins.Add(ambushOrigin);
                    ModState.Ambushes++;
                    ModState.CurrentAmbushChance = Mod.Config.Ambush.BaseChance;
                }
            }
        }
Exemple #25
0
 public static void Postfix(TurnDirector __instance)
 {
     //SkillBasedInit.Logger.Log($"TurnDirector; Combat complete, destroying initiative map.");
     ActorInitiativeHolder.OnCombatComplete();
 }