1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-15 11:03:00 +01:00

Merge pull request #5993 from wolfreak99/improved_window_inputs/ride_price_textinput

Make ride window prices allow text input
This commit is contained in:
Michael Steenbeek
2018-06-15 10:09:37 +02:00
committed by GitHub
5 changed files with 122 additions and 53 deletions

View File

@@ -1,5 +1,6 @@
0.2.0+ (in development)
------------------------------------------------------------------------
- Feature: [#5993] Ride window prices can now be set via text input.
- Feature: [#6998] Guests now wait for passing vehicles before crossing railway tracks.
- Fix: [#7628] Always-researched items can be modified in the inventory list.
- Fix: [#7643] No Money scenarios with funding set to zero.

View File

@@ -806,7 +806,7 @@ static void window_cheats_money_mouseup(rct_window *w, rct_widgetindex widgetInd
game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_NOMONEY, gParkFlags & PARK_FLAGS_NO_MONEY ? 0 : 1, GAME_COMMAND_CHEAT, 0, 0);
break;
case WIDX_MONEY_SPINNER:
money_to_string(_moneySpinnerValue, _moneySpinnerText, MONEY_STRING_MAXLENGTH);
money_to_string(_moneySpinnerValue, _moneySpinnerText, MONEY_STRING_MAXLENGTH, false);
window_text_input_raw_open(w, WIDX_MONEY_SPINNER, STR_ENTER_NEW_VALUE, STR_ENTER_NEW_VALUE, _moneySpinnerText, MONEY_STRING_MAXLENGTH);
break;
case WIDX_SET_MONEY:

View File

@@ -465,9 +465,11 @@ static constexpr const uint64 window_ride_page_enabled_widgets[] = {
(1ULL << WIDX_GRAPH_VERTICAL) |
(1ULL << WIDX_GRAPH_LATERAL),
MAIN_RIDE_ENABLED_WIDGETS |
(1ULL << WIDX_PRIMARY_PRICE) |
(1ULL << WIDX_PRIMARY_PRICE_INCREASE) |
(1ULL << WIDX_PRIMARY_PRICE_DECREASE) |
(1ULL << WIDX_PRIMARY_PRICE_SAME_THROUGHOUT_PARK) |
(1ULL << WIDX_SECONDARY_PRICE) |
(1ULL << WIDX_SECONDARY_PRICE_INCREASE) |
(1ULL << WIDX_SECONDARY_PRICE_DECREASE) |
(1ULL << WIDX_SECONDARY_PRICE_SAME_THROUGHOUT_PARK),
@@ -591,6 +593,7 @@ static void window_ride_income_mouseup(rct_window *w, rct_widgetindex widgetInde
static void window_ride_income_resize(rct_window *w);
static void window_ride_income_mousedown(rct_window *w, rct_widgetindex widgetIndex, rct_widget *widget);
static void window_ride_income_update(rct_window *w);
static void window_ride_income_textinput(rct_window *w, rct_widgetindex widgetIndex, char *text);
static void window_ride_income_invalidate(rct_window *w);
static void window_ride_income_paint(rct_window *w, rct_drawpixelinfo *dpi);
static bool window_ride_income_can_modify_primary_price(rct_window* w);
@@ -880,7 +883,7 @@ static rct_window_event_list window_ride_income_events = {
nullptr,
nullptr,
nullptr,
nullptr,
window_ride_income_textinput,
nullptr,
nullptr,
nullptr,
@@ -5840,6 +5843,8 @@ static void window_ride_graphs_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi
#pragma region Income
static utf8 _moneyInputText[MONEY_STRING_MAXLENGTH];
static void update_same_price_throughout_flags(uint32 shop_item)
{
uint32 newFlags;
@@ -5922,6 +5927,11 @@ static void window_ride_income_toggle_secondary_price(rct_window *w)
game_do_command(0, 1, 0, (1 << 8) | w->number, GAME_COMMAND_SET_RIDE_PRICE, price, 0);
}
static void window_ride_income_set_primary_price(rct_window *w, money16 price)
{
game_do_command(0, GAME_COMMAND_FLAG_APPLY, 0, w->number, GAME_COMMAND_SET_RIDE_PRICE, price, 0);
}
/**
*
* rct2: 0x006AE1E4
@@ -5936,7 +5946,7 @@ static void window_ride_income_increase_primary_price(rct_window *w)
if (price < MONEY(20, 00))
price++;
game_do_command(0, 1, 0, w->number, GAME_COMMAND_SET_RIDE_PRICE, price, 0);
window_ride_income_set_primary_price(w, price);
}
/**
@@ -5953,7 +5963,19 @@ static void window_ride_income_decrease_primary_price(rct_window *w)
if (price > MONEY(0, 00))
price--;
game_do_command(0, 1, 0, w->number, GAME_COMMAND_SET_RIDE_PRICE, price, 0);
window_ride_income_set_primary_price(w, price);
}
static money16 window_ride_income_get_secondary_price(rct_window *w)
{
Ride *ride = get_ride(w->number);
money16 price = ride->price_secondary;
return price;
}
static void window_ride_income_set_secondary_price(rct_window *w, money16 price)
{
game_do_command(0, GAME_COMMAND_FLAG_APPLY, 0, (w->number & 0x00FF) | 0x0100, GAME_COMMAND_SET_RIDE_PRICE, price, 0);
}
static bool window_ride_income_can_modify_primary_price(rct_window* w)
@@ -5973,15 +5995,12 @@ static bool window_ride_income_can_modify_primary_price(rct_window* w)
*/
static void window_ride_income_increase_secondary_price(rct_window *w)
{
Ride *ride;
money16 price = window_ride_income_get_secondary_price(w);
ride = get_ride(w->number);
money16 price = ride->price_secondary;
if (price < MONEY(20, 00))
price++;
game_do_command(0, 1, 0, (w->number & 0x00FF) | 0x0100, GAME_COMMAND_SET_RIDE_PRICE, price, 0);
window_ride_income_set_secondary_price(w, price);
}
/**
@@ -5990,15 +6009,12 @@ static void window_ride_income_increase_secondary_price(rct_window *w)
*/
static void window_ride_income_decrease_secondary_price(rct_window *w)
{
Ride *ride;
ride = get_ride(w->number);
money16 price = ride->price_secondary;
money16 price = window_ride_income_get_secondary_price(w);
if (price > MONEY(0, 00))
price--;
game_do_command(0, 1, 0, (w->number & 0x00FF) | 0x0100, GAME_COMMAND_SET_RIDE_PRICE, price, 0);
window_ride_income_set_secondary_price(w, price);
}
/**
@@ -6007,7 +6023,8 @@ static void window_ride_income_decrease_secondary_price(rct_window *w)
*/
static void window_ride_income_mouseup(rct_window *w, rct_widgetindex widgetIndex)
{
switch (widgetIndex) {
switch (widgetIndex)
{
case WIDX_CLOSE:
window_close(w);
break;
@@ -6023,9 +6040,26 @@ static void window_ride_income_mouseup(rct_window *w, rct_widgetindex widgetInde
case WIDX_TAB_10:
window_ride_set_page(w, widgetIndex - WIDX_TAB_1);
break;
case WIDX_PRIMARY_PRICE:
{
if (!window_ride_income_can_modify_primary_price(w))
return;
Ride* ride = get_ride(w->number);
money_to_string((money32)ride->price, _moneyInputText, MONEY_STRING_MAXLENGTH, true);
window_text_input_raw_open(w, WIDX_PRIMARY_PRICE, STR_ENTER_NEW_VALUE, STR_ENTER_NEW_VALUE, _moneyInputText, MONEY_STRING_MAXLENGTH);
break;
}
case WIDX_PRIMARY_PRICE_SAME_THROUGHOUT_PARK:
window_ride_income_toggle_primary_price(w);
break;
case WIDX_SECONDARY_PRICE:{
money32 price32 = (money32)window_ride_income_get_secondary_price(w);
money_to_string(price32, _moneyInputText, MONEY_STRING_MAXLENGTH, true);
window_text_input_raw_open(w, WIDX_SECONDARY_PRICE, STR_ENTER_NEW_VALUE, STR_ENTER_NEW_VALUE, _moneyInputText, MONEY_STRING_MAXLENGTH);
}break;
case WIDX_SECONDARY_PRICE_SAME_THROUGHOUT_PARK:
window_ride_income_toggle_secondary_price(w);
break;
@@ -6082,6 +6116,30 @@ static void window_ride_income_update(rct_window *w)
}
}
static void window_ride_income_textinput(rct_window* w, rct_widgetindex widgetIndex, char* text)
{
if ((widgetIndex != WIDX_PRIMARY_PRICE && widgetIndex != WIDX_SECONDARY_PRICE) || text == nullptr)
return;
money32 price = string_to_money(text);
if (price == MONEY32_UNDEFINED)
{
return;
}
price = Math::Clamp(MONEY(0, 00), price, MONEY(20, 00));
money16 price16 = (money16)price;
if (widgetIndex == WIDX_PRIMARY_PRICE)
{
window_ride_income_set_primary_price(w, price16);
}
else
{
window_ride_income_set_secondary_price(w, price16);
}
}
/**
*
* rct2: 0x006ADAA3

View File

@@ -1233,6 +1233,7 @@ void format_string_to_upper(utf8 *dest, size_t size, rct_string_id format, void
money32 string_to_money(const char* string_to_monetise)
{
const char* decimal_char = language_get_string(STR_LOCALE_DECIMAL_POINT);
const currency_descriptor* currencyDesc = &CurrencyDescriptors[gConfigGeneral.currency_format];
char processedString[128] = {};
Guard::Assert(strlen(string_to_monetise) < sizeof(processedString));
@@ -1256,6 +1257,11 @@ money32 string_to_money(const char* string_to_monetise)
return MONEY32_UNDEFINED;
else
hasDecSep = true;
// Replace localised decimal separator with an English one.
*dst_ptr++ = '.';
src_ptr++;
continue;
}
else if (*src_ptr == '-')
{
@@ -1301,34 +1307,14 @@ money32 string_to_money(const char* string_to_monetise)
processedString[0] = '0';
}
int number = 0, decimal = 0;
if (strstr(processedString, decimal_char) == nullptr)
{
// If decimal char does not exist, no tokenising is needed.
number = atoi(processedString);
}
else
{
char *numberText = strtok(processedString, decimal_char);
char *decimalText = strtok(nullptr, decimal_char);
auto number = std::stod(processedString, nullptr);
number /= (currencyDesc->rate / 10.0);
auto whole = static_cast<uint16>(number);
auto fraction = static_cast<uint8>((number - whole) * 100);
if (numberText != nullptr)
number = atoi(numberText);
if (decimalText != nullptr)
decimal = atoi(decimalText);
// The second parameter in MONEY must be two digits in length, while the game only ever uses
// the first of the two digits.
// Convert invalid numbers, such as ".6", ".234", ".05", to ".60", ".20", ".00" (respectively)
while (decimal > 10)
decimal /= 10;
if (decimal < 10)
decimal *= 10;
}
money32 result = MONEY(number, decimal);
money32 result = MONEY(whole, fraction);
// Check if MONEY resulted in overflow
if ((number > 0 && result < 0) || result / 10 < number)
if ((whole > 0 && result < 0) || result / 10 < whole)
{
result = INT_MAX;
}
@@ -1336,26 +1322,50 @@ money32 string_to_money(const char* string_to_monetise)
return result;
}
void money_to_string(money32 amount, char * buffer_to_put_value_to, size_t buffer_len)
/**
*
* @param amount The amount in tens of pounds, e.g. 123 = £ 12.30
* @param buffer_to_put_value_to Output parameter.
* @param buffer_len Length of the buffer.
* @param forceDecimals Show decimals, even if the amount does not have them. Will be ignored if the current exchange
* rate is too big to have decimals.
*/
void money_to_string(money32 amount, char * buffer_to_put_value_to, size_t buffer_len, bool forceDecimals)
{
if (amount == MONEY32_UNDEFINED) {
if (amount == MONEY32_UNDEFINED)
{
snprintf(buffer_to_put_value_to, buffer_len, "0");
return;
}
const currency_descriptor *currencyDesc = &CurrencyDescriptors[gConfigGeneral.currency_format];
int sign = amount >= 0 ? 1 : -1;
int a = abs(amount);
if (a / 10 > 0 && a % 10 > 0) { // If whole and decimal exist
int a = abs(amount) * currencyDesc->rate;
bool amountIsInteger = (a / 100 > 0) && (a % 100 == 0);
// If whole and decimal exist
if ((a / 100 > 0 && a % 100 > 0) || (amountIsInteger && forceDecimals && currencyDesc->rate < 100))
{
const char* decimal_char = language_get_string(STR_LOCALE_DECIMAL_POINT);
snprintf(buffer_to_put_value_to, buffer_len, "%d%s%d0", (a / 10) * sign, decimal_char, a % 10);
auto decimalPart = a % 100;
auto precedingZero = (decimalPart < 10) ? "0" : "";
snprintf(buffer_to_put_value_to, buffer_len, "%d%s%s%d", (a / 100) * sign, decimal_char, precedingZero, decimalPart);
}
else if (a / 10 > 0 && a % 10 == 0) { // If whole exists, but not decimal
snprintf(buffer_to_put_value_to, buffer_len, "%d", (a / 10) * sign);
// If whole exists, but not decimal
else if (amountIsInteger)
{
snprintf(buffer_to_put_value_to, buffer_len, "%d", (a / 100) * sign);
}
else if (a / 10 == 0 && a % 10 > 0) { // If decimal exists, but not whole
// If decimal exists, but not whole
else if (a / 100 == 0 && a % 100 > 0)
{
const char* decimal_char = language_get_string(STR_LOCALE_DECIMAL_POINT);
snprintf(buffer_to_put_value_to, buffer_len, "%s0%s%d0", sign < 0 ? "-" : "", decimal_char, a % 10);
snprintf(buffer_to_put_value_to, buffer_len, "%s0%s%d", sign < 0 ? "-" : "", decimal_char, a % 100);
}
else {
else
{
snprintf(buffer_to_put_value_to, buffer_len, "0");
}
}

View File

@@ -43,7 +43,7 @@ sint32 get_string_length(const utf8 *text);
// The maximum number of characters allowed for string/money conversions (anything above will risk integer overflow issues)
#define MONEY_STRING_MAXLENGTH 14
money32 string_to_money(const char* string_to_monetise);
void money_to_string(money32 amount, char * buffer_to_put_value_to, size_t buffer_len);
void money_to_string(money32 amount, char * buffer_to_put_value_to, size_t buffer_len, bool forceDecimals);
void user_string_clear_all();
rct_string_id user_string_allocate(sint32 base, const utf8 *text);