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_type.h
|
||||
language.h
|
||||
league_base.h
|
||||
league_cmd.h
|
||||
league_cmd.cpp
|
||||
league_gui.h
|
||||
league_gui.cpp
|
||||
league_type.h
|
||||
livery.h
|
||||
main_gui.cpp
|
||||
map.cpp
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "goal_cmd.h"
|
||||
#include "group_cmd.h"
|
||||
#include "industry_cmd.h"
|
||||
#include "league_cmd.h"
|
||||
#include "landscape_cmd.h"
|
||||
#include "misc_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_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)
|
||||
};
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
@ -1100,190 +1099,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
|
||||
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 */
|
||||
/*****************************/
|
||||
|
|
|
@ -16,7 +16,6 @@ void ShowDeliveredCargoGraph();
|
|||
void ShowPerformanceHistoryGraph();
|
||||
void ShowCompanyValueGraph();
|
||||
void ShowCargoPaymentRates();
|
||||
void ShowCompanyLeagueTable();
|
||||
void ShowPerformanceRatingDetail();
|
||||
|
||||
#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 "../industry_cmd.h"
|
||||
#include "../landscape_cmd.h"
|
||||
#include "../league_cmd.h"
|
||||
#include "../misc_cmd.h"
|
||||
#include "../news_cmd.h"
|
||||
#include "../object_cmd.h"
|
||||
|
|
|
@ -19,6 +19,7 @@ add_files(
|
|||
group_sl.cpp
|
||||
industry_sl.cpp
|
||||
labelmaps_sl.cpp
|
||||
league_sl.cpp
|
||||
linkgraph_sl.cpp
|
||||
map_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 _goal_chunk_handlers;
|
||||
extern const ChunkHandlerTable _story_page_chunk_handlers;
|
||||
extern const ChunkHandlerTable _league_chunk_handlers;
|
||||
extern const ChunkHandlerTable _ai_chunk_handlers;
|
||||
extern const ChunkHandlerTable _game_chunk_handlers;
|
||||
extern const ChunkHandlerTable _animated_tile_chunk_handlers;
|
||||
|
@ -271,6 +272,7 @@ static const std::vector<ChunkHandlerRef> &ChunkHandlers()
|
|||
_cargomonitor_chunk_handlers,
|
||||
_goal_chunk_handlers,
|
||||
_story_page_chunk_handlers,
|
||||
_league_chunk_handlers,
|
||||
_engine_chunk_handlers,
|
||||
_town_chunk_handlers,
|
||||
_sign_chunk_handlers,
|
||||
|
|
|
@ -177,6 +177,7 @@ add_files(
|
|||
script_industrytypelist.hpp
|
||||
script_info_docs.hpp
|
||||
script_infrastructure.hpp
|
||||
script_league.hpp
|
||||
script_list.hpp
|
||||
script_log.hpp
|
||||
script_map.hpp
|
||||
|
@ -247,6 +248,7 @@ add_files(
|
|||
script_industrytype.cpp
|
||||
script_industrytypelist.cpp
|
||||
script_infrastructure.cpp
|
||||
script_league.cpp
|
||||
script_list.cpp
|
||||
script_log.cpp
|
||||
script_map.cpp
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
* \li GSCargo::GetWeight
|
||||
* \li GSIndustryType::ResolveNewGRFID
|
||||
* \li GSObjectType::ResolveNewGRFID
|
||||
* \li GSLeagueTable
|
||||
*
|
||||
* Other changes:
|
||||
* \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_func.h"
|
||||
#include "../fileio_func.h"
|
||||
#include "../league_type.h"
|
||||
#include "../misc/endian_buffer.hpp"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
@ -298,6 +299,17 @@ void ScriptInstance::CollectGarbage()
|
|||
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()
|
||||
{
|
||||
return this->storage;
|
||||
|
|
|
@ -115,6 +115,16 @@ public:
|
|||
*/
|
||||
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.
|
||||
*/
|
||||
|
|
|
@ -51,6 +51,8 @@
|
|||
#include "guitimer_func.h"
|
||||
#include "screenshot_gui.h"
|
||||
#include "misc_cmd.h"
|
||||
#include "league_gui.h"
|
||||
#include "league_base.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);
|
||||
}
|
||||
|
||||
|
||||
static ToolbarMode _toolbar_mode;
|
||||
|
||||
static CallBackFunction SelectSignTool()
|
||||
|
@ -672,59 +673,95 @@ static CallBackFunction MenuClickGoal(int index)
|
|||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle click on the entry in the Graphs menu.
|
||||
* Handle click on the entry in the Graphs or CompanyLeague.
|
||||
*
|
||||
* @param index Graph to show.
|
||||
* @return #CBF_NONE
|
||||
*/
|
||||
static CallBackFunction MenuClickGraphs(int index)
|
||||
static CallBackFunction MenuClickGraphsOrLeague(int index)
|
||||
{
|
||||
switch (index) {
|
||||
case 0: ShowOperatingProfitGraph(); break;
|
||||
case 1: ShowIncomeGraph(); break;
|
||||
case 2: ShowDeliveredCargoGraph(); break;
|
||||
case 3: ShowPerformanceHistoryGraph(); break;
|
||||
case 4: ShowCompanyValueGraph(); break;
|
||||
case 5: ShowCargoPaymentRates(); break;
|
||||
/* functions for combined graphs/league button */
|
||||
case 6: ShowCompanyLeagueTable(); break;
|
||||
case 7: ShowPerformanceRatingDetail(); break;
|
||||
case GRMN_OPERATING_PROFIT_GRAPH: ShowOperatingProfitGraph(); break;
|
||||
case GRMN_INCOME_GRAPH: ShowIncomeGraph(); break;
|
||||
case GRMN_DELIVERED_CARGO_GRAPH: ShowDeliveredCargoGraph(); break;
|
||||
case GRMN_PERFORMANCE_HISTORY_GRAPH: ShowPerformanceHistoryGraph(); break;
|
||||
case GRMN_COMPANY_VALUE_GRAPH: ShowCompanyValueGraph(); break;
|
||||
case GRMN_CARGO_PAYMENT_RATES: ShowCargoPaymentRates(); break;
|
||||
case LTMN_PERFORMANCE_LEAGUE: ShowPerformanceLeagueTable(); break;
|
||||
case LTMN_PERFORMANCE_RATING: ShowPerformanceRatingDetail(); break;
|
||||
case LTMN_HIGHSCORE: ShowHighscoreTable(); break;
|
||||
default: {
|
||||
if (LeagueTable::IsValidID(index)) {
|
||||
ShowScriptLeagueTable((LeagueTableID)index);
|
||||
}
|
||||
}
|
||||
}
|
||||
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 --- */
|
||||
|
||||
|
@ -1299,8 +1336,8 @@ static MenuClickedProc * const _menu_clicked_procs[] = {
|
|||
MenuClickCompany, // 9
|
||||
MenuClickStory, // 10
|
||||
MenuClickGoal, // 11
|
||||
MenuClickGraphs, // 12
|
||||
MenuClickLeague, // 13
|
||||
MenuClickGraphsOrLeague, // 12
|
||||
MenuClickGraphsOrLeague, // 13
|
||||
MenuClickIndustry, // 14
|
||||
MenuClickShowTrains, // 15
|
||||
MenuClickShowRoad, // 16
|
||||
|
@ -2020,7 +2057,7 @@ struct MainToolbarWindow : Window {
|
|||
case MTHK_STORY: ShowStoryBook(_local_company); break;
|
||||
case MTHK_GOAL: ShowGoalsList(_local_company); break;
|
||||
case MTHK_GRAPHS: ShowOperatingProfitGraph(); break;
|
||||
case MTHK_LEAGUE: ShowCompanyLeagueTable(); break;
|
||||
case MTHK_LEAGUE: ShowFirstLeagueTable(); break;
|
||||
case MTHK_INDUSTRIES: ShowBuildIndustryWindow(); break;
|
||||
case MTHK_TRAIN_LIST: ShowVehicleListWindow(_local_company, VEH_TRAIN); break;
|
||||
case MTHK_ROADVEH_LIST: ShowVehicleListWindow(_local_company, VEH_ROAD); break;
|
||||
|
|
|
@ -27,6 +27,7 @@ add_files(
|
|||
highscore_widget.h
|
||||
industry_widget.h
|
||||
intro_widget.h
|
||||
league_widget.h
|
||||
link_graph_legend_widget.h
|
||||
main_widget.h
|
||||
misc_widget.h
|
||||
|
|
|
@ -51,11 +51,6 @@ enum CargoPaymentRatesWidgets {
|
|||
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. */
|
||||
enum PerformanceRatingDetailsWidgets {
|
||||
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