/// <see cref="IFogOfWarBC.GetPlacementSuggestions"/> public RCSet <RCIntRectangle> GetPlacementSuggestions(IBuildingType buildingType) { if (this.ActiveScenario == null) { throw new InvalidOperationException("No active scenario!"); } RCIntRectangle quadWindow = this.mapWindowBC.AttachedWindow.QuadTileWindow; RCSet <Tuple <RCIntRectangle, RCIntVector> > suggestions = buildingType.GetPlacementSuggestions(this.ActiveScenario, quadWindow); RCSet <RCIntRectangle> retList = new RCSet <RCIntRectangle>(); foreach (Tuple <RCIntRectangle, RCIntVector> suggestion in suggestions) { RCIntRectangle areaToCheck = suggestion.Item1; RCIntVector suggestionTranslation = suggestion.Item2; for (int x = areaToCheck.Left; x < areaToCheck.Right; x++) { for (int y = areaToCheck.Top; y < areaToCheck.Bottom; y++) { RCIntVector quadCoordToCheck = new RCIntVector(x, y); if (quadCoordToCheck.X >= 0 && quadCoordToCheck.X < this.ActiveScenario.Map.Size.X && quadCoordToCheck.Y >= 0 && quadCoordToCheck.Y < this.ActiveScenario.Map.Size.Y && this.GetFowState(quadCoordToCheck) == FOWTypeEnum.None) { RCIntVector buildingQuadSize = this.ActiveScenario.Map.CellToQuadSize(buildingType.Area.Read().Size); retList.Add(new RCIntRectangle(areaToCheck.Location + suggestionTranslation, buildingQuadSize)); } } } } return(retList); }
/// <see cref="IFogOfWarBC.CheckPlacementConstraints"/> public RCSet <RCIntVector> CheckPlacementConstraints(IBuildingType buildingType, RCIntVector position, IAddonType addonType, RCSet <Entity> entitiesToIgnore) { if (this.ActiveScenario == null) { throw new InvalidOperationException("No active scenario!"); } RCIntVector objectQuadraticSize = this.ActiveScenario.Map.CellToQuadSize(buildingType.Area.Read().Size); RCSet <RCIntVector> violatingQuadCoords = buildingType.CheckPlacementConstraints(this.ActiveScenario, position, addonType, entitiesToIgnore); for (int x = 0; x < objectQuadraticSize.X; x++) { for (int y = 0; y < objectQuadraticSize.Y; y++) { RCIntVector relativeQuadCoords = new RCIntVector(x, y); RCIntVector absQuadCoords = position + relativeQuadCoords; if (absQuadCoords.X < 0 || absQuadCoords.X >= this.ActiveScenario.Map.Size.X || absQuadCoords.Y < 0 || absQuadCoords.Y >= this.ActiveScenario.Map.Size.Y || this.GetFullFowTileFlags(absQuadCoords).HasFlag(FOWTileFlagsEnum.Current)) { violatingQuadCoords.Add(relativeQuadCoords); } } } return(violatingQuadCoords); }
/// <see cref="IScenarioMetadata.GetBuildingType"/> public IBuildingType GetBuildingType(string buildingTypeName) { if (this.attachedMetadata == null) { throw new InvalidOperationException("Metadata not yet attached!"); } IBuildingType attachedBuildingType = this.attachedMetadata.GetBuildingType(buildingTypeName); return(new IBuildingType(this.GetElementTypeUpgradeImpl(attachedBuildingType.Name))); }
/// <see cref="CmdExecutionBase.InitializeImpl"/> protected override void InitializeImpl() { IBuildingType buildingType = this.RecipientSCV.Owner.Metadata.GetBuildingType(this.buildingTypeName); RCIntVector entityQuadSize = this.Scenario.Map.CellToQuadSize(buildingType.Area.Read().Size); RCIntRectangle targetPositionQuadRect = new RCIntRectangle(this.topLeftQuadTile.Read(), entityQuadSize); this.targetArea.Write((RCNumRectangle)this.Scenario.Map.QuadToCellRect(targetPositionQuadRect) - new RCNumVector(1, 1) / 2); this.TargetPosition = this.targetArea.Read().Location - buildingType.Area.Read().Location; this.RecipientSCV.MotionControl.StartMoving(this.TargetPosition); this.Status = SCVBuildExecutionStatusEnum.MovingToTarget; }
public BuildingType(IBuildingType copyFrom) : base(copyFrom) { Unlocks = new List <uint>(copyFrom.Unlocks); Builds = new List <uint>(copyFrom.Builds); Researches = new List <uint>(copyFrom.Researches); DisplayRow = copyFrom.DisplayRow; DisplayColumn = copyFrom.DisplayColumn; }
/// <summary> /// Sets the building type that this provider belongs to. /// </summary> /// <param name="buildingType">The building type that this provider belongs to.</param> /// <exception cref="SimulatorException">If a corresponding building type has already been set for this provider.</exception> public void SetBuildingType(IBuildingType buildingType) { if (buildingType == null) { throw new ArgumentNullException("buildingType"); } if (this.buildingType != null) { throw new SimulatorException("Building type has already been set for this provider!"); } this.buildingType = buildingType; }
/// <see cref="ITargetPositionListener.SelectTargetPosition"/> public void SelectTargetPosition(RCNumVector targetPosition) { if (this.placeSelectedBuilding) { /// A position for the current selection is being selected. int[] currentSelection = this.selectionManagerBC.CurrentSelection.ToArray(); if (currentSelection.Length != 1) { throw new InvalidOperationException("The number of the currently selected entities must be 1!"); } Building selectedBuilding = this.scenarioManagerBC.ActiveScenario.GetElement <Building>(currentSelection[0]); if (selectedBuilding == null) { throw new InvalidOperationException("The currently selected entity doesn't exist or is not a building!"); } IQuadTile quadTileAtPos = this.scenarioManagerBC.ActiveScenario.Map.GetCell(targetPosition.Round()).ParentQuadTile; RCIntVector objQuadSize = this.scenarioManagerBC.ActiveScenario.Map.CellToQuadSize(selectedBuilding.ElementType.Area.Read().Size); RCIntVector topLeftQuadCoords = quadTileAtPos.MapCoords - objQuadSize / 2; this.CommandBuilder.TargetPosition = topLeftQuadCoords; } else if (this.buildingTypeName != null) { /// A position for a building type is being selected. IBuildingType buildingType = this.scenarioManagerBC.Metadata.GetBuildingType(this.buildingTypeName); if (buildingType == null) { throw new InvalidOperationException(string.Format("Building type '{0}' is not defined in the metadata!", this.buildingTypeName)); } IQuadTile quadTileAtPos = this.scenarioManagerBC.ActiveScenario.Map.GetCell(targetPosition.Round()).ParentQuadTile; RCIntVector objQuadSize = this.scenarioManagerBC.ActiveScenario.Map.CellToQuadSize(buildingType.Area.Read().Size); RCIntVector topLeftQuadCoords = quadTileAtPos.MapCoords - objQuadSize / 2; this.CommandBuilder.TargetPosition = topLeftQuadCoords; } else { /// A point on the map is being selected. this.CommandBuilder.TargetPosition = targetPosition; } }
/// <summary> /// Constructs a TerranBuildingConstructionJob instance. /// </summary> /// <param name="starterSCV">The SCV to attach to this job automatically when its being started.</param> /// <param name="buildingProduct">The type of building to be created by this job.</param> /// <param name="topLeftQuadTile">The coordinates of the top-left quadratic tile of the building to be created.</param> public TerranBuildingConstructionJob(SCV starterSCV, IBuildingType buildingProduct, RCIntVector topLeftQuadTile) : base(starterSCV.Owner, buildingProduct, 0) { if (starterSCV == null) { throw new ArgumentNullException("starterSCV"); } if (topLeftQuadTile == RCIntVector.Undefined) { throw new ArgumentNullException("topLeftQuadTile"); } this.buildingProduct = buildingProduct; this.topLeftQuadTile = this.ConstructField <RCIntVector>("topLeftQuadTile"); this.constructedBuilding = this.ConstructField <TerranBuilding>("constructedBuilding"); this.attachedSCV = this.ConstructField <SCV>("attachedSCV"); this.starterSCV = this.ConstructField <SCV>("starterSCV"); this.topLeftQuadTile.Write(topLeftQuadTile); this.constructedBuilding.Write(null); this.starterSCV.Write(starterSCV); }
/// <see cref="CommandInputListener.TryComplete"/> public override CommandInputListener.CompletionResultEnum TryComplete() { /// First we have to check the resources of the local player. Player localPlayer = this.scenarioManagerBC.ActiveScenario.GetPlayer((int)this.selectionManagerBC.LocalPlayer); IBuildingType selectedBuildingType = localPlayer.Metadata.GetBuildingType(this.selectedBuildingTypeName); int mineralsNeeded = selectedBuildingType.MineralCost != null?selectedBuildingType.MineralCost.Read() : 0; int vespeneGasNeeded = selectedBuildingType.GasCost != null?selectedBuildingType.GasCost.Read() : 0; int supplyNeeded = selectedBuildingType.SupplyUsed != null?selectedBuildingType.SupplyUsed.Read() : 0; if (mineralsNeeded > localPlayer.Minerals || vespeneGasNeeded > localPlayer.VespeneGas || (supplyNeeded > 0 && localPlayer.UsedSupply + supplyNeeded > localPlayer.TotalSupply)) { /// Insufficient resources or supply (TODO: send and error message up to the user!) return(CommandInputListener.CompletionResultEnum.FailedButContinue); } /// Resources are OK. this.CommandBuilder.Parameter = this.selectedBuildingTypeName; return(CommandInputListener.CompletionResultEnum.Succeeded); }
/// <summary> /// Checks the availability of the Build command for the given SCVs. /// </summary> /// <param name="scvsToHandle">The SCVs to check.</param> /// <param name="fullEntitySet">The set of selected entities.</param> /// <param name="buildingTypeName">The name of the type of the building or null if no building is specified.</param> /// <returns>The availability of the Build command for the given SCVs.</returns> private AvailabilityEnum CheckBuildAvailability(RCSet <SCV> scvsToHandle, RCSet <Entity> fullEntitySet, string buildingTypeName) { if (scvsToHandle.Count != fullEntitySet.Count || scvsToHandle.Count != 1) { return(AvailabilityEnum.Unavailable); } /// If the selected SCV is currently constructing -> unavailable. SCV scv = scvsToHandle.First(); if (scv.IsConstructing) { return(AvailabilityEnum.Unavailable); } /// If building type is not specified -> it is the parent build button availability check -> enable. if (buildingTypeName == null) { return(AvailabilityEnum.Enabled); } /// Check the requirements of the building. IBuildingType buildingType = scv.Owner.Metadata.GetBuildingType(buildingTypeName); foreach (IRequirement requirement in buildingType.Requirements) { if (!scv.Owner.HasBuilding(requirement.RequiredBuildingType.Name)) { return(AvailabilityEnum.Disabled); } if (requirement.RequiredAddonType != null && !scv.Owner.HasAddon(requirement.RequiredAddonType.Name)) { return(AvailabilityEnum.Disabled); } } return(AvailabilityEnum.Enabled); }
/// <see cref="ObjectPlacementView.GetSuggestionBoxes"/> public override List <RCIntRectangle> GetSuggestionBoxes() { this.UpdatePlacementData(); /// If there is no building to be placed or it has to be placed together with an addon -> no suggestion. if ((this.buildingToBePlaced == null && this.buildingTypeToBePlaced == null) || this.addonTypeToBePlaced != null) { return(new List <RCIntRectangle>()); } /// Otherwise collect the suggestion boxes for the building type being placed and transform the collected /// boxes to window coordinates. IBuildingType buildingType = this.buildingToBePlaced != null ? this.buildingToBePlaced.BuildingType : this.buildingTypeToBePlaced; RCSet <RCIntRectangle> quadSuggestionBoxes = this.fogOfWarBC.GetPlacementSuggestions(buildingType); List <RCIntRectangle> suggestionBoxes = new List <RCIntRectangle>(); foreach (RCIntRectangle quadSuggestionBox in quadSuggestionBoxes) { suggestionBoxes.Add(this.MapWindowBC.AttachedWindow.QuadToWindowRect(quadSuggestionBox)); } return(suggestionBoxes); }
/// <see cref="CommandInputListener.TryComplete"/> public override CommandInputListener.CompletionResultEnum TryComplete() { if (this.CommandBuilder.TargetPosition == RCNumVector.Undefined) { /// No target position selected -> completion failed! return(CompletionResultEnum.FailedAndCancel); } if (this.placeSelectedBuilding) { /// Target position selected for the selected building -> validate the selected position. int[] currentSelection = this.selectionManagerBC.CurrentSelection.ToArray(); if (currentSelection.Length != 1) { throw new InvalidOperationException("The number of the currently selected entities must be 1!"); } Building selectedBuilding = this.scenarioManagerBC.ActiveScenario.GetElement <Building>(currentSelection[0]); if (selectedBuilding == null) { throw new InvalidOperationException("The currently selected entity doesn't exist or is not a building!"); } if (this.addonTypeName == null) { /// There is no additional addon type. if (this.fogOfWarBC.CheckPlacementConstraints(selectedBuilding, (RCIntVector)this.CommandBuilder.TargetPosition, new RCSet <Entity>()).Count == 0) { /// Selected position is OK. return(CommandInputListener.CompletionResultEnum.Succeeded); } else { /// Selected position is invalid -> completion failed! this.CommandBuilder.TargetPosition = RCNumVector.Undefined; return(CommandInputListener.CompletionResultEnum.FailedButContinue); } } else { /// Additional addon type has to be checked as well. IAddonType addonType = this.scenarioManagerBC.Metadata.GetAddonType(this.addonTypeName); if (addonType == null) { throw new InvalidOperationException(string.Format("Addon type '{0}' is not defined in the metadata!", this.addonTypeName)); } if (this.fogOfWarBC.CheckPlacementConstraints(selectedBuilding, (RCIntVector)this.CommandBuilder.TargetPosition, addonType, new RCSet <Entity>()).Count == 0) { /// Selected position is OK. return(CommandInputListener.CompletionResultEnum.Succeeded); } else { /// Selected position is invalid -> completion failed! this.CommandBuilder.TargetPosition = RCNumVector.Undefined; return(CommandInputListener.CompletionResultEnum.FailedButContinue); } } } else if (this.buildingTypeName != null) { /// Target position selected for a given building type -> validate the selected position. IBuildingType buildingType = this.scenarioManagerBC.Metadata.GetBuildingType(this.buildingTypeName); if (buildingType == null) { throw new InvalidOperationException(string.Format("Building type '{0}' is not defined in the metadata!", this.buildingTypeName)); } RCSet <Entity> currentSelection = new RCSet <Entity>(); foreach (int selectedEntityID in this.selectionManagerBC.CurrentSelection) { currentSelection.Add(this.scenarioManagerBC.ActiveScenario.GetElement <Entity>(selectedEntityID)); } if (this.addonTypeName == null) { if (this.fogOfWarBC.CheckPlacementConstraints(buildingType, (RCIntVector)this.CommandBuilder.TargetPosition, currentSelection).Count == 0) { /// Selected position is OK. return(CompletionResultEnum.Succeeded); } else { /// Selected position is invalid -> completion failed! this.CommandBuilder.TargetPosition = RCNumVector.Undefined; return(CompletionResultEnum.FailedButContinue); } } else { /// Additional addon type has to be checked as well. IAddonType addonType = this.scenarioManagerBC.Metadata.GetAddonType(this.addonTypeName); if (addonType == null) { throw new InvalidOperationException(string.Format("Addon type '{0}' is not defined in the metadata!", this.addonTypeName)); } if (this.fogOfWarBC.CheckPlacementConstraints(buildingType, (RCIntVector)this.CommandBuilder.TargetPosition, addonType, currentSelection).Count == 0) { /// Selected position is OK. return(CommandInputListener.CompletionResultEnum.Succeeded); } else { /// Selected position is invalid -> completion failed! this.CommandBuilder.TargetPosition = RCNumVector.Undefined; return(CommandInputListener.CompletionResultEnum.FailedButContinue); } } } else { /// A point selected on the map -> validate the selected position. return(CommandInputListener.CompletionResultEnum.Succeeded); } }
/// <summary> /// Updates the placement data based on the current state of the game engine. /// </summary> private void UpdatePlacementData() { Building newBuildingToBePlaced = null; IBuildingType newBuildingTypeToBePlaced = null; IAddonType newAddonTypeToBePlaced = null; if (this.commandManagerBC.IsWaitingForTargetPosition) { if (this.commandManagerBC.PlaceSelectedBuilding) { newBuildingToBePlaced = this.GetSelectedBuilding(); } else if (this.commandManagerBC.BuildingType != null) { this.RefreshCurrentSelection(); newBuildingTypeToBePlaced = this.scenarioManagerBC.Metadata.GetBuildingType(this.commandManagerBC.BuildingType); if (newBuildingTypeToBePlaced == null) { throw new InvalidOperationException(string.Format("Building type '{0}' is not defined in the metadata!", this.commandManagerBC.BuildingType)); } } if (this.commandManagerBC.AddonType != null) { newAddonTypeToBePlaced = this.scenarioManagerBC.Metadata.GetAddonType(this.commandManagerBC.AddonType); if (newAddonTypeToBePlaced == null) { throw new InvalidOperationException(string.Format("Addon type '{0}' is not defined in the metadata!", this.commandManagerBC.AddonType)); } } } /// Check if new preview animations have to be created. bool createPreviewAnimations = false; if (newBuildingToBePlaced != this.buildingToBePlaced || newBuildingTypeToBePlaced != this.buildingTypeToBePlaced || newAddonTypeToBePlaced != this.addonTypeToBePlaced) { this.buildingToBePlaced = newBuildingToBePlaced; this.buildingTypeToBePlaced = newBuildingTypeToBePlaced; this.addonTypeToBePlaced = newAddonTypeToBePlaced; createPreviewAnimations = true; } /// Create the building and addon preview animations if necessary. if (createPreviewAnimations) { this.buildingPreviewAnimation = null; this.addonPreviewAnimation = null; if (this.buildingToBePlaced != null && this.buildingToBePlaced.ElementType.AnimationPalette != null) { Animation previewAnimDef = this.buildingToBePlaced.ElementType.AnimationPalette.PreviewAnimation; if (previewAnimDef != null) { this.buildingPreviewAnimation = new AnimationPlayer(previewAnimDef, new ConstValue <MapDirection>(MapDirection.NorthEast)); } } else if (this.buildingTypeToBePlaced != null && this.buildingTypeToBePlaced.AnimationPalette != null) { Animation previewAnimDef = this.buildingTypeToBePlaced.AnimationPalette.PreviewAnimation; if (previewAnimDef != null) { this.buildingPreviewAnimation = new AnimationPlayer(previewAnimDef, new ConstValue <MapDirection>(MapDirection.NorthEast)); } } if (this.addonTypeToBePlaced != null && this.addonTypeToBePlaced.AnimationPalette != null) { Animation previewAnimDef = this.addonTypeToBePlaced.AnimationPalette.PreviewAnimation; if (previewAnimDef != null) { this.addonPreviewAnimation = new AnimationPlayer(previewAnimDef, new ConstValue <MapDirection>(MapDirection.NorthEast)); } } } }
/// <see cref="ObjectPlacementView.GetObjectRelativeQuadRectangles"/> protected override RCSet <Tuple <RCIntRectangle, SpriteRenderInfo[]> > GetObjectRelativeQuadRectangles() { this.UpdatePlacementData(); RCSet <Tuple <RCIntRectangle, SpriteRenderInfo[]> > retList = new RCSet <Tuple <RCIntRectangle, SpriteRenderInfo[]> >(); IBuildingType buildingType = this.buildingToBePlaced != null ? this.buildingToBePlaced.BuildingType : this.buildingTypeToBePlaced; if (buildingType == null) { return(retList); } /// Calculate the building rectangle and get sprites from the building preview animation if exists. RCIntVector buildingQuadSize = this.Scenario.Map.CellToQuadSize(buildingType.Area.Read().Size); RCIntRectangle buildingRelativeRect = new RCIntRectangle((-1) * buildingQuadSize / 2, buildingQuadSize); SpriteRenderInfo[] buildingSprites = new SpriteRenderInfo[0]; if (this.buildingPreviewAnimation != null) { buildingSprites = new SpriteRenderInfo[this.buildingPreviewAnimation.CurrentFrame.Length]; for (int i = 0; i < this.buildingPreviewAnimation.CurrentFrame.Length; i++) { buildingSprites[i] = new SpriteRenderInfo() { SpriteGroup = SpriteGroupEnum.MapObjectSpriteGroup, Index = buildingType.SpritePalette.Index, DisplayCoords = buildingType.SpritePalette.GetOffset(this.buildingPreviewAnimation.CurrentFrame[i]), Section = buildingType.SpritePalette.GetSection(this.buildingPreviewAnimation.CurrentFrame[i]) }; } } retList.Add(Tuple.Create(buildingRelativeRect, buildingSprites)); if (this.addonTypeToBePlaced != null) { /// Calculate the addon rectangle and get sprites from the addon preview animation if exists. RCIntVector addonQuadSize = this.Scenario.Map.CellToQuadSize(this.addonTypeToBePlaced.Area.Read().Size); RCIntRectangle addonRelativeRect = new RCIntRectangle( buildingRelativeRect.Location + buildingType.GetRelativeAddonPosition(this.Scenario.Map, this.addonTypeToBePlaced), addonQuadSize); SpriteRenderInfo[] addonSprites = new SpriteRenderInfo[0]; if (this.addonPreviewAnimation != null) { addonSprites = new SpriteRenderInfo[this.addonPreviewAnimation.CurrentFrame.Length]; for (int i = 0; i < this.addonPreviewAnimation.CurrentFrame.Length; i++) { addonSprites[i] = new SpriteRenderInfo() { SpriteGroup = SpriteGroupEnum.MapObjectSpriteGroup, Index = this.addonTypeToBePlaced.SpritePalette.Index, DisplayCoords = this.addonTypeToBePlaced.SpritePalette.GetOffset(this.addonPreviewAnimation.CurrentFrame[i]), Section = this.addonTypeToBePlaced.SpritePalette.GetSection(this.addonPreviewAnimation.CurrentFrame[i]) }; } } retList.Add(Tuple.Create(addonRelativeRect, addonSprites)); } return(retList); }