public EditorActorBrush(EditorViewportControllerWidget editorWidget, ActorInfo actor, PlayerReference owner, WorldRenderer wr) { this.editorWidget = editorWidget; worldRenderer = wr; world = wr.World; editorLayer = world.WorldActor.Trait <EditorActorLayer>(); Actor = actor; this.owner = owner; preview = editorWidget.Get <ActorPreviewWidget>("DRAG_ACTOR_PREVIEW"); preview.GetScale = () => worldRenderer.Viewport.Zoom; preview.IsVisible = () => editorWidget.CurrentBrush == this; var buildingInfo = actor.Traits.GetOrDefault <BuildingInfo>(); if (buildingInfo != null) { locationOffset = -FootprintUtils.AdjustForBuildingSize(buildingInfo); previewOffset = FootprintUtils.CenterOffset(world, buildingInfo); } var td = new TypeDictionary(); td.Add(new FacingInit(facing)); td.Add(new TurretFacingInit(facing)); td.Add(new OwnerInit(owner.Name)); td.Add(new RaceInit(owner.Race)); preview.SetPreview(actor, td); // The preview widget may be rendered by the higher-level code before it is ticked. // Force a manual tick to ensure the bounds are set correctly for this first draw. Tick(); }
IEnumerable <Order> InnerOrder(World world, CPos xy, MouseInput mi) { if (world.Paused) { yield break; } if (mi.Button == MouseButton.Left) { var topLeft = xy - FootprintUtils.AdjustForBuildingSize(BuildingInfo); if (!world.CanPlaceBuilding(Building, BuildingInfo, topLeft, null) || !BuildingInfo.IsCloseEnoughToBase(world, Producer.Owner, Building, topLeft)) { Sound.PlayNotification(world.Map.Rules, Producer.Owner, "Speech", "BuildingCannotPlaceAudio", Producer.Owner.Country.Race); yield break; } var isLineBuild = world.Map.Rules.Actors[Building].Traits.Contains <LineBuildInfo>(); yield return(new Order(isLineBuild ? "LineBuild" : "PlaceBuilding", Producer.Owner.PlayerActor, false) { TargetLocation = topLeft, TargetActor = Producer, TargetString = Building, SuppressVisualFeedback = true }); } }
public void RenderAfterWorld(WorldRenderer wr, World world) { var position = wr.Position(wr.Viewport.ViewToWorldPx(Viewport.LastMousePos)).ToCPos(); var topLeft = position - FootprintUtils.AdjustForBuildingSize(BuildingInfo); var actorInfo = Rules.Info[Building]; foreach (var dec in actorInfo.Traits.WithInterface <IPlaceBuildingDecoration>()) { dec.Render(wr, world, actorInfo, position.CenterPosition); /* hack hack */ } var cells = new Dictionary <CPos, bool>(); // Linebuild for walls. // Assumes a 1x1 footprint; weird things will happen for other footprints if (Rules.Info[Building].Traits.Contains <LineBuildInfo>()) { foreach (var t in BuildingUtils.GetLineBuildCells(world, topLeft, Building, BuildingInfo)) { cells.Add(t, BuildingInfo.IsCloseEnoughToBase(world, world.LocalPlayer, Building, t)); } } else { if (!initialized) { var rbi = Rules.Info[Building].Traits.Get <RenderBuildingInfo>(); var palette = rbi.Palette ?? (Producer.Owner != null ? rbi.PlayerPalette + Producer.Owner.InternalName : null); preview = rbi.RenderPreview(Rules.Info[Building], wr.Palette(palette)); initialized = true; } var offset = topLeft.CenterPosition + FootprintUtils.CenterOffset(BuildingInfo) - WPos.Zero; foreach (var r in preview) { r.OffsetBy(offset).Render(wr); } var res = world.WorldActor.Trait <ResourceLayer>(); var isCloseEnough = BuildingInfo.IsCloseEnoughToBase(world, world.LocalPlayer, Building, topLeft); foreach (var t in FootprintUtils.Tiles(Building, BuildingInfo, topLeft)) { cells.Add(t, isCloseEnough && world.IsCellBuildable(t, BuildingInfo) && res.GetResource(t) == null); } } var pal = wr.Palette("terrain"); foreach (var c in cells) { var tile = c.Value ? buildOk : buildBlocked; new SpriteRenderable(tile, c.Key.CenterPosition, WVec.Zero, -511, pal, 1f, true).Render(wr); } }
public void RenderBeforeWorld(WorldRenderer wr, World world) { var position = Game.viewport.ViewToWorld(Viewport.LastMousePos); var topLeft = position - FootprintUtils.AdjustForBuildingSize(BuildingInfo); var actorInfo = Rules.Info[Building]; foreach (var dec in actorInfo.Traits.WithInterface <IPlaceBuildingDecoration>()) { dec.Render(wr, world, actorInfo, Traits.Util.CenterOfCell(position)); /* hack hack */ } var cells = new Dictionary <CPos, bool>(); // Linebuild for walls. // Assumes a 1x1 footprint; weird things will happen for other footprints if (Rules.Info[Building].Traits.Contains <LineBuildInfo>()) { foreach (var t in BuildingUtils.GetLineBuildCells(world, topLeft, Building, BuildingInfo)) { cells.Add(t, BuildingInfo.IsCloseEnoughToBase(world, world.LocalPlayer, Building, t)); } } else { if (!initialized) { var rbi = Rules.Info[Building].Traits.Get <RenderBuildingInfo>(); var palette = rbi.Palette ?? (Producer.Owner != null ? rbi.PlayerPalette + Producer.Owner.InternalName : null); preview = rbi.RenderPreview(Rules.Info[Building], wr.Palette(palette)); initialized = true; } foreach (var r in preview) { r.Sprite.DrawAt(topLeft.ToPPos().ToFloat2() + r.Pos, r.Palette.Index, r.Scale * r.Sprite.size); } var res = world.WorldActor.Trait <ResourceLayer>(); var isCloseEnough = BuildingInfo.IsCloseEnoughToBase(world, world.LocalPlayer, Building, topLeft); foreach (var t in FootprintUtils.Tiles(Building, BuildingInfo, topLeft)) { cells.Add(t, isCloseEnough && world.IsCellBuildable(t, BuildingInfo) && res.GetResource(t) == null); } } foreach (var c in cells) { (c.Value ? buildOk : buildBlocked).DrawAt(wr, c.Key.ToPPos().ToFloat2(), "terrain"); } }
IEnumerable <Order> InnerOrder(World world, CPos cell, MouseInput mi) { if (world.Paused) { yield break; } var owner = queue.Actor.Owner; if (mi.Button == MouseButton.Left) { var orderType = "PlaceBuilding"; var topLeft = cell - FootprintUtils.AdjustForBuildingSize(buildingInfo); var plugInfo = world.Map.Rules.Actors[building].TraitInfoOrDefault <PlugInfo>(); if (plugInfo != null) { orderType = "PlacePlug"; if (!AcceptsPlug(topLeft, plugInfo)) { Game.Sound.PlayNotification(world.Map.Rules, owner, "Speech", "BuildingCannotPlaceAudio", owner.Faction.InternalName); yield break; } } else { if (!world.CanPlaceBuilding(building, buildingInfo, topLeft, null) || !buildingInfo.IsCloseEnoughToBase(world, owner, building, topLeft)) { foreach (var order in ClearBlockersOrders(world, topLeft)) { yield return(order); } Game.Sound.PlayNotification(world.Map.Rules, owner, "Speech", "BuildingCannotPlaceAudio", owner.Faction.InternalName); yield break; } if (world.Map.Rules.Actors[building].HasTraitInfo <LineBuildInfo>() && !mi.Modifiers.HasModifier(Modifiers.Shift)) { orderType = "LineBuild"; } } yield return(new Order(orderType, owner.PlayerActor, false) { TargetLocation = topLeft, TargetActor = queue.Actor, TargetString = building, SuppressVisualFeedback = true }); } }
IEnumerable <Order> InnerOrder(World world, CPos xy, MouseInput mi) { if (world.Paused) { yield break; } if (mi.Button == MouseButton.Left) { var orderType = "PlaceBuilding"; var topLeft = xy - FootprintUtils.AdjustForBuildingSize(buildingInfo); var plugInfo = world.Map.Rules.Actors[building].Traits.GetOrDefault <PlugInfo>(); if (plugInfo != null) { orderType = "PlacePlug"; if (!AcceptsPlug(topLeft, plugInfo)) { Sound.PlayNotification(world.Map.Rules, producer.Owner, "Speech", "BuildingCannotPlaceAudio", producer.Owner.Faction.InternalName); yield break; } } else { if (!world.CanPlaceBuilding(building, buildingInfo, topLeft, null) || !buildingInfo.IsCloseEnoughToBase(world, producer.Owner, building, topLeft)) { Sound.PlayNotification(world.Map.Rules, producer.Owner, "Speech", "BuildingCannotPlaceAudio", producer.Owner.Faction.InternalName); yield break; } if (world.Map.Rules.Actors[building].Traits.Contains <LineBuildInfo>()) { orderType = "LineBuild"; } } yield return(new Order(orderType, producer.Owner.PlayerActor, false) { TargetLocation = topLeft, TargetActor = producer, TargetString = building, SuppressVisualFeedback = true }); } }
public void RenderBeforeWorld(WorldRenderer wr, World world) { var position = Game.viewport.ViewToWorld(Viewport.LastMousePos).ToInt2(); var topLeft = position - FootprintUtils.AdjustForBuildingSize(BuildingInfo); var actorInfo = Rules.Info[Building]; foreach (var dec in actorInfo.Traits.WithInterface <IPlaceBuildingDecoration>()) { dec.Render(wr, world, actorInfo, Traits.Util.CenterOfCell(position)); /* hack hack */ } var cells = new Dictionary <int2, bool>(); // Linebuild for walls. // Assumes a 1x1 footprint; weird things will happen for other footprints if (Rules.Info[Building].Traits.Contains <LineBuildInfo>()) { foreach (var t in BuildingUtils.GetLineBuildCells(world, topLeft, Building, BuildingInfo)) { cells.Add(t, BuildingInfo.IsCloseEnoughToBase(world, world.LocalPlayer, Building, t)); } } else { foreach (var r in Preview) { r.Sprite.DrawAt(Game.CellSize * topLeft + r.Pos, wr.GetPaletteIndex(r.Palette), r.Scale * r.Sprite.size); } var res = world.WorldActor.Trait <ResourceLayer>(); var isCloseEnough = BuildingInfo.IsCloseEnoughToBase(world, world.LocalPlayer, Building, topLeft); foreach (var t in FootprintUtils.Tiles(Building, BuildingInfo, topLeft)) { cells.Add(t, isCloseEnough && world.IsCellBuildable(t, BuildingInfo) && res.GetResource(t) == null); } } foreach (var c in cells) { (c.Value ? buildOk : buildBlocked).DrawAt(wr, Game.CellSize * c.Key, "terrain"); } }
IEnumerable <Order> InnerOrder(World world, CPos xy, MouseInput mi) { if (mi.Button == MouseButton.Left) { var topLeft = xy - FootprintUtils.AdjustForBuildingSize(BuildingInfo); if (!world.CanPlaceBuilding(Building, BuildingInfo, topLeft, null) || !BuildingInfo.IsCloseEnoughToBase(world, Producer.Owner, Building, topLeft)) { var eva = world.WorldActor.Info.Traits.Get <EvaAlertsInfo>(); Sound.Play(eva.BuildingCannotPlaceAudio); yield break; } var isLineBuild = Rules.Info[Building].Traits.Contains <LineBuildInfo>(); yield return(new Order(isLineBuild ? "LineBuild" : "PlaceBuilding", Producer.Owner.PlayerActor, false) { TargetLocation = topLeft, TargetString = Building }); } }
IEnumerable <CPos> InnerOrder(World world, CPos cell, MouseInput mi) { if (world.Paused) { yield break; } var owner = self.Owner; if (mi.Button == MouseButton.Left) { var topLeft = cell - FootprintUtils.AdjustForBuildingSize(buildingInfo); var selfPos = self.Trait <IOccupySpace>().TopLeft; var isCloseEnough = ((topLeft - selfPos).Length) <= info.MaxDistance; if (!world.CanPlaceBuilding(building, buildingInfo, topLeft, null) || !isCloseEnough) { Game.Sound.PlayNotification(world.Map.Rules, owner, "Speech", "BuildingCannotPlaceAudio", owner.Faction.InternalName); yield break; } yield return(new CPos(topLeft.X, topLeft.Y)); } }
public IEnumerable <IRenderable> RenderAboveShroud(WorldRenderer wr, World world) { var xy = wr.Viewport.ViewToWorld(Viewport.LastMousePos); var topLeft = xy - FootprintUtils.AdjustForBuildingSize(buildingInfo); var offset = world.Map.CenterOfCell(topLeft) + FootprintUtils.CenterOffset(world, buildingInfo); var rules = world.Map.Rules; var actorInfo = rules.Actors[building]; foreach (var dec in actorInfo.TraitInfos <IPlaceBuildingDecorationInfo>()) { foreach (var r in dec.Render(wr, world, actorInfo, offset)) { yield return(r); } } var cells = new Dictionary <CPos, bool>(); var plugInfo = rules.Actors[building].TraitInfoOrDefault <PlugInfo>(); if (plugInfo != null) { if (buildingInfo.Dimensions.X != 1 || buildingInfo.Dimensions.Y != 1) { throw new InvalidOperationException("Plug requires a 1x1 sized Building"); } cells.Add(topLeft, AcceptsPlug(topLeft, plugInfo)); } else if (rules.Actors[building].HasTraitInfo <LineBuildInfo>()) { // Linebuild for walls. if (buildingInfo.Dimensions.X != 1 || buildingInfo.Dimensions.Y != 1) { throw new InvalidOperationException("LineBuild requires a 1x1 sized Building"); } if (!Game.GetModifierKeys().HasModifier(Modifiers.Shift)) { foreach (var t in BuildingUtils.GetLineBuildCells(world, topLeft, building, buildingInfo)) { cells.Add(t, buildingInfo.IsCloseEnoughToBase(world, world.LocalPlayer, building, t)); } } else { cells.Add(topLeft, buildingInfo.IsCloseEnoughToBase(world, world.LocalPlayer, building, topLeft)); } } else { if (!initialized) { var td = new TypeDictionary() { new FactionInit(faction), new OwnerInit(queue.Actor.Owner), new HideBibPreviewInit() }; var init = new ActorPreviewInitializer(rules.Actors[building], wr, td); preview = rules.Actors[building].TraitInfos <IRenderActorPreviewInfo>() .SelectMany(rpi => rpi.RenderPreview(init)) .ToArray(); initialized = true; } var previewRenderables = preview .SelectMany(p => p.Render(wr, offset)) .OrderBy(WorldRenderer.RenderableScreenZPositionComparisonKey); foreach (var r in previewRenderables) { yield return(r); } var res = world.WorldActor.Trait <ResourceLayer>(); var isCloseEnough = buildingInfo.IsCloseEnoughToBase(world, world.LocalPlayer, building, topLeft); foreach (var t in FootprintUtils.Tiles(rules, building, buildingInfo, topLeft)) { cells.Add(t, isCloseEnough && world.IsCellBuildable(t, buildingInfo) && res.GetResource(t) == null); } } var pal = wr.Palette(placeBuildingInfo.Palette); var topLeftPos = world.Map.CenterOfCell(topLeft); foreach (var c in cells) { var tile = c.Value ? buildOk : buildBlocked; var pos = world.Map.CenterOfCell(c.Key); yield return(new SpriteRenderable(tile, pos, new WVec(0, 0, topLeftPos.Z - pos.Z), -511, pal, 1f, true)); } }
public IEnumerable <IRenderable> RenderAfterWorld(WorldRenderer wr, World world) { var xy = wr.Viewport.ViewToWorld(Viewport.LastMousePos); var topLeft = xy - FootprintUtils.AdjustForBuildingSize(BuildingInfo); var rules = world.Map.Rules; var actorInfo = rules.Actors[Building]; foreach (var dec in actorInfo.Traits.WithInterface <IPlaceBuildingDecoration>()) { foreach (var r in dec.Render(wr, world, actorInfo, world.Map.CenterOfCell(xy))) { yield return(r); } } var cells = new Dictionary <CPos, bool>(); // Linebuild for walls. // Requires a 1x1 footprint if (rules.Actors[Building].Traits.Contains <LineBuildInfo>()) { if (BuildingInfo.Dimensions.X != 1 || BuildingInfo.Dimensions.Y != 1) { throw new InvalidOperationException("LineBuild requires a 1x1 sized Building"); } foreach (var t in BuildingUtils.GetLineBuildCells(world, topLeft, Building, BuildingInfo)) { cells.Add(t, BuildingInfo.IsCloseEnoughToBase(world, world.LocalPlayer, Building, t)); } } else { if (!initialized) { var init = new ActorPreviewInitializer(rules.Actors[Building], Producer.Owner, wr, new TypeDictionary()); preview = rules.Actors[Building].Traits.WithInterface <IRenderActorPreviewInfo>() .SelectMany(rpi => rpi.RenderPreview(init)) .ToArray(); initialized = true; } var comparer = new RenderableComparer(wr); var offset = world.Map.CenterOfCell(topLeft) + FootprintUtils.CenterOffset(world, BuildingInfo); var previewRenderables = preview .SelectMany(p => p.Render(wr, offset)) .OrderBy(r => r, comparer); foreach (var r in previewRenderables) { yield return(r); } var res = world.WorldActor.Trait <ResourceLayer>(); var isCloseEnough = BuildingInfo.IsCloseEnoughToBase(world, world.LocalPlayer, Building, topLeft); foreach (var t in FootprintUtils.Tiles(rules, Building, BuildingInfo, topLeft)) { cells.Add(t, isCloseEnough && world.IsCellBuildable(t, BuildingInfo) && res.GetResource(t) == null); } } var pal = wr.Palette("terrain"); foreach (var c in cells) { var tile = c.Value ? buildOk : buildBlocked; yield return(new SpriteRenderable(tile, world.Map.CenterOfCell(c.Key), WVec.Zero, -511, pal, 1f, true)); } }
public IEnumerable <IRenderable> RenderAboveShroud(WorldRenderer wr, World world) { // Draw chrono range yield return(new RangeCircleRenderable( self.CenterPosition, WDist.FromCells(self.Trait <StructureChrono>().Info.MaxDistance), 0, Color.FromArgb(128, Color.LawnGreen), Color.FromArgb(96, Color.Black))); var xy = wr.Viewport.ViewToWorld(Viewport.LastMousePos); var topLeft = xy - FootprintUtils.AdjustForBuildingSize(buildingInfo); var offset = world.Map.CenterOfCell(topLeft) + FootprintUtils.CenterOffset(world, buildingInfo); var rules = world.Map.Rules; var actorInfo = self.Info; // rules.Actors[building]; foreach (var dec in actorInfo.TraitInfos <IPlaceBuildingDecorationInfo>()) { foreach (var r in dec.Render(wr, world, actorInfo, offset)) { yield return(r); } } // Cells, we are about to construct and occupy. var cells = new Dictionary <CPos, bool>(); if (!initialized) { var td = new TypeDictionary() { //new OpenRA.Mods.Common.FactionInit(faction), new OpenRA.Mods.Common.FactionInit(""), new OwnerInit(self.Owner), new HideBibPreviewInit() }; var init = new ActorPreviewInitializer(actorInfo, wr, td); preview = actorInfo.TraitInfos <IRenderActorPreviewInfo>() .SelectMany(rpi => rpi.RenderPreview(init)) .ToArray(); initialized = true; } var previewRenderables = preview .SelectMany(p => p.Render(wr, offset)) .OrderBy(WorldRenderer.RenderableScreenZPositionComparisonKey); foreach (var r in previewRenderables) { yield return(r); } var res = world.WorldActor.Trait <ResourceLayer>(); var selfPos = self.Trait <IOccupySpace>().TopLeft; var isCloseEnough = ((topLeft - selfPos).Length) <= info.MaxDistance; foreach (var t in FootprintUtils.Tiles(rules, building, buildingInfo, topLeft)) { cells.Add(t, isCloseEnough && world.IsCellBuildable(t, buildingInfo) && res.GetResource(t) == null); } var placeBuildingInfo = self.Owner.PlayerActor.Info.TraitInfo <PlaceBuildingInfo>(); var pal = wr.Palette(placeBuildingInfo.Palette); var topLeftPos = world.Map.CenterOfCell(topLeft); // draw red or white buildable cell indicator. foreach (var c in cells) { var tile = c.Value ? buildOk : buildBlocked; var pos = world.Map.CenterOfCell(c.Key); yield return(new SpriteRenderable(tile, pos, new WVec(0, 0, topLeftPos.Z - pos.Z), -511, pal, 1f, true)); } }