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); } }
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); } }
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(); } } }
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); }
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}"); }
//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); } }
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); } }
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; } } }
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; } } }
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"); } } }
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."); }
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); } } } }
public static void Postfix(TurnDirector __instance) { // Reset the attack penalty in case we've flipped actors. ModState.InjuryResistPenalty = -1; }
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(); }
private void Start() { TMTextManager = GameObject.Find("Canvas").GetComponent <TextManager>(); TMTurnDirector = GameObject.Find("TurnDirector").GetComponent <TurnDirector>(); }
private static void Postfix(TurnDirector __instance) { CBTMovement.inInterleaved = __instance.IsInterleaved; }
private static void Postfix(TurnDirector __instance, bool value) { CBTMovement.inInterleaved = value; }
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); } }
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); }
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; } } }
public static void Postfix(TurnDirector __instance) { //SkillBasedInit.Logger.Log($"TurnDirector; Combat complete, destroying initiative map."); ActorInitiativeHolder.OnCombatComplete(); }