unmovable_cmd.cpp

Go to the documentation of this file.
00001 /* $Id: unmovable_cmd.cpp 14812 2009-01-03 17:11:52Z smatz $ */
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; // reset HQ position
00055     InvalidateWindow(WC_COMPANY, cid);
00056   }
00057 
00058   /* cost of relocating company is 1% of company value */
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) { // Moving HQ
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       /* This should prevent statues from sinking into the ground when on a slope. */
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   /* checks if you're allowed to remove unmovable things */
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   /* HQ accepts passenger and mail; but we have to divide the values
00289    * between 4 tiles it occupies! */
00290 
00291   /* HQ level (depends on company performance) in the range 1..5. */
00292   uint level = GetCompanyHQSize(tile) + 1;
00293 
00294   /* Top town building generates 10, so to make HQ interesting, the top
00295    * type makes 20. */
00296   ac[CT_PASSENGERS] = max(1U, level);
00297 
00298   /* Top town building generates 4, HQ can make up to 8. The
00299    * proportion passengers:mail is different because such a huge
00300    * commercial building generates unusually high amount of mail
00301    * correspondence per physical visitor. */
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   /* not used */
00321 }
00322 
00323 static void TileLoop_Unmovable(TileIndex tile)
00324 {
00325   if (!IsCompanyHQ(tile)) return;
00326 
00327   /* HQ accepts passenger and mail; but we have to divide the values
00328    * between 4 tiles it occupies! */
00329 
00330   /* HQ level (depends on company performance) in the range 1..5. */
00331   uint level = GetCompanyHQSize(tile) + 1;
00332   assert(level < 6);
00333 
00334   uint r = Random();
00335   /* Top town buildings generate 250, so the top HQ type makes 256. */
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   /* Top town building generates 90, HQ can make up to 196. The
00343    * proportion passengers:mail is about the same as in the acceptance
00344    * equations. */
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 /* checks, if a radio tower is within a 9x9 tile square around tile */
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   /* add radio tower */
00384   int radiotowser_to_build = ScaleByMapSize(15); // maximum number of radio towers on the map
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   /* add lighthouses */
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     /* Scatter the lighthouses more evenly around the perimeter */
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       /* Transfer ownership to the new company */
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   /* Owned land remains unsold */
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,             /* draw_tile_proc */
00477   GetSlopeZ_Unmovable,            /* get_slope_z_proc */
00478   ClearTile_Unmovable,            /* clear_tile_proc */
00479   GetAcceptedCargo_Unmovable,     /* get_accepted_cargo_proc */
00480   GetTileDesc_Unmovable,          /* get_tile_desc_proc */
00481   GetTileTrackStatus_Unmovable,   /* get_tile_track_status_proc */
00482   ClickTile_Unmovable,            /* click_tile_proc */
00483   AnimateTile_Unmovable,          /* animate_tile_proc */
00484   TileLoop_Unmovable,             /* tile_loop_clear */
00485   ChangeTileOwner_Unmovable,      /* change_tile_owner_clear */
00486   NULL,                           /* get_produced_cargo_proc */
00487   NULL,                           /* vehicle_enter_tile_proc */
00488   GetFoundation_Unmovable,        /* get_foundation_proc */
00489   TerraformTile_Unmovable,        /* terraform_tile_proc */
00490 };

Generated on Fri Jan 9 19:01:53 2009 for openttd by  doxygen 1.5.6