Ejemplo n.º 1
0
        public static void RecalculateOreSpread(IEnumerable <OverlayObject> ovls, EngineType engine)
        {
            Logger.Info("Redistributing ore-spread over patches");

            foreach (OverlayObject o in ovls)
            {
                // The value consists of the sum of all dx's with a little magic offsets
                // plus the sum of all dy's with also a little magic offset, and also
                // everything is calculated modulo 12
                var type = SpecialOverlays.GetOverlayTibType(o, engine);

                if (type == OverlayTibType.Ore)
                {
                    int    x    = o.Tile.Dx;
                    int    y    = o.Tile.Dy;
                    double yInc = ((((y - 9) / 2) % 12) * (((y - 8) / 2) % 12)) % 12;
                    double xInc = ((((x - 13) / 2) % 12) * (((x - 12) / 2) % 12)) % 12;

                    // x_inc may be > y_inc so adding a big number outside of cell bounds
                    // will surely keep num positive
                    var num = (int)(yInc - xInc + 120000);
                    num %= 12;

                    if (engine <= EngineType.RedAlert2)
                    {
                        o.OverlayID = (byte)(SpecialOverlays.Ra2MinIdRiparius + num);
                    }
                    else
                    {
                        o.OverlayID = (byte)(SpecialOverlays.TsMinIdRiparius + num);
                    }
                }

                else if (type == OverlayTibType.Gems)
                {
                    int    x    = o.Tile.Dx;
                    int    y    = o.Tile.Dy;
                    double yInc = ((((y - 9) / 2) % 12) * (((y - 8) / 2) % 12)) % 12;
                    double xInc = ((((x - 13) / 2) % 12) * (((x - 12) / 2) % 12)) % 12;

                    // x_inc may be > y_inc so adding a big number outside of cell bounds
                    // will surely keep num positive
                    var num = (int)(yInc - xInc + 120000);
                    num %= 12;

                    // replace gems
                    if (engine <= EngineType.RedAlert2)
                    {
                        o.OverlayID = (byte)(SpecialOverlays.Ra2MinIdCruentus + num);
                    }
                    else
                    {
                        o.OverlayID = (byte)(SpecialOverlays.TsMinIdCruentus + num);
                    }
                }

                else if (type == OverlayTibType.Vinifera)
                {
                    int    x    = o.Tile.Dx;
                    int    y    = o.Tile.Dy;
                    double yInc = ((((y - 9) / 2) % 12) * (((y - 8) / 2) % 12)) % 12;
                    double xInc = ((((x - 13) / 2) % 12) * (((x - 12) / 2) % 12)) % 12;

                    // x_inc may be > y_inc so adding a big number outside of cell bounds
                    // will surely keep num positive
                    var num = (int)(yInc - xInc + 120000);
                    num %= 12;

                    // replace gems
                    if (engine <= EngineType.RedAlert2)
                    {
                        o.OverlayID = (byte)(SpecialOverlays.Ra2MinIdVinifera + num);
                    }
                    else
                    {
                        o.OverlayID = (byte)(SpecialOverlays.TsMinIdVinifera + num);
                    }
                }

                else if (type == OverlayTibType.Aboreus)
                {
                    int    x    = o.Tile.Dx;
                    int    y    = o.Tile.Dy;
                    double yInc = ((((y - 9) / 2) % 12) * (((y - 8) / 2) % 12)) % 12;
                    double xInc = ((((x - 13) / 2) % 12) * (((x - 12) / 2) % 12)) % 12;

                    // x_inc may be > y_inc so adding a big number outside of cell bounds
                    // will surely keep num positive
                    var num = (int)(yInc - xInc + 120000);
                    num %= 12;

                    // replace gems
                    if (engine <= EngineType.RedAlert2)
                    {
                        o.OverlayID = (byte)(SpecialOverlays.Ra2MinIdAboreus + num);
                    }
                    else
                    {
                        o.OverlayID = (byte)(SpecialOverlays.TsMinIdAboreus + num);
                    }
                }
            }
        }
Ejemplo n.º 2
0
        private object GetFrontBlock(GameObject objA, GameObject objB)
        {
            // magic, don't touch.
            // any kind of randomness or antisymmetry in this function
            // will lead to cyclic dependencies in the drawing order graph,
            // resulting in neither object every being drawn.

            // tiles never overlap
            if (objA is MapTile && objB is MapTile)
            {
                return(null);
            }

            var boxA = objA.GetBounds();
            var boxB = objB.GetBounds();

            if (!boxA.IntersectsWith(boxB))
            {
                return(null);
            }

            var hexA = GetIsoBoundingBox(objA);
            var hexB = GetIsoBoundingBox(objB);

            var sepAxis = Hexagon.GetSeparationAxis(hexA, hexB);

            // tiles can only be in front based on z-axis separation
            if ((objA is MapTile) ^ (objB is MapTile) && sepAxis != Axis.Z)
            {
                return((objA is MapTile) ? objB : objA);
            }

            // flat stuff always loses
            if (objA.Drawable.Flat ^ objB.Drawable.Flat)
            {
                if (sepAxis != Axis.Z)
                {
                    return((objA.Drawable.Flat) ? objB : objA);
                }
            }

            switch (sepAxis)
            {
            case Axis.X:
                if (hexA.xMin > hexB.xMax)
                {
                    return(objA);
                }
                else if (hexB.xMin > hexA.xMax)
                {
                    return(objB);
                }
                break;

            case Axis.Y:
                if (hexA.yMin > hexB.yMax)
                {
                    return(objA);
                }
                else if (hexB.yMin > hexA.yMax)
                {
                    return(objB);
                }
                break;

            case Axis.Z:
                if (hexA.zMin > hexB.zMax)
                {
                    return(objA);
                }
                else if (hexB.zMin > hexA.zMax)
                {
                    return(objB);
                }
                break;
            }

            // units on bridges can only be drawn after the bridge
            if (objA is OverlayObject && SpecialOverlays.IsHighBridge(objA as OverlayObject) &&
                objB is OwnableObject && (objB as OwnableObject).OnBridge)
            {
                return(objB);
            }
            else if (objB is OverlayObject && SpecialOverlays.IsHighBridge(objB as OverlayObject) &&
                     objA is OwnableObject && (objA as OwnableObject).OnBridge)
            {
                return(objA);
            }

            // no proper separation is possible, if one of both
            // objects is flat then mark the other one as in front,
            // otherwise use the one with lowest y
            if (objA.Drawable.Flat && !objB.Drawable.Flat)
            {
                return(objB);
            }
            else if (objB.Drawable.Flat && !objA.Drawable.Flat)
            {
                return(objA);
            }

            // try to make distinction based on object type
            // tile, smudge, overlay, terrain, unit/building, aircraft
            var priorities = new Dictionary <Type, int> {
                { typeof(MapTile), 0 },
                { typeof(SmudgeObject), 1 },
                { typeof(OverlayObject), 2 },
                { typeof(TerrainObject), 3 },
                { typeof(StructureObject), 3 },
                { typeof(AnimationObject), 3 },
                { typeof(UnitObject), 3 },
                { typeof(InfantryObject), 3 },
                { typeof(AircraftObject), 4 },
            };
            int prioA = priorities[objA.GetType()];
            int prioB = priorities[objB.GetType()];

            if (prioA > prioB)
            {
                return(objA);
            }
            else if (prioA < prioB)
            {
                return(objB);
            }

            // finally try the minimal y coordinate
            if (boxA.Bottom > boxB.Bottom)
            {
                return(objA);
            }
            else if (boxA.Bottom < boxB.Bottom)
            {
                return(objB);
            }

            // finally if nothing worked up to here, which is very unlikely,
            // we'll use a tie-breaker that is at least guaranteed to yield
            // the same result regardless of argument order
            return(objA.Id < objB.Id ? objA : objB);
        }