159 { WWT_PUSHTXTBTN, RESIZE_NONE, 14, 0, 139, 48, 59, STR_7029_BORROW, STR_7035_INCREASE_SIZE_OF_LOAN}, |
146 { WWT_PUSHTXTBTN, RESIZE_NONE, 14, 0, 139, 48, 59, STR_7029_BORROW, STR_7035_INCREASE_SIZE_OF_LOAN}, |
160 { WWT_PUSHTXTBTN, RESIZE_NONE, 14, 140, 279, 48, 59, STR_702A_REPAY, STR_7036_REPAY_PART_OF_LOAN}, |
147 { WWT_PUSHTXTBTN, RESIZE_NONE, 14, 140, 279, 48, 59, STR_702A_REPAY, STR_7036_REPAY_PART_OF_LOAN}, |
161 { WIDGETS_END}, |
148 { WIDGETS_END}, |
162 }; |
149 }; |
163 |
150 |
164 |
151 struct PlayerFinancesWindow : Window { |
165 static void PlayerFinancesWndProc(Window *w, WindowEvent *e) |
152 bool small; |
166 { |
153 |
167 switch (e->event) { |
154 PlayerFinancesWindow(const WindowDesc *desc, PlayerID player, bool show_small, |
168 case WE_PAINT: { |
155 bool show_stickied, int top, int left) : |
169 PlayerID player = (PlayerID)w->window_number; |
156 Window(desc, player), |
170 const Player *p = GetPlayer(player); |
157 small(show_small) |
171 |
158 { |
172 /* Recheck the size of the window as it might need to be resized due to the local player changing */ |
159 this->caption_color = this->window_number; |
173 int new_height = ((player != _local_player) ? 0 : 12) + ((WP(w, def_d).data_1 != 0) ? 48 : 74 + 10 * EXPENSES_END); |
160 |
174 if (w->height != new_height) { |
161 if (show_stickied) this->flags4 |= WF_STICKY; |
175 /* Make window dirty before and after resizing */ |
162 |
176 w->SetDirty(); |
163 /* Check if repositioning from default is required */ |
177 w->height = new_height; |
164 if (top != FIRST_GUI_CALL && left != FIRST_GUI_CALL) { |
178 w->SetDirty(); |
165 this->top = top; |
179 |
166 this->left = left; |
180 w->SetWidgetHiddenState(PFW_WIDGET_INCREASE_LOAN, player != _local_player); |
167 } |
181 w->SetWidgetHiddenState(PFW_WIDGET_REPAY_LOAN, player != _local_player); |
168 } |
182 } |
169 |
183 |
170 virtual void OnPaint() |
184 /* Borrow button only shows when there is any more money to loan */ |
171 { |
185 w->SetWidgetDisabledState(PFW_WIDGET_INCREASE_LOAN, p->current_loan == _economy.max_loan); |
172 PlayerID player = (PlayerID)this->window_number; |
186 |
173 const Player *p = GetPlayer(player); |
187 /* Repay button only shows when there is any more money to repay */ |
174 |
188 w->SetWidgetDisabledState(PFW_WIDGET_REPAY_LOAN, player != _local_player || p->current_loan == 0); |
175 /* Recheck the size of the window as it might need to be resized due to the local player changing */ |
189 |
176 int new_height = ((player != _local_player) ? 0 : 12) + ((this->small != 0) ? 48 : 74 + 10 * EXPENSES_END); |
190 SetDParam(0, p->index); |
177 if (this->height != new_height) { |
191 SetDParam(1, p->index); |
178 /* Make window dirty before and after resizing */ |
192 SetDParam(2, LOAN_INTERVAL); |
179 this->SetDirty(); |
193 DrawWindowWidgets(w); |
180 this->height = new_height; |
194 |
181 this->SetDirty(); |
195 DrawPlayerEconomyStats(p, (byte)WP(w, def_d).data_1); |
182 |
196 } break; |
183 this->SetWidgetHiddenState(PFW_WIDGET_INCREASE_LOAN, player != _local_player); |
197 |
184 this->SetWidgetHiddenState(PFW_WIDGET_REPAY_LOAN, player != _local_player); |
198 case WE_CLICK: |
185 } |
199 switch (e->we.click.widget) { |
186 |
200 case PFW_WIDGET_TOGGLE_SIZE: {/* toggle size */ |
187 /* Borrow button only shows when there is any more money to loan */ |
201 byte mode = (byte)WP(w, def_d).data_1; |
188 this->SetWidgetDisabledState(PFW_WIDGET_INCREASE_LOAN, p->current_loan == _economy.max_loan); |
202 bool stickied = !!(w->flags4 & WF_STICKY); |
189 |
203 int oldtop = w->top; ///< current top position of the window before closing it |
190 /* Repay button only shows when there is any more money to repay */ |
204 int oldleft = w->left; ///< current left position of the window before closing it |
191 this->SetWidgetDisabledState(PFW_WIDGET_REPAY_LOAN, player != _local_player || p->current_loan == 0); |
205 PlayerID player = (PlayerID)w->window_number; |
192 |
206 |
193 SetDParam(0, p->index); |
207 delete w; |
194 SetDParam(1, p->index); |
208 /* Open up the (toggled size) Finance window at the same position as the previous */ |
195 SetDParam(2, LOAN_INTERVAL); |
209 DoShowPlayerFinances(player, !HasBit(mode, 0), stickied, oldtop, oldleft); |
196 this->DrawWidgets(); |
210 } |
197 |
211 break; |
198 DrawPlayerEconomyStats(p, this->small); |
212 |
199 } |
213 case PFW_WIDGET_INCREASE_LOAN: /* increase loan */ |
200 |
214 DoCommandP(0, 0, _ctrl_pressed, NULL, CMD_INCREASE_LOAN | CMD_MSG(STR_702C_CAN_T_BORROW_ANY_MORE_MONEY)); |
201 virtual void OnClick(Point pt, int widget) |
215 break; |
202 { |
216 |
203 switch (widget) { |
217 case PFW_WIDGET_REPAY_LOAN: /* repay loan */ |
204 case PFW_WIDGET_TOGGLE_SIZE: {/* toggle size */ |
218 DoCommandP(0, 0, _ctrl_pressed, NULL, CMD_DECREASE_LOAN | CMD_MSG(STR_702F_CAN_T_REPAY_LOAN)); |
205 bool new_mode = !this->small; |
219 break; |
206 bool stickied = !!(this->flags4 & WF_STICKY); |
|
207 int oldtop = this->top; ///< current top position of the window before closing it |
|
208 int oldleft = this->left; ///< current left position of the window before closing it |
|
209 PlayerID player = (PlayerID)this->window_number; |
|
210 |
|
211 delete this; |
|
212 /* Open up the (toggled size) Finance window at the same position as the previous */ |
|
213 DoShowPlayerFinances(player, new_mode, stickied, oldtop, oldleft); |
220 } |
214 } |
221 break; |
215 break; |
222 } |
216 |
223 } |
217 case PFW_WIDGET_INCREASE_LOAN: /* increase loan */ |
|
218 DoCommandP(0, 0, _ctrl_pressed, NULL, CMD_INCREASE_LOAN | CMD_MSG(STR_702C_CAN_T_BORROW_ANY_MORE_MONEY)); |
|
219 break; |
|
220 |
|
221 case PFW_WIDGET_REPAY_LOAN: /* repay loan */ |
|
222 DoCommandP(0, 0, _ctrl_pressed, NULL, CMD_DECREASE_LOAN | CMD_MSG(STR_702F_CAN_T_REPAY_LOAN)); |
|
223 break; |
|
224 } |
|
225 } |
|
226 }; |
224 |
227 |
225 static const WindowDesc _player_finances_desc = { |
228 static const WindowDesc _player_finances_desc = { |
226 WDP_AUTO, WDP_AUTO, 407, 86 + 10 * EXPENSES_END, 407, 86 + 10 * EXPENSES_END, |
229 WDP_AUTO, WDP_AUTO, 407, 86 + 10 * EXPENSES_END, 407, 86 + 10 * EXPENSES_END, |
227 WC_FINANCES, WC_NONE, |
230 WC_FINANCES, WC_NONE, |
228 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON, |
231 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON, |
229 _player_finances_widgets, |
232 _player_finances_widgets, |
230 PlayerFinancesWndProc |
|
231 }; |
233 }; |
232 |
234 |
233 static const WindowDesc _player_finances_small_desc = { |
235 static const WindowDesc _player_finances_small_desc = { |
234 WDP_AUTO, WDP_AUTO, 280, 60, 280, 60, |
236 WDP_AUTO, WDP_AUTO, 280, 60, 280, 60, |
235 WC_FINANCES, WC_NONE, |
237 WC_FINANCES, WC_NONE, |
236 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON, |
238 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON, |
237 _player_finances_small_widgets, |
239 _player_finances_small_widgets, |
238 PlayerFinancesWndProc |
|
239 }; |
240 }; |
240 |
241 |
241 /** |
242 /** |
242 * Open the small/large finance window of the player |
243 * Open the small/large finance window of the player |
243 * |
244 * |
352 DrawSprite(SPR_VEH_BUS_SIDE_VIEW, PALETTE_RECOLOR_START + this->result, x + 16, y + 7); |
314 DrawSprite(SPR_VEH_BUS_SIDE_VIEW, PALETTE_RECOLOR_START + this->result, x + 16, y + 7); |
353 DrawStringTruncated(x + 32, y + 3, this->String(), sel ? TC_WHITE : TC_BLACK, x + width - 30); |
315 DrawStringTruncated(x + 32, y + 3, this->String(), sel ? TC_WHITE : TC_BLACK, x + width - 30); |
354 } |
316 } |
355 }; |
317 }; |
356 |
318 |
357 static void ShowColourDropDownMenu(Window *w, uint32 widget) |
319 struct SelectPlayerLiveryWindow : public Window { |
358 { |
320 private: |
359 uint32 used_colours = 0; |
321 uint32 sel; |
360 const Livery *livery; |
322 LiveryClass livery_class; |
361 LiveryScheme scheme; |
323 |
362 |
324 enum PlayerLiveryWindowWidgets { |
363 /* Disallow other player colours for the primary colour */ |
325 PLW_WIDGET_CLOSE, |
364 if (HasBit(WP(w, livery_d).sel, LS_DEFAULT) && widget == PLW_WIDGET_PRI_COL_DROPDOWN) { |
326 PLW_WIDGET_CAPTION, |
365 const Player *p; |
327 PLW_WIDGET_CLASS_GENERAL, |
366 FOR_ALL_PLAYERS(p) { |
328 PLW_WIDGET_CLASS_RAIL, |
367 if (p->is_active && p->index != _local_player) SetBit(used_colours, p->player_color); |
329 PLW_WIDGET_CLASS_ROAD, |
368 } |
330 PLW_WIDGET_CLASS_SHIP, |
369 } |
331 PLW_WIDGET_CLASS_AIRCRAFT, |
370 |
332 PLW_WIDGET_SPACER_CLASS, |
371 /* Get the first selected livery to use as the default dropdown item */ |
333 PLW_WIDGET_SPACER_DROPDOWN, |
372 for (scheme = LS_BEGIN; scheme < LS_END; scheme++) { |
334 PLW_WIDGET_PRI_COL_DROPDOWN, |
373 if (HasBit(WP(w, livery_d).sel, scheme)) break; |
335 PLW_WIDGET_SEC_COL_DROPDOWN, |
374 } |
336 PLW_WIDGET_MATRIX, |
375 if (scheme == LS_END) scheme = LS_DEFAULT; |
337 }; |
376 livery = &GetPlayer((PlayerID)w->window_number)->livery[scheme]; |
338 |
377 |
339 void ShowColourDropDownMenu(uint32 widget) |
378 DropDownList *list = new DropDownList(); |
340 { |
379 for (uint i = 0; i < lengthof(_colour_dropdown); i++) { |
341 uint32 used_colours = 0; |
380 list->push_back(new DropDownListColourItem(i, HasBit(used_colours, i))); |
342 const Livery *livery; |
381 } |
343 LiveryScheme scheme; |
382 |
344 |
383 ShowDropDownList(w, list, widget == PLW_WIDGET_PRI_COL_DROPDOWN ? livery->colour1 : livery->colour2, widget); |
345 /* Disallow other player colours for the primary colour */ |
384 } |
346 if (HasBit(this->sel, LS_DEFAULT) && widget == PLW_WIDGET_PRI_COL_DROPDOWN) { |
385 |
347 const Player *p; |
386 static void SelectPlayerLiveryWndProc(Window *w, WindowEvent *e) |
348 FOR_ALL_PLAYERS(p) { |
387 { |
349 if (p->is_active && p->index != _local_player) SetBit(used_colours, p->player_color); |
388 switch (e->event) { |
|
389 case WE_CREATE: |
|
390 w->LowerWidget(WP(w, livery_d).livery_class + PLW_WIDGET_CLASS_GENERAL); |
|
391 if (!_loaded_newgrf_features.has_2CC) { |
|
392 w->HideWidget(PLW_WIDGET_SEC_COL_DROPDOWN); |
|
393 } |
350 } |
394 break; |
351 } |
395 |
352 |
396 case WE_PAINT: { |
353 /* Get the first selected livery to use as the default dropdown item */ |
397 const Player *p = GetPlayer((PlayerID)w->window_number); |
354 for (scheme = LS_BEGIN; scheme < LS_END; scheme++) { |
398 LiveryScheme scheme = LS_DEFAULT; |
355 if (HasBit(this->sel, scheme)) break; |
399 int y = 51; |
356 } |
400 |
357 if (scheme == LS_END) scheme = LS_DEFAULT; |
401 /* Disable dropdown controls if no scheme is selected */ |
358 livery = &GetPlayer((PlayerID)this->window_number)->livery[scheme]; |
402 w->SetWidgetDisabledState(PLW_WIDGET_PRI_COL_DROPDOWN, (WP(w, livery_d).sel == 0)); |
359 |
403 w->SetWidgetDisabledState(PLW_WIDGET_SEC_COL_DROPDOWN, (WP(w, livery_d).sel == 0)); |
360 DropDownList *list = new DropDownList(); |
404 |
361 for (uint i = 0; i < lengthof(_colour_dropdown); i++) { |
405 if (!(WP(w, livery_d).sel == 0)) { |
362 list->push_back(new DropDownListColourItem(i, HasBit(used_colours, i))); |
406 for (scheme = LS_BEGIN; scheme < LS_END; scheme++) { |
363 } |
407 if (HasBit(WP(w, livery_d).sel, scheme)) break; |
364 |
|
365 ShowDropDownList(this, list, widget == PLW_WIDGET_PRI_COL_DROPDOWN ? livery->colour1 : livery->colour2, widget); |
|
366 } |
|
367 |
|
368 public: |
|
369 SelectPlayerLiveryWindow(const WindowDesc *desc, PlayerID player) : Window(desc, player) |
|
370 { |
|
371 this->caption_color = player; |
|
372 this->livery_class = LC_OTHER; |
|
373 this->sel = 1; |
|
374 this->LowerWidget(PLW_WIDGET_CLASS_GENERAL); |
|
375 this->OnInvalidateData(_loaded_newgrf_features.has_2CC); |
|
376 this->FindWindowPlacementAndResize(desc); |
|
377 } |
|
378 |
|
379 virtual void OnPaint() |
|
380 { |
|
381 const Player *p = GetPlayer((PlayerID)this->window_number); |
|
382 LiveryScheme scheme = LS_DEFAULT; |
|
383 int y = 51; |
|
384 |
|
385 /* Disable dropdown controls if no scheme is selected */ |
|
386 this->SetWidgetDisabledState(PLW_WIDGET_PRI_COL_DROPDOWN, this->sel == 0); |
|
387 this->SetWidgetDisabledState(PLW_WIDGET_SEC_COL_DROPDOWN, this->sel == 0); |
|
388 |
|
389 if (this->sel != 0) { |
|
390 for (scheme = LS_BEGIN; scheme < LS_END; scheme++) { |
|
391 if (HasBit(this->sel, scheme)) break; |
|
392 } |
|
393 if (scheme == LS_END) scheme = LS_DEFAULT; |
|
394 } |
|
395 |
|
396 SetDParam(0, STR_00D1_DARK_BLUE + p->livery[scheme].colour1); |
|
397 SetDParam(1, STR_00D1_DARK_BLUE + p->livery[scheme].colour2); |
|
398 |
|
399 this->DrawWidgets(); |
|
400 |
|
401 for (scheme = LS_DEFAULT; scheme < LS_END; scheme++) { |
|
402 if (_livery_class[scheme] == this->livery_class) { |
|
403 bool sel = HasBit(this->sel, scheme) != 0; |
|
404 |
|
405 if (scheme != LS_DEFAULT) { |
|
406 DrawSprite(p->livery[scheme].in_use ? SPR_BOX_CHECKED : SPR_BOX_EMPTY, PAL_NONE, 2, y); |
408 } |
407 } |
409 if (scheme == LS_END) scheme = LS_DEFAULT; |
408 |
|
409 DrawString(15, y, STR_LIVERY_DEFAULT + scheme, sel ? TC_WHITE : TC_BLACK); |
|
410 |
|
411 DrawSprite(SPR_SQUARE, GENERAL_SPRITE_COLOR(p->livery[scheme].colour1), 152, y); |
|
412 DrawString(165, y, STR_00D1_DARK_BLUE + p->livery[scheme].colour1, sel ? TC_WHITE : TC_GOLD); |
|
413 |
|
414 if (!this->IsWidgetHidden(PLW_WIDGET_SEC_COL_DROPDOWN)) { |
|
415 DrawSprite(SPR_SQUARE, GENERAL_SPRITE_COLOR(p->livery[scheme].colour2), 277, y); |
|
416 DrawString(290, y, STR_00D1_DARK_BLUE + p->livery[scheme].colour2, sel ? TC_WHITE : TC_GOLD); |
|
417 } |
|
418 |
|
419 y += 14; |
410 } |
420 } |
411 |
421 } |
412 SetDParam(0, STR_00D1_DARK_BLUE + p->livery[scheme].colour1); |
422 } |
413 SetDParam(1, STR_00D1_DARK_BLUE + p->livery[scheme].colour2); |
423 |
414 |
424 virtual void OnClick(Point pt, int widget) |
415 DrawWindowWidgets(w); |
425 { |
416 |
426 /* Number of liveries in each class, used to determine the height of the livery window */ |
417 for (scheme = LS_DEFAULT; scheme < LS_END; scheme++) { |
427 static const byte livery_height[] = { |
418 if (livery_class[scheme] == WP(w, livery_d).livery_class) { |
428 1, |
419 bool sel = HasBit(WP(w, livery_d).sel, scheme) != 0; |
429 13, |
420 |
430 4, |
421 if (scheme != LS_DEFAULT) { |
431 2, |
422 DrawSprite(p->livery[scheme].in_use ? SPR_BOX_CHECKED : SPR_BOX_EMPTY, PAL_NONE, 2, y); |
432 3, |
|
433 }; |
|
434 |
|
435 switch (widget) { |
|
436 /* Livery Class buttons */ |
|
437 case PLW_WIDGET_CLASS_GENERAL: |
|
438 case PLW_WIDGET_CLASS_RAIL: |
|
439 case PLW_WIDGET_CLASS_ROAD: |
|
440 case PLW_WIDGET_CLASS_SHIP: |
|
441 case PLW_WIDGET_CLASS_AIRCRAFT: { |
|
442 LiveryScheme scheme; |
|
443 |
|
444 this->RaiseWidget(this->livery_class + PLW_WIDGET_CLASS_GENERAL); |
|
445 this->livery_class = (LiveryClass)(widget - PLW_WIDGET_CLASS_GENERAL); |
|
446 this->sel = 0; |
|
447 this->LowerWidget(this->livery_class + PLW_WIDGET_CLASS_GENERAL); |
|
448 |
|
449 /* Select the first item in the list */ |
|
450 for (scheme = LS_DEFAULT; scheme < LS_END; scheme++) { |
|
451 if (_livery_class[scheme] == this->livery_class) { |
|
452 this->sel = 1 << scheme; |
|
453 break; |
423 } |
454 } |
424 |
|
425 DrawString(15, y, STR_LIVERY_DEFAULT + scheme, sel ? TC_WHITE : TC_BLACK); |
|
426 |
|
427 DrawSprite(SPR_SQUARE, GENERAL_SPRITE_COLOR(p->livery[scheme].colour1), 152, y); |
|
428 DrawString(165, y, STR_00D1_DARK_BLUE + p->livery[scheme].colour1, sel ? TC_WHITE : TC_GOLD); |
|
429 |
|
430 if (_loaded_newgrf_features.has_2CC) { |
|
431 DrawSprite(SPR_SQUARE, GENERAL_SPRITE_COLOR(p->livery[scheme].colour2), 277, y); |
|
432 DrawString(290, y, STR_00D1_DARK_BLUE + p->livery[scheme].colour2, sel ? TC_WHITE : TC_GOLD); |
|
433 } |
|
434 |
|
435 y += 14; |
|
436 } |
455 } |
|
456 this->height = 49 + livery_height[this->livery_class] * 14; |
|
457 this->widget[PLW_WIDGET_MATRIX].bottom = this->height - 1; |
|
458 this->widget[PLW_WIDGET_MATRIX].data = livery_height[this->livery_class] << 8 | 1; |
|
459 MarkWholeScreenDirty(); |
|
460 break; |
437 } |
461 } |
438 break; |
462 |
439 } |
463 case PLW_WIDGET_PRI_COL_DROPDOWN: /* First colour dropdown */ |
440 |
464 ShowColourDropDownMenu(PLW_WIDGET_PRI_COL_DROPDOWN); |
441 case WE_CLICK: { |
465 break; |
442 switch (e->we.click.widget) { |
466 |
443 /* Livery Class buttons */ |
467 case PLW_WIDGET_SEC_COL_DROPDOWN: /* Second colour dropdown */ |
444 case PLW_WIDGET_CLASS_GENERAL: |
468 ShowColourDropDownMenu(PLW_WIDGET_SEC_COL_DROPDOWN); |
445 case PLW_WIDGET_CLASS_RAIL: |
469 break; |
446 case PLW_WIDGET_CLASS_ROAD: |
470 |
447 case PLW_WIDGET_CLASS_SHIP: |
471 case PLW_WIDGET_MATRIX: { |
448 case PLW_WIDGET_CLASS_AIRCRAFT: { |
472 LiveryScheme scheme; |
449 LiveryScheme scheme; |
473 LiveryScheme j = (LiveryScheme)((pt.y - 48) / 14); |
450 |
474 |
451 w->RaiseWidget(WP(w, livery_d).livery_class + PLW_WIDGET_CLASS_GENERAL); |
475 for (scheme = LS_BEGIN; scheme <= j; scheme++) { |
452 WP(w, livery_d).livery_class = (LiveryClass)(e->we.click.widget - PLW_WIDGET_CLASS_GENERAL); |
476 if (_livery_class[scheme] != this->livery_class) j++; |
453 WP(w, livery_d).sel = 0; |
477 if (scheme >= LS_END) return; |
454 w->LowerWidget(WP(w, livery_d).livery_class + PLW_WIDGET_CLASS_GENERAL); |
|
455 |
|
456 /* Select the first item in the list */ |
|
457 for (scheme = LS_DEFAULT; scheme < LS_END; scheme++) { |
|
458 if (livery_class[scheme] == WP(w, livery_d).livery_class) { |
|
459 WP(w, livery_d).sel = 1 << scheme; |
|
460 break; |
|
461 } |
|
462 } |
|
463 w->height = 49 + livery_height[WP(w, livery_d).livery_class] * 14; |
|
464 w->widget[PLW_WIDGET_MATRIX].bottom = w->height - 1; |
|
465 w->widget[PLW_WIDGET_MATRIX].data = livery_height[WP(w, livery_d).livery_class] << 8 | 1; |
|
466 MarkWholeScreenDirty(); |
|
467 break; |
|
468 } |
478 } |
469 |
479 if (j >= LS_END) return; |
470 case PLW_WIDGET_PRI_COL_DROPDOWN: /* First colour dropdown */ |
480 |
471 ShowColourDropDownMenu(w, PLW_WIDGET_PRI_COL_DROPDOWN); |
481 /* If clicking on the left edge, toggle using the livery */ |
472 break; |
482 if (pt.x < 10) { |
473 |
483 DoCommandP(0, j | (2 << 8), !GetPlayer((PlayerID)this->window_number)->livery[j].in_use, NULL, CMD_SET_PLAYER_COLOR); |
474 case PLW_WIDGET_SEC_COL_DROPDOWN: /* Second colour dropdown */ |
|
475 ShowColourDropDownMenu(w, PLW_WIDGET_SEC_COL_DROPDOWN); |
|
476 break; |
|
477 |
|
478 case PLW_WIDGET_MATRIX: { |
|
479 LiveryScheme scheme; |
|
480 LiveryScheme j = (LiveryScheme)((e->we.click.pt.y - 48) / 14); |
|
481 |
|
482 for (scheme = LS_BEGIN; scheme <= j; scheme++) { |
|
483 if (livery_class[scheme] != WP(w, livery_d).livery_class) j++; |
|
484 if (scheme >= LS_END) return; |
|
485 } |
|
486 if (j >= LS_END) return; |
|
487 |
|
488 /* If clicking on the left edge, toggle using the livery */ |
|
489 if (e->we.click.pt.x < 10) { |
|
490 DoCommandP(0, j | (2 << 8), !GetPlayer((PlayerID)w->window_number)->livery[j].in_use, NULL, CMD_SET_PLAYER_COLOR); |
|
491 } |
|
492 |
|
493 if (_ctrl_pressed) { |
|
494 ToggleBit(WP(w, livery_d).sel, j); |
|
495 } else { |
|
496 WP(w, livery_d).sel = 1 << j; |
|
497 } |
|
498 w->SetDirty(); |
|
499 break; |
|
500 } |
484 } |
|
485 |
|
486 if (_ctrl_pressed) { |
|
487 ToggleBit(this->sel, j); |
|
488 } else { |
|
489 this->sel = 1 << j; |
|
490 } |
|
491 this->SetDirty(); |
|
492 break; |
501 } |
493 } |
502 break; |
494 } |
503 } |
495 } |
504 |
496 |
505 case WE_DROPDOWN_SELECT: { |
497 virtual void OnDropdownSelect(int widget, int index) |
506 LiveryScheme scheme; |
498 { |
507 |
499 for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) { |
508 for (scheme = LS_DEFAULT; scheme < LS_END; scheme++) { |
500 if (HasBit(this->sel, scheme)) { |
509 if (HasBit(WP(w, livery_d).sel, scheme)) { |
501 DoCommandP(0, scheme | (widget == PLW_WIDGET_PRI_COL_DROPDOWN ? 0 : 256), index, NULL, CMD_SET_PLAYER_COLOR); |
510 DoCommandP(0, scheme | (e->we.dropdown.button == PLW_WIDGET_PRI_COL_DROPDOWN ? 0 : 256), e->we.dropdown.index, NULL, CMD_SET_PLAYER_COLOR); |
|
511 } |
|
512 } |
502 } |
513 break; |
503 } |
514 } |
504 } |
515 } |
505 |
516 } |
506 virtual void OnInvalidateData(int data = 0) |
517 |
507 { |
518 static const Widget _select_player_livery_2cc_widgets[] = { |
508 static bool has2cc = true; |
|
509 |
|
510 if (has2cc == !!data) return; |
|
511 |
|
512 has2cc = !!data; |
|
513 |
|
514 int r = this->widget[has2cc ? PLW_WIDGET_SEC_COL_DROPDOWN : PLW_WIDGET_PRI_COL_DROPDOWN].right; |
|
515 this->SetWidgetHiddenState(PLW_WIDGET_SEC_COL_DROPDOWN, !has2cc); |
|
516 this->widget[PLW_WIDGET_CAPTION].right = r; |
|
517 this->widget[PLW_WIDGET_SPACER_CLASS].right = r; |
|
518 this->widget[PLW_WIDGET_MATRIX].right = r; |
|
519 this->width = r + 1; |
|
520 } |
|
521 }; |
|
522 |
|
523 static const Widget _select_player_livery_widgets[] = { |
519 { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW }, |
524 { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW }, |
520 { WWT_CAPTION, RESIZE_NONE, 14, 11, 399, 0, 13, STR_7007_NEW_COLOR_SCHEME, STR_018C_WINDOW_TITLE_DRAG_THIS }, |
525 { WWT_CAPTION, RESIZE_NONE, 14, 11, 399, 0, 13, STR_7007_NEW_COLOR_SCHEME, STR_018C_WINDOW_TITLE_DRAG_THIS }, |
521 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 21, 14, 35, SPR_IMG_COMPANY_GENERAL, STR_LIVERY_GENERAL_TIP }, |
526 { WWT_IMGBTN, RESIZE_NONE, 14, 0, 21, 14, 35, SPR_IMG_COMPANY_GENERAL, STR_LIVERY_GENERAL_TIP }, |
522 { WWT_IMGBTN, RESIZE_NONE, 14, 22, 43, 14, 35, SPR_IMG_TRAINLIST, STR_LIVERY_TRAIN_TIP }, |
527 { WWT_IMGBTN, RESIZE_NONE, 14, 22, 43, 14, 35, SPR_IMG_TRAINLIST, STR_LIVERY_TRAIN_TIP }, |
523 { WWT_IMGBTN, RESIZE_NONE, 14, 44, 65, 14, 35, SPR_IMG_TRUCKLIST, STR_LIVERY_ROADVEH_TIP }, |
528 { WWT_IMGBTN, RESIZE_NONE, 14, 44, 65, 14, 35, SPR_IMG_TRUCKLIST, STR_LIVERY_ROADVEH_TIP }, |
729 { WWT_PUSHTXTBTN, RESIZE_NONE, 14, 184, 208, 122, 133, STR_EMPTY, STR_FACE_GLASSES_TIP_2}, // PFW_WIDGET_GLASSES |
652 { WWT_PUSHTXTBTN, RESIZE_NONE, 14, 184, 208, 122, 133, STR_EMPTY, STR_FACE_GLASSES_TIP_2}, // PFW_WIDGET_GLASSES |
730 { WWT_PUSHIMGBTN, RESIZE_NONE, 14, 209, 217, 122, 133, SPR_ARROW_RIGHT, STR_FACE_GLASSES_TIP_2}, // PFW_WIDGET_GLASSES_R |
653 { WWT_PUSHIMGBTN, RESIZE_NONE, 14, 209, 217, 122, 133, SPR_ARROW_RIGHT, STR_FACE_GLASSES_TIP_2}, // PFW_WIDGET_GLASSES_R |
731 { WIDGETS_END}, |
654 { WIDGETS_END}, |
732 }; |
655 }; |
733 |
656 |
734 /** |
657 class SelectPlayerFaceWindow : public Window |
735 * Draw dynamic a label to the left of the button and a value in the button |
|
736 * |
|
737 * @param w Window on which the widget is located |
|
738 * @param widget_index index of this widget in the window |
|
739 * @param str the label which will be draw |
|
740 * @param val the value which will be draw |
|
741 * @param is_bool_widget is it a bool button |
|
742 */ |
|
743 void DrawFaceStringLabel(const Window *w, byte widget_index, StringID str, uint8 val, bool is_bool_widget) |
|
744 { |
658 { |
745 /* Write the label in gold (0x2) to the left of the button. */ |
659 PlayerFace face; // player face bits |
746 DrawStringRightAligned(w->widget[widget_index].left - (is_bool_widget ? 5 : 14), w->widget[widget_index].top + 1, str, TC_GOLD); |
660 bool advanced; // advance player face selection window |
747 |
661 |
748 if (!w->IsWidgetDisabled(widget_index)) { |
662 GenderEthnicity ge; |
749 if (is_bool_widget) { |
663 bool is_female; |
750 /* if it a bool button write yes or no */ |
664 bool is_moust_male; |
751 str = (val != 0) ? STR_FACE_YES : STR_FACE_NO; |
665 |
|
666 /** |
|
667 * Names of the widgets. Keep them in the same order as in the widget array. |
|
668 * Do not change the order of the widgets from PFW_WIDGET_HAS_MOUSTACHE_EARRING to PFW_WIDGET_GLASSES_R, |
|
669 * this order is needed for the WE_CLICK event of DrawFaceStringLabel(). |
|
670 */ |
|
671 enum PlayerFaceWindowWidgets { |
|
672 PFW_WIDGET_CLOSEBOX = 0, |
|
673 PFW_WIDGET_CAPTION, |
|
674 PFW_WIDGET_TOGGLE_LARGE_SMALL, |
|
675 PFW_WIDGET_SELECT_FACE, |
|
676 PFW_WIDGET_CANCEL, |
|
677 PFW_WIDGET_ACCEPT, |
|
678 PFW_WIDGET_MALE, |
|
679 PFW_WIDGET_FEMALE, |
|
680 PFW_WIDGET_RANDOM_NEW_FACE, |
|
681 PFW_WIDGET_TOGGLE_LARGE_SMALL_BUTTON, |
|
682 /* from here is the advanced player face selection window */ |
|
683 PFW_WIDGET_LOAD, |
|
684 PFW_WIDGET_FACECODE, |
|
685 PFW_WIDGET_SAVE, |
|
686 PFW_WIDGET_ETHNICITY_EUR, |
|
687 PFW_WIDGET_ETHNICITY_AFR, |
|
688 PFW_WIDGET_HAS_MOUSTACHE_EARRING, |
|
689 PFW_WIDGET_HAS_GLASSES, |
|
690 PFW_WIDGET_EYECOLOUR_L, |
|
691 PFW_WIDGET_EYECOLOUR, |
|
692 PFW_WIDGET_EYECOLOUR_R, |
|
693 PFW_WIDGET_CHIN_L, |
|
694 PFW_WIDGET_CHIN, |
|
695 PFW_WIDGET_CHIN_R, |
|
696 PFW_WIDGET_EYEBROWS_L, |
|
697 PFW_WIDGET_EYEBROWS, |
|
698 PFW_WIDGET_EYEBROWS_R, |
|
699 PFW_WIDGET_LIPS_MOUSTACHE_L, |
|
700 PFW_WIDGET_LIPS_MOUSTACHE, |
|
701 PFW_WIDGET_LIPS_MOUSTACHE_R, |
|
702 PFW_WIDGET_NOSE_L, |
|
703 PFW_WIDGET_NOSE, |
|
704 PFW_WIDGET_NOSE_R, |
|
705 PFW_WIDGET_HAIR_L, |
|
706 PFW_WIDGET_HAIR, |
|
707 PFW_WIDGET_HAIR_R, |
|
708 PFW_WIDGET_JACKET_L, |
|
709 PFW_WIDGET_JACKET, |
|
710 PFW_WIDGET_JACKET_R, |
|
711 PFW_WIDGET_COLLAR_L, |
|
712 PFW_WIDGET_COLLAR, |
|
713 PFW_WIDGET_COLLAR_R, |
|
714 PFW_WIDGET_TIE_EARRING_L, |
|
715 PFW_WIDGET_TIE_EARRING, |
|
716 PFW_WIDGET_TIE_EARRING_R, |
|
717 PFW_WIDGET_GLASSES_L, |
|
718 PFW_WIDGET_GLASSES, |
|
719 PFW_WIDGET_GLASSES_R, |
|
720 }; |
|
721 /** |
|
722 * Draw dynamic a label to the left of the button and a value in the button |
|
723 * |
|
724 * @param widget_index index of this widget in the window |
|
725 * @param str the label which will be draw |
|
726 * @param val the value which will be draw |
|
727 * @param is_bool_widget is it a bool button |
|
728 */ |
|
729 void DrawFaceStringLabel(byte widget_index, StringID str, uint8 val, bool is_bool_widget) |
|
730 { |
|
731 /* Write the label in gold (0x2) to the left of the button. */ |
|
732 DrawStringRightAligned(this->widget[widget_index].left - (is_bool_widget ? 5 : 14), this->widget[widget_index].top + 1, str, TC_GOLD); |
|
733 |
|
734 if (!this->IsWidgetDisabled(widget_index)) { |
|
735 if (is_bool_widget) { |
|
736 /* if it a bool button write yes or no */ |
|
737 str = (val != 0) ? STR_FACE_YES : STR_FACE_NO; |
|
738 } else { |
|
739 /* else write the value + 1 */ |
|
740 SetDParam(0, val + 1); |
|
741 str = STR_JUST_INT; |
|
742 } |
|
743 |
|
744 /* Draw the value/bool in white (0xC). If the button clicked adds 1px to x and y text coordinates (IsWindowWidgetLowered()). */ |
|
745 DrawStringCentered(this->widget[widget_index].left + (this->widget[widget_index].right - this->widget[widget_index].left) / 2 + |
|
746 this->IsWidgetLowered(widget_index), this->widget[widget_index].top + 1 + this->IsWidgetLowered(widget_index), str, TC_WHITE); |
|
747 } |
|
748 } |
|
749 |
|
750 void UpdateData() |
|
751 { |
|
752 this->ge = (GenderEthnicity)GB(this->face, _pf_info[PFV_GEN_ETHN].offset, _pf_info[PFV_GEN_ETHN].length); // get the gender and ethnicity |
|
753 this->is_female = HasBit(this->ge, GENDER_FEMALE); // get the gender: 0 == male and 1 == female |
|
754 this->is_moust_male = !is_female && GetPlayerFaceBits(this->face, PFV_HAS_MOUSTACHE, this->ge) != 0; // is a male face with moustache |
|
755 } |
|
756 |
|
757 public: |
|
758 SelectPlayerFaceWindow(const WindowDesc *desc, Window *parent, bool advanced) : Window(desc, parent->window_number) |
|
759 { |
|
760 this->parent = parent; |
|
761 this->FindWindowPlacementAndResize(desc); |
|
762 this->caption_color = this->window_number; |
|
763 this->face = GetPlayer((PlayerID)this->window_number)->face; |
|
764 this->advanced = advanced; |
|
765 |
|
766 this->UpdateData(); |
|
767 |
|
768 /* Check if repositioning from default is required */ |
|
769 if (top != FIRST_GUI_CALL && left != FIRST_GUI_CALL) { |
|
770 this->top = top; |
|
771 this->left = left; |
|
772 } |
|
773 } |
|
774 |
|
775 virtual void OnPaint() |
|
776 { |
|
777 /* lower the non-selected gender button */ |
|
778 this->SetWidgetLoweredState(PFW_WIDGET_MALE, !this->is_female); |
|
779 this->SetWidgetLoweredState(PFW_WIDGET_FEMALE, this->is_female); |
|
780 |
|
781 /* advanced player face selection window */ |
|
782 if (this->advanced) { |
|
783 /* lower the non-selected ethnicity button */ |
|
784 this->SetWidgetLoweredState(PFW_WIDGET_ETHNICITY_EUR, !HasBit(this->ge, ETHNICITY_BLACK)); |
|
785 this->SetWidgetLoweredState(PFW_WIDGET_ETHNICITY_AFR, HasBit(this->ge, ETHNICITY_BLACK)); |
|
786 |
|
787 |
|
788 /* Disable dynamically the widgets which PlayerFaceVariable has less than 2 options |
|
789 * (or in other words you haven't any choice). |
|
790 * If the widgets depend on a HAS-variable and this is false the widgets will be disabled, too. */ |
|
791 |
|
792 /* Eye colour buttons */ |
|
793 this->SetWidgetsDisabledState(_pf_info[PFV_EYE_COLOUR].valid_values[this->ge] < 2, |
|
794 PFW_WIDGET_EYECOLOUR, PFW_WIDGET_EYECOLOUR_L, PFW_WIDGET_EYECOLOUR_R, WIDGET_LIST_END); |
|
795 |
|
796 /* Chin buttons */ |
|
797 this->SetWidgetsDisabledState(_pf_info[PFV_CHIN].valid_values[this->ge] < 2, |
|
798 PFW_WIDGET_CHIN, PFW_WIDGET_CHIN_L, PFW_WIDGET_CHIN_R, WIDGET_LIST_END); |
|
799 |
|
800 /* Eyebrows buttons */ |
|
801 this->SetWidgetsDisabledState(_pf_info[PFV_EYEBROWS].valid_values[this->ge] < 2, |
|
802 PFW_WIDGET_EYEBROWS, PFW_WIDGET_EYEBROWS_L, PFW_WIDGET_EYEBROWS_R, WIDGET_LIST_END); |
|
803 |
|
804 /* Lips or (if it a male face with a moustache) moustache buttons */ |
|
805 this->SetWidgetsDisabledState(_pf_info[this->is_moust_male ? PFV_MOUSTACHE : PFV_LIPS].valid_values[this->ge] < 2, |
|
806 PFW_WIDGET_LIPS_MOUSTACHE, PFW_WIDGET_LIPS_MOUSTACHE_L, PFW_WIDGET_LIPS_MOUSTACHE_R, WIDGET_LIST_END); |
|
807 |
|
808 /* Nose buttons | male faces with moustache haven't any nose options */ |
|
809 this->SetWidgetsDisabledState(_pf_info[PFV_NOSE].valid_values[this->ge] < 2 || this->is_moust_male, |
|
810 PFW_WIDGET_NOSE, PFW_WIDGET_NOSE_L, PFW_WIDGET_NOSE_R, WIDGET_LIST_END); |
|
811 |
|
812 /* Hair buttons */ |
|
813 this->SetWidgetsDisabledState(_pf_info[PFV_HAIR].valid_values[this->ge] < 2, |
|
814 PFW_WIDGET_HAIR, PFW_WIDGET_HAIR_L, PFW_WIDGET_HAIR_R, WIDGET_LIST_END); |
|
815 |
|
816 /* Jacket buttons */ |
|
817 this->SetWidgetsDisabledState(_pf_info[PFV_JACKET].valid_values[this->ge] < 2, |
|
818 PFW_WIDGET_JACKET, PFW_WIDGET_JACKET_L, PFW_WIDGET_JACKET_R, WIDGET_LIST_END); |
|
819 |
|
820 /* Collar buttons */ |
|
821 this->SetWidgetsDisabledState(_pf_info[PFV_COLLAR].valid_values[this->ge] < 2, |
|
822 PFW_WIDGET_COLLAR, PFW_WIDGET_COLLAR_L, PFW_WIDGET_COLLAR_R, WIDGET_LIST_END); |
|
823 |
|
824 /* Tie/earring buttons | female faces without earring haven't any earring options */ |
|
825 this->SetWidgetsDisabledState(_pf_info[PFV_TIE_EARRING].valid_values[this->ge] < 2 || |
|
826 (this->is_female && GetPlayerFaceBits(this->face, PFV_HAS_TIE_EARRING, this->ge) == 0), |
|
827 PFW_WIDGET_TIE_EARRING, PFW_WIDGET_TIE_EARRING_L, PFW_WIDGET_TIE_EARRING_R, WIDGET_LIST_END); |
|
828 |
|
829 /* Glasses buttons | faces without glasses haven't any glasses options */ |
|
830 this->SetWidgetsDisabledState(_pf_info[PFV_GLASSES].valid_values[this->ge] < 2 || GetPlayerFaceBits(this->face, PFV_HAS_GLASSES, this->ge) == 0, |
|
831 PFW_WIDGET_GLASSES, PFW_WIDGET_GLASSES_L, PFW_WIDGET_GLASSES_R, WIDGET_LIST_END); |
|
832 } |
|
833 |
|
834 this->DrawWidgets(); |
|
835 |
|
836 /* Draw dynamic button value and labels for the advanced player face selection window */ |
|
837 if (this->advanced) { |
|
838 if (this->is_female) { |
|
839 /* Only for female faces */ |
|
840 this->DrawFaceStringLabel(PFW_WIDGET_HAS_MOUSTACHE_EARRING, STR_FACE_EARRING, GetPlayerFaceBits(this->face, PFV_HAS_TIE_EARRING, this->ge), true ); |
|
841 this->DrawFaceStringLabel(PFW_WIDGET_TIE_EARRING, STR_FACE_EARRING, GetPlayerFaceBits(this->face, PFV_TIE_EARRING, this->ge), false); |
|
842 } else { |
|
843 /* Only for male faces */ |
|
844 this->DrawFaceStringLabel(PFW_WIDGET_HAS_MOUSTACHE_EARRING, STR_FACE_MOUSTACHE, GetPlayerFaceBits(this->face, PFV_HAS_MOUSTACHE, this->ge), true ); |
|
845 this->DrawFaceStringLabel(PFW_WIDGET_TIE_EARRING, STR_FACE_TIE, GetPlayerFaceBits(this->face, PFV_TIE_EARRING, this->ge), false); |
|
846 } |
|
847 if (this->is_moust_male) { |
|
848 /* Only for male faces with moustache */ |
|
849 this->DrawFaceStringLabel(PFW_WIDGET_LIPS_MOUSTACHE, STR_FACE_MOUSTACHE, GetPlayerFaceBits(this->face, PFV_MOUSTACHE, this->ge), false); |
|
850 } else { |
|
851 /* Only for female faces or male faces without moustache */ |
|
852 this->DrawFaceStringLabel(PFW_WIDGET_LIPS_MOUSTACHE, STR_FACE_LIPS, GetPlayerFaceBits(this->face, PFV_LIPS, this->ge), false); |
|
853 } |
|
854 /* For all faces */ |
|
855 this->DrawFaceStringLabel(PFW_WIDGET_HAS_GLASSES, STR_FACE_GLASSES, GetPlayerFaceBits(this->face, PFV_HAS_GLASSES, this->ge), true ); |
|
856 this->DrawFaceStringLabel(PFW_WIDGET_HAIR, STR_FACE_HAIR, GetPlayerFaceBits(this->face, PFV_HAIR, this->ge), false); |
|
857 this->DrawFaceStringLabel(PFW_WIDGET_EYEBROWS, STR_FACE_EYEBROWS, GetPlayerFaceBits(this->face, PFV_EYEBROWS, this->ge), false); |
|
858 this->DrawFaceStringLabel(PFW_WIDGET_EYECOLOUR, STR_FACE_EYECOLOUR, GetPlayerFaceBits(this->face, PFV_EYE_COLOUR, this->ge), false); |
|
859 this->DrawFaceStringLabel(PFW_WIDGET_GLASSES, STR_FACE_GLASSES, GetPlayerFaceBits(this->face, PFV_GLASSES, this->ge), false); |
|
860 this->DrawFaceStringLabel(PFW_WIDGET_NOSE, STR_FACE_NOSE, GetPlayerFaceBits(this->face, PFV_NOSE, this->ge), false); |
|
861 this->DrawFaceStringLabel(PFW_WIDGET_CHIN, STR_FACE_CHIN, GetPlayerFaceBits(this->face, PFV_CHIN, this->ge), false); |
|
862 this->DrawFaceStringLabel(PFW_WIDGET_JACKET, STR_FACE_JACKET, GetPlayerFaceBits(this->face, PFV_JACKET, this->ge), false); |
|
863 this->DrawFaceStringLabel(PFW_WIDGET_COLLAR, STR_FACE_COLLAR, GetPlayerFaceBits(this->face, PFV_COLLAR, this->ge), false); |
|
864 } |
|
865 |
|
866 /* Draw the player face picture */ |
|
867 DrawPlayerFace(this->face, GetPlayer((PlayerID)this->window_number)->player_color, 2, 16); |
|
868 } |
|
869 |
|
870 virtual void OnClick(Point pt, int widget) |
|
871 { |
|
872 switch (widget) { |
|
873 /* Toggle size, advanced/simple face selection */ |
|
874 case PFW_WIDGET_TOGGLE_LARGE_SMALL: |
|
875 case PFW_WIDGET_TOGGLE_LARGE_SMALL_BUTTON: { |
|
876 DoCommandP(0, 0, this->face, NULL, CMD_SET_PLAYER_FACE); |
|
877 |
|
878 /* Backup some data before deletion */ |
|
879 int oldtop = this->top; ///< current top position of the window before closing it |
|
880 int oldleft = this->left; ///< current top position of the window before closing it |
|
881 bool adv = !this->advanced; |
|
882 Window *parent = this->parent; |
|
883 |
|
884 delete this; |
|
885 |
|
886 /* Open up the (toggled size) Face selection window at the same position as the previous */ |
|
887 DoSelectPlayerFace(parent, adv, oldtop, oldleft); |
|
888 } break; |
|
889 |
|
890 |
|
891 /* OK button */ |
|
892 case PFW_WIDGET_ACCEPT: |
|
893 DoCommandP(0, 0, this->face, NULL, CMD_SET_PLAYER_FACE); |
|
894 /* Fall-Through */ |
|
895 |
|
896 /* Cancel button */ |
|
897 case PFW_WIDGET_CANCEL: |
|
898 delete this; |
|
899 break; |
|
900 |
|
901 /* Load button */ |
|
902 case PFW_WIDGET_LOAD: |
|
903 this->face = _player_face; |
|
904 ScaleAllPlayerFaceBits(this->face); |
|
905 ShowErrorMessage(INVALID_STRING_ID, STR_FACE_LOAD_DONE, 0, 0); |
|
906 this->UpdateData(); |
|
907 this->SetDirty(); |
|
908 break; |
|
909 |
|
910 /* 'Player face number' button, view and/or set player face number */ |
|
911 case PFW_WIDGET_FACECODE: |
|
912 SetDParam(0, this->face); |
|
913 ShowQueryString(STR_JUST_INT, STR_FACE_FACECODE_CAPTION, 10 + 1, 0, this, CS_NUMERAL); |
|
914 break; |
|
915 |
|
916 /* Save button */ |
|
917 case PFW_WIDGET_SAVE: |
|
918 _player_face = this->face; |
|
919 ShowErrorMessage(INVALID_STRING_ID, STR_FACE_SAVE_DONE, 0, 0); |
|
920 break; |
|
921 |
|
922 /* Toggle gender (male/female) button */ |
|
923 case PFW_WIDGET_MALE: |
|
924 case PFW_WIDGET_FEMALE: |
|
925 SetPlayerFaceBits(this->face, PFV_GENDER, this->ge, widget - PFW_WIDGET_MALE); |
|
926 ScaleAllPlayerFaceBits(this->face); |
|
927 this->UpdateData(); |
|
928 this->SetDirty(); |
|
929 break; |
|
930 |
|
931 /* Randomize face button */ |
|
932 case PFW_WIDGET_RANDOM_NEW_FACE: |
|
933 RandomPlayerFaceBits(this->face, this->ge, this->advanced); |
|
934 this->UpdateData(); |
|
935 this->SetDirty(); |
|
936 break; |
|
937 |
|
938 /* Toggle ethnicity (european/african) button */ |
|
939 case PFW_WIDGET_ETHNICITY_EUR: |
|
940 case PFW_WIDGET_ETHNICITY_AFR: |
|
941 SetPlayerFaceBits(this->face, PFV_ETHNICITY, this->ge, widget - PFW_WIDGET_ETHNICITY_EUR); |
|
942 ScaleAllPlayerFaceBits(this->face); |
|
943 this->UpdateData(); |
|
944 this->SetDirty(); |
|
945 break; |
|
946 |
|
947 default: |
|
948 /* For all buttons from PFW_WIDGET_HAS_MOUSTACHE_EARRING to PFW_WIDGET_GLASSES_R is the same function. |
|
949 * Therefor is this combined function. |
|
950 * First it checks which PlayerFaceVariable will be change and then |
|
951 * a: invert the value for boolean variables |
|
952 * or b: it checks inside of IncreasePlayerFaceBits() if a left (_L) butten is pressed and then decrease else increase the variable */ |
|
953 if (this->advanced && widget >= PFW_WIDGET_HAS_MOUSTACHE_EARRING && widget <= PFW_WIDGET_GLASSES_R) { |
|
954 PlayerFaceVariable pfv; // which PlayerFaceVariable shall be edited |
|
955 |
|
956 if (widget < PFW_WIDGET_EYECOLOUR_L) { // Bool buttons |
|
957 switch (widget - PFW_WIDGET_HAS_MOUSTACHE_EARRING) { |
|
958 default: NOT_REACHED(); |
|
959 case 0: pfv = this->is_female ? PFV_HAS_TIE_EARRING : PFV_HAS_MOUSTACHE; break; // Has earring/moustache button |
|
960 case 1: pfv = PFV_HAS_GLASSES; break; // Has glasses button |
|
961 } |
|
962 SetPlayerFaceBits(this->face, pfv, this->ge, !GetPlayerFaceBits(this->face, pfv, this->ge)); |
|
963 ScaleAllPlayerFaceBits(this->face); |
|
964 } else { // Value buttons |
|
965 switch ((widget - PFW_WIDGET_EYECOLOUR_L) / 3) { |
|
966 default: NOT_REACHED(); |
|
967 case 0: pfv = PFV_EYE_COLOUR; break; // Eye colour buttons |
|
968 case 1: pfv = PFV_CHIN; break; // Chin buttons |
|
969 case 2: pfv = PFV_EYEBROWS; break; // Eyebrows buttons |
|
970 case 3: pfv = this->is_moust_male ? PFV_MOUSTACHE : PFV_LIPS; break; // Moustache or lips buttons |
|
971 case 4: pfv = PFV_NOSE; break; // Nose buttons |
|
972 case 5: pfv = PFV_HAIR; break; // Hair buttons |
|
973 case 6: pfv = PFV_JACKET; break; // Jacket buttons |
|
974 case 7: pfv = PFV_COLLAR; break; // Collar buttons |
|
975 case 8: pfv = PFV_TIE_EARRING; break; // Tie/earring buttons |
|
976 case 9: pfv = PFV_GLASSES; break; // Glasses buttons |
|
977 } |
|
978 /* 0 == left (_L), 1 == middle or 2 == right (_R) - button click */ |
|
979 IncreasePlayerFaceBits(this->face, pfv, this->ge, (((widget - PFW_WIDGET_EYECOLOUR_L) % 3) != 0) ? 1 : -1); |
|
980 } |
|
981 this->UpdateData(); |
|
982 this->SetDirty(); |
|
983 } |
|
984 break; |
|
985 } |
|
986 } |
|
987 |
|
988 virtual void OnQueryTextFinished(char *str) |
|
989 { |
|
990 if (str == NULL) return; |
|
991 /* Set a new player face number */ |
|
992 if (!StrEmpty(str)) { |
|
993 this->face = strtoul(str, NULL, 10); |
|
994 ScaleAllPlayerFaceBits(this->face); |
|
995 ShowErrorMessage(INVALID_STRING_ID, STR_FACE_FACECODE_SET, 0, 0); |
|
996 this->UpdateData(); |
|
997 this->SetDirty(); |
752 } else { |
998 } else { |
753 /* else write the value + 1 */ |
999 ShowErrorMessage(INVALID_STRING_ID, STR_FACE_FACECODE_ERR, 0, 0); |
754 SetDParam(0, val + 1); |
1000 } |
755 str = STR_JUST_INT; |
1001 } |
756 } |
1002 }; |
757 |
|
758 /* Draw the value/bool in white (0xC). If the button clicked adds 1px to x and y text coordinates (IsWindowWidgetLowered()). */ |
|
759 DrawStringCentered(w->widget[widget_index].left + (w->widget[widget_index].right - w->widget[widget_index].left) / 2 + |
|
760 w->IsWidgetLowered(widget_index), w->widget[widget_index].top + 1 + w->IsWidgetLowered(widget_index), str, TC_WHITE); |
|
761 } |
|
762 } |
|
763 |
|
764 /** |
|
765 * Player face selection window event definition |
|
766 * |
|
767 * @param w window pointer |
|
768 * @param e event been triggered |
|
769 */ |
|
770 static void SelectPlayerFaceWndProc(Window *w, WindowEvent *e) |
|
771 { |
|
772 PlayerFace *pf = &WP(w, facesel_d).face; // pointer to the player face bits |
|
773 GenderEthnicity ge = (GenderEthnicity)GB(*pf, _pf_info[PFV_GEN_ETHN].offset, _pf_info[PFV_GEN_ETHN].length); // get the gender and ethnicity |
|
774 bool is_female = HasBit(ge, GENDER_FEMALE); // get the gender: 0 == male and 1 == female |
|
775 bool is_moust_male = !is_female && GetPlayerFaceBits(*pf, PFV_HAS_MOUSTACHE, ge) != 0; // is a male face with moustache |
|
776 |
|
777 switch (e->event) { |
|
778 case WE_PAINT: |
|
779 /* lower the non-selected gender button */ |
|
780 w->SetWidgetLoweredState(PFW_WIDGET_MALE, !is_female); |
|
781 w->SetWidgetLoweredState(PFW_WIDGET_FEMALE, is_female); |
|
782 |
|
783 /* advanced player face selection window */ |
|
784 if (WP(w, facesel_d).advanced) { |
|
785 /* lower the non-selected ethnicity button */ |
|
786 w->SetWidgetLoweredState(PFW_WIDGET_ETHNICITY_EUR, !HasBit(ge, ETHNICITY_BLACK)); |
|
787 w->SetWidgetLoweredState(PFW_WIDGET_ETHNICITY_AFR, HasBit(ge, ETHNICITY_BLACK)); |
|
788 |
|
789 |
|
790 /* Disable dynamically the widgets which PlayerFaceVariable has less than 2 options |
|
791 * (or in other words you haven't any choice). |
|
792 * If the widgets depend on a HAS-variable and this is false the widgets will be disabled, too. */ |
|
793 |
|
794 /* Eye colour buttons */ |
|
795 w->SetWidgetsDisabledState(_pf_info[PFV_EYE_COLOUR].valid_values[ge] < 2, |
|
796 PFW_WIDGET_EYECOLOUR, PFW_WIDGET_EYECOLOUR_L, PFW_WIDGET_EYECOLOUR_R, WIDGET_LIST_END); |
|
797 |
|
798 /* Chin buttons */ |
|
799 w->SetWidgetsDisabledState(_pf_info[PFV_CHIN].valid_values[ge] < 2, |
|
800 PFW_WIDGET_CHIN, PFW_WIDGET_CHIN_L, PFW_WIDGET_CHIN_R, WIDGET_LIST_END); |
|
801 |
|
802 /* Eyebrows buttons */ |
|
803 w->SetWidgetsDisabledState(_pf_info[PFV_EYEBROWS].valid_values[ge] < 2, |
|
804 PFW_WIDGET_EYEBROWS, PFW_WIDGET_EYEBROWS_L, PFW_WIDGET_EYEBROWS_R, WIDGET_LIST_END); |
|
805 |
|
806 /* Lips or (if it a male face with a moustache) moustache buttons */ |
|
807 w->SetWidgetsDisabledState(_pf_info[is_moust_male ? PFV_MOUSTACHE : PFV_LIPS].valid_values[ge] < 2, |
|
808 PFW_WIDGET_LIPS_MOUSTACHE, PFW_WIDGET_LIPS_MOUSTACHE_L, PFW_WIDGET_LIPS_MOUSTACHE_R, WIDGET_LIST_END); |
|
809 |
|
810 /* Nose buttons | male faces with moustache haven't any nose options */ |
|
811 w->SetWidgetsDisabledState(_pf_info[PFV_NOSE].valid_values[ge] < 2 || is_moust_male, |
|
812 PFW_WIDGET_NOSE, PFW_WIDGET_NOSE_L, PFW_WIDGET_NOSE_R, WIDGET_LIST_END); |
|
813 |
|
814 /* Hair buttons */ |
|
815 w->SetWidgetsDisabledState(_pf_info[PFV_HAIR].valid_values[ge] < 2, |
|
816 PFW_WIDGET_HAIR, PFW_WIDGET_HAIR_L, PFW_WIDGET_HAIR_R, WIDGET_LIST_END); |
|
817 |
|
818 /* Jacket buttons */ |
|
819 w->SetWidgetsDisabledState(_pf_info[PFV_JACKET].valid_values[ge] < 2, |
|
820 PFW_WIDGET_JACKET, PFW_WIDGET_JACKET_L, PFW_WIDGET_JACKET_R, WIDGET_LIST_END); |
|
821 |
|
822 /* Collar buttons */ |
|
823 w->SetWidgetsDisabledState(_pf_info[PFV_COLLAR].valid_values[ge] < 2, |
|
824 PFW_WIDGET_COLLAR, PFW_WIDGET_COLLAR_L, PFW_WIDGET_COLLAR_R, WIDGET_LIST_END); |
|
825 |
|
826 /* Tie/earring buttons | female faces without earring haven't any earring options */ |
|
827 w->SetWidgetsDisabledState(_pf_info[PFV_TIE_EARRING].valid_values[ge] < 2 || |
|
828 (is_female && GetPlayerFaceBits(*pf, PFV_HAS_TIE_EARRING, ge) == 0), |
|
829 PFW_WIDGET_TIE_EARRING, PFW_WIDGET_TIE_EARRING_L, PFW_WIDGET_TIE_EARRING_R, WIDGET_LIST_END); |
|
830 |
|
831 /* Glasses buttons | faces without glasses haven't any glasses options */ |
|
832 w->SetWidgetsDisabledState(_pf_info[PFV_GLASSES].valid_values[ge] < 2 || GetPlayerFaceBits(*pf, PFV_HAS_GLASSES, ge) == 0, |
|
833 PFW_WIDGET_GLASSES, PFW_WIDGET_GLASSES_L, PFW_WIDGET_GLASSES_R, WIDGET_LIST_END); |
|
834 } |
|
835 |
|
836 DrawWindowWidgets(w); |
|
837 |
|
838 /* Draw dynamic button value and labels for the advanced player face selection window */ |
|
839 if (WP(w, facesel_d).advanced) { |
|
840 if (is_female) { |
|
841 /* Only for female faces */ |
|
842 DrawFaceStringLabel(w, PFW_WIDGET_HAS_MOUSTACHE_EARRING, STR_FACE_EARRING, GetPlayerFaceBits(*pf, PFV_HAS_TIE_EARRING, ge), true ); |
|
843 DrawFaceStringLabel(w, PFW_WIDGET_TIE_EARRING, STR_FACE_EARRING, GetPlayerFaceBits(*pf, PFV_TIE_EARRING, ge), false); |
|
844 } else { |
|
845 /* Only for male faces */ |
|
846 DrawFaceStringLabel(w, PFW_WIDGET_HAS_MOUSTACHE_EARRING, STR_FACE_MOUSTACHE, GetPlayerFaceBits(*pf, PFV_HAS_MOUSTACHE, ge), true ); |
|
847 DrawFaceStringLabel(w, PFW_WIDGET_TIE_EARRING, STR_FACE_TIE, GetPlayerFaceBits(*pf, PFV_TIE_EARRING, ge), false); |
|
848 } |
|
849 if (is_moust_male) { |
|
850 /* Only for male faces with moustache */ |
|
851 DrawFaceStringLabel(w, PFW_WIDGET_LIPS_MOUSTACHE, STR_FACE_MOUSTACHE, GetPlayerFaceBits(*pf, PFV_MOUSTACHE, ge), false); |
|
852 } else { |
|
853 /* Only for female faces or male faces without moustache */ |
|
854 DrawFaceStringLabel(w, PFW_WIDGET_LIPS_MOUSTACHE, STR_FACE_LIPS, GetPlayerFaceBits(*pf, PFV_LIPS, ge), false); |
|
855 } |
|
856 /* For all faces */ |
|
857 DrawFaceStringLabel(w, PFW_WIDGET_HAS_GLASSES, STR_FACE_GLASSES, GetPlayerFaceBits(*pf, PFV_HAS_GLASSES, ge), true ); |
|
858 DrawFaceStringLabel(w, PFW_WIDGET_HAIR, STR_FACE_HAIR, GetPlayerFaceBits(*pf, PFV_HAIR, ge), false); |
|
859 DrawFaceStringLabel(w, PFW_WIDGET_EYEBROWS, STR_FACE_EYEBROWS, GetPlayerFaceBits(*pf, PFV_EYEBROWS, ge), false); |
|
860 DrawFaceStringLabel(w, PFW_WIDGET_EYECOLOUR, STR_FACE_EYECOLOUR, GetPlayerFaceBits(*pf, PFV_EYE_COLOUR, ge), false); |
|
861 DrawFaceStringLabel(w, PFW_WIDGET_GLASSES, STR_FACE_GLASSES, GetPlayerFaceBits(*pf, PFV_GLASSES, ge), false); |
|
862 DrawFaceStringLabel(w, PFW_WIDGET_NOSE, STR_FACE_NOSE, GetPlayerFaceBits(*pf, PFV_NOSE, ge), false); |
|
863 DrawFaceStringLabel(w, PFW_WIDGET_CHIN, STR_FACE_CHIN, GetPlayerFaceBits(*pf, PFV_CHIN, ge), false); |
|
864 DrawFaceStringLabel(w, PFW_WIDGET_JACKET, STR_FACE_JACKET, GetPlayerFaceBits(*pf, PFV_JACKET, ge), false); |
|
865 DrawFaceStringLabel(w, PFW_WIDGET_COLLAR, STR_FACE_COLLAR, GetPlayerFaceBits(*pf, PFV_COLLAR, ge), false); |
|
866 } |
|
867 |
|
868 /* Draw the player face picture */ |
|
869 DrawPlayerFace(*pf, GetPlayer((PlayerID)w->window_number)->player_color, 2, 16); |
|
870 break; |
|
871 |
|
872 case WE_CLICK: |
|
873 switch (e->we.click.widget) { |
|
874 /* Toggle size, advanced/simple face selection */ |
|
875 case PFW_WIDGET_TOGGLE_LARGE_SMALL: |
|
876 case PFW_WIDGET_TOGGLE_LARGE_SMALL_BUTTON: { |
|
877 int oldtop = w->top; ///< current top position of the window before closing it |
|
878 int oldleft = w->left; ///< current top position of the window before closing it |
|
879 |
|
880 DoCommandP(0, 0, *pf, NULL, CMD_SET_PLAYER_FACE); |
|
881 delete w; |
|
882 /* Open up the (toggled size) Face selection window at the same position as the previous */ |
|
883 DoSelectPlayerFace((PlayerID)w->window_number, !WP(w, facesel_d).advanced, oldtop, oldleft); |
|
884 } break; |
|
885 |
|
886 /* Cancel button */ |
|
887 case PFW_WIDGET_CANCEL: |
|
888 delete w; |
|
889 break; |
|
890 |
|
891 /* OK button */ |
|
892 case PFW_WIDGET_ACCEPT: |
|
893 DoCommandP(0, 0, *pf, NULL, CMD_SET_PLAYER_FACE); |
|
894 delete w; |
|
895 break; |
|
896 |
|
897 /* Load button */ |
|
898 case PFW_WIDGET_LOAD: |
|
899 *pf = _player_face; |
|
900 ScaleAllPlayerFaceBits(*pf); |
|
901 ShowErrorMessage(INVALID_STRING_ID, STR_FACE_LOAD_DONE, 0, 0); |
|
902 w->SetDirty(); |
|
903 break; |
|
904 |
|
905 /* 'Player face number' button, view and/or set player face number */ |
|
906 case PFW_WIDGET_FACECODE: |
|
907 SetDParam(0, *pf); |
|
908 ShowQueryString(STR_JUST_INT, STR_FACE_FACECODE_CAPTION, 10 + 1, 0, w, CS_NUMERAL); |
|
909 break; |
|
910 |
|
911 /* Save button */ |
|
912 case PFW_WIDGET_SAVE: |
|
913 _player_face = *pf; |
|
914 ShowErrorMessage(INVALID_STRING_ID, STR_FACE_SAVE_DONE, 0, 0); |
|
915 break; |
|
916 |
|
917 /* Toggle gender (male/female) button */ |
|
918 case PFW_WIDGET_MALE: |
|
919 case PFW_WIDGET_FEMALE: |
|
920 SetPlayerFaceBits(*pf, PFV_GENDER, ge, e->we.click.widget - PFW_WIDGET_MALE); |
|
921 ScaleAllPlayerFaceBits(*pf); |
|
922 w->SetDirty(); |
|
923 break; |
|
924 |
|
925 /* Randomize face button */ |
|
926 case PFW_WIDGET_RANDOM_NEW_FACE: |
|
927 RandomPlayerFaceBits(*pf, ge, WP(w, facesel_d).advanced); |
|
928 w->SetDirty(); |
|
929 break; |
|
930 |
|
931 /* Toggle ethnicity (european/african) button */ |
|
932 case PFW_WIDGET_ETHNICITY_EUR: |
|
933 case PFW_WIDGET_ETHNICITY_AFR: |
|
934 SetPlayerFaceBits(*pf, PFV_ETHNICITY, ge, e->we.click.widget - PFW_WIDGET_ETHNICITY_EUR); |
|
935 ScaleAllPlayerFaceBits(*pf); |
|
936 w->SetDirty(); |
|
937 break; |
|
938 |
|
939 default: |
|
940 /* For all buttons from PFW_WIDGET_HAS_MOUSTACHE_EARRING to PFW_WIDGET_GLASSES_R is the same function. |
|
941 * Therefor is this combined function. |
|
942 * First it checks which PlayerFaceVariable will be change and then |
|
943 * a: invert the value for boolean variables |
|
944 * or b: it checks inside of IncreasePlayerFaceBits() if a left (_L) butten is pressed and then decrease else increase the variable */ |
|
945 if (WP(w, facesel_d).advanced && e->we.click.widget >= PFW_WIDGET_HAS_MOUSTACHE_EARRING && e->we.click.widget <= PFW_WIDGET_GLASSES_R) { |
|
946 PlayerFaceVariable pfv; // which PlayerFaceVariable shall be edited |
|
947 |
|
948 if (e->we.click.widget < PFW_WIDGET_EYECOLOUR_L) { // Bool buttons |
|
949 switch (e->we.click.widget - PFW_WIDGET_HAS_MOUSTACHE_EARRING) { |
|
950 default: NOT_REACHED(); |
|
951 case 0: pfv = is_female ? PFV_HAS_TIE_EARRING : PFV_HAS_MOUSTACHE; break; // Has earring/moustache button |
|
952 case 1: pfv = PFV_HAS_GLASSES; break; // Has glasses button |
|
953 } |
|
954 SetPlayerFaceBits(*pf, pfv, ge, !GetPlayerFaceBits(*pf, pfv, ge)); |
|
955 ScaleAllPlayerFaceBits(*pf); |
|
956 |
|
957 } else { // Value buttons |
|
958 switch ((e->we.click.widget - PFW_WIDGET_EYECOLOUR_L) / 3) { |
|
959 default: NOT_REACHED(); |
|
960 case 0: pfv = PFV_EYE_COLOUR; break; // Eye colour buttons |
|
961 case 1: pfv = PFV_CHIN; break; // Chin buttons |
|
962 case 2: pfv = PFV_EYEBROWS; break; // Eyebrows buttons |
|
963 case 3: pfv = is_moust_male ? PFV_MOUSTACHE : PFV_LIPS; break; // Moustache or lips buttons |
|
964 case 4: pfv = PFV_NOSE; break; // Nose buttons |
|
965 case 5: pfv = PFV_HAIR; break; // Hair buttons |
|
966 case 6: pfv = PFV_JACKET; break; // Jacket buttons |
|
967 case 7: pfv = PFV_COLLAR; break; // Collar buttons |
|
968 case 8: pfv = PFV_TIE_EARRING; break; // Tie/earring buttons |
|
969 case 9: pfv = PFV_GLASSES; break; // Glasses buttons |
|
970 } |
|
971 /* 0 == left (_L), 1 == middle or 2 == right (_R) - button click */ |
|
972 IncreasePlayerFaceBits(*pf, pfv, ge, (((e->we.click.widget - PFW_WIDGET_EYECOLOUR_L) % 3) != 0) ? 1 : -1); |
|
973 } |
|
974 |
|
975 w->SetDirty(); |
|
976 } |
|
977 break; |
|
978 } |
|
979 break; |
|
980 |
|
981 case WE_ON_EDIT_TEXT: |
|
982 if (e->we.edittext.str == NULL) break; |
|
983 /* Set a new player face number */ |
|
984 if (!StrEmpty(e->we.edittext.str)) { |
|
985 *pf = strtoul(e->we.edittext.str, NULL, 10); |
|
986 ScaleAllPlayerFaceBits(*pf); |
|
987 ShowErrorMessage(INVALID_STRING_ID, STR_FACE_FACECODE_SET, 0, 0); |
|
988 w->SetDirty(); |
|
989 } else { |
|
990 ShowErrorMessage(INVALID_STRING_ID, STR_FACE_FACECODE_ERR, 0, 0); |
|
991 } |
|
992 break; |
|
993 } |
|
994 } |
|
995 |
1003 |
996 /** normal/simple player face selection window description */ |
1004 /** normal/simple player face selection window description */ |
997 static const WindowDesc _select_player_face_desc = { |
1005 static const WindowDesc _select_player_face_desc = { |
998 WDP_AUTO, WDP_AUTO, 190, 163, 190, 163, |
1006 WDP_AUTO, WDP_AUTO, 190, 163, 190, 163, |
999 WC_PLAYER_FACE, WC_NONE, |
1007 WC_PLAYER_FACE, WC_NONE, |
1000 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, |
1008 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, |
1001 _select_player_face_widgets, |
1009 _select_player_face_widgets, |
1002 SelectPlayerFaceWndProc |
|
1003 }; |
1010 }; |
1004 |
1011 |
1005 /** advanced player face selection window description */ |
1012 /** advanced player face selection window description */ |
1006 static const WindowDesc _select_player_face_adv_desc = { |
1013 static const WindowDesc _select_player_face_adv_desc = { |
1007 WDP_AUTO, WDP_AUTO, 220, 220, 220, 220, |
1014 WDP_AUTO, WDP_AUTO, 220, 220, 220, 220, |
1008 WC_PLAYER_FACE, WC_NONE, |
1015 WC_PLAYER_FACE, WC_NONE, |
1009 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, |
1016 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, |
1010 _select_player_face_adv_widgets, |
1017 _select_player_face_adv_widgets, |
1011 SelectPlayerFaceWndProc |
|
1012 }; |
1018 }; |
1013 |
1019 |
1014 /** |
1020 /** |
1015 * Open the simple/advanced player face selection window |
1021 * Open the simple/advanced player face selection window |
1016 * |
1022 * |
1163 * Player company window event definition |
1158 * Player company window event definition |
1164 * |
1159 * |
1165 * @param w window pointer |
1160 * @param w window pointer |
1166 * @param e event been triggered |
1161 * @param e event been triggered |
1167 */ |
1162 */ |
1168 static void PlayerCompanyWndProc(Window *w, WindowEvent *e) |
1163 struct PlayerCompanyWindow : Window |
1169 { |
1164 { |
1170 switch (e->event) { |
1165 PlayerCompanyWindowWidgets query_widget; |
1171 case WE_PAINT: { |
1166 |
1172 const Player *p = GetPlayer((PlayerID)w->window_number); |
1167 PlayerCompanyWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number) |
1173 bool local = w->window_number == _local_player; |
1168 { |
1174 |
1169 this->caption_color = this->window_number; |
1175 w->SetWidgetHiddenState(PCW_WIDGET_NEW_FACE, !local); |
1170 } |
1176 w->SetWidgetHiddenState(PCW_WIDGET_COLOR_SCHEME, !local); |
1171 |
1177 w->SetWidgetHiddenState(PCW_WIDGET_PRESIDENT_NAME, !local); |
1172 virtual void OnPaint() |
1178 w->SetWidgetHiddenState(PCW_WIDGET_COMPANY_NAME, !local); |
1173 { |
1179 w->widget[PCW_WIDGET_BUILD_VIEW_HQ].data = (local && p->location_of_house == 0) ? STR_706F_BUILD_HQ : STR_7072_VIEW_HQ; |
1174 const Player *p = GetPlayer((PlayerID)this->window_number); |
1180 if (local && p->location_of_house != 0) w->widget[PCW_WIDGET_BUILD_VIEW_HQ].type = WWT_PUSHTXTBTN; //HQ is already built. |
1175 bool local = this->window_number == _local_player; |
1181 w->SetWidgetDisabledState(PCW_WIDGET_BUILD_VIEW_HQ, !local && p->location_of_house == 0); |
1176 |
1182 w->SetWidgetHiddenState(PCW_WIDGET_RELOCATE_HQ, !local || p->location_of_house == 0); |
1177 this->SetWidgetHiddenState(PCW_WIDGET_NEW_FACE, !local); |
1183 w->SetWidgetHiddenState(PCW_WIDGET_BUY_SHARE, local); |
1178 this->SetWidgetHiddenState(PCW_WIDGET_COLOR_SCHEME, !local); |
1184 w->SetWidgetHiddenState(PCW_WIDGET_SELL_SHARE, local); |
1179 this->SetWidgetHiddenState(PCW_WIDGET_PRESIDENT_NAME, !local); |
1185 w->SetWidgetHiddenState(PCW_WIDGET_COMPANY_PASSWORD, !local || !_networking); |
1180 this->SetWidgetHiddenState(PCW_WIDGET_COMPANY_NAME, !local); |
1186 |
1181 this->widget[PCW_WIDGET_BUILD_VIEW_HQ].data = (local && p->location_of_house == 0) ? STR_706F_BUILD_HQ : STR_7072_VIEW_HQ; |
1187 if (!local) { |
1182 if (local && p->location_of_house != 0) this->widget[PCW_WIDGET_BUILD_VIEW_HQ].type = WWT_PUSHTXTBTN; //HQ is already built. |
1188 if (_patches.allow_shares) { // Shares are allowed |
1183 this->SetWidgetDisabledState(PCW_WIDGET_BUILD_VIEW_HQ, !local && p->location_of_house == 0); |
1189 /* If all shares are owned by someone (none by nobody), disable buy button */ |
1184 this->SetWidgetHiddenState(PCW_WIDGET_RELOCATE_HQ, !local || p->location_of_house == 0); |
1190 w->SetWidgetDisabledState(PCW_WIDGET_BUY_SHARE, GetAmountOwnedBy(p, PLAYER_SPECTATOR) == 0 || |
1185 this->SetWidgetHiddenState(PCW_WIDGET_BUY_SHARE, local); |
1191 /* Only 25% left to buy. If the player is human, disable buying it up.. TODO issues! */ |
1186 this->SetWidgetHiddenState(PCW_WIDGET_SELL_SHARE, local); |
1192 (GetAmountOwnedBy(p, PLAYER_SPECTATOR) == 1 && !p->is_ai) || |
1187 this->SetWidgetHiddenState(PCW_WIDGET_COMPANY_PASSWORD, !local || !_networking); |
1193 /* Spectators cannot do anything of course */ |
1188 |
1194 _local_player == PLAYER_SPECTATOR); |
1189 if (!local) { |
1195 |
1190 if (_patches.allow_shares) { // Shares are allowed |
1196 /* If the player doesn't own any shares, disable sell button */ |
1191 /* If all shares are owned by someone (none by nobody), disable buy button */ |
1197 w->SetWidgetDisabledState(PCW_WIDGET_SELL_SHARE, (GetAmountOwnedBy(p, _local_player) == 0) || |
1192 this->SetWidgetDisabledState(PCW_WIDGET_BUY_SHARE, GetAmountOwnedBy(p, PLAYER_SPECTATOR) == 0 || |
1198 /* Spectators cannot do anything of course */ |
1193 /* Only 25% left to buy. If the player is human, disable buying it up.. TODO issues! */ |
1199 _local_player == PLAYER_SPECTATOR); |
1194 (GetAmountOwnedBy(p, PLAYER_SPECTATOR) == 1 && !p->is_ai) || |
1200 } else { // Shares are not allowed, disable buy/sell buttons |
1195 /* Spectators cannot do anything of course */ |
1201 w->DisableWidget(PCW_WIDGET_BUY_SHARE); |
1196 _local_player == PLAYER_SPECTATOR); |
1202 w->DisableWidget(PCW_WIDGET_SELL_SHARE); |
1197 |
|
1198 /* If the player doesn't own any shares, disable sell button */ |
|
1199 this->SetWidgetDisabledState(PCW_WIDGET_SELL_SHARE, (GetAmountOwnedBy(p, _local_player) == 0) || |
|
1200 /* Spectators cannot do anything of course */ |
|
1201 _local_player == PLAYER_SPECTATOR); |
|
1202 } else { // Shares are not allowed, disable buy/sell buttons |
|
1203 this->DisableWidget(PCW_WIDGET_BUY_SHARE); |
|
1204 this->DisableWidget(PCW_WIDGET_SELL_SHARE); |
|
1205 } |
|
1206 } |
|
1207 |
|
1208 SetDParam(0, p->index); |
|
1209 SetDParam(1, p->index); |
|
1210 |
|
1211 this->DrawWidgets(); |
|
1212 |
|
1213 /* Player face */ |
|
1214 DrawPlayerFace(p->face, p->player_color, 2, 16); |
|
1215 |
|
1216 /* "xxx (Manager)" */ |
|
1217 SetDParam(0, p->index); |
|
1218 DrawStringMultiCenter(48, 141, STR_7037_PRESIDENT, 94); |
|
1219 |
|
1220 /* "Inaugurated:" */ |
|
1221 SetDParam(0, p->inaugurated_year); |
|
1222 DrawString(110, 23, STR_7038_INAUGURATED, TC_FROMSTRING); |
|
1223 |
|
1224 /* "Colour scheme:" */ |
|
1225 DrawString(110, 43, STR_7006_COLOR_SCHEME, TC_FROMSTRING); |
|
1226 /* Draw company-colour bus */ |
|
1227 DrawSprite(SPR_VEH_BUS_SW_VIEW, PLAYER_SPRITE_COLOR(p->index), 215, 44); |
|
1228 |
|
1229 /* "Vehicles:" */ |
|
1230 DrawPlayerVehiclesAmount((PlayerID)this->window_number); |
|
1231 |
|
1232 /* "Company value:" */ |
|
1233 SetDParam(0, CalculateCompanyValue(p)); |
|
1234 DrawString(110, 106, STR_7076_COMPANY_VALUE, TC_FROMSTRING); |
|
1235 |
|
1236 /* Shares list */ |
|
1237 DrawCompanyOwnerText(p); |
|
1238 } |
|
1239 |
|
1240 virtual void OnClick(Point pt, int widget) |
|
1241 { |
|
1242 switch (widget) { |
|
1243 case PCW_WIDGET_NEW_FACE: DoSelectPlayerFace(this, false); break; |
|
1244 |
|
1245 case PCW_WIDGET_COLOR_SCHEME: |
|
1246 if (BringWindowToFrontById(WC_PLAYER_COLOR, this->window_number)) break; |
|
1247 new SelectPlayerLiveryWindow(&_select_player_livery_desc, (PlayerID)this->window_number); |
|
1248 break; |
|
1249 |
|
1250 case PCW_WIDGET_PRESIDENT_NAME: |
|
1251 this->query_widget = PCW_WIDGET_PRESIDENT_NAME; |
|
1252 SetDParam(0, this->window_number); |
|
1253 ShowQueryString(STR_PLAYER_NAME, STR_700B_PRESIDENT_S_NAME, 31, 94, this, CS_ALPHANUMERAL); |
|
1254 break; |
|
1255 |
|
1256 case PCW_WIDGET_COMPANY_NAME: |
|
1257 this->query_widget = PCW_WIDGET_COMPANY_NAME; |
|
1258 SetDParam(0, this->window_number); |
|
1259 ShowQueryString(STR_COMPANY_NAME, STR_700A_COMPANY_NAME, 31, 150, this, CS_ALPHANUMERAL); |
|
1260 break; |
|
1261 |
|
1262 case PCW_WIDGET_BUILD_VIEW_HQ: { |
|
1263 TileIndex tile = GetPlayer((PlayerID)this->window_number)->location_of_house; |
|
1264 if (tile == 0) { |
|
1265 if ((byte)this->window_number != _local_player) return; |
|
1266 SetObjectToPlaceWnd(SPR_CURSOR_HQ, PAL_NONE, VHM_RECT, this); |
|
1267 SetTileSelectSize(2, 2); |
|
1268 this->LowerWidget(PCW_WIDGET_BUILD_VIEW_HQ); |
|
1269 this->InvalidateWidget(PCW_WIDGET_BUILD_VIEW_HQ); |
|
1270 } else { |
|
1271 if (_ctrl_pressed) { |
|
1272 ShowExtraViewPortWindow(tile); |
|
1273 } else { |
|
1274 ScrollMainWindowToTile(tile); |
|
1275 } |
1203 } |
1276 } |
|
1277 break; |
1204 } |
1278 } |
1205 |
1279 |
1206 SetDParam(0, p->index); |
1280 case PCW_WIDGET_RELOCATE_HQ: |
1207 SetDParam(1, p->index); |
1281 SetObjectToPlaceWnd(SPR_CURSOR_HQ, PAL_NONE, VHM_RECT, this); |
1208 |
1282 SetTileSelectSize(2, 2); |
1209 DrawWindowWidgets(w); |
1283 this->LowerWidget(PCW_WIDGET_RELOCATE_HQ); |
1210 |
1284 this->InvalidateWidget(PCW_WIDGET_RELOCATE_HQ); |
1211 /* Player face */ |
1285 break; |
1212 DrawPlayerFace(p->face, p->player_color, 2, 16); |
1286 |
1213 |
1287 case PCW_WIDGET_BUY_SHARE: |
1214 /* "xxx (Manager)" */ |
1288 DoCommandP(0, this->window_number, 0, NULL, CMD_BUY_SHARE_IN_COMPANY | CMD_MSG(STR_707B_CAN_T_BUY_25_SHARE_IN_THIS)); |
1215 SetDParam(0, p->index); |
1289 break; |
1216 DrawStringMultiCenter(48, 141, STR_7037_PRESIDENT, 94); |
1290 |
1217 |
1291 case PCW_WIDGET_SELL_SHARE: |
1218 /* "Inaugurated:" */ |
1292 DoCommandP(0, this->window_number, 0, NULL, CMD_SELL_SHARE_IN_COMPANY | CMD_MSG(STR_707C_CAN_T_SELL_25_SHARE_IN)); |
1219 SetDParam(0, p->inaugurated_year); |
1293 break; |
1220 DrawString(110, 23, STR_7038_INAUGURATED, TC_FROMSTRING); |
|
1221 |
|
1222 /* "Colour scheme:" */ |
|
1223 DrawString(110, 43, STR_7006_COLOR_SCHEME, TC_FROMSTRING); |
|
1224 /* Draw company-colour bus */ |
|
1225 DrawSprite(SPR_VEH_BUS_SW_VIEW, PLAYER_SPRITE_COLOR(p->index), 215, 44); |
|
1226 |
|
1227 /* "Vehicles:" */ |
|
1228 DrawPlayerVehiclesAmount((PlayerID)w->window_number); |
|
1229 |
|
1230 /* "Company value:" */ |
|
1231 SetDParam(0, CalculateCompanyValue(p)); |
|
1232 DrawString(110, 106, STR_7076_COMPANY_VALUE, TC_FROMSTRING); |
|
1233 |
|
1234 /* Shares list */ |
|
1235 DrawCompanyOwnerText(p); |
|
1236 |
|
1237 break; |
|
1238 } |
|
1239 |
|
1240 case WE_CLICK: |
|
1241 switch (e->we.click.widget) { |
|
1242 case PCW_WIDGET_NEW_FACE: DoSelectPlayerFace((PlayerID)w->window_number, false); break; |
|
1243 |
|
1244 case PCW_WIDGET_COLOR_SCHEME: { |
|
1245 Window *wf = AllocateWindowDescFront<Window>(_loaded_newgrf_features.has_2CC ? &_select_player_livery_2cc_desc : &_select_player_livery_desc, w->window_number); |
|
1246 if (wf != NULL) { |
|
1247 wf->caption_color = wf->window_number; |
|
1248 WP(wf, livery_d).livery_class = LC_OTHER; |
|
1249 WP(wf, livery_d).sel = 1; |
|
1250 wf->LowerWidget(2); |
|
1251 } |
|
1252 break; |
|
1253 } |
|
1254 |
|
1255 case PCW_WIDGET_PRESIDENT_NAME: { |
|
1256 const Player *p = GetPlayer((PlayerID)w->window_number); |
|
1257 WP(w, def_d).byte_1 = 0; |
|
1258 SetDParam(0, p->index); |
|
1259 ShowQueryString(STR_PLAYER_NAME, STR_700B_PRESIDENT_S_NAME, 31, 94, w, CS_ALPHANUMERAL); |
|
1260 break; |
|
1261 } |
|
1262 |
|
1263 case PCW_WIDGET_COMPANY_NAME: { |
|
1264 Player *p = GetPlayer((PlayerID)w->window_number); |
|
1265 WP(w, def_d).byte_1 = 1; |
|
1266 SetDParam(0, p->index); |
|
1267 ShowQueryString(STR_COMPANY_NAME, STR_700A_COMPANY_NAME, 31, 150, w, CS_ALPHANUMERAL); |
|
1268 break; |
|
1269 } |
|
1270 |
|
1271 case PCW_WIDGET_BUILD_VIEW_HQ: { |
|
1272 TileIndex tile = GetPlayer((PlayerID)w->window_number)->location_of_house; |
|
1273 if (tile == 0) { |
|
1274 if ((byte)w->window_number != _local_player) |
|
1275 return; |
|
1276 SetObjectToPlaceWnd(SPR_CURSOR_HQ, PAL_NONE, VHM_RECT, w); |
|
1277 SetTileSelectSize(2, 2); |
|
1278 w->LowerWidget(PCW_WIDGET_BUILD_VIEW_HQ); |
|
1279 w->InvalidateWidget(PCW_WIDGET_BUILD_VIEW_HQ); |
|
1280 } else { |
|
1281 if (_ctrl_pressed) { |
|
1282 ShowExtraViewPortWindow(tile); |
|
1283 } else { |
|
1284 ScrollMainWindowToTile(tile); |
|
1285 } |
|
1286 } |
|
1287 break; |
|
1288 } |
|
1289 |
|
1290 case PCW_WIDGET_RELOCATE_HQ: |
|
1291 SetObjectToPlaceWnd(SPR_CURSOR_HQ, PAL_NONE, VHM_RECT, w); |
|
1292 SetTileSelectSize(2, 2); |
|
1293 w->LowerWidget(PCW_WIDGET_RELOCATE_HQ); |
|
1294 w->InvalidateWidget(PCW_WIDGET_RELOCATE_HQ); |
|
1295 break; |
|
1296 |
|
1297 case PCW_WIDGET_BUY_SHARE: |
|
1298 DoCommandP(0, w->window_number, 0, NULL, CMD_BUY_SHARE_IN_COMPANY | CMD_MSG(STR_707B_CAN_T_BUY_25_SHARE_IN_THIS)); |
|
1299 break; |
|
1300 |
|
1301 case PCW_WIDGET_SELL_SHARE: |
|
1302 DoCommandP(0, w->window_number, 0, NULL, CMD_SELL_SHARE_IN_COMPANY | CMD_MSG(STR_707C_CAN_T_SELL_25_SHARE_IN)); |
|
1303 break; |
|
1304 |
1294 |
1305 #ifdef ENABLE_NETWORK |
1295 #ifdef ENABLE_NETWORK |
1306 case PCW_WIDGET_COMPANY_PASSWORD: |
1296 case PCW_WIDGET_COMPANY_PASSWORD: |
1307 if (w->window_number == _local_player) ShowNetworkCompanyPasswordWindow(); |
1297 if (this->window_number == _local_player) ShowNetworkCompanyPasswordWindow(this); |
1308 break; |
1298 break; |
1309 #endif /* ENABLE_NETWORK */ |
1299 #endif /* ENABLE_NETWORK */ |
1310 } |
1300 } |
1311 break; |
1301 } |
1312 |
1302 |
1313 case WE_TICK: |
1303 virtual void OnTick() |
1314 /* redraw the window every now and then */ |
1304 { |
1315 if ((++w->vscroll.pos & 0x1F) == 0) w->SetDirty(); |
1305 /* redraw the window every now and then */ |
1316 break; |
1306 if ((++this->vscroll.pos & 0x1F) == 0) this->SetDirty(); |
1317 |
1307 } |
1318 case WE_PLACE_OBJ: |
1308 |
1319 if (DoCommandP(e->we.place.tile, 0, 0, NULL, CMD_BUILD_COMPANY_HQ | CMD_NO_WATER | CMD_MSG(STR_7071_CAN_T_BUILD_COMPANY_HEADQUARTERS))) |
1309 virtual void OnPlaceObject(Point pt, TileIndex tile) |
1320 ResetObjectToPlace(); |
1310 { |
1321 w->widget[PCW_WIDGET_BUILD_VIEW_HQ].type = WWT_PUSHTXTBTN; // this button can now behave as a normal push button |
1311 if (DoCommandP(tile, 0, 0, NULL, CMD_BUILD_COMPANY_HQ | CMD_NO_WATER | CMD_MSG(STR_7071_CAN_T_BUILD_COMPANY_HEADQUARTERS))) |
1322 w->RaiseButtons(); |
1312 ResetObjectToPlace(); |
1323 break; |
1313 this->widget[PCW_WIDGET_BUILD_VIEW_HQ].type = WWT_PUSHTXTBTN; // this button can now behave as a normal push button |
1324 |
1314 this->RaiseButtons(); |
1325 case WE_ABORT_PLACE_OBJ: |
1315 } |
1326 w->RaiseButtons(); |
1316 |
1327 break; |
1317 virtual void OnPlaceObjectAbort() |
1328 |
1318 { |
1329 case WE_DESTROY: |
1319 this->RaiseButtons(); |
1330 DeleteWindowById(WC_PLAYER_FACE, w->window_number); |
1320 } |
1331 if (w->window_number == _local_player) DeleteWindowById(WC_COMPANY_PASSWORD_WINDOW, 0); |
1321 |
1332 break; |
1322 virtual void OnQueryTextFinished(char *str) |
1333 |
1323 { |
1334 case WE_ON_EDIT_TEXT: |
1324 if (StrEmpty(str)) return; |
1335 if (StrEmpty(e->we.edittext.str)) break; |
1325 |
1336 |
1326 _cmd_text = str; |
1337 _cmd_text = e->we.edittext.str; |
1327 switch (this->query_widget) { |
1338 switch (WP(w, def_d).byte_1) { |
1328 default: NOT_REACHED(); |
1339 case 0: /* Change president name */ |
1329 |
1340 DoCommandP(0, 0, 0, NULL, CMD_CHANGE_PRESIDENT_NAME | CMD_MSG(STR_700D_CAN_T_CHANGE_PRESIDENT)); |
1330 case PCW_WIDGET_PRESIDENT_NAME: |
1341 break; |
1331 DoCommandP(0, 0, 0, NULL, CMD_CHANGE_PRESIDENT_NAME | CMD_MSG(STR_700D_CAN_T_CHANGE_PRESIDENT)); |
1342 case 1: /* Change company name */ |
1332 break; |
1343 DoCommandP(0, 0, 0, NULL, CMD_CHANGE_COMPANY_NAME | CMD_MSG(STR_700C_CAN_T_CHANGE_COMPANY_NAME)); |
1333 |
1344 break; |
1334 case PCW_WIDGET_COMPANY_NAME: |
1345 } |
1335 DoCommandP(0, 0, 0, NULL, CMD_CHANGE_COMPANY_NAME | CMD_MSG(STR_700C_CAN_T_CHANGE_COMPANY_NAME)); |
1346 break; |
1336 break; |
1347 } |
1337 } |
1348 } |
1338 } |
1349 |
1339 }; |
1350 |
1340 |
1351 static const WindowDesc _player_company_desc = { |
1341 static const WindowDesc _player_company_desc = { |
1352 WDP_AUTO, WDP_AUTO, 360, 170, 360, 170, |
1342 WDP_AUTO, WDP_AUTO, 360, 170, 360, 170, |
1353 WC_COMPANY, WC_NONE, |
1343 WC_COMPANY, WC_NONE, |
1354 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, |
1344 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, |
1355 _player_company_widgets, |
1345 _player_company_widgets, |
1356 PlayerCompanyWndProc |
|
1357 }; |
1346 }; |
1358 |
1347 |
1359 void ShowPlayerCompany(PlayerID player) |
1348 void ShowPlayerCompany(PlayerID player) |
1360 { |
1349 { |
1361 Window *w; |
|
1362 |
|
1363 if (!IsValidPlayer(player)) return; |
1350 if (!IsValidPlayer(player)) return; |
1364 |
1351 |
1365 w = AllocateWindowDescFront<Window>(&_player_company_desc, player); |
1352 AllocateWindowDescFront<PlayerCompanyWindow>(&_player_company_desc, player); |
1366 if (w != NULL) w->caption_color = w->window_number; |
|
1367 } |
1353 } |
1368 |
1354 |
1369 |
1355 |
1370 |
1356 |
1371 static void BuyCompanyWndProc(Window *w, WindowEvent *e) |
1357 struct BuyCompanyWindow : Window { |
1372 { |
1358 BuyCompanyWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number) |
1373 switch (e->event) { |
1359 { |
1374 case WE_PAINT: { |
1360 } |
1375 Player *p = GetPlayer((PlayerID)w->window_number); |
1361 |
1376 SetDParam(0, STR_COMPANY_NAME); |
1362 virtual void OnPaint() |
1377 SetDParam(1, p->index); |
1363 { |
1378 DrawWindowWidgets(w); |
1364 Player *p = GetPlayer((PlayerID)this->window_number); |
1379 |
1365 SetDParam(0, STR_COMPANY_NAME); |
1380 DrawPlayerFace(p->face, p->player_color, 2, 16); |
1366 SetDParam(1, p->index); |
1381 |
1367 this->DrawWidgets(); |
1382 SetDParam(0, p->index); |
1368 |
1383 SetDParam(1, p->bankrupt_value); |
1369 DrawPlayerFace(p->face, p->player_color, 2, 16); |
1384 DrawStringMultiCenter(214, 65, STR_705B_WE_ARE_LOOKING_FOR_A_TRANSPORT, 238); |
1370 |
1385 } break; |
1371 SetDParam(0, p->index); |
1386 |
1372 SetDParam(1, p->bankrupt_value); |
1387 case WE_CLICK: |
1373 DrawStringMultiCenter(214, 65, STR_705B_WE_ARE_LOOKING_FOR_A_TRANSPORT, 238); |
1388 switch (e->we.click.widget) { |
1374 } |
1389 case 3: |
1375 |
1390 delete w; |
1376 virtual void OnClick(Point pt, int widget) |
1391 break; |
1377 { |
1392 case 4: { |
1378 switch (widget) { |
1393 DoCommandP(0, w->window_number, 0, NULL, CMD_BUY_COMPANY | CMD_MSG(STR_7060_CAN_T_BUY_COMPANY)); |
1379 case 3: |
1394 break; |
1380 delete this; |
1395 } |
1381 break; |
1396 } |
1382 |
1397 break; |
1383 case 4: |
1398 } |
1384 DoCommandP(0, this->window_number, 0, NULL, CMD_BUY_COMPANY | CMD_MSG(STR_7060_CAN_T_BUY_COMPANY)); |
1399 } |
1385 break; |
|
1386 } |
|
1387 } |
|
1388 }; |
1400 |
1389 |
1401 static const Widget _buy_company_widgets[] = { |
1390 static const Widget _buy_company_widgets[] = { |
1402 { WWT_CLOSEBOX, RESIZE_NONE, 5, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, |
1391 { WWT_CLOSEBOX, RESIZE_NONE, 5, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, |
1403 { WWT_CAPTION, RESIZE_NONE, 5, 11, 333, 0, 13, STR_00B3_MESSAGE_FROM, STR_018C_WINDOW_TITLE_DRAG_THIS}, |
1392 { WWT_CAPTION, RESIZE_NONE, 5, 11, 333, 0, 13, STR_00B3_MESSAGE_FROM, STR_018C_WINDOW_TITLE_DRAG_THIS}, |
1404 { WWT_PANEL, RESIZE_NONE, 5, 0, 333, 14, 136, 0x0, STR_NULL}, |
1393 { WWT_PANEL, RESIZE_NONE, 5, 0, 333, 14, 136, 0x0, STR_NULL}, |
1410 static const WindowDesc _buy_company_desc = { |
1399 static const WindowDesc _buy_company_desc = { |
1411 153, 171, 334, 137, 334, 137, |
1400 153, 171, 334, 137, 334, 137, |
1412 WC_BUY_COMPANY, WC_NONE, |
1401 WC_BUY_COMPANY, WC_NONE, |
1413 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, |
1402 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, |
1414 _buy_company_widgets, |
1403 _buy_company_widgets, |
1415 BuyCompanyWndProc |
|
1416 }; |
1404 }; |
1417 |
1405 |
1418 |
1406 |
1419 void ShowBuyCompanyDialog(uint player) |
1407 void ShowBuyCompanyDialog(uint player) |
1420 { |
1408 { |
1421 AllocateWindowDescFront<Window>(&_buy_company_desc, player); |
1409 AllocateWindowDescFront<BuyCompanyWindow>(&_buy_company_desc, player); |
1422 } |
1410 } |
1423 |
1411 |
1424 /********** HIGHSCORE and ENDGAME windows */ |
1412 /********** HIGHSCORE and ENDGAME windows */ |
1425 |
1413 |
1426 /* Always draw a maximized window and within there the centered background */ |
1414 extern StringID EndGameGetPerformanceTitleFromValue(uint value); |
1427 static void SetupHighScoreEndWindow(Window *w, uint *x, uint *y) |
1415 |
|
1416 |
|
1417 struct EndGameHighScoreBaseWindow : Window |
1428 { |
1418 { |
1429 uint i; |
1419 uint32 background_img; |
1430 /* resize window to "full-screen" */ |
1420 int8 rank; |
1431 w->width = _screen.width; |
1421 |
1432 w->height = _screen.height; |
1422 EndGameHighScoreBaseWindow(const WindowDesc *desc) : Window(desc) |
1433 w->widget[0].right = w->width - 1; |
1423 { |
1434 w->widget[0].bottom = w->height - 1; |
1424 } |
1435 |
1425 |
1436 DrawWindowWidgets(w); |
1426 /* Always draw a maximized window and within there the centered background */ |
1437 |
1427 void SetupHighScoreEndWindow(uint *x, uint *y) |
1438 /* Center Highscore/Endscreen background */ |
1428 { |
1439 *x = max(0, (_screen.width / 2) - (640 / 2)); |
1429 /* resize window to "full-screen" */ |
1440 *y = max(0, (_screen.height / 2) - (480 / 2)); |
1430 this->width = _screen.width; |
1441 for (i = 0; i < 10; i++) // the image is split into 10 50px high parts |
1431 this->height = _screen.height; |
1442 DrawSprite(WP(w, highscore_d).background_img + i, PAL_NONE, *x, *y + (i * 50)); |
1432 this->widget[0].right = this->width - 1; |
1443 } |
1433 this->widget[0].bottom = this->height - 1; |
1444 |
1434 |
1445 extern StringID EndGameGetPerformanceTitleFromValue(uint value); |
1435 this->DrawWidgets(); |
|
1436 |
|
1437 /* Center Highscore/Endscreen background */ |
|
1438 *x = max(0, (_screen.width / 2) - (640 / 2)); |
|
1439 *y = max(0, (_screen.height / 2) - (480 / 2)); |
|
1440 for (uint i = 0; i < 10; i++) { // the image is split into 10 50px high parts |
|
1441 DrawSprite(this->background_img + i, PAL_NONE, *x, *y + (i * 50)); |
|
1442 } |
|
1443 } |
|
1444 |
|
1445 virtual void OnClick(Point pt, int widget) |
|
1446 { |
|
1447 delete this; |
|
1448 } |
|
1449 }; |
1446 |
1450 |
1447 /** End game window shown at the end of the game */ |
1451 /** End game window shown at the end of the game */ |
1448 static void EndGameWndProc(Window *w, WindowEvent *e) |
1452 struct EndGameWindow : EndGameHighScoreBaseWindow { |
|
1453 EndGameWindow(const WindowDesc *desc) : EndGameHighScoreBaseWindow(desc) |
|
1454 { |
|
1455 /* Pause in single-player to have a look at the highscore at your own leisure */ |
|
1456 if (!_networking) DoCommandP(0, 1, 0, NULL, CMD_PAUSE); |
|
1457 |
|
1458 this->background_img = SPR_TYCOON_IMG1_BEGIN; |
|
1459 |
|
1460 if (_local_player != PLAYER_SPECTATOR) { |
|
1461 const Player *p = GetPlayer(_local_player); |
|
1462 if (p->old_economy[0].performance_history == SCORE_MAX) { |
|
1463 this->background_img = SPR_TYCOON_IMG2_BEGIN; |
|
1464 } |
|
1465 } |
|
1466 |
|
1467 /* In a network game show the endscores of the custom difficulty 'network' which is the last one |
|
1468 * as well as generate a TOP5 of that game, and not an all-time top5. */ |
|
1469 if (_networking) { |
|
1470 this->window_number = lengthof(_highscore_table) - 1; |
|
1471 this->rank = SaveHighScoreValueNetwork(); |
|
1472 } else { |
|
1473 /* in single player _local player is always valid */ |
|
1474 const Player *p = GetPlayer(_local_player); |
|
1475 this->window_number = _opt.diff_level; |
|
1476 this->rank = SaveHighScoreValue(p); |
|
1477 } |
|
1478 |
|
1479 MarkWholeScreenDirty(); |
|
1480 } |
|
1481 |
|
1482 ~EndGameWindow() |
|
1483 { |
|
1484 if (!_networking) DoCommandP(0, 0, 0, NULL, CMD_PAUSE); // unpause |
|
1485 ShowHighscoreTable(this->window_number, this->rank); |
|
1486 } |
|
1487 |
|
1488 virtual void OnPaint() |
|
1489 { |
|
1490 const Player *p; |
|
1491 uint x, y; |
|
1492 |
|
1493 this->SetupHighScoreEndWindow(&x, &y); |
|
1494 |
|
1495 if (!IsValidPlayer(_local_player)) return; |
|
1496 |
|
1497 p = GetPlayer(_local_player); |
|
1498 /* We need to get performance from last year because the image is shown |
|
1499 * at the start of the new year when these things have already been copied */ |
|
1500 if (this->background_img == SPR_TYCOON_IMG2_BEGIN) { // Tycoon of the century \o/ |
|
1501 SetDParam(0, p->index); |
|
1502 SetDParam(1, p->index); |
|
1503 SetDParam(2, EndGameGetPerformanceTitleFromValue(p->old_economy[0].performance_history)); |
|
1504 DrawStringMultiCenter(x + (640 / 2), y + 107, STR_021C_OF_ACHIEVES_STATUS, 640); |
|
1505 } else { |
|
1506 SetDParam(0, p->index); |
|
1507 SetDParam(1, EndGameGetPerformanceTitleFromValue(p->old_economy[0].performance_history)); |
|
1508 DrawStringMultiCenter(x + (640 / 2), y + 157, STR_021B_ACHIEVES_STATUS, 640); |
|
1509 } |
|
1510 } |
|
1511 }; |
|
1512 |
|
1513 struct HighScoreWindow : EndGameHighScoreBaseWindow |
1449 { |
1514 { |
1450 switch (e->event) { |
1515 HighScoreWindow(const WindowDesc *desc, int difficulty, int8 ranking) : EndGameHighScoreBaseWindow(desc) |
1451 case WE_PAINT: { |
1516 { |
1452 const Player *p; |
1517 /* pause game to show the chart */ |
1453 uint x, y; |
1518 if (!_networking) DoCommandP(0, 1, 0, NULL, CMD_PAUSE); |
1454 |
1519 |
1455 SetupHighScoreEndWindow(w, &x, &y); |
1520 /* Close all always on-top windows to get a clean screen */ |
1456 |
1521 if (_game_mode != GM_MENU) HideVitalWindows(); |
1457 if (!IsValidPlayer(_local_player)) break; |
1522 |
1458 |
1523 MarkWholeScreenDirty(); |
1459 p = GetPlayer(_local_player); |
1524 this->window_number = difficulty; // show highscore chart for difficulty... |
1460 /* We need to get performance from last year because the image is shown |
1525 this->background_img = SPR_HIGHSCORE_CHART_BEGIN; // which background to show |
1461 * at the start of the new year when these things have already been copied */ |
1526 this->rank = ranking; |
1462 if (WP(w, highscore_d).background_img == SPR_TYCOON_IMG2_BEGIN) { // Tycoon of the century \o/ |
1527 } |
1463 SetDParam(0, p->index); |
1528 |
1464 SetDParam(1, p->index); |
1529 ~HighScoreWindow() |
1465 SetDParam(2, EndGameGetPerformanceTitleFromValue(p->old_economy[0].performance_history)); |
1530 { |
1466 DrawStringMultiCenter(x + (640 / 2), y + 107, STR_021C_OF_ACHIEVES_STATUS, 640); |
1531 if (_game_mode != GM_MENU) ShowVitalWindows(); |
1467 } else { |
1532 |
1468 SetDParam(0, p->index); |
1533 if (!_networking) DoCommandP(0, 0, 0, NULL, CMD_PAUSE); // unpause |
1469 SetDParam(1, EndGameGetPerformanceTitleFromValue(p->old_economy[0].performance_history)); |
1534 } |
1470 DrawStringMultiCenter(x + (640 / 2), y + 157, STR_021B_ACHIEVES_STATUS, 640); |
1535 |
|
1536 virtual void OnPaint() |
|
1537 { |
|
1538 const HighScore *hs = _highscore_table[this->window_number]; |
|
1539 uint x, y; |
|
1540 |
|
1541 this->SetupHighScoreEndWindow(&x, &y); |
|
1542 |
|
1543 SetDParam(0, _patches.ending_year); |
|
1544 SetDParam(1, this->window_number + STR_6801_EASY); |
|
1545 DrawStringMultiCenter(x + (640 / 2), y + 62, !_networking ? STR_0211_TOP_COMPANIES_WHO_REACHED : STR_TOP_COMPANIES_NETWORK_GAME, 500); |
|
1546 |
|
1547 /* Draw Highscore peepz */ |
|
1548 for (uint8 i = 0; i < lengthof(_highscore_table[0]); i++) { |
|
1549 SetDParam(0, i + 1); |
|
1550 DrawString(x + 40, y + 140 + (i * 55), STR_0212, TC_BLACK); |
|
1551 |
|
1552 if (hs[i].company[0] != '\0') { |
|
1553 TextColour colour = (this->rank == i) ? TC_RED : TC_BLACK; // draw new highscore in red |
|
1554 |
|
1555 DoDrawString(hs[i].company, x + 71, y + 140 + (i * 55), colour); |
|
1556 SetDParam(0, hs[i].title); |
|
1557 SetDParam(1, hs[i].score); |
|
1558 DrawString(x + 71, y + 160 + (i * 55), STR_HIGHSCORE_STATS, colour); |
1471 } |
1559 } |
1472 } break; |
1560 } |
1473 |
1561 } |
1474 case WE_CLICK: /* Close the window (and show the highscore window) */ |
1562 }; |
1475 delete w; |
|
1476 break; |
|
1477 |
|
1478 case WE_DESTROY: /* Show the highscore window when this one is closed */ |
|
1479 if (!_networking) DoCommandP(0, 0, 0, NULL, CMD_PAUSE); // unpause |
|
1480 ShowHighscoreTable(w->window_number, WP(w, highscore_d).rank); |
|
1481 break; |
|
1482 } |
|
1483 } |
|
1484 |
|
1485 static void HighScoreWndProc(Window *w, WindowEvent *e) |
|
1486 { |
|
1487 switch (e->event) { |
|
1488 case WE_PAINT: { |
|
1489 const HighScore *hs = _highscore_table[w->window_number]; |
|
1490 uint x, y; |
|
1491 uint8 i; |
|
1492 |
|
1493 SetupHighScoreEndWindow(w, &x, &y); |
|
1494 |
|
1495 SetDParam(0, _patches.ending_year); |
|
1496 SetDParam(1, w->window_number + STR_6801_EASY); |
|
1497 DrawStringMultiCenter(x + (640 / 2), y + 62, !_networking ? STR_0211_TOP_COMPANIES_WHO_REACHED : STR_TOP_COMPANIES_NETWORK_GAME, 500); |
|
1498 |
|
1499 /* Draw Highscore peepz */ |
|
1500 for (i = 0; i < lengthof(_highscore_table[0]); i++) { |
|
1501 SetDParam(0, i + 1); |
|
1502 DrawString(x + 40, y + 140 + (i * 55), STR_0212, TC_BLACK); |
|
1503 |
|
1504 if (hs[i].company[0] != '\0') { |
|
1505 TextColour colour = (WP(w, highscore_d).rank == (int8)i) ? TC_RED : TC_BLACK; // draw new highscore in red |
|
1506 |
|
1507 DoDrawString(hs[i].company, x + 71, y + 140 + (i * 55), colour); |
|
1508 SetDParam(0, hs[i].title); |
|
1509 SetDParam(1, hs[i].score); |
|
1510 DrawString(x + 71, y + 160 + (i * 55), STR_HIGHSCORE_STATS, colour); |
|
1511 } |
|
1512 } |
|
1513 } break; |
|
1514 |
|
1515 case WE_CLICK: /* Onclick to close window, and in destroy event handle the rest */ |
|
1516 delete w; |
|
1517 break; |
|
1518 |
|
1519 case WE_DESTROY: /* Get back all the hidden windows */ |
|
1520 if (_game_mode != GM_MENU) ShowVitalWindows(); |
|
1521 |
|
1522 if (!_networking) DoCommandP(0, 0, 0, NULL, CMD_PAUSE); // unpause |
|
1523 break; |
|
1524 } |
|
1525 } |
|
1526 |
1563 |
1527 static const Widget _highscore_widgets[] = { |
1564 static const Widget _highscore_widgets[] = { |
1528 { WWT_PANEL, RESIZE_NONE, 16, 0, 640, 0, 480, 0x0, STR_NULL}, |
1565 { WWT_PANEL, RESIZE_NONE, 16, 0, 640, 0, 480, 0x0, STR_NULL}, |
1529 { WIDGETS_END}, |
1566 { WIDGETS_END}, |
1530 }; |
1567 }; |