diff --git a/source/joker_effects.c b/source/joker_effects.c index f874908..8e57e06 100644 --- a/source/joker_effects.c +++ b/source/joker_effects.c @@ -1,3 +1,4 @@ +#include "chinese_text.h" #include "game.h" #include "game/round.h" #include "game_variables.h" @@ -12,7 +13,9 @@ #include #include -#define MISPRINT_MAX_MULT 23 +#define MISPRINT_MAX_MULT 23 +#define JOKER_DESC_UTF8_BUFFER_SIZE 320 +#define JOKER_DESC_ENCODED_BUFFER_SIZE 384 #define REGISTER_JOKER_DESC_FUNC(joker_desc_name) \ static int joker_desc_name(Joker* joker, Rect dest_rect); @@ -261,129 +264,215 @@ size_t get_joker_registry_size(void) #pragma region JOKER DESCRIPTIONS +static size_t joker_desc_utf8_char_size(const char* text, size_t remaining) +{ + unsigned char first = (unsigned char)text[0]; + + if (first < 0x80) + { + return 1; + } + if ((first & 0xE0) == 0xC0 && remaining >= 2) + { + return 2; + } + if ((first & 0xF0) == 0xE0 && remaining >= 3) + { + return 3; + } + if ((first & 0xF8) == 0xF0 && remaining >= 4) + { + return 4; + } + + return 1; +} + +static int joker_desc_visible_line_length(const char* line, size_t line_size) +{ + size_t offset = 0; + int visible_length = 0; + + while (offset < line_size) + { + if (line[offset] == '#' && offset + 1 < line_size && line[offset + 1] == '{') + { + offset += 2; + while (offset < line_size && line[offset] != '}') + { + offset++; + } + if (offset < line_size) + { + offset++; + } + continue; + } + + offset += joker_desc_utf8_char_size(line + offset, line_size - offset); + visible_length++; + } + + return visible_length; +} + +static int print_joker_desc(const char* utf8_desc, Rect dest_rect) +{ + char encoded_desc[JOKER_DESC_ENCODED_BUFFER_SIZE]; + size_t encoded_length = chinese_text_encode(utf8_desc, encoded_desc, sizeof(encoded_desc)); + size_t line_start = 0; + int line_y = 0; + + while (line_start < encoded_length) + { + size_t line_end = line_start; + while (line_end < encoded_length && encoded_desc[line_end] != '\n') + { + line_end++; + } + + size_t line_size = line_end - line_start; + int visible_length = joker_desc_visible_line_length(encoded_desc + line_start, line_size); + int line_x = max(0, (rect_width(&dest_rect) - visible_length) / 2); + + if (line_size > 0) + { + tte_printf( + "#{P:%d,%d}%.*s", + (dest_rect.left + line_x) * TILE_SIZE, + (dest_rect.top + line_y) * TILE_SIZE, + (int)line_size, + encoded_desc + line_start + ); + } + + line_y++; + line_start = line_end + 1; + } + + return line_y; +} + static int default_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc[] = TTE_RED_TAG "+4 " TTE_BLACK_TAG "Mult"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + static const char desc[] = TTE_RED_TAG "+4 " TTE_BLACK_TAG "倍率"; + return print_joker_desc(desc, dest_rect); } static int greedy_joker_desc(Joker* joker, Rect dest_rect) { static const char desc[] = - TTE_BLACK_TAG "Played cards with " TTE_DIAMOND_TAG TTE_BLACK_TAG "suit give " TTE_RED_TAG - "+3 " TTE_BLACK_TAG "Mult when scored"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + TTE_BLACK_TAG "打出的" TTE_YELLOW_TAG "方片" TTE_BLACK_TAG "花色牌\n计分时给予 " TTE_RED_TAG + "+3 " TTE_BLACK_TAG "倍率"; + return print_joker_desc(desc, dest_rect); } static int lusty_joker_desc(Joker* joker, Rect dest_rect) { static const char desc[] = - TTE_BLACK_TAG "Played cards with " TTE_HEART_TAG TTE_BLACK_TAG "suit give " TTE_RED_TAG - "+3 " TTE_BLACK_TAG "Mult when scored"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + TTE_BLACK_TAG "打出的" TTE_RED_TAG "红桃" TTE_BLACK_TAG "花色牌\n计分时给予 " TTE_RED_TAG + "+3 " TTE_BLACK_TAG "倍率"; + return print_joker_desc(desc, dest_rect); } static int wrathful_joker_desc(Joker* joker, Rect dest_rect) { static const char desc[] = - TTE_BLACK_TAG "Played cards with " TTE_SPADE_TAG TTE_BLACK_TAG "suit give " TTE_RED_TAG - "+3 " TTE_BLACK_TAG "Mult when scored"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + TTE_BLACK_TAG "打出的" TTE_DARK_BLUE_TAG "黑桃" TTE_BLACK_TAG + "花色牌\n计分时给予 " TTE_RED_TAG "+3 " TTE_BLACK_TAG "倍率"; + return print_joker_desc(desc, dest_rect); } static int gluttonous_joker_desc(Joker* joker, Rect dest_rect) { static const char desc[] = - TTE_BLACK_TAG "Played cards with " TTE_CLUB_TAG TTE_BLACK_TAG "suit give " TTE_RED_TAG - "+3 " TTE_BLACK_TAG "Mult when scored"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + TTE_BLACK_TAG "打出的" TTE_DARK_GREEN_TAG "梅花" TTE_BLACK_TAG + "花色牌\n计分时给予 " TTE_RED_TAG "+3 " TTE_BLACK_TAG "倍率"; + return print_joker_desc(desc, dest_rect); } static int jolly_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc[] = - TTE_RED_TAG "+8 " TTE_BLACK_TAG "Mult if played hand contains a " TTE_YELLOW_TAG "Pair"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + static const char desc[] = TTE_BLACK_TAG "出牌含有 " TTE_YELLOW_TAG "对子 " TTE_BLACK_TAG + "时\n" TTE_RED_TAG "+8 " TTE_BLACK_TAG "倍率"; + return print_joker_desc(desc, dest_rect); } static int zany_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc[] = TTE_RED_TAG - "+12 " TTE_BLACK_TAG "Mult if played hand contains a " TTE_YELLOW_TAG "Three of a Kind"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + static const char desc[] = TTE_BLACK_TAG "出牌含有 " TTE_YELLOW_TAG "三条 " TTE_BLACK_TAG + "时\n" TTE_RED_TAG "+12 " TTE_BLACK_TAG "倍率"; + return print_joker_desc(desc, dest_rect); } static int mad_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc[] = TTE_RED_TAG - "+10 " TTE_BLACK_TAG "Mult if played hand contains a " TTE_YELLOW_TAG "Two Pair"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + static const char desc[] = TTE_BLACK_TAG "出牌含有 " TTE_YELLOW_TAG "两对 " TTE_BLACK_TAG + "时\n" TTE_RED_TAG "+10 " TTE_BLACK_TAG "倍率"; + return print_joker_desc(desc, dest_rect); } static int crazy_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc[] = TTE_RED_TAG - "+12 " TTE_BLACK_TAG "Mult if played hand contains a " TTE_YELLOW_TAG "Straight"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + static const char desc[] = TTE_BLACK_TAG "出牌含有 " TTE_YELLOW_TAG "顺子 " TTE_BLACK_TAG + "时\n" TTE_RED_TAG "+12 " TTE_BLACK_TAG "倍率"; + return print_joker_desc(desc, dest_rect); } static int droll_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc[] = - TTE_RED_TAG "+10 " TTE_BLACK_TAG "Mult if played hand contains a " TTE_YELLOW_TAG "Flush"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + static const char desc[] = TTE_BLACK_TAG "出牌含有 " TTE_YELLOW_TAG "同花 " TTE_BLACK_TAG + "时\n" TTE_RED_TAG "+10 " TTE_BLACK_TAG "倍率"; + return print_joker_desc(desc, dest_rect); } static int sly_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc[] = - TTE_BLUE_TAG "+50 " TTE_BLACK_TAG "Chips if played hand contains a " TTE_YELLOW_TAG "Pair"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + static const char desc[] = TTE_BLACK_TAG "出牌含有 " TTE_YELLOW_TAG "对子 " TTE_BLACK_TAG + "时\n" TTE_BLUE_TAG "+50 " TTE_BLACK_TAG "筹码"; + return print_joker_desc(desc, dest_rect); } static int wily_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc[] = TTE_BLUE_TAG - "+100 " TTE_BLACK_TAG "Chips if played hand contains a " TTE_YELLOW_TAG "Three of a Kind"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + static const char desc[] = TTE_BLACK_TAG "出牌含有 " TTE_YELLOW_TAG "三条 " TTE_BLACK_TAG + "时\n" TTE_BLUE_TAG "+100 " TTE_BLACK_TAG "筹码"; + return print_joker_desc(desc, dest_rect); } static int clever_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc[] = TTE_BLUE_TAG - "+80 " TTE_BLACK_TAG "Chips if played hand contains a " TTE_YELLOW_TAG "Two Pair"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + static const char desc[] = TTE_BLACK_TAG "出牌含有 " TTE_YELLOW_TAG "两对 " TTE_BLACK_TAG + "时\n" TTE_BLUE_TAG "+80 " TTE_BLACK_TAG "筹码"; + return print_joker_desc(desc, dest_rect); } static int devious_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc[] = TTE_BLUE_TAG - "+100 " TTE_BLACK_TAG "Chips if played hand contains a " TTE_YELLOW_TAG "Straight"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + static const char desc[] = TTE_BLACK_TAG "出牌含有 " TTE_YELLOW_TAG "顺子 " TTE_BLACK_TAG + "时\n" TTE_BLUE_TAG "+100 " TTE_BLACK_TAG "筹码"; + return print_joker_desc(desc, dest_rect); } static int crafty_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc[] = - TTE_BLUE_TAG "+80 " TTE_BLACK_TAG "Chips if played hand contains a " TTE_YELLOW_TAG "Flush"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + static const char desc[] = TTE_BLACK_TAG "出牌含有 " TTE_YELLOW_TAG "同花 " TTE_BLACK_TAG + "时\n" TTE_BLUE_TAG "+80 " TTE_BLACK_TAG "筹码"; + return print_joker_desc(desc, dest_rect); } static int half_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc[] = - TTE_RED_TAG "+20 " TTE_BLACK_TAG "Mult if played hand contains " TTE_YELLOW_TAG - "3 " TTE_BLACK_TAG "or fewer cards"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + static const char desc[] = TTE_BLACK_TAG "出牌不超过 " TTE_YELLOW_TAG "3 " TTE_BLACK_TAG + "张时\n" TTE_RED_TAG "+20 " TTE_BLACK_TAG "倍率"; + return print_joker_desc(desc, dest_rect); } static int stencil_joker_desc(Joker* joker, Rect dest_rect) { static const char desc_format[] = - TTE_RED_TAG "X1 " TTE_BLACK_TAG - "Mult for each empty Joker slot Joker Stencil included\n\n(Now " TTE_RED_TAG - "X%ld " TTE_BLACK_TAG "Mult)"; - const u32 desc_max_size = 130; + TTE_BLACK_TAG "每个空的小丑牌槽位\n给予 " TTE_RED_TAG "X1 " TTE_BLACK_TAG + "倍率\n本牌视为空槽\n\n(当前 " TTE_RED_TAG "X%ld " TTE_BLACK_TAG "倍率)"; List* jokers = get_jokers_list(); u32 stencil_bonus = MAX_JOKERS_HELD_SIZE - list_get_len(jokers); @@ -396,322 +485,308 @@ static int stencil_joker_desc(Joker* joker, Rect dest_rect) stencil_bonus++; } - char desc[desc_max_size]; - snprintf(desc, desc_max_size, desc_format, stencil_bonus); + char desc[JOKER_DESC_UTF8_BUFFER_SIZE]; + snprintf(desc, sizeof(desc), desc_format, stencil_bonus); - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + return print_joker_desc(desc, dest_rect); } static int misprint_joker_desc(Joker* joker, Rect dest_rect) { // TODO: print glitchy desc with occasional next card reveal - char desc[] = TTE_YELLOW_TAG "Random" TTE_BLACK_TAG " Mult between " TTE_RED_TAG - "+0" TTE_BLACK_TAG " and " TTE_RED_TAG "+23"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + char desc[] = TTE_YELLOW_TAG "随机" TTE_BLACK_TAG "给予 " TTE_RED_TAG "+0 " TTE_BLACK_TAG + "到 " TTE_RED_TAG "+23\n" TTE_BLACK_TAG "倍率"; + return print_joker_desc(desc, dest_rect); } static int walkie_talkie_joker_desc(Joker* joker, Rect dest_rect) { static const char desc[] = - TTE_BLACK_TAG "Each played " TTE_YELLOW_TAG "10 " TTE_BLACK_TAG "or " TTE_YELLOW_TAG - "4 " TTE_BLACK_TAG "gives " TTE_BLUE_TAG "+10 " TTE_BLACK_TAG - "Chips and " TTE_RED_TAG "+4 " TTE_BLACK_TAG "Mult when scored"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + TTE_BLACK_TAG "打出的 " TTE_YELLOW_TAG "10 " TTE_BLACK_TAG "或 " TTE_YELLOW_TAG + "4\n" TTE_BLACK_TAG "计分时给予 " TTE_BLUE_TAG "+10 " TTE_BLACK_TAG + "筹码\n和 " TTE_RED_TAG "+4 " TTE_BLACK_TAG "倍率"; + return print_joker_desc(desc, dest_rect); } static int fibonnaci_joker_desc(Joker* joker, Rect dest_rect) { static const char desc[] = - TTE_BLACK_TAG "Each played\n" TTE_YELLOW_TAG "Ace" TTE_BLACK_TAG ", " TTE_YELLOW_TAG - "2" TTE_BLACK_TAG ", " TTE_YELLOW_TAG "3" TTE_BLACK_TAG ", " TTE_YELLOW_TAG - "5" TTE_BLACK_TAG ", " TTE_YELLOW_TAG "8\n" TTE_BLACK_TAG "gives " TTE_RED_TAG - "+8 " TTE_BLACK_TAG "Mult when scored"; + TTE_BLACK_TAG "打出的 " TTE_YELLOW_TAG "A、2、3、5、8\n" TTE_BLACK_TAG + "计分时给予 " TTE_RED_TAG "+8 " TTE_BLACK_TAG "倍率"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + return print_joker_desc(desc, dest_rect); } static int banner_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc[] = - TTE_BLUE_TAG "+30 " TTE_BLACK_TAG "Chips for each remaining " TTE_YELLOW_TAG "discard"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + static const char desc[] = TTE_BLACK_TAG "每有一次" TTE_YELLOW_TAG "剩余弃牌\n" TTE_BLACK_TAG + "给予 " TTE_BLUE_TAG "+30 " TTE_BLACK_TAG "筹码"; + return print_joker_desc(desc, dest_rect); } static int mystic_summit_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc[] = TTE_RED_TAG "+15 " TTE_BLACK_TAG "Mult when " TTE_YELLOW_TAG - "0 " TTE_BLACK_TAG "discards remaining "; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + static const char desc[] = TTE_BLACK_TAG "无" TTE_YELLOW_TAG "剩余弃牌" TTE_BLACK_TAG + "时\n" TTE_RED_TAG "+15 " TTE_BLACK_TAG "倍率"; + return print_joker_desc(desc, dest_rect); } static int blackboard_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc[] = TTE_RED_TAG - "X3 " TTE_BLACK_TAG "Mult if all cards held in hand are " TTE_SPADE_TAG TTE_BLACK_TAG - "or " TTE_CLUB_TAG; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + static const char desc[] = + TTE_BLACK_TAG "手牌均为 " TTE_DARK_BLUE_TAG "黑桃 " TTE_BLACK_TAG "或 " TTE_DARK_GREEN_TAG + "梅花\n" TTE_BLACK_TAG "时 " TTE_RED_TAG "X3 " TTE_BLACK_TAG "倍率"; + return print_joker_desc(desc, dest_rect); } static int blue_joker_desc(Joker* joker, Rect dest_rect) { static const char desc_format[] = - TTE_BLUE_TAG "+2 " TTE_BLACK_TAG "Chips for each remaining card in " TTE_YELLOW_TAG - "deck" TTE_BLACK_TAG "\n\n(Now " TTE_BLUE_TAG "+%ld" TTE_BLACK_TAG " Chips)"; - const u32 desc_max_size = 139; + TTE_BLACK_TAG "牌组中每张剩余牌\n给予 " TTE_BLUE_TAG "+2 " TTE_BLACK_TAG + "筹码\n\n(当前 " TTE_BLUE_TAG "+%ld " TTE_BLACK_TAG "筹码)"; u32 blue_bonus = (get_deck_top() + 1) * 2; - char desc[desc_max_size]; - snprintf(desc, desc_max_size, desc_format, blue_bonus); + char desc[JOKER_DESC_UTF8_BUFFER_SIZE]; + snprintf(desc, sizeof(desc), desc_format, blue_bonus); - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + return print_joker_desc(desc, dest_rect); } static int raised_fist_joker_desc(Joker* joker, Rect dest_rect) { static const char desc[] = - TTE_BLACK_TAG "Adds " TTE_YELLOW_TAG "double" TTE_BLACK_TAG " the rank of " TTE_YELLOW_TAG - "lowest" TTE_BLACK_TAG " ranked card held in hand to Mult"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + TTE_BLACK_TAG "将手牌中点数" TTE_YELLOW_TAG "最低" TTE_BLACK_TAG "牌的\n点数" TTE_YELLOW_TAG + "两倍" TTE_BLACK_TAG "加到倍率"; + return print_joker_desc(desc, dest_rect); } static int reserved_parking_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc[] = TTE_BLACK_TAG - "Each " TTE_YELLOW_TAG "face" TTE_BLACK_TAG " card held in hand has a " TTE_GREEN_TAG - "1 in 2" TTE_BLACK_TAG " chance to give " TTE_YELLOW_TAG "$1"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + static const char desc[] = + TTE_BLACK_TAG "手牌中每张" TTE_YELLOW_TAG "人头牌\n" TTE_BLACK_TAG "有 " TTE_GREEN_TAG + "1/2 " TTE_BLACK_TAG "几率给予 " TTE_YELLOW_TAG "$1"; + return print_joker_desc(desc, dest_rect); } static int business_card_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc[] = TTE_BLACK_TAG - "Played " TTE_YELLOW_TAG "face" TTE_BLACK_TAG " cards have a " TTE_GREEN_TAG - "1 in 2" TTE_BLACK_TAG " chance to give " TTE_YELLOW_TAG "$2" TTE_BLACK_TAG " when scored"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + static const char desc[] = + TTE_BLACK_TAG "打出的" TTE_YELLOW_TAG "人头牌" TTE_BLACK_TAG "计分时\n有 " TTE_GREEN_TAG + "1/2 " TTE_BLACK_TAG "几率给予 " TTE_YELLOW_TAG "$2"; + return print_joker_desc(desc, dest_rect); } static int scholar_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc[] = TTE_BLACK_TAG - "Played " TTE_YELLOW_TAG "Aces" TTE_BLACK_TAG " give " TTE_BLUE_TAG "+20" TTE_BLACK_TAG - " Chips and " TTE_RED_TAG "+4" TTE_BLACK_TAG " Mult when scored"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + static const char desc[] = + TTE_BLACK_TAG "打出的 " TTE_YELLOW_TAG "A " TTE_BLACK_TAG "计分时\n给予 " TTE_BLUE_TAG + "+20 " TTE_BLACK_TAG "筹码\n和 " TTE_RED_TAG "+4 " TTE_BLACK_TAG "倍率"; + return print_joker_desc(desc, dest_rect); } static int scary_face_joker_desc(Joker* joker, Rect dest_rect) { static const char desc[] = - TTE_BLACK_TAG "Played " TTE_YELLOW_TAG "face" TTE_BLACK_TAG " cards give " TTE_BLUE_TAG - "+30" TTE_BLACK_TAG " Chips when scored"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + TTE_BLACK_TAG "打出的" TTE_YELLOW_TAG "人头牌" TTE_BLACK_TAG "计分时\n给予 " TTE_BLUE_TAG + "+30 " TTE_BLACK_TAG "筹码"; + return print_joker_desc(desc, dest_rect); } static int abstract_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc_format[] = - TTE_RED_TAG "+3" TTE_BLACK_TAG " Mult for each " TTE_YELLOW_TAG "Joker" TTE_BLACK_TAG - " card\n\n(Now " TTE_RED_TAG "+%ld" TTE_BLACK_TAG " Mult)"; - const u32 desc_max_size = 125; + static const char desc_format[] = TTE_BLACK_TAG + "每张" TTE_YELLOW_TAG "小丑牌" TTE_BLACK_TAG "给予\n" TTE_RED_TAG "+3 " TTE_BLACK_TAG + "倍率\n\n(当前 " TTE_RED_TAG "+%ld " TTE_BLACK_TAG "倍率)"; u32 abstract_bonus = list_get_len(get_jokers_list()) * 3; - char desc[desc_max_size]; - snprintf(desc, desc_max_size, desc_format, abstract_bonus); + char desc[JOKER_DESC_UTF8_BUFFER_SIZE]; + snprintf(desc, sizeof(desc), desc_format, abstract_bonus); - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + return print_joker_desc(desc, dest_rect); } static int bull_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc_format[] = - TTE_BLUE_TAG "+2" TTE_BLACK_TAG " Chips for each " TTE_YELLOW_TAG "$1" TTE_BLACK_TAG - " you have\n\n(Now " TTE_BLUE_TAG "+%ld" TTE_BLACK_TAG " Chips)"; - const u32 desc_max_size = 127; + static const char desc_format[] = TTE_BLACK_TAG + "每拥有 " TTE_YELLOW_TAG "$1\n" TTE_BLACK_TAG "给予 " TTE_BLUE_TAG "+2 " TTE_BLACK_TAG + "筹码\n\n(当前 " TTE_BLUE_TAG "+%ld " TTE_BLACK_TAG "筹码)"; u32 bull_bonus = (g_game_vars.money > 0) ? g_game_vars.money * 2 : 0; - char desc[desc_max_size]; - snprintf(desc, desc_max_size, desc_format, bull_bonus); + char desc[JOKER_DESC_UTF8_BUFFER_SIZE]; + snprintf(desc, sizeof(desc), desc_format, bull_bonus); - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + return print_joker_desc(desc, dest_rect); } static int smiley_face_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc[] = - TTE_BLACK_TAG "Played " TTE_YELLOW_TAG "face" TTE_BLACK_TAG " cards give " TTE_RED_TAG - "+5" TTE_BLACK_TAG " Mult when scored"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + static const char desc[] = TTE_BLACK_TAG "打出的" TTE_YELLOW_TAG "人头牌" TTE_BLACK_TAG + "计分时\n给予 " TTE_RED_TAG "+5 " TTE_BLACK_TAG "倍率"; + return print_joker_desc(desc, dest_rect); } static int even_steven_joker_desc(Joker* joker, Rect dest_rect) { static const char desc[] = - TTE_BLACK_TAG "Played cards with " TTE_YELLOW_TAG "even rank give " TTE_RED_TAG - "+4" TTE_BLACK_TAG " Mult when scored\n(10, 8, 6, 4, 2)"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + TTE_BLACK_TAG "打出的" TTE_YELLOW_TAG "偶数点牌" TTE_BLACK_TAG "计分时\n给予 " TTE_RED_TAG + "+4 " TTE_BLACK_TAG "倍率\n(10、8、6、4、2)"; + return print_joker_desc(desc, dest_rect); } static int odd_todd_joker_desc(Joker* joker, Rect dest_rect) { static const char desc[] = - TTE_BLACK_TAG "Played cards with " TTE_YELLOW_TAG "odd rank give " TTE_BLUE_TAG - "+31" TTE_BLACK_TAG " Chips when scored\n(A, 9, 7, 5, 3)"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + TTE_BLACK_TAG "打出的" TTE_YELLOW_TAG "奇数点牌" TTE_BLACK_TAG "计分时\n给予 " TTE_BLUE_TAG + "+31 " TTE_BLACK_TAG "筹码\n(A、9、7、5、3)"; + return print_joker_desc(desc, dest_rect); } static int acrobat_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc[] = TTE_RED_TAG "X3" TTE_BLACK_TAG " Mult on " TTE_YELLOW_TAG - "final hand" TTE_BLACK_TAG " of round"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + static const char desc[] = TTE_BLACK_TAG "本回合" TTE_YELLOW_TAG "最后一次出牌" TTE_BLACK_TAG + "时\n" TTE_RED_TAG "X3 " TTE_BLACK_TAG "倍率"; + return print_joker_desc(desc, dest_rect); } static int hanging_chad_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc[] = TTE_BLACK_TAG "Retrigger " TTE_YELLOW_TAG "first" TTE_BLACK_TAG - " played card used in scoring " TTE_YELLOW_TAG - "2" TTE_BLACK_TAG " additional times "; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + static const char desc[] = TTE_BLACK_TAG "用于计分的" TTE_YELLOW_TAG "第一张牌\n" TTE_BLACK_TAG + "额外再触发 " TTE_YELLOW_TAG "2 " TTE_BLACK_TAG "次"; + return print_joker_desc(desc, dest_rect); } static int the_duo_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc[] = - TTE_RED_TAG "X2" TTE_BLACK_TAG " Mult if played hand contains a " TTE_YELLOW_TAG "Pair"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + static const char desc[] = TTE_BLACK_TAG "出牌含有 " TTE_YELLOW_TAG "对子 " TTE_BLACK_TAG + "时\n" TTE_RED_TAG "X2 " TTE_BLACK_TAG "倍率"; + return print_joker_desc(desc, dest_rect); } static int the_trio_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc[] = TTE_RED_TAG - "X3" TTE_BLACK_TAG " Mult if played hand contains a " TTE_YELLOW_TAG "Three of a Kind"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + static const char desc[] = TTE_BLACK_TAG "出牌含有 " TTE_YELLOW_TAG "三条 " TTE_BLACK_TAG + "时\n" TTE_RED_TAG "X3 " TTE_BLACK_TAG "倍率"; + return print_joker_desc(desc, dest_rect); } static int the_family_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc[] = TTE_RED_TAG - "X4" TTE_BLACK_TAG " Mult if played hand contains a " TTE_YELLOW_TAG "Four of a Kind"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + static const char desc[] = TTE_BLACK_TAG "出牌含有 " TTE_YELLOW_TAG "四条 " TTE_BLACK_TAG + "时\n" TTE_RED_TAG "X4 " TTE_BLACK_TAG "倍率"; + return print_joker_desc(desc, dest_rect); } static int the_order_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc[] = - TTE_RED_TAG "X3" TTE_BLACK_TAG " Mult if played hand contains a " TTE_YELLOW_TAG "Straight"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + static const char desc[] = TTE_BLACK_TAG "出牌含有 " TTE_YELLOW_TAG "顺子 " TTE_BLACK_TAG + "时\n" TTE_RED_TAG "X3 " TTE_BLACK_TAG "倍率"; + return print_joker_desc(desc, dest_rect); } static int the_tribe_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc[] = - TTE_RED_TAG "X2" TTE_BLACK_TAG " Mult if played hand contains a " TTE_YELLOW_TAG "Flush"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + static const char desc[] = TTE_BLACK_TAG "出牌含有 " TTE_YELLOW_TAG "同花 " TTE_BLACK_TAG + "时\n" TTE_RED_TAG "X2 " TTE_BLACK_TAG "倍率"; + return print_joker_desc(desc, dest_rect); } static int bootstraps_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc_format[] = - TTE_RED_TAG "+2" TTE_BLACK_TAG " Mult for every " TTE_YELLOW_TAG "$5" TTE_BLACK_TAG - " you have\n\n(Now " TTE_RED_TAG "+%ld" TTE_BLACK_TAG " Mult)"; - const u32 desc_max_size = 125; + static const char desc_format[] = TTE_BLACK_TAG + "每拥有 " TTE_YELLOW_TAG "$5\n" TTE_BLACK_TAG "给予 " TTE_RED_TAG "+2 " TTE_BLACK_TAG + "倍率\n\n(当前 " TTE_RED_TAG "+%ld " TTE_BLACK_TAG "倍率)"; u32 bootstrap_bonus = (g_game_vars.money > 0) ? (g_game_vars.money / 5) * 2 : 0; - char desc[desc_max_size]; - snprintf(desc, desc_max_size, desc_format, bootstrap_bonus); + char desc[JOKER_DESC_UTF8_BUFFER_SIZE]; + snprintf(desc, sizeof(desc), desc_format, bootstrap_bonus); - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + return print_joker_desc(desc, dest_rect); } static int shoot_the_moon_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc[] = - TTE_BLACK_TAG "Each " TTE_YELLOW_TAG "Queen" TTE_BLACK_TAG - " held in hand gives " TTE_RED_TAG "+13" TTE_BLACK_TAG " Mult"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + static const char desc[] = TTE_BLACK_TAG "手牌中每张 " TTE_YELLOW_TAG "Q\n" TTE_BLACK_TAG + "给予 " TTE_RED_TAG "+13 " TTE_BLACK_TAG "倍率"; + return print_joker_desc(desc, dest_rect); } static int photograph_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc[] = - TTE_BLACK_TAG "First played " TTE_YELLOW_TAG "face" TTE_BLACK_TAG " card gives " TTE_RED_TAG - "X2" TTE_BLACK_TAG " Mult when scored"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + static const char desc[] = TTE_BLACK_TAG "打出的" TTE_YELLOW_TAG "第一张人头牌\n" TTE_BLACK_TAG + "计分时给予 " TTE_RED_TAG "X2 " TTE_BLACK_TAG "倍率"; + return print_joker_desc(desc, dest_rect); } static int dusk_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc[] = TTE_BLACK_TAG "Retrigger all played cards in " TTE_YELLOW_TAG - "final hand" TTE_BLACK_TAG " of the round"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + static const char desc[] = + TTE_BLACK_TAG "本回合" TTE_YELLOW_TAG "最后一次出牌\n" TTE_BLACK_TAG "所有牌再触发一次"; + return print_joker_desc(desc, dest_rect); } static int brainstorm_joker_desc(Joker* joker, Rect dest_rect) { static const char desc[] = - TTE_BLACK_TAG "Copies ability of the leftmost " TTE_YELLOW_TAG "Joker"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + TTE_BLACK_TAG "复制" TTE_YELLOW_TAG "最左侧小丑牌" TTE_BLACK_TAG "能力"; + return print_joker_desc(desc, dest_rect); } static int blueprint_joker_desc(Joker* joker, Rect dest_rect) { static const char desc[] = - TTE_BLACK_TAG "Copies ability of " TTE_YELLOW_TAG "Joker" TTE_BLACK_TAG " to the right"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + TTE_BLACK_TAG "复制" TTE_YELLOW_TAG "右侧小丑牌" TTE_BLACK_TAG "能力"; + return print_joker_desc(desc, dest_rect); } static int hack_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc[] = TTE_BLACK_TAG - "Retrigger each played " TTE_YELLOW_TAG "2" TTE_BLACK_TAG ", " TTE_YELLOW_TAG - "3" TTE_BLACK_TAG ", " TTE_YELLOW_TAG "4" TTE_BLACK_TAG ", or " TTE_YELLOW_TAG "5"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + static const char desc[] = + TTE_BLACK_TAG "打出的 " TTE_YELLOW_TAG "2、3、4、5\n" TTE_BLACK_TAG "均再触发一次"; + return print_joker_desc(desc, dest_rect); } static int seltzer_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc_format[] = TTE_BLACK_TAG - "Retrigger all cards played for the next " TTE_YELLOW_TAG "%ld" TTE_BLACK_TAG " hands"; - const u32 desc_max_size = 94; + static const char desc_format[] = + TTE_BLACK_TAG "接下来 " TTE_YELLOW_TAG "%ld " TTE_BLACK_TAG "次出牌中\n所有牌再触发一次"; - char desc[desc_max_size]; - snprintf(desc, desc_max_size, desc_format, joker->persistent_state); + char desc[JOKER_DESC_UTF8_BUFFER_SIZE]; + snprintf(desc, sizeof(desc), desc_format, joker->persistent_state); - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + return print_joker_desc(desc, dest_rect); } static int sock_and_buskin_joker_desc(Joker* joker, Rect dest_rect) { static const char desc[] = - TTE_BLACK_TAG "Retrigger all played " TTE_YELLOW_TAG "face" TTE_BLACK_TAG " cards"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + TTE_BLACK_TAG "打出的" TTE_YELLOW_TAG "人头牌\n" TTE_BLACK_TAG "均再触发一次"; + return print_joker_desc(desc, dest_rect); } static int pareidolia_joker_desc(Joker* joker, Rect dest_rect) { - static const char desc[] = - TTE_BLACK_TAG "All cards are considered " TTE_YELLOW_TAG "face" TTE_BLACK_TAG " cards"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + static const char desc[] = TTE_BLACK_TAG "所有牌均视为" TTE_YELLOW_TAG "人头牌"; + return print_joker_desc(desc, dest_rect); } static int shortcut_joker_desc(Joker* joker, Rect dest_rect) { static const char desc[] = - TTE_BLACK_TAG "Allows " TTE_YELLOW_TAG "Straights" TTE_BLACK_TAG - " to be made with gaps of " TTE_YELLOW_TAG "1 rank" TTE_BLACK_TAG - "\n\n(ex: " TTE_YELLOW_TAG "10 8 6 5 3" TTE_BLACK_TAG ")"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + TTE_YELLOW_TAG "顺子" TTE_BLACK_TAG "可间隔 " TTE_YELLOW_TAG "1 " TTE_BLACK_TAG + "个点数\n\n例如 " TTE_YELLOW_TAG "10 8 6 5 3"; + return print_joker_desc(desc, dest_rect); } static int four_fingers_joker_desc(Joker* joker, Rect dest_rect) { static const char desc[] = - TTE_BLACK_TAG "All " TTE_YELLOW_TAG "Flushes" TTE_BLACK_TAG " and " TTE_YELLOW_TAG - "Straights" TTE_BLACK_TAG " can be made with 4 cards"; - return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); + TTE_YELLOW_TAG "同花" TTE_BLACK_TAG "和" TTE_YELLOW_TAG "顺子\n" TTE_BLACK_TAG + "均可由 " TTE_YELLOW_TAG "4 " TTE_BLACK_TAG "张牌组成"; + return print_joker_desc(desc, dest_rect); } #pragma endregion