bridge_gui.c
author bjarni
Fri, 08 Sep 2006 10:47:39 +0000
changeset 4574 497540b4a75f
parent 4434 4175805666a5
child 4634 897461a3e9ca
permissions -rw-r--r--
(svn r6424) -Codechange: [autoreplace] removed a loop though all vehicles from each time the window is redrawn
To do this, the player struct contains an array, that contains the count of each engine type that the player owns
Those arrays are updated each time a vehicle is build or deleted and is calculated on load (it's not saved)
It's possible to access the arrays outside of the autoreplace GUI, so feel free to read from them in other patches as well
/* $Id$ */

/** @file bridge_gui.c Graphical user interface for bridge construction*/

#include "stdafx.h"
#include "openttd.h"
#include "table/strings.h"
#include "functions.h"
#include "map.h"
#include "window.h"
#include "gui.h"
#include "viewport.h"
#include "gfx.h"
#include "command.h"
#include "sound.h"
#include "variables.h"
#include "bridge.h"

static struct BridgeData {
	uint count;
	TileIndex start_tile;
	TileIndex end_tile;
	byte type;
	byte indexes[MAX_BRIDGES];
	int32 costs[MAX_BRIDGES];
} _bridgedata;

void CcBuildBridge(bool success, TileIndex tile, uint32 p1, uint32 p2)
{
	if (success) SndPlayTileFx(SND_27_BLACKSMITH_ANVIL, tile);
}

static void BuildBridge(Window *w, int i)
{
	DeleteWindow(w);
	DoCommandP(_bridgedata.end_tile, _bridgedata.start_tile,
		_bridgedata.indexes[i] | (_bridgedata.type << 8), CcBuildBridge,
		CMD_BUILD_BRIDGE | CMD_AUTO | CMD_MSG(STR_5015_CAN_T_BUILD_BRIDGE_HERE));
}

static void BuildBridgeWndProc(Window *w, WindowEvent *e)
{
	switch (e->event) {
	case WE_PAINT: {
		uint i;

		DrawWindowWidgets(w);

		for (i = 0; i < 4 && i + w->vscroll.pos < _bridgedata.count; i++) {
			const Bridge *b = &_bridge[_bridgedata.indexes[i + w->vscroll.pos]];

			SetDParam(2, _bridgedata.costs[i + w->vscroll.pos]);
			SetDParam(1, b->speed);
			SetDParam(0, b->material);
			DrawSprite(b->sprite, 3, 15 + i * 22);

			DrawString(44, 15 + i * 22 , STR_500D, 0);
		}
	} break;

	case WE_KEYPRESS: {
		uint i = e->keypress.keycode - '1';
		if (i < 9 && i < _bridgedata.count) {
			e->keypress.cont = false;
			BuildBridge(w, i);
		}

		break;
	}

	case WE_CLICK:
		if (e->click.widget == 2) {
			uint ind = ((int)e->click.pt.y - 14) / 22;
			if (ind < 4 && (ind += w->vscroll.pos) < _bridgedata.count)
				BuildBridge(w, ind);
		}
		break;
	}
}

static const Widget _build_bridge_widgets[] = {
{   WWT_CLOSEBOX,   RESIZE_NONE,     7,     0,    10,     0,    13, STR_00C5,                    STR_018B_CLOSE_WINDOW},
{    WWT_CAPTION,   RESIZE_NONE,     7,    11,   199,     0,    13, STR_100D_SELECT_RAIL_BRIDGE, STR_018C_WINDOW_TITLE_DRAG_THIS},
{     WWT_MATRIX,   RESIZE_NONE,     7,     0,   187,    14,   101, 0x401,                       STR_101F_BRIDGE_SELECTION_CLICK},
{  WWT_SCROLLBAR,   RESIZE_NONE,     7,   188,   199,    14,   101, 0x0,                         STR_0190_SCROLL_BAR_SCROLLS_LIST},
{   WIDGETS_END},
};

static const WindowDesc _build_bridge_desc = {
	-1, -1, 200, 102,
	WC_BUILD_BRIDGE,WC_BUILD_TOOLBAR,
	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
	_build_bridge_widgets,
	BuildBridgeWndProc
};


static const Widget _build_road_bridge_widgets[] = {
{   WWT_CLOSEBOX,   RESIZE_NONE,     7,     0,    10,     0,    13, STR_00C5,                    STR_018B_CLOSE_WINDOW},
{    WWT_CAPTION,   RESIZE_NONE,     7,    11,   199,     0,    13, STR_1803_SELECT_ROAD_BRIDGE, STR_018C_WINDOW_TITLE_DRAG_THIS},
{     WWT_MATRIX,   RESIZE_NONE,     7,     0,   187,    14,   101, 0x401,                       STR_101F_BRIDGE_SELECTION_CLICK},
{  WWT_SCROLLBAR,   RESIZE_NONE,     7,   188,   199,    14,   101, 0x0,                         STR_0190_SCROLL_BAR_SCROLLS_LIST},
{   WIDGETS_END},
};

static const WindowDesc _build_road_bridge_desc = {
	-1, -1, 200, 102,
	WC_BUILD_BRIDGE,WC_BUILD_TOOLBAR,
	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
	_build_road_bridge_widgets,
	BuildBridgeWndProc
};


void ShowBuildBridgeWindow(TileIndex start, TileIndex end, byte bridge_type)
{
	uint j = 0;
	int32 ret;
	StringID errmsg;

	DeleteWindowById(WC_BUILD_BRIDGE, 0);

	_bridgedata.type = bridge_type;
	_bridgedata.start_tile = start;
	_bridgedata.end_tile = end;

	errmsg = INVALID_STRING_ID;

	// only query bridge building possibility once, result is the same for all bridges!
	// returns CMD_ERROR on failure, and price on success
	ret = DoCommand(end, start, (bridge_type << 8), DC_AUTO | DC_QUERY_COST, CMD_BUILD_BRIDGE);

	if (CmdFailed(ret)) {
		errmsg = _error_message;
	} else {
		// check which bridges can be built
		int bridge_len;         // length of the middle parts of the bridge
		int tot_bridgedata_len; // total length of bridge

		// get absolute bridge length
		bridge_len = GetBridgeLength(start, end);
		tot_bridgedata_len = bridge_len + 2;

		tot_bridgedata_len = CalcBridgeLenCostFactor(tot_bridgedata_len);

		for (bridge_type = 0; bridge_type != MAX_BRIDGES; bridge_type++) { // loop for all bridgetypes
			if (CheckBridge_Stuff(bridge_type, bridge_len)) {
				const Bridge *b = &_bridge[bridge_type];
				// bridge is accepted, add to list
				// add to terraforming & bulldozing costs the cost of the bridge itself (not computed with DC_QUERY_COST)
				_bridgedata.costs[j] = ret + (((int64)tot_bridgedata_len * _price.build_bridge * b->price) >> 8);
				_bridgedata.indexes[j] = bridge_type;
				j++;
			}
		}
	}

	_bridgedata.count = j;

	if (j != 0) {
		Window *w = AllocateWindowDesc((_bridgedata.type & 0x80) ? &_build_road_bridge_desc : &_build_bridge_desc);
		w->vscroll.cap = 4;
		w->vscroll.count = (byte)j;
	} else {
		ShowErrorMessage(errmsg, STR_5015_CAN_T_BUILD_BRIDGE_HERE, TileX(end) * TILE_SIZE, TileY(end) * TILE_SIZE);
	}
}