summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--economy.c68
-rw-r--r--economy.h42
-rw-r--r--graph_gui.c228
-rw-r--r--gui.h1
-rw-r--r--lang/english.txt31
-rw-r--r--main_gui.c7
-rw-r--r--misc.c15
-rw-r--r--ttd.c3
-rw-r--r--ttd.h1
-rw-r--r--window.c2
-rw-r--r--window.h1
11 files changed, 373 insertions, 26 deletions
diff --git a/economy.c b/economy.c
index ffc4a02d5..eef997e67 100644
--- a/economy.c
+++ b/economy.c
@@ -80,10 +80,14 @@ uint32 CalculateCompanyValue(Player *p) {
return value;
}
-static void UpdateCompanyRatingAndValue(Player *p)
+// if update is set to true, the economy is updated with this score
+// (also the house is updated, should only be true in the on-tick event)
+void UpdateCompanyRatingAndValue(Player *p, bool update)
{
byte owner = p->index;
- uint score;
+ int score = 0;
+
+ memset(_score_part[owner], 0, sizeof(_score_part[owner]));
/* Count vehicles */
{
@@ -100,16 +104,16 @@ static void UpdateCompanyRatingAndValue(Player *p)
v->type == VEH_Ship) {
num++;
if (v->age > 730) {
- if (min_profit >= v->profit_last_year)
+ if (min_profit > v->profit_last_year)
min_profit = v->profit_last_year;
}
}
}
- score = (num < 120) ? num * 100 / 120 : 100;
+ _score_part[owner][SCORE_VEHICLES] = num;
if (min_profit != MAX_INT && min_profit > 0)
- score += (min_profit < 10000) ? min_profit/100 : 100;
+ _score_part[owner][SCORE_MIN_PROFIT] = min_profit;
}
/* Count stations */
@@ -123,7 +127,7 @@ static void UpdateCompanyRatingAndValue(Player *p)
do num += facil&1; while (facil>>=1);
}
}
- score += (num < 80) ? num * 100 / 80 : 100;
+ _score_part[owner][SCORE_STATIONS] = num;
}
/* Generate statistics depending on recent income statistics */
@@ -144,9 +148,9 @@ static void UpdateCompanyRatingAndValue(Player *p)
} while (++pee,--numec);
if (min_income > 0)
- score += min_income >= 50000 ? 50 : min_income / 1000;
+ _score_part[owner][SCORE_MIN_INCOME] = min_income;
- score += max_income >= 100000 ? 100 : max_income / 1000;
+ _score_part[owner][SCORE_MAX_INCOME] = max_income;
}
}
@@ -164,35 +168,63 @@ static void UpdateCompanyRatingAndValue(Player *p)
total_delivered += pee->delivered_cargo;
} while (++pee,--numec);
- score += total_delivered >= 40000 ? 400 : total_delivered / 100;
+ _score_part[owner][SCORE_DELIVERED] = total_delivered;
}
}
-
+
/* Generate score for variety of cargo */
{
uint cargo = p->cargo_types;
uint num = 0;
do num += cargo&1; while (cargo>>=1);
- score += num < 8 ? num * 50 / 8 : 50;
- p->cargo_types = 0;
+ _score_part[owner][SCORE_CARGO] = num;
+ if (update)
+ p->cargo_types = 0;
}
/* Generate score for player money */
{
int32 money = p->player_money;
if (money > 0) {
- score += money < 10000000 ? money / (10000000/50) : 50;
+ _score_part[owner][SCORE_MONEY] = money;
}
}
/* Generate score for loan */
{
- score += (250000 - p->current_loan) >= 0 ? (250000 - p->current_loan) / 5000 : 0;
+ _score_part[owner][SCORE_LOAN] = score_info[SCORE_LOAN].needed - p->current_loan;
+ }
+
+ // Now we calculate the score for each item..
+ {
+ int i;
+ int total_score = 0;
+ int s;
+ score = 0;
+ for (i=0;i<NUM_SCORE;i++) {
+ // Skip the total
+ if (i == SCORE_TOTAL) continue;
+ // Check the score
+ s = (_score_part[owner][i] >= score_info[i].needed) ? score_info[i].score : ((_score_part[owner][i] * score_info[i].score) / score_info[i].needed);
+ if (s < 0) s = 0;
+ score += s;
+ total_score += score_info[i].score;
+ }
+
+ _score_part[owner][SCORE_TOTAL] = score;
+
+ // We always want the score scaled to SCORE_MAX (1000)
+ if (total_score != SCORE_MAX)
+ score = score * SCORE_MAX / total_score;
}
- p->old_economy[0].performance_history = score;
- UpdatePlayerHouse(p, score);
- p->old_economy[0].company_value = CalculateCompanyValue(p);
+ if (update) {
+ p->old_economy[0].performance_history = score;
+ UpdatePlayerHouse(p, score);
+ p->old_economy[0].company_value = CalculateCompanyValue(p);
+ }
+
+ InvalidateWindow(WC_PERFORMANCE_DETAIL, 0);
}
// use 255 as new_player to delete the player.
@@ -495,7 +527,7 @@ static void PlayersGenStatistics()
if (p->num_valid_stat_ent != 24)
p->num_valid_stat_ent++;
- UpdateCompanyRatingAndValue(p);
+ UpdateCompanyRatingAndValue(p, true);
PlayersCheckBankrupt(p);
if (p->block_preview != 0)
diff --git a/economy.h b/economy.h
index 5ed2e9c70..cee60e314 100644
--- a/economy.h
+++ b/economy.h
@@ -23,6 +23,48 @@ typedef struct Subsidy {
} Subsidy;
+enum {
+ SCORE_VEHICLES = 0,
+ SCORE_STATIONS = 1,
+ SCORE_MIN_PROFIT = 2,
+ SCORE_MIN_INCOME = 3,
+ SCORE_MAX_INCOME = 4,
+ SCORE_DELIVERED = 5,
+ SCORE_CARGO = 6,
+ SCORE_MONEY = 7,
+ SCORE_LOAN = 8,
+ SCORE_TOTAL = 9, // This must always be the last entry
+
+ NUM_SCORE = 10, // How many scores are there..
+
+ SCORE_MAX = 1000, // The max score that can be in the performance history
+ // the scores together of score_info is allowed to be more!
+};
+
+typedef struct ScoreInfo {
+ byte id; // Unique ID of the score
+ int needed; // How much you need to get the perfect score
+ int score; // How much score it will give
+} ScoreInfo;
+
+static const ScoreInfo score_info[] = {
+ {SCORE_VEHICLES, 120, 100},
+ {SCORE_STATIONS, 80, 100},
+ {SCORE_MIN_PROFIT, 10000, 100},
+ {SCORE_MIN_INCOME, 50000, 50},
+ {SCORE_MAX_INCOME, 100000, 100},
+ {SCORE_DELIVERED, 40000, 400},
+ {SCORE_CARGO, 8, 50},
+ {SCORE_MONEY, 10000000, 50},
+ {SCORE_LOAN, 250000, 50},
+ {SCORE_TOTAL}
+};
+
+int _score_part[MAX_PLAYERS][NUM_SCORE];
+
+void UpdateCompanyRatingAndValue(Player *p, bool update);
+
+
VARDEF Subsidy _subsidies[MAX_PLAYERS];
Pair SetupSubsidyDecodeParam(Subsidy *s, bool mode);
void DeleteSubsidyWithIndustry(byte index);
diff --git a/graph_gui.c b/graph_gui.c
index fcb6f81d8..119bea8b4 100644
--- a/graph_gui.c
+++ b/graph_gui.c
@@ -4,6 +4,7 @@
#include "gui.h"
#include "gfx.h"
#include "player.h"
+#include "economy.h"
static uint _legend_showbits;
static uint _legend_cargobits;
@@ -511,7 +512,227 @@ void ShowDeliveredCargoGraph()
InvalidateWindow(WC_GRAPH_LEGEND, 0);
_legend_showbits = 0;
}
-}
+}
+
+/*****************************/
+/* PERFORMANCE RATING DETAIL */
+/*****************************/
+
+static void PerformanceRatingDetailWndProc(Window *w, WindowEvent *e)
+{
+ switch(e->event) {
+ case WE_PAINT: {
+ int val, needed, score, i;
+ byte owner, x;
+ uint16 y=14;
+ int total_score = 0;
+ int color_done, color_notdone;
+
+ // Draw standard stuff
+ DrawWindowWidgets(w);
+
+ // The player of which we check the detail performance rating
+ owner = FindFirstBit(w->click_state) - 13;
+
+ // Paint the player icons
+ for (i=0;i<MAX_PLAYERS;i++) {
+ if (!DEREF_PLAYER(i)->is_active) {
+ // Check if we have the player as an active player
+ if (!(w->disabled_state & (1 << (i+13)))) {
+ // Bah, player gone :(
+ w->disabled_state += 1 << (i+13);
+ // Is this player selected? If so, select first player (always save? :s)
+ if (w->click_state == 1 << (i+13))
+ w->click_state = 1 << 13;
+ // We need a repaint
+ SetWindowDirty(w);
+ }
+ continue;
+ }
+
+ // Check if we have the player marked as inactive
+ if ((w->disabled_state & (1 << (i+13)))) {
+ // New player! Yippie :p
+ w->disabled_state -= 1 << (i+13);
+ // We need a repaint
+ SetWindowDirty(w);
+ }
+
+ if (i == owner) x = 1; else x = 0;
+ DrawPlayerIcon(i, i*33+11+x, 16+x);
+ }
+
+ // The colors used to show how the progress is going
+ color_done = _color_list[6].window_color_1b;
+ color_notdone = _color_list[4].window_color_1b;
+
+ // Draw all the score parts
+ for (i=0;i<NUM_SCORE;i++) {
+ y += 20;
+ val = _score_part[owner][i];
+ needed = score_info[i].needed;
+ score = score_info[i].score;
+ // SCORE_TOTAL has his own rulez ;)
+ if (i == SCORE_TOTAL) {
+ needed = total_score;
+ score = SCORE_MAX;
+ } else
+ total_score += score;
+
+ DrawString(7, y, STR_PERFORMANCE_DETAIL_VEHICLES + i, 0);
+
+ // Draw the score
+ SET_DPARAM32(0, score);
+ DrawStringRightAligned(107, y, SET_PERFORMANCE_DETAIL_INT, 0);
+
+ // Calculate the %-bar
+ if (val > needed) x = 50;
+ else if (val == 0) x = 0;
+ else x = ((val * 50) / needed);
+
+ // SCORE_LOAN is inversed
+ if (val < 0 && i == SCORE_LOAN)
+ x = 0;
+
+ // Draw the bar
+ if (x != 0)
+ GfxFillRect(112, y-2, x + 112, y+10, color_done);
+ if (x != 50)
+ GfxFillRect(x + 112, y-2, 50 + 112, y+10, color_notdone);
+
+ // Calculate the %
+ if (val > needed) x = 100;
+ else x = ((val * 100) / needed);
+
+ // SCORE_LOAN is inversed
+ if (val < 0 && i == SCORE_LOAN)
+ x = 0;
+
+ // Draw it
+ SET_DPARAM32(0, x);
+ DrawStringCentered(137, y, STR_PERFORMANCE_DETAIL_PERCENT, 0);
+
+ // SCORE_LOAN is inversed
+ if (i == SCORE_LOAN)
+ val = needed - val;
+
+ // Draw the amount we have against what is needed
+ // For some of them it is in currency format
+ SET_DPARAM32(0, val);
+ SET_DPARAM32(1, needed);
+ switch (i) {
+ case SCORE_MIN_PROFIT:
+ case SCORE_MIN_INCOME:
+ case SCORE_MAX_INCOME:
+ case SCORE_MONEY:
+ case SCORE_LOAN:
+ DrawString(167, y, STR_PERFORMANCE_DETAIL_AMOUNT_CURRENCY, 0);
+ break;
+ default:
+ DrawString(167, y, STR_PERFORMANCE_DETAIL_AMOUNT_INT, 0);
+ }
+ }
+
+ break;
+ }
+
+ case WE_CLICK:
+ // Check which button is clicked
+ if (IS_INT_INSIDE(e->click.widget, 13, 21)) {
+ // Is it no on disable?
+ if ((w->disabled_state & (1 << e->click.widget)) == 0) {
+ w->click_state = 1 << e->click.widget;
+ SetWindowDirty(w);
+ }
+ }
+ break;
+
+ case WE_CREATE:
+ {
+ int i;
+ Player *p2;
+ w->hidden_state = 0;
+ w->disabled_state = 0;
+
+ // Hide the player who are not active
+ for (i=0;i<MAX_PLAYERS;i++) {
+ if (!DEREF_PLAYER(i)->is_active) {
+ w->disabled_state += 1 << (i+13);
+ }
+ }
+ // Update all player stats with the current data
+ // (this is because _score_info is not saved to a savegame)
+ FOR_ALL_PLAYERS(p2)
+ if (p2->is_active)
+ UpdateCompanyRatingAndValue(p2, false);
+
+ w->custom[0] = 74;
+ w->custom[1] = 5;
+
+ w->click_state = 1 << 13;
+
+ SetWindowDirty(w);
+ }
+ break;
+ case WE_TICK:
+ {
+ // Update the player score every 5 days
+ if (--w->custom[0] == 0) {
+ w->custom[0] = 74;
+ if (--w->custom[1] == 0) {
+ Player *p2;
+ w->custom[1] = 5;
+ FOR_ALL_PLAYERS(p2)
+ // Skip if player is not active
+ if (p2->is_active)
+ UpdateCompanyRatingAndValue(p2, false);
+ SetWindowDirty(w);
+ }
+ }
+ }
+ break;
+ }
+}
+
+static const Widget _performance_rating_detail_widgets[] = {
+{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
+{ WWT_CAPTION, 14, 11, 266, 0, 13, STR_PERFORMANCE_DETAIL, STR_018C_WINDOW_TITLE_DRAG_THIS},
+{ WWT_IMGBTN, 14, 0, 266, 14, 27, 0x0},
+
+{ WWT_IMGBTN, 14, 0, 266, 28, 47, 0x0,STR_PERFORMANCE_DETAIL_VEHICLES_TIP},
+{ WWT_IMGBTN, 14, 0, 266, 48, 67, 0x0,STR_PERFORMANCE_DETAIL_STATIONS_TIP},
+{ WWT_IMGBTN, 14, 0, 266, 68, 87, 0x0,STR_PERFORMANCE_DETAIL_MIN_PROFIT_TIP},
+{ WWT_IMGBTN, 14, 0, 266, 88, 107, 0x0,STR_PERFORMANCE_DETAIL_MIN_INCOME_TIP},
+{ WWT_IMGBTN, 14, 0, 266, 108, 127, 0x0,STR_PERFORMANCE_DETAIL_MAX_INCOME_TIP},
+{ WWT_IMGBTN, 14, 0, 266, 128, 147, 0x0,STR_PERFORMANCE_DETAIL_DELIVERED_TIP},
+{ WWT_IMGBTN, 14, 0, 266, 148, 167, 0x0,STR_PERFORMANCE_DETAIL_CARGO_TIP},
+{ WWT_IMGBTN, 14, 0, 266, 168, 187, 0x0,STR_PERFORMANCE_DETAIL_MONEY_TIP},
+{ WWT_IMGBTN, 14, 0, 266, 188, 207, 0x0,STR_PERFORMANCE_DETAIL_LOAN_TIP},
+{ WWT_IMGBTN, 14, 0, 266, 208, 227, 0x0,STR_PERFORMANCE_DETAIL_TOTAL_TIP},
+
+{ WWT_IMGBTN, 14, 2, 34, 14, 26, 0x0,STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
+{ WWT_IMGBTN, 14, 35, 67, 14, 26, 0x0,STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
+{ WWT_IMGBTN, 14, 68, 100, 14, 26, 0x0,STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
+{ WWT_IMGBTN, 14, 101, 133, 14, 26, 0x0,STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
+{ WWT_IMGBTN, 14, 134, 166, 14, 26, 0x0,STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
+{ WWT_IMGBTN, 14, 167, 199, 14, 26, 0x0,STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
+{ WWT_IMGBTN, 14, 200, 232, 14, 26, 0x0,STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
+{ WWT_IMGBTN, 14, 233, 265, 14, 26, 0x0,STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
+{ WWT_LAST},
+};
+
+static const WindowDesc _performance_rating_detail_desc = {
+ -1, -1, 267, 228,
+ WC_PERFORMANCE_DETAIL,0,
+ WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
+ _performance_rating_detail_widgets,
+ PerformanceRatingDetailWndProc
+};
+
+void ShowPerformanceRatingDetail()
+{
+ AllocateWindowDescFront(&_performance_rating_detail_desc, 0);
+}
/***********************/
/* PERFORMANCE HISTORY */
@@ -558,14 +779,17 @@ static void PerformanceHistoryWndProc(Window *w, WindowEvent *e)
case WE_CLICK:
if (e->click.widget == 2)
ShowGraphLegend();
+ if (e->click.widget == 3)
+ ShowPerformanceRatingDetail();
break;
}
}
static const Widget _performance_history_widgets[] = {
{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
-{ WWT_CAPTION, 14, 11, 525, 0, 13, STR_7051_COMPANY_PERFORMANCE_RATINGS, STR_018C_WINDOW_TITLE_DRAG_THIS},
+{ WWT_CAPTION, 14, 11, 475, 0, 13, STR_7051_COMPANY_PERFORMANCE_RATINGS, STR_018C_WINDOW_TITLE_DRAG_THIS},
{ WWT_PUSHTXTBTN, 14, 526, 575, 0, 13, STR_704C_KEY, STR_704D_SHOW_KEY_TO_GRAPHS},
+{ WWT_PUSHTXTBTN, 14, 476, 525, 0, 13, STR_PERFORMANCE_DETAIL_KEY, STR_704D_SHOW_KEY_TO_GRAPHS},
{ WWT_IMGBTN, 14, 0, 575, 14, 237, 0x0},
{ WWT_LAST},
};
diff --git a/gui.h b/gui.h
index 37d677376..16077cd7e 100644
--- a/gui.h
+++ b/gui.h
@@ -19,6 +19,7 @@ void ShowPerformanceHistoryGraph();
void ShowCompanyValueGraph();
void ShowCargoPaymentRates();
void ShowCompanyLeagueTable();
+void ShowPerformanceRatingDetail();
/* news_gui.c */
void ShowLastNewsMessage();
diff --git a/lang/english.txt b/lang/english.txt
index d999370a8..4ad0a2a2e 100644
--- a/lang/english.txt
+++ b/lang/english.txt
@@ -342,6 +342,7 @@ STR_0157_PERFORMANCE_HISTORY_GRAPH :Performance history graph
STR_0158_COMPANY_VALUE_GRAPH :Company value graph
STR_0159_CARGO_PAYMENT_RATES :Cargo payment rates
STR_015A_COMPANY_LEAGUE_TABLE :Company league table
+STR_PERFORMANCE_DETAIL_MENU :Detail performance rating
############ range for menu ends
STR_015B_OPENTTD :{WHITE}About OpenTTD
@@ -2518,3 +2519,33 @@ STR_B005_COAL_MINE_SUBSIDENCE_LEAVES :{BLACK}{BIGFONT}Coal mine subsidence leave
STR_BRIBE_FAILED :{WHITE}Your attempted bribery has been
STR_BRIBE_FAILED_2 :{WHITE}discovered by a regional investigator
STR_BUILD_DATE :{BLACK}Built: {LTBLUE}{DATE_LONG}
+
+STR_PERFORMANCE_DETAIL :{WHITE}Detail performance rating
+STR_PERFORMANCE_DETAIL_KEY :{BLACK}Detail
+STR_PERFORMANCE_DETAIL_AMOUNT_CURRENCY :{BLACK}{TINYFONT}({CURRCOMPACT}/{CURRCOMPACT})
+STR_PERFORMANCE_DETAIL_AMOUNT_INT :{BLACK}{TINYFONT}({INT32}/{INT32})
+STR_PERFORMANCE_DETAIL_PERCENT :{WHITE}{INT32}%
+SET_PERFORMANCE_DETAIL_INT :{BLACK}{INT32}
+############ Those following lines need to be in this order!!
+STR_PERFORMANCE_DETAIL_VEHICLES :{BLACK}Vehicles:
+STR_PERFORMANCE_DETAIL_STATIONS :{BLACK}Stations:
+STR_PERFORMANCE_DETAIL_MIN_PROFIT :{BLACK}Min. profit:
+STR_PERFORMANCE_DETAIL_MIN_INCOME :{BLACK}Min. income:
+STR_PERFORMANCE_DETAIL_MAX_INCOME :{BLACK}Max. income:
+STR_PERFORMANCE_DETAIL_DELIVERED :{BLACK}Delivered:
+STR_PERFORMANCE_DETAIL_CARGO :{BLACK}Cargo:
+STR_PERFORMANCE_DETAIL_MONEY :{BLACK}Money:
+STR_PERFORMANCE_DETAIL_LOAN :{BLACK}Loan:
+STR_PERFORMANCE_DETAIL_TOTAL :{BLACK}Total:
+############ End of order list
+STR_PERFORMANCE_DETAIL_VEHICLES_TIP :{BLACK}Amount of vehicles. This includes road vehicles, trains, ships and aircraft.
+STR_PERFORMANCE_DETAIL_STATIONS_TIP :{BLACK}Amount of station parts. Every part of a station (e.g. train station, bus stop, airport) is counted, even if they are connected to one station.
+STR_PERFORMANCE_DETAIL_MIN_PROFIT_TIP :{BLACK}The minimum profit of all the vehicles that are more than 2 years old.
+STR_PERFORMANCE_DETAIL_MIN_INCOME_TIP :{BLACK}Amount of cash made in the month with the lowest profit of the past 12 quarters
+STR_PERFORMANCE_DETAIL_MAX_INCOME_TIP :{BLACK}Amount of cash made in the month with the highest profit of the past 12 quarters
+STR_PERFORMANCE_DETAIL_DELIVERED_TIP :{BLACK}Units of cargo delivered in the past four quarters.
+STR_PERFORMANCE_DETAIL_CARGO_TIP :{BLACK}Types of cargo delivered in the last quarter.
+STR_PERFORMANCE_DETAIL_MONEY_TIP :{BLACK}Amount of cash on hand
+STR_PERFORMANCE_DETAIL_LOAN_TIP :{BLACK}Do you have a high loan?
+STR_PERFORMANCE_DETAIL_TOTAL_TIP :{BLACK}Total points out of possible points
+
diff --git a/main_gui.c b/main_gui.c
index 9d6c6f5b7..f5eec080b 100644
--- a/main_gui.c
+++ b/main_gui.c
@@ -202,7 +202,10 @@ void MenuClickGraphs(int index)
void MenuClickLeague(int index)
{
- ShowCompanyLeagueTable();
+ switch(index) {
+ case 0: ShowCompanyLeagueTable(); return;
+ case 1: ShowPerformanceRatingDetail(); return;
+ }
}
void MenuClickIndustry(int index)
@@ -648,7 +651,7 @@ static void ToolbarGraphsClick(Window *w)
static void ToolbarLeagueClick(Window *w)
{
- PopupMainToolbMenu(w, 258, 11, STR_015A_COMPANY_LEAGUE_TABLE, 1);
+ PopupMainToolbMenu(w, 258, 11, STR_015A_COMPANY_LEAGUE_TABLE, 2);
}
static void ToolbarIndustryClick(Window *w)
diff --git a/misc.c b/misc.c
index 06e790019..5f86d8445 100644
--- a/misc.c
+++ b/misc.c
@@ -601,11 +601,18 @@ void IncreaseDate()
/* XXX: check if year 2050 was reached */
}
-int FindFirstBit(uint32 x)
+int FindFirstBit(uint32 value)
{
- int i = 0;
- assert(x != 0);
- for(;!(x&1);i++,x>>=1);
+ // This is much faster then the one that was before here.
+ // Created by Darkvater.. blame him if it is wrong ;)
+ // Btw, the macro FINDFIRSTBIT is better to use when your value is
+ // not more then 128.
+ byte i = 0;
+ if (value & 0xffff0000) { value >>= 16; i += 16; }
+ if (value & 0x0000ff00) { value >>= 8; i += 8; }
+ if (value & 0x000000f0) { value >>= 4; i += 4; }
+ if (value & 0x0000000c) { value >>= 2; i += 2; }
+ if (value & 0x00000002) { i += 1; }
return i;
}
diff --git a/ttd.c b/ttd.c
index 00a77c3b9..8f6d281ef 100644
--- a/ttd.c
+++ b/ttd.c
@@ -705,6 +705,9 @@ void MakeNewEditorWorld()
MarkWholeScreenDirty();
}
+void StartupPlayers();
+void StartupDisasters();
+
void StartScenario()
{
_game_mode = GM_NORMAL;
diff --git a/ttd.h b/ttd.h
index 3846148de..d6656ee35 100644
--- a/ttd.h
+++ b/ttd.h
@@ -393,6 +393,7 @@ enum {
WC_INDUSTRY_DIRECTORY = 0x43,
WC_MESSAGE_HISTORY = 0x44,
WC_CHEATS = 0x45,
+ WC_PERFORMANCE_DETAIL = 0x46,
};
diff --git a/window.c b/window.c
index 9bd17934a..8740bb183 100644
--- a/window.c
+++ b/window.c
@@ -346,6 +346,8 @@ restart:;
_last_window++;
SetWindowDirty(w);
+
+ CallWindowEventNP(w, WE_CREATE);
return w;
}
diff --git a/window.h b/window.h
index 342768149..9f8f50be1 100644
--- a/window.h
+++ b/window.h
@@ -293,6 +293,7 @@ enum WindowEvents {
WE_DROPDOWN_SELECT = 16,
WE_RCLICK = 17,
WE_KEYPRESS = 18,
+ WE_CREATE = 19,
};