示例#1
0
        /// <summary>
        /// Gets the list of all velocities that are admissible from the given velocity.
        /// </summary>
        /// <param name="currentVelocity">The given velocity.</param>
        /// <returns>All velocities that are admissible from the given velocity.</returns>
        public List <RCNumVector> GetAdmissibleVelocities(RCNumVector currentVelocity)
        {
            if (!this.velocityGraph.ContainsKey(currentVelocity))
            {
                /// Search the velocity that has a minimum difference to the current velocity.
                RCNumber    minDiff         = 0;
                RCNumVector closestVelocity = RCNumVector.Undefined;
                foreach (RCNumVector velocity in this.velocityGraph.Keys)
                {
                    RCNumber diff = MapUtils.ComputeDistance(currentVelocity, velocity);
                    if (closestVelocity == RCNumVector.Undefined || diff < minDiff)
                    {
                        minDiff         = diff;
                        closestVelocity = velocity;
                    }
                }

                if (closestVelocity == RCNumVector.Undefined)
                {
                    throw new InvalidOperationException("Impossible case!");
                }
                currentVelocity = closestVelocity;
            }

            return(new List <RCNumVector>(this.velocityGraph[currentVelocity]));
        }
示例#2
0
        /// <see cref="IMapObjectDetailsView.GetHPCondition"/>
        public MapObjectConditionEnum GetHPCondition(int objectID)
        {
            if (objectID < 0)
            {
                throw new ArgumentOutOfRangeException("objectID");
            }

            Entity entity = this.GetEntity(objectID);

            if (entity.Biometrics.HP == -1)
            {
                return(MapObjectConditionEnum.Undefined);
            }

            RCNumber hpNorm = entity.Biometrics.HP / entity.ElementType.MaxHP.Read();

            if (hpNorm <= (RCNumber)1 / (RCNumber)3)
            {
                return(MapObjectConditionEnum.Critical);
            }
            else if (hpNorm <= (RCNumber)2 / (RCNumber)3)
            {
                return(MapObjectConditionEnum.Moderate);
            }
            else
            {
                return(MapObjectConditionEnum.Excellent);
            }
        }
        /// <see cref="SCVBuildExecutionBase.ContinueMovingToTarget"/>
        protected override bool ContinueMovingToTarget()
        {
            /// Check the distance between the SCV and the target area.
            RCNumber distance = MapUtils.ComputeDistance(this.RecipientSCV.Area, this.targetArea.Read());

            if (distance > Weapon.NEARBY_DISTANCE)
            {
                /// Distance not reached yet -> continue execution if SCV is still moving.
                return(!this.RecipientSCV.MotionControl.IsMoving);
            }

            TerranBuildingConstructionJob job = new TerranBuildingConstructionJob(
                this.RecipientSCV,
                this.RecipientSCV.Owner.Metadata.GetBuildingType(this.buildingTypeName),
                this.topLeftQuadTile.Read());

            if (!job.LockResources())
            {
                /// Unable to lock the necessary resources -> abort the job and cancel.
                job.Dispose();
                return(true);
            }

            if (!job.Start())
            {
                /// Unable to start the job -> abort the job and cancel.
                job.Dispose();
                return(true);
            }

            this.Status = SCVBuildExecutionStatusEnum.Constructing;
            return(false);
        }
示例#4
0
        /// <summary>
        /// Constructs a VelocityGraph instance.
        /// </summary>
        /// <param name="maxSpeed">The maximum speed that this velocity graph is based on.</param>
        /// <param name="velocityGraph">
        /// The dictionary that represents the velocity graph.
        /// The keys of this dictionary contains all the possible velocities. The values of this dictionary are the sets of
        /// the velocities admissible from the velocity stored by corresponding key. Each velocity in one of those
        /// lists must either be present as a key in this dictionary. The (0;0) vector must be present in this
        /// dictionary as a key.
        /// </param>
        protected VelocityGraph(RCNumber maxSpeed, Dictionary <RCNumVector, RCSet <RCNumVector> > velocityGraph)
        {
            if (maxSpeed < 0)
            {
                throw new ArgumentOutOfRangeException("maxSpeed", "Maximum speed cannot be negative!");
            }
            if (velocityGraph == null)
            {
                throw new ArgumentNullException("velocityGraph");
            }
            if (!velocityGraph.ContainsKey(new RCNumVector(0, 0)))
            {
                throw new ArgumentException("Velocity graph must contain the (0;0) vector as a key!", "velocityGraph");
            }

            /// Check and save the new velocity graph.
            this.velocityGraph = new Dictionary <RCNumVector, RCSet <RCNumVector> >();
            foreach (KeyValuePair <RCNumVector, RCSet <RCNumVector> > item in velocityGraph)
            {
                if (item.Value.Any(velocity => !velocityGraph.ContainsKey(velocity)))
                {
                    throw new ArgumentException("Each velocity in the admissibility lists must either be present as a key in the velocity graph dictionary!", "velocityGraph");
                }
                this.velocityGraph.Add(item.Key, new RCSet <RCNumVector>(item.Value));
            }

            /// Save the maximum speed that this velocity graph is based on.
            this.maxSpeed = maxSpeed;
        }
示例#5
0
        /// <summary>
        /// Tries to align the minimap horizontally.
        /// </summary>
        /// <param name="minimapControlPixelSize">The size of the minimap control in pixels.</param>
        /// <param name="mapCellSize">The size of the map in cells.</param>
        /// <param name="minimapPosition">The position of the minimap on the minimap control in pixels.</param>
        /// <param name="transformation">The transformation between the map (A) and minimap (B) coordinate-systems.</param>
        /// <returns>True if the alignment was successfully; otherwise false.</returns>
        private static bool TryAlignMinimapHorizontally(
            RCIntVector minimapControlPixelSize,
            RCIntVector mapCellSize,
            out RCIntRectangle minimapPosition,
            out RCCoordTransformation transformation)
        {
            RCNumber horzAlignedMinimapHeight = (RCNumber)(minimapControlPixelSize.X * mapCellSize.Y) / (RCNumber)mapCellSize.X;

            if (horzAlignedMinimapHeight > minimapControlPixelSize.Y)
            {
                /// Cannot align horizontally.
                minimapPosition = RCIntRectangle.Undefined;
                transformation  = null;
                return(false);
            }

            /// Align horizontally
            int minimapPixelHeight = horzAlignedMinimapHeight > (int)horzAlignedMinimapHeight
                                   ? (int)horzAlignedMinimapHeight + 1
                                   : (int)horzAlignedMinimapHeight;

            minimapPosition = new RCIntRectangle(0, (minimapControlPixelSize.Y - minimapPixelHeight) / 2, minimapControlPixelSize.X, minimapPixelHeight);

            /// Create the coordinate transformation
            RCNumVector pixelSizeOnMap = new RCNumVector((RCNumber)mapCellSize.X / (RCNumber)minimapControlPixelSize.X,
                                                         (RCNumber)mapCellSize.X / (RCNumber)minimapControlPixelSize.X);
            RCNumVector nullVectorOfMinimap  = (pixelSizeOnMap / 2) - (new RCNumVector(1, 1) / 2);
            RCNumVector baseVectorOfMinimapX = new RCNumVector(pixelSizeOnMap.X, 0);
            RCNumVector baseVectorOfMinimapY = new RCNumVector(0, pixelSizeOnMap.Y);

            transformation = new RCCoordTransformation(nullVectorOfMinimap, baseVectorOfMinimapX, baseVectorOfMinimapY);

            return(true);
        }
示例#6
0
        /// <summary>
        /// Tries to align the minimap vertically.
        /// </summary>
        /// <param name="minimapControlPixelSize">The size of the minimap control in pixels.</param>
        /// <param name="mapCellSize">The size of the map in cells.</param>
        /// <param name="minimapPosition">The position of the minimap on the minimap control in pixels.</param>
        /// <param name="transformation">The transformation between the map (A) and minimap (B) coordinate-systems.</param>
        /// <returns>True if the alignment was successfully; otherwise false.</returns>
        private static bool TryAlignMinimapVertically(
            RCIntVector minimapControlPixelSize,
            RCIntVector mapCellSize,
            out RCIntRectangle minimapPosition,
            out RCCoordTransformation transformation)
        {
            RCNumber vertAlignedMinimapWidth = (RCNumber)(minimapControlPixelSize.Y * mapCellSize.X) / (RCNumber)mapCellSize.Y;

            if (vertAlignedMinimapWidth > minimapControlPixelSize.X)
            {
                /// Cannot align vertically.
                minimapPosition = RCIntRectangle.Undefined;
                transformation  = null;
                return(false);
            }

            /// Align vertically
            int minimapPixelWidth = vertAlignedMinimapWidth > (int)vertAlignedMinimapWidth
                                  ? (int)vertAlignedMinimapWidth + 1
                                  : (int)vertAlignedMinimapWidth;

            minimapPosition = new RCIntRectangle((minimapControlPixelSize.X - minimapPixelWidth) / 2, 0, minimapPixelWidth, minimapControlPixelSize.Y);

            /// Create the coordinate transformation
            RCNumVector pixelSizeOnMap = new RCNumVector((RCNumber)mapCellSize.Y / (RCNumber)minimapControlPixelSize.Y,
                                                         (RCNumber)mapCellSize.Y / (RCNumber)minimapControlPixelSize.Y);
            RCNumVector nullVectorOfMinimap  = (pixelSizeOnMap / 2) - (new RCNumVector(1, 1) / 2);
            RCNumVector baseVectorOfMinimapX = new RCNumVector(pixelSizeOnMap.X, 0);
            RCNumVector baseVectorOfMinimapY = new RCNumVector(0, pixelSizeOnMap.Y);

            transformation = new RCCoordTransformation(nullVectorOfMinimap, baseVectorOfMinimapX, baseVectorOfMinimapY);

            return(true);
        }
示例#7
0
        /// <see cref="SCVBuildExecutionBase.ContinueMovingToTarget"/>
        protected override bool ContinueMovingToTarget()
        {
            /// First try to retrieve the target building from the scenario.
            TerranBuilding targetBuilding = this.Scenario.GetElementOnMap <TerranBuilding>(this.targetBuildingID.Read(), MapObjectLayerEnum.GroundObjects);

            if (targetBuilding == null)
            {
                /// Target building not found -> finish command execution.
                return(true);
            }

            /// Check the distance between the SCV and the target building.
            RCNumber distance = MapUtils.ComputeDistance(this.RecipientSCV.Area, targetBuilding.Area);

            if (distance > Weapon.NEARBY_DISTANCE)
            {
                /// Distance not reached yet -> continue execution if SCV is still moving.
                return(!this.RecipientSCV.MotionControl.IsMoving);
            }

            /// Check if the target building has an inactive construction job.
            if (targetBuilding.ConstructionJob == null || targetBuilding.ConstructionJob.AttachedSCV != null)
            {
                /// Target building doesn't have an inactive construction job -> finish command execution.
                return(true);
            }

            /// Attach the SCV to the construction job of the target building.
            targetBuilding.ConstructionJob.AttachSCV(this.RecipientSCV);
            this.Status = SCVBuildExecutionStatusEnum.Constructing;
            return(false);
        }
示例#8
0
 /// <summary>
 /// Sets the speed of the corresponding element type.
 /// </summary>
 public void SetSpeed(RCNumber speed)
 {
     if (this.metadata.IsFinalized)
     {
         throw new InvalidOperationException("Already finalized!");
     }
     this.speed = new ConstValue <RCNumber>(speed);
 }
示例#9
0
        /// <summary>
        /// Computes the distance between two points on the map.
        /// </summary>
        /// <param name="fromCoords">The first point on the map.</param>
        /// <param name="toCoords">The second point on the map.</param>
        /// <returns>The computed distance between the given points.</returns>
        public static RCNumber ComputeDistance(RCNumVector fromCoords, RCNumVector toCoords)
        {
            RCNumber horz = (toCoords.X - fromCoords.X).Abs();
            RCNumber vert = (toCoords.Y - fromCoords.Y).Abs();
            RCNumber diff = (horz - vert).Abs();

            return((horz < vert ? horz : vert) * RCNumber.ROOT_OF_TWO + diff);
        }
示例#10
0
 /// <see cref="Weapon.IsInRange"/>
 protected override bool IsInRange(RCNumber distance)
 {
     if (this.attachedWeapon.Read() == null)
     {
         throw new InvalidOperationException("Custom weapon is not attached to this stub!");
     }
     return(this.attachedWeapon.Read().IsInRange(distance));
 }
示例#11
0
 /// <summary>
 /// Converts the distance given in cells to a distance given in quadratic tiles.
 /// </summary>
 /// <param name="cellDistance">The distance given in cells.</param>
 /// <returns>The distance given in quadratic tiles.</returns>
 public static RCNumber CellToQuadDistance(RCNumber cellDistance)
 {
     if (cellDistance < 0)
     {
         throw new ArgumentOutOfRangeException("cellDistance", "Distance cannot be negative!");
     }
     return(cellDistance / MapStructure.NAVCELL_PER_QUAD);
 }
示例#12
0
        /// <see cref="Weapon.IsInRange"/>
        protected override bool IsInRange(RCNumber distance)
        {
            if (this.weaponData.RangeMax.Read() == 0)
            {
                return(distance <= Weapon.NEARBY_DISTANCE);
            }
            RCNumber quadDistance = MapUtils.CellToQuadDistance(distance);

            return(quadDistance >= this.weaponData.RangeMin.Read() && quadDistance <= this.weaponData.RangeMax.Read());
        }
示例#13
0
        /// <summary>
        /// Selects an enemy that can be attacked by the owner.
        /// </summary>
        /// <returns>An enemy that can be attacked by the owner or null if no such enemy has been found.</returns>
        public Entity SelectEnemyForStandardWeapons()
        {
            if (this.standardWeapons.Count == 0)
            {
                /// The owner has no standard weapons -> no enemy can be attacked.
                return(null);
            }

            /// Select the nearest enemy.
            RCNumber nearestEnemyDistance = 0;
            Entity   nearestEnemy         = null;

            foreach (Entity locatedEntity in this.owner.Read().Locator.LocateEntities())
            {
                /// Check if the located entity is an enemy or not.
                if (locatedEntity.Owner == null || locatedEntity.Owner == this.owner.Read().Owner)
                {
                    continue;
                }

                /// Check if any of the standard weapons can target the located entity.
                bool hasWeaponCanTargetEntity = false;
                foreach (Weapon standardWeapon in this.standardWeapons)
                {
                    if (standardWeapon.CanTargetEntity(locatedEntity))
                    {
                        hasWeaponCanTargetEntity = true;
                        break;
                    }
                }
                if (!hasWeaponCanTargetEntity)
                {
                    /// The owner has no weapons that can attack the located enemy -> continue with the next located enemy.
                    continue;
                }

                if (nearestEnemy == null)
                {
                    nearestEnemy = locatedEntity;
                }
                else
                {
                    RCNumber distance = MapUtils.ComputeDistance(this.owner.Read().Area, locatedEntity.Area);
                    if (distance < nearestEnemyDistance)
                    {
                        nearestEnemy = locatedEntity;
                    }
                }
            }

            return(nearestEnemy);
        }
示例#14
0
        /// <summary>
        /// Internal method for calculating the ground level for this quadratic tile.
        /// </summary>
        /// <returns>The calculated ground level.</returns>
        private int CalculateGroundLevel()
        {
            RCNumber groundLevelSum = 0;

            for (int row = 0; row < MapStructure.NAVCELL_PER_QUAD; row++)
            {
                for (int col = 0; col < MapStructure.NAVCELL_PER_QUAD; col++)
                {
                    groundLevelSum += this.cells[col, row].GroundLevel;
                }
            }
            return((groundLevelSum / (MapStructure.NAVCELL_PER_QUAD * MapStructure.NAVCELL_PER_QUAD)).Round());
        }
示例#15
0
        /// <summary>
        /// Begins the landing of the owner of this motion control.
        /// </summary>
        /// <param name="landOnTheSpot">True to land without transition.</param>
        /// <exception cref="InvalidOperationException">If the status of this motion control is not MotionControlStatusEnum.Flying.</exception>
        /// <returns>True if the landing operation started successfully; otherwise false.</returns>
        public bool BeginLand(bool landOnTheSpot)
        {
            if (this.position.Read() == RCNumVector.Undefined)
            {
                throw new InvalidOperationException("The owner is currently detached from the map!");
            }
            if (this.Status != MotionControlStatusEnum.InAir)
            {
                throw new InvalidOperationException("The owner is currently not in the air!");
            }

            this.StopMoving();

            /// Calculate position after land.
            RCNumVector positionAfterLand = RCNumVector.Undefined;

            if (landOnTheSpot)
            {
                /// Landing on the spot.
                positionAfterLand = this.position.Read();
            }
            else
            {
                /// Normal landing.
                RCNumber bottomToMapEdgeDistance = this.owner.Read().Scenario.Map.CellSize.Y + (RCNumber)1 / (RCNumber)2
                                                   - this.owner.Read().Area.Bottom;
                if (bottomToMapEdgeDistance < 0)
                {
                    return(false);
                }

                RCNumber transitionValue = bottomToMapEdgeDistance <= Constants.MAX_VTOL_TRANSITION ? bottomToMapEdgeDistance : Constants.MAX_VTOL_TRANSITION;
                positionAfterLand = this.position.Read() + new RCNumVector(0, transitionValue);
            }

            /// Try to reserve the position on the ground and remove the reservation from the air.
            if (!this.groundPathTracker.Read().OnAttaching(positionAfterLand))
            {
                return(false);
            }
            this.airPathTracker.Read().OnDetached();

            /// Initialize the VTOL operation for landing.
            this.SetStatus(MotionControlStatusEnum.Landing);
            this.vtolOperationProgress.Write(0);
            this.vtolInitialPosition.Write(this.position.Read());
            this.vtolFinalPosition.Write(positionAfterLand);
            this.currentPathTracker.Write(null);

            return(true);
        }
示例#16
0
        /// <summary>
        /// Perform a repair step on the owner entity.
        /// </summary>
        /// <returns>True if the repair step performed successfully; otherwise false.</returns>
        public bool Repair()
        {
            if (this.owner.Read().ElementType.BuildTime == null)
            {
                throw new InvalidOperationException("Unable to repair entities if build time is not defined in the metadata!");
            }
            if (this.hp.Read() == -1)
            {
                throw new InvalidOperationException("Unable to repair non-attackable entities!");
            }
            if (this.IsUnderConstruction)
            {
                throw new InvalidOperationException("Unable to repair entities under construction!");
            }

            /// If we reached the maximum HP -> repair step failed to perform.
            if (this.hp.Read() == this.owner.Read().ElementType.MaxHP.Read())
            {
                return(false);
            }

            /// Calculate the HP to add and the resources to take in this repair step.
            RCNumber hpToAdd = (RCNumber)this.owner.Read().ElementType.MaxHP.Read() / (RCNumber)this.owner.Read().ElementType.BuildTime.Read();
            RCNumber totalOriginalMineralCost = this.owner.Read().ElementType.MineralCost != null
                ? this.owner.Read().ElementType.MineralCost.Read()
                : 0;

            RCNumber mineralsToTake       = totalOriginalMineralCost * REPAIR_COST_RATE / this.owner.Read().ElementType.BuildTime.Read();
            RCNumber totalOriginalGasCost = this.owner.Read().ElementType.GasCost != null
                ? this.owner.Read().ElementType.GasCost.Read()
                : 0;

            RCNumber gasToTake = totalOriginalGasCost * REPAIR_COST_RATE / this.owner.Read().ElementType.BuildTime.Read();

            /// Try to take the necessary resources from the player of the owner entity (if it has a player).
            if (this.owner.Read().Owner != null && !this.owner.Read().Owner.TakeResources(mineralsToTake, gasToTake))
            {
                /// Not enough resources -> repair step failed to perform.
                return(false);
            }

            /// Necessary resources taken successfully (or the entity is neutral) -> modify the HP value and return with success.
            RCNumber newHP = this.hp.Read() + hpToAdd;

            if (newHP > this.owner.Read().ElementType.MaxHP.Read())
            {
                newHP = this.owner.Read().ElementType.MaxHP.Read();
            }
            this.hp.Write(newHP);
            return(true);
        }
示例#17
0
        /// <summary>
        /// Gives the given amount of minerals and vespene gas to this player.
        /// </summary>
        /// <param name="minerals">The amount of minerals to be given.</param>
        /// <param name="vespeneGas">The amount of vespene gas to be given.</param>
        public void GiveResources(RCNumber minerals, RCNumber vespeneGas)
        {
            if (minerals < 0)
            {
                throw new ArgumentOutOfRangeException("minerals", "The amount of minerals to be given cannot be negative!");
            }
            if (vespeneGas < 0)
            {
                throw new ArgumentOutOfRangeException("vespeneGas", "The amount of vespene gas to be given cannot be negative!");
            }

            this.minerals.Write(this.minerals.Read() + minerals);
            this.vespeneGas.Write(this.vespeneGas.Read() + vespeneGas);
        }
示例#18
0
 /// <see cref="EntityBehavior.UpdateMapObject"/>
 public override void UpdateMapObject(Entity entity)
 {
     if (entity.Biometrics.IsUnderConstruction)
     {
         /// Entity is under construction -> play the animation that belongs to the current construction progress.
         RCNumber progressPerIndex = (RCNumber)entity.ElementType.BuildTime.Read()
                                     / (RCNumber)(this.constructionAnimations.Length);
         this.PlayConstructionAnimation(entity, (int)(entity.Biometrics.ConstructionProgress / progressPerIndex));
     }
     else
     {
         /// Entity is not under construction -> stop every construction animations.
         this.StopStartAnimations(entity, this.constructionAnimationsSet, new RCSet <string>());
     }
 }
示例#19
0
        /// <summary>
        /// Begins or continues the construction progress of the owner entity.
        /// </summary>
        public void Construct()
        {
            if (this.owner.Read().ElementType.BuildTime == null)
            {
                throw new InvalidOperationException("Unable to construct entities if build time is not defined in the metadata!");
            }
            if (this.hp.Read() == -1)
            {
                throw new InvalidOperationException("Unable to construct non-attackable entities!");
            }

            /// Do nothing if the HP reached 0.
            if (this.hp.Read() == 0)
            {
                return;
            }

            if (this.constructionProgress.Read() == -1)
            {
                /// Begin the construction starting from 10% of MaxHP.
                this.constructionProgress.Write(0);
                this.hp.Write((RCNumber)this.owner.Read().ElementType.MaxHP.Read() / (RCNumber)10);
                if (this.energy.Read() != -1)
                {
                    /// Starting from 50 (or MaxEnergy) at the beginning of the construction.
                    this.energy.Write(Math.Min(this.owner.Read().ElementType.MaxEnergy.Read(), INITIAL_ENERGY));
                }
            }
            else
            {
                /// Do nothing if the construction has already completed.
                if (!this.IsUnderConstruction)
                {
                    return;
                }

                /// Continue construction and increment HP accordingly.
                this.constructionProgress.Write(this.constructionProgress.Read() + 1);
                RCNumber hpIncrement = ((RCNumber)this.owner.Read().ElementType.MaxHP.Read() * (RCNumber)9)
                                       / ((RCNumber)this.owner.Read().ElementType.BuildTime.Read() * (RCNumber)10);
                this.hp.Write(this.hp.Read() + hpIncrement);
                if (this.hp.Read() > this.owner.Read().ElementType.MaxHP.Read())
                {
                    this.hp.Write(this.owner.Read().ElementType.MaxHP.Read());
                }
            }
        }
示例#20
0
        /// <summary>
        /// Calculates the next position of the controlled entity from its current position and the next waypoint.
        /// </summary>
        /// <returns>The calculated next position of the controlled entity.</returns>
        private RCNumVector CalculateNextPosition()
        {
            RCNumVector currentPosition = this.controlledEntity.Read().MotionControl.PositionVector.Read();
            RCNumber    distToWP        = MapUtils.ComputeDistance(currentPosition, this.CurrentWaypoint);

            if (distToWP > this.controlledEntity.Read().ElementType.Speed.Read())
            {
                // Move towards the next waypoint.
                RCNumVector translationVect = (this.controlledEntity.Read().ElementType.Speed.Read() / distToWP) * (this.CurrentWaypoint - currentPosition);
                return(currentPosition + translationVect);
            }
            else
            {
                // Next waypoint can be reached in this step.
                return(this.CurrentWaypoint);
            }
        }
示例#21
0
        /// <see cref="ISelectionIndicatorView.GetVisibleSelIndicators"/>
        public List <SelIndicatorRenderInfo> GetVisibleSelIndicators()
        {
            RCSet <int> currentSelection = this.selectionManager.CurrentSelection;

            if (currentSelection.Count == 0)
            {
                return(new List <SelIndicatorRenderInfo>());
            }

            /// Display the selection indicators of the currently visible entities inside the currently visible window of quadratic tiles.
            List <SelIndicatorRenderInfo> retList = new List <SelIndicatorRenderInfo>();

            foreach (MapObject mapObject in this.fogOfWarBC.GetAllMapObjectsToUpdate())
            {
                Entity entity = mapObject.Owner as Entity;
                if (entity != null && currentSelection.Contains(entity.ID.Read()))
                {
                    SelIndicatorTypeEnum indicatorType
                        = entity.Owner != null
                        ? (entity.Owner.PlayerIndex == (int)this.selectionManager.LocalPlayer ? SelIndicatorTypeEnum.Friendly : SelIndicatorTypeEnum.Enemy)
                        : SelIndicatorTypeEnum.Neutral;
                    RCNumber hpNorm = entity.Biometrics.HP != -1
                        ? entity.Biometrics.HP / entity.ElementType.MaxHP.Read()
                        : -1;

                    RCNumber energyNorm = -1;
                    if (entity.Owner != null && entity.Owner.PlayerIndex == (int)this.selectionManager.LocalPlayer)
                    {
                        energyNorm = entity.Biometrics.Energy != -1
                                   ? entity.Biometrics.Energy / entity.ElementType.MaxEnergy.Read()
                                   : -1;
                    }

                    retList.Add(new SelIndicatorRenderInfo()
                    {
                        ObjectID         = entity.ID.Read(),
                        SelIndicatorType = indicatorType,
                        IndicatorRect    = this.MapWindowBC.AttachedWindow.MapToWindowRect(entity.Area),
                        HpNormalized     = hpNorm,
                        EnergyNormalized = energyNorm,
                        ShieldNormalized = -1, // TODO: must be based on real data after Protoss will have been implemented!
                    });
                }
            }
            return(retList);
        }
示例#22
0
        /// <summary>
        /// Loads an RCNumVector defined in the given string.
        /// </summary>
        /// <param name="fromStr">The string to load from.</param>
        /// <returns>The loaded RCNumVector.</returns>
        public static RCNumVector LoadNumVector(string fromStr)
        {
            if (fromStr == null)
            {
                throw new ArgumentNullException("fromStr");
            }

            string[] componentStrings = fromStr.Split(';');
            if (componentStrings.Length != 2)
            {
                throw new ConfigurationException("Vector format error!");
            }

            RCNumber vectorX = LoadNum(componentStrings[0]);
            RCNumber vectorY = LoadNum(componentStrings[1]);

            return(new RCNumVector(vectorX, vectorY));
        }
示例#23
0
        /// <summary>
        /// Loads an RCNumRectangle defined in the given string in format: "X;Y;Width;Height".
        /// </summary>
        /// <param name="fromStr">The string to load from.</param>
        /// <returns>The loaded RCNumRectangle.</returns>
        public static RCNumRectangle LoadNumRectangle(string fromStr)
        {
            if (fromStr == null)
            {
                throw new ArgumentNullException("fromStr");
            }

            string[] componentStrings = fromStr.Split(';');
            if (componentStrings.Length != 4)
            {
                throw new ConfigurationException("Rectangle format error!");
            }

            RCNumber rectX      = LoadNum(componentStrings[0]);
            RCNumber rectY      = LoadNum(componentStrings[1]);
            RCNumber rectWidth  = LoadNum(componentStrings[2]);
            RCNumber rectHeight = LoadNum(componentStrings[3]);

            return(new RCNumRectangle(rectX, rectY, rectWidth, rectHeight));
        }
示例#24
0
        /// <summary>
        /// Takes the given amount of minerals and vespene gas from this player.
        /// </summary>
        /// <param name="minerals">The amount of minerals to be taken.</param>
        /// <param name="vespeneGas">The amount of vespene gas to be taken.</param>
        /// <returns>True if the given amount of resources has been taken successfully.</returns>
        public bool TakeResources(RCNumber minerals, RCNumber vespeneGas)
        {
            if (minerals < 0)
            {
                throw new ArgumentOutOfRangeException("minerals", "The amount of minerals to be taken cannot be negative!");
            }
            if (vespeneGas < 0)
            {
                throw new ArgumentOutOfRangeException("vespeneGas", "The amount of vespene gas to be taken cannot be negative!");
            }

            if (this.minerals.Read() < minerals || this.vespeneGas.Read() < vespeneGas)
            {
                return(false);
            }

            this.minerals.Write(this.minerals.Read() - minerals);
            this.vespeneGas.Write(this.vespeneGas.Read() - vespeneGas);
            return(true);
        }
示例#25
0
 /// <summary>
 /// Calculates the map direction out of the given heading vector.
 /// </summary>
 /// <param name="headingVector">The heading vector.</param>
 private void CalculateMapDirection(RCNumVector headingVector)
 {
     // New heading -> recalculate the map direction.
     if (headingVector.X == 0 && headingVector.Y == 0)
     {
         this.cachedMapDirection = MapDirection.Undefined;
     }                                                                                                       // In case of 0 heading vector -> map direction is undefined.
     else if (headingVector.X == 0)
     {
         this.cachedMapDirection = headingVector.Y > 0 ? MapDirection.South : MapDirection.North;
     }                                                                                                                           // In case of vertical heading vector -> map direction is South or North based on the Y-coordinate.
     else
     {
         // In any other cases -> map direction is calculated from the tangent of the heading vector.
         RCNumber tangentOfVelocity = headingVector.Y / headingVector.X;
         if (SE_NW_TANGENT_LOWERBOUND < tangentOfVelocity && tangentOfVelocity <= SE_NW_TANGENT_UPPERBOUND)
         {
             // SouthEast or NorthWest
             this.cachedMapDirection = headingVector.X > 0 && headingVector.Y > 0
                                     ? MapDirection.SouthEast
                                     : MapDirection.NorthWest;
         }
         else if (SW_NE_TANGENT_LOWERBOUND < tangentOfVelocity && tangentOfVelocity <= SW_NE_TANGENT_UPPERBOUND)
         {
             // SouthWest or NorthEast
             this.cachedMapDirection = headingVector.X < 0 && headingVector.Y > 0
                                     ? MapDirection.SouthWest
                                     : MapDirection.NorthEast;
         }
         else if (W_E_TANGENT_LOWERBOUND < tangentOfVelocity && tangentOfVelocity <= W_E_TANGENT_UPPERBOUND)
         {
             // West or East
             this.cachedMapDirection = headingVector.X < 0 ? MapDirection.West : MapDirection.East;
         }
         else
         {
             // North or South
             this.cachedMapDirection = headingVector.Y < 0 ? MapDirection.North : MapDirection.South;
         }
     }
 }
        /// <see cref="UIObject.Render_i"/>
        protected override void Render_i(IUIRenderContext renderContext)
        {
            /// Render the progress bar sprite.
            renderContext.RenderSprite(this.progressBarSprite, PROGRESSBAR_SPRITE_POS);

            /// Render the progress of the current production job.
            RCNumber progressNorm = this.productionDetailsView.ProductionLineProgressNormalized;

            if (progressNorm != -1)
            {
                int lineWidth = (int)(PROGRESSBAR_INNER_RECT.Width * progressNorm);
                if (lineWidth > 0)
                {
                    renderContext.RenderRectangle(this.progressBarBrush,
                                                  new RCIntRectangle(PROGRESSBAR_INNER_RECT.Left,
                                                                     PROGRESSBAR_INNER_RECT.Top,
                                                                     lineWidth,
                                                                     PROGRESSBAR_INNER_RECT.Height));
                }
            }
        }
示例#27
0
        /// <summary>
        /// Continue the execution in case of a follow command.
        /// </summary>
        /// <returns>True if execution is finished; otherwise false.</returns>
        private void ContinueFollow()
        {
            /// Check if target entity still can be located.
            this.targetEntity.Write(this.LocateEntity(this.targetEntityID.Read()));
            if (!this.HasToFollowTarget)
            {
                return;
            }

            /// Calculate its distance from the recipient entity.
            RCNumber distance = MapUtils.ComputeDistance(this.recipientEntity.Read().Area, this.targetEntity.Read().Area);

            if (distance > MAX_DISTANCE)
            {
                /// Too far -> start approaching again.
                this.recipientEntity.Read().MotionControl.StartMoving(this.targetEntity.Read().MotionControl.PositionVector.Read());
            }
            //else
            //{
            //    /// Close enough -> stop the recipient entity.
            //    this.recipientEntity.Read().MotionControl.StopMoving();
            //}
        }
示例#28
0
        /// <summary>
        /// Makes an absolute damage on the owner of this biometrics.
        /// </summary>
        /// <param name="damageValue">The amount of the damage.</param>
        public void Damage(RCNumber damageValue)
        {
            if (this.owner.Read().ElementType.Size == null)
            {
                throw new InvalidOperationException("Unable to make damage on non-attackable entities!");
            }
            if (this.owner.Read().ElementType.Armor == null)
            {
                throw new InvalidOperationException("Unable to make damage on non-attackable entities!");
            }
            if (this.hp.Read() == -1)
            {
                throw new InvalidOperationException("Unable to make damage on non-attackable entities!");
            }

            RCNumber newHP = this.hp.Read() - damageValue;

            if (newHP < 0)
            {
                newHP = 0;
            }
            this.hp.Write(newHP);
        }
示例#29
0
        /// <summary>
        /// Calculates the bounding box of the given entities.
        /// </summary>
        /// <param name="entities">The entities.</param>
        /// <returns>The bounding box of the given entities.</returns>
        private RCNumRectangle CalculateBoundingBox(RCSet <Entity> entities)
        {
            RCNumber top = -1, left = -1, bottom = -1, right = -1;

            foreach (Entity entity in entities)
            {
                RCNumVector entityPosition = entity.MotionControl.PositionVector.Read();
                if (top == -1 || entityPosition.Y < top)
                {
                    top = entityPosition.Y;
                }
                if (left == -1 || entityPosition.X < left)
                {
                    left = entityPosition.X;
                }
                if (bottom == -1 || entityPosition.Y > bottom)
                {
                    bottom = entityPosition.Y;
                }
                if (right == -1 || entityPosition.X > right)
                {
                    right = entityPosition.X;
                }
            }

            if (right - left == 0)
            {
                left  -= (RCNumber)1 / (RCNumber)2;
                right += (RCNumber)1 / (RCNumber)2;
            }
            if (bottom - top == 0)
            {
                top    -= (RCNumber)1 / (RCNumber)2;
                bottom += (RCNumber)1 / (RCNumber)2;
            }
            return(new RCNumRectangle(left, top, right - left, bottom - top));
        }
示例#30
0
        /// <summary>
        /// Begins the takeoff of the owner of this motion control.
        /// </summary>
        /// <exception cref="InvalidOperationException">If the status of this motion control is not MotionControlStatusEnum.Fixed.</exception>
        /// <returns>True if the takeoff operation started successfully; otherwise false.</returns>
        public bool BeginTakeOff()
        {
            if (this.position.Read() == RCNumVector.Undefined)
            {
                throw new InvalidOperationException("The owner is currently detached from the map!");
            }
            if (this.Status != MotionControlStatusEnum.Fixed)
            {
                throw new InvalidOperationException("The owner is currently not fixed!");
            }

            /// Calculate position after take-off.
            RCNumber topToMapEdgeDistance = this.owner.Read().Area.Top + (RCNumber)1 / (RCNumber)2;

            if (topToMapEdgeDistance < 0)
            {
                return(false);
            }
            RCNumber    transitionValue      = topToMapEdgeDistance <= Constants.MAX_VTOL_TRANSITION ? topToMapEdgeDistance : Constants.MAX_VTOL_TRANSITION;
            RCNumVector positionAfterTakeOff = this.owner.Read().MotionControl.PositionVector.Read() - new RCNumVector(0, transitionValue);

            /// Try to reserve the position in the air and remove the reservation from the ground.
            if (!this.airPathTracker.Read().OnAttaching(positionAfterTakeOff))
            {
                return(false);
            }
            this.groundPathTracker.Read().OnDetached();

            /// Initialize the VTOL operation for take-off.
            this.Unfix();
            this.SetStatus(MotionControlStatusEnum.TakingOff);
            this.vtolOperationProgress.Write(0);
            this.vtolInitialPosition.Write(this.position.Read());
            this.vtolFinalPosition.Write(positionAfterTakeOff);
            this.currentPathTracker.Write(null);
            return(true);
        }