Changeset - r7922:d7c3cc15726d
[Not reviewed]
src/aircraft_cmd.cpp
Show inline comments
 
@@ -812,54 +812,54 @@ static void HelicopterTickHandler(Vehicl
 
	}
 

	
 
	u->cur_image = img;
 

	
 
	BeginVehicleMove(u);
 
	VehiclePositionChanged(u);
 
	EndVehicleMove(u);
 
}
 

	
 
static void SetAircraftPosition(Vehicle *v, int x, int y, int z)
 
{
 
	v->x_pos = x;
 
	v->y_pos = y;
 
	v->z_pos = z;
 

	
 
	v->cur_image = v->GetImage(v->direction);
 
	if (v->subtype == AIR_HELICOPTER) v->Next()->Next()->cur_image = GetRotorImage(v);
 

	
 
	BeginVehicleMove(v);
 
	VehiclePositionChanged(v);
 
	EndVehicleMove(v);
 

	
 
	Vehicle *u = v->Next();
 

	
 
	int safe_x = clamp(x, 0, MapMaxX() * TILE_SIZE);
 
	int safe_y = clamp(y - 1, 0, MapMaxY() * TILE_SIZE);
 
	int safe_x = Clamp(x, 0, MapMaxX() * TILE_SIZE);
 
	int safe_y = Clamp(y - 1, 0, MapMaxY() * TILE_SIZE);
 
	u->x_pos = x;
 
	u->y_pos = y - ((v->z_pos-GetSlopeZ(safe_x, safe_y)) >> 3);;
 

	
 
	safe_y = clamp(u->y_pos, 0, MapMaxY() * TILE_SIZE);
 
	safe_y = Clamp(u->y_pos, 0, MapMaxY() * TILE_SIZE);
 
	u->z_pos = GetSlopeZ(safe_x, safe_y);
 
	u->cur_image = v->cur_image;
 

	
 
	BeginVehicleMove(u);
 
	VehiclePositionChanged(u);
 
	EndVehicleMove(u);
 

	
 
	u = u->Next();
 
	if (u != NULL) {
 
		u->x_pos = x;
 
		u->y_pos = y;
 
		u->z_pos = z + 5;
 

	
 
		BeginVehicleMove(u);
 
		VehiclePositionChanged(u);
 
		EndVehicleMove(u);
 
	}
 
}
 

	
 
/** Handle Aircraft specific tasks when a an Aircraft enters a hangar
 
 * @param *v Vehicle that enters the hangar
 
 */
 
void HandleAircraftEnterHangar(Vehicle *v)
 
{
src/depot.h
Show inline comments
 
@@ -30,49 +30,49 @@ struct Depot : PoolItem<Depot, DepotID, 
 
static inline bool IsValidDepotID(DepotID index)
 
{
 
	return index < GetDepotPoolSize() && GetDepot(index)->IsValid();
 
}
 

	
 
void ShowDepotWindow(TileIndex tile, VehicleType type);
 

	
 
#define FOR_ALL_DEPOTS_FROM(d, start) for (d = GetDepot(start); d != NULL; d = (d->index + 1U < GetDepotPoolSize()) ? GetDepot(d->index + 1U) : NULL) if (d->IsValid())
 
#define FOR_ALL_DEPOTS(d) FOR_ALL_DEPOTS_FROM(d, 0)
 

	
 
#define MIN_SERVINT_PERCENT  5
 
#define MAX_SERVINT_PERCENT 90
 
#define MIN_SERVINT_DAYS    30
 
#define MAX_SERVINT_DAYS   800
 

	
 
/**
 
 * Get the service interval domain.
 
 * Get the new proposed service interval for the vehicle is indeed, clamped
 
 * within the given bounds. @see MIN_SERVINT_PERCENT ,etc.
 
 * @param index proposed service interval
 
 * @return service interval
 
 */
 
static inline Date GetServiceIntervalClamped(uint index)
 
{
 
	return (_patches.servint_ispercent) ? clamp(index, MIN_SERVINT_PERCENT, MAX_SERVINT_PERCENT) : clamp(index, MIN_SERVINT_DAYS, MAX_SERVINT_DAYS);
 
	return (_patches.servint_ispercent) ? Clamp(index, MIN_SERVINT_PERCENT, MAX_SERVINT_PERCENT) : Clamp(index, MIN_SERVINT_DAYS, MAX_SERVINT_DAYS);
 
}
 

	
 
/**
 
 * Check if a tile is a depot of the given type.
 
 */
 
static inline bool IsTileDepotType(TileIndex tile, TransportType type)
 
{
 
	switch (type) {
 
		case TRANSPORT_RAIL:
 
			return IsTileType(tile, MP_RAILWAY) && GetRailTileType(tile)  == RAIL_TILE_DEPOT;
 

	
 
		case TRANSPORT_ROAD:
 
			return IsTileType(tile, MP_ROAD)    && GetRoadTileType(tile)  == ROAD_TILE_DEPOT;
 

	
 
		case TRANSPORT_WATER:
 
			return IsTileType(tile, MP_WATER)   && GetWaterTileType(tile) == WATER_TILE_DEPOT;
 

	
 
		default:
 
			NOT_REACHED();
 
			return false;
 
	}
 
}
 

	
 
/**
src/disaster_cmd.cpp
Show inline comments
 
@@ -138,55 +138,55 @@ static void InitializeDisasterVehicle(Ve
 
	BeginVehicleMove(v);
 
	EndVehicleMove(v);
 
}
 

	
 
static void DeleteDisasterVeh(Vehicle *v)
 
{
 
	DeleteVehicleChain(v);
 
}
 

	
 
static void SetDisasterVehiclePos(Vehicle *v, int x, int y, byte z)
 
{
 
	Vehicle *u;
 

	
 
	BeginVehicleMove(v);
 
	v->x_pos = x;
 
	v->y_pos = y;
 
	v->z_pos = z;
 
	v->tile = TileVirtXY(x, y);
 

	
 
	DisasterVehicleUpdateImage(v);
 
	VehiclePositionChanged(v);
 
	EndVehicleMove(v);
 

	
 
	if ((u = v->Next()) != NULL) {
 
		int safe_x = clamp(x, 0, MapMaxX() * TILE_SIZE);
 
		int safe_y = clamp(y - 1, 0, MapMaxY() * TILE_SIZE);
 
		int safe_x = Clamp(x, 0, MapMaxX() * TILE_SIZE);
 
		int safe_y = Clamp(y - 1, 0, MapMaxY() * TILE_SIZE);
 
		BeginVehicleMove(u);
 

	
 
		u->x_pos = x;
 
		u->y_pos = y - 1 - (max(z - GetSlopeZ(safe_x, safe_y), 0U) >> 3);
 
		safe_y = clamp(u->y_pos, 0, MapMaxY() * TILE_SIZE);
 
		safe_y = Clamp(u->y_pos, 0, MapMaxY() * TILE_SIZE);
 
		u->z_pos = GetSlopeZ(safe_x, safe_y);
 
		u->direction = v->direction;
 

	
 
		DisasterVehicleUpdateImage(u);
 
		VehiclePositionChanged(u);
 
		EndVehicleMove(u);
 

	
 
		if ((u = u->Next()) != NULL) {
 
			BeginVehicleMove(u);
 
			u->x_pos = x;
 
			u->y_pos = y;
 
			u->z_pos = z + 5;
 
			VehiclePositionChanged(u);
 
			EndVehicleMove(u);
 
		}
 
	}
 
}
 

	
 
/**
 
 * Zeppeliner handling, v->current_order.dest states:
 
 * 0: Zeppeliner initialization has found a small airport, go there and crash
 
 * 1: Create crash and animate falling down for extra dramatic effect
 
 * 2: Create more smoke and leave debris on ground
 
 * 2: Clear the runway after some time and remove crashed zeppeliner
src/economy.cpp
Show inline comments
 
@@ -191,49 +191,49 @@ int UpdateCompanyRatingAndValue(Player *
 
		if (update) p->cargo_types = 0;
 
	}
 

	
 
/* Generate score for player money */
 
	{
 
		if (p->player_money > 0) {
 
			_score_part[owner][SCORE_MONEY] = ClampToI32(p->player_money);
 
		}
 
	}
 

	
 
/* Generate score for loan */
 
	{
 
		_score_part[owner][SCORE_LOAN] = ClampToI32(_score_info[SCORE_LOAN].needed - p->current_loan);
 
	}
 

	
 
	/* Now we calculate the score for each item.. */
 
	{
 
		int total_score = 0;
 
		int s;
 
		score = 0;
 
		for (ScoreID i = SCORE_BEGIN; i < SCORE_END; i++) {
 
			/* Skip the total */
 
			if (i == SCORE_TOTAL) continue;
 
			/*  Check the score */
 
			s = clamp(_score_part[owner][i], 0, _score_info[i].needed) * _score_info[i].score / _score_info[i].needed;
 
			s = Clamp(_score_part[owner][i], 0, _score_info[i].needed) * _score_info[i].score / _score_info[i].needed;
 
			score += s;
 
			total_score += _score_info[i].score;
 
		}
 

	
 
		_score_part[owner][SCORE_TOTAL] = score;
 

	
 
		/*  We always want the score scaled to SCORE_MAX (1000) */
 
		if (total_score != SCORE_MAX) score = score * SCORE_MAX / total_score;
 
	}
 

	
 
	if (update) {
 
		p->old_economy[0].performance_history = score;
 
		UpdateCompanyHQ(p, score);
 
		p->old_economy[0].company_value = CalculateCompanyValue(p);
 
	}
 

	
 
	InvalidateWindow(WC_PERFORMANCE_DETAIL, 0);
 
	return score;
 
}
 

	
 
/*  use PLAYER_SPECTATOR as new_player to delete the player. */
 
void ChangeOwnershipOfPlayerItems(PlayerID old_player, PlayerID new_player)
 
{
 
	Town *t;
src/genworld_gui.cpp
Show inline comments
 
@@ -366,64 +366,64 @@ static void GenerateLandscapeWndProc(Win
 
					STR_TOWN_LAYOUT_WARNING_MESSAGE,
 
					w,
 
					LandscapeGenerationCallback);
 
			} else if (mode == GLWP_HEIGHTMAP &&
 
					(WP(w, generate_d).x * 2 < (1U << _patches_newgame.map_x) ||
 
					WP(w, generate_d).x / 2 > (1U << _patches_newgame.map_x) ||
 
					WP(w, generate_d).y * 2 < (1U << _patches_newgame.map_y) ||
 
					WP(w, generate_d).y / 2 > (1U << _patches_newgame.map_y))) {
 
				ShowQuery(
 
					STR_HEIGHTMAP_SCALE_WARNING_CAPTION,
 
					STR_HEIGHTMAP_SCALE_WARNING_MESSAGE,
 
					w,
 
					LandscapeGenerationCallback);
 

	
 
			} else {
 
				StartGeneratingLandscape(mode);
 
			}
 
			break;
 
		case GLAND_START_DATE_DOWN: case GLAND_START_DATE_UP: // Year buttons
 
			/* Don't allow too fast scrolling */
 
			if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
 
				HandleButtonClick(w, e->we.click.widget);
 
				SetWindowDirty(w);
 

	
 
				_patches_newgame.starting_year = clamp(_patches_newgame.starting_year + e->we.click.widget - GLAND_START_DATE_TEXT, MIN_YEAR, MAX_YEAR);
 
				_patches_newgame.starting_year = Clamp(_patches_newgame.starting_year + e->we.click.widget - GLAND_START_DATE_TEXT, MIN_YEAR, MAX_YEAR);
 
			}
 
			_left_button_clicked = false;
 
			break;
 
		case GLAND_START_DATE_TEXT: // Year text
 
			WP(w, generate_d).widget_id = GLAND_START_DATE_TEXT;
 
			SetDParam(0, _patches_newgame.starting_year);
 
			ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_START_DATE_QUERY_CAPT, 8, 100, w, CS_NUMERAL);
 
			break;
 
		case GLAND_SNOW_LEVEL_DOWN: case GLAND_SNOW_LEVEL_UP: // Snow line buttons
 
			/* Don't allow too fast scrolling */
 
			if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
 
				HandleButtonClick(w, e->we.click.widget);
 
				SetWindowDirty(w);
 

	
 
				_patches_newgame.snow_line_height = clamp(_patches_newgame.snow_line_height + e->we.click.widget - GLAND_SNOW_LEVEL_TEXT, 2, MAX_SNOWLINE_HEIGHT);
 
				_patches_newgame.snow_line_height = Clamp(_patches_newgame.snow_line_height + e->we.click.widget - GLAND_SNOW_LEVEL_TEXT, 2, MAX_SNOWLINE_HEIGHT);
 
			}
 
			_left_button_clicked = false;
 
			break;
 
		case GLAND_SNOW_LEVEL_TEXT: // Snow line text
 
			WP(w, generate_d).widget_id = GLAND_SNOW_LEVEL_TEXT;
 
			SetDParam(0, _patches_newgame.snow_line_height);
 
			ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_SNOW_LINE_QUERY_CAPT, 3, 100, w, CS_NUMERAL);
 
			break;
 
		case GLAND_TREE_TEXT: case GLAND_TREE_PULLDOWN: // Tree placer
 
			ShowDropDownMenu(w, tree_placer, _patches_newgame.tree_placer, GLAND_TREE_PULLDOWN, 0, 0);
 
			break;
 
		case GLAND_LANDSCAPE_TEXT: case GLAND_LANDSCAPE_PULLDOWN: // Landscape generator OR Heightmap rotation
 
		/* case GLAND_HEIGHTMAP_ROTATION_TEXT: case GLAND_HEIGHTMAP_ROTATION_PULLDOWN:*/
 
			if (mode == GLWP_HEIGHTMAP) {
 
				ShowDropDownMenu(w, rotation, _patches_newgame.heightmap_rotation, GLAND_HEIGHTMAP_ROTATION_PULLDOWN, 0, 0);
 
			} else {
 
				ShowDropDownMenu(w, landscape, _patches_newgame.land_generator, GLAND_LANDSCAPE_PULLDOWN, 0, 0);
 
			}
 
			break;
 
		case GLAND_TERRAIN_TEXT: case GLAND_TERRAIN_PULLDOWN: // Terrain type
 
			ShowDropDownMenu(w, elevations, _opt_newgame.diff.terrain_type, GLAND_TERRAIN_PULLDOWN, 0, 0);
 
			break;
 
		case GLAND_WATER_TEXT: case GLAND_WATER_PULLDOWN: // Water quantity
 
			ShowDropDownMenu(w, sea_lakes, _opt_newgame.diff.quantity_sea_lakes, GLAND_WATER_PULLDOWN, 0, 0);
 
@@ -473,53 +473,53 @@ static void GenerateLandscapeWndProc(Win
 
					_patches_newgame.land_generator = e->we.dropdown.index;
 
				}
 
				break;
 
			case GLAND_TERRAIN_PULLDOWN:
 
				_opt_newgame.diff.terrain_type = e->we.dropdown.index;
 
				if (_opt_newgame.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
 
				DoCommandP(0, 12, _opt_newgame.diff.terrain_type, NULL, CMD_CHANGE_DIFFICULTY_LEVEL);
 
				break;
 
			case GLAND_WATER_PULLDOWN:
 
				_opt_newgame.diff.quantity_sea_lakes = e->we.dropdown.index;
 
				if (_opt_newgame.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0);
 
				DoCommandP(0, 13, _opt_newgame.diff.quantity_sea_lakes, NULL, CMD_CHANGE_DIFFICULTY_LEVEL);
 
				break;
 
		}
 
		SetWindowDirty(w);
 
		break;
 

	
 
	case WE_ON_EDIT_TEXT: {
 
		if (e->we.edittext.str != NULL) {
 
			int32 value = atoi(e->we.edittext.str);
 

	
 
			switch (WP(w, generate_d).widget_id) {
 
			case GLAND_START_DATE_TEXT:
 
				InvalidateWidget(w, GLAND_START_DATE_TEXT);
 
				_patches_newgame.starting_year = clamp(value, MIN_YEAR, MAX_YEAR);
 
				_patches_newgame.starting_year = Clamp(value, MIN_YEAR, MAX_YEAR);
 
				break;
 
			case GLAND_SNOW_LEVEL_TEXT:
 
				InvalidateWidget(w, GLAND_SNOW_LEVEL_TEXT);
 
				_patches_newgame.snow_line_height = clamp(value, 2, MAX_SNOWLINE_HEIGHT);
 
				_patches_newgame.snow_line_height = Clamp(value, 2, MAX_SNOWLINE_HEIGHT);
 
				break;
 
			}
 

	
 
			SetWindowDirty(w);
 
		}
 
		break;
 
	}
 
	}
 
}
 

	
 
static const WindowDesc _generate_landscape_desc = {
 
	WDP_CENTER, WDP_CENTER, 338, 268, 338, 268,
 
	WC_GENERATE_LANDSCAPE, WC_NONE,
 
	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
 
	_generate_landscape_widgets,
 
	GenerateLandscapeWndProc,
 
};
 

	
 
static const WindowDesc _heightmap_load_desc = {
 
	WDP_CENTER, WDP_CENTER, 338, 236, 338, 236,
 
	WC_GENERATE_LANDSCAPE, WC_NONE,
 
	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS,
 
	_heightmap_load_widgets,
 
	GenerateLandscapeWndProc,
 
@@ -636,95 +636,95 @@ static void CreateScenarioWndProc(Window
 
	case WE_CLICK:
 
		switch (e->we.click.widget) {
 
		case CSCEN_TEMPERATE: case CSCEN_ARCTIC: case CSCEN_TROPICAL: case CSCEN_TOYLAND:
 
			RaiseWindowWidget(w, _opt_newgame.landscape + CSCEN_TEMPERATE);
 
			SetNewLandscapeType(e->we.click.widget - CSCEN_TEMPERATE);
 
			break;
 
		case CSCEN_MAPSIZE_X_TEXT: case CSCEN_MAPSIZE_X_PULLDOWN: // Mapsize X
 
			ShowDropDownMenu(w, mapsizes, _patches_newgame.map_x - 6, CSCEN_MAPSIZE_X_PULLDOWN, 0, 0);
 
			break;
 
		case CSCEN_MAPSIZE_Y_TEXT: case CSCEN_MAPSIZE_Y_PULLDOWN: // Mapsize Y
 
			ShowDropDownMenu(w, mapsizes, _patches_newgame.map_y - 6, CSCEN_MAPSIZE_Y_PULLDOWN, 0, 0);
 
			break;
 
		case CSCEN_EMPTY_WORLD: // Empty world / flat world
 
			StartGeneratingLandscape(GLWP_SCENARIO);
 
			break;
 
		case CSCEN_RANDOM_WORLD: // Generate
 
			ShowGenerateLandscape();
 
			break;
 
		case CSCEN_START_DATE_DOWN: case CSCEN_START_DATE_UP: // Year buttons
 
			/* Don't allow too fast scrolling */
 
			if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
 
				HandleButtonClick(w, e->we.click.widget);
 
				SetWindowDirty(w);
 

	
 
				_patches_newgame.starting_year = clamp(_patches_newgame.starting_year + e->we.click.widget - CSCEN_START_DATE_TEXT, MIN_YEAR, MAX_YEAR);
 
				_patches_newgame.starting_year = Clamp(_patches_newgame.starting_year + e->we.click.widget - CSCEN_START_DATE_TEXT, MIN_YEAR, MAX_YEAR);
 
			}
 
			_left_button_clicked = false;
 
			break;
 
		case CSCEN_START_DATE_TEXT: // Year text
 
			WP(w, generate_d).widget_id = CSCEN_START_DATE_TEXT;
 
			SetDParam(0, _patches_newgame.starting_year);
 
			ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_START_DATE_QUERY_CAPT, 8, 100, w, CS_NUMERAL);
 
			break;
 
		case CSCEN_FLAT_LAND_HEIGHT_DOWN: case CSCEN_FLAT_LAND_HEIGHT_UP: // Height level buttons
 
			/* Don't allow too fast scrolling */
 
			if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
 
				HandleButtonClick(w, e->we.click.widget);
 
				SetWindowDirty(w);
 

	
 
				_patches_newgame.se_flat_world_height = clamp(_patches_newgame.se_flat_world_height + e->we.click.widget - CSCEN_FLAT_LAND_HEIGHT_TEXT, 0, MAX_TILE_HEIGHT);
 
				_patches_newgame.se_flat_world_height = Clamp(_patches_newgame.se_flat_world_height + e->we.click.widget - CSCEN_FLAT_LAND_HEIGHT_TEXT, 0, MAX_TILE_HEIGHT);
 
			}
 
			_left_button_clicked = false;
 
			break;
 
		case CSCEN_FLAT_LAND_HEIGHT_TEXT: // Height level text
 
			WP(w, generate_d).widget_id = CSCEN_FLAT_LAND_HEIGHT_TEXT;
 
			SetDParam(0, _patches_newgame.se_flat_world_height);
 
			ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_FLAT_WORLD_HEIGHT_QUERY_CAPT, 3, 100, w, CS_NUMERAL);
 
			break;
 
		}
 
		break;
 

	
 
	case WE_DROPDOWN_SELECT:
 
		switch (e->we.dropdown.button) {
 
			case CSCEN_MAPSIZE_X_PULLDOWN: _patches_newgame.map_x = e->we.dropdown.index + 6; break;
 
			case CSCEN_MAPSIZE_Y_PULLDOWN: _patches_newgame.map_y = e->we.dropdown.index + 6; break;
 
		}
 
		SetWindowDirty(w);
 
		break;
 

	
 
	case WE_ON_EDIT_TEXT: {
 
		if (e->we.edittext.str != NULL) {
 
			int32 value = atoi(e->we.edittext.str);
 

	
 
			switch (WP(w, generate_d).widget_id) {
 
			case CSCEN_START_DATE_TEXT:
 
				InvalidateWidget(w, CSCEN_START_DATE_TEXT);
 
				_patches_newgame.starting_year = clamp(value, MIN_YEAR, MAX_YEAR);
 
				_patches_newgame.starting_year = Clamp(value, MIN_YEAR, MAX_YEAR);
 
				break;
 
			case CSCEN_FLAT_LAND_HEIGHT_TEXT:
 
				InvalidateWidget(w, CSCEN_FLAT_LAND_HEIGHT_TEXT);
 
				_patches_newgame.se_flat_world_height = clamp(value, 0, MAX_TILE_HEIGHT);
 
				_patches_newgame.se_flat_world_height = Clamp(value, 0, MAX_TILE_HEIGHT);
 
				break;
 
			}
 

	
 
			SetWindowDirty(w);
 
		}
 
		break;
 
	}
 
	}
 
}
 

	
 
static const Widget _create_scenario_widgets[] = {
 
{   WWT_CLOSEBOX, RESIZE_NONE, 13,   0,  10,   0,  13, STR_00C5,                STR_018B_CLOSE_WINDOW},
 
{    WWT_CAPTION, RESIZE_NONE, 13,  11, 337,   0,  13, STR_SE_CAPTION,          STR_NULL},
 
{      WWT_PANEL, RESIZE_NONE, 13,   0, 337,  14, 169, 0x0,                     STR_NULL},
 

	
 
{   WWT_IMGBTN_2, RESIZE_NONE, 12,  10,  86,  24,  78, SPR_SELECT_TEMPERATE,    STR_030E_SELECT_TEMPERATE_LANDSCAPE},
 
{   WWT_IMGBTN_2, RESIZE_NONE, 12,  90, 166,  24,  78, SPR_SELECT_SUB_ARCTIC,   STR_030F_SELECT_SUB_ARCTIC_LANDSCAPE},
 
{   WWT_IMGBTN_2, RESIZE_NONE, 12, 170, 246,  24,  78, SPR_SELECT_SUB_TROPICAL, STR_0310_SELECT_SUB_TROPICAL_LANDSCAPE},
 
{   WWT_IMGBTN_2, RESIZE_NONE, 12, 250, 326,  24,  78, SPR_SELECT_TOYLAND,      STR_0311_SELECT_TOYLAND_LANDSCAPE},
 

	
 
{    WWT_TEXTBTN, RESIZE_NONE,  6,  12, 115,  95, 124, STR_SE_FLAT_WORLD,       STR_SE_FLAT_WORLD_TIP},         // Empty (sea-level) map
 
{    WWT_TEXTBTN, RESIZE_NONE,  6,  12, 115, 131, 160, STR_SE_RANDOM_LAND,      STR_022A_GENERATE_RANDOM_LAND}, // Generate
 

	
 
{      WWT_PANEL, RESIZE_NONE, 12, 216, 251,  95, 106, 0x0,                     STR_NULL},
src/graph_gui.cpp
Show inline comments
 
@@ -985,59 +985,59 @@ static void PerformanceRatingDetailWndPr
 
			color_notdone = _colour_gradient[COLOUR_RED][4];
 

	
 
			/* Draw all the score parts */
 
			for (ScoreID i = SCORE_BEGIN; i < SCORE_END; i++) {
 
				int val    = _score_part[_performance_rating_detail_player][i];
 
				int needed = _score_info[i].needed;
 
				int score  = _score_info[i].score;
 

	
 
				y += 20;
 
				/* SCORE_TOTAL has his own rulez ;) */
 
				if (i == SCORE_TOTAL) {
 
					needed = total_score;
 
					score = SCORE_MAX;
 
				} else {
 
					total_score += score;
 
				}
 

	
 
				DrawString(7, y, STR_PERFORMANCE_DETAIL_VEHICLES + i, TC_FROMSTRING);
 

	
 
				/* Draw the score */
 
				SetDParam(0, score);
 
				DrawStringRightAligned(107, y, SET_PERFORMANCE_DETAIL_INT, TC_FROMSTRING);
 

	
 
				/* Calculate the %-bar */
 
				x = clamp(val, 0, needed) * 50 / needed;
 
				x = Clamp(val, 0, needed) * 50 / needed;
 

	
 
				/* SCORE_LOAN is inversed */
 
				if (val < 0 && i == SCORE_LOAN) x = 0;
 

	
 
				/* Draw the bar */
 
				if (x !=  0) GfxFillRect(112,     y - 2, 112 + x,  y + 10, color_done);
 
				if (x != 50) GfxFillRect(112 + x, y - 2, 112 + 50, y + 10, color_notdone);
 

	
 
				/* Calculate the % */
 
				x = clamp(val, 0, needed) * 100 / needed;
 
				x = Clamp(val, 0, needed) * 100 / needed;
 

	
 
				/* SCORE_LOAN is inversed */
 
				if (val < 0 && i == SCORE_LOAN) x = 0;
 

	
 
				/* Draw it */
 
				SetDParam(0, x);
 
				DrawStringCentered(137, y, STR_PERFORMANCE_DETAIL_PERCENT, TC_FROMSTRING);
 

	
 
				/* SCORE_LOAN is inversed */
 
				if (i == SCORE_LOAN) val = needed - val;
 

	
 
				/* Draw the amount we have against what is needed
 
				 * For some of them it is in currency format */
 
				SetDParam(0, val);
 
				SetDParam(1, needed);
 
				switch (i) {
 
					case SCORE_MIN_PROFIT:
 
					case SCORE_MIN_INCOME:
 
					case SCORE_MAX_INCOME:
 
					case SCORE_MONEY:
 
					case SCORE_LOAN:
 
						DrawString(167, y, STR_PERFORMANCE_DETAIL_AMOUNT_CURRENCY, TC_FROMSTRING);
 
						break;
 
					default:
src/industry_cmd.cpp
Show inline comments
 
@@ -1607,49 +1607,49 @@ CommandCost CmdBuildIndustry(TileIndex t
 
			/* Prospecting has a chance to fail, however we cannot guarantee that something can
 
			 * be built on the map, so the chance gets lower when the map is fuller, but there
 
			 * is nothing we can really do about that. */
 
			if (Random() <= indspec->prospecting_chance) {
 
				for (int i = 0; i < 5000; i++) {
 
					const Industry *ind = CreateNewIndustryHelper(RandomTile(), p1, flags, indspec, RandomRange(indspec->num_table));
 
					if (ind != NULL) {
 
						SetDParam(0, indspec->name);
 
						if (indspec->new_industry_text > STR_LAST_STRINGID) {
 
							SetDParam(1, STR_TOWN);
 
							SetDParam(2, ind->town->index);
 
						} else {
 
							SetDParam(1, ind->town->index);
 
						}
 
						AddNewsItem(indspec->new_industry_text,
 
								NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_TILE, NT_OPENCLOSE, 0), ind->xy, 0);
 
						break;
 
					}
 
				}
 
			}
 
		}
 
	} else {
 
		int count = indspec->num_table;
 
		const IndustryTileTable * const *itt = indspec->table;
 
		int num = clamp(p2, 0, count - 1);
 
		int num = Clamp(p2, 0, count - 1);
 

	
 
		_error_message = STR_0239_SITE_UNSUITABLE;
 
		do {
 
			if (--count < 0) return CMD_ERROR;
 
			if (--num < 0) num = indspec->num_table - 1;
 
		} while (!CheckIfIndustryTilesAreFree(tile, itt[num], num, p1));
 

	
 
		if (CreateNewIndustryHelper(tile, p1, flags, indspec, num) == NULL) return CMD_ERROR;
 
	}
 

	
 
	return CommandCost(indspec->GetConstructionCost());
 
}
 

	
 

	
 
Industry *CreateNewIndustry(TileIndex tile, IndustryType type)
 
{
 
	const IndustrySpec *indspec = GetIndustrySpec(type);
 

	
 
	return CreateNewIndustryHelper(tile, type, DC_EXEC, indspec, RandomRange(indspec->num_table));
 
}
 

	
 
enum {
 
	NB_NUMOFINDUSTRY = 11,
 
	NB_DIFFICULTY_LEVEL = 5,
 
@@ -2026,49 +2026,49 @@ static void ChangeIndustryProduction(Ind
 
	}
 

	
 
	if (standard && monthly != smooth_economy) return;
 

	
 
	if (standard && indspec->life_type == INDUSTRYLIFE_BLACK_HOLE) return;
 

	
 
	if (standard && (indspec->life_type & (INDUSTRYLIFE_ORGANIC | INDUSTRYLIFE_EXTRACTIVE)) != 0) {
 
		/* decrease or increase */
 
		bool only_decrease = (indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD) && _opt.landscape == LT_TEMPERATE;
 

	
 
		if (smooth_economy) {
 
			closeit = true;
 
			for (byte j = 0; j < 2 && i->produced_cargo[j] != CT_INVALID; j++){
 
				uint32 r = Random();
 
				int old_prod, new_prod, percent;
 

	
 
				new_prod = old_prod = i->production_rate[j];
 

	
 
				if (CHANCE16I(20, 1024, r)) new_prod -= max(((RandomRange(50) + 10) * old_prod) >> 8, 1U);
 
				/* Chance of increasing becomes better when more is transported */
 
				if (CHANCE16I(20 + (i->last_month_pct_transported[j] * 20 >> 8), 1024, r >> 16) && !only_decrease) {
 
					new_prod += max(((RandomRange(50) + 10) * old_prod) >> 8, 1U);
 
				}
 

	
 
				new_prod = clamp(new_prod, 1, 255);
 
				new_prod = Clamp(new_prod, 1, 255);
 
				/* Do not stop closing the industry when it has the lowest possible production rate */
 
				if (new_prod == old_prod && old_prod > 1) {
 
					closeit = false;
 
					continue;
 
				}
 

	
 
				percent = (old_prod == 0) ? 100 : (new_prod * 100 / old_prod - 100);
 
				i->production_rate[j] = new_prod;
 

	
 
				/* Close the industry when it has the lowest possible production rate */
 
				if (new_prod > 1) closeit = false;
 

	
 
				if (abs(percent) >= 10) {
 
					ReportNewsProductionChangeIndustry(i, i->produced_cargo[j], percent);
 
				}
 
			}
 
		} else {
 
			if (only_decrease || CHANCE16(1, 3)) {
 
				/* If you transport > 60%, 66% chance we increase, else 33% chance we increase */
 
				if (!only_decrease && (i->last_month_pct_transported[0] > 153) != CHANCE16(1, 3)) {
 
					mul = 1; // Increase production
 
				} else {
 
					div = 1; // Decrease production
 
				}
src/industry_gui.cpp
Show inline comments
 
@@ -562,49 +562,49 @@ static void IndustryViewWndProc(Window *
 
					WP(w, indview_d).editbox_line = line;
 
					SetDParam(0, i->production_rate[line] * 8);
 
					ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_CONFIG_GAME_PRODUCTION, 10, 100, w, CS_ALPHANUMERAL);
 
				}
 
			}
 
		} break;
 
		case 6:
 
			i = GetIndustry(w->window_number);
 
			ScrollMainWindowToTile(i->xy + TileDiffXY(1, 1));
 
		} break;
 

	
 
		}
 
		break;
 
	case WE_TIMEOUT:
 
		WP(w, indview_d).clicked_line = 0;
 
		WP(w, indview_d).clicked_button = 0;
 
		SetWindowDirty(w);
 
		break;
 

	
 
	case WE_ON_EDIT_TEXT:
 
		if (e->we.edittext.str[0] != '\0') {
 
			Industry* i = GetIndustry(w->window_number);
 
			int line = WP(w, indview_d).editbox_line;
 

	
 
			i->production_rate[line] = clampu(atoi(e->we.edittext.str), 0, 255);
 
			i->production_rate[line] = ClampU(atoi(e->we.edittext.str), 0, 255);
 
			UpdateIndustryProduction(i);
 
			SetWindowDirty(w);
 
		}
 
	}
 
}
 

	
 
static void UpdateIndustryProduction(Industry *i)
 
{
 
	for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
 
		if (i->produced_cargo[j] != CT_INVALID) {
 
			i->last_month_production[j] = 8 * i->production_rate[j];
 
		}
 
	}
 
}
 

	
 
static const Widget _industry_view_widgets[] = {
 
{   WWT_CLOSEBOX,   RESIZE_NONE,     9,     0,    10,     0,    13, STR_00C5,          STR_018B_CLOSE_WINDOW},
 
{    WWT_CAPTION,   RESIZE_NONE,     9,    11,   247,     0,    13, STR_4801,          STR_018C_WINDOW_TITLE_DRAG_THIS},
 
{  WWT_STICKYBOX,   RESIZE_NONE,     9,   248,   259,     0,    13, 0x0,               STR_STICKY_BUTTON},
 
{      WWT_PANEL,   RESIZE_NONE,     9,     0,   259,    14,   105, 0x0,               STR_NULL},
 
{      WWT_INSET,   RESIZE_NONE,     9,     2,   257,    16,   103, 0x0,               STR_NULL},
 
{      WWT_PANEL,   RESIZE_NONE,     9,     0,   259,   106,   147, 0x0,               STR_NULL},
 
{ WWT_PUSHTXTBTN,   RESIZE_NONE,     9,     0,   129,   148,   159, STR_00E4_LOCATION, STR_482C_CENTER_THE_MAIN_VIEW_ON},
 
{      WWT_PANEL,   RESIZE_NONE,     9,   130,   259,   148,   159, 0x0,               STR_NULL},
src/macros.h
Show inline comments
 
@@ -130,93 +130,93 @@ static inline int min(const int a, const
 
 *
 
 * @param a The first unsigned integer
 
 * @param b The second unsigned integer
 
 * @return The smaller value
 
 */
 
static inline uint minu(const uint a, const uint b)
 
{
 
	return a < b ? a : b;
 
}
 

	
 
/**
 
 * Clamp an integer between an interval.
 
 *
 
 * This function returns a value which is between the given interval of
 
 * min and max. If the given value is in this interval the value itself
 
 * is returned otherwise the border of the interval is returned, according
 
 * which side of the interval was 'left'.
 
 *
 
 * @note The min value must be less or equal of max or you get some
 
 *       unexpected results.
 
 * @param a The value to clamp/truncate.
 
 * @param min The minimum of the interval.
 
 * @param max the maximum of the interval.
 
 * @returns A value between min and max which is closest to a.
 
 * @see clampu(uint, uint, uint)
 
 * @see ClampU(uint, uint, uint)
 
 */
 
static inline int clamp(const int a, const int min, const int max)
 
static inline int Clamp(const int a, const int min, const int max)
 
{
 
	if (a <= min) return min;
 
	if (a >= max) return max;
 
	return a;
 
}
 

	
 
/**
 
 * Clamp an unsigned integer between an interval.
 
 *
 
 * This function returns a value which is between the given interval of
 
 * min and max. If the given value is in this interval the value itself
 
 * is returned otherwise the border of the interval is returned, according
 
 * which side of the interval was 'left'.
 
 *
 
 * @note The min value must be less or equal of max or you get some
 
 *       unexpected results.
 
 * @param a The value to clamp/truncate.
 
 * @param min The minimum of the interval.
 
 * @param max the maximum of the interval.
 
 * @returns A value between min and max which is closest to a.
 
 * @see clamp(int, int, int)
 
 * @see Clamp(int, int, int)
 
 */
 
static inline uint clampu(const uint a, const uint min, const uint max)
 
static inline uint ClampU(const uint a, const uint min, const uint max)
 
{
 
	if (a <= min) return min;
 
	if (a >= max) return max;
 
	return a;
 
}
 

	
 
/**
 
 * Reduce a signed 64-bit int to a signed 32-bit one
 
 *
 
 * This function clamps a 64-bit integer to a 32-bit integer.
 
 * If the 64-bit value is smaller than the smallest 32-bit integer
 
 * value 0x80000000 this value is returned (the left one bit is the sign bit).
 
 * If the 64-bit value is greater than the greatest 32-bit integer value 0x7FFFFFFF
 
 * this value is returned. In all other cases the 64-bit value 'fits' in a
 
 * 32-bits integer field and so the value is casted to int32 and returned.
 
 *
 
 * @param a The 64-bit value to clamps
 
 * @return The 64-bit value reduced to a 32-bit value
 
 * @see clamp(int, int, int)
 
 * @see Clamp(int, int, int)
 
 */
 
static inline int32 ClampToI32(const int64 a)
 
{
 
	if (a <= (int32)0x80000000) return 0x80000000;
 
	if (a >= (int32)0x7FFFFFFF) return 0x7FFFFFFF;
 
	return (int32)a;
 
}
 

	
 
/**
 
 * Multiply two integer values and shift the results to right.
 
 *
 
 * This function multiplies two integer values. The result is
 
 * shifted by the amount of shift to right.
 
 *
 
 * @param a The first integer
 
 * @param b The second integer
 
 * @param shift The amount to shift the value to right.
 
 * @return The shifted result
 
 */
 
static inline int32 BIGMULSS(const int32 a, const int32 b, const uint8 shift)
 
{
 
	return (int32)((int64)a * (int64)b >> shift);
 
}
 

	
src/main_gui.cpp
Show inline comments
 
@@ -75,49 +75,49 @@ void CcGiveMoney(bool success, TileIndex
 

	
 
	if (!_network_server) {
 
		SEND_COMMAND(PACKET_CLIENT_CHAT)(NETWORK_ACTION_GIVE_MONEY, DESTTYPE_TEAM, p2, msg);
 
	} else {
 
		NetworkServer_HandleChat(NETWORK_ACTION_GIVE_MONEY, DESTTYPE_TEAM, p2, msg, NETWORK_SERVER_INDEX);
 
	}
 
#endif /* ENABLE_NETWORK */
 
}
 

	
 
void HandleOnEditText(const char *str)
 
{
 
	int id = _rename_id;
 
	_cmd_text = str;
 

	
 
	switch (_rename_what) {
 
	case 1: // Rename a waypoint
 
		if (*str == '\0') return;
 
		DoCommandP(0, id, 0, NULL, CMD_RENAME_WAYPOINT | CMD_MSG(STR_CANT_CHANGE_WAYPOINT_NAME));
 
		break;
 
#ifdef ENABLE_NETWORK
 
	case 3: { // Give money, you can only give money in excess of loan
 
		const Player *p = GetPlayer(_current_player);
 
		Money money = min(p->player_money - p->current_loan, (Money)(atoi(str) / _currency->rate));
 

	
 
		uint32 money_c = clamp(ClampToI32(money), 0, 20000000); // Clamp between 20 million and 0
 
		uint32 money_c = Clamp(ClampToI32(money), 0, 20000000); // Clamp between 20 million and 0
 

	
 
		/* Give 'id' the money, and substract it from ourself */
 
		DoCommandP(0, money_c, id, CcGiveMoney, CMD_GIVE_MONEY | CMD_MSG(STR_INSUFFICIENT_FUNDS));
 
	} break;
 
#endif /* ENABLE_NETWORK */
 
		default: NOT_REACHED();
 
	}
 

	
 
	_rename_id = _rename_what = -1;
 
}
 

	
 
/**
 
 * This code is shared for the majority of the pushbuttons.
 
 * Handles e.g. the pressing of a button (to build things), playing of click sound and sets certain parameters
 
 *
 
 * @param w Window which called the function
 
 * @param widget ID of the widget (=button) that called this function
 
 * @param cursor How should the cursor image change? E.g. cursor with depot image in it
 
 * @param mode Tile highlighting mode, e.g. drawing a rectangle or a dot on the ground
 
 * @param placeproc Procedure which will be called when someone clicks on the map
 
 * @return true if the button is clicked, false if it's unclicked
 
 */
 
bool HandlePlacePushButton(Window *w, int widget, CursorID cursor, ViewportHighlightMode mode, PlaceProc *placeproc)
 
{
 
@@ -695,49 +695,49 @@ static int GetStringListMaxWidth(StringI
 
 * button bits 0 -  7 - widget clicked to get dropdown
 
 * action bits 8 - 15 - function of widget to execute on select (defaults to bits 0 - 7)
 
 * @param base_string The first StringID shown in the dropdown list. All others are
 
 * consecutive indeces from the language file. XXX - fix? Use ingame-string tables?
 
 * @param item_count Number of strings in the list, see previous parameter
 
 * @param disabled_mask Bitmask of disabled strings in the list
 
 * @return Return a pointer to the newly created dropdown window */
 
static Window *PopupMainToolbMenu(Window *w, uint16 parent_button, StringID base_string, byte item_count, byte disabled_mask)
 
{
 
	int width;
 
	int x = w->widget[GB(parent_button, 0, 8)].left;
 

	
 
	assert(disabled_mask == 0 || item_count <= 8);
 
	LowerWindowWidget(w, parent_button);
 
	InvalidateWidget(w, parent_button);
 

	
 
	DeleteWindowById(WC_TOOLBAR_MENU, 0);
 

	
 
	/* Extend the dropdown toolbar to the longest string in the list and
 
	 * also make sure the dropdown is fully visible within the window.
 
	 * x + w->left because x is supposed to be the offset of the toolbar-button
 
	 * we clicked on and w->left the toolbar window itself. So meaning that
 
	 * the default position is aligned with the left side of the clicked button */
 
	width = max(GetStringListMaxWidth(base_string, item_count) + 6, 140);
 
	x = w->left + clamp(x, 0, w->width - width); // or alternatively '_screen.width - width'
 
	x = w->left + Clamp(x, 0, w->width - width); // or alternatively '_screen.width - width'
 

	
 
	w = AllocateWindow(x, 22, width, item_count * 10 + 2, MenuWndProc, WC_TOOLBAR_MENU, _menu_widgets);
 
	w->widget[0].bottom = item_count * 10 + 1;
 
	w->flags4 &= ~WF_WHITE_BORDER_MASK;
 

	
 
	WP(w,menu_d).item_count = item_count;
 
	WP(w,menu_d).sel_index = 0;
 
	WP(w,menu_d).main_button = GB(parent_button, 0, 8);
 
	WP(w,menu_d).action_id = (GB(parent_button, 8, 8) != 0) ? GB(parent_button, 8, 8) : parent_button;
 
	WP(w,menu_d).string_id = base_string;
 
	WP(w,menu_d).checked_items = 0;
 
	WP(w,menu_d).disabled_items = disabled_mask;
 

	
 
	_popup_menu_active = true;
 

	
 
	SndPlayFx(SND_15_BEEP);
 
	return w;
 
}
 

	
 
static Window *PopupMainPlayerToolbMenu(Window *w, int main_button, int gray)
 
{
 
	int x = w->widget[main_button].left + w->left;
 

	
 
	LowerWindowWidget(w, main_button);
 
@@ -974,62 +974,62 @@ static void ToolbarOptionsClick(Window *
 
	if (HASBIT(_display_opt, DO_SHOW_TOWN_NAMES))    SETBIT(x,  6);
 
	if (HASBIT(_display_opt, DO_SHOW_STATION_NAMES)) SETBIT(x,  7);
 
	if (HASBIT(_display_opt, DO_SHOW_SIGNS))         SETBIT(x,  8);
 
	if (HASBIT(_display_opt, DO_WAYPOINTS))          SETBIT(x,  9);
 
	if (HASBIT(_display_opt, DO_FULL_ANIMATION))     SETBIT(x, 10);
 
	if (HASBIT(_display_opt, DO_FULL_DETAIL))        SETBIT(x, 11);
 
	if (IsTransparencySet(TO_HOUSES) && IsTransparencySet(TO_TREES)) SETBIT(x, 12);
 
	if (IsTransparencySet(TO_SIGNS))                     SETBIT(x, 13);
 
	WP(w,menu_d).checked_items = x;
 
}
 

	
 

	
 
static void ToolbarScenSaveOrLoad(Window *w)
 
{
 
	PopupMainToolbMenu(w, 3, STR_0292_SAVE_SCENARIO, 6, 0);
 
}
 

	
 
static void ToolbarScenDateBackward(Window *w)
 
{
 
	/* don't allow too fast scrolling */
 
	if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
 
		HandleButtonClick(w, 6);
 
		SetWindowDirty(w);
 

	
 
		_patches_newgame.starting_year = clamp(_patches_newgame.starting_year - 1, MIN_YEAR, MAX_YEAR);
 
		_patches_newgame.starting_year = Clamp(_patches_newgame.starting_year - 1, MIN_YEAR, MAX_YEAR);
 
		SetDate(ConvertYMDToDate(_patches_newgame.starting_year, 0, 1));
 
	}
 
	_left_button_clicked = false;
 
}
 

	
 
static void ToolbarScenDateForward(Window *w)
 
{
 
	/* don't allow too fast scrolling */
 
	if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
 
		HandleButtonClick(w, 7);
 
		SetWindowDirty(w);
 

	
 
		_patches_newgame.starting_year = clamp(_patches_newgame.starting_year + 1, MIN_YEAR, MAX_YEAR);
 
		_patches_newgame.starting_year = Clamp(_patches_newgame.starting_year + 1, MIN_YEAR, MAX_YEAR);
 
		SetDate(ConvertYMDToDate(_patches_newgame.starting_year, 0, 1));
 
	}
 
	_left_button_clicked = false;
 
}
 

	
 
static void ToolbarScenMapTownDir(Window *w)
 
{
 
	/* Scenario editor button, *hack*hack* use different button to activate */
 
	PopupMainToolbMenu(w, 8 | (17 << 8), STR_02DE_MAP_OF_WORLD, 4, 0);
 
}
 

	
 
static void ToolbarScenZoomIn(Window *w)
 
{
 
	if (DoZoomInOutWindow(ZOOM_IN, FindWindowById(WC_MAIN_WINDOW, 0))) {
 
		HandleButtonClick(w, 9);
 
		SndPlayFx(SND_15_BEEP);
 
	}
 
}
 

	
 
static void ToolbarScenZoomOut(Window *w)
 
{
 
	if (DoZoomInOutWindow(ZOOM_OUT, FindWindowById(WC_MAIN_WINDOW, 0))) {
 
		HandleButtonClick(w, 10);
 
		SndPlayFx(SND_15_BEEP);
src/misc_gui.cpp
Show inline comments
 
@@ -588,50 +588,50 @@ void ShowErrorMessage(StringID msg_1, St
 

	
 
	if (_errmsg_message_1 != STR_013B_OWNED_BY || GetDParamX(_errmsg_decode_params,2) >= 8) {
 

	
 
		if ( (x|y) != 0) {
 
			pt = RemapCoords2(x, y);
 
			vp = FindWindowById(WC_MAIN_WINDOW, 0)->viewport;
 

	
 
			/* move x pos to opposite corner */
 
			pt.x = UnScaleByZoom(pt.x - vp->virtual_left, vp->zoom) + vp->left;
 
			pt.x = (pt.x < (_screen.width >> 1)) ? _screen.width - 260 : 20;
 

	
 
			/* move y pos to opposite corner */
 
			pt.y = UnScaleByZoom(pt.y - vp->virtual_top, vp->zoom) + vp->top;
 
			pt.y = (pt.y < (_screen.height >> 1)) ? _screen.height - 80 : 100;
 

	
 
		} else {
 
			pt.x = (_screen.width - 240) >> 1;
 
			pt.y = (_screen.height - 46) >> 1;
 
		}
 
		w = AllocateWindow(pt.x, pt.y, 240, 46, ErrmsgWndProc, WC_ERRMSG, _errmsg_widgets);
 
	} else {
 
		if ( (x|y) != 0) {
 
			pt = RemapCoords2(x, y);
 
			vp = FindWindowById(WC_MAIN_WINDOW, 0)->viewport;
 
			pt.x = clamp(UnScaleByZoom(pt.x - vp->virtual_left, vp->zoom) + vp->left - (334/2), 0, _screen.width - 334);
 
			pt.y = clamp(UnScaleByZoom(pt.y - vp->virtual_top, vp->zoom) + vp->top - (137/2), 22, _screen.height - 137);
 
			pt.x = Clamp(UnScaleByZoom(pt.x - vp->virtual_left, vp->zoom) + vp->left - (334/2), 0, _screen.width - 334);
 
			pt.y = Clamp(UnScaleByZoom(pt.y - vp->virtual_top, vp->zoom) + vp->top - (137/2), 22, _screen.height - 137);
 
		} else {
 
			pt.x = (_screen.width - 334) >> 1;
 
			pt.y = (_screen.height - 137) >> 1;
 
		}
 
		w = AllocateWindow(pt.x, pt.y, 334, 137, ErrmsgWndProc, WC_ERRMSG, _errmsg_face_widgets);
 
	}
 

	
 
	w->desc_flags = WDF_STD_BTN | WDF_DEF_WIDGET;
 
}
 

	
 

	
 
void ShowEstimatedCostOrIncome(Money cost, int x, int y)
 
{
 
	StringID msg = STR_0805_ESTIMATED_COST;
 

	
 
	if (cost < 0) {
 
		cost = -cost;
 
		msg = STR_0807_ESTIMATED_INCOME;
 
	}
 
	SetDParam(0, cost);
 
	ShowErrorMessage(INVALID_STRING_ID, msg, x, y);
 
}
 

	
 
void ShowCostOrIncomeAnimation(int x, int y, int z, Money cost)
 
@@ -725,51 +725,51 @@ void GuiShowTooltipsWithArgs(StringID st
 
	Window *w;
 
	uint i;
 
	int x, y;
 

	
 
	DeleteWindowById(WC_TOOLTIPS, 0);
 

	
 
	/* We only show measurement tooltips with patch setting on */
 
	if (str == STR_NULL || (paramcount != 0 && !_patches.measure_tooltip)) return;
 

	
 
	for (i = 0; i != paramcount; i++) SetDParam(i, params[i]);
 
	GetString(buffer, str, lastof(buffer));
 

	
 
	br = GetStringBoundingBox(buffer);
 
	br.width += 6; br.height += 4; // increase slightly to have some space around the box
 

	
 
	/* Cut tooltip length to 200 pixels max, wrap to new line if longer */
 
	if (br.width > 200) {
 
		br.height += ((br.width - 4) / 176) * 10;
 
		br.width = 200;
 
	}
 

	
 
	/* Correctly position the tooltip position, watch out for window and cursor size
 
	 * Clamp value to below main toolbar and above statusbar. If tooltip would
 
	 * go below window, flip it so it is shown above the cursor */
 
	y = clamp(_cursor.pos.y + _cursor.size.y + _cursor.offs.y + 5, 22, _screen.height - 12);
 
	y = Clamp(_cursor.pos.y + _cursor.size.y + _cursor.offs.y + 5, 22, _screen.height - 12);
 
	if (y + br.height > _screen.height - 12) y = _cursor.pos.y + _cursor.offs.y - br.height - 5;
 
	x = clamp(_cursor.pos.x - (br.width >> 1), 0, _screen.width - br.width);
 
	x = Clamp(_cursor.pos.x - (br.width >> 1), 0, _screen.width - br.width);
 

	
 
	w = AllocateWindow(x, y, br.width, br.height, TooltipsWndProc, WC_TOOLTIPS, _tooltips_widgets);
 

	
 
	WP(w, tooltips_d).string_id = str;
 
	assert(sizeof(WP(w, tooltips_d).params[0]) == sizeof(params[0]));
 
	memcpy(WP(w, tooltips_d).params, params, sizeof(WP(w, tooltips_d).params[0]) * paramcount);
 
	WP(w, tooltips_d).paramcount = paramcount;
 

	
 
	w->flags4 &= ~WF_WHITE_BORDER_MASK; // remove white-border from tooltip
 
	w->widget[0].right = br.width;
 
	w->widget[0].bottom = br.height;
 
}
 

	
 

	
 
static void DrawStationCoverageText(const AcceptedCargo accepts,
 
	int str_x, int str_y, StationCoverageType sct)
 
{
 
	char *b = _userstring;
 
	bool first = true;
 

	
 
	b = InlineString(b, STR_000D_ACCEPTS);
 

	
 
	for (CargoID i = 0; i < NUM_CARGO; i++) {
 
		if (b >= lastof(_userstring) - 5) break;
 
@@ -1917,49 +1917,49 @@ static void CheatsWndProc(Window *w, Win
 
			uint x = e->we.click.pt.x;
 

	
 
			/* not clicking a button? */
 
			if (!IS_INT_INSIDE(x, 20, 40) || btn >= lengthof(_cheats_ui)) break;
 

	
 
			ce = &_cheats_ui[btn];
 
			oldvalue = value = (int32)ReadValue(ce->variable, ce->type);
 

	
 
			*ce->been_used = true;
 

	
 
			switch (ce->type) {
 
			case SLE_BOOL:
 
				if (ce->flags & CE_CLICK) WP(w,def_d).data_1 = btn * 2 + 1;
 
				value ^= 1;
 
				if (ce->proc != NULL) ce->proc(value, 0);
 
				break;
 
			default: {
 
				/* Add a dynamic step-size to the scroller. In a maximum of
 
				 * 50-steps you should be able to get from min to max */
 
				uint16 step = ((ce->max - ce->min) / 20);
 
				if (step == 0) step = 1;
 

	
 
				/* Increase or decrease the value and clamp it to extremes */
 
				value += (x >= 30) ? step : -step;
 
				value = clamp(value, ce->min, ce->max);
 
				value = Clamp(value, ce->min, ce->max);
 

	
 
				/* take whatever the function returns */
 
				value = ce->proc(value, (x >= 30) ? 1 : -1);
 

	
 
				if (value != oldvalue) {
 
					WP(w,def_d).data_1 = btn * 2 + 1 + ((x >= 30) ? 1 : 0);
 
				}
 
			} break;
 
			}
 

	
 
			if (value != oldvalue) {
 
				WriteValue(ce->variable, ce->type, (int64)value);
 
				SetWindowDirty(w);
 
			}
 

	
 
			w->flags4 |= 5 << WF_TIMEOUT_SHL;
 

	
 
			SetWindowDirty(w);
 
		}
 
		break;
 
	case WE_TIMEOUT:
 
		WP(w,def_d).data_1 = 0;
 
		SetWindowDirty(w);
 
		break;
src/network/core/udp.cpp
Show inline comments
 
@@ -209,50 +209,50 @@ void NetworkUDPSocketHandler::Recv_Netwo
 
	 *              Please observe the order.
 
	 * The parts must be read in the same order as they are sent!
 
	 */
 

	
 
	/* Update the documentation in udp.h on changes
 
	 * to the NetworkGameInfo wire-protocol! */
 

	
 
	switch (info->game_info_version) {
 
		case 4: {
 
			GRFConfig **dst = &info->grfconfig;
 
			uint i;
 
			uint num_grfs = p->Recv_uint8();
 

	
 
			for (i = 0; i < num_grfs; i++) {
 
				GRFConfig *c = CallocT<GRFConfig>(1);
 
				this->Recv_GRFIdentifier(p, c);
 
				this->HandleIncomingNetworkGameInfoGRFConfig(c);
 

	
 
				/* Append GRFConfig to the list */
 
				*dst = c;
 
				dst = &c->next;
 
			}
 
		} /* Fallthrough */
 
		case 3:
 
			info->game_date      = clamp(p->Recv_uint32(), 0, MAX_DATE);
 
			info->start_date     = clamp(p->Recv_uint32(), 0, MAX_DATE);
 
			info->game_date      = Clamp(p->Recv_uint32(), 0, MAX_DATE);
 
			info->start_date     = Clamp(p->Recv_uint32(), 0, MAX_DATE);
 
			/* Fallthrough */
 
		case 2:
 
			info->companies_max  = p->Recv_uint8 ();
 
			info->companies_on   = p->Recv_uint8 ();
 
			info->spectators_max = p->Recv_uint8 ();
 
			/* Fallthrough */
 
		case 1:
 
			p->Recv_string(info->server_name,     sizeof(info->server_name));
 
			p->Recv_string(info->server_revision, sizeof(info->server_revision));
 
			info->server_lang    = p->Recv_uint8 ();
 
			info->use_password   = p->Recv_bool  ();
 
			info->clients_max    = p->Recv_uint8 ();
 
			info->clients_on     = p->Recv_uint8 ();
 
			info->spectators_on  = p->Recv_uint8 ();
 
			if (info->game_info_version < 3) { // 16 bits dates got scrapped and are read earlier
 
				info->game_date    = p->Recv_uint16() + DAYS_TILL_ORIGINAL_BASE_YEAR;
 
				info->start_date   = p->Recv_uint16() + DAYS_TILL_ORIGINAL_BASE_YEAR;
 
			}
 
			p->Recv_string(info->map_name, sizeof(info->map_name));
 
			info->map_width      = p->Recv_uint16();
 
			info->map_height     = p->Recv_uint16();
 
			info->map_set        = p->Recv_uint8 ();
 
			info->dedicated      = p->Recv_bool  ();
 

	
src/network/network_gui.cpp
Show inline comments
 
@@ -671,51 +671,51 @@ static void NetworkStartServerWindowWndP
 
			ShowQueryString(BindCString(_network_server_password), STR_NETWORK_SET_PASSWORD, 20, 250, w, CS_ALPHANUMERAL);
 
			break;
 

	
 
		case 5: { /* Select map */
 
			int y = (e->we.click.pt.y - NSSWND_START) / NSSWND_ROWSIZE;
 

	
 
			y += w->vscroll.pos;
 
			if (y >= w->vscroll.count) return;
 

	
 
			nd->map = (y == 0) ? NULL : _fios_list + y - 1;
 
			SetWindowDirty(w);
 
			} break;
 
		case 7: case 8: /* Connection type */
 
			ShowDropDownMenu(w, _connection_types_dropdown, _network_advertise, 8, 0, 0); // do it for widget 8
 
			break;
 
		case  9: case 11: // Click on up/down button for number of players
 
		case 12: case 14: // Click on up/down button for number of companies
 
		case 15: case 17: // Click on up/down button for number of spectators
 
			/* Don't allow too fast scrolling */
 
			if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) {
 
				HandleButtonClick(w, e->we.click.widget);
 
				SetWindowDirty(w);
 
				switch (e->we.click.widget) {
 
					default: NOT_REACHED();
 
					case  9: case 11: _network_game_info.clients_max    = clamp(_network_game_info.clients_max    + e->we.click.widget - 10, 2, MAX_CLIENTS); break;
 
					case 12: case 14: _network_game_info.companies_max  = clamp(_network_game_info.companies_max  + e->we.click.widget - 13, 1, MAX_PLAYERS); break;
 
					case 15: case 17: _network_game_info.spectators_max = clamp(_network_game_info.spectators_max + e->we.click.widget - 16, 0, MAX_CLIENTS); break;
 
					case  9: case 11: _network_game_info.clients_max    = Clamp(_network_game_info.clients_max    + e->we.click.widget - 10, 2, MAX_CLIENTS); break;
 
					case 12: case 14: _network_game_info.companies_max  = Clamp(_network_game_info.companies_max  + e->we.click.widget - 13, 1, MAX_PLAYERS); break;
 
					case 15: case 17: _network_game_info.spectators_max = Clamp(_network_game_info.spectators_max + e->we.click.widget - 16, 0, MAX_CLIENTS); break;
 
				}
 
			}
 
			_left_button_clicked = false;
 
			break;
 
		case 10: // Click on number of players
 
			nd->widget_id = 10;
 
			SetDParam(0, _network_game_info.clients_max);
 
			ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_NETWORK_NUMBER_OF_CLIENTS, 3, 50, w, CS_NUMERAL);
 
			break;
 
		case 13: // Click on number of companies
 
			nd->widget_id = 13;
 
			SetDParam(0, _network_game_info.companies_max);
 
			ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_NETWORK_NUMBER_OF_COMPANIES, 3, 50, w, CS_NUMERAL);
 
			break;
 
		case 16: // Click on number of companies
 
			nd->widget_id = 16;
 
			SetDParam(0, _network_game_info.spectators_max);
 
			ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_NETWORK_NUMBER_OF_SPECTATORS, 3, 50, w, CS_NUMERAL);
 
			break;
 
		case 18: case 19: { /* Language */
 
			uint sel = 0;
 
			for (uint i = 0; i < lengthof(_language_dropdown) - 1; i++) {
 
				if (_language_dropdown[i] == STR_NETWORK_LANG_ANY + _network_game_info.server_lang) {
 
					sel = i;
 
@@ -768,51 +768,51 @@ static void NetworkStartServerWindowWndP
 

	
 
	case WE_MOUSELOOP:
 
		if (nd->field == 3) HandleEditBox(w, &WP(w, network_ql_d).q, 3);
 
		break;
 

	
 
	case WE_KEYPRESS:
 
		if (nd->field == 3) {
 
			if (HandleEditBoxKey(w, &WP(w, network_ql_d).q, 3, e) == 1) break; // enter pressed
 

	
 
			ttd_strlcpy(_network_server_name, WP(w, network_ql_d).q.text.buf, sizeof(_network_server_name));
 
		}
 
		break;
 

	
 
	case WE_ON_EDIT_TEXT:
 
		if (e->we.edittext.str == NULL) break;
 

	
 
		if (nd->widget_id == 4) {
 
			ttd_strlcpy(_network_server_password, e->we.edittext.str, lengthof(_network_server_password));
 
			_network_game_info.use_password = (_network_server_password[0] != '\0');
 
		} else {
 
			int32 value = atoi(e->we.edittext.str);
 
			InvalidateWidget(w, nd->widget_id);
 
			switch (nd->widget_id) {
 
				default: NOT_REACHED();
 
				case 10: _network_game_info.clients_max    = clamp(value, 2, MAX_CLIENTS); break;
 
				case 13: _network_game_info.companies_max  = clamp(value, 1, MAX_PLAYERS); break;
 
				case 16: _network_game_info.spectators_max = clamp(value, 0, MAX_CLIENTS); break;
 
				case 10: _network_game_info.clients_max    = Clamp(value, 2, MAX_CLIENTS); break;
 
				case 13: _network_game_info.companies_max  = Clamp(value, 1, MAX_PLAYERS); break;
 
				case 16: _network_game_info.spectators_max = Clamp(value, 0, MAX_CLIENTS); break;
 
			}
 
		}
 

	
 
		SetWindowDirty(w);
 
		break;
 
	}
 
}
 

	
 
static const Widget _network_start_server_window_widgets[] = {
 
{   WWT_CLOSEBOX,   RESIZE_NONE,   BGC,     0,    10,     0,    13, STR_00C5,                       STR_018B_CLOSE_WINDOW },
 
{    WWT_CAPTION,   RESIZE_NONE,   BGC,    11,   419,     0,    13, STR_NETWORK_START_GAME_WINDOW,  STR_NULL},
 
{      WWT_PANEL,   RESIZE_NONE,   BGC,     0,   419,    14,   243, 0x0,                            STR_NULL},
 

	
 
{      WWT_PANEL,   RESIZE_NONE,   BGC,   100,   272,    22,    33, 0x0,                            STR_NETWORK_NEW_GAME_NAME_TIP},
 
{ WWT_PUSHTXTBTN,   RESIZE_NONE,   BTC,   285,   405,    22,    33, STR_NETWORK_SET_PASSWORD,       STR_NETWORK_PASSWORD_TIP},
 

	
 
{      WWT_INSET,   RESIZE_NONE,   BGC,    10,   271,    62,   216, 0x0,                            STR_NETWORK_SELECT_MAP_TIP},
 
{  WWT_SCROLLBAR,   RESIZE_NONE,   BGC,   259,   270,    63,   215, 0x0,                            STR_0190_SCROLL_BAR_SCROLLS_LIST},
 
/* Combo/selection boxes to control Connection Type / Max Clients / Max Companies / Max Observers / Language */
 
{      WWT_INSET,   RESIZE_NONE,   BGC,   280,   410,    77,    88, STR_NETWORK_LAN_INTERNET_COMBO, STR_NETWORK_CONNECTION_TIP},
 
{    WWT_TEXTBTN,   RESIZE_NONE,   BGC,   399,   409,    78,    87, STR_0225,                       STR_NETWORK_CONNECTION_TIP},
 
{     WWT_IMGBTN,   RESIZE_NONE,   BGC,   280,   291,   109,   120, SPR_ARROW_DOWN,                 STR_NETWORK_NUMBER_OF_CLIENTS_TIP},
 
{ WWT_PUSHTXTBTN,   RESIZE_NONE,   BGC,   292,   397,   109,   120, STR_NETWORK_CLIENTS_SELECT,     STR_NETWORK_NUMBER_OF_CLIENTS_TIP},
 
{     WWT_IMGBTN,   RESIZE_NONE,   BGC,   398,   410,   109,   120, SPR_ARROW_UP,                   STR_NETWORK_NUMBER_OF_CLIENTS_TIP},
src/newgrf.cpp
Show inline comments
 
@@ -1172,49 +1172,49 @@ static bool BridgeChangeInfo(uint brid, 
 
					}
 

	
 
					for (byte sprite = 0; sprite < 32; sprite++) {
 
						SpriteID image = grf_load_word(&buf);
 
						SpriteID pal   = grf_load_word(&buf);
 

	
 
						if (HASBIT(pal, 15)) {
 
							SETBIT(image, PALETTE_MODIFIER_TRANSPARENT);
 
						}
 

	
 
						/* Clear old color modifer bit */
 
						CLRBIT(image, 15);
 

	
 
						bridge->sprite_table[tableid][sprite].sprite = image;
 
						bridge->sprite_table[tableid][sprite].pal    = pal;
 
					}
 
				}
 
			} break;
 

	
 
			case 0x0E: // Flags; bit 0 - disable far pillars
 
				bridge->flags = grf_load_byte(&buf);
 
				break;
 

	
 
			case 0x0F: // Long format year of availability (year since year 0)
 
				bridge->avail_year = clamp(grf_load_dword(&buf), MIN_YEAR, MAX_YEAR);
 
				bridge->avail_year = Clamp(grf_load_dword(&buf), MIN_YEAR, MAX_YEAR);
 
				break;
 

	
 
			default:
 
				ret = true;
 
				break;
 
		}
 
	}
 

	
 
	*bufp = buf;
 
	return ret;
 
}
 

	
 
static bool TownHouseChangeInfo(uint hid, int numinfo, int prop, byte **bufp, int len)
 
{
 
	byte *buf = *bufp;
 
	bool ret = false;
 

	
 
	if (hid + numinfo > HOUSE_MAX) {
 
		grfmsg(1, "TownHouseChangeInfo: Too many houses loaded (%u), max (%u). Ignoring.", hid + numinfo, HOUSE_MAX);
 
		return false;
 
	}
 

	
 
	/* Allocate house specs if they haven't been allocated already. */
 
	if (_cur_grffile->housespec == NULL) {
 
@@ -1349,49 +1349,49 @@ static bool TownHouseChangeInfo(uint hid
 
				_house_mngr.Add(hid + i, _cur_grffile->grfid, override);
 
			} break;
 

	
 
			case 0x16: // Periodic refresh multiplier
 
				housespec->processing_time = grf_load_byte(&buf);
 
				break;
 

	
 
			case 0x17: // Four random colours to use
 
				for (uint j = 0; j < 4; j++) housespec->random_colour[j] = grf_load_byte(&buf);
 
				break;
 

	
 
			case 0x18: // Relative probability of appearing
 
				housespec->probability = grf_load_byte(&buf);
 
				break;
 

	
 
			case 0x19: // Extra flags
 
				housespec->extra_flags = (HouseExtraFlags)grf_load_byte(&buf);
 
				break;
 

	
 
			case 0x1A: // Animation frames
 
				housespec->animation_frames = grf_load_byte(&buf);
 
				break;
 

	
 
			case 0x1B: // Animation speed
 
				housespec->animation_speed = clamp(grf_load_byte(&buf), 2, 16);
 
				housespec->animation_speed = Clamp(grf_load_byte(&buf), 2, 16);
 
				break;
 

	
 
			case 0x1C: // Class of the building type
 
				housespec->class_id = AllocateHouseClassID(grf_load_byte(&buf), _cur_grffile->grfid);
 
				break;
 

	
 
			case 0x1D: // Callback flags 2
 
				housespec->callback_mask |= (grf_load_byte(&buf) << 8);
 
				break;
 

	
 
			case 0x1E: { // Accepted cargo types
 
				uint32 cargotypes = grf_load_dword(&buf);
 

	
 
				/* Check if the cargo types should not be changed */
 
				if (cargotypes == 0xFFFFFFFF) break;
 

	
 
				for (uint j = 0; j < 3; j++) {
 
					/* Get the cargo number from the 'list' */
 
					uint8 cargo_part = GB(cargotypes, 8 * j, 8);
 
					CargoID cargo = GetCargoTranslation(cargo_part, _cur_grffile);
 

	
 
					if (cargo == CT_INVALID) {
 
						/* Disable acceptance of invalid cargo type */
 
						housespec->cargo_acceptance[j] = 0;
 
@@ -3388,49 +3388,49 @@ static void GraphicsNew(byte *buf, int l
 
	}
 

	
 
	_skip_sprites = skip_num;
 
}
 

	
 
/* Action 0x05 (SKIP) */
 
static void SkipAct5(byte *buf, int len)
 
{
 
	if (!check_length(len, 2, "SkipAct5")) return;
 
	buf++;
 

	
 
	/* Ignore type byte */
 
	grf_load_byte(&buf);
 

	
 
	/* Skip the sprites of this action */
 
	_skip_sprites = grf_load_extended(&buf);
 

	
 
	grfmsg(3, "SkipAct5: Skipping %d sprites", _skip_sprites);
 
}
 

	
 
static uint32 GetParamVal(byte param, uint32 *cond_val)
 
{
 
	switch (param) {
 
		case 0x81: // current year
 
			return clamp(_cur_year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR;
 
			return Clamp(_cur_year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR;
 

	
 
		case 0x83: // current climate, 0=temp, 1=arctic, 2=trop, 3=toyland
 
			return _opt.landscape;
 

	
 
		case 0x84: { // GRF loading stage
 
			uint32 res = 0;
 

	
 
			if (_cur_stage > GLS_INIT) SETBIT(res, 0);
 
			if (_cur_stage == GLS_RESERVE) SETBIT(res, 8);
 
			if (_cur_stage == GLS_ACTIVATION) SETBIT(res, 9);
 
			return res;
 
		}
 

	
 
		case 0x85: // TTDPatch flags, only for bit tests
 
			if (cond_val == NULL) {
 
				/* Supported in Action 0x07 and 0x09, not 0x0D */
 
				return 0;
 
			} else {
 
				uint32 param_val = _ttdpatch_flags[*cond_val / 0x20];
 
				*cond_val %= 0x20;
 
				return param_val;
 
			}
 

	
 
		case 0x86: // road traffic side, bit 4 clear=left, set=right
src/newgrf_engine.cpp
Show inline comments
 
@@ -475,49 +475,49 @@ static uint8 LiveryHelper(EngineID engin
 
	const Livery *l;
 

	
 
	if (v == NULL) {
 
		l = GetEngineLivery(engine, _current_player, INVALID_ENGINE, NULL);
 
	} else if (v->type == VEH_TRAIN) {
 
		l = GetEngineLivery((v->u.rail.first_engine != INVALID_ENGINE && (IsArticulatedPart(v) || UsesWagonOverride(v))) ? v->u.rail.first_engine : v->engine_type, v->owner, v->u.rail.first_engine, v);
 
	} else {
 
		l = GetEngineLivery(v->engine_type, v->owner, INVALID_ENGINE, v);
 
	}
 

	
 
	return l->colour1 + l->colour2 * 16;
 
}
 

	
 

	
 
static uint32 VehicleGetVariable(const ResolverObject *object, byte variable, byte parameter, bool *available)
 
{
 
	const Vehicle *v = GRV(object);
 

	
 
	if (v == NULL) {
 
		/* Vehicle does not exist, so we're in a purchase list */
 
		switch (variable) {
 
			case 0x43: return _current_player | (LiveryHelper(object->u.vehicle.self_type, NULL) << 24); // Owner information
 
			case 0x46: return 0;               // Motion counter
 
			case 0x48: return GetEngine(object->u.vehicle.self_type)->flags; // Vehicle Type Info
 
			case 0xC4: return clamp(_cur_year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR; // Build year
 
			case 0xC4: return Clamp(_cur_year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR; // Build year
 
			case 0xDA: return INVALID_VEHICLE; // Next vehicle
 
			case 0x7F: return GetGRFParameter(object->u.vehicle.self_type, parameter); // Read GRF parameter
 
		}
 

	
 
		*available = false;
 
		return UINT_MAX;
 
	}
 

	
 
	/* Calculated vehicle parameters */
 
	switch (variable) {
 
		case 0x40: // Get length of consist
 
		case 0x41: // Get length of same consecutive wagons
 
			{
 
				const Vehicle* u;
 
				byte chain_before = 0;
 
				byte chain_after  = 0;
 

	
 
				for (u = v->First(); u != v; u = u->Next()) {
 
					chain_before++;
 
					if (variable == 0x41 && u->engine_type != v->engine_type) chain_before = 0;
 
				}
 

	
 
				while (u->Next() != NULL && (variable == 0x40 || u->Next()->engine_type == v->engine_type)) {
 
					chain_after++;
 
@@ -690,49 +690,49 @@ static uint32 VehicleGetVariable(const R
 
		case 0x1B: return GB(v->x_pos, 8, 8);
 
		case 0x1C: return v->y_pos;
 
		case 0x1D: return GB(v->y_pos, 8, 8);
 
		case 0x1E: return v->z_pos;
 
		case 0x1F: return object->info_view ? DIR_W : v->direction;
 
		case 0x28: return v->cur_image;
 
		case 0x29: return GB(v->cur_image, 8, 8);
 
		case 0x32: return v->vehstatus;
 
		case 0x33: return 0; // non-existent high byte of vehstatus
 
		case 0x34: return v->cur_speed;
 
		case 0x35: return GB(v->cur_speed, 8, 8);
 
		case 0x36: return v->subspeed;
 
		case 0x37: return v->acceleration;
 
		case 0x39: return v->cargo_type;
 
		case 0x3A: return v->cargo_cap;
 
		case 0x3B: return GB(v->cargo_cap, 8, 8);
 
		case 0x3C: return v->cargo.Count();
 
		case 0x3D: return GB(v->cargo.Count(), 8, 8);
 
		case 0x3E: return v->cargo.Source();
 
		case 0x3F: return v->cargo.DaysInTransit();
 
		case 0x40: return v->age;
 
		case 0x41: return GB(v->age, 8, 8);
 
		case 0x42: return v->max_age;
 
		case 0x43: return GB(v->max_age, 8, 8);
 
		case 0x44: return clamp(v->build_year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR;
 
		case 0x44: return Clamp(v->build_year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR;
 
		case 0x45: return v->unitnumber;
 
		case 0x46: return v->engine_type;
 
		case 0x47: return GB(v->engine_type, 8, 8);
 
		case 0x48: return v->spritenum;
 
		case 0x49: return v->day_counter;
 
		case 0x4A: return v->breakdowns_since_last_service;
 
		case 0x4B: return v->breakdown_ctr;
 
		case 0x4C: return v->breakdown_delay;
 
		case 0x4D: return v->breakdown_chance;
 
		case 0x4E: return v->reliability;
 
		case 0x4F: return GB(v->reliability, 8, 8);
 
		case 0x50: return v->reliability_spd_dec;
 
		case 0x51: return GB(v->reliability_spd_dec, 8, 8);
 
		case 0x52: return ClampToI32(v->profit_this_year);
 
		case 0x53: return GB(ClampToI32(v->profit_this_year),  8, 24);
 
		case 0x54: return GB(ClampToI32(v->profit_this_year), 16, 16);
 
		case 0x55: return GB(ClampToI32(v->profit_this_year), 24,  8);
 
		case 0x56: return ClampToI32(v->profit_last_year);
 
		case 0x57: return GB(ClampToI32(v->profit_last_year),  8, 24);
 
		case 0x58: return GB(ClampToI32(v->profit_last_year), 16, 16);
 
		case 0x59: return GB(ClampToI32(v->profit_last_year), 24,  8);
 
		case 0x5A: return v->Next() == NULL ? INVALID_VEHICLE : v->Next()->index;
 
		case 0x5C: return ClampToI32(v->value);
 
		case 0x5D: return GB(ClampToI32(v->value),  8, 24);
src/newgrf_house.cpp
Show inline comments
 
@@ -190,49 +190,49 @@ uint32 GetNearbyTileInformation(byte par
 
	Slope tileh = GetTileSlope(tile, &z);
 
	return GetTileType(tile) << 24 | z << 16 | tile_type << 8 | tileh;
 
}
 

	
 
/**
 
 * HouseGetVariable():
 
 *
 
 * Used by the resolver to get values for feature 07 deterministic spritegroups.
 
 */
 
static uint32 HouseGetVariable(const ResolverObject *object, byte variable, byte parameter, bool *available)
 
{
 
	const Town *town = object->u.house.town;
 
	TileIndex tile   = object->u.house.tile;
 
	HouseID house_id = object->u.house.house_id;
 

	
 
	if (object->scope == VSG_SCOPE_PARENT) {
 
		return TownGetVariable(variable, parameter, available, town);
 
	}
 

	
 
	switch (variable) {
 
		/* Construction stage. */
 
		case 0x40: return (IsTileType(tile, MP_HOUSE) ? GetHouseBuildingStage(tile) : 0) | OriginalTileRandomiser(TileX(tile), TileY(tile)) << 2;
 

	
 
		/* Building age. */
 
		case 0x41: return clamp(_cur_year - GetHouseConstructionYear(tile), 0, 0xFF);
 
		case 0x41: return Clamp(_cur_year - GetHouseConstructionYear(tile), 0, 0xFF);
 

	
 
		/* Town zone */
 
		case 0x42: return GetTownRadiusGroup(town, tile);
 

	
 
		/* Terrain type */
 
		case 0x43: return GetTerrainType(tile);
 

	
 
		/* Number of this type of building on the map. */
 
		case 0x44: return GetNumHouses(house_id, town);
 

	
 
		/* Whether the town is being created or just expanded. */
 
		case 0x45: return _generating_world ? 1 : 0;
 

	
 
		/* Current animation frame. */
 
		case 0x46: return IsTileType(tile, MP_HOUSE) ? GetHouseAnimationFrame(tile) : 0;
 

	
 

	
 
		/* Building counts for old houses with id = parameter. */
 
		case 0x60: return GetNumHouses(parameter, town);
 

	
 
		/* Building counts for new houses with id = parameter. */
 
		case 0x61: {
 
			const HouseSpec *hs = GetHouseSpecs(house_id);
 
			if (hs->grffile == NULL) return 0;
 
@@ -348,62 +348,62 @@ void DrawTileLayout(const TileInfo *ti, 
 
			);
 
		} else {
 
			AddChildSpriteScreen(image, pal, (byte)dtss->delta_x, (byte)dtss->delta_y, IsTransparencySet(TO_HOUSES));
 
		}
 
	}
 
}
 

	
 
void DrawNewHouseTile(TileInfo *ti, HouseID house_id)
 
{
 
	const HouseSpec *hs = GetHouseSpecs(house_id);
 
	const SpriteGroup *group;
 
	ResolverObject object;
 

	
 
	if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, FOUNDATION_LEVELED);
 

	
 
	NewHouseResolver(&object, house_id, ti->tile, GetTownByTile(ti->tile));
 

	
 
	group = Resolve(hs->spritegroup, &object);
 
	if (group == NULL || group->type != SGT_TILELAYOUT) {
 
		/* XXX: This is for debugging purposes really, and shouldn't stay. */
 
		DrawGroundSprite(SPR_SHADOW_CELL, PAL_NONE);
 
	} else {
 
		/* Limit the building stage to the number of stages supplied. */
 
		byte stage = GetHouseBuildingStage(ti->tile);
 
		stage = clamp(stage - 4 + group->g.layout.num_sprites, 0, group->g.layout.num_sprites - 1);
 
		stage = Clamp(stage - 4 + group->g.layout.num_sprites, 0, group->g.layout.num_sprites - 1);
 
		DrawTileLayout(ti, group, stage, house_id);
 
	}
 
}
 

	
 
void AnimateNewHouseTile(TileIndex tile)
 
{
 
	const HouseSpec *hs = GetHouseSpecs(GetHouseType(tile));
 
	byte animation_speed = hs->animation_speed;
 
	bool frame_set_by_callback = false;
 

	
 
	if (HASBIT(hs->callback_mask, CBM_HOUSE_ANIMATION_SPEED)) {
 
		uint16 callback_res = GetHouseCallback(CBID_HOUSE_ANIMATION_SPEED, 0, 0, GetHouseType(tile), GetTownByTile(tile), tile);
 
		if (callback_res != CALLBACK_FAILED) animation_speed = clamp(callback_res & 0xFF, 2, 16);
 
		if (callback_res != CALLBACK_FAILED) animation_speed = Clamp(callback_res & 0xFF, 2, 16);
 
	}
 

	
 
	/* An animation speed of 2 means the animation frame changes 4 ticks, and
 
	 * increasing this value by one doubles the wait. 2 is the minimum value
 
	 * allowed for animation_speed, which corresponds to 120ms, and 16 is the
 
	 * maximum, corresponding to around 33 minutes. */
 
	if (_tick_counter % (1 << animation_speed) != 0) return;
 

	
 
	byte frame      = GetHouseAnimationFrame(tile);
 
	byte num_frames = GB(hs->animation_frames, 0, 7);
 

	
 
	if (HASBIT(hs->callback_mask, CBM_HOUSE_ANIMATION_NEXT_FRAME)) {
 
		uint32 param = (hs->extra_flags & CALLBACK_1A_RANDOM_BITS) ? Random() : 0;
 
		uint16 callback_res = GetHouseCallback(CBID_HOUSE_ANIMATION_NEXT_FRAME, param, 0, GetHouseType(tile), GetTownByTile(tile), tile);
 

	
 
		if (callback_res != CALLBACK_FAILED) {
 
			frame_set_by_callback = true;
 

	
 
			switch (callback_res & 0xFF) {
 
				case 0xFF:
 
					DeleteAnimatedTile(tile);
 
					break;
 
				case 0xFE:
 
					/* Carry on as normal. */
src/newgrf_industries.cpp
Show inline comments
 
@@ -294,56 +294,56 @@ uint32 IndustryGetVariable(const Resolve
 
		case 0x96: return industry->this_month_production[1];
 
		case 0x97: return GB(industry->this_month_production[1], 8, 8);
 
		/* amount of cargo transported so far THIS month. */
 
		case 0x98: return industry->this_month_transported[0];
 
		case 0x99: return GB(industry->this_month_transported[0], 8, 8);
 
		case 0x9A: return industry->this_month_transported[1];
 
		case 0x9B: return GB(industry->this_month_transported[0], 8, 8);
 
		/* fraction of cargo transported LAST month. */
 
		case 0x9C:
 
		case 0x9D: return industry->last_month_pct_transported[variable - 0x9C];
 
		/* amount of cargo produced LAST month. */
 
		case 0x9E: return industry->last_month_production[0];
 
		case 0x9F: return GB(industry->last_month_production[0], 8, 8);
 
		case 0xA0: return industry->last_month_production[1];
 
		case 0xA1: return GB(industry->last_month_production[1], 8, 8);
 
		/* amount of cargo transported last month. */
 
		case 0xA2: return industry->last_month_transported[0];
 
		case 0xA3: return GB(industry->last_month_transported[0], 8, 8);
 
		case 0xA4: return industry->last_month_transported[1];
 
		case 0xA5: return GB(industry->last_month_transported[0], 8, 8);
 

	
 
		case 0xA6: return industry->type;
 
		case 0xA7: return industry->founder;
 
		case 0xA8: return industry->random_color;
 
		case 0xA9: return clamp(0, industry->last_prod_year - 1920, 255);
 
		case 0xA9: return Clamp(0, industry->last_prod_year - 1920, 255);
 
		case 0xAA: return industry->counter;
 
		case 0xAB: return GB(industry->counter, 8, 8);
 
		case 0xAC: return industry->was_cargo_delivered;
 

	
 
		case 0xB0: return clamp(0, industry->construction_date - DAYS_TILL_ORIGINAL_BASE_YEAR, 65535); // Date when built since 1920 (in days)
 
		case 0xB0: return Clamp(0, industry->construction_date - DAYS_TILL_ORIGINAL_BASE_YEAR, 65535); // Date when built since 1920 (in days)
 
		case 0xB3: return industry->construction_type; // Construction type
 
		case 0xB4: return clamp(0, industry->last_cargo_accepted_at - DAYS_TILL_ORIGINAL_BASE_YEAR, 65535); // Date last cargo accepted since 1920 (in days)
 
		case 0xB4: return Clamp(0, industry->last_cargo_accepted_at - DAYS_TILL_ORIGINAL_BASE_YEAR, 65535); // Date last cargo accepted since 1920 (in days)
 
	}
 

	
 
	DEBUG(grf, 1, "Unhandled industry property 0x%X", variable);
 

	
 
	*available = false;
 
	return (uint32)-1;
 
}
 

	
 
static const SpriteGroup *IndustryResolveReal(const ResolverObject *object, const SpriteGroup *group)
 
{
 
	/* IndustryTile do not have 'real' groups */
 
	return NULL;
 
}
 

	
 
static uint32 IndustryGetRandomBits(const ResolverObject *object)
 
{
 
	return object->u.industry.ind == NULL ? 0 : object->u.industry.ind->random;
 
}
 

	
 
static uint32 IndustryGetTriggers(const ResolverObject *object)
 
{
 
	return object->u.industry.ind == NULL ? 0 : object->u.industry.ind->random_triggers;
 
}
 

	
 
@@ -494,52 +494,52 @@ static int32 DerefIndProd(uint field, bo
 
	return use_register ? (int32)GetRegister(field) : field;
 
}
 

	
 
/**
 
 * Get the industry production callback and apply it to the industry.
 
 * @param ind    the industry this callback has to be called for
 
 * @param reason the reason it is called (0 = incoming cargo, 1 = periodic tick callback)
 
 */
 
void IndustryProductionCallback(Industry *ind, int reason)
 
{
 
	const IndustrySpec *spec = GetIndustrySpec(ind->type);
 
	ResolverObject object;
 
	NewIndustryResolver(&object, ind->xy, ind);
 
	if ((spec->behaviour & INDUSTRYBEH_PRODCALLBACK_RANDOM) != 0) object.callback_param1 = Random();
 
	object.callback_param2 = reason;
 

	
 
	for (uint loop = 0;; loop++) {
 
		SB(object.callback_param2, 8, 16, loop);
 
		const SpriteGroup *group = Resolve(spec->grf_prop.spritegroup, &object);
 
		if (group == NULL || group->type != SGT_INDUSTRY_PRODUCTION) break;
 

	
 
		bool deref = (group->g.indprod.version == 1);
 

	
 
		for (uint i = 0; i < 3; i++) {
 
			ind->incoming_cargo_waiting[i] = clamp(ind->incoming_cargo_waiting[i] - DerefIndProd(group->g.indprod.substract_input[i], deref), 0, 0xFFFF);
 
			ind->incoming_cargo_waiting[i] = Clamp(ind->incoming_cargo_waiting[i] - DerefIndProd(group->g.indprod.substract_input[i], deref), 0, 0xFFFF);
 
		}
 
		for (uint i = 0; i < 2; i++) {
 
			ind->produced_cargo_waiting[i] = clamp(ind->produced_cargo_waiting[i] + DerefIndProd(group->g.indprod.add_output[i], deref), 0, 0xFFFF);
 
			ind->produced_cargo_waiting[i] = Clamp(ind->produced_cargo_waiting[i] + DerefIndProd(group->g.indprod.add_output[i], deref), 0, 0xFFFF);
 
		}
 

	
 
		int32 again = DerefIndProd(group->g.indprod.again, deref);
 
		if (again == 0) break;
 

	
 
		SB(object.callback_param2, 24, 8, again);
 
	}
 

	
 
	InvalidateWindow(WC_INDUSTRY_VIEW, ind->index);
 
}
 

	
 
void DoTriggerIndustry(Industry *ind, IndustryTileTrigger trigger)
 
{
 
	ResolverObject object;
 

	
 
	NewIndustryResolver(&object, ind->xy, ind);
 
	object.callback = CBID_RANDOM_TRIGGER;
 
	object.trigger = trigger;
 

	
 
	const SpriteGroup *group = Resolve(GetIndustrySpec(ind->type)->grf_prop.spritegroup, &object);
 
	if (group == NULL) return;
 

	
 
	byte new_random_bits = Random();
 
	ind->random &= ~object.reseed;
src/newgrf_industrytiles.cpp
Show inline comments
 
@@ -223,96 +223,96 @@ uint16 GetIndustryTileCallback(CallbackI
 
bool DrawNewIndustryTile(TileInfo *ti, Industry *i, IndustryGfx gfx, const IndustryTileSpec *inds)
 
{
 
	const SpriteGroup *group;
 
	ResolverObject object;
 

	
 
	if (ti->tileh != SLOPE_FLAT) {
 
		bool draw_old_one = true;
 
		if (HASBIT(inds->callback_flags, CBM_INDT_DRAW_FOUNDATIONS)) {
 
			/* Called to determine the type (if any) of foundation to draw for industry tile */
 
			uint32 callback_res = GetIndustryTileCallback(CBID_INDUSTRY_DRAW_FOUNDATIONS, 0, 0, gfx, i, ti->tile);
 
			draw_old_one = callback_res != 0;
 
		}
 

	
 
		if (draw_old_one) DrawFoundation(ti, FOUNDATION_LEVELED);
 
	}
 

	
 
	NewIndustryTileResolver(&object, gfx, ti->tile, i);
 

	
 
	group = Resolve(inds->grf_prop.spritegroup, &object);
 
	if (group == NULL || group->type != SGT_TILELAYOUT) {
 
		return false;
 
	} else {
 
		/* Limit the building stage to the number of stages supplied. */
 
		byte stage = GetIndustryConstructionStage(ti->tile);
 
		stage = clamp(stage - 4 + group->g.layout.num_sprites, 0, group->g.layout.num_sprites - 1);
 
		stage = Clamp(stage - 4 + group->g.layout.num_sprites, 0, group->g.layout.num_sprites - 1);
 
		IndustryDrawTileLayout(ti, group, i->random_color, stage, gfx);
 
		return true;
 
	}
 
}
 

	
 
extern bool IsSlopeRefused(Slope current, Slope refused);
 

	
 
bool PerformIndustryTileSlopeCheck(TileIndex ind_base_tile, TileIndex ind_tile, const IndustryTileSpec *its, IndustryType type, IndustryGfx gfx, uint itspec_index)
 
{
 
	Industry ind;
 
	ind.index = INVALID_INDUSTRY;
 
	ind.xy = ind_base_tile;
 
	ind.width = 0;
 
	ind.type = type;
 

	
 
	uint16 callback_res = GetIndustryTileCallback(CBID_INDTILE_SHAPE_CHECK, 0, itspec_index, gfx, &ind, ind_tile);
 
	if (callback_res == CALLBACK_FAILED) {
 
		return !IsSlopeRefused(GetTileSlope(ind_tile, NULL), its->slopes_refused);
 
	}
 
	if (its->grf_prop.grffile->grf_version < 7) {
 
		return callback_res != 0;
 
	}
 

	
 
	/* Copy some parameters from the registers to the error message text ref. stack */
 
	SwitchToErrorRefStack();
 
	PrepareTextRefStackUsage(4);
 
	SwitchToNormalRefStack();
 

	
 
	switch (callback_res) {
 
		case 0x400: return true;
 
		case 0x401: _error_message = STR_0239_SITE_UNSUITABLE;                 return false;
 
		case 0x402: _error_message = STR_0317_CAN_ONLY_BE_BUILT_IN_RAINFOREST; return false;
 
		case 0x403: _error_message = STR_0318_CAN_ONLY_BE_BUILT_IN_DESERT;     return false;
 
		default: _error_message = GetGRFStringID(its->grf_prop.grffile->grfid, 0xD000 + callback_res); return false;
 
	}
 
}
 

	
 
void AnimateNewIndustryTile(TileIndex tile)
 
{
 
	Industry *ind = GetIndustryByTile(tile);
 
	IndustryGfx gfx = GetIndustryGfx(tile);
 
	const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);
 
	byte animation_speed = itspec->animation_speed;
 

	
 
	if (HASBIT(itspec->callback_flags, CBM_INDT_ANIM_SPEED)) {
 
		uint16 callback_res = GetIndustryTileCallback(CBID_INDTILE_ANIMATION_SPEED, 0, 0, gfx, ind, tile);
 
		if (callback_res != CALLBACK_FAILED) animation_speed = clamp(callback_res & 0xFF, 0, 16);
 
		if (callback_res != CALLBACK_FAILED) animation_speed = Clamp(callback_res & 0xFF, 0, 16);
 
	}
 

	
 
	/* An animation speed of 2 means the animation frame changes 4 ticks, and
 
	 * increasing this value by one doubles the wait. 0 is the minimum value
 
	 * allowed for animation_speed, which corresponds to 30ms, and 16 is the
 
	 * maximum, corresponding to around 33 minutes. */
 
	if ((_tick_counter % (1 << animation_speed)) != 0) return;
 

	
 
	bool frame_set_by_callback = false;
 
	byte frame = GetIndustryAnimationState(tile);
 
	uint16 num_frames = GB(itspec->animation_info, 0, 8);
 

	
 
	if (HASBIT(itspec->callback_flags, CBM_INDT_ANIM_NEXT_FRAME)) {
 
		uint16 callback_res = GetIndustryTileCallback(CBID_INDTILE_ANIM_NEXT_FRAME, HASBIT(itspec->animation_special_flags, 0) ? Random() : 0, 0, gfx, ind, tile);
 

	
 
		if (callback_res != CALLBACK_FAILED) {
 
			frame_set_by_callback = true;
 

	
 
			switch (callback_res & 0xFF) {
 
				case 0xFF:
 
					DeleteAnimatedTile(tile);
 
					break;
 
				case 0xFE:
 
					/* Carry on as normal. */
src/newgrf_spritegroup.cpp
Show inline comments
 
@@ -63,49 +63,49 @@ SpriteGroup *AllocateSpriteGroup()
 
	/* This is totally different to the other pool allocators, as we never remove an item from the pool. */
 
	if (_spritegroup_count == GetSpriteGroupPoolSize()) {
 
		if (!_SpriteGroup_pool.AddBlockToPool()) return NULL;
 
	}
 

	
 
	return GetSpriteGroup(_spritegroup_count++);
 
}
 

	
 

	
 
void InitializeSpriteGroupPool()
 
{
 
	_SpriteGroup_pool.CleanPool();
 

	
 
	_spritegroup_count = 0;
 
}
 

	
 
TemporaryStorageArray<uint32, 0x110> _temp_store;
 

	
 

	
 
static inline uint32 GetVariable(const ResolverObject *object, byte variable, byte parameter, bool *available)
 
{
 
	/* Return common variables */
 
	switch (variable) {
 
		case 0x00: return max(_date - DAYS_TILL_ORIGINAL_BASE_YEAR, 0);
 
		case 0x01: return clamp(_cur_year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR;
 
		case 0x01: return Clamp(_cur_year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR;
 
		case 0x02: return _cur_month;
 
		case 0x03: return _opt.landscape;
 
		case 0x09: return _date_fract;
 
		case 0x0A: return _tick_counter;
 
		case 0x0C: return object->callback;
 
		case 0x10: return object->callback_param1;
 
		case 0x11: return 0;
 
		case 0x18: return object->callback_param2;
 
		case 0x1A: return UINT_MAX;
 
		case 0x1B: return GB(_display_opt, 0, 6);
 
		case 0x1C: return object->last_value;
 
		case 0x20: return _opt.landscape == LT_ARCTIC ? GetSnowLine() : 0xFF;
 

	
 
		case 0x7D: return _temp_store.Get(parameter);
 

	
 
		/* Not a common variable, so evalute the feature specific variables */
 
		default: return object->GetVariable(object, variable, parameter, available);
 
	}
 
}
 

	
 

	
 
/**
 
 * Rotate val rot times to the right
 
 * @param val the value to rotate
src/newgrf_station.cpp
Show inline comments
 
@@ -371,49 +371,49 @@ static uint32 StationGetVariable(const R
 

	
 
		if (st != NULL) {
 
			t = st->town;
 
		} else if (tile != INVALID_TILE) {
 
			t = GetTownByTile(tile);
 
		} else {
 
			*available = false;
 
			return UINT_MAX;
 
		}
 

	
 
		return TownGetVariable(variable, parameter, available, t);
 
	}
 

	
 
	if (st == NULL) {
 
		/* Station does not exist, so we're in a purchase list */
 
		switch (variable) {
 
			case 0x40:
 
			case 0x41:
 
			case 0x46:
 
			case 0x47:
 
			case 0x49: return 0x2110000;       // Platforms, tracks & position
 
			case 0x42: return 0;               // Rail type (XXX Get current type from GUI?)
 
			case 0x43: return _current_player; // Station owner
 
			case 0x44: return 2;               // PBS status
 
			case 0xFA: return clamp(_date - DAYS_TILL_ORIGINAL_BASE_YEAR, 0, 65535); // Build date, clamped to a 16 bit value
 
			case 0xFA: return Clamp(_date - DAYS_TILL_ORIGINAL_BASE_YEAR, 0, 65535); // Build date, clamped to a 16 bit value
 
		}
 

	
 
		*available = false;
 
		return UINT_MAX;
 
	}
 

	
 
	switch (variable) {
 
		/* Calculated station variables */
 
		case 0x40:
 
			if (!HASBIT(_svc.valid, 0)) { _svc.v40 = GetPlatformInfoHelper(tile, false, false, false); SETBIT(_svc.valid, 0); }
 
			return _svc.v40;
 

	
 
		case 0x41:
 
			if (!HASBIT(_svc.valid, 1)) { _svc.v41 = GetPlatformInfoHelper(tile, true,  false, false); SETBIT(_svc.valid, 1); }
 
			return _svc.v41;
 

	
 
		case 0x42: return GetTerrainType(tile) | (GetRailType(tile) << 8);
 
		case 0x43: return st->owner; // Station owner
 
		case 0x44: return 2;         // PBS status
 
		case 0x45:
 
			if (!HASBIT(_svc.valid, 2)) { _svc.v45 = GetRailContinuationInfo(tile); SETBIT(_svc.valid, 2); }
 
			return _svc.v45;
 

	
 
		case 0x46:
 
@@ -430,49 +430,49 @@ static uint32 StationGetVariable(const R
 

	
 
			for (cargo_type = 0; cargo_type < NUM_CARGO; cargo_type++) {
 
				if (HASBIT(st->goods[cargo_type].acceptance_pickup, GoodsEntry::PICKUP)) SETBIT(value, cargo_type);
 
			}
 
			return value;
 
		}
 
		case 0x49:
 
			if (!HASBIT(_svc.valid, 5)) { _svc.v49 = GetPlatformInfoHelper(tile, false, true, false); SETBIT(_svc.valid, 5); }
 
			return _svc.v49;
 

	
 
		/* Variables which use the parameter */
 
		/* Variables 0x60 to 0x65 are handled separately below */
 

	
 
		/* General station properties */
 
		case 0x82: return 50;
 
		case 0x84: return st->string_id;
 
		case 0x86: return 0;
 
		case 0x8A: return st->had_vehicle_of_type;
 
		case 0xF0: return st->facilities;
 
		case 0xF1: return st->airport_type;
 
		case 0xF2: return st->truck_stops->status;
 
		case 0xF3: return st->bus_stops->status;
 
		case 0xF6: return st->airport_flags;
 
		case 0xF7: return GB(st->airport_flags, 8, 8);
 
		case 0xFA: return clamp(st->build_date - DAYS_TILL_ORIGINAL_BASE_YEAR, 0, 65535);
 
		case 0xFA: return Clamp(st->build_date - DAYS_TILL_ORIGINAL_BASE_YEAR, 0, 65535);
 
	}
 

	
 
	/* Handle cargo variables with parameter, 0x60 to 0x65 */
 
	if (variable >= 0x60 && variable <= 0x65) {
 
		CargoID c = GetCargoTranslation(parameter, object->u.station.statspec->grffile);
 

	
 
		if (c == CT_INVALID) return 0;
 
		const GoodsEntry *ge = &st->goods[c];
 

	
 
		switch (variable) {
 
			case 0x60: return min(ge->cargo.Count(), 4095);
 
			case 0x61: return ge->days_since_pickup;
 
			case 0x62: return ge->rating;
 
			case 0x63: return ge->cargo.DaysInTransit();
 
			case 0x64: return ge->last_speed | (ge->last_age << 8);
 
			case 0x65: return GB(ge->acceptance_pickup, GoodsEntry::ACCEPTANCE, 1) << 3;
 
		}
 
	}
 

	
 
	/* Handle cargo variables (deprecated) */
 
	if (variable >= 0x8C && variable <= 0xEC) {
 
		const GoodsEntry *g = &st->goods[GB(variable - 0x8C, 3, 4)];
 
		switch (GB(variable - 0x8C, 0, 3)) {
 
			case 0: return g->cargo.Count();
src/npf.cpp
Show inline comments
 
@@ -83,52 +83,52 @@ static uint NPFHash(uint key1, uint key2
 
}
 

	
 
static int32 NPFCalcZero(AyStar* as, AyStarNode* current, OpenListNode* parent)
 
{
 
	return 0;
 
}
 

	
 
/* Calcs the tile of given station that is closest to a given tile
 
 * for this we assume the station is a rectangle,
 
 * as defined by its top tile (st->train_tile) and its width/height (st->trainst_w, st->trainst_h)
 
 */
 
static TileIndex CalcClosestStationTile(StationID station, TileIndex tile)
 
{
 
	const Station* st = GetStation(station);
 

	
 
	uint minx = TileX(st->train_tile);  // topmost corner of station
 
	uint miny = TileY(st->train_tile);
 
	uint maxx = minx + st->trainst_w - 1; // lowermost corner of station
 
	uint maxy = miny + st->trainst_h - 1;
 
	uint x;
 
	uint y;
 

	
 
	/* we are going the aim for the x coordinate of the closest corner
 
	 * but if we are between those coordinates, we will aim for our own x coordinate */
 
	x = clamp(TileX(tile), minx, maxx);
 
	x = Clamp(TileX(tile), minx, maxx);
 

	
 
	/* same for y coordinate, see above comment */
 
	y = clamp(TileY(tile), miny, maxy);
 
	y = Clamp(TileY(tile), miny, maxy);
 

	
 
	/* return the tile of our target coordinates */
 
	return TileXY(x, y);
 
}
 

	
 
/* Calcs the heuristic to the target station or tile. For train stations, it
 
 * takes into account the direction of approach.
 
 */
 
static int32 NPFCalcStationOrTileHeuristic(AyStar* as, AyStarNode* current, OpenListNode* parent)
 
{
 
	NPFFindStationOrTileData* fstd = (NPFFindStationOrTileData*)as->user_target;
 
	NPFFoundTargetData* ftd = (NPFFoundTargetData*)as->user_path;
 
	TileIndex from = current->tile;
 
	TileIndex to = fstd->dest_coords;
 
	uint dist;
 

	
 
	/* for train-stations, we are going to aim for the closest station tile */
 
	if (as->user_data[NPF_TYPE] == TRANSPORT_RAIL && fstd->station_index != INVALID_STATION)
 
		to = CalcClosestStationTile(fstd->station_index, from);
 

	
 
	if (as->user_data[NPF_TYPE] == TRANSPORT_ROAD) {
 
		/* Since roads only have diagonal pieces, we use manhattan distance here */
 
		dist = DistanceManhattan(from, to) * NPF_TILE_LENGTH;
 
	} else {
src/oldloader.cpp
Show inline comments
 
@@ -1614,49 +1614,49 @@ static bool LoadOldMain(LoadgameState *l
 
				}
 
			} break;
 
			default: break;
 
		}
 
	}
 

	
 
	/* Make sure the available engines are really available, otherwise
 
	 * we will get a "new vehicle"-spree. */
 
	for (Engine *e = _engines; e != endof(_engines); e++) {
 
		if (_date >= (e->intro_date + 365)) {
 
			e->flags = (e->flags & ~ENGINE_EXCLUSIVE_PREVIEW) | ENGINE_AVAILABLE;
 
			AddRemoveEngineFromAutoreplaceAndBuildWindows(e->type);
 
			e->player_avail = (byte)-1;
 
		}
 
	}
 

	
 
	/* Fix the game to be compatible with OpenTTD */
 
	FixOldTowns();
 
	FixOldStations();
 
	FixOldVehicles();
 

	
 
	AddTypeToEngines();
 

	
 
	/* We have a new difficulty setting */
 
	_opt.diff.town_council_tolerance = clamp(_opt.diff_level, 0, 2);
 
	_opt.diff.town_council_tolerance = Clamp(_opt.diff_level, 0, 2);
 

	
 
	DEBUG(oldloader, 3, "Finished converting game data");
 
	DEBUG(oldloader, 1, "TTD(Patch) savegame successfully converted");
 

	
 
	return true;
 
}
 

	
 
bool LoadOldSaveGame(const char *file)
 
{
 
	LoadgameState ls;
 

	
 
	DEBUG(oldloader, 3, "Trying to load a TTD(Patch) savegame");
 

	
 
	InitLoading(&ls);
 

	
 
	/* Open file */
 
	ls.file = fopen(file, "rb");
 

	
 
	if (ls.file == NULL) {
 
		DEBUG(oldloader, 0, "Cannot open file '%s'", file);
 
		return false;
 
	}
 

	
 
	/* Load the main chunk */
src/openttd.cpp
Show inline comments
 
@@ -259,50 +259,50 @@ md_continue_here:;
 
					md->opt = (char*)t;
 
					md->cont = NULL;
 
					return *s;
 
				}
 
				md->opt = NULL;
 
				md->cont = s;
 
				return *s;
 
			}
 
		} else {
 
			/* This is currently not supported. */
 
			return -2;
 
		}
 
	}
 
}
 

	
 

	
 
static void ParseResolution(int res[2], const char *s)
 
{
 
	const char *t = strchr(s, 'x');
 
	if (t == NULL) {
 
		ShowInfoF("Invalid resolution '%s'", s);
 
		return;
 
	}
 

	
 
	res[0] = clamp(strtoul(s, NULL, 0), 64, MAX_SCREEN_WIDTH);
 
	res[1] = clamp(strtoul(t + 1, NULL, 0), 64, MAX_SCREEN_HEIGHT);
 
	res[0] = Clamp(strtoul(s, NULL, 0), 64, MAX_SCREEN_WIDTH);
 
	res[1] = Clamp(strtoul(t + 1, NULL, 0), 64, MAX_SCREEN_HEIGHT);
 
}
 

	
 
static void InitializeDynamicVariables()
 
{
 
	/* Dynamic stuff needs to be initialized somewhere... */
 
	_town_sort     = NULL;
 
	_industry_sort = NULL;
 
	_industry_mngr.ResetMapping();
 
	_industile_mngr.ResetMapping();
 
}
 

	
 

	
 
static void UnInitializeGame()
 
{
 
	UnInitWindowSystem();
 

	
 
	/* Uninitialize airport state machines */
 
	UnInitializeAirports();
 

	
 
	/* Uninitialize variables that are allocated dynamically */
 
	_Town_pool.CleanPool();
 
	_Industry_pool.CleanPool();
 
	_Station_pool.CleanPool();
 
	_Vehicle_pool.CleanPool();
src/players.cpp
Show inline comments
 
@@ -74,49 +74,49 @@ void DrawPlayerIcon(PlayerID p, int x, i
 
 * - 4 and 5: chin
 
 * - 6 to 9: eyebrows
 
 * - 10 to 13: nose
 
 * - 13 to 15: lips (also moustache for males)
 
 * - 16 to 19: hair
 
 * - 20 to 22: eye color
 
 * - 20 to 27: tie, ear rings etc.
 
 * - 28 to 30: glasses
 
 * - 19, 26 and 27: race (bit 27 set and bit 19 equal to bit 26 = black, otherwise white)
 
 * - 31: gender (0 = male, 1 = female)
 
 *
 
 * @param face the face in the old format
 
 * @return the face in the new format
 
 */
 
PlayerFace ConvertFromOldPlayerFace(uint32 face)
 
{
 
	PlayerFace pf = 0;
 
	GenderEthnicity ge = GE_WM;
 

	
 
	if (HASBIT(face, 31)) SetBitT(ge, GENDER_FEMALE);
 
	if (HASBIT(face, 27) && (HASBIT(face, 26) == HASBIT(face, 19))) SetBitT(ge, ETHNICITY_BLACK);
 

	
 
	SetPlayerFaceBits(pf, PFV_GEN_ETHN,    ge, ge);
 
	SetPlayerFaceBits(pf, PFV_HAS_GLASSES, ge, GB(face, 28, 3) <= 1);
 
	SetPlayerFaceBits(pf, PFV_EYE_COLOUR,  ge, HASBIT(ge, ETHNICITY_BLACK) ? 0 : clampu(GB(face, 20, 3), 5, 7) - 5);
 
	SetPlayerFaceBits(pf, PFV_EYE_COLOUR,  ge, HASBIT(ge, ETHNICITY_BLACK) ? 0 : ClampU(GB(face, 20, 3), 5, 7) - 5);
 
	SetPlayerFaceBits(pf, PFV_CHIN,        ge, ScalePlayerFaceValue(PFV_CHIN,     ge, GB(face,  4, 2)));
 
	SetPlayerFaceBits(pf, PFV_EYEBROWS,    ge, ScalePlayerFaceValue(PFV_EYEBROWS, ge, GB(face,  6, 4)));
 
	SetPlayerFaceBits(pf, PFV_HAIR,        ge, ScalePlayerFaceValue(PFV_HAIR,     ge, GB(face, 16, 4)));
 
	SetPlayerFaceBits(pf, PFV_JACKET,      ge, ScalePlayerFaceValue(PFV_JACKET,   ge, GB(face, 20, 2)));
 
	SetPlayerFaceBits(pf, PFV_COLLAR,      ge, ScalePlayerFaceValue(PFV_COLLAR,   ge, GB(face, 22, 2)));
 
	SetPlayerFaceBits(pf, PFV_GLASSES,     ge, GB(face, 28, 1));
 

	
 
	uint lips = GB(face, 10, 4);
 
	if (!HASBIT(ge, GENDER_FEMALE) && lips < 4) {
 
		SetPlayerFaceBits(pf, PFV_HAS_MOUSTACHE, ge, true);
 
		SetPlayerFaceBits(pf, PFV_MOUSTACHE,     ge, max(lips, 1U) - 1);
 
	} else {
 
		if (!HASBIT(ge, GENDER_FEMALE)) {
 
			lips = lips * 15 / 16;
 
			lips -= 3;
 
			if (HASBIT(ge, ETHNICITY_BLACK) && lips > 8) lips = 0;
 
		} else {
 
			lips = ScalePlayerFaceValue(PFV_LIPS, ge, lips);
 
		}
 
		SetPlayerFaceBits(pf, PFV_LIPS, ge, lips);
 

	
 
		uint nose = GB(face, 13, 3);
 
		if (ge == GE_WF) {
 
			nose = (nose * 3 >> 3) * 3 >> 2; // There is 'hole' in the nose sprites for females
src/rail_gui.cpp
Show inline comments
 
@@ -1088,49 +1088,49 @@ static const WindowDesc _station_builder
 
	StationBuildWndProc
 
};
 

	
 
static const WindowDesc _newstation_builder_desc = {
 
	WDP_AUTO, WDP_AUTO, 148, 290, 148, 290,
 
	WC_BUILD_STATION, WC_BUILD_TOOLBAR,
 
	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
 
	_newstation_builder_widgets,
 
	StationBuildWndProc
 
};
 

	
 
static void ShowStationBuilder()
 
{
 
	Window *w;
 
	if (GetNumStationClasses() <= 2 && GetNumCustomStations(STAT_CLASS_DFLT) == 1) {
 
		w = AllocateWindowDesc(&_station_builder_desc);
 
		_railstation.newstations = false;
 
	} else {
 
		w = AllocateWindowDesc(&_newstation_builder_desc);
 
		_railstation.newstations = true;
 
		_railstation.station_count = GetNumCustomStations(_railstation.station_class);
 

	
 
		w->vscroll.count = _railstation.station_count;
 
		w->vscroll.cap   = 5;
 
		w->vscroll.pos   = clamp(_railstation.station_type - 2, 0, w->vscroll.count - w->vscroll.cap);
 
		w->vscroll.pos   = Clamp(_railstation.station_type - 2, 0, w->vscroll.count - w->vscroll.cap);
 
	}
 
}
 

	
 
/** Enum referring to the widgets of the build rail depot window */
 
enum BuildRailDepotWidgets {
 
	BRDW_CLOSEBOX = 0,
 
	BRDW_CAPTION,
 
	BRDW_BACKGROUND,
 
	BRDW_DEPOT_NE,
 
	BRDW_DEPOT_SE,
 
	BRDW_DEPOT_SW,
 
	BRDW_DEPOT_NW,
 
};
 

	
 
static void BuildTrainDepotWndProc(Window *w, WindowEvent *e)
 
{
 
	switch (e->event) {
 
	case WE_CREATE: LowerWindowWidget(w, _build_depot_direction + BRDW_DEPOT_NE); break;
 

	
 
	case WE_PAINT: {
 
		DrawWindowWidgets(w);
 

	
 
		DrawTrainDepotSprite(70, 17, DIAGDIR_NE, _cur_railtype);
 
		DrawTrainDepotSprite(70, 69, DIAGDIR_SE, _cur_railtype);
src/roadveh_cmd.cpp
Show inline comments
 
@@ -108,49 +108,49 @@ void DrawRoadVehEngine(int x, int y, Eng
 

	
 
	if (is_custom_sprite(spritenum)) {
 
		int sprite = GetCustomVehicleIcon(engine, DIR_W);
 

	
 
		if (sprite != 0) {
 
			DrawSprite(sprite, pal, x, y);
 
			return;
 
		}
 
		spritenum = orig_road_vehicle_info[engine - ROAD_ENGINES_INDEX].image_index;
 
	}
 
	DrawSprite(6 + _roadveh_images[spritenum], pal, x, y);
 
}
 

	
 
static CommandCost EstimateRoadVehCost(EngineID engine_type)
 
{
 
	return CommandCost(((_price.roadveh_base >> 3) * GetEngineProperty(engine_type, 0x11, RoadVehInfo(engine_type)->base_cost)) >> 5);
 
}
 

	
 
byte GetRoadVehLength(const Vehicle *v)
 
{
 
	byte length = 8;
 

	
 
	uint16 veh_len = GetVehicleCallback(CBID_VEHICLE_LENGTH, 0, 0, v->engine_type, v);
 
	if (veh_len != CALLBACK_FAILED) {
 
		length -= clamp(veh_len, 0, 7);
 
		length -= Clamp(veh_len, 0, 7);
 
	}
 

	
 
	return length;
 
}
 

	
 
void RoadVehUpdateCache(Vehicle *v)
 
{
 
	assert(v->type == VEH_ROAD);
 
	assert(IsRoadVehFront(v));
 

	
 
	for (Vehicle *u = v; u != NULL; u = u->Next()) {
 
		/* Check the v->first cache. */
 
		assert(u->First() == v);
 

	
 
		/* Update the 'first engine' */
 
		u->u.road.first_engine = (v == u) ? INVALID_ENGINE : v->engine_type;
 

	
 
		/* Update the length of the vehicle. */
 
		u->u.road.cached_veh_length = GetRoadVehLength(u);
 
	}
 
}
 

	
 
/** Build a road vehicle.
 
 * @param tile tile of depot where road vehicle is built
src/screenshot.cpp
Show inline comments
 
@@ -102,49 +102,49 @@ static bool MakeBmpImage(const char *nam
 
	bih.bitcount = TO_LE16(pixelformat);
 
	bih.compression = 0;
 
	bih.sizeimage = 0;
 
	bih.xpels = 0;
 
	bih.ypels = 0;
 
	bih.clrused = 0;
 
	bih.clrimp = 0;
 

	
 
	if (pixelformat == 8) {
 
		/* convert the palette to the windows format */
 
		for (i = 0; i != 256; i++) {
 
			rq[i].red   = palette[i].r;
 
			rq[i].green = palette[i].g;
 
			rq[i].blue  = palette[i].b;
 
			rq[i].reserved = 0;
 
		}
 
	}
 

	
 
	/* write file header and info header and palette */
 
	if (fwrite(&bfh, sizeof(bfh), 1, f) != 1) return false;
 
	if (fwrite(&bih, sizeof(bih), 1, f) != 1) return false;
 
	if (pixelformat == 8) if (fwrite(rq, sizeof(rq), 1, f) != 1) return false;
 

	
 
	/* use by default 64k temp memory */
 
	maxlines = clamp(65536 / padw, 16, 128);
 
	maxlines = Clamp(65536 / padw, 16, 128);
 

	
 
	/* now generate the bitmap bits */
 
	void *buff = MallocT<uint8>(padw * maxlines * bpp); // by default generate 128 lines at a time.
 
	if (buff == NULL) {
 
		fclose(f);
 
		return false;
 
	}
 
	memset(buff, 0, padw * maxlines); // zero the buffer to have the padding bytes set to 0
 

	
 
	/* start at the bottom, since bitmaps are stored bottom up. */
 
	do {
 
		/* determine # lines */
 
		n = min(h, maxlines);
 
		h -= n;
 

	
 
		/* render the pixels */
 
		callb(userdata, buff, h, padw, n);
 

	
 
		/* write each line */
 
		while (n)
 
			if (fwrite((uint8 *)buff + (--n) * padw * bpp, padw * bpp, 1, f) != 1) {
 
				free(buff);
 
				fclose(f);
 
				return false;
 
@@ -230,49 +230,49 @@ static bool MakePNGImage(const char *nam
 

	
 
	png_write_info(png_ptr, info_ptr);
 
	png_set_flush(png_ptr, 512);
 

	
 
	if (pixelformat == 32) {
 
		png_color_8 sig_bit;
 

	
 
		/* Save exact color/alpha resolution */
 
		sig_bit.alpha = 0;
 
		sig_bit.blue  = 8;
 
		sig_bit.green = 8;
 
		sig_bit.red   = 8;
 
		sig_bit.gray  = 8;
 
		png_set_sBIT(png_ptr, info_ptr, &sig_bit);
 

	
 
#ifdef TTD_LITTLE_ENDIAN
 
		png_set_bgr(png_ptr);
 
		png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
 
#else
 
		png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
 
#endif
 
	}
 

	
 
	/* use by default 64k temp memory */
 
	maxlines = clamp(65536 / w, 16, 128);
 
	maxlines = Clamp(65536 / w, 16, 128);
 

	
 
	/* now generate the bitmap bits */
 
	void *buff = MallocT<uint8>(w * maxlines * bpp); // by default generate 128 lines at a time.
 
	if (buff == NULL) {
 
		png_destroy_write_struct(&png_ptr, &info_ptr);
 
		fclose(f);
 
		return false;
 
	}
 
	memset(buff, 0, w * maxlines * bpp);
 

	
 
	y = 0;
 
	do {
 
		/* determine # lines to write */
 
		n = min(h - y, maxlines);
 

	
 
		/* render the pixels into the buffer */
 
		callb(userdata, buff, y, w, n);
 
		y += n;
 

	
 
		/* write them to png */
 
		for (i = 0; i != n; i++)
 
			png_write_row(png_ptr, (png_bytep)buff + i * w * bpp);
 
	} while (y != h);
 

	
 
@@ -330,49 +330,49 @@ static bool MakePCXImage(const char *nam
 
	memset(&pcx, 0, sizeof(pcx));
 

	
 
	/* setup pcx header */
 
	pcx.manufacturer = 10;
 
	pcx.version = 5;
 
	pcx.rle = 1;
 
	pcx.bpp = 8;
 
	pcx.xmax = TO_LE16(w - 1);
 
	pcx.ymax = TO_LE16(h - 1);
 
	pcx.hdpi = TO_LE16(320);
 
	pcx.vdpi = TO_LE16(320);
 

	
 
	pcx.planes = 1;
 
	pcx.cpal = TO_LE16(1);
 
	pcx.width = pcx.pitch = TO_LE16(w);
 
	pcx.height = TO_LE16(h);
 

	
 
	/* write pcx header */
 
	if (fwrite(&pcx, sizeof(pcx), 1, f) != 1) {
 
		fclose(f);
 
		return false;
 
	}
 

	
 
	/* use by default 64k temp memory */
 
	maxlines = clamp(65536 / w, 16, 128);
 
	maxlines = Clamp(65536 / w, 16, 128);
 

	
 
	/* now generate the bitmap bits */
 
	uint8 *buff = MallocT<uint8>(w * maxlines); // by default generate 128 lines at a time.
 
	if (buff == NULL) {
 
		fclose(f);
 
		return false;
 
	}
 
	memset(buff, 0, w * maxlines); // zero the buffer to have the padding bytes set to 0
 

	
 
	y = 0;
 
	do {
 
		/* determine # lines to write */
 
		uint n = min(h - y, maxlines);
 
		uint i;
 

	
 
		/* render the pixels into the buffer */
 
		callb(userdata, buff, y, w, n);
 
		y += n;
 

	
 
		/* write them to pcx */
 
		for (i = 0; i != n; i++) {
 
			const uint8 *bufp = buff + i * w;
 
			byte runchar = bufp[0];
 
			uint runcount = 1;
src/settings.cpp
Show inline comments
 
@@ -644,54 +644,54 @@ static void Write_ValidateSetting(void *
 

	
 
	if (sdb->cmd != SDT_BOOLX &&
 
			sdb->cmd != SDT_NUMX &&
 
			sdb->cmd != SDT_ONEOFMANY &&
 
			sdb->cmd != SDT_MANYOFMANY) {
 
		return;
 
	}
 

	
 
	/* We cannot know the maximum value of a bitset variable, so just have faith */
 
	if (sdb->cmd != SDT_MANYOFMANY) {
 
		/* We need to take special care of the uint32 type as we receive from the function
 
		 * a signed integer. While here also bail out on 64-bit settings as those are not
 
		 * supported. Unsigned 8 and 16-bit variables are safe since they fit into a signed
 
		 * 32-bit variable
 
		 * TODO: Support 64-bit settings/variables */
 
		switch (GetVarMemType(sd->save.conv)) {
 
			case SLE_VAR_BL:
 
			case SLE_VAR_I8:
 
			case SLE_VAR_U8:
 
			case SLE_VAR_I16:
 
			case SLE_VAR_U16:
 
			case SLE_VAR_I32: {
 
				/* Override the minimum value. No value below sdb->min, except special value 0 */
 
				int32 min = ((sdb->flags & SGF_0ISDISABLED) && val <= sdb->min) ? 0 : sdb->min;
 
				val = clamp(val, min, sdb->max);
 
				val = Clamp(val, min, sdb->max);
 
			} break;
 
			case SLE_VAR_U32: {
 
				/* Override the minimum value. No value below sdb->min, except special value 0 */
 
				uint min = ((sdb->flags & SGF_0ISDISABLED) && (uint)val <= (uint)sdb->min) ? 0 : sdb->min;
 
				WriteValue(ptr, SLE_VAR_U32, (int64)clampu(val, min, sdb->max));
 
				WriteValue(ptr, SLE_VAR_U32, (int64)ClampU(val, min, sdb->max));
 
				return;
 
			}
 
			case SLE_VAR_I64:
 
			case SLE_VAR_U64:
 
			default: NOT_REACHED(); break;
 
		}
 
	}
 

	
 
	WriteValue(ptr, sd->save.conv, (int64)val);
 
}
 

	
 
/** Load values from a group of an IniFile structure into the internal representation
 
 * @param ini pointer to IniFile structure that holds administrative information
 
 * @param sd pointer to SettingDesc structure whose internally pointed variables will
 
 *        be given values
 
 * @param grpname the group of the IniFile to search in for the new values
 
 * @param object pointer to the object been loaded */
 
static void ini_load_settings(IniFile *ini, const SettingDesc *sd, const char *grpname, void *object)
 
{
 
	IniGroup *group;
 
	IniGroup *group_def = ini_getgroup(ini, grpname, -1);
 
	IniItem *item;
 
	const void *p;
 
	void *ptr;
src/settings_gui.cpp
Show inline comments
 
@@ -408,49 +408,49 @@ static const GDType _default_game_diff[3
 

	
 
void SetDifficultyLevel(int mode, GameOptions *gm_opt)
 
{
 
	int i;
 
	assert(mode <= 3);
 

	
 
	gm_opt->diff_level = mode;
 
	if (mode != 3) { // not custom
 
		for (i = 0; i != GAME_DIFFICULTY_NUM; i++)
 
			((GDType*)&gm_opt->diff)[i] = _default_game_diff[mode][i];
 
	}
 
}
 

	
 
/**
 
 * Checks the difficulty levels read from the configuration and
 
 * forces them to be correct when invalid.
 
 */
 
void CheckDifficultyLevels()
 
{
 
	if (_opt_newgame.diff_level != 3) {
 
		SetDifficultyLevel(_opt_newgame.diff_level, &_opt_newgame);
 
	} else {
 
		for (uint i = 0; i < GAME_DIFFICULTY_NUM; i++) {
 
			GDType *diff = ((GDType*)&_opt_newgame.diff) + i;
 
			*diff = clamp(*diff, _game_setting_info[i].min, _game_setting_info[i].max);
 
			*diff = Clamp(*diff, _game_setting_info[i].min, _game_setting_info[i].max);
 
			*diff -= *diff % _game_setting_info[i].step;
 
		}
 
	}
 
}
 

	
 
extern void StartupEconomy();
 

	
 
enum {
 
	GAMEDIFF_WND_TOP_OFFSET = 45,
 
	GAMEDIFF_WND_ROWSIZE    = 9
 
};
 

	
 
/* Temporary holding place of values in the difficulty window until 'Save' is clicked */
 
static GameOptions _opt_mod_temp;
 
// 0x383E = (1 << 13) | (1 << 12) | (1 << 11) | (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1)
 
#define DIFF_INGAME_DISABLED_BUTTONS 0x383E
 

	
 
static void GameDifficultyWndProc(Window *w, WindowEvent *e)
 
{
 
	switch (e->event) {
 
	case WE_CREATE: // Setup disabled buttons when creating window
 
		/* disable all other difficulty buttons during gameplay except for 'custom' */
 
		SetWindowWidgetDisabledState(w,  3, _game_mode == GM_NORMAL);
 
		SetWindowWidgetDisabledState(w,  4, _game_mode == GM_NORMAL);
 
@@ -1128,76 +1128,76 @@ static void CustCurrencyWndProc(Window *
 
				case 2: // prefix
 
					if (IS_INT_INSIDE(x, 10, 30)) { // clicked button
 
						WP(w,def_d).data_1 = 1 << (line * 2 + 1);
 
					}
 
					str = BindCString(_custom_currency.prefix);
 
					len = 12;
 
					break;
 

	
 
				case 3: // suffix
 
					if (IS_INT_INSIDE(x, 10, 30)) { // clicked button
 
						WP(w,def_d).data_1 = 1 << (line * 2 + 1);
 
					}
 
					str = BindCString(_custom_currency.suffix);
 
					len = 12;
 
					break;
 

	
 
				case 4: // to euro
 
					if (IS_INT_INSIDE(x, 10, 30)) { // clicked buttons
 
						if (x < 20) {
 
							_custom_currency.to_euro = (_custom_currency.to_euro <= 2000) ?
 
								CF_NOEURO : _custom_currency.to_euro - 1;
 
							WP(w,def_d).data_1 = 1 << (line * 2 + 0);
 
						} else {
 
							_custom_currency.to_euro =
 
								clamp(_custom_currency.to_euro + 1, 2000, MAX_YEAR);
 
								Clamp(_custom_currency.to_euro + 1, 2000, MAX_YEAR);
 
							WP(w,def_d).data_1 = 1 << (line * 2 + 1);
 
						}
 
					} else { // enter text
 
						SetDParam(0, _custom_currency.to_euro);
 
						str = STR_CONFIG_PATCHES_INT32;
 
						len = 4;
 
						afilter = CS_NUMERAL;
 
					}
 
					break;
 
			}
 

	
 
			if (len != 0) {
 
				WP(w, def_d).data_2 = line;
 
				ShowQueryString(str, STR_CURRENCY_CHANGE_PARAMETER, len + 1, 250, w, afilter);
 
			}
 

	
 
			w->flags4 |= 5 << WF_TIMEOUT_SHL;
 
			SetWindowDirty(w);
 
			break;
 
		}
 

	
 
		case WE_ON_EDIT_TEXT: {
 
				const char *b = e->we.edittext.str;
 

	
 
				switch (WP(w,def_d).data_2) {
 
					case 0: /* Exchange rate */
 
						_custom_currency.rate = clamp(atoi(b), 1, 5000);
 
						_custom_currency.rate = Clamp(atoi(b), 1, 5000);
 
						break;
 

	
 
					case 1: /* Thousands seperator */
 
						_custom_currency.separator = (b[0] == '\0') ? ' ' : b[0];
 
						ttd_strlcpy(_str_separator, b, lengthof(_str_separator));
 
						break;
 

	
 
					case 2: /* Currency prefix */
 
						ttd_strlcpy(_custom_currency.prefix, b, lengthof(_custom_currency.prefix));
 
						break;
 

	
 
					case 3: /* Currency suffix */
 
						ttd_strlcpy(_custom_currency.suffix, b, lengthof(_custom_currency.suffix));
 
						break;
 

	
 
					case 4: { /* Year to switch to euro */
 
						int val = atoi(b);
 

	
 
						_custom_currency.to_euro =
 
							(val < 2000 ? CF_NOEURO : min(val, MAX_YEAR));
 
						break;
 
					}
 
				}
 
			MarkWholeScreenDirty();
src/sound.cpp
Show inline comments
 
@@ -127,49 +127,49 @@ static bool SetBankSource(MixerChannel *
 
	assert(fe->bits_per_sample == 8 && fe->channels == 1 && fe->file_size != 0 && fe->rate != 0);
 

	
 
	MxSetChannelRawSrc(mc, mem, fe->file_size, fe->rate, MX_AUTOFREE);
 

	
 
	return true;
 
}
 

	
 
bool SoundInitialize(const char *filename)
 
{
 
	OpenBankFile(filename);
 
	return true;
 
}
 

	
 
/* Low level sound player */
 
static void StartSound(uint sound, int panning, uint volume)
 
{
 
	MixerChannel *mc;
 
	uint left_vol, right_vol;
 

	
 
	if (volume == 0) return;
 
	mc = MxAllocateChannel();
 
	if (mc == NULL) return;
 
	if (!SetBankSource(mc, sound)) return;
 

	
 
	panning = clamp(panning, -PANNING_LEVELS, PANNING_LEVELS);
 
	panning = Clamp(panning, -PANNING_LEVELS, PANNING_LEVELS);
 
	left_vol = (volume * PANNING_LEVELS) - (volume * panning);
 
	right_vol = (volume * PANNING_LEVELS) + (volume * panning);
 
	MxSetChannelVolume(mc, left_vol * 128 / PANNING_LEVELS, right_vol * 128 / PANNING_LEVELS);
 
	MxActivateChannel(mc);
 
}
 

	
 

	
 
static const byte _vol_factor_by_zoom[] = {255, 190, 134, 87};
 
assert_compile(lengthof(_vol_factor_by_zoom) == ZOOM_LVL_END);
 

	
 
static const byte _sound_base_vol[] = {
 
	128,  90, 128, 128, 128, 128, 128, 128,
 
	128,  90,  90, 128, 128, 128, 128, 128,
 
	128, 128, 128,  80, 128, 128, 128, 128,
 
	128, 128, 128, 128, 128, 128, 128, 128,
 
	128, 128,  90,  90,  90, 128,  90, 128,
 
	128,  90, 128, 128, 128,  90, 128, 128,
 
	128, 128, 128, 128,  90, 128, 128, 128,
 
	128,  90, 128, 128, 128, 128, 128, 128,
 
	128, 128,  90,  90,  90, 128, 128, 128,
 
	 90,
 
};
 

	
 
static const byte _sound_idx[] = {
src/station_cmd.cpp
Show inline comments
 
@@ -650,49 +650,49 @@ static void UpdateStationAcceptance(Stat
 
			} else {
 
				if (HASBIT(old_acc, i) && num_rej < lengthof(rejects)) {
 
					/* Old cargo is no longer accepted */
 
					rejects[num_rej++] = i;
 
				}
 
			}
 
		}
 

	
 
		/* Show news message if there are any changes */
 
		if (num_acc > 0) ShowRejectOrAcceptNews(st, num_acc, accepts, accept_msg[num_acc - 1]);
 
		if (num_rej > 0) ShowRejectOrAcceptNews(st, num_rej, rejects, reject_msg[num_rej - 1]);
 
	}
 

	
 
	/* redraw the station view since acceptance changed */
 
	InvalidateWindowWidget(WC_STATION_VIEW, st->index, 4);
 
}
 

	
 
static void UpdateStationSignCoord(Station *st)
 
{
 
	const StationRect *r = &st->rect;
 

	
 
	if (r->IsEmpty()) return; /* no tiles belong to this station */
 

	
 
	/* clamp sign coord to be inside the station rect */
 
	st->xy = TileXY(clampu(TileX(st->xy), r->left, r->right), clampu(TileY(st->xy), r->top, r->bottom));
 
	st->xy = TileXY(ClampU(TileX(st->xy), r->left, r->right), ClampU(TileY(st->xy), r->top, r->bottom));
 
	UpdateStationVirtCoordDirty(st);
 
}
 

	
 
/** This is called right after a station was deleted.
 
 * It checks if the whole station is free of substations, and if so, the station will be
 
 * deleted after a little while.
 
 * @param st Station
 
 */
 
static void DeleteStationIfEmpty(Station *st)
 
{
 
	if (st->facilities == 0) {
 
		st->delete_ctr = 0;
 
		RebuildStationLists();
 
		InvalidateWindow(WC_STATION_LIST, st->owner);
 
	}
 
	/* station remains but it probably lost some parts - station sign should stay in the station boundaries */
 
	UpdateStationSignCoord(st);
 
}
 

	
 
static CommandCost ClearTile_Station(TileIndex tile, byte flags);
 

	
 
/** Tries to clear the given area.
 
 * @param tile TileIndex to start check
 
 * @param w width of search area
 
@@ -2466,49 +2466,49 @@ static void UpdateStationRating(Station 
 
			if (IsValidPlayer(st->owner) && HASBIT(st->town->statues, st->owner)) rating += 26;
 

	
 
			{
 
				byte days = ge->days_since_pickup;
 
				if (st->last_vehicle_type == VEH_SHIP) days >>= 2;
 
				(days > 21) ||
 
				(rating += 25, days > 12) ||
 
				(rating += 25, days > 6) ||
 
				(rating += 45, days > 3) ||
 
				(rating += 35, true);
 
			}
 

	
 
			uint waiting = ge->cargo.Count();
 
			(rating -= 90, waiting > 1500) ||
 
			(rating += 55, waiting > 1000) ||
 
			(rating += 35, waiting > 600) ||
 
			(rating += 10, waiting > 300) ||
 
			(rating += 20, waiting > 100) ||
 
			(rating += 10, true);
 

	
 
			{
 
				int or_ = ge->rating; // old rating
 

	
 
				/* only modify rating in steps of -2, -1, 0, 1 or 2 */
 
				ge->rating = rating = or_ + clamp(clamp(rating, 0, 255) - or_, -2, 2);
 
				ge->rating = rating = or_ + Clamp(Clamp(rating, 0, 255) - or_, -2, 2);
 

	
 
				/* if rating is <= 64 and more than 200 items waiting,
 
				 * remove some random amount of goods from the station */
 
				if (rating <= 64 && waiting >= 200) {
 
					int dec = Random() & 0x1F;
 
					if (waiting < 400) dec &= 7;
 
					waiting -= dec + 1;
 
					waiting_changed = true;
 
				}
 

	
 
				/* if rating is <= 127 and there are any items waiting, maybe remove some goods. */
 
				if (rating <= 127 && waiting != 0) {
 
					uint32 r = Random();
 
					if (rating <= (int)GB(r, 0, 7)) {
 
						/* Need to have int, otherwise it will just overflow etc. */
 
						waiting = max((int)waiting - (int)GB(r, 8, 2) - 1, 0);
 
						waiting_changed = true;
 
					}
 
				}
 

	
 
				/* At some point we really must cap the cargo. Previously this
 
				 * was a strict 4095, but now we'll have a less strict, but
 
				 * increasingly agressive truncation of the amount of cargo. */
 
				static const uint WAITING_CARGO_THRESHOLD  = 1 << 12;
 
@@ -2556,49 +2556,49 @@ void OnTick_Station()
 
	if (++_station_tick_ctr > GetMaxStationIndex()) _station_tick_ctr = 0;
 

	
 
	if (IsValidStationID(i)) StationHandleBigTick(GetStation(i));
 

	
 
	Station *st;
 
	FOR_ALL_STATIONS(st) StationHandleSmallTick(st);
 
}
 

	
 
void StationMonthlyLoop()
 
{
 
}
 

	
 

	
 
void ModifyStationRatingAround(TileIndex tile, PlayerID owner, int amount, uint radius)
 
{
 
	Station *st;
 

	
 
	FOR_ALL_STATIONS(st) {
 
		if (st->owner == owner &&
 
				DistanceManhattan(tile, st->xy) <= radius) {
 
			for (CargoID i = 0; i < NUM_CARGO; i++) {
 
				GoodsEntry* ge = &st->goods[i];
 

	
 
				if (ge->acceptance_pickup != 0) {
 
					ge->rating = clamp(ge->rating + amount, 0, 255);
 
					ge->rating = Clamp(ge->rating + amount, 0, 255);
 
				}
 
			}
 
		}
 
	}
 
}
 

	
 
static void UpdateStationWaiting(Station *st, CargoID type, uint amount)
 
{
 
	st->goods[type].cargo.Append(new CargoPacket(st->index, amount));
 
	SETBIT(st->goods[type].acceptance_pickup, GoodsEntry::PICKUP);
 

	
 
	InvalidateWindow(WC_STATION_VIEW, st->index);
 
	st->MarkTilesDirty(true);
 
}
 

	
 
static bool IsUniqueStationName(const char *name)
 
{
 
	const Station *st;
 
	char buf[512];
 

	
 
	FOR_ALL_STATIONS(st) {
 
		SetDParam(0, st->index);
 
		GetString(buf, STR_STATION, lastof(buf));
 
		if (strcmp(buf, name) == 0) return false;
src/town_map.h
Show inline comments
 
@@ -262,49 +262,49 @@ static inline byte GetHouseBuildingStage
 
 * @return the construction stage of the house
 
 */
 
static inline byte GetHouseConstructionTick(TileIndex t)
 
{
 
	assert(IsTileType(t, MP_HOUSE));
 
	return IsHouseCompleted(t) ? 0 : GB(_m[t].m5, 0, 3);
 
}
 

	
 
/**
 
 * Sets the increment stage of a house
 
 * It is working with the whole counter + stage 5 bits, making it
 
 * easier to work:  the wraparound is automatic.
 
 * @param t the tile of the house to increment the construction stage of
 
 * @pre IsTileType(t, MP_HOUSE)
 
 */
 
static inline void IncHouseConstructionTick(TileIndex t)
 
{
 
	assert(IsTileType(t, MP_HOUSE));
 
	AB(_m[t].m5, 0, 5, 1);
 

	
 
	if (GB(_m[t].m5, 3, 2) == TOWN_HOUSE_COMPLETED) {
 
		/* House is now completed.
 
		 * Store the year of construction as well, for newgrf house purpose */
 
		SetHouseCompleted(t, true);
 
		_m[t].m5 = clamp(_cur_year - ORIGINAL_BASE_YEAR, 0, 0xFF);
 
		_m[t].m5 = Clamp(_cur_year - ORIGINAL_BASE_YEAR, 0, 0xFF);
 
	}
 
}
 

	
 
/**
 
 * Get the year that this house was constructed (between 1920 and 2175).
 
 * @param t the tile of this house
 
 * @pre IsTileType(t, MP_HOUSE)
 
 * @return year
 
 */
 
static inline Year GetHouseConstructionYear(TileIndex t)
 
{
 
	assert(IsTileType(t, MP_HOUSE));
 
	return IsHouseCompleted(t) ? _m[t].m5 + ORIGINAL_BASE_YEAR : 0;
 
}
 

	
 
/**
 
 * Set the random bits for this house.
 
 * This is required for newgrf house
 
 * @param t      the tile of this house
 
 * @param random the new random bits
 
 * @pre IsTileType(t, MP_HOUSE)
 
 */
 
static inline void SetHouseRandomBits(TileIndex t, byte random)
 
{
src/train_cmd.cpp
Show inline comments
 
@@ -223,49 +223,49 @@ void TrainConsistChanged(Vehicle* v)
 
				u->u.rail.railtype = RAILTYPE_RAIL;
 
				u->u.rail.compatible_railtypes |= (1 << RAILTYPE_RAIL);
 
			}
 

	
 
			/* max speed is the minimum of the speed limits of all vehicles in the consist */
 
			if ((rvi_u->railveh_type != RAILVEH_WAGON || _patches.wagon_speed_limits) && !UsesWagonOverride(u)) {
 
				uint16 speed = GetVehicleProperty(u, 0x09, rvi_u->max_speed);
 
				if (speed != 0) max_speed = min(speed, max_speed);
 
			}
 
		}
 

	
 
		if (u->cargo_type == rvi_u->cargo_type && u->cargo_subtype == 0) {
 
			/* Set cargo capacity if we've not been refitted */
 
			u->cargo_cap = GetVehicleProperty(u, 0x14, rvi_u->capacity);
 
		}
 

	
 
		u->u.rail.user_def_data = GetVehicleProperty(u, 0x25, rvi_u->user_def_data);
 

	
 
		/* check the vehicle length (callback) */
 
		uint16 veh_len = CALLBACK_FAILED;
 
		if (HASBIT(EngInfo(u->engine_type)->callbackmask, CBM_VEHICLE_LENGTH)) {
 
			veh_len = GetVehicleCallback(CBID_VEHICLE_LENGTH, 0, 0, u->engine_type, u);
 
		}
 
		if (veh_len == CALLBACK_FAILED) veh_len = rvi_u->shorten_factor;
 
		veh_len = clamp(veh_len, 0, u->Next() == NULL ? 7 : 5); // the clamp on vehicles not the last in chain is stricter, as too short wagons can break the 'follow next vehicle' code
 
		veh_len = Clamp(veh_len, 0, u->Next() == NULL ? 7 : 5); // the clamp on vehicles not the last in chain is stricter, as too short wagons can break the 'follow next vehicle' code
 
		u->u.rail.cached_veh_length = 8 - veh_len;
 
		v->u.rail.cached_total_length += u->u.rail.cached_veh_length;
 
	}
 

	
 
	/* store consist weight/max speed in cache */
 
	v->u.rail.cached_max_speed = max_speed;
 

	
 
	/* recalculate cached weights and power too (we do this *after* the rest, so it is known which wagons are powered and need extra weight added) */
 
	TrainCargoChanged(v);
 
}
 

	
 
/* These two arrays are used for realistic acceleration. XXX: How should they
 
 * be interpreted? */
 
static const byte _curve_neighbours45[8][2] = {
 
	{7, 1},
 
	{0, 2},
 
	{1, 3},
 
	{2, 4},
 
	{3, 5},
 
	{4, 6},
 
	{5, 7},
 
	{6, 0},
 
};
 

	
 
@@ -331,49 +331,49 @@ static int GetTrainAcceleration(Vehicle 
 
					sum += pos - lastpos;
 
					if (pos - lastpos == 1) {
 
						max_speed = 88;
 
					}
 
				}
 
				lastpos = pos;
 
			}
 
		}
 

	
 
		/*if we have a 90 degree turn, fix the speed limit to 60 */
 
		if (_curve_neighbours90[dir][0] == ndir ||
 
				_curve_neighbours90[dir][1] == ndir) {
 
			max_speed = 61;
 
		}
 
	}
 

	
 
	if (numcurve > 0) sum /= numcurve;
 

	
 
	if ((curvecount[0] != 0 || curvecount[1] != 0) && max_speed > 88) {
 
		int total = curvecount[0] + curvecount[1];
 

	
 
		if (curvecount[0] == 1 && curvecount[1] == 1) {
 
			max_speed = 0xFFFF;
 
		} else if (total > 1) {
 
			max_speed = 232 - (13 - clamp(sum, 1, 12)) * (13 - clamp(sum, 1, 12));
 
			max_speed = 232 - (13 - Clamp(sum, 1, 12)) * (13 - Clamp(sum, 1, 12));
 
		}
 
	}
 

	
 
	max_speed += (max_speed / 2) * v->u.rail.railtype;
 

	
 
	if (IsTileType(v->tile, MP_STATION) && IsFrontEngine(v)) {
 
		if (TrainShouldStop(v, v->tile)) {
 
			int station_length = GetStationByTile(v->tile)->GetPlatformLength(v->tile, DirToDiagDir(v->direction));
 
			int delta_v;
 

	
 
			max_speed = 120;
 

	
 
			delta_v = v->cur_speed / (station_length + 1);
 
			if (v->max_speed > (v->cur_speed - delta_v))
 
				max_speed = v->cur_speed - (delta_v / 10);
 

	
 
			max_speed = max(max_speed, 25 * station_length);
 
		}
 
	}
 

	
 
	int mass = v->u.rail.cached_weight;
 
	int power = v->u.rail.cached_power * 746;
 
	max_speed = min(max_speed, v->u.rail.cached_max_speed);
 

	
 
@@ -434,49 +434,49 @@ static int GetTrainAcceleration(Vehicle 
 
		force = (mode == AM_ACCEL && v->u.rail.railtype != RAILTYPE_MAGLEV) ? min(max_te, power) : power;
 
		force = max(force, (mass * 8) + resistance);
 
	}
 

	
 
	if (force <= 0) force = 10000;
 

	
 
	if (v->u.rail.railtype != RAILTYPE_MAGLEV) force = min(force, mass * 10 * 200);
 

	
 
	if (mode == AM_ACCEL) {
 
		return (force - resistance) / (mass * 4);
 
	} else {
 
		return min((-force - resistance) / (mass * 4), -10000 / (mass * 4));
 
	}
 
}
 

	
 
static void UpdateTrainAcceleration(Vehicle* v)
 
{
 
	assert(IsFrontEngine(v));
 

	
 
	v->max_speed = v->u.rail.cached_max_speed;
 

	
 
	uint power = v->u.rail.cached_power;
 
	uint weight = v->u.rail.cached_weight;
 
	assert(weight != 0);
 
	v->acceleration = clamp(power / weight * 4, 1, 255);
 
	v->acceleration = Clamp(power / weight * 4, 1, 255);
 
}
 

	
 
int Train::GetImage(Direction direction) const
 
{
 
	int img = this->spritenum;
 
	int base;
 

	
 
	if (HASBIT(this->u.rail.flags, VRF_REVERSE_DIRECTION)) direction = ReverseDir(direction);
 

	
 
	if (is_custom_sprite(img)) {
 
		base = GetCustomVehicleSprite(this, (Direction)(direction + 4 * IS_CUSTOM_SECONDHEAD_SPRITE(img)));
 
		if (base != 0) return base;
 
		img = orig_rail_vehicle_info[this->engine_type].image_index;
 
	}
 

	
 
	base = _engine_sprite_base[img] + ((direction + _engine_sprite_add[img]) & _engine_sprite_and[img]);
 

	
 
	if (this->cargo.Count() >= this->cargo_cap / 2U) base += _wagon_full_adder[img];
 
	return base;
 
}
 

	
 
void DrawTrainEngine(int x, int y, EngineID engine, SpriteID pal)
 
{
 
	const RailVehicleInfo *rvi = RailVehInfo(engine);
 
@@ -2492,49 +2492,49 @@ void Train::MarkDirty()
 
static int UpdateTrainSpeed(Vehicle *v)
 
{
 
	uint accel;
 

	
 
	if (v->vehstatus & VS_STOPPED || HASBIT(v->u.rail.flags, VRF_REVERSING)) {
 
		if (_patches.realistic_acceleration) {
 
			accel = GetTrainAcceleration(v, AM_BRAKE) * 2;
 
		} else {
 
			accel = v->acceleration * -2;
 
		}
 
	} else {
 
		if (_patches.realistic_acceleration) {
 
			accel = GetTrainAcceleration(v, AM_ACCEL);
 
		} else {
 
			accel = v->acceleration;
 
		}
 
	}
 

	
 
	uint spd = v->subspeed + accel * 2;
 
	v->subspeed = (byte)spd;
 
	{
 
		int tempmax = v->max_speed;
 
		if (v->cur_speed > v->max_speed)
 
			tempmax = v->cur_speed - (v->cur_speed / 10) - 1;
 
		v->cur_speed = spd = clamp(v->cur_speed + ((int)spd >> 8), 0, tempmax);
 
		v->cur_speed = spd = Clamp(v->cur_speed + ((int)spd >> 8), 0, tempmax);
 
	}
 

	
 
	if (!(v->direction & 1)) spd = spd * 3 >> 2;
 

	
 
	spd += v->progress;
 
	v->progress = (byte)spd;
 
	return (spd >> 8);
 
}
 

	
 
static void TrainEnterStation(Vehicle *v, StationID station)
 
{
 
	v->last_station_visited = station;
 

	
 
	/* check if a train ever visited this station before */
 
	Station *st = GetStation(station);
 
	if (!(st->had_vehicle_of_type & HVOT_TRAIN)) {
 
		st->had_vehicle_of_type |= HVOT_TRAIN;
 
		SetDParam(0, st->index);
 
		uint32 flags = v->owner == _local_player ?
 
			NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_VEHICLE, NT_ARRIVAL_PLAYER, 0) :
 
			NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_VEHICLE, NT_ARRIVAL_OTHER,  0);
 
		AddNewsItem(
 
			STR_8801_CITIZENS_CELEBRATE_FIRST,
 
			flags,
src/vehicle.cpp
Show inline comments
 
@@ -1331,50 +1331,50 @@ Vehicle *CreateEffectVehicle(int x, int 
 
{
 
	Vehicle *v;
 

	
 
	v = new SpecialVehicle();
 
	if (v != NULL) {
 
		v->subtype = type;
 
		v->x_pos = x;
 
		v->y_pos = y;
 
		v->z_pos = z;
 
		v->tile = 0;
 
		v->UpdateDeltaXY(INVALID_DIR);
 
		v->vehstatus = VS_UNCLICKABLE;
 

	
 
		_effect_init_procs[type](v);
 

	
 
		VehiclePositionChanged(v);
 
		BeginVehicleMove(v);
 
		EndVehicleMove(v);
 
	}
 
	return v;
 
}
 

	
 
Vehicle *CreateEffectVehicleAbove(int x, int y, int z, EffectVehicle type)
 
{
 
	int safe_x = clamp(x, 0, MapMaxX() * TILE_SIZE);
 
	int safe_y = clamp(y, 0, MapMaxY() * TILE_SIZE);
 
	int safe_x = Clamp(x, 0, MapMaxX() * TILE_SIZE);
 
	int safe_y = Clamp(y, 0, MapMaxY() * TILE_SIZE);
 
	return CreateEffectVehicle(x, y, GetSlopeZ(safe_x, safe_y) + z, type);
 
}
 

	
 
Vehicle *CreateEffectVehicleRel(const Vehicle *v, int x, int y, int z, EffectVehicle type)
 
{
 
	return CreateEffectVehicle(v->x_pos + x, v->y_pos + y, v->z_pos + z, type);
 
}
 

	
 
void SpecialVehicle::Tick()
 
{
 
	_effect_tick_procs[this->subtype](this);
 
}
 

	
 
Vehicle *CheckClickOnVehicle(const ViewPort *vp, int x, int y)
 
{
 
	Vehicle *found = NULL, *v;
 
	uint dist, best_dist = (uint)-1;
 

	
 
	if ( (uint)(x -= vp->left) >= (uint)vp->width ||
 
			 (uint)(y -= vp->top) >= (uint)vp->height)
 
				return NULL;
 

	
 
	x = ScaleByZoom(x, vp->zoom) + vp->virtual_left;
 
	y = ScaleByZoom(y, vp->zoom) + vp->virtual_top;
src/video/cocoa_v.mm
Show inline comments
 
@@ -1223,49 +1223,49 @@ static const char* QZ_SetVideoWindowed(u
 
		_cocoa_video_data.window = [ [ OTTD_QuartzWindow alloc ]
 
										initWithContentRect:contentRect
 
										styleMask:style
 
										backing:NSBackingStoreBuffered
 
										defer:NO ];
 

	
 
		if (_cocoa_video_data.window == nil)
 
			return "Could not create the Cocoa window";
 

	
 
		snprintf(caption, sizeof(caption), "OpenTTD %s", _openttd_revision);
 
		nsscaption = [ [ NSString alloc ] initWithCString:caption ];
 
		[ _cocoa_video_data.window setTitle:nsscaption ];
 
		[ _cocoa_video_data.window setMiniwindowTitle:nsscaption ];
 
		[ nsscaption release ];
 

	
 
		[ _cocoa_video_data.window setAcceptsMouseMovedEvents:YES ];
 
		[ _cocoa_video_data.window setViewsNeedDisplay:NO ];
 

	
 
		[ _cocoa_video_data.window setDelegate: [ [ [ OTTD_QuartzWindowDelegate alloc ] init ] autorelease ] ];
 
	} else {
 
		/* We already have a window, just change its size */
 
		if (!isCustom) {
 
			[ _cocoa_video_data.window setContentSize:contentRect.size ];
 
			// Ensure frame height - title bar height >= view height
 
			contentRect.size.height = clamp(height, 0, [ _cocoa_video_data.window frame ].size.height - 22 /* 22 is the height of title bar of window*/);
 
			contentRect.size.height = Clamp(height, 0, [ _cocoa_video_data.window frame ].size.height - 22 /* 22 is the height of title bar of window*/);
 
			height = contentRect.size.height;
 
			[ _cocoa_video_data.qdview setFrameSize:contentRect.size ];
 
		}
 
	}
 

	
 
	// Update again
 
	_cocoa_video_data.width = width;
 
	_cocoa_video_data.height = height;
 

	
 
	[ _cocoa_video_data.window center ];
 

	
 
	/* Only recreate the view if it doesn't already exist */
 
	if (_cocoa_video_data.qdview == nil) {
 
		_cocoa_video_data.qdview = [ [ NSQuickDrawView alloc ] initWithFrame:contentRect ];
 
		[ _cocoa_video_data.qdview setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ];
 
		[ [ _cocoa_video_data.window contentView ] addSubview:_cocoa_video_data.qdview ];
 
		[ _cocoa_video_data.qdview release ];
 
		[ _cocoa_video_data.window makeKeyAndOrderFront:nil ];
 
	}
 

	
 
	CGrafPtr thePort = (OpaqueGrafPtr*) [ _cocoa_video_data.qdview qdPort ];
 

	
 
	LockPortBits(thePort);
 
	_cocoa_video_data.realpixels = GetPixBaseAddr(GetPortPixMap(thePort));
src/video/sdl_v.cpp
Show inline comments
 
@@ -399,50 +399,50 @@ static int PollEvent()
 

	
 
		case SDL_ACTIVEEVENT:
 
			if (!(ev.active.state & SDL_APPMOUSEFOCUS)) break;
 

	
 
			if (ev.active.gain) { // mouse entered the window, enable cursor
 
				_cursor.in_window = true;
 
			} else {
 
				UndrawMouseCursor(); // mouse left the window, undraw cursor
 
				_cursor.in_window = false;
 
			}
 
			break;
 

	
 
		case SDL_QUIT: HandleExitGameRequest(); break;
 

	
 
		case SDL_KEYDOWN: /* Toggle full-screen on ALT + ENTER/F */
 
			if ((ev.key.keysym.mod & (KMOD_ALT | KMOD_META)) &&
 
					(ev.key.keysym.sym == SDLK_RETURN || ev.key.keysym.sym == SDLK_f)) {
 
				ToggleFullScreen(!_fullscreen);
 
			} else {
 
				HandleKeypress(ConvertSdlKeyIntoMy(&ev.key.keysym));
 
			}
 
			break;
 

	
 
		case SDL_VIDEORESIZE: {
 
			int w = clamp(ev.resize.w, 64, MAX_SCREEN_WIDTH);
 
			int h = clamp(ev.resize.h, 64, MAX_SCREEN_HEIGHT);
 
			int w = Clamp(ev.resize.w, 64, MAX_SCREEN_WIDTH);
 
			int h = Clamp(ev.resize.h, 64, MAX_SCREEN_HEIGHT);
 
			ChangeResInGame(w, h);
 
			break;
 
		}
 
	}
 
	return -1;
 
}
 

	
 
const char *VideoDriver_SDL::Start(const char * const *parm)
 
{
 
	char buf[30];
 

	
 
	const char *s = SdlOpen(SDL_INIT_VIDEO);
 
	if (s != NULL) return s;
 

	
 
	SDL_CALL SDL_VideoDriverName(buf, 30);
 
	DEBUG(driver, 1, "SDL: using driver '%s'", buf);
 

	
 
	GetVideoModes();
 
	CreateMainSurface(_cur_resolution[0], _cur_resolution[1]);
 
	MarkWholeScreenDirty();
 

	
 
	SDL_CALL SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
 
	SDL_CALL SDL_EnableUNICODE(1);
 
	return NULL;
src/video/win32_v.cpp
Show inline comments
 
@@ -524,50 +524,50 @@ static LRESULT CALLBACK WndProcGdi(HWND 
 
		case WM_SIZE:
 
			if (wParam != SIZE_MINIMIZED) {
 
				/* Set maximized flag when we maximize (obviously), but also when we
 
				 * switched to fullscreen from a maximized state */
 
				_window_maximize = (wParam == SIZE_MAXIMIZED || (_window_maximize && _fullscreen));
 
				if (_window_maximize) {
 
					_bck_resolution[0] = _cur_resolution[0];
 
					_bck_resolution[1] = _cur_resolution[1];
 
				}
 
				ClientSizeChanged(LOWORD(lParam), HIWORD(lParam));
 
			}
 
			return 0;
 

	
 
#if !defined(WINCE)
 
		case WM_SIZING: {
 
			RECT* r = (RECT*)lParam;
 
			RECT r2;
 
			int w, h;
 

	
 
			SetRect(&r2, 0, 0, 0, 0);
 
			AdjustWindowRect(&r2, GetWindowLong(hwnd, GWL_STYLE), FALSE);
 

	
 
			w = r->right - r->left - (r2.right - r2.left);
 
			h = r->bottom - r->top - (r2.bottom - r2.top);
 
			w = clamp(w, 64, MAX_SCREEN_WIDTH);
 
			h = clamp(h, 64, MAX_SCREEN_HEIGHT);
 
			w = Clamp(w, 64, MAX_SCREEN_WIDTH);
 
			h = Clamp(h, 64, MAX_SCREEN_HEIGHT);
 
			SetRect(&r2, 0, 0, w, h);
 

	
 
			AdjustWindowRect(&r2, GetWindowLong(hwnd, GWL_STYLE), FALSE);
 
			w = r2.right - r2.left;
 
			h = r2.bottom - r2.top;
 

	
 
			switch (wParam) {
 
				case WMSZ_BOTTOM:
 
					r->bottom = r->top + h;
 
					break;
 

	
 
				case WMSZ_BOTTOMLEFT:
 
					r->bottom = r->top + h;
 
					r->left = r->right - w;
 
					break;
 

	
 
				case WMSZ_BOTTOMRIGHT:
 
					r->bottom = r->top + h;
 
					r->right = r->left + w;
 
					break;
 

	
 
				case WMSZ_LEFT:
 
					r->left = r->right - w;
 
					break;
 
@@ -656,50 +656,50 @@ static void RegisterWndClass()
 
		WNDCLASS wnd = {
 
			0,
 
			WndProcGdi,
 
			0,
 
			0,
 
			hinst,
 
			LoadIcon(hinst, MAKEINTRESOURCE(100)),
 
			LoadCursor(NULL, IDC_ARROW),
 
			0,
 
			0,
 
			_T("OTTD")
 
		};
 

	
 
		registered = true;
 
		if (!RegisterClass(&wnd)) error("RegisterClass failed");
 
	}
 
}
 

	
 
static bool AllocateDibSection(int w, int h)
 
{
 
	BITMAPINFO *bi;
 
	HDC dc;
 
	int bpp = BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth();
 

	
 
	w = clamp(w, 64, MAX_SCREEN_WIDTH);
 
	h = clamp(h, 64, MAX_SCREEN_HEIGHT);
 
	w = Clamp(w, 64, MAX_SCREEN_WIDTH);
 
	h = Clamp(h, 64, MAX_SCREEN_HEIGHT);
 

	
 
	if (bpp == 0) error("Can't use a blitter that blits 0 bpp for normal visuals");
 

	
 
	if (w == _screen.width && h == _screen.height)
 
		return false;
 

	
 
	_screen.width = w;
 
	_screen.pitch = (bpp == 8) ? ALIGN(w, 4) : w;
 
	_screen.height = h;
 
	bi = (BITMAPINFO*)alloca(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256);
 
	memset(bi, 0, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256);
 
	bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
 

	
 
	bi->bmiHeader.biWidth = _wnd.width = w;
 
	bi->bmiHeader.biHeight = -(_wnd.height = h);
 

	
 
	bi->bmiHeader.biPlanes = 1;
 
	bi->bmiHeader.biBitCount = BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth();
 
	bi->bmiHeader.biCompression = BI_RGB;
 

	
 
	if (_wnd.dib_sect) DeleteObject(_wnd.dib_sect);
 

	
 
	dc = GetDC(0);
 
	_wnd.dib_sect = CreateDIBSection(dc, bi, DIB_RGB_COLORS, (VOID**)&_wnd.buffer_bits, NULL, 0);
src/viewport.cpp
Show inline comments
 
@@ -351,50 +351,50 @@ ViewPort *IsPtInWindowViewport(const Win
 
	return NULL;
 
}
 

	
 
static Point TranslateXYToTileCoord(const ViewPort *vp, int x, int y)
 
{
 
	Point pt;
 
	int a,b;
 
	uint z;
 

	
 
	if ( (uint)(x -= vp->left) >= (uint)vp->width ||
 
				(uint)(y -= vp->top) >= (uint)vp->height) {
 
				Point pt = {-1, -1};
 
				return pt;
 
	}
 

	
 
	x = (ScaleByZoom(x, vp->zoom) + vp->virtual_left) >> 2;
 
	y = (ScaleByZoom(y, vp->zoom) + vp->virtual_top) >> 1;
 

	
 
	a = y-x;
 
	b = y+x;
 

	
 
	/* we need to move variables in to the valid range, as the
 
	 * GetTileZoomCenterWindow() function can call here with invalid x and/or y,
 
	 * when the user tries to zoom out along the sides of the map */
 
	a = clamp(a, 0, (int)(MapMaxX() * TILE_SIZE) - 1);
 
	b = clamp(b, 0, (int)(MapMaxY() * TILE_SIZE) - 1);
 
	a = Clamp(a, 0, (int)(MapMaxX() * TILE_SIZE) - 1);
 
	b = Clamp(b, 0, (int)(MapMaxY() * TILE_SIZE) - 1);
 

	
 
	/* (a, b) is the X/Y-world coordinate that belongs to (x,y) if the landscape would be completely flat on height 0.
 
	 * Now find the Z-world coordinate by fix point iteration.
 
	 * This is a bit tricky because the tile height is non-continuous at foundations.
 
	 * The clicked point should be approached from the back, otherwise there are regions that are not clickable.
 
	 * (FOUNDATION_HALFTILE_LOWER on SLOPE_STEEP_S hides north halftile completely)
 
	 * So give it a z-malus of 4 in the first iterations.
 
	 */
 
	z = 0;
 
	for (int i = 0; i < 5; i++) z = GetSlopeZ(a + max(z, 4u) - 4, b + max(z, 4u) - 4) / 2;
 
	for (uint malus = 3; malus > 0; malus--) z = GetSlopeZ(a + max(z, malus) - malus, b + max(z, malus) - malus) / 2;
 
	for (int i = 0; i < 5; i++) z = GetSlopeZ(a + z, b + z) / 2;
 

	
 
	pt.x = a + z;
 
	pt.y = b + z;
 

	
 
	return pt;
 
}
 

	
 
/* When used for zooming, check area below current coordinates (x,y)
 
 * and return the tile of the zoomed out/in position (zoom_x, zoom_y)
 
 * when you just want the tile, make x = zoom_x and y = zoom_y */
 
static Point GetTileFromScreenXY(int x, int y, int zoom_x, int zoom_y)
 
{
 
@@ -1628,82 +1628,82 @@ void DrawWindowViewport(const Window *w)
 
{
 
	DrawPixelInfo *dpi = _cur_dpi;
 

	
 
	dpi->left += w->left;
 
	dpi->top += w->top;
 

	
 
	ViewportDraw(w->viewport, dpi->left, dpi->top, dpi->left + dpi->width, dpi->top + dpi->height);
 

	
 
	dpi->left -= w->left;
 
	dpi->top -= w->top;
 
}
 

	
 
static inline void ClampViewportToMap(const ViewPort *vp, int &x, int &y)
 
{
 
	/* Centre of the viewport is hot spot */
 
	x += vp->virtual_width / 2;
 
	y += vp->virtual_height / 2;
 

	
 
	/* Convert viewport coordinates to map coordinates
 
	 * Calculation is scaled by 4 to avoid rounding errors */
 
	int vx = -x + y * 2;
 
	int vy =  x + y * 2;
 

	
 
	/* clamp to size of map */
 
	vx = clamp(vx, 0, MapMaxX() * TILE_SIZE * 4);
 
	vy = clamp(vy, 0, MapMaxY() * TILE_SIZE * 4);
 
	vx = Clamp(vx, 0, MapMaxX() * TILE_SIZE * 4);
 
	vy = Clamp(vy, 0, MapMaxY() * TILE_SIZE * 4);
 

	
 
	/* Convert map coordinates to viewport coordinates */
 
	x = (-vx + vy) / 2;
 
	y = ( vx + vy) / 4;
 

	
 
	/* Remove centreing */
 
	x -= vp->virtual_width / 2;
 
	y -= vp->virtual_height / 2;
 
}
 

	
 
void UpdateViewportPosition(Window *w)
 
{
 
	const ViewPort *vp = w->viewport;
 

	
 
	if (WP(w, vp_d).follow_vehicle != INVALID_VEHICLE) {
 
		const Vehicle* veh = GetVehicle(WP(w,vp_d).follow_vehicle);
 
		Point pt = MapXYZToViewport(vp, veh->x_pos, veh->y_pos, veh->z_pos);
 

	
 
		SetViewportPosition(w, pt.x, pt.y);
 
	} else {
 
		/* Ensure the destination location is within the map */
 
		ClampViewportToMap(vp, WP(w, vp_d).dest_scrollpos_x, WP(w, vp_d).dest_scrollpos_y);
 

	
 
		int delta_x = WP(w, vp_d).dest_scrollpos_x - WP(w, vp_d).scrollpos_x;
 
		int delta_y = WP(w, vp_d).dest_scrollpos_y - WP(w, vp_d).scrollpos_y;
 

	
 
		if (delta_x != 0 || delta_y != 0) {
 
			if (_patches.smooth_scroll) {
 
				int max_scroll = ScaleByMapSize1D(512);
 
				/* Not at our desired positon yet... */
 
				WP(w, vp_d).scrollpos_x += clamp(delta_x / 4, -max_scroll, max_scroll);
 
				WP(w, vp_d).scrollpos_y += clamp(delta_y / 4, -max_scroll, max_scroll);
 
				WP(w, vp_d).scrollpos_x += Clamp(delta_x / 4, -max_scroll, max_scroll);
 
				WP(w, vp_d).scrollpos_y += Clamp(delta_y / 4, -max_scroll, max_scroll);
 
			} else {
 
				WP(w, vp_d).scrollpos_x = WP(w, vp_d).dest_scrollpos_x;
 
				WP(w, vp_d).scrollpos_y = WP(w, vp_d).dest_scrollpos_y;
 
			}
 
		}
 

	
 
		ClampViewportToMap(vp, WP(w, vp_d).scrollpos_x, WP(w, vp_d).scrollpos_y);
 
		SetViewportPosition(w, WP(w, vp_d).scrollpos_x, WP(w, vp_d).scrollpos_y);
 
	}
 
}
 

	
 
/**
 
 * Marks a viewport as dirty for repaint.
 
 *
 
 * @param vp The viewport to mark as dirty
 
 * @todo documents the missing parameters @c left, @c top, @c right and @c bottom
 
 * @todo detailed description missing
 
 * @ingroup dirty
 
 */
 
static void MarkViewportDirty(const ViewPort *vp, int left, int top, int right, int bottom)
 
{
 
	right -= vp->virtual_left;
 
	if (right <= 0) return;
 

	
 
@@ -2698,50 +2698,50 @@ calc_heightdiff_single_direction:;
 
			if (_patches.measure_tooltip) {
 
				TileIndex t0 = TileVirtXY(sx, sy);
 
				TileIndex t1 = TileVirtXY(x, y);
 
				uint distance = DistanceManhattan(t0, t1) + 1;
 
				byte index = 0;
 
				uint64 params[2];
 

	
 
				if (distance != 1) {
 
					/* With current code passing a HT_LINE style to calculate the height
 
					 * difference is enough. However if/when a point-tool is created
 
					 * with this method, function should be called with new_style (below)
 
					 * instead of HT_LINE | style case HT_POINT is handled specially
 
					 * new_style := (_thd.next_drawstyle & HT_RECT) ? HT_LINE | style : _thd.next_drawstyle; */
 
					int heightdiff = CalcHeightdiff(HT_LINE | style, 0, t0, t1);
 

	
 
					params[index++] = distance;
 
					if (heightdiff != 0) params[index++] = heightdiff;
 
				}
 

	
 
				GuiShowTooltipsWithArgs(measure_strings_length[index], index, params);
 
			} break;
 

	
 
		case VPM_X_AND_Y_LIMITED: { /* drag an X by Y constrained rect area */
 
			int limit = (_thd.sizelimit - 1) * TILE_SIZE;
 
			x = sx + clamp(x - sx, -limit, limit);
 
			y = sy + clamp(y - sy, -limit, limit);
 
			x = sx + Clamp(x - sx, -limit, limit);
 
			y = sy + Clamp(y - sy, -limit, limit);
 
			} /* Fallthrough */
 
		case VPM_X_AND_Y: { /* drag an X by Y area */
 
			if (_patches.measure_tooltip) {
 
				static const StringID measure_strings_area[] = {
 
					STR_NULL, STR_NULL, STR_MEASURE_AREA, STR_MEASURE_AREA_HEIGHTDIFF
 
				};
 

	
 
				TileIndex t0 = TileVirtXY(sx, sy);
 
				TileIndex t1 = TileVirtXY(x, y);
 
				uint dx = delta(TileX(t0), TileX(t1)) + 1;
 
				uint dy = delta(TileY(t0), TileY(t1)) + 1;
 
				byte index = 0;
 
				uint64 params[3];
 

	
 
				/* If dragging an area (eg dynamite tool) and it is actually a single
 
				 * row/column, change the type to 'line' to get proper calculation for height */
 
				style = _thd.next_drawstyle;
 
				if (style & HT_RECT) {
 
					if (dx == 1) {
 
						style = HT_LINE | HT_DIR_Y;
 
					} else if (dy == 1) {
 
						style = HT_LINE | HT_DIR_X;
 
					}
 
				}
src/window.cpp
Show inline comments
 
@@ -175,49 +175,49 @@ static void DispatchRightClickEvent(Wind
 
/** Dispatch the mousewheel-action to the window which will scroll any
 
 * compatible scrollbars if the mouse is pointed over the bar or its contents
 
 * @param *w Window
 
 * @param widget the widget where the scrollwheel was used
 
 * @param wheel scroll up or down
 
 */
 
static void DispatchMouseWheelEvent(Window *w, int widget, int wheel)
 
{
 
	const Widget *wi1, *wi2;
 
	Scrollbar *sb;
 

	
 
	if (widget < 0) return;
 

	
 
	wi1 = &w->widget[widget];
 
	wi2 = &w->widget[widget + 1];
 

	
 
	/* The listbox can only scroll if scrolling was done on the scrollbar itself,
 
	 * or on the listbox (and the next item is (must be) the scrollbar)
 
	 * XXX - should be rewritten as a widget-dependent scroller but that's
 
	 * not happening until someone rewrites the whole widget-code */
 
	if ((sb = &w->vscroll,  wi1->type == WWT_SCROLLBAR)  || (sb = &w->vscroll2, wi1->type == WWT_SCROLL2BAR)  ||
 
			(sb = &w->vscroll2, wi2->type == WWT_SCROLL2BAR) || (sb = &w->vscroll, wi2->type == WWT_SCROLLBAR) ) {
 

	
 
		if (sb->count > sb->cap) {
 
			int pos = clamp(sb->pos + wheel, 0, sb->count - sb->cap);
 
			int pos = Clamp(sb->pos + wheel, 0, sb->count - sb->cap);
 
			if (pos != sb->pos) {
 
				sb->pos = pos;
 
				SetWindowDirty(w);
 
			}
 
		}
 
	}
 
}
 

	
 
static void DrawOverlappedWindow(Window* const *wz, int left, int top, int right, int bottom);
 

	
 
void DrawOverlappedWindowForAll(int left, int top, int right, int bottom)
 
{
 
	Window* const *wz;
 
	DrawPixelInfo bk;
 
	_cur_dpi = &bk;
 

	
 
	FOR_ALL_WINDOWS(wz) {
 
		const Window *w = *wz;
 
		if (right > w->left &&
 
				bottom > w->top &&
 
				left < w->left + w->width &&
 
				top < w->top + w->height) {
 
			DrawOverlappedWindow(wz, left, top, right, bottom);
 
		}
 
@@ -1274,50 +1274,50 @@ static bool HandleWindowDragging()
 
							vsnap = delta;
 
						}
 
					}
 

	
 
					if (w->left + w->width >= v->left && w->left <= v->left + v->width) {
 
						/* Your top border <-> other top border */
 
						delta = abs(v->top - y);
 
						if (delta <= vsnap) {
 
							ny = v->top;
 
							vsnap = delta;
 
						}
 

	
 
						/* Your bottom border <-> other bottom border */
 
						delta = abs(v->top + v->height - y - w->height);
 
						if (delta <= vsnap) {
 
							ny = v->top + v->height - w->height;
 
							vsnap = delta;
 
						}
 
					}
 
				}
 
			}
 

	
 
			/* Make sure the window doesn't leave the screen
 
			 * 13 is the height of the title bar */
 
			nx = clamp(nx, 13 - t->right, _screen.width - 13 - t->left);
 
			ny = clamp(ny, 0, _screen.height - 13);
 
			nx = Clamp(nx, 13 - t->right, _screen.width - 13 - t->left);
 
			ny = Clamp(ny, 0, _screen.height - 13);
 

	
 
			/* Make sure the title bar isn't hidden by behind the main tool bar */
 
			v = FindWindowById(WC_MAIN_TOOLBAR, 0);
 
			if (v != NULL) {
 
				int v_bottom = v->top + v->height;
 
				int v_right = v->left + v->width;
 
				if (ny + t->top >= v->top && ny + t->top < v_bottom) {
 
					if ((v->left < 13 && nx + t->left < v->left) ||
 
							(v_right > _screen.width - 13 && nx + t->right > v_right)) {
 
						ny = v_bottom;
 
					} else {
 
						if (nx + t->left > v->left - 13 &&
 
								nx + t->right < v_right + 13) {
 
							if (w->top >= v_bottom) {
 
								ny = v_bottom;
 
							} else if (w->left < nx) {
 
								nx = v->left - 13 - t->left;
 
							} else {
 
								nx = v_right + 13 - t->right;
 
							}
 
						}
 
					}
 
				}
 
			}
 
@@ -2092,55 +2092,55 @@ void RelocateAllWindows(int neww, int ne
 
					e.we.sizing.size.x = w->width;
 
					e.we.sizing.size.y = w->height;
 
					e.we.sizing.diff.x = neww - w->width;
 
					e.we.sizing.diff.y = 0;
 
					w->wndproc(w, &e);
 
				}
 

	
 
				top = w->top;
 
				left = PositionMainToolbar(w); // changes toolbar orientation
 
				break;
 

	
 
			case WC_SELECT_GAME:
 
			case WC_GAME_OPTIONS:
 
			case WC_NETWORK_WINDOW:
 
				top = (newh - w->height) >> 1;
 
				left = (neww - w->width) >> 1;
 
				break;
 

	
 
			case WC_NEWS_WINDOW:
 
				top = newh - w->height;
 
				left = (neww - w->width) >> 1;
 
				break;
 

	
 
			case WC_STATUS_BAR:
 
				ResizeWindow(w, clamp(neww, 320, 640) - w->width, 0);
 
				ResizeWindow(w, Clamp(neww, 320, 640) - w->width, 0);
 
				top = newh - w->height;
 
				left = (neww - w->width) >> 1;
 
				break;
 

	
 
			case WC_SEND_NETWORK_MSG:
 
				ResizeWindow(w, clamp(neww, 320, 640) - w->width, 0);
 
				ResizeWindow(w, Clamp(neww, 320, 640) - w->width, 0);
 
				top = (newh - 26); // 26 = height of status bar + height of chat bar
 
				left = (neww - w->width) >> 1;
 
				break;
 

	
 
			case WC_CONSOLE:
 
				IConsoleResize(w);
 
				continue;
 

	
 
			default:
 
				left = w->left;
 
				if (left + (w->width >> 1) >= neww) left = neww - w->width;
 
				top = w->top;
 
				if (top + (w->height >> 1) >= newh) top = newh - w->height;
 
				break;
 
		}
 

	
 
		if (w->viewport != NULL) {
 
			w->viewport->left += left - w->left;
 
			w->viewport->top += top - w->top;
 
		}
 

	
 
		w->left = left;
 
		w->top = top;
 
	}
0 comments (0 inline, 0 general)