/// <see cref="IMapEditorService.PlaceVespeneGeyser"/> public bool PlaceVespeneGeyser(RCIntVector position) { if (this.scenarioManager.ActiveScenario == null) { throw new InvalidOperationException("No active scenario!"); } if (position == RCIntVector.Undefined) { throw new ArgumentNullException("position"); } RCIntVector navCellCoords = this.mapWindowBC.AttachedWindow.WindowToMapCoords(position).Round(); IQuadTile quadTileAtPos = this.scenarioManager.ActiveScenario.Map.GetCell(navCellCoords).ParentQuadTile; IScenarioElementType objectType = this.scenarioManager.Metadata.GetElementType(VespeneGeyser.VESPENEGEYSER_TYPE_NAME); RCIntVector objQuadSize = this.scenarioManager.ActiveScenario.Map.CellToQuadSize(objectType.Area.Read().Size); RCIntVector topLeftQuadCoords = quadTileAtPos.MapCoords - objQuadSize / 2; if (objectType.CheckPlacementConstraints(this.scenarioManager.ActiveScenario, topLeftQuadCoords, new RCSet <Entity>()).Count != 0) { return(false); } VespeneGeyser placedVespeneGeyser = new VespeneGeyser(); this.scenarioManager.ActiveScenario.AddElementToScenario(placedVespeneGeyser); placedVespeneGeyser.AttachToMap(this.scenarioManager.ActiveScenario.Map.GetQuadTile(topLeftQuadCoords)); return(true); }
/// <summary> /// Attaches this entity to the given quadratic tile on the map. /// </summary> /// <param name="topLeftTile">The quadratic tile at the top-left corner of this entity.</param> /// <param name="elementsToIgnore">An optional list of scenario elements to ignore during attach.</param> /// <returns>True if this entity was successfully attached to the map; otherwise false.</returns> /// <remarks>Note that the caller has to explicitly call MotionControl.Fix to fix this entity after calling this method.</remarks> public bool AttachToMap(IQuadTile topLeftTile, params ScenarioElement[] elementsToIgnore) { ICell topLeftCell = topLeftTile.GetCell(new RCIntVector(0, 0)); RCNumVector position = topLeftCell.MapCoords - new RCNumVector(1, 1) / 2 - this.ElementType.Area.Read().Location; return(this.AttachToMap(position, elementsToIgnore)); }
/// <see cref="ITerrainObjectConstraint.Check"/> public RCSet <RCIntVector> Check(IMapAccess map, RCIntVector position) { if (map == null) { throw new ArgumentNullException("map"); } if (position == RCIntVector.Undefined) { throw new ArgumentNullException("position"); } RCSet <RCIntVector> retList = new RCSet <RCIntVector>(); RCIntVector absQuadCoords = position + this.quadCoords; if (absQuadCoords.X >= 0 && absQuadCoords.X < map.Size.X && absQuadCoords.Y >= 0 && absQuadCoords.Y < map.Size.Y) { IQuadTile checkedQuadTile = map.GetQuadTile(absQuadCoords); IIsoTile checkedIsoTile = checkedQuadTile.PrimaryIsoTile; if (checkedIsoTile.Type.TerrainA != this.terrainA || checkedIsoTile.Type.TerrainB != this.terrainB || !this.allowedCombinations.Contains(checkedIsoTile.Type.Combination)) { retList.Add(this.quadCoords); foreach (IQuadTile neighbour in checkedQuadTile.Neighbours) { if (neighbour.PrimaryIsoTile == checkedIsoTile) { retList.Add(neighbour.MapCoords - position); } } } } return(retList); }
/// <see cref="IScenarioLoader.LoadScenario"/> public Scenario LoadScenario(IMapAccess map, byte[] data) { if (map == null) { throw new ArgumentNullException("map"); } if (data == null) { throw new ArgumentNullException("data"); } /// Load the packages from the byte array. int offset = 0; Scenario scenario = new Scenario(map); while (offset < data.Length) { int parsedBytes; RCPackage package = RCPackage.Parse(data, offset, data.Length - offset, out parsedBytes); if (package == null || !package.IsCommitted) { throw new SimulatorException("Syntax error!"); } offset += parsedBytes; if (package.PackageFormat.ID == ScenarioFileFormat.MINERAL_FIELD) { IQuadTile quadTile = map.GetQuadTile(new RCIntVector(package.ReadShort(0), package.ReadShort(1))); MineralField mineralField = new MineralField(); mineralField.ResourceAmount.Write(package.ReadInt(2)); scenario.AddElementToScenario(mineralField); mineralField.AttachToMap(quadTile); } else if (package.PackageFormat.ID == ScenarioFileFormat.VESPENE_GEYSER) { IQuadTile quadTile = map.GetQuadTile(new RCIntVector(package.ReadShort(0), package.ReadShort(1))); VespeneGeyser vespeneGeyser = new VespeneGeyser(); vespeneGeyser.ResourceAmount.Write(package.ReadInt(2)); scenario.AddElementToScenario(vespeneGeyser); vespeneGeyser.AttachToMap(quadTile); } else if (package.PackageFormat.ID == ScenarioFileFormat.START_LOCATION) { IQuadTile quadTile = map.GetQuadTile(new RCIntVector(package.ReadShort(0), package.ReadShort(1))); StartLocation startLocation = new StartLocation(package.ReadByte(2)); scenario.AddElementToScenario(startLocation); startLocation.AttachToMap(quadTile); } } /// Check the constraints of the visible entities. foreach (Entity entity in scenario.GetElementsOnMap <Entity>(MapObjectLayerEnum.GroundObjects, MapObjectLayerEnum.AirObjects)) { if (entity.CheckPlacementConstraints(entity.MapObject.QuadraticPosition.Location, new RCSet <Entity>()).Count != 0) { throw new MapException(string.Format("Entity at {0} is voilating its placement constraints!", entity.MapObject.QuadraticPosition.Location)); } } return(scenario); }
/// <summary> /// Constructs a terrain object. /// </summary> /// <param name="map">The map that this terrain object belongs to.</param> /// <param name="type">The type of this terrain object.</param> /// <param name="mapCoords">The coordinates of the top-left quadratic tile of this terrain object.</param> public TerrainObject(IMapAccess map, ITerrainObjectType type, RCIntVector mapCoords) { if (map == null) { throw new ArgumentNullException("map"); } if (type == null) { throw new ArgumentNullException("type"); } if (mapCoords == RCIntVector.Undefined) { throw new ArgumentNullException("type"); } if (type.Tileset != map.Tileset) { throw new MapException("Tileset of the TerrainObjectType and tileset of the map are not the same!"); } this.mapCoords = mapCoords; this.type = type; this.parentMap = map; this.cells = new Cell[this.type.QuadraticSize.X * MapStructure.NAVCELL_PER_QUAD, this.type.QuadraticSize.Y * MapStructure.NAVCELL_PER_QUAD]; this.quadTiles = new QuadTile[this.type.QuadraticSize.X, this.type.QuadraticSize.Y]; /// Set the references to the appropriate quadratic tiles and cells. for (int quadX = 0; quadX < this.type.QuadraticSize.X; quadX++) { for (int quadY = 0; quadY < this.type.QuadraticSize.Y; quadY++) { RCIntVector relQuadCoords = new RCIntVector(quadX, quadY); if (!this.type.IsExcluded(relQuadCoords)) { IQuadTile currQuadTile = this.parentMap.GetQuadTile(this.mapCoords + relQuadCoords); this.quadTiles[quadX, quadY] = currQuadTile; for (int navX = 0; navX < MapStructure.NAVCELL_PER_QUAD; navX++) { for (int navY = 0; navY < MapStructure.NAVCELL_PER_QUAD; navY++) { RCIntVector relNavCoords = relQuadCoords * MapStructure.NAVCELL_PER_QUAD + new RCIntVector(navX, navY); this.cells[relNavCoords.X, relNavCoords.Y] = currQuadTile.GetCell(new RCIntVector(navX, navY)); } } } } } /// TODO: Apply the cell data changesets! /// TODO: Attach this TerrainObject to the map! }
/// <summary> /// Implements visibility calculations when there is no running FogOfWars. /// </summary> /// <returns>The results of the visibility calculations.</returns> private FowVisibilityInfo CalculateVisibilityWithoutFow() { /// Collect the isometric & quadratic tiles that need to be updated. IMapAccess map = this.ActiveScenario.Map; RCSet <IIsoTile> isoTilesToUpdate = new RCSet <IIsoTile>(); RCSet <ITerrainObject> terrainObjectsToUpdate = new RCSet <ITerrainObject>(); for (int column = this.quadTileWindow.Left; column < this.quadTileWindow.Right; column++) { for (int row = this.quadTileWindow.Top; row < this.quadTileWindow.Bottom; row++) { /// Add the primary & secondary isometric tiles into the update lists. IQuadTile quadTileToUpdate = map.GetQuadTile(new RCIntVector(column, row)); if (quadTileToUpdate.PrimaryIsoTile != null) { isoTilesToUpdate.Add(quadTileToUpdate.PrimaryIsoTile); } if (quadTileToUpdate.SecondaryIsoTile != null) { isoTilesToUpdate.Add(quadTileToUpdate.SecondaryIsoTile); } if (quadTileToUpdate.TerrainObject != null) { terrainObjectsToUpdate.Add(quadTileToUpdate.TerrainObject); } } } /// Collect the currently visible map objects on the ground. RCSet <MapObject> groundMapObjectsToUpdate = this.ActiveScenario.GetMapObjects( this.mapWindowBC.AttachedWindow.WindowMapCoords, MapObjectLayerEnum.GroundObjects, MapObjectLayerEnum.GroundMissiles); /// Collect the currently visible map objects in the air. RCSet <MapObject> airMapObjectsToUpdate = this.ActiveScenario.GetMapObjects( this.mapWindowBC.AttachedWindow.WindowMapCoords, MapObjectLayerEnum.AirObjects, MapObjectLayerEnum.AirMissiles); /// Create the calculated visibility info. return(new FowVisibilityInfo { IsoTilesToUpdate = isoTilesToUpdate, TerrainObjectsToUpdate = terrainObjectsToUpdate, QuadTilesToUpdate = new List <IQuadTile>(), EntitySnapshotsToUpdate = new List <EntitySnapshot>(), GroundMapObjectsToUpdate = groundMapObjectsToUpdate, AirMapObjectsToUpdate = airMapObjectsToUpdate }); }
/// <see cref="IMapEditorService.PlaceStartLocation"/> public bool PlaceStartLocation(RCIntVector position, int playerIndex) { if (this.scenarioManager.ActiveScenario == null) { throw new InvalidOperationException("No active scenario!"); } if (position == RCIntVector.Undefined) { throw new ArgumentNullException("position"); } RCIntVector navCellCoords = this.mapWindowBC.AttachedWindow.WindowToMapCoords(position).Round(); IQuadTile quadTileAtPos = this.scenarioManager.ActiveScenario.Map.GetCell(navCellCoords).ParentQuadTile; IScenarioElementType objectType = this.scenarioManager.Metadata.GetElementType(StartLocation.STARTLOCATION_TYPE_NAME); RCIntVector objQuadSize = this.scenarioManager.ActiveScenario.Map.CellToQuadSize(objectType.Area.Read().Size); RCIntVector topLeftQuadCoords = quadTileAtPos.MapCoords - objQuadSize / 2; if (objectType.CheckPlacementConstraints(this.scenarioManager.ActiveScenario, topLeftQuadCoords, new RCSet <Entity>()).Count != 0) { return(false); } /// Check if a start location with the given player index already exists. RCSet <StartLocation> startLocations = this.scenarioManager.ActiveScenario.GetAllElements <StartLocation>(); StartLocation startLocation = null; foreach (StartLocation sl in startLocations) { if (sl.PlayerIndex == playerIndex) { startLocation = sl; break; } } /// If a start location with the given player index already exists, change its quadratic coordinates, /// otherwise create a new start location. if (startLocation != null) { startLocation.DetachFromMap(); } else { startLocation = new StartLocation(playerIndex); this.scenarioManager.ActiveScenario.AddElementToScenario(startLocation); } startLocation.AttachToMap(this.scenarioManager.ActiveScenario.Map.GetQuadTile(topLeftQuadCoords)); return(true); }
/// <see cref="Weapon.OnImpact"/> protected override void OnImpact(Missile impactedMissile) { IQuadTile launchQuadTile = impactedMissile.Scenario.Map.GetCell(impactedMissile.LaunchPosition.Round()).ParentQuadTile; IQuadTile impactQuadTile = impactedMissile.Scenario.Map.GetCell(impactedMissile.TargetEntity.MotionControl.PositionVector.Read().Round()).ParentQuadTile; /// TODO: Don't use the default random generator here because scenario update needs to be deterministic! bool makeDamage = impactedMissile.LaunchedFromAir || impactedMissile.TargetEntity.MotionControl.IsFlying || impactQuadTile.GroundLevel <= launchQuadTile.GroundLevel || RandomService.DefaultGenerator.Next(100) < LOW_TO_HIGH_GROUNDLEVEL_DAMAGE_PROBABILITY; if (makeDamage) { impactedMissile.TargetEntity.Biometrics.Damage(this.weaponData.DamageType.Read(), this.weaponData.Damage.Read(), impactedMissile.Owner == impactedMissile.TargetEntity.Owner); } }
/// <see cref="IMapEditor.PlaceTerrainObject"/> public ITerrainObject PlaceTerrainObject(IMapAccess targetMap, IQuadTile targetTile, ITerrainObjectType type) { if (targetMap == null) { throw new ArgumentNullException("targetMap"); } if (targetTile == null) { throw new ArgumentNullException("targetTile"); } if (type == null) { throw new ArgumentNullException("type"); } if (targetMap.Tileset != type.Tileset) { throw new InvalidOperationException("The tileset of the terrain object type must be the same as the tileset of the map!"); } /// TODO: Avoid this downcast! MapAccess targetMapObj = targetMap as MapAccess; if (targetMapObj == null) { throw new ArgumentException("The given map cannot be handled by the MapEditor!", "targetMap"); } if (type.CheckConstraints(targetMap, targetTile.MapCoords).Count != 0) { return(null); } if (type.CheckTerrainObjectIntersections(targetMap, targetTile.MapCoords).Count != 0) { return(null); } /// TODO: Might be better to create the TerrainObject with a factory? ITerrainObject newObj = new TerrainObject(targetMap, type, targetTile.MapCoords); foreach (ICellDataChangeSet changeset in newObj.Type.CellDataChangesets) { changeset.Apply(newObj); } targetMapObj.AttachTerrainObject(newObj); return(newObj); }
/// <see cref="IMapEditorService.PlaceTerrainObject"/> public bool PlaceTerrainObject(RCIntVector position, string terrainObject) { if (this.scenarioManager.ActiveScenario == null) { throw new InvalidOperationException("No active scenario!"); } if (position == RCIntVector.Undefined) { throw new ArgumentNullException("position"); } if (terrainObject == null) { throw new ArgumentNullException("terrainObject"); } ITerrainObjectType terrainObjType = this.scenarioManager.ActiveScenario.Map.Tileset.GetTerrainObjectType(terrainObject); RCIntVector navCellCoords = this.mapWindowBC.AttachedWindow.WindowToMapCoords(position).Round(); IQuadTile quadTileAtPos = this.scenarioManager.ActiveScenario.Map.GetCell(navCellCoords).ParentQuadTile; RCIntVector topLeftQuadCoords = quadTileAtPos.MapCoords - terrainObjType.QuadraticSize / 2; ITerrainObject placedTerrainObject = null; if (topLeftQuadCoords.X >= 0 && topLeftQuadCoords.Y >= 0 && topLeftQuadCoords.X < this.scenarioManager.ActiveScenario.Map.Size.X && topLeftQuadCoords.Y < this.scenarioManager.ActiveScenario.Map.Size.Y) { IQuadTile targetQuadTile = this.scenarioManager.ActiveScenario.Map.GetQuadTile(topLeftQuadCoords); placedTerrainObject = this.mapEditor.PlaceTerrainObject(this.scenarioManager.ActiveScenario.Map, targetQuadTile, terrainObjType); } if (placedTerrainObject != null) { RCNumRectangle terrObjRect = new RCNumRectangle(this.scenarioManager.ActiveScenario.Map.GetQuadTile(placedTerrainObject.MapCoords).GetCell(new RCIntVector(0, 0)).MapCoords, placedTerrainObject.CellSize) - new RCNumVector(1, 1) / 2; foreach (Entity affectedEntity in this.scenarioManager.ActiveScenario.GetElementsOnMap <Entity>(terrObjRect, MapObjectLayerEnum.AirObjects, MapObjectLayerEnum.GroundObjects)) { if (affectedEntity.CheckPlacementConstraints(affectedEntity.MapObject.QuadraticPosition.Location, new RCSet <Entity>()).Count != 0) { affectedEntity.DetachFromMap(); this.scenarioManager.ActiveScenario.RemoveElementFromScenario(affectedEntity); affectedEntity.Dispose(); } } } return(placedTerrainObject != null); }
/// <see cref="PostponedCmdExecution.ContinueImpl_i"/> protected override void InitializeImpl_i() { IQuadTile topLeftTile = this.Scenario.Map.GetQuadTile(this.topLeftQuadTile.Read()); ICell topLeftCell = topLeftTile.GetCell(new RCIntVector(0, 0)); RCNumVector landPosition = topLeftCell.MapCoords - new RCNumVector(1, 1) / 2 - this.recipientEntity.Read().ElementType.Area.Read().Location; if (landPosition.Y - Constants.MAX_VTOL_TRANSITION >= 0) { this.targetPosition.Write(landPosition - new RCNumVector(0, Constants.MAX_VTOL_TRANSITION)); this.landOnTheSpot.Write(0x00); } else { this.targetPosition.Write(landPosition); this.landOnTheSpot.Write(0x01); } this.recipientEntity.Read().MotionControl.StartMoving(this.targetPosition.Read()); }
/// <summary> /// Collects the terrain objects to render into the given list. /// </summary> /// <param name="targetList">The target list.</param> private void CollectTerrainObjectSprites(ref List <SpriteRenderInfo> targetList) { /// Collect the terrain objects that need to be rendered. RCSet <ITerrainObject> terrainObjectsToRender = new RCSet <ITerrainObject>(); for (int column = this.MapWindowBC.FullWindow.QuadTileWindow.Left; column < this.MapWindowBC.FullWindow.QuadTileWindow.Right; column++) { for (int row = this.MapWindowBC.FullWindow.QuadTileWindow.Top; row < this.MapWindowBC.FullWindow.QuadTileWindow.Bottom; row++) { /// Add the primary & secondary isometric tiles & the terrain objects into the render lists. IQuadTile quadTileToUpdate = this.Map.GetQuadTile(new RCIntVector(column, row)); if (quadTileToUpdate.TerrainObject != null && terrainObjectsToRender.Add(quadTileToUpdate.TerrainObject)) { targetList.Add(this.ConvertTerrainObjectToSpriteInst(quadTileToUpdate.TerrainObject)); } } } }
/// <summary> /// Detaches the given terrain object from the map structure. /// </summary> /// <param name="terrainObj">The terrain object to be detached.</param> /// <exception cref="InvalidOperationException">If the given terrain object was not attached to this map.</exception> public void DetachTerrainObject(ITerrainObject terrainObj) { if (!this.terrainObjects.Remove(terrainObj)) { throw new InvalidOperationException("The given terrain object was not attached to this map!"); } for (int x = 0; x < terrainObj.Type.QuadraticSize.X; x++) { for (int y = 0; y < terrainObj.Type.QuadraticSize.Y; y++) { IQuadTile quadTile = terrainObj.GetQuadTile(new RCIntVector(x, y)); if (quadTile != null) { QuadTile quadTileObj = this.mapStructure.GetQuadTile(quadTile.MapCoords); quadTileObj.DetachTerrainObject(); } } } }
/// <summary> /// Adds the given entity snapshot and all of its cutting quadratic tiles into the update lists. /// </summary> /// <param name="snapshot">The entity snapshot to add.</param> /// <param name="snapshotUpdateList">The snapshot update list.</param> /// <param name="quadTileUpdateList">The quadratic update list.</param> private void AddEntitySnapshotToUpdate(EntitySnapshot snapshot, RCSet <EntitySnapshot> snapshotUpdateList, RCSet <IQuadTile> quadTileUpdateList) { if (snapshot != null && snapshotUpdateList.Add(snapshot)) { for (int col = snapshot.QuadraticPosition.Left; col < snapshot.QuadraticPosition.Right; col++) { for (int row = snapshot.QuadraticPosition.Top; row < snapshot.QuadraticPosition.Bottom; row++) { IQuadTile quadTileToUpdate = this.ActiveScenario.Map.GetQuadTile(new RCIntVector(col, row)); if (quadTileToUpdate != null && (this.fowCacheMatrix.GetFullFowFlagsAtQuadTile(quadTileToUpdate.MapCoords) != FOWTileFlagsEnum.None || this.fowCacheMatrix.GetPartialFowFlagsAtQuadTile(quadTileToUpdate.MapCoords) != FOWTileFlagsEnum.None)) { quadTileUpdateList.Add(quadTileToUpdate); } } } } }
/// <summary> /// Adds the given terrain object and all of its cutting quadratic tiles into the update lists. /// </summary> /// <param name="terrainObj">The terrain object to add.</param> /// <param name="terrainObjUpdateList">The terrain object update list.</param> /// <param name="quadTileUpdateList">The quadratic update list.</param> private void AddTerrainObjectToUpdate(ITerrainObject terrainObj, RCSet <ITerrainObject> terrainObjUpdateList, RCSet <IQuadTile> quadTileUpdateList) { if (terrainObj != null && terrainObjUpdateList.Add(terrainObj)) { for (int col = 0; col < terrainObj.Type.QuadraticSize.X; col++) { for (int row = 0; row < terrainObj.Type.QuadraticSize.Y; row++) { IQuadTile quadTileToUpdate = terrainObj.GetQuadTile(new RCIntVector(col, row)); if (quadTileToUpdate != null && (this.fowCacheMatrix.GetFullFowFlagsAtQuadTile(quadTileToUpdate.MapCoords) != FOWTileFlagsEnum.None || this.fowCacheMatrix.GetPartialFowFlagsAtQuadTile(quadTileToUpdate.MapCoords) != FOWTileFlagsEnum.None)) { quadTileUpdateList.Add(quadTileToUpdate); } } } } }
/// <summary> /// Converts a rectangle of cells to a rectangle of quadratic tiles. /// </summary> /// <param name="cellRect">The cell rectangle to convert.</param> /// <returns>The quadratic rectangle.</returns> public RCIntRectangle CellToQuadRect(RCIntRectangle cellRect) { if (cellRect == RCIntRectangle.Undefined) { throw new ArgumentNullException("cellRect"); } RCIntVector topLeftNavCellCoords = new RCIntVector(Math.Min(this.CellSize.X - 1, Math.Max(0, cellRect.Left)), Math.Min(this.CellSize.Y - 1, Math.Max(0, cellRect.Top))); RCIntVector bottomRightNavCellCoords = new RCIntVector(Math.Min(this.CellSize.X - 1, Math.Max(0, cellRect.Right - 1)), Math.Min(this.CellSize.Y - 1, Math.Max(0, cellRect.Bottom - 1))); IQuadTile topLeftQuadTile = this.GetCell(topLeftNavCellCoords).ParentQuadTile; IQuadTile bottomRightQuadTile = this.GetCell(bottomRightNavCellCoords).ParentQuadTile; RCIntRectangle quadTileWindow = new RCIntRectangle( topLeftQuadTile.MapCoords.X, topLeftQuadTile.MapCoords.Y, bottomRightQuadTile.MapCoords.X - topLeftQuadTile.MapCoords.X + 1, bottomRightQuadTile.MapCoords.Y - topLeftQuadTile.MapCoords.Y + 1); return(quadTileWindow); }
/// <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> /// Calculates the quadratic coordinates currently visible by the owner entity. /// </summary> /// <returns>The quadratic coordinates currently visible by the owner entity.</returns> private RCSet <RCIntVector> CalculateVisibleQuadCoords() { IQuadTile currentQuadTile = this.owner.Read().Scenario.Map.GetCell(this.owner.Read().MotionControl.PositionVector.Read().Round()).ParentQuadTile; RCSet <RCIntVector> retList = new RCSet <RCIntVector>(); foreach (RCIntVector relativeQuadCoord in this.owner.Read().ElementType.RelativeQuadCoordsInSight) { RCIntVector otherQuadCoords = currentQuadTile.MapCoords + relativeQuadCoord; if (otherQuadCoords.X >= 0 && otherQuadCoords.X < this.owner.Read().Scenario.Map.Size.X&& otherQuadCoords.Y >= 0 && otherQuadCoords.Y < this.owner.Read().Scenario.Map.Size.Y) { IQuadTile otherQuadTile = this.owner.Read().Scenario.Map.GetQuadTile(otherQuadCoords); if (this.owner.Read().MotionControl.IsFlying || currentQuadTile.GroundLevel >= otherQuadTile.GroundLevel) { retList.Add(otherQuadTile.MapCoords); } } } return(retList); }
/// <summary> /// Collects the isometric tiles to render into the given list. /// </summary> /// <param name="targetList">The target list.</param> private void CollectIsoTileSprites(ref List <SpriteRenderInfo> targetList) { /// Collect the isometric tiles that need to be rendered. RCSet <IIsoTile> isoTilesToRender = new RCSet <IIsoTile>(); for (int column = this.MapWindowBC.FullWindow.QuadTileWindow.Left; column < this.MapWindowBC.FullWindow.QuadTileWindow.Right; column++) { for (int row = this.MapWindowBC.FullWindow.QuadTileWindow.Top; row < this.MapWindowBC.FullWindow.QuadTileWindow.Bottom; row++) { /// Add the primary & secondary isometric tiles into the render list. IQuadTile quadTileToUpdate = this.Map.GetQuadTile(new RCIntVector(column, row)); if (quadTileToUpdate.PrimaryIsoTile != null && isoTilesToRender.Add(quadTileToUpdate.PrimaryIsoTile)) { targetList.Add(this.ConvertIsoTileToSpriteInst(quadTileToUpdate.PrimaryIsoTile)); } if (quadTileToUpdate.SecondaryIsoTile != null && isoTilesToRender.Add(quadTileToUpdate.SecondaryIsoTile)) { targetList.Add(this.ConvertIsoTileToSpriteInst(quadTileToUpdate.SecondaryIsoTile)); } } } }
/// <see cref="EntityPlacementConstraint.CheckImpl"/> protected override RCSet <RCIntVector> CheckImpl(Scenario scenario, RCIntVector position, RCSet <Entity> entitiesToIgnore) { RCIntRectangle objArea = new RCIntRectangle(position, scenario.Map.CellToQuadSize(this.EntityType.Area.Read().Size)); RCSet <RCIntVector> retList = new RCSet <RCIntVector>(); for (int absY = objArea.Top; absY < objArea.Bottom; absY++) { for (int absX = objArea.Left; absX < objArea.Right; absX++) { RCIntVector absQuadCoords = new RCIntVector(absX, absY); if (absQuadCoords.X >= 0 && absQuadCoords.X < scenario.Map.Size.X && absQuadCoords.Y >= 0 && absQuadCoords.Y < scenario.Map.Size.Y) { IQuadTile checkedQuadTile = scenario.Map.GetQuadTile(absQuadCoords); if (!checkedQuadTile.IsBuildable) { retList.Add(absQuadCoords - position); } } } } return(retList); }
/// <summary> /// Adds the given map object and all of its cutting quadratic tiles into the update lists. /// </summary> /// <param name="mapObj">The map object to add.</param> /// <param name="mapObjectUpdateList">The map object update list.</param> /// <param name="quadTileUpdateList">The quadratic update list.</param> private void AddMapObjectToUpdate(MapObject mapObj, RCSet <MapObject> mapObjectUpdateList, RCSet <IQuadTile> quadTileUpdateList) { if (mapObj != null && mapObjectUpdateList.Add(mapObj)) { for (int col = mapObj.QuadraticPosition.Left; col < mapObj.QuadraticPosition.Right; col++) { for (int row = mapObj.QuadraticPosition.Top; row < mapObj.QuadraticPosition.Bottom; row++) { IQuadTile quadTileToUpdate = this.ActiveScenario.Map.GetQuadTile(new RCIntVector(col, row)); if (quadTileToUpdate != null && (this.fowCacheMatrix.GetFullFowFlagsAtQuadTile(quadTileToUpdate.MapCoords) != FOWTileFlagsEnum.None || this.fowCacheMatrix.GetPartialFowFlagsAtQuadTile(quadTileToUpdate.MapCoords) != FOWTileFlagsEnum.None)) { quadTileUpdateList.Add(quadTileToUpdate); } } } if (mapObj.QuadraticShadowPosition != RCIntRectangle.Undefined) { for (int col = mapObj.QuadraticShadowPosition.Left; col < mapObj.QuadraticShadowPosition.Right; col++) { for (int row = mapObj.QuadraticShadowPosition.Top; row < mapObj.QuadraticShadowPosition.Bottom; row++) { IQuadTile quadTileToUpdate = this.ActiveScenario.Map.GetQuadTile(new RCIntVector(col, row)); if (quadTileToUpdate != null && (this.fowCacheMatrix.GetFullFowFlagsAtQuadTile(quadTileToUpdate.MapCoords) != FOWTileFlagsEnum.None || this.fowCacheMatrix.GetPartialFowFlagsAtQuadTile(quadTileToUpdate.MapCoords) != FOWTileFlagsEnum.None)) { quadTileUpdateList.Add(quadTileToUpdate); } } } } } }
/// <see cref="IObjectPlacementView.GetObjectPlacementBox"/> public ObjectPlacementBox GetObjectPlacementBox(RCIntVector position) { /// Calculate the top-left quadratic coordinates based on the retrieved object rectangles relative to the quadratic tile at the incoming position. RCSet <Tuple <RCIntRectangle, SpriteRenderInfo[]> > objRectsRelativeToQuadTileAtPos = this.GetObjectRelativeQuadRectangles(); if (objRectsRelativeToQuadTileAtPos.Count == 0) { return(new ObjectPlacementBox { Sprites = new List <SpriteRenderInfo>(), IllegalParts = new List <RCIntRectangle>(), LegalParts = new List <RCIntRectangle>() }); } RCIntVector navCellCoords = this.MapWindowBC.AttachedWindow.WindowToMapCoords(position).Round(); IQuadTile quadTileAtPos = this.Map.GetCell(navCellCoords).ParentQuadTile; RCIntVector topLeftQuadCoords = quadTileAtPos.MapCoords; foreach (Tuple <RCIntRectangle, SpriteRenderInfo[]> relativeRect in objRectsRelativeToQuadTileAtPos) { RCIntVector rectTopLeftQuadCoords = topLeftQuadCoords + relativeRect.Item1.Location; if (rectTopLeftQuadCoords.X < topLeftQuadCoords.X && rectTopLeftQuadCoords.Y < topLeftQuadCoords.Y || rectTopLeftQuadCoords.X < topLeftQuadCoords.X && rectTopLeftQuadCoords.Y == topLeftQuadCoords.Y || rectTopLeftQuadCoords.X == topLeftQuadCoords.X && rectTopLeftQuadCoords.Y < topLeftQuadCoords.Y) { topLeftQuadCoords = rectTopLeftQuadCoords; } } /// Calculate the object rectangles relative to the calculated top-left quadratic coordinates. RCSet <Tuple <RCIntRectangle, SpriteRenderInfo[]> > objRectsRelativeToTopLeftQuadTile = new RCSet <Tuple <RCIntRectangle, SpriteRenderInfo[]> >(); foreach (Tuple <RCIntRectangle, SpriteRenderInfo[]> relativeRect in objRectsRelativeToQuadTileAtPos) { objRectsRelativeToTopLeftQuadTile.Add(Tuple.Create( new RCIntRectangle( relativeRect.Item1.Location + quadTileAtPos.MapCoords - topLeftQuadCoords, relativeRect.Item1.Size), relativeRect.Item2)); } /// Get the sprites to be displayed, translate their DisplayCoordinates accordingly from the top-left quadratic tile, /// and collect the violating quadratic coordinates. ObjectPlacementBox placementBox = new ObjectPlacementBox { Sprites = new List <SpriteRenderInfo>(), IllegalParts = new List <RCIntRectangle>(), LegalParts = new List <RCIntRectangle>() }; RCSet <RCIntVector> violatingQuadCoords = this.CheckObjectConstraints(topLeftQuadCoords); foreach (Tuple <RCIntRectangle, SpriteRenderInfo[]> relativeRect in objRectsRelativeToTopLeftQuadTile) { RCIntVector topLeftDisplayCoords = this.MapWindowBC.AttachedWindow.QuadToWindowRect(new RCIntRectangle(topLeftQuadCoords + relativeRect.Item1.Location, new RCIntVector(1, 1))).Location; for (int i = 0; i < relativeRect.Item2.Length; i++) { relativeRect.Item2[i].DisplayCoords += topLeftDisplayCoords; placementBox.Sprites.Add(relativeRect.Item2[i]); } for (int x = relativeRect.Item1.Left; x < relativeRect.Item1.Right; x++) { for (int y = relativeRect.Item1.Top; y < relativeRect.Item1.Bottom; y++) { RCIntVector relativeQuadCoords = new RCIntVector(x, y); RCIntVector absQuadCoords = topLeftQuadCoords + relativeQuadCoords; RCIntRectangle partRect = this.MapWindowBC.AttachedWindow.QuadToWindowRect(new RCIntRectangle(absQuadCoords, new RCIntVector(1, 1))); if (violatingQuadCoords.Contains(relativeQuadCoords)) { placementBox.IllegalParts.Add(partRect); } else { placementBox.LegalParts.Add(partRect); } } } } return(placementBox); }
/// <summary> /// Implements visibility calculations when at least 1 FogOfWar is running. /// </summary> /// <returns>The results of the visibility calculations.</returns> private FowVisibilityInfo CalculateVisibilityWithFow() { if (this.quadTileWindow == RCIntRectangle.Undefined) { throw new InvalidOperationException("Visibility window not defined!"); } /// Collect the isometric & quadratic tiles that need to be updated. IMapAccess map = this.ActiveScenario.Map; RCSet <IIsoTile> isoTilesToUpdate = new RCSet <IIsoTile>(); RCSet <IQuadTile> quadTilesToUpdate = new RCSet <IQuadTile>(); RCSet <ITerrainObject> terrainObjectsToUpdate = new RCSet <ITerrainObject>(); RCSet <EntitySnapshot> entitySnapshotsToUpdate = new RCSet <EntitySnapshot>(); for (int column = this.quadTileWindow.Left; column < this.quadTileWindow.Right; column++) { for (int row = this.quadTileWindow.Top; row < this.quadTileWindow.Bottom; row++) { RCIntVector quadCoords = new RCIntVector(column, row); /// If the FOW is full at the current quadratic tile -> continue with the next. FOWTypeEnum fowAtQuadTile = this.fowCacheMatrix.GetFowStateAtQuadTile(quadCoords); if (fowAtQuadTile == FOWTypeEnum.Full) { continue; } /// Add the primary & secondary isometric tiles and all of their cutting quadratic tiles into the update lists. IQuadTile quadTileToUpdate = map.GetQuadTile(quadCoords); this.AddIsoTileToUpdate(quadTileToUpdate.PrimaryIsoTile, isoTilesToUpdate, quadTilesToUpdate); this.AddIsoTileToUpdate(quadTileToUpdate.SecondaryIsoTile, isoTilesToUpdate, quadTilesToUpdate); /// Add the terrain object and all of its cutting quadratic tiles into the update lists. this.AddTerrainObjectToUpdate(quadTileToUpdate.TerrainObject, terrainObjectsToUpdate, quadTilesToUpdate); /// Add the entity snapshot and all of its cutting quadratic tiles into the update lists. EntitySnapshot entitySnapshotAtQuadTile = this.fowCacheMatrix.GetEntitySnapshotAtQuadTile(quadCoords); this.AddEntitySnapshotToUpdate(entitySnapshotAtQuadTile, entitySnapshotsToUpdate, quadTilesToUpdate); } } /// Collect the currently visible map objects on the ground. RCSet <MapObject> groundObjectsOnMap = this.ActiveScenario.GetMapObjects( this.mapWindowBC.AttachedWindow.WindowMapCoords, MapObjectLayerEnum.GroundObjects, MapObjectLayerEnum.GroundMissiles); RCSet <MapObject> groundMapObjectsToUpdate = new RCSet <MapObject>(); foreach (MapObject groundMapObj in groundObjectsOnMap) { bool breakLoop = false; for (int col = groundMapObj.QuadraticPosition.Left; !breakLoop && col < groundMapObj.QuadraticPosition.Right; col++) { for (int row = groundMapObj.QuadraticPosition.Top; !breakLoop && row < groundMapObj.QuadraticPosition.Bottom; row++) { if (this.fowCacheMatrix.GetFowStateAtQuadTile(new RCIntVector(col, row)) == FOWTypeEnum.None) { /// Found at least 1 quadratic tile where the map objects is visible. this.AddMapObjectToUpdate(groundMapObj, groundMapObjectsToUpdate, quadTilesToUpdate); breakLoop = true; } } } } /// Collect the currently visible map objects in the air. RCSet <MapObject> airObjectsOnMap = this.ActiveScenario.GetMapObjects( this.mapWindowBC.AttachedWindow.WindowMapCoords, MapObjectLayerEnum.AirObjects, MapObjectLayerEnum.AirMissiles); RCSet <MapObject> airMapObjectsToUpdate = new RCSet <MapObject>(); foreach (MapObject airMapObj in airObjectsOnMap) { bool breakLoop = false; for (int col = airMapObj.QuadraticPosition.Left; !breakLoop && col < airMapObj.QuadraticPosition.Right; col++) { for (int row = airMapObj.QuadraticPosition.Top; !breakLoop && row < airMapObj.QuadraticPosition.Bottom; row++) { if (this.fowCacheMatrix.GetFowStateAtQuadTile(new RCIntVector(col, row)) == FOWTypeEnum.None) { /// Found at least 1 quadratic tile where the map objects is visible. this.AddMapObjectToUpdate(airMapObj, airMapObjectsToUpdate, quadTilesToUpdate); breakLoop = true; } } } } /// Create the calculated visibility info. return(new FowVisibilityInfo { IsoTilesToUpdate = isoTilesToUpdate, TerrainObjectsToUpdate = terrainObjectsToUpdate, QuadTilesToUpdate = quadTilesToUpdate, EntitySnapshotsToUpdate = entitySnapshotsToUpdate, GroundMapObjectsToUpdate = groundMapObjectsToUpdate, AirMapObjectsToUpdate = airMapObjectsToUpdate }); }