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