Feature: [GS] Scriptable league tables (#10001)
(cherry picked from commit 5e14a20b3b
)
This commit is contained in:
@@ -18,7 +18,6 @@
|
||||
#include "window_func.h"
|
||||
#include "date_func.h"
|
||||
#include "gfx_func.h"
|
||||
#include "sortlist_type.h"
|
||||
#include "core/geometry_func.hpp"
|
||||
#include "currency.h"
|
||||
#include "zoom_func.h"
|
||||
@@ -1160,192 +1159,6 @@ void ShowCargoPaymentRates()
|
||||
AllocateWindowDescFront<PaymentRatesGraphWindow>(&_cargo_payment_rates_desc, 0);
|
||||
}
|
||||
|
||||
/************************/
|
||||
/* COMPANY LEAGUE TABLE */
|
||||
/************************/
|
||||
|
||||
static const StringID _performance_titles[] = {
|
||||
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_ENGINEER,
|
||||
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_ENGINEER,
|
||||
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_TRAFFIC_MANAGER,
|
||||
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_TRAFFIC_MANAGER,
|
||||
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_TRANSPORT_COORDINATOR,
|
||||
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_TRANSPORT_COORDINATOR,
|
||||
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_ROUTE_SUPERVISOR,
|
||||
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_ROUTE_SUPERVISOR,
|
||||
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_DIRECTOR,
|
||||
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_DIRECTOR,
|
||||
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_CHIEF_EXECUTIVE,
|
||||
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_CHIEF_EXECUTIVE,
|
||||
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_CHAIRMAN,
|
||||
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_CHAIRMAN,
|
||||
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_PRESIDENT,
|
||||
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_TYCOON,
|
||||
};
|
||||
|
||||
static inline StringID GetPerformanceTitleFromValue(uint value)
|
||||
{
|
||||
return _performance_titles[std::min(value, 1000u) >> 6];
|
||||
}
|
||||
|
||||
class CompanyLeagueWindow : public Window {
|
||||
private:
|
||||
GUIList<const Company*> companies;
|
||||
uint ordinal_width; ///< The width of the ordinal number
|
||||
uint text_width; ///< The width of the actual text
|
||||
uint icon_width; ///< The width of the company icon
|
||||
int line_height; ///< Height of the text lines
|
||||
|
||||
/**
|
||||
* (Re)Build the company league list
|
||||
*/
|
||||
void BuildCompanyList()
|
||||
{
|
||||
if (!this->companies.NeedRebuild()) return;
|
||||
|
||||
this->companies.clear();
|
||||
|
||||
for (const Company *c : Company::Iterate()) {
|
||||
this->companies.push_back(c);
|
||||
}
|
||||
|
||||
this->companies.shrink_to_fit();
|
||||
this->companies.RebuildDone();
|
||||
}
|
||||
|
||||
/** Sort the company league by performance history */
|
||||
static bool PerformanceSorter(const Company * const &c1, const Company * const &c2)
|
||||
{
|
||||
return c2->old_economy[0].performance_history < c1->old_economy[0].performance_history;
|
||||
}
|
||||
|
||||
public:
|
||||
CompanyLeagueWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc)
|
||||
{
|
||||
this->InitNested(window_number);
|
||||
this->companies.ForceRebuild();
|
||||
this->companies.NeedResort();
|
||||
}
|
||||
|
||||
void OnPaint() override
|
||||
{
|
||||
this->BuildCompanyList();
|
||||
this->companies.Sort(&PerformanceSorter);
|
||||
|
||||
this->DrawWidgets();
|
||||
}
|
||||
|
||||
void DrawWidget(const Rect &r, int widget) const override
|
||||
{
|
||||
if (widget != WID_CL_BACKGROUND) return;
|
||||
|
||||
int icon_y_offset = 1 + (FONT_HEIGHT_NORMAL - this->line_height) / 2;
|
||||
uint y = r.top + WD_FRAMERECT_TOP - icon_y_offset;
|
||||
|
||||
bool rtl = _current_text_dir == TD_RTL;
|
||||
uint ordinal_left = rtl ? r.right - WD_FRAMERECT_LEFT - this->ordinal_width : r.left + WD_FRAMERECT_LEFT;
|
||||
uint ordinal_right = rtl ? r.right - WD_FRAMERECT_LEFT : r.left + WD_FRAMERECT_LEFT + this->ordinal_width;
|
||||
uint icon_left = r.left + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT + (rtl ? this->text_width : this->ordinal_width);
|
||||
uint text_left = rtl ? r.left + WD_FRAMERECT_LEFT : r.right - WD_FRAMERECT_LEFT - this->text_width;
|
||||
uint text_right = rtl ? r.left + WD_FRAMERECT_LEFT + this->text_width : r.right - WD_FRAMERECT_LEFT;
|
||||
|
||||
for (uint i = 0; i != this->companies.size(); i++) {
|
||||
const Company *c = this->companies[i];
|
||||
DrawString(ordinal_left, ordinal_right, y, i + STR_ORDINAL_NUMBER_1ST, i == 0 ? TC_WHITE : TC_YELLOW);
|
||||
|
||||
DrawCompanyIcon(c->index, icon_left, y + icon_y_offset);
|
||||
|
||||
SetDParam(0, c->index);
|
||||
SetDParam(1, c->index);
|
||||
SetDParam(2, GetPerformanceTitleFromValue(c->old_economy[0].performance_history));
|
||||
DrawString(text_left, text_right, y, STR_COMPANY_LEAGUE_COMPANY_NAME);
|
||||
y += this->line_height;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
|
||||
{
|
||||
if (widget != WID_CL_BACKGROUND) return;
|
||||
|
||||
this->ordinal_width = 0;
|
||||
for (uint i = 0; i < MAX_COMPANIES; i++) {
|
||||
this->ordinal_width = std::max(this->ordinal_width, GetStringBoundingBox(STR_ORDINAL_NUMBER_1ST + i).width);
|
||||
}
|
||||
this->ordinal_width += 5; // Keep some extra spacing
|
||||
|
||||
uint widest_width = 0;
|
||||
uint widest_title = 0;
|
||||
for (uint i = 0; i < lengthof(_performance_titles); i++) {
|
||||
uint width = GetStringBoundingBox(_performance_titles[i]).width;
|
||||
if (width > widest_width) {
|
||||
widest_title = i;
|
||||
widest_width = width;
|
||||
}
|
||||
}
|
||||
|
||||
Dimension d = GetSpriteSize(SPR_COMPANY_ICON);
|
||||
this->icon_width = d.width + 2;
|
||||
this->line_height = std::max<int>(d.height + 2, FONT_HEIGHT_NORMAL);
|
||||
|
||||
for (const Company *c : Company::Iterate()) {
|
||||
SetDParam(0, c->index);
|
||||
SetDParam(1, c->index);
|
||||
SetDParam(2, _performance_titles[widest_title]);
|
||||
widest_width = std::max(widest_width, GetStringBoundingBox(STR_COMPANY_LEAGUE_COMPANY_NAME).width);
|
||||
}
|
||||
|
||||
this->text_width = widest_width + 30; // Keep some extra spacing
|
||||
|
||||
size->width = WD_FRAMERECT_LEFT + this->ordinal_width + WD_FRAMERECT_RIGHT + this->icon_width + WD_FRAMERECT_LEFT + this->text_width + WD_FRAMERECT_RIGHT;
|
||||
size->height = WD_FRAMERECT_TOP + this->line_height * MAX_COMPANIES + WD_FRAMERECT_BOTTOM;
|
||||
}
|
||||
|
||||
|
||||
void OnGameTick() override
|
||||
{
|
||||
if (this->companies.NeedResort()) {
|
||||
this->SetDirty();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Some data on this window has become invalid.
|
||||
* @param data Information about the changed data.
|
||||
* @param gui_scope Whether the call is done from GUI scope. You may not do everything when not in GUI scope. See #InvalidateWindowData() for details.
|
||||
*/
|
||||
void OnInvalidateData(int data = 0, bool gui_scope = true) override
|
||||
{
|
||||
if (data == 0) {
|
||||
/* This needs to be done in command-scope to enforce rebuilding before resorting invalid data */
|
||||
this->companies.ForceRebuild();
|
||||
} else {
|
||||
this->companies.ForceResort();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const NWidgetPart _nested_company_league_widgets[] = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_BROWN),
|
||||
NWidget(WWT_CAPTION, COLOUR_BROWN), SetDataTip(STR_COMPANY_LEAGUE_TABLE_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||
NWidget(WWT_SHADEBOX, COLOUR_BROWN),
|
||||
NWidget(WWT_STICKYBOX, COLOUR_BROWN),
|
||||
EndContainer(),
|
||||
NWidget(WWT_PANEL, COLOUR_BROWN, WID_CL_BACKGROUND), SetMinimalSize(400, 0), SetMinimalTextLines(15, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM),
|
||||
};
|
||||
|
||||
static WindowDesc _company_league_desc(
|
||||
WDP_AUTO, "league", 0, 0,
|
||||
WC_COMPANY_LEAGUE, WC_NONE,
|
||||
0,
|
||||
_nested_company_league_widgets, lengthof(_nested_company_league_widgets)
|
||||
);
|
||||
|
||||
void ShowCompanyLeagueTable()
|
||||
{
|
||||
AllocateWindowDescFront<CompanyLeagueWindow>(&_company_league_desc, 0);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
/* PERFORMANCE RATING DETAIL */
|
||||
/*****************************/
|
||||
|
Reference in New Issue
Block a user