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); } } } }
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); }