Exemple #1
0
        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");
            }
        }
Exemple #5
0
        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
                });
            }
        }
Exemple #6
0
        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));
            }
        }
Exemple #10
0
        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));
            }
        }