bool TickQueue(IBot bot, ProductionQueue queue) { var currentBuilding = queue.AllQueued().FirstOrDefault(); // Waiting to build something if (currentBuilding == null && failCount < baseBuilder.Info.MaximumFailedPlacementAttempts) { var item = ChooseBuildingToBuild(queue); if (item == null) { return(false); } bot.QueueOrder(Order.StartProduction(queue.Actor, item.Name, 1)); } else if (currentBuilding != null && currentBuilding.Done) { // Production is complete // Choose the placement logic // HACK: HACK HACK HACK // TODO: Derive this from BuildingCommonNames instead var type = BuildingType.Building; CPos? location = null; string orderString = "PlaceBuilding"; // Check if Building is a plug for other Building var actorInfo = world.Map.Rules.Actors[currentBuilding.Item]; var plugInfo = actorInfo.TraitInfoOrDefault <PlugInfo>(); if (plugInfo != null) { var possibleBuilding = world.ActorsWithTrait <Pluggable>().FirstOrDefault(a => a.Actor.Owner == player && a.Trait.AcceptsPlug(a.Actor, plugInfo.Type)); if (possibleBuilding.Actor != null) { orderString = "PlacePlug"; location = possibleBuilding.Actor.Location + possibleBuilding.Trait.Info.Offset; } } else { // Check if Building is a defense and if we should place it towards the enemy or not. if (actorInfo.HasTraitInfo <AttackBaseInfo>() && world.LocalRandom.Next(100) < baseBuilder.Info.PlaceDefenseTowardsEnemyChance) { type = BuildingType.Defense; } else if (baseBuilder.Info.RefineryTypes.Contains(actorInfo.Name)) { type = BuildingType.Refinery; } location = ChooseBuildLocation(currentBuilding.Item, true, type); } if (location == null) { AIUtils.BotDebug("{0} has nowhere to place {1}".F(player, currentBuilding.Item)); bot.QueueOrder(Order.CancelProduction(queue.Actor, currentBuilding.Item, 1)); failCount += failCount; // If we just reached the maximum fail count, cache the number of current structures if (failCount == baseBuilder.Info.MaximumFailedPlacementAttempts) { cachedBuildings = world.ActorsHavingTrait <Building>().Count(a => a.Owner == player); cachedBases = world.ActorsHavingTrait <BaseProvider>().Count(a => a.Owner == player); } } else { failCount = 0; bot.QueueOrder(new Order(orderString, player.PlayerActor, Target.FromCell(world, location.Value), false) { // Building to place TargetString = currentBuilding.Item, // Actor ID to associate the placement with ExtraData = queue.Actor.ActorID, SuppressVisualFeedback = true }); return(true); } } return(true); }
bool TickQueue(IBot bot, ProductionQueue queue) { var currentBuilding = queue.AllQueued().FirstOrDefault(); // Waiting to build something if (currentBuilding == null && failCount < baseBuilder.Info.MaximumFailedPlacementAttempts) { var item = ChooseBuildingToBuild(queue); if (item == null) { return(false); } bot.QueueOrder(Order.StartProduction(queue.Actor, item.Name, 1)); } else if (currentBuilding != null && currentBuilding.Done) { // Production is complete // Choose the placement logic // HACK: HACK HACK HACK // TODO: Derive this from BuildingCommonNames instead var type = BuildingType.Building; if (world.Map.Rules.Actors[currentBuilding.Item].HasTraitInfo <AttackBaseInfo>()) { type = BuildingType.Defense; } else if (baseBuilder.Info.RefineryTypes.Contains(world.Map.Rules.Actors[currentBuilding.Item].Name)) { type = BuildingType.Refinery; } var location = ChooseBuildLocation(currentBuilding.Item, true, type); if (location == null) { AIUtils.BotDebug("AI: {0} has nowhere to place {1}".F(player, currentBuilding.Item)); bot.QueueOrder(Order.CancelProduction(queue.Actor, currentBuilding.Item, 1)); failCount += failCount; // If we just reached the maximum fail count, cache the number of current structures if (failCount == baseBuilder.Info.MaximumFailedPlacementAttempts) { cachedBuildings = world.ActorsHavingTrait <Building>().Count(a => a.Owner == player); cachedBases = world.ActorsHavingTrait <BaseProvider>().Count(a => a.Owner == player); } } else { failCount = 0; bot.QueueOrder(new Order("PlaceBuilding", player.PlayerActor, Target.FromCell(world, location.Value), false) { // Building to place TargetString = currentBuilding.Item, // Actor ID to associate the placement with ExtraData = queue.Actor.ActorID, SuppressVisualFeedback = true }); return(true); } } return(true); }