43 #include "table/strings.h"
49 bool _ignore_restrictions;
82 if (callback > 0x400) {
84 }
else if (indspec->
grf_prop.
grffile->grf_version >= 8 ||
GB(callback, 0, 8) != 0xFF) {
102 template <
typename TC,
typename TS>
106 for (uint j = 0; j <
lengthof(cargoes); j++) {
110 suffixes[j][0] =
'\0';
120 static char industry_name[2][64];
123 GetString(industry_name[0], indsp1->
name,
lastof(industry_name[0]));
126 GetString(industry_name[1], indsp2->
name,
lastof(industry_name[1]));
128 int r =
strnatcmp(industry_name[0], industry_name[1]);
131 return (r != 0) ? r : (*a - *b);
159 uint8 indtype =
GB(p1, 0, 8);
169 static const NWidgetPart _nested_build_industry_widgets[] = {
178 NWidget(
WWT_MATRIX, COLOUR_DARK_GREEN,
WID_DPI_MATRIX_WIDGET),
SetMatrixDataTip(1, 0, STR_FUND_INDUSTRY_SELECTION_TOOLTIP),
SetFill(1, 0),
SetResize(1, 1),
SetScrollbar(
WID_DPI_SCROLLBAR),
185 SetDataTip(STR_INDUSTRY_DISPLAY_CHAIN, STR_INDUSTRY_DISPLAY_CHAIN_TOOLTIP),
193 WDP_AUTO,
"build_industry", 170, 212,
196 _nested_build_industry_widgets,
lengthof(_nested_build_industry_widgets)
222 if (_game_mode == GM_EDITOR) {
296 for (byte i = 0; i < this->
count; i++) {
302 d.height = 5 * resize->height;
311 for (byte i = 0; i < this->
count; i++) {
316 char cargo_suffix[3][512];
318 StringID str = STR_INDUSTRY_VIEW_REQUIRES_CARGO;
332 str = STR_INDUSTRY_VIEW_PRODUCES_CARGO;
336 for (byte j = 0; j <
lengthof(indsp->produced_cargo); j++) {
337 if (indsp->produced_cargo[j] ==
CT_INVALID)
continue;
355 d.width += padding.width;
356 d.height += padding.height;
369 if (_game_mode == GM_EDITOR) {
371 SetDParam(0, STR_FUND_INDUSTRY_BUILD_NEW_INDUSTRY);
384 uint text_left, text_right, icon_left, icon_right;
387 icon_left = icon_right - 10;
392 icon_right = icon_left + 10;
402 DrawString(text_left, text_right, y, STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES, selected ? TC_WHITE : TC_ORANGE);
408 DrawString(text_left, text_right, y, indsp->
name, selected ? TC_WHITE : TC_ORANGE);
422 DrawStringMultiLine(left, right, y, bottom, STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_TOOLTIP);
428 if (_game_mode != GM_EDITOR) {
430 DrawString(left, right, y, STR_FUND_INDUSTRY_INDUSTRY_BUILD_COST);
435 char cargo_suffix[3][512];
437 StringID str = STR_INDUSTRY_VIEW_REQUIRES_CARGO;
452 str = STR_INDUSTRY_VIEW_PRODUCES_CARGO;
456 for (byte j = 0; j <
lengthof(indsp->produced_cargo); j++) {
457 if (indsp->produced_cargo[j] ==
CT_INVALID)
continue;
470 if (callback_res > 0x400) {
474 if (str != STR_UNDEFINED) {
492 if (y < this->
count) {
552 uint32 seed = InteractiveRandom();
554 if (_game_mode == GM_EDITOR) {
564 _ignore_restrictions =
true;
566 DoCommandP(tile, (InteractiveRandomRange(indsp->
num_table) << 8) | this->selected_type, seed,
570 _ignore_restrictions =
false;
621 if (!gui_scope)
return;
630 void ShowBuildIndustryWindow()
637 static void UpdateIndustryProduction(
Industry *i);
639 static inline bool IsProductionAlterable(
const Industry *i)
643 (is->production_rate[0] != 0 || is->production_rate[1] != 0 || is->
IsRawIndustry()) &&
715 bool has_accept =
false;
716 char cargo_suffix[3][512];
741 StringID str = STR_INDUSTRY_VIEW_REQUIRES_CARGO;
775 if (this->editable ==
EA_RATE) {
798 if (callback_res > 0x400) {
802 if (message != STR_NULL && message != STR_UNDEFINED) {
843 if (pt.y >= this->production_offset_y) {
858 NWidgetBase *nwi = this->GetWidget<NWidgetBase>(widget);
887 default: NOT_REACHED();
890 UpdateIndustryProduction(i);
909 default: NOT_REACHED();
955 uint value = atoi(str);
967 UpdateIndustryProduction(i);
978 if (!gui_scope)
return;
980 if (IsProductionAlterable(i)) {
999 static void UpdateIndustryProduction(
Industry *i)
1023 NWidget(
NWID_VIEWPORT, INVALID_COLOUR,
WID_IV_VIEWPORT),
SetMinimalSize(254, 86),
SetFill(1, 0),
SetPadding(1, 1, 1, 1),
SetResize(1, 1),
1037 WDP_AUTO,
"view_industry", 260, 120,
1040 _nested_industry_view_widgets,
lengthof(_nested_industry_view_widgets)
1043 void ShowIndustryViewWindow(
int industry)
1083 static const Industry *last_industry;
1086 static const StringID sorter_names[];
1089 GUIIndustryList industries;
1096 this->industries.
Clear();
1099 FOR_ALL_INDUSTRIES(i) {
1100 *this->industries.
Append() = i;
1108 if (!this->industries.
Sort())
return;
1109 IndustryDirectoryWindow::last_industry = NULL;
1140 if (p1 > p2)
Swap(p1, p2);
1142 return (p1 << 8) + p2;
1148 static char buf_cache[96];
1149 static char buf[96];
1152 GetString(buf, STR_INDUSTRY_NAME,
lastof(buf));
1154 if (*b != last_industry) {
1157 GetString(buf_cache, STR_INDUSTRY_NAME,
lastof(buf_cache));
1170 int r = it_a - it_b;
1177 uint prod_a = 0, prod_b = 0;
1178 for (uint i = 0; i <
lengthof((*a)->produced_cargo); i++) {
1179 if ((*a)->produced_cargo[i] !=
CT_INVALID) prod_a += (*a)->last_month_production[i];
1180 if ((*b)->produced_cargo[i] !=
CT_INVALID) prod_b += (*b)->last_month_production[i];
1182 int r = prod_a - prod_b;
1226 case 1:
return STR_INDUSTRY_DIRECTORY_ITEM_NOPROD;
1227 case 5:
return STR_INDUSTRY_DIRECTORY_ITEM;
1228 default:
return STR_INDUSTRY_DIRECTORY_ITEM_TWO;
1238 this->industries.
SetListing(this->last_sorting);
1239 this->industries.
SetSortFuncs(IndustryDirectoryWindow::sorter_funcs);
1248 this->last_sorting = this->industries.
GetListing();
1266 if (this->industries.
Length() == 0) {
1270 for (uint i = this->vscroll->
GetPosition(); i < this->industries.
Length(); i++) {
1287 d.height += padding.height;
1288 *size =
maxdim(*size, d);
1294 for (uint i = 0; IndustryDirectoryWindow::sorter_names[i] !=
INVALID_STRING_ID; i++) {
1297 d.width += padding.width;
1298 d.height += padding.height;
1299 *size =
maxdim(*size, d);
1305 for (uint i = 0; i < this->industries.
Length(); i++) {
1308 resize->height = d.height;
1312 *size =
maxdim(*size, d);
1333 if (p < this->industries.
Length()) {
1347 if (this->industries.
SortType() != index) {
1386 Listing IndustryDirectoryWindow::last_sorting = {
false, 0};
1387 const Industry *IndustryDirectoryWindow::last_industry = NULL;
1391 &IndustryNameSorter,
1392 &IndustryTypeSorter,
1393 &IndustryProductionSorter,
1394 &IndustryTransportedCargoSorter
1398 const StringID IndustryDirectoryWindow::sorter_names[] = {
1401 STR_SORT_BY_PRODUCTION,
1402 STR_SORT_BY_TRANSPORTED,
1409 WDP_AUTO,
"list_industries", 428, 190,
1412 _nested_industry_directory_widgets,
lengthof(_nested_industry_directory_widgets)
1415 void ShowIndustryDirectory()
1434 SetDataTip(STR_INDUSTRY_CARGOES_NOTIFY_SMALLMAP, STR_INDUSTRY_CARGOES_NOTIFY_SMALLMAP_TOOLTIP),
1437 SetDataTip(STR_INDUSTRY_CARGOES_SELECT_INDUSTRY, STR_INDUSTRY_CARGOES_SELECT_INDUSTRY_TOOLTIP),
1439 SetDataTip(STR_INDUSTRY_CARGOES_SELECT_CARGO, STR_INDUSTRY_CARGOES_SELECT_CARGO_TOOLTIP),
1451 WDP_AUTO,
"industry_cargoes", 300, 210,
1454 _nested_industry_cargoes_widgets,
lengthof(_nested_industry_cargoes_widgets)
1524 this->u.industry.ind_type =
ind_type;
1542 for (
int i = 0; i < this->u.cargo.num_cargoes; i++) {
1543 if (cargo == this->u.cargo.vertical_cargoes[i]) {
1548 if (column < 0)
return -1;
1551 assert(this->u.cargo.supp_cargoes[column] ==
INVALID_CARGO);
1552 this->u.cargo.supp_cargoes[column] = column;
1554 assert(this->u.cargo.cust_cargoes[column] ==
INVALID_CARGO);
1555 this->u.cargo.cust_cargoes[column] = column;
1569 if (this->u.cargo.supp_cargoes[i] !=
INVALID_CARGO)
return true;
1570 if (this->u.cargo.cust_cargoes[i] !=
INVALID_CARGO)
return true;
1589 for (i = 0; i < MAX_CARGOES && i < length; i++) {
1591 this->u.cargo.vertical_cargoes[num] = cargoes[i];
1595 this->u.cargo.num_cargoes = (count < 0) ? num : count;
1597 this->u.cargo.top_end =
top_end;
1613 for (i = 0; i < MAX_CARGOES && i < length; i++) this->u.cargo_label.cargoes[i] = cargoes[i];
1615 this->u.cargo_label.left_align = left_align;
1625 this->u.header = textid;
1637 switch (this->u.cargo.num_cargoes) {
1642 default: NOT_REACHED();
1651 void Draw(
int xpos,
int ypos)
const
1653 switch (this->
type) {
1677 int blob_left, blob_right;
1692 const CargoID *other_right, *other_left;
1694 other_right = this->u.industry.other_accepted;
1695 other_left = this->u.industry.other_produced;
1697 other_right = this->u.industry.other_produced;
1698 other_left = this->u.industry.other_accepted;
1723 int colpos = cargo_base;
1724 for (
int i = 0; i < this->u.cargo.num_cargoes; i++) {
1736 const CargoID *hor_left, *hor_right;
1738 hor_left = this->u.cargo.cust_cargoes;
1739 hor_right = this->u.cargo.supp_cargoes;
1741 hor_left = this->u.cargo.supp_cargoes;
1742 hor_right = this->u.cargo.cust_cargoes;
1747 int col = hor_left[i];
1750 for (; col > 0; col--) {
1758 int col = hor_right[i];
1761 for (; col < this->u.cargo.num_cargoes - 1; col++) {
1804 for (col = 0; col < this->u.cargo.num_cargoes; col++) {
1805 if (pt.x < cpos)
break;
1822 if (this->u.cargo.supp_cargoes[row] !=
INVALID_CARGO)
return this->u.cargo.vertical_cargoes[this->u.cargo.supp_cargoes[row]];
1829 if (col == this->u.cargo.num_cargoes) {
1830 if (this->u.cargo.cust_cargoes[row] !=
INVALID_CARGO)
return this->u.cargo.vertical_cargoes[this->u.cargo.cust_cargoes[row]];
1831 if (right != NULL) {
1842 return (this->u.cargo.supp_cargoes[row] !=
INVALID_CARGO) ? this->u.cargo.vertical_cargoes[this->u.cargo.supp_cargoes[row]] :
INVALID_CARGO;
1845 return (this->u.cargo.cust_cargoes[row] !=
INVALID_CARGO) ? this->u.cargo.vertical_cargoes[this->u.cargo.cust_cargoes[row]] :
INVALID_CARGO;
1866 return this->u.cargo_label.cargoes[row];
1928 int other_count = 0;
1931 for (uint i = 0; i <
lengthof(indsp->produced_cargo); i++) {
1932 int col = cargo_fld->
ConnectCargo(indsp->produced_cargo[i],
true);
1933 if (col < 0) others[other_count++] = indsp->produced_cargo[i];
1937 for (uint i = 0; i < MAX_CARGOES && other_count > 0; i++) {
1942 for (uint i = 0; i < cargo_fld->u.
cargo.num_cargoes; i++) {
1944 if (cid == CT_PASSENGERS || cid == CT_MAIL) cargo_fld->
ConnectCargo(cid,
true);
1963 for (uint i = 0; i < cargo_fld->u.
cargo.num_cargoes; i++) {
1964 int col = cargo_fld->
ConnectCargo(cargo_fld->u.
cargo.vertical_cargoes[i], !accepting);
1965 if (col >= 0) cargoes[col] = cargo_fld->u.
cargo.vertical_cargoes[i];
1985 int other_count = 0;
1990 if (col < 0) others[other_count++] = indsp->
accepts_cargo[i];
1994 for (uint i = 0; i < MAX_CARGOES && other_count > 0; i++) {
1999 for (uint i = 0; i < cargo_fld->u.
cargo.num_cargoes; i++) {
2072 CargoesField::small_height = d.height;
2079 if (!indsp->
enabled)
continue;
2082 d.width =
max(d.width, this->ind_textsize.width);
2091 if (!csp->
IsValid())
continue;
2099 uint min_ind_height = CargoesField::VERT_CARGO_EDGE * 2 + MAX_CARGOES *
FONT_HEIGHT_NORMAL + (MAX_CARGOES - 1) * CargoesField::VERT_CARGO_SPACE;
2102 CargoesField::industry_width = d.width;
2103 CargoesField::normal_height = d.height + CargoesField::VERT_INTER_INDUSTRY_SPACE;
2114 size->width =
max(size->width, this->ind_textsize.width + padding.width);
2118 size->width =
max(size->width, this->cargo_textsize.width + padding.width);
2148 while (length1 > 0) {
2150 for (uint i = 0; i < length2; i++)
if (*cargoes1 == cargoes2[i])
return true;
2166 for (uint i = 0; i < length; i++) {
2168 if (cargoes[i] == CT_PASSENGERS || cargoes[i] == CT_MAIL)
return true;
2183 case LT_TEMPERATE: climate_mask =
HZ_TEMP;
break;
2186 case LT_TOYLAND: climate_mask =
HZ_TOYLND;
break;
2187 default: NOT_REACHED();
2189 for (uint i = 0; i < length; i++) {
2215 if (!indsp->
enabled)
continue;
2233 if (!indsp->
enabled)
continue;
2248 while (top < bottom && !this->
fields[top].columns[column].HasConnection()) {
2252 this->
fields[
top].columns[column].u.cargo.top_end =
true;
2254 while (bottom > top && !this->
fields[bottom].columns[column].HasConnection()) {
2258 this->
fields[bottom].columns[column].u.cargo.bottom_end =
true;
2270 this->
fields[row].columns[col].MakeIndustry(it);
2272 this->
fields[row].ConnectIndustryProduced(col);
2274 this->
fields[row].ConnectIndustryAccepted(col);
2296 this->GetWidget<NWidgetCore>(
WID_IC_CAPTION)->widget_data = STR_INDUSTRY_CARGOES_INDUSTRY_CAPTION;
2315 int num_indrows =
max(3,
max(num_supp, num_cust));
2316 for (
int i = 0; i < num_indrows; i++) {
2325 int central_row = 1 + num_indrows / 2;
2326 this->
fields[central_row].columns[2].MakeIndustry(it);
2327 this->
fields[central_row].ConnectIndustryProduced(2);
2328 this->
fields[central_row].ConnectIndustryAccepted(2);
2331 this->
fields[central_row - 1].MakeCargoLabel(2,
true);
2332 this->
fields[central_row + 1].MakeCargoLabel(2,
false);
2339 if (!indsp->
enabled)
continue;
2342 this->
PlaceIndustry(1 + supp_count * num_indrows / num_supp, 0, it);
2347 this->
PlaceIndustry(1 + cust_count * num_indrows / num_cust, 4, it);
2352 if (houses_supply) {
2353 this->
PlaceIndustry(1 + supp_count * num_indrows / num_supp, 0, NUM_INDUSTRYTYPES);
2356 if (houses_accept) {
2357 this->
PlaceIndustry(1 + cust_count * num_indrows / num_cust, 4, NUM_INDUSTRYTYPES);
2375 this->GetWidget<NWidgetCore>(
WID_IC_CAPTION)->widget_data = STR_INDUSTRY_CARGOES_CARGO_CAPTION;
2391 int num_indrows =
max(num_supp, num_cust);
2392 for (
int i = 0; i < num_indrows; i++) {
2401 this->
fields[num_indrows].MakeCargoLabel(0,
false);
2408 if (!indsp->
enabled)
continue;
2411 this->
PlaceIndustry(1 + supp_count * num_indrows / num_supp, 0, it);
2416 this->
PlaceIndustry(1 + cust_count * num_indrows / num_cust, 2, it);
2421 if (houses_supply) {
2422 this->
PlaceIndustry(1 + supp_count * num_indrows / num_supp, 0, NUM_INDUSTRYTYPES);
2425 if (houses_accept) {
2426 this->
PlaceIndustry(1 + cust_count * num_indrows / num_cust, 2, NUM_INDUSTRYTYPES);
2446 if (!gui_scope)
return;
2464 int width = r.right - r.left + 1;
2468 _cur_dpi = &tmp_dpi;
2477 int row_height = (i == 0) ? CargoesField::small_height : CargoesField::normal_height;
2478 if (vpos + row_height >= 0) {
2479 int xpos = left_pos;
2488 while (col >= 0 && col <= last_column) {
2489 this->
fields[i].columns[col].Draw(xpos, vpos);
2490 xpos += (col & 1) ? CargoesField::CARGO_FIELD_WIDTH : CargoesField::industry_width;
2495 if (vpos >= height)
break;
2515 if (pt.y < vpos)
return false;
2517 int row = (pt.y - vpos) / CargoesField::normal_height;
2518 if (row + 1 >= (
int)this->
fields.
Length())
return false;
2519 vpos = pt.y - vpos - row * CargoesField::normal_height;
2523 if (pt.x < xpos)
return false;
2525 for (column = 0; column <= 5; column++) {
2526 int width = (column & 1) ? CargoesField::CARGO_FIELD_WIDTH : CargoesField::industry_width;
2527 if (pt.x < xpos + width)
break;
2531 if (column > num_columns)
return false;
2538 fieldxy->x = num_columns - column;
2539 xy->x = ((column & 1) ? CargoesField::CARGO_FIELD_WIDTH : CargoesField::industry_width) - xpos;
2541 fieldxy->x = column;
2555 switch (fld->
type) {
2561 CargoesField *lft = (fieldxy.x > 0) ? this->
fields[fieldxy.y].columns + fieldxy.x - 1 : NULL;
2562 CargoesField *rgt = (fieldxy.x < 4) ? this->
fields[fieldxy.y].columns + fieldxy.x + 1 : NULL;
2597 if (lst->
Length() == 0) {
2611 if (!indsp->
enabled)
continue;
2614 if (lst->
Length() == 0) {
2627 if (index < 0)
return;
2649 switch (fld->
type) {
2651 CargoesField *lft = (fieldxy.x > 0) ? this->
fields[fieldxy.y].columns + fieldxy.x - 1 : NULL;
2652 CargoesField *rgt = (fieldxy.x < 4) ? this->
fields[fieldxy.y].columns + fieldxy.x + 1 : NULL;
2664 GuiShowTooltips(
this, STR_INDUSTRY_CARGOES_INDUSTRY_TOOLTIP, 0, NULL, TCC_HOVER);
2674 params[0] = csp->
name;
2675 GuiShowTooltips(
this, STR_INDUSTRY_CARGOES_CARGO_TOOLTIP, 1, params, TCC_HOVER);
2702 if (
id >= NUM_INDUSTRYTYPES)
return;