# bridge_gui.cpp

Go to the documentation of this file.

    00001 /* $Id: bridge_gui.cpp 12136 2008-02-14 03:10:22Z belugas $ */
    00002
    00005 #include "stdafx.h"
    00006 #include "openttd.h"
    00007 #include "gui.h"
    00008 #include "window_gui.h"
    00009 #include "command_func.h"
    00010 #include "economy_func.h"
    00011 #include "variables.h"
    00012 #include "bridge.h"
    00013 #include "strings_func.h"
    00014 #include "window_func.h"
    00015 #include "sound_func.h"
    00016 #include "map_func.h"
    00017 #include "viewport_func.h"
    00018 #include "gfx_func.h"
    00019 #include "tunnelbridge.h"
    00020
    00021 #include "table/strings.h"
    00022
    00023 static struct BridgeData {
    00024   uint8 last_size;
    00025   uint count;
    00026   TileIndex start_tile;
    00027   TileIndex end_tile;
    00028   uint32 type;
    00029   BridgeType indexes[MAX_BRIDGES];
    00030   Money costs[MAX_BRIDGES];
    00031
    00032   BridgeData()
    00033     : last_size(4)
    00034     , count(0)
    00035     {};
    00036 } _bridgedata;
    00037
    00038 void CcBuildBridge(bool success, TileIndex tile, uint32 p1, uint32 p2)
    00039 {
    00040   if (success) SndPlayTileFx(SND_27_BLACKSMITH_ANVIL, tile);
    00041 }
    00042
    00043 static void BuildBridge(Window *w, int i)
    00044 {
    00045   DeleteWindow(w);
    00046   DoCommandP(_bridgedata.end_tile, _bridgedata.start_tile,
    00047     _bridgedata.type | _bridgedata.indexes[i], CcBuildBridge,
    00048     CMD_BUILD_BRIDGE | CMD_MSG(STR_5015_CAN_T_BUILD_BRIDGE_HERE));
    00049 }
    00050
    00051 /* Names of the build bridge selection window */
    00052 enum BuildBridgeSelectionWidgets {
    00053   BBSW_CLOSEBOX = 0,
    00054   BBSW_CAPTION,
    00055   BBSW_BRIDGE_LIST,
    00056   BBSW_SCROLLBAR,
    00057   BBSW_RESIZEBOX
    00058 };
    00059
    00060 static void BuildBridgeWndProc(Window *w, WindowEvent *e)
    00061 {
    00062   switch (e->event) {
    00063     case WE_CREATE:
    00064       w->resize.step_height = 22;
    00065       w->vscroll.count = _bridgedata.count;
    00066
    00067       if (_bridgedata.last_size <= 4) {
    00068         w->vscroll.cap = 4;
    00069       } else {
    00070         /* Resize the bridge selection window if we used a bigger one the last time */
    00071         w->vscroll.cap = (w->vscroll.count > _bridgedata.last_size) ? _bridgedata.last_size : w->vscroll.count;
    00072         ResizeWindow(w, 0, (w->vscroll.cap - 4) * w->resize.step_height);
    00073         w->widget[BBSW_BRIDGE_LIST].data = (w->vscroll.cap << 8) + 1;
    00074       }
    00075       break;
    00076
    00077     case WE_PAINT: {
    00078       DrawWindowWidgets(w);
    00079
    00080       uint y = 15;
    00081       for (uint i = 0; (i < w->vscroll.cap) && ((i + w->vscroll.pos) < _bridgedata.count); i++) {
    00082         const BridgeSpec *b = GetBridgeSpec(_bridgedata.indexes[i + w->vscroll.pos]);
    00083
    00084         SetDParam(2, _bridgedata.costs[i + w->vscroll.pos]);
    00085         SetDParam(1, b->speed * 10 / 16);
    00086         SetDParam(0, b->material);
    00087
    00088         DrawSprite(b->sprite, b->pal, 3, y);
    00089         DrawString(44, y, STR_500D, TC_FROMSTRING);
    00090         y += w->resize.step_height;
    00091       }
    00092       break;
    00093     }
    00094
    00095     case WE_KEYPRESS: {
    00096       const uint8 i = e->we.keypress.keycode - '1';
    00097       if (i < 9 && i < _bridgedata.count) {
    00098         e->we.keypress.cont = false;
    00099         BuildBridge(w, i);
    00100       }
    00101
    00102       break;
    00103     }
    00104
    00105     case WE_CLICK:
    00106       if (e->we.click.widget == BBSW_BRIDGE_LIST) {
    00107         uint ind = ((int)e->we.click.pt.y - 14) / w->resize.step_height;
    00108         if (ind < w->vscroll.cap) {
    00109           ind += w->vscroll.pos;
    00110           if (ind < _bridgedata.count) {
    00111             BuildBridge(w, ind);
    00112           }
    00113         }
    00114       }
    00115       break;
    00116
    00117     case WE_RESIZE:
    00118       w->vscroll.cap += e->we.sizing.diff.y / (int)w->resize.step_height;
    00119       w->widget[BBSW_BRIDGE_LIST].data = (w->vscroll.cap << 8) + 1;
    00120       SetVScrollCount(w, _bridgedata.count);
    00121
    00122       _bridgedata.last_size = w->vscroll.cap;
    00123       break;
    00124   }
    00125 }
    00126
    00127 /* Widget definition for the rail bridge selection window */
    00128 static const Widget _build_bridge_widgets[] = {
    00129 {   WWT_CLOSEBOX,   RESIZE_NONE,  7,   0,  10,   0,  13, STR_00C5,                    STR_018B_CLOSE_WINDOW},            // BBSW_CLOSEBOX
    00130 {    WWT_CAPTION,   RESIZE_NONE,  7,  11, 199,   0,  13, STR_100D_SELECT_RAIL_BRIDGE, STR_018C_WINDOW_TITLE_DRAG_THIS},  // BBSW_CAPTION
    00131 {     WWT_MATRIX, RESIZE_BOTTOM,  7,   0, 187,  14, 101, 0x401,                       STR_101F_BRIDGE_SELECTION_CLICK},  // BBSW_BRIDGE_LIST
    00132 {  WWT_SCROLLBAR, RESIZE_BOTTOM,  7, 188, 199,  14,  89, 0x0,                         STR_0190_SCROLL_BAR_SCROLLS_LIST}, // BBSW_SCROLLBAR
    00133 {  WWT_RESIZEBOX,     RESIZE_TB,  7, 188, 199,  90, 101, 0x0,                         STR_RESIZE_BUTTON},                // BBSW_RESIZEBOX
    00134 {   WIDGETS_END},
    00135 };
    00136
    00137 /* Window definition for the rail bridge selection window */
    00138 static const WindowDesc _build_bridge_desc = {
    00139   WDP_AUTO, WDP_AUTO, 200, 102, 200, 102,
    00140   WC_BUILD_BRIDGE, WC_BUILD_TOOLBAR,
    00141   WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_RESIZABLE,
    00142   _build_bridge_widgets,
    00143   BuildBridgeWndProc
    00144 };
    00145
    00146 void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transport_type, byte bridge_type)
    00147 {
    00148   DeleteWindowById(WC_BUILD_BRIDGE, 0);
    00149
    00150   _bridgedata.type = (transport_type << 15) | (bridge_type << 8); //prepare the parameter for use only once
    00151   _bridgedata.start_tile = start;
    00152   _bridgedata.end_tile = end;
    00153
    00154   /* only query bridge building possibility once, result is the same for all bridges!
    00155    * returns CMD_ERROR on failure, and price on success */
    00156   StringID errmsg = INVALID_STRING_ID;
    00157   CommandCost ret = DoCommand(end, start, _bridgedata.type, DC_AUTO | DC_QUERY_COST, CMD_BUILD_BRIDGE);
    00158
    00159   uint8 j = 0;
    00160   if (CmdFailed(ret)) {
    00161     errmsg = _error_message;
    00162   } else {
    00163     /* check which bridges can be built
    00164      * get absolute bridge length
    00165      * length of the middle parts of the bridge */
    00166     const uint bridge_len = GetTunnelBridgeLength(start, end);
    00167     /* total length of bridge */
    00168     const uint tot_bridgedata_len = CalcBridgeLenCostFactor(bridge_len + 2);
    00169
    00170     /* loop for all bridgetypes */
    00171     for (BridgeType brd_type = 0; brd_type != MAX_BRIDGES; brd_type++) {
    00172       if (CheckBridge_Stuff(brd_type, bridge_len)) {
    00173         /* bridge is accepted, add to list */
    00174         const BridgeSpec *b = GetBridgeSpec(brd_type);
    00175         /* Add to terraforming & bulldozing costs the cost of the
    00176          * bridge itself (not computed with DC_QUERY_COST) */
    00177         _bridgedata.costs[j] = ret.GetCost() + (((int64)tot_bridgedata_len * _price.build_bridge * b->price) >> 8);
    00178         _bridgedata.indexes[j] = brd_type;
    00179         j++;
    00180       }
    00181     }
    00182
    00183     _bridgedata.count = j;
    00184   }
    00185
    00186   if (j != 0) {
    00187     Window *w = AllocateWindowDesc(&_build_bridge_desc);
    00188     /* Change the data, or the caption of the gui. Set it to road or rail, accordingly */
    00189     w->widget[BBSW_CAPTION].data = (transport_type == TRANSPORT_ROAD) ? STR_1803_SELECT_ROAD_BRIDGE : STR_100D_SELECT_RAIL_BRIDGE;
    00190   } else {
    00191     ShowErrorMessage(errmsg, STR_5015_CAN_T_BUILD_BRIDGE_HERE, TileX(end) * TILE_SIZE, TileY(end) * TILE_SIZE);
    00192   }
    00193 }