mirror of https://github.com/OpenTTD/OpenTTD
(svn r11442) -Feature: make news messages related to the industry (production) changes better configurable; you can now disable news messages popping up for industries you are not servicing. Patch by Alberth.
parent
70c7a44a4d
commit
4dcd71038d
|
@ -13,6 +13,7 @@
|
|||
#include "table/sprites.h"
|
||||
#include "map.h"
|
||||
#include "tile.h"
|
||||
#include "train.h"
|
||||
#include "landscape.h"
|
||||
#include "viewport.h"
|
||||
#include "command.h"
|
||||
|
@ -1856,6 +1857,134 @@ static bool CheckIndustryCloseDownProtection(IndustryType type)
|
|||
return (indspec->behaviour & INDUSTRYBEH_CANCLOSE_LASTINSTANCE) == 0 && GetIndustryTypeCount(type) <= 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can given cargo type be accepted or produced by the industry?
|
||||
* @param cargo: Cargo type
|
||||
* @param ind: Industry
|
||||
* @param *c_accepts: Pointer to boolean for acceptance of cargo
|
||||
* @param *c_produces: Pointer to boolean for production of cargo
|
||||
* @return: \c *c_accepts is set when industry accepts the cargo type,
|
||||
* \c *c_produces is set when the industry produces the cargo type
|
||||
*/
|
||||
static void CanCargoServiceIndustry(CargoID cargo, Industry *ind, bool *c_accepts, bool *c_produces)
|
||||
{
|
||||
const IndustrySpec *indspec = GetIndustrySpec(ind->type);
|
||||
|
||||
/* Check for acceptance of cargo */
|
||||
for (uint j = 0; j < lengthof(ind->accepts_cargo) && ind->accepts_cargo[j] != CT_INVALID; j++) {
|
||||
if (cargo == ind->accepts_cargo[j]) {
|
||||
if (HASBIT(indspec->callback_flags, CBM_IND_REFUSE_CARGO)) {
|
||||
uint16 res = GetIndustryCallback(CBID_INDUSTRY_REFUSE_CARGO,
|
||||
0, GetReverseCargoTranslation(cargo, indspec->grf_prop.grffile),
|
||||
ind, ind->type, ind->xy);
|
||||
if (res == 0) continue;
|
||||
}
|
||||
*c_accepts = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for produced cargo */
|
||||
for (uint j = 0; j < lengthof(ind->produced_cargo) && ind->produced_cargo[j] != CT_INVALID; j++) {
|
||||
if (cargo == ind->produced_cargo[j]) {
|
||||
*c_produces = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute who can service the industry.
|
||||
*
|
||||
* Here, 'can service' means that he/she has trains and stations close enough
|
||||
* to the industry with the right cargo type and the right orders (ie has the
|
||||
* technical means).
|
||||
*
|
||||
* @param ind: Industry being investigated.
|
||||
*
|
||||
* @return: 0 if nobody can service the industry, 2 if the local player can
|
||||
* service the industry, and 1 otherwise (only competitors can service the
|
||||
* industry)
|
||||
*/
|
||||
int WhoCanServiceIndustry(Industry* ind)
|
||||
{
|
||||
/* Find all stations within reach of the industry */
|
||||
StationSet stations = FindStationsAroundIndustryTile(ind->xy, ind->width, ind->height);
|
||||
|
||||
if (stations.size() == 0) return 0; // No stations found at all => nobody services
|
||||
|
||||
const Vehicle *v;
|
||||
int result = 0;
|
||||
FOR_ALL_VEHICLES(v) {
|
||||
/* Is it worthwhile to try this vehicle? */
|
||||
if (v->owner != _local_player && result != 0) continue;
|
||||
|
||||
/* Check whether it accepts the right kind of cargo */
|
||||
bool c_accepts = false;
|
||||
bool c_produces = false;
|
||||
if (v->type == VEH_TRAIN && IsFrontEngine(v)) {
|
||||
const Vehicle *u = v;
|
||||
BEGIN_ENUM_WAGONS(u)
|
||||
CanCargoServiceIndustry(u->cargo_type, ind, &c_accepts, &c_produces);
|
||||
END_ENUM_WAGONS(u)
|
||||
} else if (v->type == VEH_ROAD || v->type == VEH_SHIP || v->type == VEH_AIRCRAFT) {
|
||||
CanCargoServiceIndustry(v->cargo_type, ind, &c_accepts, &c_produces);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
if (!c_accepts && !c_produces) continue; // Wrong cargo
|
||||
|
||||
/* Check orders of the vehicle.
|
||||
* We cannot check the first of shared orders only, since the first vehicle in such a chain
|
||||
* may have a different cargo type.
|
||||
*/
|
||||
const Order *o;
|
||||
FOR_VEHICLE_ORDERS(v, o) {
|
||||
if (o->type == OT_GOTO_STATION && !HASBIT(o->flags, OFB_TRANSFER)) {
|
||||
/* Vehicle visits a station to load or unload */
|
||||
Station *st = GetStation(o->dest);
|
||||
if (!st->IsValid()) continue;
|
||||
|
||||
/* Same cargo produced by industry is dropped here => not serviced by vehicle v */
|
||||
if (HASBIT(o->flags, OFB_UNLOAD) && !c_accepts) break;
|
||||
|
||||
if (stations.find(st) != stations.end()) {
|
||||
if (v->owner == _local_player) return 2; // Player services industry
|
||||
result = 1; // Competitor services industry
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Report news that industry production has changed significantly
|
||||
*
|
||||
* @param ind: Industry with changed production
|
||||
* @param type: Cargo type that has changed
|
||||
* @param percent: Percentage of change (>0 means increase, <0 means decrease)
|
||||
*/
|
||||
static void ReportNewsProductionChangeIndustry(Industry *ind, CargoID type, int percent)
|
||||
{
|
||||
NewsType nt;
|
||||
|
||||
switch (WhoCanServiceIndustry(ind)) {
|
||||
case 0: nt = NT_INDUSTRY_NOBODY; break;
|
||||
case 1: nt = NT_INDUSTRY_OTHER; break;
|
||||
case 2: nt = NT_INDUSTRY_PLAYER; break;
|
||||
default: NOT_REACHED(); break;
|
||||
}
|
||||
SetDParam(2, abs(percent));
|
||||
SetDParam(0, GetCargo(type)->name);
|
||||
SetDParam(1, ind->index);
|
||||
AddNewsItem(
|
||||
percent >= 0 ? STR_INDUSTRY_PROD_GOUP : STR_INDUSTRY_PROD_GODOWN,
|
||||
NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_TILE, nt, 0),
|
||||
ind->xy + TileDiffXY(1, 1), 0
|
||||
);
|
||||
}
|
||||
|
||||
/** Change industry production or do closure
|
||||
* @param i Industry for which changes are performed
|
||||
* @param monthly true if it's the monthly call, false if it's the random call
|
||||
|
@ -1909,7 +2038,6 @@ static void ChangeIndustryProduction(Industry *i, bool monthly)
|
|||
for (byte j = 0; j < 2 && i->produced_cargo[j] != CT_INVALID; j++){
|
||||
uint32 r = Random();
|
||||
int old_prod, new_prod, percent;
|
||||
int mag;
|
||||
|
||||
new_prod = old_prod = i->production_rate[j];
|
||||
|
||||
|
@ -1932,16 +2060,8 @@ static void ChangeIndustryProduction(Industry *i, bool monthly)
|
|||
/* Close the industry when it has the lowest possible production rate */
|
||||
if (new_prod > 1) closeit = false;
|
||||
|
||||
mag = abs(percent);
|
||||
if (mag >= 10) {
|
||||
SetDParam(2, mag);
|
||||
SetDParam(0, GetCargo(i->produced_cargo[j])->name);
|
||||
SetDParam(1, i->index);
|
||||
AddNewsItem(
|
||||
percent >= 0 ? STR_INDUSTRY_PROD_GOUP : STR_INDUSTRY_PROD_GODOWN,
|
||||
NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_TILE, NT_ECONOMY, 0),
|
||||
i->xy + TileDiffXY(1, 1), 0
|
||||
);
|
||||
if (abs(percent) >= 10) {
|
||||
ReportNewsProductionChangeIndustry(i, i->produced_cargo[j], percent);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -1989,6 +2109,19 @@ static void ChangeIndustryProduction(Industry *i, bool monthly)
|
|||
}
|
||||
|
||||
if (!suppress_message && str != STR_NULL) {
|
||||
NewsType nt;
|
||||
/* Compute news category */
|
||||
if (closeit) {
|
||||
nt = NT_OPENCLOSE;
|
||||
} else {
|
||||
switch (WhoCanServiceIndustry(i)) {
|
||||
case 0: nt = NT_INDUSTRY_NOBODY; break;
|
||||
case 1: nt = NT_INDUSTRY_OTHER; break;
|
||||
case 2: nt = NT_INDUSTRY_PLAYER; break;
|
||||
default: NOT_REACHED(); break;
|
||||
}
|
||||
}
|
||||
/* Set parameters of news string */
|
||||
if (str > STR_LAST_STRINGID) {
|
||||
SetDParam(0, STR_TOWN);
|
||||
SetDParam(1, i->town->index);
|
||||
|
@ -2000,8 +2133,9 @@ static void ChangeIndustryProduction(Industry *i, bool monthly)
|
|||
} else {
|
||||
SetDParam(0, i->index);
|
||||
}
|
||||
/* and report the news to the user */
|
||||
AddNewsItem(str,
|
||||
NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_TILE, closeit ? NT_OPENCLOSE : NT_ECONOMY, 0),
|
||||
NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_TILE, nt, 0),
|
||||
i->xy + TileDiffXY(1, 1), 0);
|
||||
}
|
||||
}
|
||||
|
@ -2084,7 +2218,7 @@ static CommandCost TerraformTile_Industry(TileIndex tile, uint32 flags, uint z_n
|
|||
uint16 res = GetIndustryTileCallback(CBID_INDUSTRY_AUTOSLOPE, 0, 0, gfx, GetIndustryByTile(tile), tile);
|
||||
if ((res == 0) || (res == CALLBACK_FAILED)) return _price.terraform;
|
||||
} else {
|
||||
// allow autoslope
|
||||
/* allow autoslope */
|
||||
return _price.terraform;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -594,6 +594,9 @@ STR_0208_ACCIDENTS_DISASTERS :{YELLOW}Acciden
|
|||
STR_0209_COMPANY_INFORMATION :{YELLOW}Company information
|
||||
STR_NEWS_OPEN_CLOSE :{YELLOW}Open / close of industries
|
||||
STR_020A_ECONOMY_CHANGES :{YELLOW}Economy changes
|
||||
STR_INDUSTRY_CHANGES_SERVED_BY_PLAYER :{YELLOW}Production changes of industries served by the player
|
||||
STR_INDUSTRY_CHANGES_SERVED_BY_OTHER :{YELLOW}Production changes of industries served by competitor(s)
|
||||
STR_OTHER_INDUSTRY_PRODUCTION_CHANGES :{YELLOW}Other industry production changes
|
||||
STR_020B_ADVICE_INFORMATION_ON_PLAYER :{YELLOW}Advice / information on player's vehicles
|
||||
STR_020C_NEW_VEHICLES :{YELLOW}New vehicles
|
||||
STR_020D_CHANGES_OF_CARGO_ACCEPTANCE :{YELLOW}Changes to cargo acceptance
|
||||
|
|
|
@ -53,6 +53,9 @@ enum NewsType {
|
|||
NT_COMPANY_INFO, ///< Company info (new companies, bankrupcy messages)
|
||||
NT_OPENCLOSE, ///< Opening and closing of industries
|
||||
NT_ECONOMY, ///< Economic changes (recession, industry up/dowm)
|
||||
NT_INDUSTRY_PLAYER, ///< Production changes of industry serviced by local player
|
||||
NT_INDUSTRY_OTHER, ///< Production changes of industry serviced by competitor(s)
|
||||
NT_INDUSTRY_NOBODY, ///< Other industry production changes
|
||||
NT_ADVICE, ///< Bits of news about vehicles of the player
|
||||
NT_NEW_VEHICLES, ///< New vehicle has become available
|
||||
NT_ACCEPTANCE, ///< A type of cargo is (no longer) accepted
|
||||
|
|
181
src/news_gui.cpp
181
src/news_gui.cpp
|
@ -341,6 +341,9 @@ static const byte _news_items_age[NT_END] = {
|
|||
60, ///< NT_COMPANY_INFO
|
||||
90, ///< NT_OPENCLOSE
|
||||
30, ///< NT_ECONOMY
|
||||
30, ///< NT_INDUSTRY_PLAYER
|
||||
30, ///< NT_INDUSTRY_OTHER
|
||||
30, ///< NT_INDUSTRY_NOBODY
|
||||
150, ///< NT_ADVICE
|
||||
30, ///< NT_NEW_VEHICLES
|
||||
90, ///< NT_ACCEPTANCE
|
||||
|
@ -394,17 +397,20 @@ static WindowDesc _news_type0_desc = {
|
|||
};
|
||||
|
||||
static const SoundFx _news_sounds[NT_END] = {
|
||||
SND_1D_APPLAUSE,
|
||||
SND_1D_APPLAUSE,
|
||||
SND_BEGIN,
|
||||
SND_BEGIN,
|
||||
SND_BEGIN,
|
||||
SND_BEGIN,
|
||||
SND_BEGIN,
|
||||
SND_1E_OOOOH,
|
||||
SND_BEGIN,
|
||||
SND_BEGIN,
|
||||
SND_BEGIN,
|
||||
SND_1D_APPLAUSE, ///< NT_ARRIVAL_PLAYER
|
||||
SND_1D_APPLAUSE, ///< NT_ARRIVAL_OTHER
|
||||
SND_BEGIN, ///< NT_ACCIDENT
|
||||
SND_BEGIN, ///< NT_COMPANY_INFO
|
||||
SND_BEGIN, ///< NT_OPENCLOSE
|
||||
SND_BEGIN, ///< NT_ECONOMY
|
||||
SND_BEGIN, ///< NT_INDUSTRY_PLAYER
|
||||
SND_BEGIN, ///< NT_INDUSTRY_OTHER
|
||||
SND_BEGIN, ///< NT_INDUSTRY_NOBODY
|
||||
SND_BEGIN, ///< NT_ADVICE
|
||||
SND_1E_OOOOH, ///< NT_NEW_VEHICLES
|
||||
SND_BEGIN, ///< NT_ACCEPTANCE
|
||||
SND_BEGIN, ///< NT_SUBSIDIES
|
||||
SND_BEGIN, ///< NT_GENERAL
|
||||
};
|
||||
|
||||
const char *_news_display_name[NT_END] = {
|
||||
|
@ -414,6 +420,9 @@ const char *_news_display_name[NT_END] = {
|
|||
"company_info",
|
||||
"openclose",
|
||||
"economy",
|
||||
"production_player",
|
||||
"production_other",
|
||||
"production_nobody",
|
||||
"advice",
|
||||
"new_vehicles",
|
||||
"acceptance",
|
||||
|
@ -771,6 +780,7 @@ void ShowMessageHistory()
|
|||
}
|
||||
|
||||
|
||||
/** News settings window widget offset constants */
|
||||
enum {
|
||||
WIDGET_NEWSOPT_BTN_SUMMARY = 4, ///< Button that adjusts at once the level for all settings
|
||||
WIDGET_NEWSOPT_DROP_SUMMARY, ///< Drop down button for same upper button
|
||||
|
@ -880,83 +890,106 @@ static void MessageOptionsWndProc(Window *w, WindowEvent *e)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The news settings window widgets
|
||||
*
|
||||
* Main part of the window is a list of news-setting lines, one for each news category.
|
||||
* Each line is constructed by an expansion of the \c NEWS_SETTINGS_LINE macro
|
||||
*/
|
||||
|
||||
/**
|
||||
* Macro to construct one news-setting line in the news-settings window.
|
||||
* One line consists of four widgets, namely
|
||||
* - A [<] button
|
||||
* - A [...] label
|
||||
* - A [>] button
|
||||
* - A text label describing the news category
|
||||
* Horizontal positions of the widgets are hard-coded, vertical start position is (\a basey + \a linenum * \c NEWS_SETTING_BASELINE_SKIP).
|
||||
* Height of one line is 12, with the text label shifted 1 pixel down.
|
||||
*
|
||||
* First line should be widget number WIDGET_NEWSOPT_START_OPTION
|
||||
*
|
||||
* @param basey: Base Y coordinate
|
||||
* @param linenum: Count, news-setting is the \a linenum-th line
|
||||
* @param text: StringID for the text label to display
|
||||
*/
|
||||
#define NEWS_SETTINGS_LINE(basey, linenum, text) \
|
||||
{ WWT_PUSHIMGBTN, RESIZE_NONE, COLOUR_YELLOW, \
|
||||
4, 12, basey + linenum * NEWS_SETTING_BASELINE_SKIP, basey + 11 + linenum * NEWS_SETTING_BASELINE_SKIP, \
|
||||
SPR_ARROW_LEFT, STR_HSCROLL_BAR_SCROLLS_LIST}, \
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, COLOUR_YELLOW, \
|
||||
13, 89, basey + linenum * NEWS_SETTING_BASELINE_SKIP, basey + 11 + linenum * NEWS_SETTING_BASELINE_SKIP, \
|
||||
STR_EMPTY, STR_NULL}, \
|
||||
{ WWT_PUSHIMGBTN, RESIZE_NONE, COLOUR_YELLOW, \
|
||||
90, 98, basey + linenum * NEWS_SETTING_BASELINE_SKIP, basey + 11 + linenum * NEWS_SETTING_BASELINE_SKIP, \
|
||||
SPR_ARROW_RIGHT, STR_HSCROLL_BAR_SCROLLS_LIST}, \
|
||||
{ WWT_TEXT, RESIZE_NONE, COLOUR_YELLOW, \
|
||||
103, 409, basey + 1 + linenum * NEWS_SETTING_BASELINE_SKIP, basey + 13 + linenum * NEWS_SETTING_BASELINE_SKIP, \
|
||||
text, STR_NULL}
|
||||
|
||||
static const int NEWS_SETTING_BASELINE_SKIP = 12; ///< Distance between two news-setting lines, should be at least 12
|
||||
|
||||
|
||||
static const Widget _message_options_widgets[] = {
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 13, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 13, 11, 409, 0, 13, STR_0204_MESSAGE_OPTIONS, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, RESIZE_NONE, 13, 0, 409, 14, 196, 0x0, STR_NULL},
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, COLOUR_BROWN, 0, 10, 0, 13,
|
||||
STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, COLOUR_BROWN, 11, 409, 0, 13,
|
||||
STR_0204_MESSAGE_OPTIONS, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, RESIZE_NONE, COLOUR_BROWN, 0, 409, 14, 64 + NT_END * NEWS_SETTING_BASELINE_SKIP,
|
||||
0x0, STR_NULL},
|
||||
|
||||
/* Text at the top of the main panel, in black */
|
||||
{ WWT_LABEL, RESIZE_NONE, 13, 0, 409, 13, 26, STR_0205_MESSAGE_TYPES, STR_NULL},
|
||||
{ WWT_LABEL, RESIZE_NONE, COLOUR_BROWN,
|
||||
0, 409, 13, 26,
|
||||
STR_0205_MESSAGE_TYPES, STR_NULL},
|
||||
|
||||
/* General drop down and sound button */
|
||||
{ WWT_PANEL, RESIZE_NONE, 3, 4, 86, 166, 177, 0x0, STR_NULL},
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 3, 87, 98, 166, 177, STR_0225, STR_NULL},
|
||||
{ WWT_TEXT, RESIZE_NONE, 3, 103, 409, 167, 179, STR_MESSAGES_ALL, STR_NULL},
|
||||
/* General drop down and sound button, widgets WIDGET_NEWSOPT_BTN_SUMMARY and WIDGET_NEWSOPT_DROP_SUMMARY */
|
||||
{ WWT_PANEL, RESIZE_NONE, COLOUR_YELLOW,
|
||||
4, 86, 34 + NT_END * NEWS_SETTING_BASELINE_SKIP, 45 + NT_END * NEWS_SETTING_BASELINE_SKIP,
|
||||
0x0, STR_NULL},
|
||||
|
||||
{ WWT_TEXTBTN_2, RESIZE_NONE, 3, 4, 98, 178, 189, STR_02DB_OFF, STR_NULL},
|
||||
{ WWT_TEXT, RESIZE_NONE, 3, 103, 409, 179, 191, STR_MESSAGE_SOUND, STR_NULL},
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, COLOUR_YELLOW,
|
||||
87, 98, 34 + NT_END * NEWS_SETTING_BASELINE_SKIP, 45 + NT_END * NEWS_SETTING_BASELINE_SKIP,
|
||||
STR_0225, STR_NULL},
|
||||
|
||||
/* Each four group is composed of the buttons [<] [..] [>] and the descriptor of the setting */
|
||||
{ WWT_PUSHIMGBTN, RESIZE_NONE, 3, 4, 12, 26, 37, SPR_ARROW_LEFT, STR_HSCROLL_BAR_SCROLLS_LIST},
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, 3, 13, 89, 26, 37, STR_EMPTY, STR_NULL},
|
||||
{ WWT_PUSHIMGBTN, RESIZE_NONE, 3, 90, 98, 26, 37, SPR_ARROW_RIGHT, STR_HSCROLL_BAR_SCROLLS_LIST},
|
||||
{ WWT_TEXT, RESIZE_NONE, 3, 103, 409, 27, 39, STR_0206_ARRIVAL_OF_FIRST_VEHICLE, STR_NULL},
|
||||
{ WWT_TEXT, RESIZE_NONE, COLOUR_YELLOW,
|
||||
103, 409, 35 + NT_END * NEWS_SETTING_BASELINE_SKIP, 47 + NT_END * NEWS_SETTING_BASELINE_SKIP,
|
||||
STR_MESSAGES_ALL, STR_NULL},
|
||||
|
||||
{ WWT_PUSHIMGBTN, RESIZE_NONE, 3, 4, 12, 38, 49, SPR_ARROW_LEFT, STR_HSCROLL_BAR_SCROLLS_LIST},
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, 3, 13, 89, 38, 49, STR_EMPTY, STR_NULL},
|
||||
{ WWT_PUSHIMGBTN, RESIZE_NONE, 3, 90, 98, 38, 49, SPR_ARROW_RIGHT, STR_HSCROLL_BAR_SCROLLS_LIST},
|
||||
{ WWT_TEXT, RESIZE_NONE, 3, 103, 409, 39, 51, STR_0207_ARRIVAL_OF_FIRST_VEHICLE, STR_NULL},
|
||||
/* Below is widget WIDGET_NEWSOPT_SOUNDTICKER */
|
||||
{ WWT_TEXTBTN_2, RESIZE_NONE, COLOUR_YELLOW,
|
||||
4, 98, 46 + NT_END * NEWS_SETTING_BASELINE_SKIP, 57 + NT_END * NEWS_SETTING_BASELINE_SKIP,
|
||||
STR_02DB_OFF, STR_NULL},
|
||||
|
||||
{ WWT_PUSHIMGBTN, RESIZE_NONE, 3, 4, 12, 50, 61, SPR_ARROW_LEFT, STR_HSCROLL_BAR_SCROLLS_LIST},
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, 3, 13, 89, 50, 61, STR_EMPTY, STR_NULL},
|
||||
{ WWT_PUSHIMGBTN, RESIZE_NONE, 3, 90, 98, 50, 61, SPR_ARROW_RIGHT, STR_HSCROLL_BAR_SCROLLS_LIST},
|
||||
{ WWT_TEXT, RESIZE_NONE, 3, 103, 409, 51, 63, STR_0208_ACCIDENTS_DISASTERS, STR_NULL},
|
||||
{ WWT_TEXT, RESIZE_NONE, COLOUR_YELLOW,
|
||||
103, 409, 47 + NT_END * NEWS_SETTING_BASELINE_SKIP, 59 + NT_END * NEWS_SETTING_BASELINE_SKIP,
|
||||
STR_MESSAGE_SOUND, STR_NULL},
|
||||
|
||||
{ WWT_PUSHIMGBTN, RESIZE_NONE, 3, 4, 12, 62, 73, SPR_ARROW_LEFT, STR_HSCROLL_BAR_SCROLLS_LIST},
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, 3, 13, 89, 62, 73, STR_EMPTY, STR_NULL},
|
||||
{ WWT_PUSHIMGBTN, RESIZE_NONE, 3, 90, 98, 62, 73, SPR_ARROW_RIGHT, STR_HSCROLL_BAR_SCROLLS_LIST},
|
||||
{ WWT_TEXT, RESIZE_NONE, 3, 103, 409, 63, 75, STR_0209_COMPANY_INFORMATION, STR_NULL},
|
||||
|
||||
{ WWT_PUSHIMGBTN, RESIZE_NONE, 3, 4, 12, 74, 85, SPR_ARROW_LEFT, STR_HSCROLL_BAR_SCROLLS_LIST},
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, 3, 13, 89, 74, 85, STR_EMPTY, STR_NULL},
|
||||
{ WWT_PUSHIMGBTN, RESIZE_NONE, 3, 90, 98, 74, 85, SPR_ARROW_RIGHT, STR_HSCROLL_BAR_SCROLLS_LIST},
|
||||
{ WWT_TEXT, RESIZE_NONE, 3, 103, 409, 75, 87, STR_NEWS_OPEN_CLOSE, STR_NULL},
|
||||
|
||||
{ WWT_PUSHIMGBTN, RESIZE_NONE, 3, 4, 12, 86, 97, SPR_ARROW_LEFT, STR_HSCROLL_BAR_SCROLLS_LIST},
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, 3, 13, 89, 86, 97, STR_EMPTY, STR_NULL},
|
||||
{ WWT_PUSHIMGBTN, RESIZE_NONE, 3, 90, 98, 86, 97, SPR_ARROW_RIGHT, STR_HSCROLL_BAR_SCROLLS_LIST},
|
||||
{ WWT_TEXT, RESIZE_NONE, 3, 103, 409, 87, 99, STR_020A_ECONOMY_CHANGES, STR_NULL},
|
||||
|
||||
{ WWT_PUSHIMGBTN, RESIZE_NONE, 3, 4, 12, 98, 109, SPR_ARROW_LEFT, STR_HSCROLL_BAR_SCROLLS_LIST},
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, 3, 13, 89, 98, 109, STR_EMPTY, STR_NULL},
|
||||
{ WWT_PUSHIMGBTN, RESIZE_NONE, 3, 90, 98, 98, 109, SPR_ARROW_RIGHT, STR_HSCROLL_BAR_SCROLLS_LIST},
|
||||
{ WWT_TEXT, RESIZE_NONE, 3, 103, 409, 99, 111, STR_020B_ADVICE_INFORMATION_ON_PLAYER, STR_NULL},
|
||||
|
||||
{ WWT_PUSHIMGBTN, RESIZE_NONE, 3, 4, 12, 110, 121, SPR_ARROW_LEFT, STR_HSCROLL_BAR_SCROLLS_LIST},
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, 3, 13, 89, 110, 121, STR_EMPTY, STR_NULL},
|
||||
{ WWT_PUSHIMGBTN, RESIZE_NONE, 3, 90, 98, 110, 121, SPR_ARROW_RIGHT, STR_HSCROLL_BAR_SCROLLS_LIST},
|
||||
{ WWT_TEXT, RESIZE_NONE, 3, 103, 409, 111, 123, STR_020C_NEW_VEHICLES, STR_NULL},
|
||||
|
||||
{ WWT_PUSHIMGBTN, RESIZE_NONE, 3, 4, 12, 122, 133, SPR_ARROW_LEFT, STR_HSCROLL_BAR_SCROLLS_LIST},
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, 3, 13, 89, 122, 133, STR_EMPTY, STR_NULL},
|
||||
{ WWT_PUSHIMGBTN, RESIZE_NONE, 3, 90, 98, 122, 133, SPR_ARROW_RIGHT, STR_HSCROLL_BAR_SCROLLS_LIST},
|
||||
{ WWT_TEXT, RESIZE_NONE, 3, 103, 409, 123, 135, STR_020D_CHANGES_OF_CARGO_ACCEPTANCE, STR_NULL},
|
||||
|
||||
{ WWT_PUSHIMGBTN, RESIZE_NONE, 3, 4, 12, 134, 145, SPR_ARROW_LEFT, STR_HSCROLL_BAR_SCROLLS_LIST},
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, 3, 13, 89, 134, 145, STR_EMPTY, STR_NULL},
|
||||
{ WWT_PUSHIMGBTN, RESIZE_NONE, 3, 90, 98, 134, 145, SPR_ARROW_RIGHT, STR_HSCROLL_BAR_SCROLLS_LIST},
|
||||
{ WWT_TEXT, RESIZE_NONE, 3, 103, 409, 135, 147, STR_020E_SUBSIDIES, STR_NULL},
|
||||
|
||||
{ WWT_PUSHIMGBTN, RESIZE_NONE, 3, 4, 12, 146, 157, SPR_ARROW_LEFT, STR_HSCROLL_BAR_SCROLLS_LIST},
|
||||
{ WWT_PUSHTXTBTN, RESIZE_NONE, 3, 13, 89, 146, 157, STR_EMPTY, STR_NULL},
|
||||
{ WWT_PUSHIMGBTN, RESIZE_NONE, 3, 90, 98, 146, 157, SPR_ARROW_RIGHT, STR_HSCROLL_BAR_SCROLLS_LIST},
|
||||
{ WWT_TEXT, RESIZE_NONE, 3, 103, 409, 147, 159, STR_020F_GENERAL_INFORMATION, STR_NULL},
|
||||
/* List of news-setting lines (4 widgets for each line).
|
||||
* First widget must be number WIDGET_NEWSOPT_START_OPTION
|
||||
*/
|
||||
NEWS_SETTINGS_LINE(26, NT_ARRIVAL_PLAYER, STR_0206_ARRIVAL_OF_FIRST_VEHICLE),
|
||||
NEWS_SETTINGS_LINE(26, NT_ARRIVAL_OTHER, STR_0207_ARRIVAL_OF_FIRST_VEHICLE),
|
||||
NEWS_SETTINGS_LINE(26, NT_ACCIDENT, STR_0208_ACCIDENTS_DISASTERS),
|
||||
NEWS_SETTINGS_LINE(26, NT_COMPANY_INFO, STR_0209_COMPANY_INFORMATION),
|
||||
NEWS_SETTINGS_LINE(26, NT_OPENCLOSE, STR_NEWS_OPEN_CLOSE),
|
||||
NEWS_SETTINGS_LINE(26, NT_ECONOMY, STR_020A_ECONOMY_CHANGES),
|
||||
NEWS_SETTINGS_LINE(26, NT_INDUSTRY_PLAYER, STR_INDUSTRY_CHANGES_SERVED_BY_PLAYER),
|
||||
NEWS_SETTINGS_LINE(26, NT_INDUSTRY_OTHER, STR_INDUSTRY_CHANGES_SERVED_BY_OTHER),
|
||||
NEWS_SETTINGS_LINE(26, NT_INDUSTRY_NOBODY, STR_OTHER_INDUSTRY_PRODUCTION_CHANGES),
|
||||
NEWS_SETTINGS_LINE(26, NT_ADVICE, STR_020B_ADVICE_INFORMATION_ON_PLAYER),
|
||||
NEWS_SETTINGS_LINE(26, NT_NEW_VEHICLES, STR_020C_NEW_VEHICLES),
|
||||
NEWS_SETTINGS_LINE(26, NT_ACCEPTANCE, STR_020D_CHANGES_OF_CARGO_ACCEPTANCE),
|
||||
NEWS_SETTINGS_LINE(26, NT_SUBSIDIES, STR_020E_SUBSIDIES),
|
||||
NEWS_SETTINGS_LINE(26, NT_GENERAL, STR_020F_GENERAL_INFORMATION),
|
||||
|
||||
{ WIDGETS_END},
|
||||
};
|
||||
|
||||
static const WindowDesc _message_options_desc = {
|
||||
270, 22, 410, 197, 410, 197,
|
||||
270, 22, 410, 65 + NT_END * NEWS_SETTING_BASELINE_SKIP,
|
||||
410, 65 + NT_END * NEWS_SETTING_BASELINE_SKIP,
|
||||
WC_GAME_OPTIONS, WC_NONE,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
|
||||
_message_options_widgets,
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "newgrf_station.h"
|
||||
#include "cargopacket.h"
|
||||
#include <list>
|
||||
#include <set>
|
||||
|
||||
struct Station;
|
||||
struct RoadStop;
|
||||
|
@ -241,6 +242,11 @@ enum CatchmentArea {
|
|||
|
||||
void ModifyStationRatingAround(TileIndex tile, PlayerID owner, int amount, uint radius);
|
||||
|
||||
/** A set of stations (\c const \c Station* ) */
|
||||
typedef std::set<Station*> StationSet;
|
||||
|
||||
StationSet FindStationsAroundIndustryTile(TileIndex tile, int w, int h);
|
||||
|
||||
void ShowStationViewWindow(StationID station);
|
||||
void UpdateAllStationVirtCoord();
|
||||
|
||||
|
|
|
@ -433,7 +433,14 @@ static void ShowRejectOrAcceptNews(const Station *st, uint num_items, CargoID *c
|
|||
AddNewsItem(msg, NEWS_FLAGS(NM_SMALL, NF_VIEWPORT | NF_TILE, NT_ACCEPTANCE, 0), st->xy, 0);
|
||||
}
|
||||
|
||||
/** Get a list of the cargo types being produced around the tile.*/
|
||||
/**
|
||||
* Get a list of the cargo types being produced around the tile (in a rectangle).
|
||||
* @param produced: Destination array of produced cargo
|
||||
* @param tile: Center of the search area
|
||||
* @param w: Width of the center
|
||||
* @param h: Height of the center
|
||||
* @param rad: Radius of the search area
|
||||
*/
|
||||
void GetProductionAroundTiles(AcceptedCargo produced, TileIndex tile,
|
||||
int w, int h, int rad)
|
||||
{
|
||||
|
@ -477,7 +484,14 @@ void GetProductionAroundTiles(AcceptedCargo produced, TileIndex tile,
|
|||
}
|
||||
}
|
||||
|
||||
/** Get a list of the cargo types that are accepted around the tile.*/
|
||||
/**
|
||||
* Get a list of the cargo types that are accepted around the tile.
|
||||
* @param accepts: Destination array of accepted cargo
|
||||
* @param tile: Center of the search area
|
||||
* @param w: Width of the center
|
||||
* @param h: Height of the center
|
||||
* @param rad: Radius of the rectangular search area
|
||||
*/
|
||||
void GetAcceptanceAroundTiles(AcceptedCargo accepts, TileIndex tile,
|
||||
int w, int h, int rad)
|
||||
{
|
||||
|
@ -2626,14 +2640,20 @@ CommandCost CmdRenameStation(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
|||
return CommandCost();
|
||||
}
|
||||
|
||||
|
||||
uint MoveGoodsToStation(TileIndex tile, int w, int h, CargoID type, uint amount)
|
||||
/**
|
||||
* Find all (non-buoy) stations around an industry tile
|
||||
*
|
||||
* @param tile: Center tile to search from
|
||||
* @param w: Width of the center
|
||||
* @param h: Height of the center
|
||||
*
|
||||
* @return: Set of found stations
|
||||
*/
|
||||
StationSet FindStationsAroundIndustryTile(TileIndex tile, int w, int h)
|
||||
{
|
||||
Station* around[8];
|
||||
StationSet station_set;
|
||||
|
||||
for (uint i = 0; i < lengthof(around); i++) around[i] = NULL;
|
||||
|
||||
int w_prod; //width and height of the "producer" of the cargo
|
||||
int w_prod; // width and height of the "producer" of the cargo
|
||||
int h_prod;
|
||||
int max_rad;
|
||||
if (_patches.modified_catchment) {
|
||||
|
@ -2656,91 +2676,103 @@ uint MoveGoodsToStation(TileIndex tile, int w, int h, CargoID type, uint amount)
|
|||
|
||||
Station *st = GetStationByTile(cur_tile);
|
||||
|
||||
for (uint i = 0; i != lengthof(around); i++) {
|
||||
if (around[i] == NULL) {
|
||||
if (!st->IsBuoy() &&
|
||||
(st->town->exclusive_counter == 0 || st->town->exclusivity == st->owner) && // check exclusive transport rights
|
||||
st->goods[type].rating != 0 && // when you've got the lowest rating you can get, it's better not to give cargo anymore
|
||||
(!_patches.selectgoods || st->goods[type].last_speed != 0) && // we are servicing the station (or cargo is dumped on all stations)
|
||||
((st->facilities & ~FACIL_BUS_STOP) != 0 || IsCargoInClass(type, CC_PASSENGERS)) && // if we have other fac. than a bus stop, or the cargo is passengers
|
||||
((st->facilities & ~FACIL_TRUCK_STOP) != 0 || !IsCargoInClass(type, CC_PASSENGERS))) { // if we have other fac. than a cargo bay or the cargo is not passengers
|
||||
if (_patches.modified_catchment) {
|
||||
/* min and max coordinates of the producer relative */
|
||||
const int x_min_prod = max_rad + 1;
|
||||
const int x_max_prod = max_rad + w_prod;
|
||||
const int y_min_prod = max_rad + 1;
|
||||
const int y_max_prod = max_rad + h_prod;
|
||||
if (st->IsBuoy()) continue; // bouys don't accept cargo
|
||||
|
||||
int rad = FindCatchmentRadius(st);
|
||||
|
||||
int x_dist = min(w_cur - x_min_prod, x_max_prod - w_cur);
|
||||
if (w_cur < x_min_prod) {
|
||||
x_dist = x_min_prod - w_cur;
|
||||
} else if (w_cur > x_max_prod) {
|
||||
x_dist = w_cur - x_max_prod;
|
||||
}
|
||||
if (_patches.modified_catchment) {
|
||||
/* min and max coordinates of the producer relative */
|
||||
const int x_min_prod = max_rad + 1;
|
||||
const int x_max_prod = max_rad + w_prod;
|
||||
const int y_min_prod = max_rad + 1;
|
||||
const int y_max_prod = max_rad + h_prod;
|
||||
|
||||
int y_dist = min(h_cur - y_min_prod, y_max_prod - h_cur);
|
||||
if (h_cur < y_min_prod) {
|
||||
y_dist = y_min_prod - h_cur;
|
||||
} else if (h_cur > y_max_prod) {
|
||||
y_dist = h_cur - y_max_prod;
|
||||
}
|
||||
int rad = FindCatchmentRadius(st);
|
||||
|
||||
if (x_dist > rad || y_dist > rad) break;
|
||||
}
|
||||
|
||||
around[i] = st;
|
||||
}
|
||||
break;
|
||||
} else if (around[i] == st) {
|
||||
break;
|
||||
int x_dist = min(w_cur - x_min_prod, x_max_prod - w_cur);
|
||||
if (w_cur < x_min_prod) {
|
||||
x_dist = x_min_prod - w_cur;
|
||||
} else if (w_cur > x_max_prod) {
|
||||
x_dist = w_cur - x_max_prod;
|
||||
}
|
||||
|
||||
if (x_dist > rad) continue;
|
||||
|
||||
int y_dist = min(h_cur - y_min_prod, y_max_prod - h_cur);
|
||||
if (h_cur < y_min_prod) {
|
||||
y_dist = y_min_prod - h_cur;
|
||||
} else if (h_cur > y_max_prod) {
|
||||
y_dist = h_cur - y_max_prod;
|
||||
}
|
||||
|
||||
if (y_dist > rad) continue;
|
||||
}
|
||||
|
||||
/* Insert the station in the set. This will fail if it has
|
||||
* already been added.
|
||||
*/
|
||||
station_set.insert(st);
|
||||
|
||||
END_TILE_LOOP(cur_tile, w, h, tile - TileDiffXY(max_rad, max_rad))
|
||||
|
||||
/* no stations around at all? */
|
||||
if (around[0] == NULL) return 0;
|
||||
return station_set;
|
||||
}
|
||||
|
||||
if (around[1] == NULL) {
|
||||
uint MoveGoodsToStation(TileIndex tile, int w, int h, CargoID type, uint amount)
|
||||
{
|
||||
Station *st1 = NULL; // Station with best rating
|
||||
Station *st2 = NULL; // Second best station
|
||||
uint best_rating1 = 0; // rating of st1
|
||||
uint best_rating2 = 0; // rating of st2
|
||||
|
||||
StationSet all_stations = FindStationsAroundIndustryTile(tile, w, h);
|
||||
for (StationSet::iterator st_iter = all_stations.begin(); st_iter != all_stations.end(); ++st_iter) {
|
||||
Station *st = *st_iter;
|
||||
|
||||
/* Is the station reserved exclusively for somebody else? */
|
||||
if (st->town->exclusive_counter > 0 && st->town->exclusivity != st->owner) continue;
|
||||
|
||||
if (st->goods[type].rating == 0) continue; // Lowest possible rating, better not to give cargo anymore
|
||||
|
||||
if (_patches.selectgoods && st->goods[type].last_speed == 0) continue; // Selectively servicing stations, and not this one
|
||||
|
||||
if (IsCargoInClass(type, CC_PASSENGERS)) {
|
||||
if (st->facilities == FACIL_TRUCK_STOP) continue; // passengers are never served by just a truck stop
|
||||
} else {
|
||||
if (st->facilities == FACIL_BUS_STOP) continue; // non-passengers are never served by just a bus stop
|
||||
}
|
||||
|
||||
/* This station can be used, add it to st1/st2 */
|
||||
if (st1 == NULL || st->goods[type].rating >= best_rating1) {
|
||||
st2 = st1; best_rating2 = best_rating1; st1 = st; best_rating1 = st->goods[type].rating;
|
||||
} else if (st2 == NULL || st->goods[type].rating >= best_rating2) {
|
||||
st2 = st; best_rating2 = st->goods[type].rating;
|
||||
}
|
||||
}
|
||||
|
||||
/* no stations around at all? */
|
||||
if (st1 == NULL) return 0;
|
||||
|
||||
if (st2 == NULL) {
|
||||
/* only one station around */
|
||||
uint moved = (amount * around[0]->goods[type].rating >> 8) + 1;
|
||||
UpdateStationWaiting(around[0], type, moved);
|
||||
uint moved = amount * best_rating1 / 256 + 1;
|
||||
UpdateStationWaiting(st1, type, moved);
|
||||
return moved;
|
||||
}
|
||||
|
||||
/* several stations around, find the two with the highest rating */
|
||||
Station *st1 = NULL;
|
||||
Station *st2 = NULL;
|
||||
uint best_rating = 0;
|
||||
uint best_rating2 = 0;
|
||||
|
||||
for (uint i = 0; i != lengthof(around) && around[i] != NULL; i++) {
|
||||
if (around[i]->goods[type].rating >= best_rating) {
|
||||
best_rating2 = best_rating;
|
||||
st2 = st1;
|
||||
|
||||
best_rating = around[i]->goods[type].rating;
|
||||
st1 = around[i];
|
||||
} else if (around[i]->goods[type].rating >= best_rating2) {
|
||||
best_rating2 = around[i]->goods[type].rating;
|
||||
st2 = around[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* several stations around, the best two (highest rating) are in st1 and st2 */
|
||||
assert(st1 != NULL);
|
||||
assert(st2 != NULL);
|
||||
assert(best_rating != 0 || best_rating2 != 0);
|
||||
assert(best_rating1 != 0 || best_rating2 != 0);
|
||||
|
||||
/* the 2nd highest one gets a penalty */
|
||||
best_rating2 >>= 1;
|
||||
|
||||
/* amount given to station 1 */
|
||||
uint t = (best_rating * (amount + 1)) / (best_rating + best_rating2);
|
||||
uint t = (best_rating1 * (amount + 1)) / (best_rating1 + best_rating2);
|
||||
|
||||
uint moved = 0;
|
||||
if (t != 0) {
|
||||
moved = t * best_rating / 256 + 1;
|
||||
moved = t * best_rating1 / 256 + 1;
|
||||
amount -= t;
|
||||
UpdateStationWaiting(st1, type, moved);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue