tron@2186: /* $Id$ */ tron@2186: belugas@6443: /** @file bridge_gui.cpp Graphical user interface for bridge construction */ celestar@2262: truelight@0: #include "stdafx.h" Darkvater@1891: #include "openttd.h" truelight@0: #include "gui.h" rubidium@8603: #include "window_gui.h" rubidium@8612: #include "command_func.h" rubidium@8612: #include "economy_func.h" tron@2159: #include "variables.h" celestar@2262: #include "bridge.h" rubidium@8610: #include "strings_func.h" rubidium@8627: #include "window_func.h" rubidium@8653: #include "sound_func.h" rubidium@8635: #include "map_func.h" rubidium@8720: #include "viewport_func.h" rubidium@8720: #include "gfx_func.h" smatz@8894: #include "tunnelbridge.h" truelight@0: rubidium@8760: #include "table/strings.h" rubidium@8760: truelight@0: static struct BridgeData { skidd13@8516: uint8 last_size; tron@2133: uint count; truelight@0: TileIndex start_tile; truelight@0: TileIndex end_tile; belugas@9053: uint32 type; ///< Data type for the bridge. Bit 16,15 = transport type, 14..8 = road/rail pieces, 7..0 = type of bridge belugas@9028: BridgeType indexes[MAX_BRIDGES]; rubidium@7486: Money costs[MAX_BRIDGES]; skidd13@8516: skidd13@8516: BridgeData() skidd13@8516: : last_size(4) skidd13@8516: , count(0) skidd13@8516: {}; celestar@2262: } _bridgedata; truelight@0: tron@1977: void CcBuildBridge(bool success, TileIndex tile, uint32 p1, uint32 p2) truelight@0: { tron@541: if (success) SndPlayTileFx(SND_27_BLACKSMITH_ANVIL, tile); truelight@0: } truelight@0: truelight@0: static void BuildBridge(Window *w, int i) truelight@0: { truelight@0: DeleteWindow(w); tron@2639: DoCommandP(_bridgedata.end_tile, _bridgedata.start_tile, belugas@9053: _bridgedata.type | _bridgedata.indexes[i], CcBuildBridge, rubidium@8017: CMD_BUILD_BRIDGE | CMD_MSG(STR_5015_CAN_T_BUILD_BRIDGE_HERE)); truelight@0: } truelight@0: skidd13@8516: /* Names of the build bridge selection window */ skidd13@8516: enum BuildBridgeSelectionWidgets { skidd13@8516: BBSW_CLOSEBOX = 0, skidd13@8516: BBSW_CAPTION, skidd13@8516: BBSW_BRIDGE_LIST, skidd13@8516: BBSW_SCROLLBAR, skidd13@8516: BBSW_RESIZEBOX skidd13@8516: }; skidd13@8516: truelight@0: static void BuildBridgeWndProc(Window *w, WindowEvent *e) truelight@0: { tron@2952: switch (e->event) { skidd13@8516: case WE_CREATE: skidd13@8516: w->resize.step_height = 22; skidd13@8516: w->vscroll.count = _bridgedata.count; skidd13@8516: skidd13@8516: if (_bridgedata.last_size <= 4) { skidd13@8516: w->vscroll.cap = 4; skidd13@8516: } else { skidd13@8516: /* Resize the bridge selection window if we used a bigger one the last time */ skidd13@8516: w->vscroll.cap = (w->vscroll.count > _bridgedata.last_size) ? _bridgedata.last_size : w->vscroll.count; skidd13@8516: ResizeWindow(w, 0, (w->vscroll.cap - 4) * w->resize.step_height); skidd13@8516: w->widget[BBSW_BRIDGE_LIST].data = (w->vscroll.cap << 8) + 1; skidd13@8516: } skidd13@8516: break; skidd13@8516: skidd13@8479: case WE_PAINT: { peter1138@6530: DrawWindowWidgets(w); truelight@0: skidd13@8479: uint y = 15; skidd13@8479: for (uint i = 0; (i < w->vscroll.cap) && ((i + w->vscroll.pos) < _bridgedata.count); i++) { belugas@9031: const BridgeSpec *b = GetBridgeSpec(_bridgedata.indexes[i + w->vscroll.pos]); truelight@0: rubidium@7498: SetDParam(2, _bridgedata.costs[i + w->vscroll.pos]); peter1138@6530: SetDParam(1, b->speed * 10 / 16); peter1138@6530: SetDParam(0, b->material); truelight@0: skidd13@8479: DrawSprite(b->sprite, b->pal, 3, y); skidd13@8479: DrawString(44, y, STR_500D, TC_FROMSTRING); skidd13@8479: y += w->resize.step_height; peter1138@6530: } peter1138@6530: break; skidd13@8479: } peter1138@6530: peter1138@6530: case WE_KEYPRESS: { skidd13@8479: const uint8 i = e->we.keypress.keycode - '1'; peter1138@6530: if (i < 9 && i < _bridgedata.count) { peter1138@6530: e->we.keypress.cont = false; peter1138@6530: BuildBridge(w, i); peter1138@6530: } peter1138@6530: peter1138@6530: break; truelight@0: } truelight@193: peter1138@6530: case WE_CLICK: skidd13@8516: if (e->we.click.widget == BBSW_BRIDGE_LIST) { skidd13@8479: uint ind = ((int)e->we.click.pt.y - 14) / w->resize.step_height; skidd13@8479: if (ind < w->vscroll.cap) { skidd13@8479: ind += w->vscroll.pos; skidd13@8479: if (ind < _bridgedata.count) { skidd13@8479: BuildBridge(w, ind); skidd13@8479: } skidd13@8479: } peter1138@6530: } peter1138@6530: break; skidd13@8479: skidd13@8479: case WE_RESIZE: skidd13@8479: w->vscroll.cap += e->we.sizing.diff.y / (int)w->resize.step_height; skidd13@8516: w->widget[BBSW_BRIDGE_LIST].data = (w->vscroll.cap << 8) + 1; skidd13@8479: SetVScrollCount(w, _bridgedata.count); skidd13@8516: skidd13@8516: _bridgedata.last_size = w->vscroll.cap; skidd13@8479: break; truelight@0: } truelight@0: } truelight@0: skidd13@8516: /* Widget definition for the rail bridge selection window */ truelight@0: static const Widget _build_bridge_widgets[] = { skidd13@8516: { WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, // BBSW_CLOSEBOX skidd13@8516: { WWT_CAPTION, RESIZE_NONE, 7, 11, 199, 0, 13, STR_100D_SELECT_RAIL_BRIDGE, STR_018C_WINDOW_TITLE_DRAG_THIS}, // BBSW_CAPTION skidd13@8516: { WWT_MATRIX, RESIZE_BOTTOM, 7, 0, 187, 14, 101, 0x401, STR_101F_BRIDGE_SELECTION_CLICK}, // BBSW_BRIDGE_LIST skidd13@8516: { WWT_SCROLLBAR, RESIZE_BOTTOM, 7, 188, 199, 14, 89, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, // BBSW_SCROLLBAR skidd13@8516: { WWT_RESIZEBOX, RESIZE_TB, 7, 188, 199, 90, 101, 0x0, STR_RESIZE_BUTTON}, // BBSW_RESIZEBOX darkvater@176: { WIDGETS_END}, truelight@0: }; truelight@0: skidd13@8516: /* Window definition for the rail bridge selection window */ truelight@0: static const WindowDesc _build_bridge_desc = { rubidium@7837: WDP_AUTO, WDP_AUTO, 200, 102, 200, 102, Darkvater@5070: WC_BUILD_BRIDGE, WC_BUILD_TOOLBAR, skidd13@8479: WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_RESIZABLE, truelight@0: _build_bridge_widgets, truelight@0: BuildBridgeWndProc truelight@0: }; truelight@0: belugas@9053: void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transport_type, byte bridge_type) truelight@0: { truelight@0: DeleteWindowById(WC_BUILD_BRIDGE, 0); truelight@0: belugas@9054: _bridgedata.type = (transport_type << 15) | (bridge_type << 8); //prepare the parameter for use only once celestar@2262: _bridgedata.start_tile = start; celestar@2262: _bridgedata.end_tile = end; truelight@0: skidd13@8479: /* only query bridge building possibility once, result is the same for all bridges! skidd13@8479: * returns CMD_ERROR on failure, and price on success */ skidd13@8479: StringID errmsg = INVALID_STRING_ID; belugas@9053: CommandCost ret = DoCommand(end, start, _bridgedata.type, DC_AUTO | DC_QUERY_COST, CMD_BUILD_BRIDGE); truelight@0: skidd13@8479: uint8 j = 0; peter1138@2737: if (CmdFailed(ret)) { truelight@0: errmsg = _error_message; tron@2548: } else { skidd13@8479: /* check which bridges can be built skidd13@8479: * get absolute bridge length skidd13@8479: * length of the middle parts of the bridge */ smatz@8894: const uint bridge_len = GetTunnelBridgeLength(start, end); skidd13@8479: /* total length of bridge */ skidd13@8479: const uint tot_bridgedata_len = CalcBridgeLenCostFactor(bridge_len + 2); truelight@0: skidd13@8479: /* loop for all bridgetypes */ belugas@9028: for (BridgeType brd_type = 0; brd_type != MAX_BRIDGES; brd_type++) { belugas@9028: if (CheckBridge_Stuff(brd_type, bridge_len)) { skidd13@8479: /* bridge is accepted, add to list */ belugas@9031: const BridgeSpec *b = GetBridgeSpec(brd_type); skidd13@8479: /* Add to terraforming & bulldozing costs the cost of the skidd13@8479: * bridge itself (not computed with DC_QUERY_COST) */ rubidium@7446: _bridgedata.costs[j] = ret.GetCost() + (((int64)tot_bridgedata_len * _price.build_bridge * b->price) >> 8); belugas@9028: _bridgedata.indexes[j] = brd_type; truelight@0: j++; truelight@0: } truelight@0: } skidd13@8479: skidd13@8479: _bridgedata.count = j; truelight@0: } truelight@0: truelight@0: if (j != 0) { belugas@9053: Window *w = AllocateWindowDesc(&_build_bridge_desc); belugas@9053: /* Change the data, or the caption of the gui. Set it to road or rail, accordingly */ belugas@9053: w->widget[BBSW_CAPTION].data = (transport_type == TRANSPORT_ROAD) ? STR_1803_SELECT_ROAD_BRIDGE : STR_100D_SELECT_RAIL_BRIDGE; truelight@0: } else { celestar@3422: ShowErrorMessage(errmsg, STR_5015_CAN_T_BUILD_BRIDGE_HERE, TileX(end) * TILE_SIZE, TileY(end) * TILE_SIZE); truelight@0: } truelight@0: }