From b03c2ab77afcbd9cba6ec552bf5dbbb3e8e316d4 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Tue, 12 Aug 2014 00:27:25 +0100 Subject: [PATCH] implement new campaign window --- src/game.h | 2 +- src/string_ids.h | 6 + src/widget.c | 6 +- src/window.h | 10 + src/window_new_campaign.c | 390 +++++++++++++++++++++++++++++++++++++- 5 files changed, 408 insertions(+), 6 deletions(-) diff --git a/src/game.h b/src/game.h index a0635bb4f5..900873f8d1 100644 --- a/src/game.h +++ b/src/game.h @@ -70,7 +70,7 @@ enum GAME_COMMAND { GAME_COMMAND_SET_CURRENT_LOAN, GAME_COMMAND_46, GAME_COMMAND_47, - GAME_COMMAND_48, + GAME_COMMAND_START_MARKETING_CAMPAIGN, GAME_COMMAND_49, GAME_COMMAND_50, GAME_COMMAND_51, diff --git a/src/string_ids.h b/src/string_ids.h index a462ab6a4b..f60c52950f 100644 --- a/src/string_ids.h +++ b/src/string_ids.h @@ -587,6 +587,11 @@ enum { STR_MARKETING_CAMPAIGNS_AVAILABLE = 2411, STR_START_THIS_MARKETING_CAMPAIGN = 2412, STR_MARKETING_PER_WEEK = 2413, + STR_MARKETING_NOT_SELECTED = 2414, + STR_MARKETING_RIDE = 2415, + STR_MARKETING_ITEM = 2416, + + STR_LENGTH_OF_TIME = 2417, STR_MARKETING_VOUCHERS_FOR_FREE_ENTRY_TO_THE_PARK = 2424, STR_MARKETING_VOUCHERS_FOR_FREE_RIDES_ON_A_PARTICULAR_RIDE = 2425, @@ -733,6 +738,7 @@ enum { STR_TUTORIAL = 2856, STR_PRESS_KEY_OR_MOUSE_BUTTON_FOR_CONTROL = 2857, + STR_CANT_START_MARKETING_CAMPAIGN = 2858, STR_INFOGRAMES_INTERACTIVE_CREDITS = 2860, STR_LICENSED_TO_INFOGRAMES_INTERACTIVE_INC = 2861, diff --git a/src/widget.c b/src/widget.c index 3b39727f08..3cf0aeb95c 100644 --- a/src/widget.c +++ b/src/widget.c @@ -157,8 +157,6 @@ void widget_draw(rct_drawpixelinfo *dpi, rct_window *w, int widgetIndex) widget_scroll_draw(dpi, w, widgetIndex); break; case WWT_CHECKBOX: - widget_checkbox_draw(dpi, w, widgetIndex); - break; case WWT_24: widget_checkbox_draw(dpi, w, widgetIndex); break; @@ -414,9 +412,9 @@ static void widget_text_unknown(rct_drawpixelinfo *dpi, rct_window *w, int widge widget = &w->widgets[widgetIndex]; // Get the colour -// colour = w->colours[widget->colour]; + colour = w->colours[widget->colour]; // do not use widget color as this is already used as background for the text_button - colour = 2; + // colour = 2; // Resolve the absolute ltrb l = w->x + widget->left; diff --git a/src/window.h b/src/window.h index 6aebd03301..ed999dc2b1 100644 --- a/src/window.h +++ b/src/window.h @@ -394,6 +394,11 @@ void window_event_helper(rct_window* w, short widgetIndex, WINDOW_EVENTS event); __asm mov widgetIndex, dx \ __asm mov w, esi + #define window_dropdown_get_registers(w, widgetIndex, dropdownIndex) \ + __asm mov dropdownIndex, ax \ + __asm mov widgetIndex, dx \ + __asm mov w, esi + #define window_paint_get_registers(w, dpi) \ __asm mov w, esi \ __asm mov dpi, edi @@ -405,6 +410,11 @@ void window_event_helper(rct_window* w, short widgetIndex, WINDOW_EVENTS event); __asm__ ( "mov %[widgetIndex], dx " : [widgetIndex] "+m" (widgetIndex) ); \ __asm__ ( "mov %[w], esi " : [w] "+m" (w) ); + #define window_dropdown_get_registers(w, widgetIndex, dropdownIndex) \ + __asm__ ( "mov %[dropdownIndex], ax " : [dropdownIndex] "+m" (dropdownIndex) ); \ + __asm__ ( "mov %[widgetIndex], dx " : [widgetIndex] "+m" (widgetIndex) ); \ + __asm__ ( "mov %[w], esi " : [w] "+m" (w) ); + #define window_paint_get_registers(w, dpi) \ __asm__ ( "mov %[w], esi " : [w] "+m" (w) ); \ __asm__ ( "mov %[dpi], edi " : [dpi] "+m" (dpi) ); diff --git a/src/window_new_campaign.c b/src/window_new_campaign.c index ac772cc39f..30445ec4ea 100644 --- a/src/window_new_campaign.c +++ b/src/window_new_campaign.c @@ -18,8 +18,111 @@ * along with this program. If not, see . *****************************************************************************/ +#include #include "addresses.h" +#include "game.h" +#include "marketing.h" +#include "ride.h" +#include "string_ids.h" +#include "widget.h" #include "window.h" +#include "window_dropdown.h" + +#define SELECTED_RIDE_UNDEFINED ((sint16)0xFFFF) + +enum WINDOW_NEW_CAMPAIGN_WIDGET_IDX { + WIDX_BACKGROUND, + WIDX_TITLE, + WIDX_CLOSE, + WIDX_RIDE_LABEL, + WIDX_RIDE_DROPDOWN, + WIDX_RIDE_DROPDOWN_BUTTON, + WIDX_WEEKS_LABEL, + WIDX_WEEKS_SPINNER, + WIDX_WEEKS_INCREASE_BUTTON, + WIDX_WEEKS_DECREASE_BUTTON, + WIDX_START_BUTTON +}; + +static rct_widget window_new_campaign_widgets[] = { + { WWT_FRAME, 0, 0, 349, 0, 106, 0xFFFFFFFF, STR_NONE }, // panel / background + { WWT_CAPTION, 0, 1, 348, 1, 14, 0, STR_WINDOW_TITLE_TIP }, // title bar + { WWT_CLOSEBOX, 0, 337, 347, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, // close x button + { WWT_24, 0, 0, 139, 24, 35, 0, STR_NONE }, // ride label + { WWT_DROPDOWN, 0, 100, 341, 24, 35, 0, STR_NONE }, // ride dropdown + { WWT_DROPDOWN_BUTTON, 0, 330, 340, 25, 34, 876, STR_NONE }, // ride dropdown button + { WWT_24, 0, 0, 139, 41, 52, STR_LENGTH_OF_TIME, STR_NONE }, // weeks label + { WWT_SPINNER, 0, 120, 219, 41, 52, 0, STR_NONE }, // weeks + { WWT_DROPDOWN_BUTTON, 0, 208, 218, 42, 46, STR_NUMERIC_UP, STR_NONE }, // weeks + + { WWT_DROPDOWN_BUTTON, 0, 208, 218, 47, 51, STR_NUMERIC_DOWN, STR_NONE }, // weeks - + { WWT_DROPDOWN_BUTTON, 0, 14, 335, 89, 100, STR_MARKETING_START_THIS_MARKETING_CAMPAIGN, STR_NONE }, // start button + { WIDGETS_END } +}; + + +static void window_new_campaign_emptysub() { } +static void window_new_campaign_mouseup(); +static void window_new_campaign_mousedown(int widgetIndex, rct_window*w, rct_widget* widget); +static void window_new_campaign_dropdown(); +static void window_new_campaign_invalidate(); +static void window_new_campaign_paint(); + +static void* window_new_campaign_events[] = { + window_new_campaign_emptysub, + window_new_campaign_mouseup, + window_new_campaign_emptysub, + window_new_campaign_mousedown, + window_new_campaign_dropdown, + window_new_campaign_emptysub, + window_new_campaign_emptysub, + window_new_campaign_emptysub, + window_new_campaign_emptysub, + window_new_campaign_emptysub, + window_new_campaign_emptysub, + window_new_campaign_emptysub, + window_new_campaign_emptysub, + window_new_campaign_emptysub, + window_new_campaign_emptysub, + window_new_campaign_emptysub, + window_new_campaign_emptysub, + window_new_campaign_emptysub, + window_new_campaign_emptysub, + window_new_campaign_emptysub, + window_new_campaign_emptysub, + window_new_campaign_emptysub, + window_new_campaign_emptysub, + window_new_campaign_emptysub, + window_new_campaign_emptysub, + window_new_campaign_invalidate, + window_new_campaign_paint, + window_new_campaign_emptysub +}; + +uint8 window_new_campaign_rides[MAX_RIDES]; +uint8 window_new_campaign_shop_items[64]; + +int ride_reliability_compare(const void *a, const void *b) +{ + rct_ride *rideA, *rideB; + + rideA = GET_RIDE(*((uint8*)a)); + rideB = GET_RIDE(*((uint8*)b)); + return rideB->reliability - rideA->reliability; +} + +int ride_name_compare(const void *a, const void *b) +{ + char rideAName[256], rideBName[256]; + rct_ride *rideA, *rideB; + + rideA = GET_RIDE(*((uint8*)a)); + rideB = GET_RIDE(*((uint8*)b)); + + format_string(rideAName, rideA->var_04A, &rideA->var_04C); + format_string(rideBName, rideB->var_04A, &rideB->var_04C); + + return _strcmpi(rideAName, rideBName); +} /** * @@ -27,5 +130,290 @@ */ void window_new_campaign_open(int campaignType) { - RCT2_CALLPROC_X(0x0069E16F, campaignType, 0, 0, 0, 0, 0, 0); + // RCT2_CALLPROC_X(0x0069E16F, campaignType, 0, 0, 0, 0, 0, 0); + + rct_window *w; + rct_ride *ride; + int i, numApplicableRides; + + w = window_bring_to_front_by_id(WC_NEW_CAMPAIGN, 0); + if (w != NULL) { + if (w->var_480 == campaignType) + return; + + window_close(w); + } + + w = window_create_auto_pos(350, 107, (uint32*)window_new_campaign_events, WC_NEW_CAMPAIGN, 0); + w->widgets = window_new_campaign_widgets; + w->enabled_widgets = + (1 << WIDX_CLOSE) | + (1 << WIDX_RIDE_DROPDOWN) | + (1 << WIDX_RIDE_DROPDOWN_BUTTON) | + (1 << WIDX_WEEKS_INCREASE_BUTTON) | + (1 << WIDX_WEEKS_DECREASE_BUTTON) | + (1 << WIDX_START_BUTTON); + w->var_020 = 0x300; + window_init_scroll_widgets(w); + w->colours[0] = 19; + w->colours[1] = 19; + w->colours[2] = 19; + + window_new_campaign_widgets[WIDX_TITLE].image = STR_MARKETING_VOUCHERS_FOR_FREE_ENTRY_TO_THE_PARK + campaignType; + + // Campaign type + w->var_480 = campaignType; + + // Number of weeks + w->var_482 = 2; + + // Currently selected ride + w->var_484 = SELECTED_RIDE_UNDEFINED; + + // Get all applicable rides + numApplicableRides = 0; + window_new_campaign_rides[0] = 255; + FOR_ALL_RIDES(i, ride) { + if (!(RCT2_GLOBAL(0x0097CF40 + (ride->type * 8), uint32) & 0x03820000)) + window_new_campaign_rides[numApplicableRides++] = i; + } + window_new_campaign_rides[numApplicableRides] = 255; + + // Take top 40 most reliable rides + if (numApplicableRides > 40) { + qsort(window_new_campaign_rides, countof(window_new_campaign_rides), sizeof(uint8), ride_reliability_compare); + numApplicableRides = 40; + } + + // Sort rides by name + qsort(window_new_campaign_rides, numApplicableRides, sizeof(uint8), ride_name_compare); +} + +/** + * + * rct2: 0x0069E320 + */ +static void window_new_campaign_get_shop_items() +{ + int i, numItems; + rct_ride *ride; + + uint64 items = 0; + FOR_ALL_RIDES(i, ride) { + uint8 *rideTypeInfo = RCT2_ADDRESS(0x009ACFA4, void*)[ride->subtype]; + uint8 itemType = RCT2_GLOBAL(rideTypeInfo + 0x1C0, uint8); + if (itemType != 255) + items |= 1LL << itemType; + } + + // Remove certain items? + items &= 0x0011FF78036BA3E0; + + // + numItems = 0; + for (i = 0; i < 64; i++) + if (items & (1LL << i)) + window_new_campaign_shop_items[numItems++] = i; + window_new_campaign_shop_items[numItems] = 255; +} + +/** + * + * rct2: 0x0069E50B + */ +static void window_new_campaign_mouseup() +{ + rct_window *w; + short widgetIndex; + + window_mouse_up_get_registers(w, widgetIndex); + + switch (widgetIndex) { + case WIDX_CLOSE: + window_close(w); + break; + case WIDX_START_BUTTON: + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_START_MARKETING_CAMPAIGN; + game_do_command(0, (w->var_482 << 8) | 1, 0, (w->var_484 << 8) | w->var_480, GAME_COMMAND_START_MARKETING_CAMPAIGN, 0, 0); + window_close(w); + break; + } +} + +/** + * + * rct2: 0x0069E51C + */ +static void window_new_campaign_mousedown(int widgetIndex, rct_window *w, rct_widget* widget) +{ + rct_widget *dropdownWidget; + + switch (widgetIndex) { + case WIDX_RIDE_DROPDOWN_BUTTON: + dropdownWidget = widget - 1; + + if (w->var_480 == ADVERTISING_CAMPAIGN_FOOD_OR_DRINK_FREE) { + window_new_campaign_get_shop_items(); + if (window_new_campaign_shop_items[0] != 255) { + int numItems = 0; + for (int i = 0; i < 40; i++) { + if (window_new_campaign_shop_items[i] == 255) + break; + + rct_string_id itemStringId = window_new_campaign_shop_items[i] + 2016; + if (itemStringId >= 2048) + itemStringId += 96; + + gDropdownItemsFormat[i] = 1142; + gDropdownItemsArgs[i] = itemStringId; + numItems++; + } + + window_dropdown_show_text_custom_width( + w->x + dropdownWidget->left, + w->y + dropdownWidget->top, + dropdownWidget->bottom - dropdownWidget->top + 1, + w->colours[1], + 0x80, + numItems, + dropdownWidget->right - dropdownWidget->left - 3 + ); + } + } else { + if (window_new_campaign_rides[0] != 255) { + int numItems = 0; + for (int i = 0; i < 40; i++) { + if (window_new_campaign_rides[i] == 255) + break; + + rct_ride *ride = GET_RIDE(window_new_campaign_rides[i]); + gDropdownItemsFormat[i] = 1142; + gDropdownItemsArgs[i] = (ride->var_04C << 16) | ride->var_04A; + numItems++; + } + + window_dropdown_show_text_custom_width( + w->x + dropdownWidget->left, + w->y + dropdownWidget->top, + dropdownWidget->bottom - dropdownWidget->top + 1, + w->colours[1], + 0x80, + numItems, + dropdownWidget->right - dropdownWidget->left - 3 + ); + } + } + break; + case WIDX_WEEKS_INCREASE_BUTTON: + w->var_482 = min(w->var_482 + 1, 6); + window_invalidate(w); + break; + case WIDX_WEEKS_DECREASE_BUTTON: + w->var_482 = max(w->var_482 - 1, 2); + window_invalidate(w); + break; + } +} + +/** + * + * rct2: 0x0069E537 + */ +static void window_new_campaign_dropdown() +{ + rct_window *w; + short widgetIndex, dropdownIndex; + + window_dropdown_get_registers(w, widgetIndex, dropdownIndex); + + if (widgetIndex != WIDX_RIDE_DROPDOWN_BUTTON) + return; + + if (w->var_480 == ADVERTISING_CAMPAIGN_FOOD_OR_DRINK_FREE) { + rct_string_id itemStringId = (uint16)gDropdownItemsArgs[dropdownIndex] - 2016; + if (itemStringId >= 32) + itemStringId -= 96; + w->var_484 = itemStringId; + } else { + w->var_484 = window_new_campaign_rides[dropdownIndex]; + } + + window_invalidate(w); +} + +/** + * + * rct2: 0x0069E397 + */ +static void window_new_campaign_invalidate() +{ + rct_window *w; + + window_get_register(w); + + window_new_campaign_widgets[WIDX_RIDE_LABEL].type = WWT_EMPTY; + window_new_campaign_widgets[WIDX_RIDE_DROPDOWN].type = WWT_EMPTY; + window_new_campaign_widgets[WIDX_RIDE_DROPDOWN_BUTTON].type = WWT_EMPTY; + window_new_campaign_widgets[WIDX_RIDE_DROPDOWN].image = STR_MARKETING_NOT_SELECTED; + switch (w->var_480) { + case ADVERTISING_CAMPAIGN_RIDE_FREE: + case ADVERTISING_CAMPAIGN_RIDE: + window_new_campaign_widgets[WIDX_RIDE_LABEL].type = WWT_24; + window_new_campaign_widgets[WIDX_RIDE_DROPDOWN].type = WWT_DROPDOWN; + window_new_campaign_widgets[WIDX_RIDE_DROPDOWN_BUTTON].type = WWT_DROPDOWN_BUTTON; + window_new_campaign_widgets[WIDX_RIDE_LABEL].image = STR_MARKETING_RIDE; + if (w->var_484 != SELECTED_RIDE_UNDEFINED) { + rct_ride *ride = GET_RIDE(w->var_484); + window_new_campaign_widgets[WIDX_RIDE_DROPDOWN].image = ride->var_04A; + RCT2_GLOBAL(0x013CE952, uint32) = ride->var_04C; + } + break; + case ADVERTISING_CAMPAIGN_FOOD_OR_DRINK_FREE: + window_new_campaign_widgets[WIDX_RIDE_LABEL].type = WWT_24; + window_new_campaign_widgets[WIDX_RIDE_DROPDOWN].type = WWT_DROPDOWN; + window_new_campaign_widgets[WIDX_RIDE_DROPDOWN_BUTTON].type = WWT_DROPDOWN_BUTTON; + window_new_campaign_widgets[WIDX_RIDE_LABEL].image = STR_MARKETING_ITEM; + if (w->var_484 != SELECTED_RIDE_UNDEFINED) { + rct_string_id itemStringId = w->var_484 + 2016; + if (itemStringId >= 2048) + itemStringId += 96; + window_new_campaign_widgets[WIDX_RIDE_DROPDOWN].image = itemStringId; + } + break; + } + + // Set current number of weeks spinner + window_new_campaign_widgets[WIDX_WEEKS_SPINNER].image = (STR_MARKETING_1_WEEK - 1) + w->var_482; + + // Enable / disable start button based on ride dropdown + w->disabled_widgets &= ~(1 << WIDX_START_BUTTON); + if (window_new_campaign_widgets[WIDX_RIDE_DROPDOWN].type == WWT_DROPDOWN && w->var_484 == SELECTED_RIDE_UNDEFINED) + w->disabled_widgets |= 1 << WIDX_START_BUTTON; +} + +/** + * + * rct2: 0x0069E493 + */ +static void window_new_campaign_paint() +{ + rct_window *w; + rct_drawpixelinfo *dpi; + int x, y; + + window_paint_get_registers(w, dpi); + + window_draw_widgets(w, dpi); + + x = w->x + 14; + y = w->y + 60; + + // Price per week + money32 pricePerWeek = AdvertisingCampaignPricePerWeek[w->var_480]; + gfx_draw_string_left(dpi, STR_MARKETING_COST_PER_WEEK, &pricePerWeek, 0, x, y); + y += 13; + + // Total price + money32 totalPrice = AdvertisingCampaignPricePerWeek[w->var_480] * w->var_482; + gfx_draw_string_left(dpi, STR_MARKETING_TOTAL_COST, &totalPrice, 0, x, y); } \ No newline at end of file