public void ResolveOrder(Actor self, Order order) { var os = order.OrderString; if (os != "PlaceBuilding" && os != "LineBuild" && os != "PlacePlug") { return; } self.World.AddFrameEndTask(w => { var prevItems = GetNumBuildables(self.Owner); if (order.TargetActor.IsDead) { return; } var unit = self.World.Map.Rules.Actors[order.TargetString]; var queue = order.TargetActor.TraitsImplementing <ProductionQueue>() .FirstOrDefault(q => q.CanBuild(unit) && q.CurrentItem() != null && q.CurrentItem().Item == order.TargetString && q.CurrentItem().RemainingTime == 0); if (queue == null) { return; } var producer = queue.MostLikelyProducer(); var faction = producer.Trait != null ? producer.Trait.Faction : self.Owner.Faction.InternalName; var buildingInfo = unit.Traits.Get <BuildingInfo>(); var buildableInfo = unit.Traits.GetOrDefault <BuildableInfo>(); if (buildableInfo != null && buildableInfo.ForceFaction != null) { faction = buildableInfo.ForceFaction; } if (os == "LineBuild") { var playSounds = true; foreach (var t in BuildingUtils.GetLineBuildCells(w, order.TargetLocation, order.TargetString, buildingInfo)) { var building = w.CreateActor(order.TargetString, new TypeDictionary { new LocationInit(t), new OwnerInit(order.Player), new FactionInit(faction) }); if (playSounds) { foreach (var s in buildingInfo.BuildSounds) { Sound.PlayToPlayer(order.Player, s, building.CenterPosition); } } playSounds = false; } } else if (os == "PlacePlug") { var host = self.World.WorldActor.Trait <BuildingInfluence>().GetBuildingAt(order.TargetLocation); if (host == null) { return; } var plugInfo = unit.Traits.GetOrDefault <PlugInfo>(); if (plugInfo == null) { return; } var location = host.Location; var pluggable = host.TraitsImplementing <Pluggable>() .FirstOrDefault(p => location + p.Info.Offset == order.TargetLocation && p.AcceptsPlug(host, plugInfo.Type)); if (pluggable == null) { return; } pluggable.EnablePlug(host, plugInfo.Type); foreach (var s in buildingInfo.BuildSounds) { Sound.PlayToPlayer(order.Player, s, host.CenterPosition); } } else { if (!self.World.CanPlaceBuilding(order.TargetString, buildingInfo, order.TargetLocation, null) || !buildingInfo.IsCloseEnoughToBase(self.World, order.Player, order.TargetString, order.TargetLocation)) { return; } var building = w.CreateActor(order.TargetString, new TypeDictionary { new LocationInit(order.TargetLocation), new OwnerInit(order.Player), new FactionInit(faction), }); foreach (var s in buildingInfo.BuildSounds) { Sound.PlayToPlayer(order.Player, s, building.CenterPosition); } } if (producer.Actor != null) { foreach (var nbp in producer.Actor.TraitsImplementing <INotifyBuildingPlaced>()) { nbp.BuildingPlaced(producer.Actor); } } queue.FinishProduction(); if (buildingInfo.RequiresBaseProvider) { // May be null if the build anywhere cheat is active // BuildingInfo.IsCloseEnoughToBase has already verified that this is a valid build location var provider = buildingInfo.FindBaseProvider(w, self.Owner, order.TargetLocation); if (provider != null) { provider.Trait <BaseProvider>().BeginCooldown(); } } if (GetNumBuildables(self.Owner) > prevItems) { w.Add(new DelayedAction(info.NewOptionsNotificationDelay, () => Sound.PlayNotification(self.World.Map.Rules, order.Player, "Speech", info.NewOptionsNotification, order.Player.Faction.InternalName))); } }); }
void IResolveOrder.ResolveOrder(Actor self, Order order) { var os = order.OrderString; if (os != "PlaceBuilding" && os != "LineBuild" && os != "PlacePlug") { return; } self.World.AddFrameEndTask(w => { var prevItems = GetNumBuildables(self.Owner); var targetActor = w.GetActorById(order.ExtraData); var targetLocation = w.Map.CellContaining(order.Target.CenterPosition); if (targetActor == null || targetActor.IsDead) { return; } var actorInfo = self.World.Map.Rules.Actors[order.TargetString]; var queue = targetActor.TraitsImplementing <ProductionQueue>() .FirstOrDefault(q => q.CanBuild(actorInfo) && q.AllQueued().Any(i => i.Done && i.Item == order.TargetString)); if (queue == null) { return; } // Find the ProductionItem associated with the building that we are trying to place var item = queue.AllQueued().FirstOrDefault(i => i.Done && i.Item == order.TargetString); if (item == null) { return; } // Override with the alternate actor if (order.ExtraLocation.X > 0) { var variant = actorInfo.TraitInfos <PlaceBuildingVariantsInfo>() .SelectMany(p => p.Actors) .Skip(order.ExtraLocation.X - 1) .FirstOrDefault(); if (variant != null) { actorInfo = self.World.Map.Rules.Actors[variant]; } } var producer = queue.MostLikelyProducer(); var faction = producer.Trait?.Faction ?? self.Owner.Faction.InternalName; var buildingInfo = actorInfo.TraitInfo <BuildingInfo>(); var buildableInfo = actorInfo.TraitInfoOrDefault <BuildableInfo>(); if (buildableInfo != null && buildableInfo.ForceFaction != null) { faction = buildableInfo.ForceFaction; } if (os == "LineBuild") { // Build the parent actor first var placed = w.CreateActor(actorInfo.Name, new TypeDictionary { new LocationInit(targetLocation), new OwnerInit(order.Player), new FactionInit(faction), new PlaceBuildingInit() }); foreach (var s in buildingInfo.BuildSounds) { Game.Sound.PlayToPlayer(SoundType.World, order.Player, s, placed.CenterPosition); } // Build the connection segments var segmentType = actorInfo.TraitInfo <LineBuildInfo>().SegmentType; if (string.IsNullOrEmpty(segmentType)) { segmentType = actorInfo.Name; } foreach (var t in BuildingUtils.GetLineBuildCells(w, targetLocation, actorInfo, buildingInfo, order.Player)) { if (t.Cell == targetLocation) { continue; } w.CreateActor(t.Cell == targetLocation ? actorInfo.Name : segmentType, new TypeDictionary { new LocationInit(t.Cell), new OwnerInit(order.Player), new FactionInit(faction), new LineBuildDirectionInit(t.Cell.X == targetLocation.X ? LineBuildDirection.Y : LineBuildDirection.X), new LineBuildParentInit(new[] { t.Actor, placed }), new PlaceBuildingInit() }); } } else if (os == "PlacePlug") { var plugInfo = actorInfo.TraitInfoOrDefault <PlugInfo>(); if (plugInfo == null) { return; } foreach (var a in self.World.ActorMap.GetActorsAt(targetLocation)) { var pluggables = a.TraitsImplementing <Pluggable>() .Where(p => p.AcceptsPlug(a, plugInfo.Type)) .ToList(); var pluggable = pluggables.FirstOrDefault(p => a.Location + p.Info.Offset == targetLocation) ?? pluggables.FirstOrDefault(); if (pluggable == null) { return; } pluggable.EnablePlug(a, plugInfo.Type); foreach (var s in buildingInfo.BuildSounds) { Game.Sound.PlayToPlayer(SoundType.World, order.Player, s, a.CenterPosition); } } } else { if (!self.World.CanPlaceBuilding(targetLocation, actorInfo, buildingInfo, null) || !buildingInfo.IsCloseEnoughToBase(self.World, order.Player, actorInfo, targetLocation)) { return; } var replaceableTypes = actorInfo.TraitInfos <ReplacementInfo>() .SelectMany(r => r.ReplaceableTypes) .ToHashSet(); if (replaceableTypes.Any()) { foreach (var t in buildingInfo.Tiles(targetLocation)) { foreach (var a in self.World.ActorMap.GetActorsAt(t)) { if (a.TraitsImplementing <Replaceable>().Any(r => !r.IsTraitDisabled && r.Info.Types.Overlaps(replaceableTypes))) { self.World.Remove(a); } } } } var building = w.CreateActor(actorInfo.Name, new TypeDictionary { new LocationInit(targetLocation), new OwnerInit(order.Player), new FactionInit(faction), new PlaceBuildingInit() }); foreach (var s in buildingInfo.BuildSounds) { Game.Sound.PlayToPlayer(SoundType.World, order.Player, s, building.CenterPosition); } } if (producer.Actor != null) { foreach (var nbp in producer.Actor.TraitsImplementing <INotifyBuildingPlaced>()) { nbp.BuildingPlaced(producer.Actor); } } queue.EndProduction(item); // FindBaseProvider may return null if the build anywhere cheat is active // BuildingInfo.IsCloseEnoughToBase has already verified that this is a valid build location if (buildingInfo.RequiresBaseProvider) { buildingInfo.FindBaseProvider(w, self.Owner, targetLocation)?.BeginCooldown(); } if (GetNumBuildables(self.Owner) > prevItems) { triggerNotification = true; } }); }
void IResolveOrder.ResolveOrder(Actor self, Order order) { var os = order.OrderString; if (os != "PlaceBuilding" && os != "LineBuild" && os != "PlacePlug") { return; } self.World.AddFrameEndTask(w => { var prevItems = GetNumBuildables(self.Owner); if (order.TargetActor.IsDead) { return; } var unit = self.World.Map.Rules.Actors[order.TargetString]; var queue = order.TargetActor.TraitsImplementing <ProductionQueue>() .FirstOrDefault(q => q.CanBuild(unit) && q.CurrentItem() != null && q.CurrentItem().Item == order.TargetString && q.CurrentItem().RemainingTime == 0); if (queue == null) { return; } var producer = queue.MostLikelyProducer(); var faction = producer.Trait != null ? producer.Trait.Faction : self.Owner.Faction.InternalName; var buildingInfo = unit.TraitInfo <BuildingInfo>(); var buildableInfo = unit.TraitInfoOrDefault <BuildableInfo>(); if (buildableInfo != null && buildableInfo.ForceFaction != null) { faction = buildableInfo.ForceFaction; } if (os == "LineBuild") { // Build the parent actor first var placed = w.CreateActor(order.TargetString, new TypeDictionary { new LocationInit(order.TargetLocation), new OwnerInit(order.Player), new FactionInit(faction), }); foreach (var s in buildingInfo.BuildSounds) { Game.Sound.PlayToPlayer(SoundType.World, order.Player, s, placed.CenterPosition); } // Build the connection segments var segmentType = unit.TraitInfo <LineBuildInfo>().SegmentType; if (string.IsNullOrEmpty(segmentType)) { segmentType = order.TargetString; } foreach (var t in BuildingUtils.GetLineBuildCells(w, order.TargetLocation, order.TargetString, buildingInfo)) { if (t.First == order.TargetLocation) { continue; } w.CreateActor(t.First == order.TargetLocation ? order.TargetString : segmentType, new TypeDictionary { new LocationInit(t.First), new OwnerInit(order.Player), new FactionInit(faction), new LineBuildDirectionInit(t.First.X == order.TargetLocation.X ? LineBuildDirection.Y : LineBuildDirection.X), new LineBuildParentInit(new[] { t.Second, placed }) }); } } else if (os == "PlacePlug") { var host = self.World.WorldActor.Trait <BuildingInfluence>().GetBuildingAt(order.TargetLocation); if (host == null) { return; } var plugInfo = unit.TraitInfoOrDefault <PlugInfo>(); if (plugInfo == null) { return; } var location = host.Location; var pluggable = host.TraitsImplementing <Pluggable>() .FirstOrDefault(p => location + p.Info.Offset == order.TargetLocation && p.AcceptsPlug(host, plugInfo.Type)); if (pluggable == null) { return; } pluggable.EnablePlug(host, plugInfo.Type); foreach (var s in buildingInfo.BuildSounds) { Game.Sound.PlayToPlayer(SoundType.World, order.Player, s, host.CenterPosition); } } else { if (!self.World.CanPlaceBuilding(order.TargetString, buildingInfo, order.TargetLocation, null) || !buildingInfo.IsCloseEnoughToBase(self.World, order.Player, order.TargetString, order.TargetLocation)) { return; } var building = w.CreateActor(order.TargetString, new TypeDictionary { new LocationInit(order.TargetLocation), new OwnerInit(order.Player), new FactionInit(faction), }); foreach (var s in buildingInfo.BuildSounds) { Game.Sound.PlayToPlayer(SoundType.World, order.Player, s, building.CenterPosition); } } if (producer.Actor != null) { foreach (var nbp in producer.Actor.TraitsImplementing <INotifyBuildingPlaced>()) { nbp.BuildingPlaced(producer.Actor); } } queue.FinishProduction(); if (buildingInfo.RequiresBaseProvider) { // May be null if the build anywhere cheat is active // BuildingInfo.IsCloseEnoughToBase has already verified that this is a valid build location var provider = buildingInfo.FindBaseProvider(w, self.Owner, order.TargetLocation); if (provider != null) { provider.Trait <BaseProvider>().BeginCooldown(); } } if (GetNumBuildables(self.Owner) > prevItems) { triggerNotification = true; } }); }