diff --git a/OpenRA.Mods.RA/BelowUnits.cs b/OpenRA.Mods.RA/BelowUnits.cs index 73c6fe4616..9de8e5b48d 100644 --- a/OpenRA.Mods.RA/BelowUnits.cs +++ b/OpenRA.Mods.RA/BelowUnits.cs @@ -29,7 +29,7 @@ namespace OpenRA.Mods.RA { // Offset effective position to the top of the northernmost occupied cell var bi = self.Info.Traits.GetOrDefault(); - offset = (bi != null) ? -FootprintUtils.CenterOffset(bi).Y : -512; + offset = ((bi != null) ? -FootprintUtils.CenterOffset(bi).Y : 0) - 512; } public IEnumerable ModifyRender(Actor self, WorldRenderer wr, IEnumerable r) diff --git a/OpenRA.Mods.RA/Buildings/BaseProvider.cs b/OpenRA.Mods.RA/Buildings/BaseProvider.cs index 0622f5a441..c3c28e8b61 100755 --- a/OpenRA.Mods.RA/Buildings/BaseProvider.cs +++ b/OpenRA.Mods.RA/Buildings/BaseProvider.cs @@ -17,7 +17,7 @@ namespace OpenRA.Mods.RA.Buildings { public class BaseProviderInfo : ITraitInfo { - public readonly float Range = 10; + public readonly int Range = 10; public readonly int Cooldown = 0; public readonly int InitialDelay = 0; diff --git a/OpenRA.Mods.RA/Buildings/Building.cs b/OpenRA.Mods.RA/Buildings/Building.cs index f4904e8b82..dbe8fda472 100755 --- a/OpenRA.Mods.RA/Buildings/Building.cs +++ b/OpenRA.Mods.RA/Buildings/Building.cs @@ -38,23 +38,20 @@ namespace OpenRA.Mods.RA.Buildings public object Create(ActorInitializer init) { return new Building(init, this); } - public PPos CenterLocation(CPos topLeft) + public Actor FindBaseProvider(World world, Player p, CPos topLeft) { - return (PPos)((2 * topLeft.ToInt2() + Dimensions) * Game.CellSize / 2); - } - - bool HasBaseProvider(World world, Player p, CPos topLeft) - { - var center = CenterLocation(topLeft); + var center = topLeft.CenterPosition + FootprintUtils.CenterOffset(this); foreach (var bp in world.ActorsWithTrait()) { if (bp.Actor.Owner.Stances[p] != Stance.Ally || !bp.Trait.Ready()) continue; - if (Combat.IsInRange(center, bp.Trait.Info.Range, bp.Actor.CenterLocation)) - return true; + // Range is counted from the center of the actor, not from each cell. + var target = Target.FromPos(bp.Actor.CenterLocation); + if (target.IsInRange(center, WRange.FromCells(bp.Trait.Info.Range))) + return bp.Actor; } - return false; + return null; } public bool IsCloseEnoughToBase(World world, Player p, string buildingName, CPos topLeft) @@ -62,7 +59,7 @@ namespace OpenRA.Mods.RA.Buildings if (p.PlayerActor.Trait().BuildAnywhere) return true; - if (RequiresBaseProvider && !HasBaseProvider(world, p, topLeft)) + if (RequiresBaseProvider && FindBaseProvider(world, p, topLeft) == null) return false; var buildingMaxBounds = (CVec)Dimensions; @@ -126,7 +123,9 @@ namespace OpenRA.Mods.RA.Buildings occupiedCells = FootprintUtils.UnpathableTiles( self.Info.Name, Info, TopLeft ) .Select(c => Pair.New(c, SubCell.FullCell)).ToArray(); - pxPosition = Info.CenterLocation(topLeft); + + var position = topLeft.CenterPosition + FootprintUtils.CenterOffset(Info); + pxPosition = PPos.FromWPosHackZ(position); } public int GetPowerUsage() diff --git a/OpenRA.Mods.RA/Buildings/FootprintUtils.cs b/OpenRA.Mods.RA/Buildings/FootprintUtils.cs index cddc6ac7c2..ddddcef376 100755 --- a/OpenRA.Mods.RA/Buildings/FootprintUtils.cs +++ b/OpenRA.Mods.RA/Buildings/FootprintUtils.cs @@ -65,7 +65,8 @@ namespace OpenRA.Mods.RA.Buildings public static WVec CenterOffset(BuildingInfo buildingInfo) { var dim = buildingInfo.Dimensions; - return new CVec(dim.X, dim.Y).ToWVec() / 2; + // Offset is measured relative to the center of the cell, so need to subtract an additional half cell. + return new CVec(dim.X, dim.Y).ToWVec() / 2 - new WVec(512, 512, 0); } } } diff --git a/OpenRA.Mods.RA/Orders/PlaceBuildingOrderGenerator.cs b/OpenRA.Mods.RA/Orders/PlaceBuildingOrderGenerator.cs index b561ca2dfd..602c48b42e 100755 --- a/OpenRA.Mods.RA/Orders/PlaceBuildingOrderGenerator.cs +++ b/OpenRA.Mods.RA/Orders/PlaceBuildingOrderGenerator.cs @@ -98,7 +98,7 @@ namespace OpenRA.Mods.RA.Orders initialized = true; } - var offset = (topLeft - CPos.Zero).ToWVec() + FootprintUtils.CenterOffset(BuildingInfo); + var offset = topLeft.CenterPosition + FootprintUtils.CenterOffset(BuildingInfo) - WPos.Zero; foreach (var r in preview) r.WithPos(r.Pos + offset).Render(wr); diff --git a/OpenRA.Mods.RA/Player/PlaceBuilding.cs b/OpenRA.Mods.RA/Player/PlaceBuilding.cs index 607b8f647f..cfa783579b 100755 --- a/OpenRA.Mods.RA/Player/PlaceBuilding.cs +++ b/OpenRA.Mods.RA/Player/PlaceBuilding.cs @@ -83,18 +83,11 @@ namespace OpenRA.Mods.RA if (buildingInfo.RequiresBaseProvider) { - var center = buildingInfo.CenterLocation(order.TargetLocation); - foreach (var bp in w.ActorsWithTrait()) - { - if (bp.Actor.Owner.Stances[self.Owner] != Stance.Ally || !bp.Trait.Ready()) - continue; - - if (Combat.IsInRange(center, bp.Trait.Info.Range, bp.Actor.CenterLocation)) - { - bp.Trait.BeginCooldown(); - break; - } - } + // May be null if the build anywhere cheat is active + // BuildingInfo.IsCloseEnoughToBase has already verified that this is a valid build location + var producer = buildingInfo.FindBaseProvider(w, self.Owner, order.TargetLocation); + if (producer != null) + producer.Trait().BeginCooldown(); } if (GetNumBuildables(self.Owner) > prevItems) diff --git a/OpenRA.Mods.RA/Render/RenderBuildingWarFactory.cs b/OpenRA.Mods.RA/Render/RenderBuildingWarFactory.cs index a766115f47..23e55b5cde 100755 --- a/OpenRA.Mods.RA/Render/RenderBuildingWarFactory.cs +++ b/OpenRA.Mods.RA/Render/RenderBuildingWarFactory.cs @@ -49,10 +49,12 @@ namespace OpenRA.Mods.RA.Render : base(init, info) { roof = new Animation(GetImage(init.self)); - var bi = init.self.Info.Traits.Get(); + + // Additional 512 units move from center -> top of cell + var offset = FootprintUtils.CenterOffset(bi).Y + 512; anims.Add("roof", new AnimationWithOffset(roof, null, - () => !buildComplete, FootprintUtils.CenterOffset(bi).Y)); + () => !buildComplete, offset)); } public void BuildingComplete( Actor self )