unmovable_cmd.cpp

Go to the documentation of this file.
00001 /* $Id: unmovable_cmd.cpp 12199 2008-02-20 17:49:50Z frosch $ */
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; // reset HQ position
00052     InvalidateWindow(WC_COMPANY, pid);
00053   }
00054 
00055   /* cost of relocating company is 1% of company value */
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) { // Moving HQ
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       /* This should prevent statues from sinking into the ground when on a slope. */
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   /* checks if you're allowed to remove unmovable things */
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; // HQ level (depends on company performance) in the range 1..5.
00282 
00283   if (!IsCompanyHQ(tile)) return;
00284 
00285   /* HQ accepts passenger and mail; but we have to divide the values
00286    * between 4 tiles it occupies! */
00287 
00288   level = GetCompanyHQSize(tile) + 1;
00289 
00290   /* Top town building generates 10, so to make HQ interesting, the top
00291    * type makes 20. */
00292   ac[CT_PASSENGERS] = max(1U, level);
00293 
00294   /* Top town building generates 4, HQ can make up to 8. The
00295    * proportion passengers:mail is different because such a huge
00296    * commercial building generates unusually high amount of mail
00297    * correspondence per physical visitor. */
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   /* not used */
00317 }
00318 
00319 static void TileLoop_Unmovable(TileIndex tile)
00320 {
00321   uint level; // HQ level (depends on company performance) in the range 1..5.
00322   uint32 r;
00323 
00324   if (!IsCompanyHQ(tile)) return;
00325 
00326   /* HQ accepts passenger and mail; but we have to divide the values
00327    * between 4 tiles it occupies! */
00328 
00329   level = GetCompanyHQSize(tile) + 1;
00330   assert(level < 6);
00331 
00332   r = Random();
00333   /* Top town buildings generate 250, so the top HQ type makes 256. */
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   /* Top town building generates 90, HQ can make up to 196. The
00341    * proportion passengers:mail is about the same as in the acceptance
00342    * equations. */
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 /* checks, if a radio tower is within a 9x9 tile square around tile */
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   /* add radio tower */
00385   i = ScaleByMapSize(1000);
00386   j = ScaleByMapSize(15); // maximum number of radio towers on the map
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   /* add lighthouses */
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     /* Avoid infinite loops */
00414     if (++loop_count > 1000) break;
00415 
00416     r = Random();
00417 
00418     /* Scatter the lighthouses more evenly around the perimeter */
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       /* Transfer ownership to the new company */
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   /* Owned land remains unsold */
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,             /* draw_tile_proc */
00482   GetSlopeZ_Unmovable,            /* get_slope_z_proc */
00483   ClearTile_Unmovable,            /* clear_tile_proc */
00484   GetAcceptedCargo_Unmovable,     /* get_accepted_cargo_proc */
00485   GetTileDesc_Unmovable,          /* get_tile_desc_proc */
00486   GetTileTrackStatus_Unmovable,   /* get_tile_track_status_proc */
00487   ClickTile_Unmovable,            /* click_tile_proc */
00488   AnimateTile_Unmovable,          /* animate_tile_proc */
00489   TileLoop_Unmovable,             /* tile_loop_clear */
00490   ChangeTileOwner_Unmovable,      /* change_tile_owner_clear */
00491   NULL,                           /* get_produced_cargo_proc */
00492   NULL,                           /* vehicle_enter_tile_proc */
00493   GetFoundation_Unmovable,        /* get_foundation_proc */
00494   TerraformTile_Unmovable,        /* terraform_tile_proc */
00495 };

Generated on Mon Sep 22 20:34:20 2008 for openttd by  doxygen 1.5.6