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 }

Generated on Wed Oct 1 17:03:20 2008 for openttd by  doxygen 1.5.6