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