Changeset - r26612:e1c0fa463732
src/CMakeLists.txt
Show inline comments
 
@@ -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
src/command.cpp
Show inline comments
 
@@ -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"
src/command_type.h
Show inline comments
 
@@ -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)
 
};
 

	
src/graph_gui.cpp
Show inline comments
 
@@ -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 */
 
/*****************************/
src/graph_gui.h
Show inline comments
 
@@ -16,7 +16,6 @@ void ShowDeliveredCargoGraph();
 
void ShowPerformanceHistoryGraph();
 
void ShowCompanyValueGraph();
 
void ShowCargoPaymentRates();
 
void ShowCompanyLeagueTable();
 
void ShowPerformanceRatingDetail();
 

	
 
#endif /* GRAPH_GUI_H */
src/league_base.h
Show inline comments
 
new file 100644
 
/*
 
 * 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 */
src/league_cmd.cpp
Show inline comments
 
new file 100644
 
/*
 
 * 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();
 
}
src/league_cmd.h
Show inline comments
 
new file 100644
 
/*
 
 * 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 */
src/league_gui.cpp
Show inline comments
 
new file 100644
 
/*
 
 * 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();
 
	}
 
}
src/league_gui.h
Show inline comments
 
new file 100644
 
/*
 
 * 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 */
src/league_type.h
Show inline comments
 
new file 100644
 
/*
 
 * 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 */
src/network/network_command.cpp
Show inline comments
 
@@ -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"
src/saveload/CMakeLists.txt
Show inline comments
 
@@ -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
src/saveload/league_sl.cpp
Show inline comments
 
new file 100644
 
/*
 
 * 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);
src/saveload/saveload.cpp
Show inline comments
 
@@ -240,6 +240,7 @@ static const std::vector<ChunkHandlerRef
 
	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
 
		_cargomonitor_chunk_handlers,
 
		_goal_chunk_handlers,
 
		_story_page_chunk_handlers,
 
		_league_chunk_handlers,
 
		_engine_chunk_handlers,
 
		_town_chunk_handlers,
 
		_sign_chunk_handlers,
src/script/api/CMakeLists.txt
Show inline comments
 
@@ -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
src/script/api/game_changelog.hpp
Show inline comments
 
@@ -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
src/script/api/script_league.cpp
Show inline comments
 
new file 100644
 
/*
 
 * 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);
 
}
src/script/api/script_league.hpp
Show inline comments
 
new file 100644
 
/*
 
 * 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 */
src/script/script_instance.cpp
Show inline comments
 
@@ -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;
src/script/script_instance.hpp
Show inline comments
 
@@ -116,6 +116,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.
 
	 */
 
	class ScriptController *GetController() { return controller; }
src/toolbar_gui.cpp
Show inline comments
 
@@ -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(Wi
 
	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(in
 
	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_cli
 
	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;
src/widgets/CMakeLists.txt
Show inline comments
 
@@ -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
src/widgets/graph_widget.h
Show inline comments
 
@@ -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.
src/widgets/league_widget.h
Show inline comments
 
new file 100644
 
/*
 
 * 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 */
0 comments (0 inline, 0 general)