public static void SpawnAmbush(Vector3 ambushOrigin)
        {
            if (!Mod.Config.InfantryAmbush.Enabled)
            {
                return;
            }

            int infantrySpawns = Mod.Random.Next(ModState.InfantryAmbushDefForContract.MinSpawns, ModState.InfantryAmbushDefForContract.MaxSpawns);

            Mod.Log.Debug?.Write($"Spawning up to {infantrySpawns} infantry spawns as part of this ambush.");

            // Create a new lance in the target team
            Lance ambushLance = TeamHelper.CreateAmbushLance(ModState.AmbushTeam);

            // Build list of candidate trap buildings
            List <BattleTech.Building> candidates = CandidateBuildingsHelper.ClosestCandidatesToPosition(ambushOrigin, Mod.Config.Ambush.SearchRadius);

            if (candidates.Count < ModState.InfantryAmbushDefForContract.MinSpawns)
            {
                Mod.Log.Debug?.Write($"Insufficient candidate buildings to spawn an infantry ambush. Skipping.");
                return;
            }

            // Make sure we don't spawn more turrets than buildings
            if (infantrySpawns > candidates.Count)
            {
                infantrySpawns = candidates.Count;
            }

            List <AbstractActor>       spawnedActors  = new List <AbstractActor>();
            List <BattleTech.Building> spawnBuildings = new List <BattleTech.Building>();

            for (int i = 0; i < infantrySpawns; i++)
            {
                BattleTech.Building spawnBuildingShell = candidates.ElementAt(i);

                // Spawn a turret trap
                AbstractActor ambushTurret = SpawnAmbushTurret(ModState.AmbushTeam, ambushLance, spawnBuildingShell, ambushOrigin);
                spawnedActors.Add(ambushTurret);
                spawnBuildings.Add(spawnBuildingShell);
                Mod.Log.Info?.Write($"Spawned turret: {ambushTurret.DisplayName} in building: {spawnBuildingShell.DisplayName}");
            }

            // Remove any buildings that are part of this ambush from candidates
            ModState.CandidateBuildings.RemoveAll(x => spawnBuildings.Contains(x));

            // Determine the targets that should be prioritized by the enemies
            List <ICombatant> targets = new List <ICombatant>();

            foreach (ICombatant combatant in ModState.Combat.GetAllCombatants())
            {
                if (!combatant.IsDead && !combatant.IsFlaggedForDeath &&
                    combatant.team != null &&
                    ModState.Combat.HostilityMatrix.IsLocalPlayerFriendly(combatant.team))
                {
                    if (Vector3.Distance(ambushOrigin, combatant.CurrentPosition) <= Mod.Config.Ambush.SearchRadius)
                    {
                        targets.Add(combatant);
                    }
                }
            }

            Mod.Log.Info?.Write($"Adding InfantryAmbushSequence for {spawnedActors.Count} actors.");
            try
            {
                InfantryAmbushSequence ambushSequence =
                    new InfantryAmbushSequence(ModState.Combat, ambushOrigin, spawnedActors, spawnBuildings, targets, Mod.Config.InfantryAmbush.FreeAttackEnabled);
                ModState.Combat.MessageCenter.PublishMessage(new AddSequenceToStackMessage(ambushSequence));
            }
            catch (Exception e)
            {
                Mod.Log.Error?.Write(e, "Failed to create AES sequence due to error!");
            }
        }
        public static void SpawnAmbush(Vector3 ambushOrigin, AmbushType ambushType)
        {
            // Determine how many units we're spawning
            int minSpawns = 0, maxSpawns = 0;

            if (ambushType == AmbushType.BattleArmor)
            {
                if (!Mod.Config.BattleArmorAmbush.Enabled)
                {
                    return;
                }
                minSpawns = ModState.BattleArmorAmbushDefForContract.MinSpawns;
                maxSpawns = ModState.BattleArmorAmbushDefForContract.MaxSpawns;
            }
            else if (ambushType == AmbushType.Mech)
            {
                if (!Mod.Config.MechAmbush.Enabled)
                {
                    return;
                }
                minSpawns = ModState.MechAmbushDefForContract.MinSpawns;
                maxSpawns = ModState.MechAmbushDefForContract.MaxSpawns;
            }
            else if (ambushType == AmbushType.Vehicle)
            {
                if (!Mod.Config.VehicleAmbush.Enabled)
                {
                    return;
                }
                minSpawns = ModState.VehicleAmbushDefForContract.MinSpawns;
                maxSpawns = ModState.VehicleAmbushDefForContract.MaxSpawns;
            }

            int actorsToSpawn = Mod.Random.Next(minSpawns, maxSpawns);

            Mod.Log.Debug?.Write($"Spawning {actorsToSpawn} actors as part of this ambush.");

            // Starting with the closest building, look through the buildings and determine how many locations can support a unit.
            List <BattleTech.Building> candidates = CandidateBuildingsHelper.ClosestCandidatesToPosition(ambushOrigin, Mod.Config.Ambush.SearchRadius);

            if (candidates.Count < minSpawns)
            {
                Mod.Log.Debug?.Write($"Insufficient candidate buildings for a spawn ambush. Skipping.");
                return;
            }

            // Create a new lance in the target team
            Lance ambushLance = TeamHelper.CreateAmbushLance(ModState.AmbushTeam);

            ModState.CurrentSpawningLance = ambushLance;

            EncounterLayerData         encounterLayerData = ModState.Combat.EncounterLayerData;
            List <BattleTech.Building> buildingsToLevel   = new List <BattleTech.Building>();
            List <AbstractActor>       spawnedActors      = new List <AbstractActor>();

            foreach (BattleTech.Building building in candidates)
            {
                if (actorsToSpawn == 0)
                {
                    break;                     // nothing more to do, end processing.
                }
                // Spawn one unit at the origin of the building
                buildingsToLevel.Add(building);
                Mod.Log.Debug?.Write("Spawning actor at building origin.");

                AbstractActor spawnedActor = null;
                if (ambushType == AmbushType.BattleArmor)
                {
                    spawnedActor = SpawnAmbushMech(ModState.AmbushTeam, ambushLance, ambushOrigin, building.CurrentPosition, building.CurrentRotation, ModState.BattleArmorAmbushDefForContract.SpawnPool);
                }
                else if (ambushType == AmbushType.Mech)
                {
                    spawnedActor = SpawnAmbushMech(ModState.AmbushTeam, ambushLance, ambushOrigin, building.CurrentPosition, building.CurrentRotation, ModState.MechAmbushDefForContract.SpawnPool);
                }
                else if (ambushType == AmbushType.Vehicle)
                {
                    spawnedActor = SpawnAmbushVehicle(ModState.AmbushTeam, ambushLance, ambushOrigin, building.CurrentPosition, building.CurrentRotation);
                }

                spawnedActors.Add(spawnedActor);
                actorsToSpawn--;

                // Iterate through adjacent hexes to see if we can spawn more units in the building
                List <Vector3> adjacentHexes = ModState.Combat.HexGrid.GetGridPointsAroundPointWithinRadius(ambushOrigin, 3); // 3 hexes should cover most large buidlings
                foreach (Vector3 adjacentHex in adjacentHexes)
                {
                    if (actorsToSpawn == 0)
                    {
                        break;
                    }

                    Point cellPoint = new Point(ModState.Combat.MapMetaData.GetXIndex(adjacentHex.x), ModState.Combat.MapMetaData.GetZIndex(adjacentHex.z));
                    Mod.Log.Debug?.Write($" Evaluating point {cellPoint.X}, {cellPoint.Z} for potential ambush.");
                    if (encounterLayerData.mapEncounterLayerDataCells[cellPoint.Z, cellPoint.X].HasSpecifiedBuilding(building.GUID))
                    {
                        Mod.Log.Debug?.Write($"Spawning actor at adjacent hex at position: {adjacentHex}");
                        AbstractActor additionalSpawn = null;
                        if (ambushType == AmbushType.BattleArmor)
                        {
                            additionalSpawn = SpawnAmbushMech(ModState.AmbushTeam, ambushLance, ambushOrigin, adjacentHex, building.CurrentRotation, ModState.BattleArmorAmbushDefForContract.SpawnPool);
                        }
                        else if (ambushType == AmbushType.Mech)
                        {
                            additionalSpawn = SpawnAmbushMech(ModState.AmbushTeam, ambushLance, ambushOrigin, adjacentHex, building.CurrentRotation, ModState.MechAmbushDefForContract.SpawnPool);
                        }
                        else if (ambushType == AmbushType.Vehicle)
                        {
                            additionalSpawn = SpawnAmbushVehicle(ModState.AmbushTeam, ambushLance, ambushOrigin, adjacentHex, building.CurrentRotation);
                        }

                        spawnedActors.Add(additionalSpawn);
                        actorsToSpawn--;
                    }
                    else
                    {
                        Mod.Log.Debug?.Write($" Hex {adjacentHex} is outside of the main building, skipping.");
                    }
                }
            }

            // Remove any buildings that are part of this ambush from candidates
            ModState.CandidateBuildings.RemoveAll(x => buildingsToLevel.Contains(x));

            // Determine the targets that should be prioritized by the enemies
            List <ICombatant> targets = new List <ICombatant>();

            foreach (ICombatant combatant in ModState.Combat.GetAllCombatants())
            {
                if (!combatant.IsDead && !combatant.IsFlaggedForDeath &&
                    combatant.team != null &&
                    ModState.Combat.HostilityMatrix.IsLocalPlayerFriendly(combatant.team))
                {
                    if (Vector3.Distance(ambushOrigin, combatant.CurrentPosition) <= Mod.Config.Ambush.SearchRadius)
                    {
                        targets.Add(combatant);
                    }
                }
            }

            bool applyAttacks = false;

            if (ambushType == AmbushType.BattleArmor && Mod.Config.BattleArmorAmbush.FreeAttackEnabled)
            {
                applyAttacks = true;
            }
            if (ambushType == AmbushType.Mech && Mod.Config.MechAmbush.FreeAttackEnabled)
            {
                applyAttacks = true;
            }
            if (ambushType == AmbushType.Vehicle && Mod.Config.VehicleAmbush.FreeAttackEnabled)
            {
                applyAttacks = true;
            }

            Mod.Log.Info?.Write($"Adding SpawnAmbushSequence for {spawnedActors.Count} actors and {buildingsToLevel.Count} buildings to be leveled.");
            try
            {
                SpawnAmbushSequence ambushSequence = new SpawnAmbushSequence(ModState.Combat, ambushOrigin, spawnedActors, buildingsToLevel, targets, applyAttacks);
                ModState.Combat.MessageCenter.PublishMessage(new AddSequenceToStackMessage(ambushSequence));
            }
            catch (Exception e)
            {
                Mod.Log.Error?.Write(e, "Failed to create AES sequence due to error!");
            }
        }