mirror of https://github.com/OpenTTD/OpenTTD.git
Feature: [GS] Scriptable league tables (#10001)
This commit is contained in:
parent
b9ce3de23d
commit
5e14a20b3b
|
@ -216,6 +216,12 @@ add_files(
|
||||||
landscape_cmd.h
|
landscape_cmd.h
|
||||||
landscape_type.h
|
landscape_type.h
|
||||||
language.h
|
language.h
|
||||||
|
league_base.h
|
||||||
|
league_cmd.h
|
||||||
|
league_cmd.cpp
|
||||||
|
league_gui.h
|
||||||
|
league_gui.cpp
|
||||||
|
league_type.h
|
||||||
livery.h
|
livery.h
|
||||||
main_gui.cpp
|
main_gui.cpp
|
||||||
map.cpp
|
map.cpp
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "goal_cmd.h"
|
#include "goal_cmd.h"
|
||||||
#include "group_cmd.h"
|
#include "group_cmd.h"
|
||||||
#include "industry_cmd.h"
|
#include "industry_cmd.h"
|
||||||
|
#include "league_cmd.h"
|
||||||
#include "landscape_cmd.h"
|
#include "landscape_cmd.h"
|
||||||
#include "misc_cmd.h"
|
#include "misc_cmd.h"
|
||||||
#include "news_cmd.h"
|
#include "news_cmd.h"
|
||||||
|
|
|
@ -337,6 +337,12 @@ enum Commands : uint16 {
|
||||||
|
|
||||||
CMD_OPEN_CLOSE_AIRPORT, ///< open/close an airport to incoming aircraft
|
CMD_OPEN_CLOSE_AIRPORT, ///< open/close an airport to incoming aircraft
|
||||||
|
|
||||||
|
CMD_CREATE_LEAGUE_TABLE, ///< create a new league table
|
||||||
|
CMD_CREATE_LEAGUE_TABLE_ELEMENT, ///< create a new element in a league table
|
||||||
|
CMD_UPDATE_LEAGUE_TABLE_ELEMENT_DATA, ///< update the data fields of a league table element
|
||||||
|
CMD_UPDATE_LEAGUE_TABLE_ELEMENT_SCORE, ///< update the score of a league table element
|
||||||
|
CMD_REMOVE_LEAGUE_TABLE_ELEMENT, ///< remove a league table element
|
||||||
|
|
||||||
CMD_END, ///< Must ALWAYS be on the end of this list!! (period)
|
CMD_END, ///< Must ALWAYS be on the end of this list!! (period)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
#include "window_func.h"
|
#include "window_func.h"
|
||||||
#include "date_func.h"
|
#include "date_func.h"
|
||||||
#include "gfx_func.h"
|
#include "gfx_func.h"
|
||||||
#include "sortlist_type.h"
|
|
||||||
#include "core/geometry_func.hpp"
|
#include "core/geometry_func.hpp"
|
||||||
#include "currency.h"
|
#include "currency.h"
|
||||||
#include "zoom_func.h"
|
#include "zoom_func.h"
|
||||||
|
@ -1100,190 +1099,6 @@ void ShowCargoPaymentRates()
|
||||||
AllocateWindowDescFront<PaymentRatesGraphWindow>(&_cargo_payment_rates_desc, 0);
|
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
|
|
||||||
int line_height; ///< Height of the text lines
|
|
||||||
Dimension icon; ///< Dimenion of the company icon.
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (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;
|
|
||||||
|
|
||||||
Rect ir = r.Shrink(WidgetDimensions::scaled.framerect);
|
|
||||||
int icon_y_offset = (this->line_height - this->icon.height) / 2;
|
|
||||||
int text_y_offset = (this->line_height - FONT_HEIGHT_NORMAL) / 2;
|
|
||||||
|
|
||||||
bool rtl = _current_text_dir == TD_RTL;
|
|
||||||
Rect ordinal = ir.WithWidth(this->ordinal_width, rtl);
|
|
||||||
uint icon_left = ir.Indent(rtl ? this->text_width : this->ordinal_width, rtl).left;
|
|
||||||
Rect text = ir.WithWidth(this->text_width, !rtl);
|
|
||||||
|
|
||||||
for (uint i = 0; i != this->companies.size(); i++) {
|
|
||||||
const Company *c = this->companies[i];
|
|
||||||
DrawString(ordinal.left, ordinal.right, ir.top + text_y_offset, i + STR_ORDINAL_NUMBER_1ST, i == 0 ? TC_WHITE : TC_YELLOW);
|
|
||||||
|
|
||||||
DrawCompanyIcon(c->index, icon_left, ir.top + 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, ir.top + text_y_offset, STR_COMPANY_LEAGUE_COMPANY_NAME);
|
|
||||||
ir.top += 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 += WidgetDimensions::scaled.hsep_wide; // 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this->icon = GetSpriteSize(SPR_COMPANY_ICON);
|
|
||||||
this->line_height = std::max<int>(this->icon.height + WidgetDimensions::scaled.vsep_normal, 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 + WidgetDimensions::scaled.hsep_indent * 3; // Keep some extra spacing
|
|
||||||
|
|
||||||
size->width = WidgetDimensions::scaled.framerect.Horizontal() + this->ordinal_width + this->icon.width + this->text_width + WidgetDimensions::scaled.framerect.Horizontal();
|
|
||||||
size->height = this->line_height * MAX_COMPANIES + WidgetDimensions::scaled.framerect.Vertical();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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, WidgetDimensions::unscaled.framerect.Vertical()),
|
|
||||||
};
|
|
||||||
|
|
||||||
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 */
|
/* PERFORMANCE RATING DETAIL */
|
||||||
/*****************************/
|
/*****************************/
|
||||||
|
|
|
@ -16,7 +16,6 @@ void ShowDeliveredCargoGraph();
|
||||||
void ShowPerformanceHistoryGraph();
|
void ShowPerformanceHistoryGraph();
|
||||||
void ShowCompanyValueGraph();
|
void ShowCompanyValueGraph();
|
||||||
void ShowCargoPaymentRates();
|
void ShowCargoPaymentRates();
|
||||||
void ShowCompanyLeagueTable();
|
|
||||||
void ShowPerformanceRatingDetail();
|
void ShowPerformanceRatingDetail();
|
||||||
|
|
||||||
#endif /* GRAPH_GUI_H */
|
#endif /* GRAPH_GUI_H */
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* This file is part of OpenTTD.
|
||||||
|
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||||
|
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file league_base.h %LeagueTable base class. */
|
||||||
|
|
||||||
|
#ifndef LEAGUE_BASE_H
|
||||||
|
#define LEAGUE_BASE_H
|
||||||
|
|
||||||
|
#include "company_type.h"
|
||||||
|
#include "goal_type.h"
|
||||||
|
#include "league_type.h"
|
||||||
|
#include "core/pool_type.hpp"
|
||||||
|
|
||||||
|
bool IsValidLink(Link link);
|
||||||
|
|
||||||
|
typedef Pool<LeagueTableElement, LeagueTableElementID, 64, 64000> LeagueTableElementPool;
|
||||||
|
extern LeagueTableElementPool _league_table_element_pool;
|
||||||
|
|
||||||
|
typedef Pool<LeagueTable, LeagueTableID, 4, 256> LeagueTablePool;
|
||||||
|
extern LeagueTablePool _league_table_pool;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Struct about league table elements.
|
||||||
|
* Each LeagueTable is composed of one or more elements. Elements are sorted by their rating (higher=better).
|
||||||
|
**/
|
||||||
|
struct LeagueTableElement : LeagueTableElementPool::PoolItem<&_league_table_element_pool> {
|
||||||
|
LeagueTableID table; ///< Id of the table which this element belongs to
|
||||||
|
uint64 rating; ///< Value that determines ordering of elements in the table (higher=better)
|
||||||
|
CompanyID company; ///< Company Id to show the color blob for or INVALID_COMPANY
|
||||||
|
std::string text; ///< Text of the element
|
||||||
|
std::string score; ///< String representation of the score associated with the element
|
||||||
|
Link link; ///< What opens when element is clicked
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We need an (empty) constructor so struct isn't zeroed (as C++ standard states)
|
||||||
|
*/
|
||||||
|
LeagueTableElement() { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (Empty) destructor has to be defined else operator delete might be called with nullptr parameter
|
||||||
|
*/
|
||||||
|
~LeagueTableElement() { }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** Struct about custom league tables */
|
||||||
|
struct LeagueTable : LeagueTablePool::PoolItem<&_league_table_pool> {
|
||||||
|
std::string title; ///< Title of the table
|
||||||
|
std::string header; ///< Text to show above the table
|
||||||
|
std::string footer; ///< Text to show below the table
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We need an (empty) constructor so struct isn't zeroed (as C++ standard states)
|
||||||
|
*/
|
||||||
|
LeagueTable() { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (Empty) destructor has to be defined else operator delete might be called with nullptr parameter
|
||||||
|
*/
|
||||||
|
~LeagueTable() { }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* LEAGUE_BASE_H */
|
|
@ -0,0 +1,176 @@
|
||||||
|
/*
|
||||||
|
* This file is part of OpenTTD.
|
||||||
|
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||||
|
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file league_cmd.cpp Handling of league tables. */
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "league_cmd.h"
|
||||||
|
#include "league_base.h"
|
||||||
|
#include "command_type.h"
|
||||||
|
#include "command_func.h"
|
||||||
|
#include "industry.h"
|
||||||
|
#include "story_base.h"
|
||||||
|
#include "town.h"
|
||||||
|
#include "window_func.h"
|
||||||
|
#include "core/pool_func.hpp"
|
||||||
|
|
||||||
|
#include "safeguards.h"
|
||||||
|
|
||||||
|
LeagueTableElementPool _league_table_element_pool("LeagueTableElement");
|
||||||
|
INSTANTIATE_POOL_METHODS(LeagueTableElement)
|
||||||
|
|
||||||
|
LeagueTablePool _league_table_pool("LeagueTable");
|
||||||
|
INSTANTIATE_POOL_METHODS(LeagueTable)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether a link is valid, i.e. has a valid target.
|
||||||
|
* @param link the link to check
|
||||||
|
* @return true iff the link is valid
|
||||||
|
*/
|
||||||
|
bool IsValidLink(Link link)
|
||||||
|
{
|
||||||
|
switch (link.type) {
|
||||||
|
case LT_NONE: return (link.target == 0);
|
||||||
|
case LT_TILE: return IsValidTile(link.target);
|
||||||
|
case LT_INDUSTRY: return Industry::IsValidID(link.target);
|
||||||
|
case LT_TOWN: return Town::IsValidID(link.target);
|
||||||
|
case LT_COMPANY: return Company::IsValidID(link.target);
|
||||||
|
case LT_STORY_PAGE: return StoryPage::IsValidID(link.target);
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new league table.
|
||||||
|
* @param flags type of operation
|
||||||
|
* @param title Title of the league table
|
||||||
|
* @param header Text to show above the table
|
||||||
|
* @param footer Text to show below the table
|
||||||
|
* @return the cost of this operation or an error
|
||||||
|
*/
|
||||||
|
std::tuple<CommandCost, LeagueTableID> CmdCreateLeagueTable(DoCommandFlag flags, const std::string &title, const std::string &header, const std::string &footer)
|
||||||
|
{
|
||||||
|
if (_current_company != OWNER_DEITY) return { CMD_ERROR, INVALID_LEAGUE_TABLE };
|
||||||
|
if (!LeagueTable::CanAllocateItem()) return { CMD_ERROR, INVALID_LEAGUE_TABLE };
|
||||||
|
if (title.empty()) return { CMD_ERROR, INVALID_LEAGUE_TABLE };
|
||||||
|
|
||||||
|
if (flags & DC_EXEC) {
|
||||||
|
LeagueTable *lt = new LeagueTable();
|
||||||
|
lt->title = title;
|
||||||
|
lt->header = header;
|
||||||
|
lt->footer = footer;
|
||||||
|
return { CommandCost(), lt->index };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { CommandCost(), INVALID_LEAGUE_TABLE };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new element in a league table.
|
||||||
|
* @param flags type of operation
|
||||||
|
* @param table Id of the league table this element belongs to
|
||||||
|
* @param rating Value that elements are ordered by
|
||||||
|
* @param company Company to show the color blob for or INVALID_COMPANY
|
||||||
|
* @param text Text of the element
|
||||||
|
* @param score String representation of the score associated with the element
|
||||||
|
* @param link_type Type of the referenced object
|
||||||
|
* @param link_target Id of the referenced object
|
||||||
|
* @return the cost of this operation or an error
|
||||||
|
*/
|
||||||
|
std::tuple<CommandCost, LeagueTableElementID> CmdCreateLeagueTableElement(DoCommandFlag flags, LeagueTableID table, int64 rating, CompanyID company, const std::string &text, const std::string &score, LinkType link_type, LinkTargetID link_target)
|
||||||
|
{
|
||||||
|
if (_current_company != OWNER_DEITY) return { CMD_ERROR, INVALID_LEAGUE_TABLE_ELEMENT };
|
||||||
|
if (!LeagueTableElement::CanAllocateItem()) return { CMD_ERROR, INVALID_LEAGUE_TABLE_ELEMENT };
|
||||||
|
Link link{link_type, link_target};
|
||||||
|
if (!IsValidLink(link)) return { CMD_ERROR, INVALID_LEAGUE_TABLE_ELEMENT };
|
||||||
|
if (company != INVALID_COMPANY && !Company::IsValidID(company)) return { CMD_ERROR, INVALID_LEAGUE_TABLE_ELEMENT };
|
||||||
|
|
||||||
|
if (flags & DC_EXEC) {
|
||||||
|
LeagueTableElement *lte = new LeagueTableElement();
|
||||||
|
lte->table = table;
|
||||||
|
lte->rating = rating;
|
||||||
|
lte->company = company;
|
||||||
|
lte->text = text;
|
||||||
|
lte->score = score;
|
||||||
|
lte->link = link;
|
||||||
|
InvalidateWindowData(WC_COMPANY_LEAGUE, table);
|
||||||
|
return { CommandCost(), lte->index };
|
||||||
|
}
|
||||||
|
return { CommandCost(), INVALID_LEAGUE_TABLE_ELEMENT };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the attributes of a league table element.
|
||||||
|
* @param flags type of operation
|
||||||
|
* @param element Id of the element to update
|
||||||
|
* @param company Company to show the color blob for or INVALID_COMPANY
|
||||||
|
* @param text Text of the element
|
||||||
|
* @param link_type Type of the referenced object
|
||||||
|
* @param link_target Id of the referenced object
|
||||||
|
* @return the cost of this operation or an error
|
||||||
|
*/
|
||||||
|
CommandCost CmdUpdateLeagueTableElementData(DoCommandFlag flags, LeagueTableElementID element, CompanyID company, const std::string &text, LinkType link_type, LinkTargetID link_target)
|
||||||
|
{
|
||||||
|
if (_current_company != OWNER_DEITY) return CMD_ERROR;
|
||||||
|
auto lte = LeagueTableElement::GetIfValid(element);
|
||||||
|
if (lte == nullptr) return CMD_ERROR;
|
||||||
|
if (company != INVALID_COMPANY && !Company::IsValidID(company)) return CMD_ERROR;
|
||||||
|
Link link{link_type, link_target};
|
||||||
|
if (!IsValidLink(link)) return CMD_ERROR;
|
||||||
|
|
||||||
|
if (flags & DC_EXEC) {
|
||||||
|
lte->company = company;
|
||||||
|
lte->text = text;
|
||||||
|
lte->link = link;
|
||||||
|
InvalidateWindowData(WC_COMPANY_LEAGUE, lte->table);
|
||||||
|
}
|
||||||
|
return CommandCost();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the score of a league table element.
|
||||||
|
* @param flags type of operation
|
||||||
|
* @param element Id of the element to update
|
||||||
|
* @param rating Value that elements are ordered by
|
||||||
|
* @param score String representation of the score associated with the element
|
||||||
|
* @return the cost of this operation or an error
|
||||||
|
*/
|
||||||
|
CommandCost CmdUpdateLeagueTableElementScore(DoCommandFlag flags, LeagueTableElementID element, int64 rating, const std::string &score)
|
||||||
|
{
|
||||||
|
if (_current_company != OWNER_DEITY) return CMD_ERROR;
|
||||||
|
auto lte = LeagueTableElement::GetIfValid(element);
|
||||||
|
if (lte == nullptr) return CMD_ERROR;
|
||||||
|
|
||||||
|
if (flags & DC_EXEC) {
|
||||||
|
lte->rating = rating;
|
||||||
|
lte->score = score;
|
||||||
|
InvalidateWindowData(WC_COMPANY_LEAGUE, lte->table);
|
||||||
|
}
|
||||||
|
return CommandCost();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a league table element.
|
||||||
|
* @param flags type of operation
|
||||||
|
* @param element Id of the element to update
|
||||||
|
* @return the cost of this operation or an error
|
||||||
|
*/
|
||||||
|
CommandCost CmdRemoveLeagueTableElement(DoCommandFlag flags, LeagueTableElementID element)
|
||||||
|
{
|
||||||
|
if (_current_company != OWNER_DEITY) return CMD_ERROR;
|
||||||
|
auto lte = LeagueTableElement::GetIfValid(element);
|
||||||
|
if (lte == nullptr) return CMD_ERROR;
|
||||||
|
|
||||||
|
if (flags & DC_EXEC) {
|
||||||
|
auto table = lte->table;
|
||||||
|
delete lte;
|
||||||
|
InvalidateWindowData(WC_COMPANY_LEAGUE, table);
|
||||||
|
}
|
||||||
|
return CommandCost();
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* This file is part of OpenTTD.
|
||||||
|
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||||
|
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file league_cmd.h Command definitions related to league tables. */
|
||||||
|
|
||||||
|
#ifndef LEAGUE_CMD_H
|
||||||
|
#define LEAGUE_CMD_H
|
||||||
|
|
||||||
|
#include "league_type.h"
|
||||||
|
#include "command_type.h"
|
||||||
|
#include "company_type.h"
|
||||||
|
|
||||||
|
std::tuple<CommandCost, LeagueTableID> CmdCreateLeagueTable(DoCommandFlag flags, const std::string &title, const std::string &header, const std::string &footer);
|
||||||
|
std::tuple<CommandCost, LeagueTableElementID> CmdCreateLeagueTableElement(DoCommandFlag flags, LeagueTableID table, int64 rating, CompanyID company, const std::string &text, const std::string &score, LinkType link_type, LinkTargetID link_target);
|
||||||
|
CommandCost CmdUpdateLeagueTableElementData(DoCommandFlag flags, LeagueTableElementID element, CompanyID company, const std::string &text, LinkType link_type, LinkTargetID link_target);
|
||||||
|
CommandCost CmdUpdateLeagueTableElementScore(DoCommandFlag flags, LeagueTableElementID element, int64 rating, const std::string &score);
|
||||||
|
CommandCost CmdRemoveLeagueTableElement(DoCommandFlag flags, LeagueTableElementID element);
|
||||||
|
|
||||||
|
DEF_CMD_TRAIT(CMD_CREATE_LEAGUE_TABLE, CmdCreateLeagueTable, CMD_DEITY, CMDT_OTHER_MANAGEMENT)
|
||||||
|
DEF_CMD_TRAIT(CMD_CREATE_LEAGUE_TABLE_ELEMENT, CmdCreateLeagueTableElement, CMD_DEITY | CMD_STR_CTRL, CMDT_OTHER_MANAGEMENT)
|
||||||
|
DEF_CMD_TRAIT(CMD_UPDATE_LEAGUE_TABLE_ELEMENT_DATA, CmdUpdateLeagueTableElementData, CMD_DEITY | CMD_STR_CTRL, CMDT_OTHER_MANAGEMENT)
|
||||||
|
DEF_CMD_TRAIT(CMD_UPDATE_LEAGUE_TABLE_ELEMENT_SCORE, CmdUpdateLeagueTableElementScore, CMD_DEITY | CMD_STR_CTRL, CMDT_OTHER_MANAGEMENT)
|
||||||
|
DEF_CMD_TRAIT(CMD_REMOVE_LEAGUE_TABLE_ELEMENT, CmdRemoveLeagueTableElement, CMD_DEITY, CMDT_OTHER_MANAGEMENT)
|
||||||
|
|
||||||
|
#endif /* LEAGUE_CMD_H */
|
|
@ -0,0 +1,452 @@
|
||||||
|
/*
|
||||||
|
* This file is part of OpenTTD.
|
||||||
|
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||||
|
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file league_gui.cpp GUI for league tables. */
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "league_gui.h"
|
||||||
|
|
||||||
|
#include "company_base.h"
|
||||||
|
#include "company_gui.h"
|
||||||
|
#include "gui.h"
|
||||||
|
#include "industry.h"
|
||||||
|
#include "league_base.h"
|
||||||
|
#include "sortlist_type.h"
|
||||||
|
#include "story_base.h"
|
||||||
|
#include "strings_func.h"
|
||||||
|
#include "tile_map.h"
|
||||||
|
#include "town.h"
|
||||||
|
#include "viewport_func.h"
|
||||||
|
#include "window_gui.h"
|
||||||
|
#include "widgets/league_widget.h"
|
||||||
|
#include "table/strings.h"
|
||||||
|
#include "table/sprites.h"
|
||||||
|
|
||||||
|
#include "safeguards.h"
|
||||||
|
|
||||||
|
|
||||||
|
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 PerformanceLeagueWindow : 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
|
||||||
|
int line_height; ///< Height of the text lines
|
||||||
|
Dimension icon; ///< Dimension of the company icon.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (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:
|
||||||
|
PerformanceLeagueWindow(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_PLT_BACKGROUND) return;
|
||||||
|
|
||||||
|
Rect ir = r.Shrink(WidgetDimensions::scaled.framerect);
|
||||||
|
int icon_y_offset = (this->line_height - this->icon.height) / 2;
|
||||||
|
int text_y_offset = (this->line_height - FONT_HEIGHT_NORMAL) / 2;
|
||||||
|
|
||||||
|
bool rtl = _current_text_dir == TD_RTL;
|
||||||
|
Rect ordinal = ir.WithWidth(this->ordinal_width, rtl);
|
||||||
|
uint icon_left = ir.Indent(rtl ? this->text_width : this->ordinal_width, rtl).left;
|
||||||
|
Rect text = ir.WithWidth(this->text_width, !rtl);
|
||||||
|
|
||||||
|
for (uint i = 0; i != this->companies.size(); i++) {
|
||||||
|
const Company *c = this->companies[i];
|
||||||
|
DrawString(ordinal.left, ordinal.right, ir.top + text_y_offset, i + STR_ORDINAL_NUMBER_1ST, i == 0 ? TC_WHITE : TC_YELLOW);
|
||||||
|
|
||||||
|
DrawCompanyIcon(c->index, icon_left, ir.top + 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, ir.top + text_y_offset, STR_COMPANY_LEAGUE_COMPANY_NAME);
|
||||||
|
ir.top += this->line_height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
|
||||||
|
{
|
||||||
|
if (widget != WID_PLT_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 += WidgetDimensions::scaled.hsep_wide; // 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this->icon = GetSpriteSize(SPR_COMPANY_ICON);
|
||||||
|
this->line_height = std::max<int>(this->icon.height + WidgetDimensions::scaled.vsep_normal, 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 + WidgetDimensions::scaled.hsep_indent * 3; // Keep some extra spacing
|
||||||
|
|
||||||
|
size->width = WidgetDimensions::scaled.framerect.Horizontal() + this->ordinal_width + this->icon.width + this->text_width + WidgetDimensions::scaled.hsep_wide;
|
||||||
|
size->height = this->line_height * MAX_COMPANIES + WidgetDimensions::scaled.framerect.Vertical();
|
||||||
|
}
|
||||||
|
|
||||||
|
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_performance_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_PLT_BACKGROUND), SetMinimalSize(400, 0), SetMinimalTextLines(15, WidgetDimensions::unscaled.framerect.Vertical()),
|
||||||
|
};
|
||||||
|
|
||||||
|
static WindowDesc _performance_league_desc(
|
||||||
|
WDP_AUTO, "league", 0, 0,
|
||||||
|
WC_COMPANY_LEAGUE, WC_NONE,
|
||||||
|
0,
|
||||||
|
_nested_performance_league_widgets, lengthof(_nested_performance_league_widgets)
|
||||||
|
);
|
||||||
|
|
||||||
|
void ShowPerformanceLeagueTable()
|
||||||
|
{
|
||||||
|
AllocateWindowDescFront<PerformanceLeagueWindow>(&_performance_league_desc, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void HandleLinkClick(Link link)
|
||||||
|
{
|
||||||
|
TileIndex xy;
|
||||||
|
switch (link.type) {
|
||||||
|
case LT_NONE: return;
|
||||||
|
|
||||||
|
case LT_TILE:
|
||||||
|
if (!IsValidTile(link.target)) return;
|
||||||
|
xy = link.target;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LT_INDUSTRY:
|
||||||
|
if (!Industry::IsValidID(link.target)) return;
|
||||||
|
xy = Industry::Get(link.target)->location.tile;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LT_TOWN:
|
||||||
|
if (!Town::IsValidID(link.target)) return;
|
||||||
|
xy = Town::Get(link.target)->xy;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LT_COMPANY:
|
||||||
|
ShowCompany((CompanyID)link.target);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case LT_STORY_PAGE: {
|
||||||
|
if (!StoryPage::IsValidID(link.target)) return;
|
||||||
|
CompanyID story_company = StoryPage::Get(link.target)->company;
|
||||||
|
ShowStoryBook(story_company, link.target);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_ctrl_pressed) {
|
||||||
|
ShowExtraViewportWindow(xy);
|
||||||
|
} else {
|
||||||
|
ScrollMainWindowToTile(xy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ScriptLeagueWindow : public Window {
|
||||||
|
private:
|
||||||
|
LeagueTableID table;
|
||||||
|
std::vector<std::pair<uint, const LeagueTableElement *>> rows;
|
||||||
|
uint rank_width; ///< The width of the rank ordinal
|
||||||
|
uint text_width; ///< The width of the actual text
|
||||||
|
uint score_width; ///< The width of the score text
|
||||||
|
uint header_height; ///< Height of the table header
|
||||||
|
int line_height; ///< Height of the text lines
|
||||||
|
Dimension icon_size; ///< Dimenion of the company icon.
|
||||||
|
std::string title;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rebuild the company league list
|
||||||
|
*/
|
||||||
|
void BuildTable()
|
||||||
|
{
|
||||||
|
this->rows.clear();
|
||||||
|
this->title = std::string{};
|
||||||
|
auto lt = LeagueTable::GetIfValid(this->table);
|
||||||
|
if (lt == nullptr) return;
|
||||||
|
|
||||||
|
/* We store title in the window class so we can safely reference the string later */
|
||||||
|
this->title = lt->title;
|
||||||
|
|
||||||
|
std::vector<const LeagueTableElement *> elements;
|
||||||
|
for(LeagueTableElement *lte : LeagueTableElement::Iterate()) {
|
||||||
|
if (lte->table == this->table) {
|
||||||
|
elements.push_back(lte);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::sort(elements.begin(), elements.end(), [](auto a, auto b) { return a->rating > b->rating; });
|
||||||
|
|
||||||
|
/* Calculate rank, companies with the same rating share the ranks */
|
||||||
|
uint rank = 0;
|
||||||
|
for (uint i = 0; i != elements.size(); i++) {
|
||||||
|
auto *lte = elements[i];
|
||||||
|
if (i > 0 && elements[i - 1]->rating != lte->rating) rank = i;
|
||||||
|
this->rows.emplace_back(std::make_pair(rank, lte));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
ScriptLeagueWindow(WindowDesc *desc, LeagueTableID table) : Window(desc)
|
||||||
|
{
|
||||||
|
this->table = table;
|
||||||
|
this->BuildTable();
|
||||||
|
this->InitNested(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetStringParameters(int widget) const override
|
||||||
|
{
|
||||||
|
if (widget != WID_SLT_CAPTION) return;
|
||||||
|
SetDParamStr(0, this->title);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnPaint() override
|
||||||
|
{
|
||||||
|
this->DrawWidgets();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawWidget(const Rect &r, int widget) const override
|
||||||
|
{
|
||||||
|
if (widget != WID_SLT_BACKGROUND) return;
|
||||||
|
|
||||||
|
auto lt = LeagueTable::GetIfValid(this->table);
|
||||||
|
if (lt == nullptr) return;
|
||||||
|
|
||||||
|
Rect ir = r.Shrink(WidgetDimensions::scaled.framerect);
|
||||||
|
|
||||||
|
if (!lt->header.empty()) {
|
||||||
|
SetDParamStr(0, lt->header);
|
||||||
|
ir.top = DrawStringMultiLine(ir.left, ir.right, ir.top, UINT16_MAX, STR_JUST_RAW_STRING, TC_BLACK) + WidgetDimensions::scaled.vsep_wide;
|
||||||
|
}
|
||||||
|
|
||||||
|
int icon_y_offset = (this->line_height - this->icon_size.height) / 2;
|
||||||
|
int text_y_offset = (this->line_height - FONT_HEIGHT_NORMAL) / 2;
|
||||||
|
|
||||||
|
/* Calculate positions.of the columns */
|
||||||
|
bool rtl = _current_text_dir == TD_RTL;
|
||||||
|
int spacer = WidgetDimensions::scaled.hsep_wide;
|
||||||
|
Rect rank_rect = ir.WithWidth(this->rank_width, rtl);
|
||||||
|
Rect icon_rect = ir.Indent(this->rank_width + (rtl ? 0 : spacer), rtl).WithWidth(this->icon_size.width, rtl);
|
||||||
|
Rect text_rect = ir.Indent(this->rank_width + spacer + this->icon_size.width, rtl).WithWidth(this->text_width, rtl);
|
||||||
|
Rect score_rect = ir.Indent(this->rank_width + 2 * spacer + this->icon_size.width + this->text_width, rtl).WithWidth(this->score_width, rtl);
|
||||||
|
|
||||||
|
for (auto [rank, lte] : this->rows) {
|
||||||
|
DrawString(rank_rect.left, rank_rect.right, ir.top + text_y_offset, rank + STR_ORDINAL_NUMBER_1ST, rank == 0 ? TC_WHITE : TC_YELLOW);
|
||||||
|
if (this->icon_size.width > 0 && lte->company != INVALID_COMPANY) DrawCompanyIcon(lte->company, icon_rect.left, ir.top + icon_y_offset);
|
||||||
|
SetDParamStr(0, lte->text);
|
||||||
|
DrawString(text_rect.left, text_rect.right, ir.top + text_y_offset, STR_JUST_RAW_STRING, TC_BLACK);
|
||||||
|
SetDParamStr(0, lte->score);
|
||||||
|
DrawString(score_rect.left, score_rect.right, ir.top + text_y_offset, STR_JUST_RAW_STRING, TC_BLACK, SA_RIGHT);
|
||||||
|
ir.top += this->line_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lt->footer.empty()) {
|
||||||
|
ir.top += WidgetDimensions::scaled.vsep_wide;
|
||||||
|
SetDParamStr(0, lt->footer);
|
||||||
|
ir.top = DrawStringMultiLine(ir.left, ir.right, ir.top, UINT16_MAX, STR_JUST_RAW_STRING, TC_BLACK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
|
||||||
|
{
|
||||||
|
if (widget != WID_SLT_BACKGROUND) return;
|
||||||
|
|
||||||
|
auto lt = LeagueTable::GetIfValid(this->table);
|
||||||
|
if (lt == nullptr) return;
|
||||||
|
|
||||||
|
this->icon_size = GetSpriteSize(SPR_COMPANY_ICON);
|
||||||
|
this->line_height = std::max<int>(this->icon_size.height + WidgetDimensions::scaled.fullbevel.Vertical(), FONT_HEIGHT_NORMAL);
|
||||||
|
|
||||||
|
/* Calculate maximum width of every column */
|
||||||
|
this->rank_width = this->text_width = this->score_width = 0;
|
||||||
|
bool show_icon_column = false;
|
||||||
|
for (auto [rank, lte] : this->rows) {
|
||||||
|
this->rank_width = std::max(this->rank_width, GetStringBoundingBox(STR_ORDINAL_NUMBER_1ST + rank).width);
|
||||||
|
SetDParamStr(0, lte->text);
|
||||||
|
this->text_width = std::max(this->text_width, GetStringBoundingBox(STR_JUST_RAW_STRING).width);
|
||||||
|
SetDParamStr(0, lte->score);
|
||||||
|
this->score_width = std::max(this->score_width, GetStringBoundingBox(STR_JUST_RAW_STRING).width);
|
||||||
|
if (lte->company != INVALID_COMPANY) show_icon_column = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!show_icon_column) this->icon_size.width = 0;
|
||||||
|
else this->icon_size.width += WidgetDimensions::scaled.hsep_wide;
|
||||||
|
|
||||||
|
size->width = this->rank_width + this->icon_size.width + this->text_width + this->score_width + WidgetDimensions::scaled.framerect.Horizontal() + WidgetDimensions::scaled.hsep_wide * 2;
|
||||||
|
size->height = this->line_height * std::max<uint>(3u, (unsigned)this->rows.size()) + WidgetDimensions::scaled.framerect.Vertical();
|
||||||
|
|
||||||
|
if (!lt->header.empty()) {
|
||||||
|
SetDParamStr(0, lt->header);
|
||||||
|
this->header_height = GetStringHeight(STR_JUST_RAW_STRING, size->width - WidgetDimensions::scaled.framerect.Horizontal()) + WidgetDimensions::scaled.vsep_wide;
|
||||||
|
size->height += header_height;
|
||||||
|
} else this->header_height = 0;
|
||||||
|
|
||||||
|
if (!lt->footer.empty()) {
|
||||||
|
SetDParamStr(0, lt->footer);
|
||||||
|
size->height += GetStringHeight(STR_JUST_RAW_STRING, size->width - WidgetDimensions::scaled.framerect.Horizontal()) + WidgetDimensions::scaled.vsep_wide;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnClick(Point pt, int widget, int click_count) override
|
||||||
|
{
|
||||||
|
if (widget != WID_SLT_BACKGROUND) return;
|
||||||
|
|
||||||
|
auto *wid = this->GetWidget<NWidgetResizeBase>(WID_SLT_BACKGROUND);
|
||||||
|
int index = (pt.y - WidgetDimensions::scaled.framerect.top - wid->pos_y - this->header_height) / this->line_height;
|
||||||
|
if (index >= 0 && (uint)index < this->rows.size()) {
|
||||||
|
auto lte = this->rows[index].second;
|
||||||
|
HandleLinkClick(lte->link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
{
|
||||||
|
this->BuildTable();
|
||||||
|
this->ReInit();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const NWidgetPart _nested_script_league_widgets[] = {
|
||||||
|
NWidget(NWID_HORIZONTAL),
|
||||||
|
NWidget(WWT_CLOSEBOX, COLOUR_BROWN),
|
||||||
|
NWidget(WWT_CAPTION, COLOUR_BROWN, WID_SLT_CAPTION), SetDataTip(STR_BLACK_RAW_STRING, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||||
|
NWidget(WWT_SHADEBOX, COLOUR_BROWN),
|
||||||
|
NWidget(WWT_STICKYBOX, COLOUR_BROWN),
|
||||||
|
EndContainer(),
|
||||||
|
NWidget(WWT_PANEL, COLOUR_BROWN, WID_SLT_BACKGROUND), SetMinimalSize(400, 0), SetMinimalTextLines(15, WidgetDimensions::scaled.framerect.Vertical()),
|
||||||
|
};
|
||||||
|
|
||||||
|
static WindowDesc _script_league_desc(
|
||||||
|
WDP_AUTO, "league", 0, 0,
|
||||||
|
WC_COMPANY_LEAGUE, WC_NONE,
|
||||||
|
0,
|
||||||
|
_nested_script_league_widgets, lengthof(_nested_script_league_widgets)
|
||||||
|
);
|
||||||
|
|
||||||
|
void ShowScriptLeagueTable(LeagueTableID table)
|
||||||
|
{
|
||||||
|
if (!LeagueTable::IsValidID(table)) return;
|
||||||
|
AllocateWindowDescFront<ScriptLeagueWindow>(&_script_league_desc, table);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowFirstLeagueTable()
|
||||||
|
{
|
||||||
|
auto it = LeagueTable::Iterate();
|
||||||
|
if (!it.empty()) {
|
||||||
|
ShowScriptLeagueTable((*it.begin())->index);
|
||||||
|
} else {
|
||||||
|
ShowPerformanceLeagueTable();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
* This file is part of OpenTTD.
|
||||||
|
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||||
|
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file league_gui.h League table GUI functions. */
|
||||||
|
|
||||||
|
#ifndef LEAGUE_GUI_H
|
||||||
|
#define LEAGUE_GUI_H
|
||||||
|
|
||||||
|
#include "league_type.h"
|
||||||
|
|
||||||
|
void ShowPerformanceLeagueTable();
|
||||||
|
void ShowScriptLeagueTable(LeagueTableID table);
|
||||||
|
void ShowFirstLeagueTable();
|
||||||
|
|
||||||
|
#endif /* LEAGUE_GUI_H */
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* This file is part of OpenTTD.
|
||||||
|
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||||
|
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file league_type.h basic types related to league tables */
|
||||||
|
|
||||||
|
#ifndef LEAGUE_TYPE_H
|
||||||
|
#define LEAGUE_TYPE_H
|
||||||
|
|
||||||
|
/** Types of the possible link targets. */
|
||||||
|
enum LinkType : byte {
|
||||||
|
LT_NONE = 0, ///< No link
|
||||||
|
LT_TILE = 1, ///< Link a tile
|
||||||
|
LT_INDUSTRY = 2, ///< Link an industry
|
||||||
|
LT_TOWN = 3, ///< Link a town
|
||||||
|
LT_COMPANY = 4, ///< Link a company
|
||||||
|
LT_STORY_PAGE = 5, ///< Link a story page
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef uint32 LinkTargetID; ///< Contains either tile, industry ID, town ID, story page ID or company ID
|
||||||
|
|
||||||
|
struct Link {
|
||||||
|
LinkType type;
|
||||||
|
LinkTargetID target;
|
||||||
|
Link(LinkType type, LinkTargetID target): type{type}, target{target} {}
|
||||||
|
Link(): Link(LT_NONE, 0) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef uint8 LeagueTableID; ///< ID of a league table
|
||||||
|
struct LeagueTable;
|
||||||
|
static const LeagueTableID INVALID_LEAGUE_TABLE = 0xFF; ///< Invalid/unknown index of LeagueTable
|
||||||
|
|
||||||
|
typedef uint16 LeagueTableElementID; ///< ID of a league table element
|
||||||
|
struct LeagueTableElement;
|
||||||
|
static const LeagueTableElementID INVALID_LEAGUE_TABLE_ELEMENT = 0xFFFF; ///< Invalid/unknown index of LeagueTableElement
|
||||||
|
|
||||||
|
#endif /* LEAGUE_TYPE_H */
|
|
@ -26,6 +26,7 @@
|
||||||
#include "../group_cmd.h"
|
#include "../group_cmd.h"
|
||||||
#include "../industry_cmd.h"
|
#include "../industry_cmd.h"
|
||||||
#include "../landscape_cmd.h"
|
#include "../landscape_cmd.h"
|
||||||
|
#include "../league_cmd.h"
|
||||||
#include "../misc_cmd.h"
|
#include "../misc_cmd.h"
|
||||||
#include "../news_cmd.h"
|
#include "../news_cmd.h"
|
||||||
#include "../object_cmd.h"
|
#include "../object_cmd.h"
|
||||||
|
|
|
@ -19,6 +19,7 @@ add_files(
|
||||||
group_sl.cpp
|
group_sl.cpp
|
||||||
industry_sl.cpp
|
industry_sl.cpp
|
||||||
labelmaps_sl.cpp
|
labelmaps_sl.cpp
|
||||||
|
league_sl.cpp
|
||||||
linkgraph_sl.cpp
|
linkgraph_sl.cpp
|
||||||
map_sl.cpp
|
map_sl.cpp
|
||||||
misc_sl.cpp
|
misc_sl.cpp
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
/*
|
||||||
|
* This file is part of OpenTTD.
|
||||||
|
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||||
|
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file league_sl.cpp Code handling saving and loading of league tables */
|
||||||
|
|
||||||
|
#include "../stdafx.h"
|
||||||
|
|
||||||
|
#include "saveload.h"
|
||||||
|
|
||||||
|
#include "../league_base.h"
|
||||||
|
|
||||||
|
#include "../safeguards.h"
|
||||||
|
|
||||||
|
static const SaveLoad _league_table_elements_desc[] = {
|
||||||
|
SLE_VAR(LeagueTableElement, table, SLE_UINT8),
|
||||||
|
SLE_VAR(LeagueTableElement, rating, SLE_UINT64),
|
||||||
|
SLE_VAR(LeagueTableElement, company, SLE_UINT8),
|
||||||
|
SLE_SSTR(LeagueTableElement, text, SLE_STR | SLF_ALLOW_CONTROL),
|
||||||
|
SLE_SSTR(LeagueTableElement, score, SLE_STR | SLF_ALLOW_CONTROL),
|
||||||
|
SLE_VAR(LeagueTableElement, link.type, SLE_UINT8),
|
||||||
|
SLE_VAR(LeagueTableElement, link.target, SLE_UINT32),
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LEAEChunkHandler : ChunkHandler {
|
||||||
|
LEAEChunkHandler() : ChunkHandler('LEAE', CH_TABLE) {}
|
||||||
|
|
||||||
|
void Save() const override
|
||||||
|
{
|
||||||
|
SlTableHeader(_league_table_elements_desc);
|
||||||
|
|
||||||
|
for (LeagueTableElement *lte : LeagueTableElement::Iterate()) {
|
||||||
|
SlSetArrayIndex(lte->index);
|
||||||
|
SlObject(lte, _league_table_elements_desc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Load() const override
|
||||||
|
{
|
||||||
|
const std::vector<SaveLoad> slt = SlTableHeader(_league_table_elements_desc);
|
||||||
|
|
||||||
|
int index;
|
||||||
|
while ((index = SlIterateArray()) != -1) {
|
||||||
|
LeagueTableElement *lte = new (index) LeagueTableElement();
|
||||||
|
SlObject(lte, slt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const SaveLoad _league_tables_desc[] = {
|
||||||
|
SLE_SSTR(LeagueTable, title, SLE_STR | SLF_ALLOW_CONTROL),
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LEATChunkHandler : ChunkHandler {
|
||||||
|
LEATChunkHandler() : ChunkHandler('LEAT', CH_TABLE) {}
|
||||||
|
|
||||||
|
void Save() const override
|
||||||
|
{
|
||||||
|
SlTableHeader(_league_tables_desc);
|
||||||
|
|
||||||
|
for (LeagueTable *lt : LeagueTable::Iterate()) {
|
||||||
|
SlSetArrayIndex(lt->index);
|
||||||
|
SlObject(lt, _league_tables_desc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Load() const override
|
||||||
|
{
|
||||||
|
const std::vector<SaveLoad> slt = SlTableHeader(_league_tables_desc);
|
||||||
|
|
||||||
|
int index;
|
||||||
|
while ((index = SlIterateArray()) != -1) {
|
||||||
|
LeagueTable *lt = new (index) LeagueTable();
|
||||||
|
SlObject(lt, slt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const LEAEChunkHandler LEAE;
|
||||||
|
static const LEATChunkHandler LEAT;
|
||||||
|
static const ChunkHandlerRef league_chunk_handlers[] = {
|
||||||
|
LEAE,
|
||||||
|
LEAT,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const ChunkHandlerTable _league_chunk_handlers(league_chunk_handlers);
|
|
@ -240,6 +240,7 @@ static const std::vector<ChunkHandlerRef> &ChunkHandlers()
|
||||||
extern const ChunkHandlerTable _cargomonitor_chunk_handlers;
|
extern const ChunkHandlerTable _cargomonitor_chunk_handlers;
|
||||||
extern const ChunkHandlerTable _goal_chunk_handlers;
|
extern const ChunkHandlerTable _goal_chunk_handlers;
|
||||||
extern const ChunkHandlerTable _story_page_chunk_handlers;
|
extern const ChunkHandlerTable _story_page_chunk_handlers;
|
||||||
|
extern const ChunkHandlerTable _league_chunk_handlers;
|
||||||
extern const ChunkHandlerTable _ai_chunk_handlers;
|
extern const ChunkHandlerTable _ai_chunk_handlers;
|
||||||
extern const ChunkHandlerTable _game_chunk_handlers;
|
extern const ChunkHandlerTable _game_chunk_handlers;
|
||||||
extern const ChunkHandlerTable _animated_tile_chunk_handlers;
|
extern const ChunkHandlerTable _animated_tile_chunk_handlers;
|
||||||
|
@ -271,6 +272,7 @@ static const std::vector<ChunkHandlerRef> &ChunkHandlers()
|
||||||
_cargomonitor_chunk_handlers,
|
_cargomonitor_chunk_handlers,
|
||||||
_goal_chunk_handlers,
|
_goal_chunk_handlers,
|
||||||
_story_page_chunk_handlers,
|
_story_page_chunk_handlers,
|
||||||
|
_league_chunk_handlers,
|
||||||
_engine_chunk_handlers,
|
_engine_chunk_handlers,
|
||||||
_town_chunk_handlers,
|
_town_chunk_handlers,
|
||||||
_sign_chunk_handlers,
|
_sign_chunk_handlers,
|
||||||
|
|
|
@ -177,6 +177,7 @@ add_files(
|
||||||
script_industrytypelist.hpp
|
script_industrytypelist.hpp
|
||||||
script_info_docs.hpp
|
script_info_docs.hpp
|
||||||
script_infrastructure.hpp
|
script_infrastructure.hpp
|
||||||
|
script_league.hpp
|
||||||
script_list.hpp
|
script_list.hpp
|
||||||
script_log.hpp
|
script_log.hpp
|
||||||
script_map.hpp
|
script_map.hpp
|
||||||
|
@ -247,6 +248,7 @@ add_files(
|
||||||
script_industrytype.cpp
|
script_industrytype.cpp
|
||||||
script_industrytypelist.cpp
|
script_industrytypelist.cpp
|
||||||
script_infrastructure.cpp
|
script_infrastructure.cpp
|
||||||
|
script_league.cpp
|
||||||
script_list.cpp
|
script_list.cpp
|
||||||
script_log.cpp
|
script_log.cpp
|
||||||
script_map.cpp
|
script_map.cpp
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
* \li GSCargo::GetWeight
|
* \li GSCargo::GetWeight
|
||||||
* \li GSIndustryType::ResolveNewGRFID
|
* \li GSIndustryType::ResolveNewGRFID
|
||||||
* \li GSObjectType::ResolveNewGRFID
|
* \li GSObjectType::ResolveNewGRFID
|
||||||
|
* \li GSLeagueTable
|
||||||
*
|
*
|
||||||
* Other changes:
|
* Other changes:
|
||||||
* \li GSRoad::HasRoadType now correctly checks RoadType against RoadType
|
* \li GSRoad::HasRoadType now correctly checks RoadType against RoadType
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
/*
|
||||||
|
* This file is part of OpenTTD.
|
||||||
|
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||||
|
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file script_league.cpp Implementation of ScriptLeagueTable. */
|
||||||
|
|
||||||
|
#include "../../stdafx.h"
|
||||||
|
|
||||||
|
#include "script_league.hpp"
|
||||||
|
|
||||||
|
#include "../script_instance.hpp"
|
||||||
|
#include "script_error.hpp"
|
||||||
|
#include "../../league_base.h"
|
||||||
|
#include "../../league_cmd.h"
|
||||||
|
|
||||||
|
#include "../../safeguards.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* static */ bool ScriptLeagueTable::IsValidLeagueTable(LeagueTableID table_id)
|
||||||
|
{
|
||||||
|
return ::LeagueTable::IsValidID(table_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ ScriptLeagueTable::LeagueTableID ScriptLeagueTable::New(Text *title, Text *header, Text *footer)
|
||||||
|
{
|
||||||
|
CCountedPtr<Text> title_counter(title);
|
||||||
|
CCountedPtr<Text> header_counter(header);
|
||||||
|
CCountedPtr<Text> footer_counter(footer);
|
||||||
|
|
||||||
|
EnforcePrecondition(LEAGUE_TABLE_INVALID, ScriptObject::GetCompany() == OWNER_DEITY);
|
||||||
|
EnforcePrecondition(LEAGUE_TABLE_INVALID, title != nullptr);
|
||||||
|
const char *encoded_title = title->GetEncodedText();
|
||||||
|
EnforcePreconditionEncodedText(LEAGUE_TABLE_INVALID, encoded_title);
|
||||||
|
|
||||||
|
auto encoded_header = (header != nullptr ? std::string{ header->GetEncodedText() } : std::string{});
|
||||||
|
auto encoded_footer = (footer != nullptr ? std::string{ footer->GetEncodedText() } : std::string{});
|
||||||
|
|
||||||
|
if (!ScriptObject::Command<CMD_CREATE_LEAGUE_TABLE>::Do(&ScriptInstance::DoCommandReturnLeagueTableID, encoded_title, encoded_header, encoded_footer)) return LEAGUE_TABLE_INVALID;
|
||||||
|
|
||||||
|
/* In case of test-mode, we return LeagueTableID 0 */
|
||||||
|
return (ScriptLeagueTable::LeagueTableID)0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ bool ScriptLeagueTable::IsValidLeagueTableElement(LeagueTableElementID element_id)
|
||||||
|
{
|
||||||
|
return ::LeagueTableElement::IsValidID(element_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ ScriptLeagueTable::LeagueTableElementID ScriptLeagueTable::NewElement(ScriptLeagueTable::LeagueTableID table, int64 rating, ScriptCompany::CompanyID company, Text *text, Text *score, LinkType link_type, uint32 link_target)
|
||||||
|
{
|
||||||
|
CCountedPtr<Text> text_counter(text);
|
||||||
|
CCountedPtr<Text> score_counter(score);
|
||||||
|
|
||||||
|
EnforcePrecondition(LEAGUE_TABLE_ELEMENT_INVALID, ScriptObject::GetCompany() == OWNER_DEITY);
|
||||||
|
|
||||||
|
EnforcePrecondition(LEAGUE_TABLE_ELEMENT_INVALID, IsValidLeagueTable(table));
|
||||||
|
|
||||||
|
EnforcePrecondition(LEAGUE_TABLE_ELEMENT_INVALID, company == ScriptCompany::COMPANY_INVALID || ScriptCompany::ResolveCompanyID(company) != ScriptCompany::COMPANY_INVALID);
|
||||||
|
CompanyID c = (::CompanyID)company;
|
||||||
|
if (company == ScriptCompany::COMPANY_INVALID) c = INVALID_COMPANY;
|
||||||
|
|
||||||
|
EnforcePrecondition(LEAGUE_TABLE_ELEMENT_INVALID, text != nullptr);
|
||||||
|
const char *encoded_text_ptr = text->GetEncodedText();
|
||||||
|
EnforcePreconditionEncodedText(LEAGUE_TABLE_ELEMENT_INVALID, encoded_text_ptr);
|
||||||
|
std::string encoded_text = encoded_text_ptr; // save into string so GetEncodedText can reuse the internal buffer
|
||||||
|
|
||||||
|
EnforcePrecondition(LEAGUE_TABLE_ELEMENT_INVALID, score != nullptr);
|
||||||
|
const char *encoded_score = score->GetEncodedText();
|
||||||
|
EnforcePreconditionEncodedText(LEAGUE_TABLE_ELEMENT_INVALID, encoded_score);
|
||||||
|
|
||||||
|
EnforcePrecondition(LEAGUE_TABLE_ELEMENT_INVALID, IsValidLink(Link((::LinkType)link_type, link_target)));
|
||||||
|
|
||||||
|
if (!ScriptObject::Command<CMD_CREATE_LEAGUE_TABLE_ELEMENT>::Do(&ScriptInstance::DoCommandReturnLeagueTableElementID, table, rating, c, encoded_text, encoded_score, (::LinkType)link_type, (::LinkTargetID)link_target)) return LEAGUE_TABLE_ELEMENT_INVALID;
|
||||||
|
|
||||||
|
/* In case of test-mode, we return LeagueTableElementID 0 */
|
||||||
|
return (ScriptLeagueTable::LeagueTableElementID)0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ bool ScriptLeagueTable::UpdateElementData(LeagueTableElementID element, ScriptCompany::CompanyID company, Text *text, LinkType link_type, LinkTargetID link_target)
|
||||||
|
{
|
||||||
|
CCountedPtr<Text> text_counter(text);
|
||||||
|
|
||||||
|
EnforcePrecondition(false, ScriptObject::GetCompany() == OWNER_DEITY);
|
||||||
|
EnforcePrecondition(false, IsValidLeagueTableElement(element));
|
||||||
|
|
||||||
|
EnforcePrecondition(false, company == ScriptCompany::COMPANY_INVALID || ScriptCompany::ResolveCompanyID(company) != ScriptCompany::COMPANY_INVALID);
|
||||||
|
CompanyID c = (::CompanyID)company;
|
||||||
|
if (company == ScriptCompany::COMPANY_INVALID) c = INVALID_COMPANY;
|
||||||
|
|
||||||
|
EnforcePrecondition(false, text != nullptr);
|
||||||
|
const char *encoded_text = text->GetEncodedText();
|
||||||
|
EnforcePreconditionEncodedText(false, encoded_text);
|
||||||
|
|
||||||
|
EnforcePrecondition(false, IsValidLink(Link((::LinkType)link_type, link_target)));
|
||||||
|
|
||||||
|
return ScriptObject::Command<CMD_UPDATE_LEAGUE_TABLE_ELEMENT_DATA>::Do(element, c, encoded_text, (::LinkType)link_type, (::LinkTargetID)link_target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ bool ScriptLeagueTable::UpdateElementScore(LeagueTableElementID element, int64 rating, Text *score)
|
||||||
|
{
|
||||||
|
CCountedPtr<Text> score_counter(score);
|
||||||
|
|
||||||
|
EnforcePrecondition(false, ScriptObject::GetCompany() == OWNER_DEITY);
|
||||||
|
EnforcePrecondition(false, IsValidLeagueTableElement(element));
|
||||||
|
|
||||||
|
EnforcePrecondition(false, score != nullptr);
|
||||||
|
const char *encoded_score = score->GetEncodedText();
|
||||||
|
EnforcePreconditionEncodedText(false, encoded_score);
|
||||||
|
|
||||||
|
return ScriptObject::Command<CMD_UPDATE_LEAGUE_TABLE_ELEMENT_SCORE>::Do(element, rating, encoded_score);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ bool ScriptLeagueTable::RemoveElement(LeagueTableElementID element)
|
||||||
|
{
|
||||||
|
EnforcePrecondition(false, ScriptObject::GetCompany() == OWNER_DEITY);
|
||||||
|
EnforcePrecondition(false, IsValidLeagueTableElement(element));
|
||||||
|
|
||||||
|
return ScriptObject::Command<CMD_REMOVE_LEAGUE_TABLE_ELEMENT>::Do(element);
|
||||||
|
}
|
|
@ -0,0 +1,134 @@
|
||||||
|
/*
|
||||||
|
* This file is part of OpenTTD.
|
||||||
|
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||||
|
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file script_league.hpp Everything to manipulate league tables. */
|
||||||
|
|
||||||
|
#ifndef SCRIPT_LEAGUE_HPP
|
||||||
|
#define SCRIPT_LEAGUE_HPP
|
||||||
|
|
||||||
|
#include "script_company.hpp"
|
||||||
|
#include "script_text.hpp"
|
||||||
|
#include "../../league_type.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class that handles league table related functions.
|
||||||
|
*
|
||||||
|
* To create a league table:
|
||||||
|
* 1. Create the league table
|
||||||
|
* 2. Create league table elements that will be shown in the table in the order of their rating (higher=better).
|
||||||
|
*
|
||||||
|
* @api game
|
||||||
|
*/
|
||||||
|
class ScriptLeagueTable : public ScriptObject {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* The league table IDs.
|
||||||
|
*/
|
||||||
|
enum LeagueTableID {
|
||||||
|
LEAGUE_TABLE_INVALID = ::INVALID_LEAGUE_TABLE, ///< An invalid league table id.
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The league table element IDs.
|
||||||
|
*/
|
||||||
|
enum LeagueTableElementID {
|
||||||
|
LEAGUE_TABLE_ELEMENT_INVALID = ::INVALID_LEAGUE_TABLE_ELEMENT, ///< An invalid league table element id.
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of a link.
|
||||||
|
*/
|
||||||
|
enum LinkType : byte {
|
||||||
|
LINK_NONE = ::LT_NONE, ///< No link
|
||||||
|
LINK_TILE = ::LT_TILE, ///< Link a tile
|
||||||
|
LINK_INDUSTRY = ::LT_INDUSTRY, ///< Link an industry
|
||||||
|
LINK_TOWN = ::LT_TOWN, ///< Link a town
|
||||||
|
LINK_COMPANY = ::LT_COMPANY, ///< Link a company
|
||||||
|
LINK_STORY_PAGE = ::LT_STORY_PAGE, ///< Link a story page
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether this is a valid league table ID.
|
||||||
|
* @param table_id The LeagueTableID to check.
|
||||||
|
* @return true iff this league table is valid.
|
||||||
|
*/
|
||||||
|
static bool IsValidLeagueTable(LeagueTableID table_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether this is a valid league table element ID.
|
||||||
|
* @param element_id The LeagueTableElementID to check.
|
||||||
|
* @return true iff this league table element is valid.
|
||||||
|
*/
|
||||||
|
static bool IsValidLeagueTableElement(LeagueTableElementID element_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new league table.
|
||||||
|
* @param title League table title (can be either a raw string, or ScriptText object).
|
||||||
|
* @return The new LeagueTableID, or LEAGUE_TABLE_INVALID if it failed.
|
||||||
|
* @pre No ScriptCompanyMode may be in scope.
|
||||||
|
* @pre title != nullptr && len(title) != 0.
|
||||||
|
*/
|
||||||
|
static LeagueTableID New(Text *title, Text *header, Text *footer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new league table element.
|
||||||
|
* @param table Id of the league table this element belongs to.
|
||||||
|
* @param rating Value that elements are ordered by.
|
||||||
|
* @param company Company to show the color blob for or INVALID_COMPANY.
|
||||||
|
* @param text Text of the element (can be either a raw string, or ScriptText object).
|
||||||
|
* @param score String representation of the score associated with the element (can be either a raw string, or ScriptText object).
|
||||||
|
* @param link_type Type of the referenced object.
|
||||||
|
* @param link_target Id of the referenced object.
|
||||||
|
* @return The new LeagueTableElementID, or LEAGUE_TABLE_ELEMENT_INVALID if it failed.
|
||||||
|
* @pre No ScriptCompanyMode may be in scope.
|
||||||
|
* @pre IsValidLeagueTable(table).
|
||||||
|
* @pre text != nullptr && len(text) != 0.
|
||||||
|
* @pre score != nullptr && len(score) != 0.
|
||||||
|
* @pre IsValidLink(Link(link_type, link_target)).
|
||||||
|
*/
|
||||||
|
static LeagueTableElementID NewElement(LeagueTableID table, int64 rating, ScriptCompany::CompanyID company, Text *text, Text *score, LinkType link_type, LinkTargetID link_target);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the attributes of a league table element.
|
||||||
|
* @param element Id of the element to update
|
||||||
|
* @param company Company to show the color blob for or INVALID_COMPANY.
|
||||||
|
* @param text Text of the element (can be either a raw string, or ScriptText object).
|
||||||
|
* @param link_type Type of the referenced object.
|
||||||
|
* @param link_target Id of the referenced object.
|
||||||
|
* @return True if the action succeeded.
|
||||||
|
* @pre No ScriptCompanyMode may be in scope.
|
||||||
|
* @pre IsValidLeagueTableElement(element).
|
||||||
|
* @pre text != nullptr && len(text) != 0.
|
||||||
|
* @pre IsValidLink(Link(link_type, link_target)).
|
||||||
|
*/
|
||||||
|
static bool UpdateElementData(LeagueTableElementID element, ScriptCompany::CompanyID company, Text *text, LinkType link_type, LinkTargetID link_target);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new league table element.
|
||||||
|
* @param element Id of the element to update
|
||||||
|
* @param rating Value that elements are ordered by.
|
||||||
|
* @param score String representation of the score associated with the element (can be either a raw string, or ScriptText object).
|
||||||
|
* @return True if the action succeeded.
|
||||||
|
* @pre No ScriptCompanyMode may be in scope.
|
||||||
|
* @pre IsValidLeagueTableElement(element).
|
||||||
|
* @pre score != nullptr && len(score) != 0.
|
||||||
|
*/
|
||||||
|
static bool UpdateElementScore(LeagueTableElementID element, int64 rating, Text *score);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a league table element.
|
||||||
|
* @param element Id of the element to update
|
||||||
|
* @return True if the action succeeded.
|
||||||
|
* @pre No ScriptCompanyMode may be in scope.
|
||||||
|
* @pre IsValidLeagueTableElement(element).
|
||||||
|
*/
|
||||||
|
static bool RemoveElement(LeagueTableElementID element);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* SCRIPT_LEAGUE_HPP */
|
|
@ -26,6 +26,7 @@
|
||||||
#include "../company_base.h"
|
#include "../company_base.h"
|
||||||
#include "../company_func.h"
|
#include "../company_func.h"
|
||||||
#include "../fileio_func.h"
|
#include "../fileio_func.h"
|
||||||
|
#include "../league_type.h"
|
||||||
#include "../misc/endian_buffer.hpp"
|
#include "../misc/endian_buffer.hpp"
|
||||||
|
|
||||||
#include "../safeguards.h"
|
#include "../safeguards.h"
|
||||||
|
@ -298,6 +299,17 @@ void ScriptInstance::CollectGarbage()
|
||||||
instance->engine->InsertResult(EndianBufferReader::ToValue<StoryPageElementID>(ScriptObject::GetLastCommandResData()));
|
instance->engine->InsertResult(EndianBufferReader::ToValue<StoryPageElementID>(ScriptObject::GetLastCommandResData()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */ void ScriptInstance::DoCommandReturnLeagueTableElementID(ScriptInstance *instance)
|
||||||
|
{
|
||||||
|
instance->engine->InsertResult(EndianBufferReader::ToValue<LeagueTableElementID>(ScriptObject::GetLastCommandResData()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ void ScriptInstance::DoCommandReturnLeagueTableID(ScriptInstance *instance)
|
||||||
|
{
|
||||||
|
instance->engine->InsertResult(EndianBufferReader::ToValue<LeagueTableID>(ScriptObject::GetLastCommandResData()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ScriptStorage *ScriptInstance::GetStorage()
|
ScriptStorage *ScriptInstance::GetStorage()
|
||||||
{
|
{
|
||||||
return this->storage;
|
return this->storage;
|
||||||
|
|
|
@ -115,6 +115,16 @@ public:
|
||||||
*/
|
*/
|
||||||
static void DoCommandReturnStoryPageElementID(ScriptInstance *instance);
|
static void DoCommandReturnStoryPageElementID(ScriptInstance *instance);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a LeagueTableID reply for a DoCommand.
|
||||||
|
*/
|
||||||
|
static void DoCommandReturnLeagueTableID(ScriptInstance *instance);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a LeagueTableElementID reply for a DoCommand.
|
||||||
|
*/
|
||||||
|
static void DoCommandReturnLeagueTableElementID(ScriptInstance *instance);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the controller attached to the instance.
|
* Get the controller attached to the instance.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -51,6 +51,8 @@
|
||||||
#include "guitimer_func.h"
|
#include "guitimer_func.h"
|
||||||
#include "screenshot_gui.h"
|
#include "screenshot_gui.h"
|
||||||
#include "misc_cmd.h"
|
#include "misc_cmd.h"
|
||||||
|
#include "league_gui.h"
|
||||||
|
#include "league_base.h"
|
||||||
|
|
||||||
#include "widgets/toolbar_widget.h"
|
#include "widgets/toolbar_widget.h"
|
||||||
|
|
||||||
|
@ -250,7 +252,6 @@ static void PopupMainCompanyToolbMenu(Window *w, int widget, int grey = 0)
|
||||||
PopupMainToolbMenu(w, widget, std::move(list), _local_company == COMPANY_SPECTATOR ? (widget == WID_TN_COMPANIES ? CTMN_CLIENT_LIST : CTMN_SPECTATOR) : (int)_local_company);
|
PopupMainToolbMenu(w, widget, std::move(list), _local_company == COMPANY_SPECTATOR ? (widget == WID_TN_COMPANIES ? CTMN_CLIENT_LIST : CTMN_SPECTATOR) : (int)_local_company);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static ToolbarMode _toolbar_mode;
|
static ToolbarMode _toolbar_mode;
|
||||||
|
|
||||||
static CallBackFunction SelectSignTool()
|
static CallBackFunction SelectSignTool()
|
||||||
|
@ -672,59 +673,95 @@ static CallBackFunction MenuClickGoal(int index)
|
||||||
return CBF_NONE;
|
return CBF_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- Graphs button menu --- */
|
/* --- Graphs and League Table button menu --- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum for the League Toolbar's and Graph Toolbar's related buttons.
|
||||||
|
* Use continuous numbering as League Toolbar can be combined into the Graph Toolbar.
|
||||||
|
*/
|
||||||
|
static const int GRMN_OPERATING_PROFIT_GRAPH = -1; ///< Show operating profit graph
|
||||||
|
static const int GRMN_INCOME_GRAPH = -2; ///< Show income graph
|
||||||
|
static const int GRMN_DELIVERED_CARGO_GRAPH = -3; ///< Show delivered cargo graph
|
||||||
|
static const int GRMN_PERFORMANCE_HISTORY_GRAPH = -4; ///< Show performance history graph
|
||||||
|
static const int GRMN_COMPANY_VALUE_GRAPH = -5; ///< Show company value graph
|
||||||
|
static const int GRMN_CARGO_PAYMENT_RATES = -6; ///< Show cargo payment rates graph
|
||||||
|
static const int LTMN_PERFORMANCE_LEAGUE = -7; ///< Show default league table
|
||||||
|
static const int LTMN_PERFORMANCE_RATING = -8; ///< Show detailed performance rating
|
||||||
|
static const int LTMN_HIGHSCORE = -9; ///< Show highscrore table
|
||||||
|
|
||||||
|
static void AddDropDownLeagueTableOptions(DropDownList &list) {
|
||||||
|
if (LeagueTable::GetNumItems() > 0) {
|
||||||
|
for (LeagueTable *lt : LeagueTable::Iterate()) {
|
||||||
|
list.emplace_back(new DropDownListCharStringItem(lt->title, lt->index, false));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
list.emplace_back(new DropDownListStringItem(STR_GRAPH_MENU_COMPANY_LEAGUE_TABLE, LTMN_PERFORMANCE_LEAGUE, false));
|
||||||
|
list.emplace_back(new DropDownListStringItem(STR_GRAPH_MENU_DETAILED_PERFORMANCE_RATING, LTMN_PERFORMANCE_RATING, false));
|
||||||
|
if (!_networking) {
|
||||||
|
list.emplace_back(new DropDownListStringItem(STR_GRAPH_MENU_HIGHSCORE, LTMN_HIGHSCORE, false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static CallBackFunction ToolbarGraphsClick(Window *w)
|
static CallBackFunction ToolbarGraphsClick(Window *w)
|
||||||
{
|
{
|
||||||
PopupMainToolbMenu(w, WID_TN_GRAPHS, STR_GRAPH_MENU_OPERATING_PROFIT_GRAPH, (_toolbar_mode == TB_NORMAL) ? 6 : 8);
|
DropDownList list;
|
||||||
|
|
||||||
|
list.emplace_back(new DropDownListStringItem(STR_GRAPH_MENU_OPERATING_PROFIT_GRAPH, GRMN_OPERATING_PROFIT_GRAPH, false));
|
||||||
|
list.emplace_back(new DropDownListStringItem(STR_GRAPH_MENU_INCOME_GRAPH, GRMN_INCOME_GRAPH, false));
|
||||||
|
list.emplace_back(new DropDownListStringItem(STR_GRAPH_MENU_DELIVERED_CARGO_GRAPH, GRMN_DELIVERED_CARGO_GRAPH, false));
|
||||||
|
list.emplace_back(new DropDownListStringItem(STR_GRAPH_MENU_PERFORMANCE_HISTORY_GRAPH, GRMN_PERFORMANCE_HISTORY_GRAPH, false));
|
||||||
|
list.emplace_back(new DropDownListStringItem(STR_GRAPH_MENU_COMPANY_VALUE_GRAPH, GRMN_COMPANY_VALUE_GRAPH, false));
|
||||||
|
list.emplace_back(new DropDownListStringItem(STR_GRAPH_MENU_CARGO_PAYMENT_RATES, GRMN_CARGO_PAYMENT_RATES, false));
|
||||||
|
|
||||||
|
if (_toolbar_mode != TB_NORMAL) AddDropDownLeagueTableOptions(list);
|
||||||
|
|
||||||
|
ShowDropDownList(w, std::move(list), 0, WID_TN_GRAPHS, 140, true, true);
|
||||||
|
if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
|
||||||
|
|
||||||
|
return CBF_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CallBackFunction ToolbarLeagueClick(Window *w)
|
||||||
|
{
|
||||||
|
DropDownList list;
|
||||||
|
|
||||||
|
AddDropDownLeagueTableOptions(list);
|
||||||
|
|
||||||
|
ShowDropDownList(w, std::move(list), 0, WID_TN_LEAGUE, 140, true, true);
|
||||||
|
if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
|
||||||
|
|
||||||
return CBF_NONE;
|
return CBF_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle click on the entry in the Graphs menu.
|
* Handle click on the entry in the Graphs or CompanyLeague.
|
||||||
*
|
*
|
||||||
* @param index Graph to show.
|
* @param index Graph to show.
|
||||||
* @return #CBF_NONE
|
* @return #CBF_NONE
|
||||||
*/
|
*/
|
||||||
static CallBackFunction MenuClickGraphs(int index)
|
static CallBackFunction MenuClickGraphsOrLeague(int index)
|
||||||
{
|
{
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case 0: ShowOperatingProfitGraph(); break;
|
case GRMN_OPERATING_PROFIT_GRAPH: ShowOperatingProfitGraph(); break;
|
||||||
case 1: ShowIncomeGraph(); break;
|
case GRMN_INCOME_GRAPH: ShowIncomeGraph(); break;
|
||||||
case 2: ShowDeliveredCargoGraph(); break;
|
case GRMN_DELIVERED_CARGO_GRAPH: ShowDeliveredCargoGraph(); break;
|
||||||
case 3: ShowPerformanceHistoryGraph(); break;
|
case GRMN_PERFORMANCE_HISTORY_GRAPH: ShowPerformanceHistoryGraph(); break;
|
||||||
case 4: ShowCompanyValueGraph(); break;
|
case GRMN_COMPANY_VALUE_GRAPH: ShowCompanyValueGraph(); break;
|
||||||
case 5: ShowCargoPaymentRates(); break;
|
case GRMN_CARGO_PAYMENT_RATES: ShowCargoPaymentRates(); break;
|
||||||
/* functions for combined graphs/league button */
|
case LTMN_PERFORMANCE_LEAGUE: ShowPerformanceLeagueTable(); break;
|
||||||
case 6: ShowCompanyLeagueTable(); break;
|
case LTMN_PERFORMANCE_RATING: ShowPerformanceRatingDetail(); break;
|
||||||
case 7: ShowPerformanceRatingDetail(); break;
|
case LTMN_HIGHSCORE: ShowHighscoreTable(); break;
|
||||||
|
default: {
|
||||||
|
if (LeagueTable::IsValidID(index)) {
|
||||||
|
ShowScriptLeagueTable((LeagueTableID)index);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return CBF_NONE;
|
return CBF_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- League button menu --- */
|
|
||||||
|
|
||||||
static CallBackFunction ToolbarLeagueClick(Window *w)
|
|
||||||
{
|
|
||||||
PopupMainToolbMenu(w, WID_TN_LEAGUE, STR_GRAPH_MENU_COMPANY_LEAGUE_TABLE, _networking ? 2 : 3);
|
|
||||||
return CBF_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle click on the entry in the CompanyLeague menu.
|
|
||||||
*
|
|
||||||
* @param index Menu entry number.
|
|
||||||
* @return #CBF_NONE
|
|
||||||
*/
|
|
||||||
static CallBackFunction MenuClickLeague(int index)
|
|
||||||
{
|
|
||||||
switch (index) {
|
|
||||||
case 0: ShowCompanyLeagueTable(); break;
|
|
||||||
case 1: ShowPerformanceRatingDetail(); break;
|
|
||||||
case 2: ShowHighscoreTable(); break;
|
|
||||||
}
|
|
||||||
return CBF_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* --- Industries button menu --- */
|
/* --- Industries button menu --- */
|
||||||
|
|
||||||
|
@ -1299,8 +1336,8 @@ static MenuClickedProc * const _menu_clicked_procs[] = {
|
||||||
MenuClickCompany, // 9
|
MenuClickCompany, // 9
|
||||||
MenuClickStory, // 10
|
MenuClickStory, // 10
|
||||||
MenuClickGoal, // 11
|
MenuClickGoal, // 11
|
||||||
MenuClickGraphs, // 12
|
MenuClickGraphsOrLeague, // 12
|
||||||
MenuClickLeague, // 13
|
MenuClickGraphsOrLeague, // 13
|
||||||
MenuClickIndustry, // 14
|
MenuClickIndustry, // 14
|
||||||
MenuClickShowTrains, // 15
|
MenuClickShowTrains, // 15
|
||||||
MenuClickShowRoad, // 16
|
MenuClickShowRoad, // 16
|
||||||
|
@ -2020,7 +2057,7 @@ struct MainToolbarWindow : Window {
|
||||||
case MTHK_STORY: ShowStoryBook(_local_company); break;
|
case MTHK_STORY: ShowStoryBook(_local_company); break;
|
||||||
case MTHK_GOAL: ShowGoalsList(_local_company); break;
|
case MTHK_GOAL: ShowGoalsList(_local_company); break;
|
||||||
case MTHK_GRAPHS: ShowOperatingProfitGraph(); break;
|
case MTHK_GRAPHS: ShowOperatingProfitGraph(); break;
|
||||||
case MTHK_LEAGUE: ShowCompanyLeagueTable(); break;
|
case MTHK_LEAGUE: ShowFirstLeagueTable(); break;
|
||||||
case MTHK_INDUSTRIES: ShowBuildIndustryWindow(); break;
|
case MTHK_INDUSTRIES: ShowBuildIndustryWindow(); break;
|
||||||
case MTHK_TRAIN_LIST: ShowVehicleListWindow(_local_company, VEH_TRAIN); break;
|
case MTHK_TRAIN_LIST: ShowVehicleListWindow(_local_company, VEH_TRAIN); break;
|
||||||
case MTHK_ROADVEH_LIST: ShowVehicleListWindow(_local_company, VEH_ROAD); break;
|
case MTHK_ROADVEH_LIST: ShowVehicleListWindow(_local_company, VEH_ROAD); break;
|
||||||
|
|
|
@ -27,6 +27,7 @@ add_files(
|
||||||
highscore_widget.h
|
highscore_widget.h
|
||||||
industry_widget.h
|
industry_widget.h
|
||||||
intro_widget.h
|
intro_widget.h
|
||||||
|
league_widget.h
|
||||||
link_graph_legend_widget.h
|
link_graph_legend_widget.h
|
||||||
main_widget.h
|
main_widget.h
|
||||||
misc_widget.h
|
misc_widget.h
|
||||||
|
|
|
@ -51,11 +51,6 @@ enum CargoPaymentRatesWidgets {
|
||||||
WID_CPR_MATRIX_SCROLLBAR,///< Cargo list scrollbar.
|
WID_CPR_MATRIX_SCROLLBAR,///< Cargo list scrollbar.
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Widget of the #CompanyLeagueWindow class. */
|
|
||||||
enum CompanyLeagueWidgets {
|
|
||||||
WID_CL_BACKGROUND, ///< Background of the window.
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Widget of the #PerformanceRatingDetailWindow class. */
|
/** Widget of the #PerformanceRatingDetailWindow class. */
|
||||||
enum PerformanceRatingDetailsWidgets {
|
enum PerformanceRatingDetailsWidgets {
|
||||||
WID_PRD_SCORE_FIRST, ///< First entry in the score list.
|
WID_PRD_SCORE_FIRST, ///< First entry in the score list.
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* This file is part of OpenTTD.
|
||||||
|
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||||
|
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file league_widget.h Types related to the graph widgets. */
|
||||||
|
|
||||||
|
#ifndef WIDGETS_LEAGUE_WIDGET_H
|
||||||
|
#define WIDGETS_LEAGUE_WIDGET_H
|
||||||
|
|
||||||
|
/** Widget of the #PerformanceLeagueWindow class. */
|
||||||
|
enum PerformanceLeagueWidgets {
|
||||||
|
WID_PLT_BACKGROUND, ///< Background of the window.
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Widget of the #ScriptLeagueWindow class. */
|
||||||
|
enum ScriptLeagueWidgets {
|
||||||
|
WID_SLT_CAPTION, ///< Caption of the window.
|
||||||
|
WID_SLT_BACKGROUND, ///< Background of the window.
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* WIDGETS_LEAGUE_WIDGET_H */
|
Loading…
Reference in New Issue