0
|
1 |
#include "stdafx.h"
|
|
2 |
#include "ttd.h"
|
|
3 |
#include "window.h"
|
|
4 |
#include "gui.h"
|
|
5 |
#include "station.h"
|
|
6 |
#include "gfx.h"
|
|
7 |
#include "player.h"
|
|
8 |
#include "town.h"
|
|
9 |
#include "command.h"
|
|
10 |
|
|
11 |
static void StationsWndShowStationRating(int x, int y, int type, uint acceptance, int rating)
|
|
12 |
{
|
|
13 |
static const byte _rating_colors[NUM_CARGO] = {152,32,15,174,208,194,191,55,184,10,191,48};
|
|
14 |
int color = _rating_colors[type];
|
|
15 |
uint w;
|
|
16 |
|
|
17 |
if (acceptance > 575)
|
|
18 |
acceptance = 575;
|
|
19 |
|
|
20 |
acceptance = (acceptance + 7) >> 3;
|
|
21 |
|
|
22 |
/* draw cargo */
|
|
23 |
if ( (w=acceptance>>3) != 0) {
|
|
24 |
GfxFillRect(x, y, x+w-1, y+6, color);
|
|
25 |
x += w;
|
|
26 |
}
|
|
27 |
|
|
28 |
if ( (w=acceptance&7) != 0) {
|
|
29 |
if (w==7) w--;
|
|
30 |
GfxFillRect(x, y+(w-1), x, y+6, color);
|
|
31 |
}
|
|
32 |
|
|
33 |
x -= (acceptance>>3);
|
|
34 |
|
|
35 |
DrawString(x+1, y, _cargoc.names_short[type], 0x10);
|
|
36 |
|
|
37 |
/* draw green/red ratings bar */
|
|
38 |
GfxFillRect(x+1, y+8, x+7, y+8, 0xB8);
|
|
39 |
|
|
40 |
rating = (rating >> 5);
|
|
41 |
|
|
42 |
if (rating != 0) {
|
|
43 |
GfxFillRect(x+1, y+8, x+rating, y+8, 0xD0);
|
|
44 |
}
|
|
45 |
}
|
|
46 |
|
|
47 |
// used to get a sorted list of the stations
|
|
48 |
typedef struct StationSort {
|
|
49 |
uint16 index;
|
|
50 |
byte owner;
|
|
51 |
} StationSort;
|
|
52 |
|
|
53 |
static StationSort _station_sort[lengthof(_stations)];
|
|
54 |
static uint16 _num_station_sort[MAX_PLAYERS];
|
|
55 |
|
|
56 |
static char _bufcache[64];
|
|
57 |
static uint16 _last_station_idx;
|
|
58 |
|
|
59 |
static int CDECL StationSorterByName(const void *a, const void *b)
|
|
60 |
{
|
|
61 |
char buf1[64];
|
|
62 |
Station *st;
|
|
63 |
StationSort *cmp1, *cmp2;
|
|
64 |
cmp1 = (StationSort*)a;
|
|
65 |
cmp2 = (StationSort*)b;
|
|
66 |
|
|
67 |
// sort stations by owner, and inside owner by name
|
|
68 |
if (cmp1->owner == cmp2->owner) { // if same owner, sort by name
|
|
69 |
st = DEREF_STATION(cmp1->index);
|
|
70 |
SET_DPARAM16(0, st->town->townnametype);
|
|
71 |
SET_DPARAM32(1, st->town->townnameparts);
|
|
72 |
GetString(buf1, st->string_id);
|
|
73 |
|
|
74 |
if ( cmp2->index != _last_station_idx) {
|
|
75 |
_last_station_idx = cmp2->index;
|
|
76 |
st = DEREF_STATION(cmp2->index);
|
|
77 |
SET_DPARAM16(0, st->town->townnametype);
|
|
78 |
SET_DPARAM32(1, st->town->townnameparts);
|
|
79 |
GetString(_bufcache, st->string_id);
|
|
80 |
}
|
|
81 |
|
|
82 |
return strcmp(buf1, _bufcache); // sort by name
|
|
83 |
}
|
|
84 |
return cmp1->owner - cmp2->owner; // sort by owner
|
|
85 |
}
|
|
86 |
|
|
87 |
static void MakeSortedStationList(Window *w)
|
|
88 |
{
|
|
89 |
Station *st;
|
|
90 |
uint16 n = 0;
|
|
91 |
uint16 *i;
|
|
92 |
// reset to 0 just to be sure
|
|
93 |
for (i = _num_station_sort; i != endof(_num_station_sort); i++) {*i = 0;}
|
|
94 |
|
|
95 |
FOR_ALL_STATIONS(st) {
|
|
96 |
if(st->xy && st->owner != OWNER_NONE) {
|
|
97 |
_station_sort[n].index = st->index;
|
|
98 |
_station_sort[n++].owner = st->owner;
|
|
99 |
_num_station_sort[st->owner]++; // add number of stations of player
|
|
100 |
}
|
|
101 |
}
|
|
102 |
|
|
103 |
// create cumulative station-ownage
|
|
104 |
// stations are stored as a cummulative index, eg 25, 41, 43. This means
|
|
105 |
// Player0: 25; Player1: (41-25) 16; Player2: (43-41) 2
|
|
106 |
for (i = &_num_station_sort[1]; i != endof(_num_station_sort); i++) {*i += *(i-1);}
|
|
107 |
|
|
108 |
_last_station_idx = 255; // used for "cache"
|
|
109 |
qsort(_station_sort, n, sizeof(_station_sort[0]), StationSorterByName);
|
|
110 |
//#ifdef _DEBUG
|
|
111 |
// {printf("Resorting Stations list...\n");}
|
|
112 |
//#endif
|
|
113 |
}
|
|
114 |
|
|
115 |
static void PlayerStationsWndProc(Window *w, WindowEvent *e)
|
|
116 |
{
|
|
117 |
switch(e->event) {
|
|
118 |
case WE_PAINT: {
|
|
119 |
byte i;
|
|
120 |
if (_station_sort_dirty) {
|
|
121 |
_station_sort_dirty = false;
|
|
122 |
MakeSortedStationList(w);
|
|
123 |
}
|
|
124 |
|
|
125 |
// stations are stored as a cummulative index, eg 25, 41, 43. This means
|
|
126 |
// Player0: 25; Player1: (41-25) 16; Player2: (43-41) 2 stations
|
|
127 |
i = (byte)(w->window_number == 0) ? 0 : _num_station_sort[w->window_number-1];;
|
|
128 |
SetVScrollCount(w, _num_station_sort[w->window_number] - i);
|
|
129 |
|
|
130 |
/* draw widgets, with player's name in the caption */
|
|
131 |
{
|
|
132 |
Player *p = DEREF_PLAYER(w->window_number);
|
|
133 |
SET_DPARAM16(0, p->name_1);
|
|
134 |
SET_DPARAM32(1, p->name_2);
|
|
135 |
SET_DPARAM16(2, w->vscroll.count);
|
|
136 |
DrawWindowWidgets(w);
|
|
137 |
}
|
|
138 |
|
|
139 |
{
|
|
140 |
byte p = 0;
|
|
141 |
Station *st;
|
|
142 |
int x,xb = 2;
|
|
143 |
int y = 16; // offset from top of widget
|
|
144 |
int j;
|
|
145 |
|
|
146 |
if (w->vscroll.count == 0) { // player has no stations
|
|
147 |
DrawString(xb, y, STR_304A_NONE, 0);
|
|
148 |
return;
|
|
149 |
}
|
|
150 |
|
|
151 |
i += w->vscroll.pos; // offset from sorted station list of current player
|
|
152 |
assert(i < _num_station_sort[w->window_number]); // at least one station must exist
|
|
153 |
|
|
154 |
while (i < _num_station_sort[w->window_number]) { // do until max number of stations of owner
|
|
155 |
st = DEREF_STATION(_station_sort[i].index);
|
|
156 |
|
|
157 |
SET_DPARAM16(0, st->index);
|
|
158 |
SET_DPARAM8(1, st->facilities);
|
|
159 |
x = DrawString(xb, y, STR_3049_0, 0) + 5;
|
|
160 |
|
|
161 |
// show cargo waiting and station ratings
|
|
162 |
for(j=0; j!=NUM_CARGO; j++) {
|
|
163 |
int acc = (st->goods[j].waiting_acceptance & 0xFFF);
|
|
164 |
if (acc != 0) {
|
|
165 |
StationsWndShowStationRating(x, y, j, acc, st->goods[j].rating);
|
|
166 |
x += 10;
|
|
167 |
}
|
|
168 |
}
|
|
169 |
y += 10;
|
|
170 |
i++; // next station
|
|
171 |
if (++p == 12) { break;} // max number of stations in 1 window
|
|
172 |
}
|
|
173 |
}
|
|
174 |
} break;
|
|
175 |
case WE_CLICK: {
|
|
176 |
switch(e->click.widget) {
|
|
177 |
case 2: {
|
|
178 |
uint y = (e->click.pt.y - 15) / 10;
|
|
179 |
uint16 p;
|
|
180 |
|
|
181 |
if (!IS_INT_INSIDE(y, 0, 12)) { return;}
|
|
182 |
|
|
183 |
// get the p-th OUR station from globally sorted list
|
|
184 |
p = y + w->vscroll.pos;
|
|
185 |
p += (w->window_number == 0) ? 0 : _num_station_sort[w->window_number-1]; // get offset of first station in list
|
|
186 |
if (p < _num_station_sort[w->window_number]) {
|
|
187 |
ScrollMainWindowToTile(DEREF_STATION(_station_sort[p].index)->xy);
|
|
188 |
}
|
|
189 |
} break;
|
|
190 |
}
|
|
191 |
} break;
|
|
192 |
|
|
193 |
case WE_4:
|
|
194 |
WP(w,plstations_d).refresh_counter++;
|
|
195 |
if (WP(w,plstations_d).refresh_counter==5) {
|
|
196 |
WP(w,plstations_d).refresh_counter = 0;
|
|
197 |
SetWindowDirty(w);
|
|
198 |
}
|
|
199 |
break;
|
|
200 |
}
|
|
201 |
}
|
|
202 |
|
|
203 |
static const Widget _player_stations_widgets[] = {
|
|
204 |
{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
|
205 |
{ WWT_CAPTION, 14, 11, 357, 0, 13, STR_3048_STATIONS, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
|
206 |
{ WWT_PANEL, 14, 0, 346, 14, 137, 0x0, STR_3057_STATION_NAMES_CLICK_ON},
|
|
207 |
{ WWT_SCROLLBAR, 14, 347, 357, 14, 137, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
|
|
208 |
{ WWT_LAST},
|
|
209 |
};
|
|
210 |
|
|
211 |
static const WindowDesc _player_stations_desc = {
|
|
212 |
-1, -1, 358, 138,
|
|
213 |
WC_STATION_LIST,0,
|
|
214 |
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
|
|
215 |
_player_stations_widgets,
|
|
216 |
PlayerStationsWndProc
|
|
217 |
};
|
|
218 |
|
|
219 |
|
|
220 |
void ShowPlayerStations(int player)
|
|
221 |
{
|
|
222 |
Window *w;
|
|
223 |
|
|
224 |
w = AllocateWindowDescFront(&_player_stations_desc, player);
|
|
225 |
if (w) {
|
|
226 |
w->caption_color = (byte)w->window_number;
|
|
227 |
w->vscroll.cap = 12;
|
|
228 |
}
|
|
229 |
}
|
|
230 |
|
|
231 |
static const Widget _station_view_expanded_widgets[] = {
|
|
232 |
{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
|
233 |
{ WWT_CAPTION, 14, 11, 248, 0, 13, STR_300A_0, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
|
234 |
{ WWT_IMGBTN, 14, 0, 237, 14, 65, 0x0, 0},
|
|
235 |
{ WWT_SCROLLBAR, 14, 238, 248, 14, 65, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
|
|
236 |
{ WWT_EMPTY, 0, 0, 0, 0, 0, 0x0, 0},
|
|
237 |
{ WWT_IMGBTN, 14, 0, 248, 66, 197, 0x0, 0},
|
|
238 |
{ WWT_PUSHTXTBTN, 14, 0, 82, 198, 209, STR_00E4_LOCATION, STR_3053_CENTER_MAIN_VIEW_ON_STATION},
|
|
239 |
{ WWT_PUSHTXTBTN, 14, 83, 165, 198, 209, STR_3033_ACCEPTS, STR_3056_SHOW_LIST_OF_ACCEPTED_CARGO},
|
|
240 |
{ WWT_PUSHTXTBTN, 14, 166, 248, 198, 209, STR_0130_RENAME, STR_3055_CHANGE_NAME_OF_STATION},
|
|
241 |
{ WWT_LAST},
|
|
242 |
};
|
|
243 |
|
|
244 |
static const Widget _station_view_widgets[] = {
|
|
245 |
{ WWT_TEXTBTN, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
|
246 |
{ WWT_CAPTION, 14, 11, 248, 0, 13, STR_300A_0, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
|
247 |
{ WWT_IMGBTN, 14, 0, 237, 14, 65, 0x0, 0},
|
|
248 |
{ WWT_SCROLLBAR, 14, 238, 248, 14, 65, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
|
|
249 |
{ WWT_IMGBTN, 14, 0, 248, 66, 97, 0x0, 0},
|
|
250 |
{ WWT_EMPTY, 0, 0, 0, 0, 0, 0x0, 0},
|
|
251 |
{ WWT_PUSHTXTBTN, 14, 0, 82, 98, 109, STR_00E4_LOCATION, STR_3053_CENTER_MAIN_VIEW_ON_STATION},
|
|
252 |
{ WWT_PUSHTXTBTN, 14, 83, 165, 98, 109, STR_3032_RATINGS, STR_3054_SHOW_STATION_RATINGS},
|
|
253 |
{ WWT_PUSHTXTBTN, 14, 166, 248, 98, 109, STR_0130_RENAME, STR_3055_CHANGE_NAME_OF_STATION},
|
|
254 |
{ WWT_LAST},
|
|
255 |
};
|
|
256 |
|
|
257 |
static void DrawStationViewWindow(Window *w)
|
|
258 |
{
|
|
259 |
Station *st;
|
|
260 |
int i;
|
|
261 |
int num;
|
|
262 |
int x,y;
|
|
263 |
int pos;
|
|
264 |
StringID str;
|
|
265 |
byte station_id;
|
|
266 |
byte *b;
|
|
267 |
|
|
268 |
|
|
269 |
station_id = (byte)w->window_number;
|
|
270 |
|
|
271 |
st = DEREF_STATION(w->window_number);
|
|
272 |
|
|
273 |
num = 1;
|
|
274 |
for(i=0; i!=NUM_CARGO; i++) {
|
|
275 |
if ((st->goods[i].waiting_acceptance & 0xFFF) != 0) {
|
|
276 |
num++;
|
|
277 |
if (st->goods[i].enroute_from != station_id)
|
|
278 |
num++;
|
|
279 |
}
|
|
280 |
}
|
|
281 |
SetVScrollCount(w, num);
|
|
282 |
|
|
283 |
w->disabled_state = st->owner == _local_player ? 0 : (1 << 8);
|
|
284 |
SET_DPARAM16(0, st->index);
|
|
285 |
SET_DPARAM8(1, st->facilities);
|
|
286 |
DrawWindowWidgets(w);
|
|
287 |
|
|
288 |
x = 2;
|
|
289 |
y = 15;
|
|
290 |
pos = w->vscroll.pos;
|
|
291 |
|
|
292 |
if (--pos < 0) {
|
|
293 |
str = STR_00D0_NOTHING;
|
|
294 |
for(i=0; i!=NUM_CARGO; i++)
|
|
295 |
if (st->goods[i].waiting_acceptance & 0xFFF)
|
|
296 |
str = STR_EMPTY;
|
|
297 |
SET_DPARAM16(0, str);
|
|
298 |
DrawString(x, y, STR_0008_WAITING, 0);
|
|
299 |
y += 10;
|
|
300 |
}
|
|
301 |
|
|
302 |
i = 0;
|
|
303 |
do {
|
|
304 |
uint waiting = (st->goods[i].waiting_acceptance & 0xFFF);
|
|
305 |
if (waiting == 0)
|
|
306 |
continue;
|
|
307 |
|
|
308 |
num = (waiting + 5) / 10;
|
|
309 |
if (num != 0) {
|
|
310 |
int cur_x = x;
|
|
311 |
num = min(num, 23);
|
|
312 |
do {
|
|
313 |
DrawSprite(_cargoc.sprites[i], cur_x, y);
|
|
314 |
cur_x += 10;
|
|
315 |
} while (--num);
|
|
316 |
}
|
|
317 |
|
|
318 |
if ( st->goods[i].enroute_from == station_id) {
|
|
319 |
if (--pos < 0) {
|
|
320 |
SET_DPARAM16(1, waiting);
|
|
321 |
SET_DPARAM16(0, _cargoc.names_long_s[i] + (waiting==1 ? 0 : 32));
|
|
322 |
DrawStringRightAligned(x + 234, y, STR_0009, 0);
|
|
323 |
y += 10;
|
|
324 |
}
|
|
325 |
} else {
|
|
326 |
/* enroute */
|
|
327 |
if (--pos < 0) {
|
|
328 |
SET_DPARAM16(1, waiting);
|
|
329 |
SET_DPARAM16(0, _cargoc.names_long_s[i] + (waiting==1 ? 0 : 32));
|
|
330 |
DrawStringRightAligned(x + 234, y, STR_000A_EN_ROUTE_FROM, 0);
|
|
331 |
y += 10;
|
|
332 |
}
|
|
333 |
|
|
334 |
if (pos > -5 && --pos < 0) {
|
|
335 |
SET_DPARAM16(0, st->goods[i].enroute_from);
|
|
336 |
DrawStringRightAligned(x + 234, y, STR_000B, 0);
|
|
337 |
y += 10;
|
|
338 |
}
|
|
339 |
}
|
|
340 |
} while (pos > -5 && ++i != 12);
|
|
341 |
|
|
342 |
if (w->widget == _station_view_widgets) {
|
|
343 |
b = _userstring;
|
|
344 |
b[0] = 0x81;
|
|
345 |
b[1] = STR_000C_ACCEPTS;
|
|
346 |
b[2] = STR_000C_ACCEPTS >> 8;
|
|
347 |
b += 3;
|
|
348 |
|
|
349 |
for(i=0; i!=NUM_CARGO; i++) {
|
|
350 |
if (st->goods[i].waiting_acceptance & 0x8000) {
|
|
351 |
b[0] = 0x81;
|
|
352 |
WRITE_LE_UINT16(b+1, _cargoc.names_s[i]);
|
|
353 |
WRITE_LE_UINT16(b+3, 0x202C);
|
|
354 |
b += 5;
|
|
355 |
}
|
|
356 |
}
|
|
357 |
|
|
358 |
if (b == (byte*)&_userstring[3]) {
|
|
359 |
b[0] = 0x81;
|
|
360 |
b[1] = STR_00D0_NOTHING;
|
|
361 |
b[2] = STR_00D0_NOTHING >> 8;
|
|
362 |
b[3] = 0;
|
|
363 |
} else {
|
|
364 |
b[-2] = 0;
|
|
365 |
}
|
|
366 |
|
|
367 |
DrawStringMultiLine(2, 67, STR_SPEC_USERSTRING, 245);
|
|
368 |
} else {
|
|
369 |
|
|
370 |
DrawString(2, 67, STR_3034_LOCAL_RATING_OF_TRANSPORT, 0);
|
|
371 |
|
|
372 |
y = 77;
|
|
373 |
for(i=0; i!=NUM_CARGO; i++) {
|
|
374 |
if (st->goods[i].enroute_from != 0xFF) {
|
|
375 |
SET_DPARAM16(0, _cargoc.names_s[i]);
|
|
376 |
SET_DPARAM8(2, st->goods[i].rating * 101 >> 8);
|
|
377 |
SET_DPARAM16(1, STR_3035_APPALLING + (st->goods[i].rating >> 5));
|
|
378 |
DrawString(8, y, STR_303D, 0);
|
|
379 |
y += 10;
|
|
380 |
}
|
|
381 |
}
|
|
382 |
}
|
|
383 |
}
|
|
384 |
|
|
385 |
|
|
386 |
static void StationViewWndProc(Window *w, WindowEvent *e)
|
|
387 |
{
|
|
388 |
switch(e->event) {
|
|
389 |
case WE_PAINT:
|
|
390 |
DrawStationViewWindow(w);
|
|
391 |
break;
|
|
392 |
|
|
393 |
case WE_CLICK:
|
|
394 |
switch(e->click.widget) {
|
|
395 |
case 6:
|
|
396 |
ScrollMainWindowToTile(DEREF_STATION(w->window_number)->xy);
|
|
397 |
break;
|
|
398 |
|
|
399 |
case 7:
|
|
400 |
SetWindowDirty(w);
|
|
401 |
|
|
402 |
/* toggle height/widget set */
|
|
403 |
w->height ^= (210 ^ 110);
|
|
404 |
*(uint32*)&w->widget ^= (uint32)_station_view_expanded_widgets ^ (uint32)_station_view_widgets;
|
|
405 |
|
|
406 |
SetWindowDirty(w);
|
|
407 |
break;
|
|
408 |
|
|
409 |
case 8: {
|
|
410 |
Station *st = DEREF_STATION(w->window_number);
|
|
411 |
SET_DPARAM16(0, st->town->townnametype);
|
|
412 |
SET_DPARAM32(1, st->town->townnameparts);
|
|
413 |
ShowQueryString(st->string_id, STR_3030_RENAME_STATION_LOADING, 31, 180, w->window_class, w->window_number);
|
|
414 |
} break;
|
|
415 |
}
|
|
416 |
break;
|
|
417 |
|
|
418 |
case WE_ON_EDIT_TEXT: {
|
|
419 |
Station *st;
|
|
420 |
byte *b = e->edittext.str;
|
|
421 |
if (*b == 0)
|
|
422 |
return;
|
|
423 |
memcpy(_decode_parameters, b, 32);
|
|
424 |
|
|
425 |
st = DEREF_STATION(w->window_number);
|
|
426 |
DoCommandP(st->xy, w->window_number, 0, NULL, CMD_RENAME_STATION | CMD_MSG(STR_3031_CAN_T_RENAME_STATION));
|
|
427 |
} break;
|
|
428 |
}
|
|
429 |
}
|
|
430 |
|
|
431 |
|
|
432 |
static const WindowDesc _station_view_desc = {
|
|
433 |
-1, -1, 249, 110,
|
|
434 |
WC_STATION_VIEW,0,
|
|
435 |
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
|
|
436 |
_station_view_widgets,
|
|
437 |
StationViewWndProc
|
|
438 |
};
|
|
439 |
|
|
440 |
void ShowStationViewWindow(int station)
|
|
441 |
{
|
|
442 |
Window *w;
|
|
443 |
byte color;
|
|
444 |
|
|
445 |
w = AllocateWindowDescFront(&_station_view_desc, station);
|
|
446 |
if (w) {
|
|
447 |
color = DEREF_STATION(w->window_number)->owner;
|
|
448 |
if (color != 0x10)
|
|
449 |
w->caption_color = color;
|
|
450 |
w->vscroll.cap = 5;
|
|
451 |
}
|
|
452 |
}
|