public void 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>()) { dec.Render(wr, world, actorInfo, world.Map.CenterOfCell(xy)); } var cells = new Dictionary <CPos, bool>(); // Linebuild for walls. // Assumes a 1x1 footprint; weird things will happen for other footprints if (rules.Actors[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.Actors[Building].Traits.GetOrDefault <RenderBuildingInfo>(); if (rbi == null) { preview = new IRenderable[0]; } else { var palette = rbi.Palette ?? (Producer.Owner != null ? rbi.PlayerPalette + Producer.Owner.InternalName : null); preview = rbi.RenderPreview(world, rules.Actors[Building], wr.Palette(palette)); } initialized = true; } var offset = world.Map.CenterOfCell(topLeft) + FootprintUtils.CenterOffset(world, 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(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; new SpriteRenderable(tile, world.Map.CenterOfCell(c.Key), WVec.Zero, -511, pal, 1f, true).Render(wr); } }
public CPos?ChooseBuildLocation(string actorType, bool distanceToBaseIsImportant, int maxBaseDistance, BuildingType type) { var bi = Rules.Info[actorType].Traits.GetOrDefault <BuildingInfo>(); if (bi == null) { return(null); } Func <WPos, CPos, CPos?> findPos = (pos, center) => { for (var k = MaxBaseDistance; k >= 0; k--) { var tlist = world.FindTilesInCircle(center, k) .OrderBy(a => (a.CenterPosition - pos).LengthSquared); foreach (var t in tlist) { if (world.CanPlaceBuilding(actorType, bi, t, null)) { if (bi.IsCloseEnoughToBase(world, p, actorType, t)) { if (NoBuildingsUnder(Util.ExpandFootprint(FootprintUtils.Tiles(actorType, bi, t), false))) { return(t); } } } } } return(null); }; switch (type) { case BuildingType.Defense: Actor enemyBase = FindEnemyBuildingClosestToPos(baseCenter.CenterPosition); return(enemyBase != null?findPos(enemyBase.CenterPosition, defenseCenter) : null); case BuildingType.Refinery: var tilesPos = world.FindTilesInCircle(baseCenter, MaxBaseDistance) .Where(a => resourceTypes.Contains(world.GetTerrainType(new CPos(a.X, a.Y)))) .OrderBy(a => (a.CenterPosition - baseCenter.CenterPosition).LengthSquared); return(tilesPos.Any() ? findPos(tilesPos.First().CenterPosition, baseCenter) : null); case BuildingType.Building: for (var k = 0; k < maxBaseDistance; k++) { foreach (var t in world.FindTilesInCircle(baseCenter, k)) { if (world.CanPlaceBuilding(actorType, bi, t, null)) { if (distanceToBaseIsImportant && !bi.IsCloseEnoughToBase(world, p, actorType, t)) { continue; } if (NoBuildingsUnder(Util.ExpandFootprint(FootprintUtils.Tiles(actorType, bi, t), false))) { return(t); } } } } break; } // Can't find a build location return(null); }
public override bool IsCloseEnoughToBase(World world, Player p, string buildingName, CPos topLeft) { if (base.IsCloseEnoughToBase(world, p, buildingName, topLeft)) { return(true); } var shroud = p.Shroud; var hasVisibleCells = false; var hasExploredCells = false; for (var y = topLeft.Y; y < topLeft.Y + Dimensions.Y; y++) { for (var x = topLeft.X; x < topLeft.X + Dimensions.X; x++) { var pos = new CPos(x, y); if (!shroud.IsExplored(pos)) { if (AllCellsShouldBeExplored) { return(false); } } else { hasExploredCells = true; } if (!shroud.IsVisible(pos)) { if (AllCellsShouldBeVisible) { return(false); } } else { hasVisibleCells = true; } } } if (AnyCellShouldBeExplored && !hasExploredCells) { return(false); } if (AnyCellShouldBeVisible && !hasVisibleCells) { return(false); } var scanStart = world.Map.Clamp(topLeft - new CVec(Adjacent, Adjacent)); var scanEnd = world.Map.Clamp(topLeft + Dimensions + new CVec(Adjacent, Adjacent)); var nearnessCandidates = new List <CPos>(); var co = world.WorldActor.Trait <D2ConcreteOwners>(); var allyBuildEnabled = world.WorldActor.Trait <MapBuildRadius>().AllyBuildRadiusEnabled; for (var y = scanStart.Y; y < scanEnd.Y; y++) { for (var x = scanStart.X; x < scanEnd.X; x++) { var pos = new CPos(x, y); if (shroud.IsExplored(pos) && shroud.IsVisible(pos)) { var ownerAtPos = co.GetOwnerAt(pos); if (ownerAtPos != null && (ownerAtPos == p || (allyBuildEnabled && ownerAtPos.Stances[p] == Stance.Ally))) { nearnessCandidates.Add(pos); } } } } var buildingTiles = FootprintUtils.Tiles(world.Map.Rules, buildingName, this, topLeft).ToList(); return(nearnessCandidates .Any(a => buildingTiles .Any(b => Math.Abs(a.X - b.X) <= Adjacent && Math.Abs(a.Y - b.Y) <= Adjacent))); }
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.TraitInfos <IPlaceBuildingDecorationInfo>()) { foreach (var r in dec.Render(wr, world, actorInfo, world.Map.CenterOfCell(xy))) { 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"); } foreach (var t in BuildingUtils.GetLineBuildCells(world, topLeft, building, buildingInfo)) { cells.Add(t, buildingInfo.IsCloseEnoughToBase(world, world.LocalPlayer, building, t)); } } else { if (!initialized) { var td = new TypeDictionary() { new FactionInit(faction), new OwnerInit(producer.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 offset = world.Map.CenterOfCell(topLeft) + FootprintUtils.CenterOffset(world, buildingInfo); 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> 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)); } }
public override void AddedToWorld(Actor self) { base.AddedToWorld(self); blockedPositions = FootprintUtils.Tiles(self); }