192 TRACK_BIT_ALL, |
190 TRACK_BIT_ALL, |
193 |
191 |
194 TRACK_BIT_Y | TRACK_BIT_UPPER | TRACK_BIT_RIGHT, |
192 TRACK_BIT_Y | TRACK_BIT_UPPER | TRACK_BIT_RIGHT, |
195 TRACK_BIT_ALL, |
193 TRACK_BIT_ALL, |
196 TRACK_BIT_ALL |
194 TRACK_BIT_ALL |
197 } |
|
198 }; |
195 }; |
199 |
196 |
|
197 /** |
|
198 * Checks if a track combination is valid on a specific slope and returns the needed foundation. |
|
199 * |
|
200 * @param tileh Tile slope. |
|
201 * @param bits Trackbits. |
|
202 * @return Needed foundation or FOUNDATION_INVALID if track/slope combination is not allowed. |
|
203 */ |
200 Foundation GetRailFoundation(Slope tileh, TrackBits bits) |
204 Foundation GetRailFoundation(Slope tileh, TrackBits bits) |
201 { |
205 { |
202 if (!IsSteepSlope(tileh)) { |
206 if (bits == TRACK_BIT_NONE) return FOUNDATION_NONE; |
203 if ((~_valid_tileh_slopes[0][tileh] & bits) == 0) return FOUNDATION_NONE; |
207 |
204 if ((~_valid_tileh_slopes[1][tileh] & bits) == 0) return FOUNDATION_LEVELED; |
208 if (IsSteepSlope(tileh)) { |
205 } |
209 /* Test for inclined foundations */ |
206 |
210 if (bits == TRACK_BIT_X) return FOUNDATION_INCLINED_X; |
207 switch (bits) { |
211 if (bits == TRACK_BIT_Y) return FOUNDATION_INCLINED_Y; |
208 default: NOT_REACHED(); |
212 |
209 case TRACK_BIT_X: return FOUNDATION_INCLINED_X; |
213 /* Get higher track */ |
210 case TRACK_BIT_Y: return FOUNDATION_INCLINED_Y; |
214 Corner highest_corner = GetHighestSlopeCorner(tileh); |
211 case TRACK_BIT_LEFT: return (tileh == SLOPE_STEEP_W ? FOUNDATION_STEEP_HIGHER : FOUNDATION_STEEP_LOWER); |
215 TrackBits higher_track = CornerToTrackBits(highest_corner); |
212 case TRACK_BIT_LOWER: return (tileh == SLOPE_STEEP_S ? FOUNDATION_STEEP_HIGHER : FOUNDATION_STEEP_LOWER); |
216 |
213 case TRACK_BIT_RIGHT: return (tileh == SLOPE_STEEP_E ? FOUNDATION_STEEP_HIGHER : FOUNDATION_STEEP_LOWER); |
217 /* Only higher track? */ |
214 case TRACK_BIT_UPPER: return (tileh == SLOPE_STEEP_N ? FOUNDATION_STEEP_HIGHER : FOUNDATION_STEEP_LOWER); |
218 if (bits == higher_track) return FOUNDATION_STEEP_HIGHER; |
215 } |
219 |
216 } |
220 /* Overlap with higher track? */ |
217 |
221 if (TracksOverlap(bits | higher_track)) return FOUNDATION_INVALID; |
218 |
222 |
|
223 /* either lower track or both higher and lower track */ |
|
224 return ((bits & higher_track) != 0 ? FOUNDATION_INVALID : FOUNDATION_STEEP_LOWER); |
|
225 } else { |
|
226 if ((~_valid_tracks_without_foundation[tileh] & bits) == 0) return FOUNDATION_NONE; |
|
227 |
|
228 bool valid_on_leveled = ((~_valid_tracks_on_leveled_foundation[tileh] & bits) == 0); |
|
229 |
|
230 switch (bits) { |
|
231 case TRACK_BIT_X: |
|
232 if (HasSlopeHighestCorner(tileh)) return FOUNDATION_INCLINED_X; |
|
233 return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID); |
|
234 |
|
235 case TRACK_BIT_Y: |
|
236 if (HasSlopeHighestCorner(tileh)) return FOUNDATION_INCLINED_Y; |
|
237 return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID); |
|
238 |
|
239 default: |
|
240 return (valid_on_leveled ? FOUNDATION_LEVELED : FOUNDATION_INVALID); |
|
241 } |
|
242 } |
|
243 } |
|
244 |
|
245 |
|
246 /** |
|
247 * Tests if a track can be build on a tile. |
|
248 * |
|
249 * @param tileh Tile slope. |
|
250 * @param rail_bits Tracks to build. |
|
251 * @param existing Tracks already built. |
|
252 * @param tile Tile (used for water test) |
|
253 * @return Error message or cost for foundation building. |
|
254 */ |
219 static CommandCost CheckRailSlope(Slope tileh, TrackBits rail_bits, TrackBits existing, TileIndex tile) |
255 static CommandCost CheckRailSlope(Slope tileh, TrackBits rail_bits, TrackBits existing, TileIndex tile) |
220 { |
256 { |
221 if (IsSteepSlope(tileh)) { |
257 /* don't allow building on the lower side of a coast */ |
222 if (_patches.build_on_slopes && existing == 0) { |
258 if (IsTileType(tile, MP_WATER)) { |
223 /* There may only be one track on steep slopes. (Autoslope calls with multiple bits in rail_bits) */ |
259 if (!IsSteepSlope(tileh) && ((~_valid_tracks_on_leveled_foundation[tileh] & (rail_bits | existing)) != 0)) return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER); |
224 if (KILL_FIRST_BIT(rail_bits & TRACK_BIT_MASK) == 0) { |
260 } |
225 TrackBits valid = TRACK_BIT_CROSS | (HASBIT(1 << SLOPE_STEEP_W | 1 << SLOPE_STEEP_E, tileh) ? TRACK_BIT_VERT : TRACK_BIT_HORZ); |
261 |
226 if (valid & rail_bits) return _price.terraform; |
262 Foundation f_new = GetRailFoundation(tileh, rail_bits | existing); |
227 } |
263 |
228 } |
264 /* check track/slope combination */ |
229 } else { |
265 if ((f_new == FOUNDATION_INVALID) || |
230 rail_bits |= existing; |
266 ((f_new != FOUNDATION_NONE) && (!_patches.build_on_slopes || _is_old_ai_player)) |
231 |
267 ) return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
232 /* don't allow building on the lower side of a coast */ |
268 |
233 if (IsTileType(tile, MP_WATER) && |
269 Foundation f_old = GetRailFoundation(tileh, existing); |
234 ~_valid_tileh_slopes[1][tileh] & rail_bits) { |
270 return CommandCost(f_new != f_old ? _price.terraform : 0); |
235 return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER); |
|
236 } |
|
237 |
|
238 /* no special foundation */ |
|
239 if ((~_valid_tileh_slopes[0][tileh] & rail_bits) == 0) { |
|
240 return CommandCost(); |
|
241 } else if (!_patches.build_on_slopes || _is_old_ai_player) { |
|
242 return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
|
243 } |
|
244 |
|
245 if ((~_valid_tileh_slopes[1][tileh] & rail_bits) == 0 || ( // whole tile is leveled up |
|
246 (rail_bits == TRACK_BIT_X || rail_bits == TRACK_BIT_Y) && |
|
247 (tileh == SLOPE_W || tileh == SLOPE_S || tileh == SLOPE_E || tileh == SLOPE_N) |
|
248 )) { // partly up |
|
249 return CommandCost((existing != 0) ? 0 : _price.terraform); |
|
250 } |
|
251 } |
|
252 return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
|
253 } |
271 } |
254 |
272 |
255 /* Validate functions for rail building */ |
273 /* Validate functions for rail building */ |
256 static inline bool ValParamTrackOrientation(Track track) {return IsValidTrack(track);} |
274 static inline bool ValParamTrackOrientation(Track track) {return IsValidTrack(track);} |
257 |
275 |