/** * Returns the reverse direction of the given DiagDirection * * @param d The DiagDirection to get the reverse from * @return The reverse direction */ //inline public static DiagDirection ReverseDiagDir(this DiagDirection d) { if (d.IsValidDiagDirection() == false) { throw new ArgumentOutOfRangeException(nameof(d)); } return((DiagDirection)(2 ^ (int)d)); }
/** * Convert a DiagDirection to the axis. * * This function returns the axis which belongs to the given * DiagDirection. The axis X belongs to the DiagDirection * north-east and south-west. * * @param d The DiagDirection * @return The axis which belongs to the direction */ //inline public static Axis DiagDirToAxis(this DiagDirection d) { if (d.IsValidDiagDirection() == false) { throw new ArgumentOutOfRangeException(nameof(d)); } return((Axis)((int)d & 1)); }
/** * Convert a DiagDirection to a TileIndexDiff * * @param dir The DiagDirection * @return The resulting TileIndexDiff * @see TileIndexDiffCByDiagDir */ //inline public static TileIndexDiff TileOffsByDiagDir(DiagDirection dir) { if (dir.IsValidDiagDirection() == false) { throw new ArgumentOutOfRangeException(nameof(dir)); } return(ToTileIndexDiff(_tileoffs_by_diagdir[(int)dir])); }
/** * Make the given tile a roadstop tile. * @param t the tile to make a roadstop * @param o the owner of the roadstop * @param sid the station to which this tile belongs * @param rst the type of roadstop to make this tile * @param rt the roadtypes on this tile * @param d the direction of the roadstop */ public static void MakeRoadStop(this TileIndex t, Owner o, StationID sid, RoadStopType rst, RoadTypes rt, DiagDirection d) { MakeStation(t, o, sid, (rst == RoadStopType.ROADSTOP_BUS ? StationType.STATION_BUS : StationType.STATION_TRUCK), d); t.SetRoadTypes(rt); t.SetRoadOwner(RoadType.ROADTYPE_ROAD, o); t.SetRoadOwner(RoadType.ROADTYPE_TRAM, o); }
/** * Convert a DiagDirection to a Direction. * * This function can be used to convert the 4-way DiagDirection * to the 8-way Direction. As 4-way are less than 8-way not all * possible directions can be calculated. * * @param dir The direction to convert * @return The resulting Direction */ //inline public static Direction DiagDirToDir(this DiagDirection dir) { if (dir.IsValidDiagDirection() == false) { throw new ArgumentOutOfRangeException(nameof(dir)); } return((Direction)((int)dir * 2 + 1)); ; }
/** * Applies a difference on a DiagDirection * * This function applies a difference on a DiagDirection and returns * the new DiagDirection. * * @param d The DiagDirection * @param delta The difference to apply on * @return The new direction which was calculated */ //inline public static DiagDirection ChangeDiagDir(this DiagDirection d, DiagDirDiff delta) { if (d.IsValidDiagDirection() == false) { throw new ArgumentOutOfRangeException(nameof(d)); } /* Cast to uint so compiler can use bitmask. Result can never be negative. */ return((DiagDirection)(((int)d + (int)delta) % 4)); }
/** * Make a water lock. * @param t Tile to place the water lock section. * @param o Owner of the lock. * @param d Direction of the water lock. * @param wc_lower Original water class of the lower part. * @param wc_upper Original water class of the upper part. * @param wc_middle Original water class of the middle part. */ /*inline*/ public static void MakeLock(TileIndex t, Owner o, DiagDirection d, WaterClass wc_lower, WaterClass wc_upper, WaterClass wc_middle) { TileIndexDiff delta = Map.TileOffsByDiagDir(d); /* Keep the current waterclass and owner for the tiles. * It allows to restore them after the lock is deleted */ MakeLockTile(t, o, LockPart.LOCK_PART_MIDDLE, d, wc_middle); MakeLockTile((uint)(t - delta), IsWaterTile((uint)(t - delta)) ? TileMap.GetTileOwner((uint)(t - delta)) : o, LockPart.LOCK_PART_LOWER, d, wc_lower); MakeLockTile((uint)(t + delta), IsWaterTile((uint)(t + delta)) ? TileMap.GetTileOwner((uint)(t + delta)) : o, LockPart.LOCK_PART_UPPER, d, wc_upper); }
/** * Makes a rail tunnel entrance * @param t the entrance of the tunnel * @param o the owner of the entrance * @param d the direction facing out of the tunnel * @param r the rail type used in the tunnel */ public static void MakeRailTunnel(this TileIndex t, Owner o, DiagDirection d, RailType r) { TileMap.SetTileType(t, TileType.MP_TUNNELBRIDGE); TileMap.SetTileOwner(t, o); Map._m[t].m2 = 0; Map._m[t].m3 = (byte)r; Map._m[t].m4 = 0; Map._m[t].m5 = (byte)((int)TransportType.TRANSPORT_RAIL << 2 | d); Map._me[t].m6 = BitMath.SB(Map._me[t].m6, 2, 4, 0); Map._me[t].m7 = 0; }
public static void MakeRailDepot(this TileIndex t, Owner o, DepotID did, DiagDirection d, RailType r) { TileMap.SetTileType(t, TileType.MP_RAILWAY); TileMap.SetTileOwner(t, o); Map._m[t].m2 = did; Map._m[t].m3 = (byte)r; Map._m[t].m4 = 0; Map._m[t].m5 = (byte)((int)RailTileType.RAIL_TILE_DEPOT << 6 | (int)d); BitMath.SB(Map._me[t].m6, 2, 4, 0); Map._me[t].m7 = 0; }
/** * Make a bridge ramp for roads. * @param t the tile to make a bridge ramp * @param o the new owner of the bridge ramp * @param owner_road the new owner of the road on the bridge * @param owner_tram the new owner of the tram on the bridge * @param bridgetype the type of bridge this bridge ramp belongs to * @param d the direction this ramp must be facing * @param r the road type of the bridge */ public static void MakeRoadBridgeRamp(TileIndex t, Owner o, Owner owner_road, Owner owner_tram, BridgeType bridgetype, DiagDirection d, RoadTypes r) { MakeBridgeRamp(t, o, bridgetype, d, TransportType.TRANSPORT_ROAD, 0); SetRoadOwner(t, RoadType.ROADTYPE_ROAD, owner_road); if (owner_tram != Owner.OWNER_TOWN) { SetRoadOwner(t, RoadType.ROADTYPE_TRAM, owner_tram); } SetRoadTypes(t, r); }
/** * Make a road depot. * @param t Tile to make a level crossing. * @param owner New owner of the depot. * @param did New depot ID. * @param dir Direction of the depot exit. * @param rt Road type of the depot. */ public static void MakeRoadDepot(this TileIndex t, Owner owner, DepotID did, DiagDirection dir, RoadType rt) { TileMap.SetTileType(t, TileType.MP_ROAD); TileMap.SetTileOwner(t, owner); Map._m[t].m2 = did; Map._m[t].m3 = 0; Map._m[t].m4 = 0; Map._m[t].m5 = RoadTileType.ROAD_TILE_DEPOT << 6 | dir; Map._me[t].m6 = BitMath.SB(Map._me[t].m6, 2, 4, 0); Map._me[t].m7 = RoadTypeToRoadTypes(rt) << 6 | owner; SetRoadOwner(t, RoadType.ROADTYPE_TRAM, owner); }
/** * Finds the end of a bridge in the specified direction starting at a middle tile * @param tile the bridge tile to find the bridge ramp for * @param dir the direction to search in */ public static TileIndex GetBridgeEnd(TileIndex tile, DiagDirection dir) { TileIndexDiff delta = Map.TileOffsByDiagDir(dir); dir = dir.ReverseDiagDir(); do { tile += (uint)delta.Difference; } while (!IsBridgeTile(tile) || GetTunnelBridgeDirection(tile) != dir); return(tile); }
/** * Calculate the difference between two DiagDirection values * * @param d0 The first direction as the base * @param d1 The second direction as the offset from the base * @return The difference how the second direction drifts of the first one. */ //inline public static DiagDirDiff DiagDirDifference(this DiagDirection d0, DiagDirection d1) { if (d0.IsValidDiagDirection() == false) { throw new ArgumentOutOfRangeException(nameof(d0)); } if (d1.IsValidDiagDirection() == false) { throw new ArgumentOutOfRangeException(nameof(d1)); } /* Cast to uint so compiler can use bitmask. Result can never be negative. */ return((DiagDirDiff)(((int)d0 - (int)d1) % 4)); }
/** * Is there a fence at the given border? * @param t the tile to check for fences * @param side the border to check * @pre IsClearGround(t, CLEAR_FIELDS) * @return 0 if there is no fence, otherwise the fence type */ public static uint GetFence(this TileIndex t, DiagDirection side) { Debug.Assert(IsClearGround(t, ClearGround.CLEAR_FIELDS)); switch (side) { default: throw new NotReachedException(); case DiagDirection.DIAGDIR_SE: return(BitMath.GB(Map._m[t].m4, 2, 3)); case DiagDirection.DIAGDIR_SW: return(BitMath.GB(Map._m[t].m4, 5, 3)); case DiagDirection.DIAGDIR_NE: return(BitMath.GB(Map._m[t].m3, 5, 3)); case DiagDirection.DIAGDIR_NW: return(BitMath.GB(Map._me[t].m6, 2, 3)); } }
/** * Makes a road tunnel entrance * @param t the entrance of the tunnel * @param o the owner of the entrance * @param d the direction facing out of the tunnel * @param r the road type used in the tunnel */ public static void MakeRoadTunnel(this TileIndex t, Owner o, DiagDirection d, RoadTypes r) { TileMap.SetTileType(t, TileType.MP_TUNNELBRIDGE); TileMap.SetTileOwner(t, o); Map._m[t].m2 = 0; Map._m[t].m3 = 0; Map._m[t].m4 = 0; Map._m[t].m5 = (byte)((int)TransportType.TRANSPORT_ROAD << 2 | (int)d); Map._me[t].m6 = BitMath.SB(Map._me[t].m6, 2, 4, 0); Map._me[t].m7 = 0; t.SetRoadOwner(RoadType.ROADTYPE_ROAD, o); if (o != Owner.OWNER_TOWN) { t.SetRoadOwner(RoadType.ROADTYPE_TRAM, o); } t.SetRoadTypes(r); }
/** * Is there a tunnel in the way in the given direction? * @param tile the tile to search from. * @param z the 'z' to search on. * @param dir the direction to start searching to. * @return true if and only if there is a tunnel. */ public static bool IsTunnelInWayDir(this TileIndex tile, int z, DiagDirection dir) { TileIndexDiff delta = TileOffsByDiagDir(dir); int height; do { tile -= delta; if (!TileMap.IsValidTile(tile)) { return(false); } height = TileMap.GetTileZ(tile); } while (z < height); return(z == height && IsTunnelTile(tile) && GetTunnelBridgeDirection(tile) == dir); }
/** * Make a lock section. * @param t Tile to place the water lock section. * @param o Owner of the lock. * @param part Part to place. * @param dir Lock orientation * @param original_water_class Original water class. * @see MakeLock */ /*inline*/ public static void MakeLockTile(TileIndex t, Owner o, LockPart part, DiagDirection dir, WaterClass original_water_class) { TileMap.SetTileType(t, TileType.MP_WATER); TileMap.SetTileOwner(t, o); SetWaterClass(t, original_water_class); Map._m[t].m2 = 0; Map._m[t].m3 = 0; Map._m[t].m4 = 0; Map._m[t].m5 = (byte) ((int)WaterTileTypeBitLayout.WBL_TYPE_LOCK << (int)WaterTileTypeBitLayout.WBL_TYPE_BEGIN | (int)part << (int)WaterTileTypeBitLayout.WBL_LOCK_PART_BEGIN | (int)dir << (int)WaterTileTypeBitLayout.WBL_LOCK_ORIENT_BEGIN); BitMath.SB(ref Map._me[t].m6, 2, 4, 0); Map._me[t].m7 = 0; }
/** * Gets the other end of the tunnel. Where a vehicle would reappear when it * enters at the given tile. * @param tile the tile to search from. * @return the tile of the other end of the tunnel. */ public static TileIndex GetOtherTunnelEnd(this TileIndex tile) { DiagDirection dir = GetTunnelBridgeDirection(tile); TileIndexDiff delta = TileOffsByDiagDir(dir); int z = TileMap.GetTileZ(tile); dir = ReverseDiagDir(dir); do { tile += delta; } while ( !IsTunnelTile(tile) || GetTunnelBridgeDirection(tile) != dir || TileMap.GetTileZ(tile) != z ); return(tile); }
/** * Gets the distance to the edge of the map in given direction. * @param tile the tile to get the distance from * @param dir the direction of interest * @return the distance from the edge in tiles */ public static uint DistanceFromEdgeDir(TileIndex tile, DiagDirection dir) { switch (dir) { case DiagDirection.DIAGDIR_NE: return((uint)(TileX(tile) - (_settings_game.construction.freeform_edges ? 1 : 0))); case DiagDirection.DIAGDIR_NW: return((uint)(TileY(tile) - (_settings_game.construction.freeform_edges ? 1 : 0))); case DiagDirection.DIAGDIR_SW: return(MapMaxX() - TileX(tile) - 1); case DiagDirection.DIAGDIR_SE: return(MapMaxY() - TileY(tile) - 1); default: throw new NotReachedException(); } }
/** * Sets the type of fence (and whether there is one) for the given border. * @param t the tile to check for fences * @param side the border to check * @param h 0 if there is no fence, otherwise the fence type * @pre IsClearGround(t, CLEAR_FIELDS) */ public static void SetFence(this TileIndex t, DiagDirection side, uint h) { Debug.Assert(IsClearGround(t, ClearGround.CLEAR_FIELDS)); switch (side) { default: throw new NotReachedException(); case DiagDirection.DIAGDIR_SE: Map._m[t].m4 = (byte)BitMath.SB(Map._m[t].m4, 2, 3, h); break; case DiagDirection.DIAGDIR_SW: Map._m[t].m4 = (byte)BitMath.SB(Map._m[t].m4, 5, 3, h); break; case DiagDirection.DIAGDIR_NE: Map._m[t].m3 = (byte)BitMath.SB(Map._m[t].m3, 5, 3, h); break; case DiagDirection.DIAGDIR_NW: Map._me[t].m6 = (byte)BitMath.SB(Map._me[t].m6, 2, 3, h); break; } }
/** * Checks if an integer value is a valid DiagDirection * * @param d The value to check * @return True if the value belongs to a DiagDirection, else false */ //inline //TODO Change to IsValid public static bool IsValidDiagDirection(this DiagDirection d) { return(d < DiagDirection.DIAGDIR_END); }
/** * Clean up unnecessary RoadBits of a planed tile. * @param tile current tile * @param org_rb planed RoadBits * @return optimised RoadBits */ RoadBits CleanUpRoadBits(TileIndex tile, RoadBits org_rb) { if (!TileMap.IsValidTile(tile)) { return(RoadBits.ROAD_NONE); } for (DiagDirection dir = DiagDirection.DIAGDIR_BEGIN; dir < DiagDirection.DIAGDIR_END; dir++) { TileIndex neighbor_tile = TileAddByDiagDir(tile, dir); /* Get the Roadbit pointing to the neighbor_tile */ RoadBits target_rb = DiagDirToRoadBits(dir); /* If the roadbit is in the current plan */ if (org_rb & target_rb) { bool connective = false; const RoadBits mirrored_rb = MirrorRoadBits(target_rb); if (TileMap.IsValidTile(neighbor_tile)) { switch (TileMap.GetTileType(neighbor_tile)) { /* Always connective ones */ case TileType.MP_CLEAR: case TileType.MP_TREES: connective = true; break; /* The conditionally connective ones */ case TileType.MP_TUNNELBRIDGE: case TileType.MP_STATION: case TileType.MP_ROAD: if (IsNormalRoadTile(neighbor_tile)) { /* Always connective */ connective = true; } else { const RoadBits neighbor_rb = GetAnyRoadBits(neighbor_tile, RoadType.ROADTYPE_ROAD) | GetAnyRoadBits(neighbor_tile, RoadType.ROADTYPE_TRAM); /* Accept only connective tiles */ connective = (neighbor_rb & mirrored_rb) != RoadBits.ROAD_NONE; } break; case TileType.MP_RAILWAY: connective = IsPossibleCrossing(neighbor_tile, DiagDirToAxis(dir)); break; case TileType.MP_WATER: /* Check for real water tile */ connective = !WaterMap.IsWater(neighbor_tile); break; /* The definitely not connective ones */ default: break; } } /* If the neighbor tile is inconnective, remove the planed road connection to it */ if (!connective) { org_rb ^= target_rb; } } } return(org_rb); }
/** * Make the given tile a dock tile. * @param t the tile to make a dock * @param o the owner of the dock * @param sid the station to which this tile belongs * @param d the direction of the dock * @param wc the type of water on this tile */ public static void MakeDock(this TileIndex t, Owner o, StationID sid, DiagDirection d, WaterClass wc) { MakeStation(t, o, sid, StationType.STATION_DOCK, d); MakeStation(t + Map.TileOffsByDiagDir(d), o, sid, StationType.STATION_DOCK, GFX_DOCK_BASE_WATER_PART + d.DiagDirToAxis(), wc); }
/** * Make a bridge ramp for aqueducts. * @param t the tile to make a bridge ramp * @param o the new owner of the bridge ramp * @param d the direction this ramp must be facing */ public static void MakeAqueductBridgeRamp(TileIndex t, Owner o, DiagDirection d) { MakeBridgeRamp(t, o, 0, d, TransportType.TRANSPORT_WATER, 0); }
/** * Make a bridge ramp for rails. * @param t the tile to make a bridge ramp * @param o the new owner of the bridge ramp * @param bridgetype the type of bridge this bridge ramp belongs to * @param d the direction this ramp must be facing * @param r the rail type of the bridge */ public static void MakeRailBridgeRamp(TileIndex t, Owner o, BridgeType bridgetype, DiagDirection d, RailType r) { MakeBridgeRamp(t, o, bridgetype, d, TransportType.TRANSPORT_RAIL, r); }
/** * Adds a DiagDir to a tile. * * @param tile The current tile * @param dir The direction in which we want to step * @return the moved tile */ //inline public static TileIndex TileAddByDiagDir(TileIndex tile, DiagDirection dir) { return(TILE_ADD(tile, (uint)TileOffsByDiagDir(dir).Difference)); }
/** * Generic part to make a bridge ramp for both roads and rails. * @param t the tile to make a bridge ramp * @param o the new owner of the bridge ramp * @param bridgetype the type of bridge this bridge ramp belongs to * @param d the direction this ramp must be facing * @param tt the transport type of the bridge * @param rt the road or rail type * @note this function should not be called directly. */ public static void MakeBridgeRamp(TileIndex t, Owner o, BridgeType bridgetype, DiagDirection d, TransportType tt, RailType rt) { TileMap.SetTileType(t, TileType.MP_TUNNELBRIDGE); TileMap.SetTileOwner(t, o); Map._m[t].m2 = 0; Map._m[t].m3 = (byte)rt; Map._m[t].m4 = 0; Map._m[t].m5 = (byte)(1 << 7 | (byte)tt << 2 | (byte)d); BitMath.SB(ref Map._me[t].m6, 2, 4, bridgetype); Map._me[t].m7 = 0; }