00001
00002
00005 #include "stdafx.h"
00006 #include "openttd.h"
00007 #include "landscape.h"
00008 #include "command_func.h"
00009 #include "viewport_func.h"
00010 #include "company_base.h"
00011 #include "town.h"
00012 #include "sprite.h"
00013 #include "bridge_map.h"
00014 #include "unmovable_map.h"
00015 #include "genworld.h"
00016 #include "autoslope.h"
00017 #include "transparency.h"
00018 #include "functions.h"
00019 #include "window_func.h"
00020 #include "vehicle_func.h"
00021 #include "company_gui.h"
00022 #include "economy_func.h"
00023 #include "cheat_type.h"
00024 #include "landscape_type.h"
00025 #include "unmovable.h"
00026
00027 #include "table/strings.h"
00028 #include "table/sprites.h"
00029 #include "table/unmovable_land.h"
00030
00039 static inline const UnmovableSpec *GetUnmovableSpec(UnmovableType type)
00040 {
00041 assert(type < UNMOVABLE_MAX);
00042 return &_original_unmovable[type];
00043 }
00044
00052 static CommandCost DestroyCompanyHQ(CompanyID cid, DoCommandFlag flags)
00053 {
00054 Company *c = GetCompany(cid);
00055
00056 if (flags & DC_EXEC) {
00057 TileIndex t = c->location_of_HQ;
00058
00059 DoClearSquare(t);
00060 DoClearSquare(t + TileDiffXY(0, 1));
00061 DoClearSquare(t + TileDiffXY(1, 0));
00062 DoClearSquare(t + TileDiffXY(1, 1));
00063 c->location_of_HQ = INVALID_TILE;
00064 InvalidateWindow(WC_COMPANY, cid);
00065 }
00066
00067
00068 return CommandCost(EXPENSES_PROPERTY, CalculateCompanyValue(c) / 100);
00069 }
00070
00071 void UpdateCompanyHQ(Company *c, uint score)
00072 {
00073 byte val;
00074 TileIndex tile = c->location_of_HQ;
00075
00076 if (tile == INVALID_TILE) return;
00077
00078 (val = 0, score < 170) ||
00079 (val++, score < 350) ||
00080 (val++, score < 520) ||
00081 (val++, score < 720) ||
00082 (val++, true);
00083
00084 EnlargeCompanyHQ(tile, val);
00085
00086 MarkTileDirtyByTile(tile);
00087 MarkTileDirtyByTile(tile + TileDiffXY(0, 1));
00088 MarkTileDirtyByTile(tile + TileDiffXY(1, 0));
00089 MarkTileDirtyByTile(tile + TileDiffXY(1, 1));
00090 }
00091
00092 extern CommandCost CheckFlatLandBelow(TileIndex tile, uint w, uint h, DoCommandFlag flags, uint invalid_dirs, StationID *station, bool check_clear = true);
00093
00100 CommandCost CmdBuildCompanyHQ(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00101 {
00102 Company *c = GetCompany(_current_company);
00103 CommandCost cost(EXPENSES_PROPERTY);
00104
00105 cost = CheckFlatLandBelow(tile, 2, 2, flags, 0, NULL);
00106 if (CmdFailed(cost)) return cost;
00107
00108 if (c->location_of_HQ != INVALID_TILE) {
00109 cost.AddCost(DestroyCompanyHQ(_current_company, flags));
00110 }
00111
00112 if (flags & DC_EXEC) {
00113 int score = UpdateCompanyRatingAndValue(c, false);
00114
00115 c->location_of_HQ = tile;
00116
00117 MakeCompanyHQ(tile, _current_company);
00118
00119 UpdateCompanyHQ(c, score);
00120 InvalidateWindow(WC_COMPANY, c->index);
00121 }
00122
00123 return cost;
00124 }
00125
00134 CommandCost CmdPurchaseLandArea(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00135 {
00136 CommandCost cost(EXPENSES_CONSTRUCTION);
00137
00138 if (IsOwnedLandTile(tile) && IsTileOwner(tile, _current_company)) {
00139 return_cmd_error(STR_5807_YOU_ALREADY_OWN_IT);
00140 }
00141
00142 cost = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
00143 if (CmdFailed(cost)) return CMD_ERROR;
00144
00145 if (flags & DC_EXEC) {
00146 MakeOwnedLand(tile, _current_company);
00147 MarkTileDirtyByTile(tile);
00148 }
00149
00150 return cost.AddCost(GetUnmovableSpec(UNMOVABLE_OWNED_LAND)->GetBuildingCost());
00151 }
00152
00161 CommandCost CmdSellLandArea(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00162 {
00163 if (!IsOwnedLandTile(tile)) return CMD_ERROR;
00164 if (!CheckTileOwnership(tile) && _current_company != OWNER_WATER) return CMD_ERROR;
00165
00166 if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
00167
00168 if (flags & DC_EXEC) DoClearSquare(tile);
00169
00170 return CommandCost(EXPENSES_CONSTRUCTION, - GetUnmovableSpec(UNMOVABLE_OWNED_LAND)->GetRemovalCost());
00171 }
00172
00173 static Foundation GetFoundation_Unmovable(TileIndex tile, Slope tileh);
00174
00175 static void DrawTile_Unmovable(TileInfo *ti)
00176 {
00177
00178 switch (GetUnmovableType(ti->tile)) {
00179 default: NOT_REACHED(); break;
00180 case UNMOVABLE_TRANSMITTER:
00181 case UNMOVABLE_LIGHTHOUSE: {
00182 const DrawTileSeqStruct *dtu = &_draw_tile_transmitterlighthouse_data[GetUnmovableType(ti->tile)];
00183
00184 if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, FOUNDATION_LEVELED);
00185 DrawClearLandTile(ti, 2);
00186
00187 if (IsInvisibilitySet(TO_STRUCTURES)) break;
00188
00189 AddSortableSpriteToDraw(
00190 dtu->image.sprite, PAL_NONE, ti->x | dtu->delta_x, ti->y | dtu->delta_y,
00191 dtu->size_x, dtu->size_y, dtu->size_z, ti->z,
00192 IsTransparencySet(TO_STRUCTURES)
00193 );
00194 break;
00195 }
00196
00197 case UNMOVABLE_STATUE:
00198
00199 if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, GetFoundation_Unmovable(ti->tile, ti->tileh));
00200
00201 DrawGroundSprite(SPR_CONCRETE_GROUND, PAL_NONE);
00202
00203 if (IsInvisibilitySet(TO_STRUCTURES)) break;
00204
00205 AddSortableSpriteToDraw(SPR_STATUE_COMPANY, COMPANY_SPRITE_COLOUR(GetTileOwner(ti->tile)), ti->x, ti->y, 16, 16, 25, ti->z, IsTransparencySet(TO_STRUCTURES));
00206 break;
00207
00208 case UNMOVABLE_OWNED_LAND:
00209 DrawClearLandTile(ti, 0);
00210
00211 AddSortableSpriteToDraw(
00212 SPR_BOUGHT_LAND, COMPANY_SPRITE_COLOUR(GetTileOwner(ti->tile)),
00213 ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2, 1, 1, BB_HEIGHT_UNDER_BRIDGE, GetSlopeZ(ti->x + TILE_SIZE / 2, ti->y + TILE_SIZE / 2)
00214 );
00215 DrawBridgeMiddle(ti);
00216 break;
00217
00218 case UNMOVABLE_HQ:{
00219 assert(IsCompanyHQ(ti->tile));
00220 if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, FOUNDATION_LEVELED);
00221
00222 SpriteID palette = COMPANY_SPRITE_COLOUR(GetTileOwner(ti->tile));
00223
00224 const DrawTileSprites *t = &_unmovable_display_datas[GetCompanyHQSize(ti->tile) << 2 | GetCompanyHQSection(ti->tile)];
00225 DrawGroundSprite(t->ground.sprite, palette);
00226
00227 if (IsInvisibilitySet(TO_STRUCTURES)) break;
00228
00229 const DrawTileSeqStruct *dtss;
00230 foreach_draw_tile_seq(dtss, t->seq) {
00231 AddSortableSpriteToDraw(
00232 dtss->image.sprite, palette,
00233 ti->x + dtss->delta_x, ti->y + dtss->delta_y,
00234 dtss->size_x, dtss->size_y,
00235 dtss->size_z, ti->z + dtss->delta_z,
00236 IsTransparencySet(TO_STRUCTURES)
00237 );
00238 }
00239 break;
00240 }
00241 }
00242 }
00243
00244 static uint GetSlopeZ_Unmovable(TileIndex tile, uint x, uint y)
00245 {
00246 if (IsOwnedLand(tile)) {
00247 uint z;
00248 Slope tileh = GetTileSlope(tile, &z);
00249
00250 return z + GetPartialZ(x & 0xF, y & 0xF, tileh);
00251 } else {
00252 return GetTileMaxZ(tile);
00253 }
00254 }
00255
00256 static Foundation GetFoundation_Unmovable(TileIndex tile, Slope tileh)
00257 {
00258 return IsOwnedLand(tile) ? FOUNDATION_NONE : FlatteningFoundation(tileh);
00259 }
00260
00261 static CommandCost ClearTile_Unmovable(TileIndex tile, DoCommandFlag flags)
00262 {
00263 if (IsCompanyHQ(tile)) {
00264 if (_current_company == OWNER_WATER) {
00265 return DestroyCompanyHQ(GetTileOwner(tile), DC_EXEC);
00266 } else {
00267 return_cmd_error(STR_5804_COMPANY_HEADQUARTERS_IN);
00268 }
00269 }
00270
00271 if (IsOwnedLand(tile)) {
00272 return DoCommand(tile, 0, 0, flags, CMD_SELL_LAND_AREA);
00273 }
00274
00275
00276 if (_game_mode != GM_EDITOR && _current_company != OWNER_WATER && ((flags & DC_AUTO || !_cheats.magic_bulldozer.value)) )
00277 return_cmd_error(STR_5800_OBJECT_IN_THE_WAY);
00278
00279 if (IsStatue(tile)) {
00280 if (flags & DC_AUTO) return_cmd_error(STR_5800_OBJECT_IN_THE_WAY);
00281
00282 TownID town = GetStatueTownID(tile);
00283 ClrBit(GetTown(town)->statues, GetTileOwner(tile));
00284 InvalidateWindow(WC_TOWN_AUTHORITY, town);
00285 }
00286
00287 if (flags & DC_EXEC) {
00288 DoClearSquare(tile);
00289 }
00290
00291 return CommandCost();
00292 }
00293
00294 static void GetAcceptedCargo_Unmovable(TileIndex tile, AcceptedCargo ac)
00295 {
00296 if (!IsCompanyHQ(tile)) return;
00297
00298
00299
00300
00301
00302 uint level = GetCompanyHQSize(tile) + 1;
00303
00304
00305
00306 ac[CT_PASSENGERS] = max(1U, level);
00307
00308
00309
00310
00311
00312 ac[CT_MAIL] = max(1U, level / 2);
00313 }
00314
00315
00316 static void GetTileDesc_Unmovable(TileIndex tile, TileDesc *td)
00317 {
00318 td->str = GetUnmovableSpec(GetUnmovableType(tile))->name;
00319 td->owner[0] = GetTileOwner(tile);
00320 }
00321
00322 static void AnimateTile_Unmovable(TileIndex tile)
00323 {
00324
00325 }
00326
00327 static void TileLoop_Unmovable(TileIndex tile)
00328 {
00329 if (!IsCompanyHQ(tile)) return;
00330
00331
00332
00333
00334
00335 uint level = GetCompanyHQSize(tile) + 1;
00336 assert(level < 6);
00337
00338 uint r = Random();
00339
00340 if (GB(r, 0, 8) < (256 / 4 / (6 - level))) {
00341 uint amt = GB(r, 0, 8) / 8 / 4 + 1;
00342 if (_economy.fluct <= 0) amt = (amt + 1) >> 1;
00343 MoveGoodsToStation(tile, 2, 2, CT_PASSENGERS, amt);
00344 }
00345
00346
00347
00348
00349 if (GB(r, 8, 8) < (196 / 4 / (6 - level))) {
00350 uint amt = GB(r, 8, 8) / 8 / 4 + 1;
00351 if (_economy.fluct <= 0) amt = (amt + 1) >> 1;
00352 MoveGoodsToStation(tile, 2, 2, CT_MAIL, amt);
00353 }
00354 }
00355
00356
00357 static TrackStatus GetTileTrackStatus_Unmovable(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
00358 {
00359 return 0;
00360 }
00361
00362 static bool ClickTile_Unmovable(TileIndex tile)
00363 {
00364 if (!IsCompanyHQ(tile)) return false;
00365
00366 ShowCompany(GetTileOwner(tile));
00367 return true;
00368 }
00369
00370
00371
00372 static bool IsRadioTowerNearby(TileIndex tile)
00373 {
00374 TileIndex tile_s = tile - TileDiffXY(min(TileX(tile), 4U), min(TileY(tile), 4U));
00375 uint w = min(TileX(tile), 4U) + 1 + min(MapMaxX() - TileX(tile), 4U);
00376 uint h = min(TileY(tile), 4U) + 1 + min(MapMaxY() - TileY(tile), 4U);
00377
00378 BEGIN_TILE_LOOP(tile, w, h, tile_s)
00379 if (IsTransmitterTile(tile)) return true;
00380 END_TILE_LOOP(tile, w, h, tile_s)
00381
00382 return false;
00383 }
00384
00385 void GenerateUnmovables()
00386 {
00387 if (_settings_game.game_creation.landscape == LT_TOYLAND) return;
00388
00389
00390 int radiotower_to_build = ScaleByMapSize(15);
00391 int lighthouses_to_build = _settings_game.game_creation.landscape == LT_TROPIC ? 0 : ScaleByMapSize1D((Random() & 3) + 7);
00392
00393
00394 if (_settings_game.construction.freeform_edges && lighthouses_to_build != 0) {
00395 uint num_water_tiles = 0;
00396 for (uint x = 0; x < MapMaxX(); x++) {
00397 if (IsTileType(TileXY(x, 1), MP_WATER)) num_water_tiles++;
00398 if (IsTileType(TileXY(x, MapMaxY() - 1), MP_WATER)) num_water_tiles++;
00399 }
00400 for (uint y = 1; y < MapMaxY() - 1; y++) {
00401 if (IsTileType(TileXY(1, y), MP_WATER)) num_water_tiles++;
00402 if (IsTileType(TileXY(MapMaxX() - 1, y), MP_WATER)) num_water_tiles++;
00403 }
00404
00405
00406 lighthouses_to_build = lighthouses_to_build * num_water_tiles / (2 * MapMaxY() + 2 * MapMaxX() - 6);
00407 }
00408
00409 SetGeneratingWorldProgress(GWP_UNMOVABLE, radiotower_to_build + lighthouses_to_build);
00410
00411 for (uint i = ScaleByMapSize(1000); i != 0; i--) {
00412 TileIndex tile = RandomTile();
00413
00414 uint h;
00415 if (IsTileType(tile, MP_CLEAR) && GetTileSlope(tile, &h) == SLOPE_FLAT && h >= TILE_HEIGHT * 4 && !IsBridgeAbove(tile)) {
00416 if (IsRadioTowerNearby(tile)) continue;
00417
00418 MakeTransmitter(tile);
00419 IncreaseGeneratingWorldProgress(GWP_UNMOVABLE);
00420 if (--radiotower_to_build == 0) break;
00421 }
00422 }
00423
00424
00425 uint maxx = MapMaxX();
00426 uint maxy = MapMaxY();
00427 for (int loop_count = 0; loop_count < 1000 && lighthouses_to_build != 0; loop_count++) {
00428 uint r = Random();
00429
00430
00431 int perimeter = (GB(r, 16, 16) % (2 * (maxx + maxy))) - maxy;
00432 DiagDirection dir;
00433 for (dir = DIAGDIR_NE; perimeter > 0; dir++) {
00434 perimeter -= (DiagDirToAxis(dir) == AXIS_X) ? maxx : maxy;
00435 }
00436
00437 TileIndex tile;
00438 switch (dir) {
00439 default:
00440 case DIAGDIR_NE: tile = TileXY(maxx - 1, r % maxy); break;
00441 case DIAGDIR_SE: tile = TileXY(r % maxx, 1); break;
00442 case DIAGDIR_SW: tile = TileXY(1, r % maxy); break;
00443 case DIAGDIR_NW: tile = TileXY(r % maxx, maxy - 1); break;
00444 }
00445
00446
00447 if (!IsTileType(tile, MP_WATER)) continue;
00448
00449 for (int j = 0; j < 19; j++) {
00450 uint h;
00451 if (IsTileType(tile, MP_CLEAR) && GetTileSlope(tile, &h) == SLOPE_FLAT && h <= TILE_HEIGHT * 2 && !IsBridgeAbove(tile)) {
00452 MakeLighthouse(tile);
00453 IncreaseGeneratingWorldProgress(GWP_UNMOVABLE);
00454 lighthouses_to_build--;
00455 assert(tile == TILE_MASK(tile));
00456 break;
00457 }
00458 tile = TILE_MASK(tile + TileOffsByDiagDir(dir));
00459 }
00460 }
00461 }
00462
00463 static void ChangeTileOwner_Unmovable(TileIndex tile, Owner old_owner, Owner new_owner)
00464 {
00465 if (!IsTileOwner(tile, old_owner)) return;
00466
00467 if (IsOwnedLand(tile) && new_owner != INVALID_OWNER) {
00468 SetTileOwner(tile, new_owner);
00469 } else if (IsStatueTile(tile)) {
00470 TownID town = GetStatueTownID(tile);
00471 Town *t = GetTown(town);
00472 ClrBit(t->statues, old_owner);
00473 if (new_owner != INVALID_OWNER && !HasBit(t->statues, new_owner)) {
00474
00475 SetBit(t->statues, new_owner);
00476 SetTileOwner(tile, new_owner);
00477 } else {
00478 DoClearSquare(tile);
00479 }
00480
00481 InvalidateWindow(WC_TOWN_AUTHORITY, town);
00482 } else {
00483 DoClearSquare(tile);
00484 }
00485 }
00486
00487 static CommandCost TerraformTile_Unmovable(TileIndex tile, DoCommandFlag flags, uint z_new, Slope tileh_new)
00488 {
00489
00490 if (IsOwnedLand(tile) && CheckTileOwnership(tile)) return CommandCost();
00491
00492 if (AutoslopeEnabled() && (IsStatue(tile) || IsCompanyHQ(tile))) {
00493 if (!IsSteepSlope(tileh_new) && (z_new + GetSlopeMaxZ(tileh_new) == GetTileMaxZ(tile))) return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform);
00494 }
00495
00496 return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
00497 }
00498
00499 extern const TileTypeProcs _tile_type_unmovable_procs = {
00500 DrawTile_Unmovable,
00501 GetSlopeZ_Unmovable,
00502 ClearTile_Unmovable,
00503 GetAcceptedCargo_Unmovable,
00504 GetTileDesc_Unmovable,
00505 GetTileTrackStatus_Unmovable,
00506 ClickTile_Unmovable,
00507 AnimateTile_Unmovable,
00508 TileLoop_Unmovable,
00509 ChangeTileOwner_Unmovable,
00510 NULL,
00511 NULL,
00512 GetFoundation_Unmovable,
00513 TerraformTile_Unmovable,
00514 };