Localize Joker descriptions in Chinese

Translate every registered Joker description while preserving names and gameplay effects. Encode the text through the extended TTE font and center explicit UTF-8 lines without counting formatting tags.
This commit is contained in:
2026-07-19 11:36:01 +08:00
parent c7ef3c0047
commit c1632590c6
+267 -192
View File
@@ -1,3 +1,4 @@
#include "chinese_text.h"
#include "game.h" #include "game.h"
#include "game/round.h" #include "game/round.h"
#include "game_variables.h" #include "game_variables.h"
@@ -12,7 +13,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#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) \ #define REGISTER_JOKER_DESC_FUNC(joker_desc_name) \
static int joker_desc_name(Joker* joker, Rect dest_rect); 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 #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 int default_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = TTE_RED_TAG "+4 " TTE_BLACK_TAG "Mult"; static const char desc[] = TTE_RED_TAG "+4 " 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 greedy_joker_desc(Joker* joker, Rect dest_rect) static int greedy_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = static const char desc[] =
TTE_BLACK_TAG "Played cards with " TTE_DIAMOND_TAG TTE_BLACK_TAG "suit give " TTE_RED_TAG TTE_BLACK_TAG "打出的" TTE_YELLOW_TAG "方片" TTE_BLACK_TAG "花色牌\n计分时给予 " TTE_RED_TAG
"+3 " TTE_BLACK_TAG "Mult when scored"; "+3 " 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 lusty_joker_desc(Joker* joker, Rect dest_rect) static int lusty_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = static const char desc[] =
TTE_BLACK_TAG "Played cards with " TTE_HEART_TAG TTE_BLACK_TAG "suit give " TTE_RED_TAG TTE_BLACK_TAG "打出的" TTE_RED_TAG "红桃" TTE_BLACK_TAG "花色牌\n计分时给予 " TTE_RED_TAG
"+3 " TTE_BLACK_TAG "Mult when scored"; "+3 " 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 wrathful_joker_desc(Joker* joker, Rect dest_rect) static int wrathful_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = static const char desc[] =
TTE_BLACK_TAG "Played cards with " TTE_SPADE_TAG TTE_BLACK_TAG "suit give " TTE_RED_TAG TTE_BLACK_TAG "打出的" TTE_DARK_BLUE_TAG "黑桃" TTE_BLACK_TAG
"+3 " TTE_BLACK_TAG "Mult when scored"; "花色牌\n计分时给予 " TTE_RED_TAG "+3 " 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 gluttonous_joker_desc(Joker* joker, Rect dest_rect) static int gluttonous_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = static const char desc[] =
TTE_BLACK_TAG "Played cards with " TTE_CLUB_TAG TTE_BLACK_TAG "suit give " TTE_RED_TAG TTE_BLACK_TAG "打出的" TTE_DARK_GREEN_TAG "梅花" TTE_BLACK_TAG
"+3 " TTE_BLACK_TAG "Mult when scored"; "花色牌\n计分时给予 " TTE_RED_TAG "+3 " 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 jolly_joker_desc(Joker* joker, Rect dest_rect) static int jolly_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = static const char desc[] = TTE_BLACK_TAG "出牌含有 " TTE_YELLOW_TAG "对子 " TTE_BLACK_TAG
TTE_RED_TAG "+8 " TTE_BLACK_TAG "Mult if played hand contains a " TTE_YELLOW_TAG "Pair"; "时\n" 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 zany_joker_desc(Joker* joker, Rect dest_rect) static int zany_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = TTE_RED_TAG static const char desc[] = TTE_BLACK_TAG "出牌含有 " TTE_YELLOW_TAG "三条 " TTE_BLACK_TAG
"+12 " TTE_BLACK_TAG "Mult if played hand contains a " TTE_YELLOW_TAG "Three of a Kind"; "时\n" TTE_RED_TAG "+12 " 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 mad_joker_desc(Joker* joker, Rect dest_rect) static int mad_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = TTE_RED_TAG static const char desc[] = TTE_BLACK_TAG "出牌含有 " TTE_YELLOW_TAG "两对 " TTE_BLACK_TAG
"+10 " TTE_BLACK_TAG "Mult if played hand contains a " TTE_YELLOW_TAG "Two Pair"; "时\n" TTE_RED_TAG "+10 " 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 crazy_joker_desc(Joker* joker, Rect dest_rect) static int crazy_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = TTE_RED_TAG static const char desc[] = TTE_BLACK_TAG "出牌含有 " TTE_YELLOW_TAG "顺子 " TTE_BLACK_TAG
"+12 " TTE_BLACK_TAG "Mult if played hand contains a " TTE_YELLOW_TAG "Straight"; "时\n" TTE_RED_TAG "+12 " 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 droll_joker_desc(Joker* joker, Rect dest_rect) static int droll_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = static const char desc[] = TTE_BLACK_TAG "出牌含有 " TTE_YELLOW_TAG "同花 " TTE_BLACK_TAG
TTE_RED_TAG "+10 " TTE_BLACK_TAG "Mult if played hand contains a " TTE_YELLOW_TAG "Flush"; "时\n" TTE_RED_TAG "+10 " 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 sly_joker_desc(Joker* joker, Rect dest_rect) static int sly_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = static const char desc[] = TTE_BLACK_TAG "出牌含有 " TTE_YELLOW_TAG "对子 " TTE_BLACK_TAG
TTE_BLUE_TAG "+50 " TTE_BLACK_TAG "Chips if played hand contains a " TTE_YELLOW_TAG "Pair"; "时\n" TTE_BLUE_TAG "+50 " 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 wily_joker_desc(Joker* joker, Rect dest_rect) static int wily_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = TTE_BLUE_TAG static const char desc[] = TTE_BLACK_TAG "出牌含有 " TTE_YELLOW_TAG "三条 " TTE_BLACK_TAG
"+100 " TTE_BLACK_TAG "Chips if played hand contains a " TTE_YELLOW_TAG "Three of a Kind"; "时\n" TTE_BLUE_TAG "+100 " 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 clever_joker_desc(Joker* joker, Rect dest_rect) static int clever_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = TTE_BLUE_TAG static const char desc[] = TTE_BLACK_TAG "出牌含有 " TTE_YELLOW_TAG "两对 " TTE_BLACK_TAG
"+80 " TTE_BLACK_TAG "Chips if played hand contains a " TTE_YELLOW_TAG "Two Pair"; "时\n" TTE_BLUE_TAG "+80 " 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 devious_joker_desc(Joker* joker, Rect dest_rect) static int devious_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = TTE_BLUE_TAG static const char desc[] = TTE_BLACK_TAG "出牌含有 " TTE_YELLOW_TAG "顺子 " TTE_BLACK_TAG
"+100 " TTE_BLACK_TAG "Chips if played hand contains a " TTE_YELLOW_TAG "Straight"; "时\n" TTE_BLUE_TAG "+100 " 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 crafty_joker_desc(Joker* joker, Rect dest_rect) static int crafty_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = static const char desc[] = TTE_BLACK_TAG "出牌含有 " TTE_YELLOW_TAG "同花 " TTE_BLACK_TAG
TTE_BLUE_TAG "+80 " TTE_BLACK_TAG "Chips if played hand contains a " TTE_YELLOW_TAG "Flush"; "时\n" TTE_BLUE_TAG "+80 " 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 half_joker_desc(Joker* joker, Rect dest_rect) static int half_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = static const char desc[] = TTE_BLACK_TAG "出牌不超过 " TTE_YELLOW_TAG "3 " TTE_BLACK_TAG
TTE_RED_TAG "+20 " TTE_BLACK_TAG "Mult if played hand contains " TTE_YELLOW_TAG "张时\n" TTE_RED_TAG "+20 " TTE_BLACK_TAG "倍率";
"3 " TTE_BLACK_TAG "or fewer cards"; return print_joker_desc(desc, dest_rect);
return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true);
} }
static int stencil_joker_desc(Joker* joker, Rect dest_rect) static int stencil_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc_format[] = static const char desc_format[] =
TTE_RED_TAG "X1 " TTE_BLACK_TAG TTE_BLACK_TAG "每个空的小丑牌槽位\n给予 " TTE_RED_TAG "X1 " TTE_BLACK_TAG
"Mult for each empty Joker slot Joker Stencil included\n\n(Now " TTE_RED_TAG "倍率\n本牌视为空槽\n\n(当前 " TTE_RED_TAG "X%ld " TTE_BLACK_TAG "倍率)";
"X%ld " TTE_BLACK_TAG "Mult)";
const u32 desc_max_size = 130;
List* jokers = get_jokers_list(); List* jokers = get_jokers_list();
u32 stencil_bonus = MAX_JOKERS_HELD_SIZE - list_get_len(jokers); 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++; stencil_bonus++;
} }
char desc[desc_max_size]; char desc[JOKER_DESC_UTF8_BUFFER_SIZE];
snprintf(desc, desc_max_size, desc_format, stencil_bonus); 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) static int misprint_joker_desc(Joker* joker, Rect dest_rect)
{ {
// TODO: print glitchy desc with occasional next card reveal // TODO: print glitchy desc with occasional next card reveal
char desc[] = TTE_YELLOW_TAG "Random" TTE_BLACK_TAG " Mult between " TTE_RED_TAG char desc[] = TTE_YELLOW_TAG "随机" TTE_BLACK_TAG "给予 " TTE_RED_TAG "+0 " TTE_BLACK_TAG
"+0" TTE_BLACK_TAG " and " TTE_RED_TAG "+23"; "到 " TTE_RED_TAG "+23\n" 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 walkie_talkie_joker_desc(Joker* joker, Rect dest_rect) static int walkie_talkie_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = static const char desc[] =
TTE_BLACK_TAG "Each played " TTE_YELLOW_TAG "10 " TTE_BLACK_TAG "or " TTE_YELLOW_TAG TTE_BLACK_TAG "打出的 " TTE_YELLOW_TAG "10 " TTE_BLACK_TAG "或 " TTE_YELLOW_TAG
"4 " TTE_BLACK_TAG "gives " TTE_BLUE_TAG "+10 " TTE_BLACK_TAG "4\n" TTE_BLACK_TAG "计分时给予 " TTE_BLUE_TAG "+10 " TTE_BLACK_TAG
"Chips and " TTE_RED_TAG "+4 " TTE_BLACK_TAG "Mult when scored"; "筹码\n和 " TTE_RED_TAG "+4 " 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 fibonnaci_joker_desc(Joker* joker, Rect dest_rect) static int fibonnaci_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = static const char desc[] =
TTE_BLACK_TAG "Each played\n" TTE_YELLOW_TAG "Ace" TTE_BLACK_TAG ", " TTE_YELLOW_TAG TTE_BLACK_TAG "打出的 " TTE_YELLOW_TAG "A、2、3、5、8\n" TTE_BLACK_TAG
"2" TTE_BLACK_TAG ", " TTE_YELLOW_TAG "3" TTE_BLACK_TAG ", " TTE_YELLOW_TAG "计分时给予 " TTE_RED_TAG "+8 " TTE_BLACK_TAG "倍率";
"5" TTE_BLACK_TAG ", " TTE_YELLOW_TAG "8\n" TTE_BLACK_TAG "gives " TTE_RED_TAG
"+8 " TTE_BLACK_TAG "Mult when scored";
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 int banner_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = static const char desc[] = TTE_BLACK_TAG "每有一次" TTE_YELLOW_TAG "剩余弃牌\n" TTE_BLACK_TAG
TTE_BLUE_TAG "+30 " TTE_BLACK_TAG "Chips for each remaining " TTE_YELLOW_TAG "discard"; "给予 " TTE_BLUE_TAG "+30 " 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 mystic_summit_joker_desc(Joker* joker, Rect 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 static const char desc[] = TTE_BLACK_TAG "无" TTE_YELLOW_TAG "剩余弃牌" TTE_BLACK_TAG
"0 " TTE_BLACK_TAG "discards remaining "; "时\n" TTE_RED_TAG "+15 " 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 blackboard_joker_desc(Joker* joker, Rect dest_rect) static int blackboard_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = TTE_RED_TAG static const char desc[] =
"X3 " TTE_BLACK_TAG "Mult if all cards held in hand are " TTE_SPADE_TAG TTE_BLACK_TAG TTE_BLACK_TAG "手牌均为 " TTE_DARK_BLUE_TAG "黑桃 " TTE_BLACK_TAG "或 " TTE_DARK_GREEN_TAG
"or " TTE_CLUB_TAG; "梅花\n" TTE_BLACK_TAG "时 " TTE_RED_TAG "X3 " 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 blue_joker_desc(Joker* joker, Rect dest_rect) static int blue_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc_format[] = static const char desc_format[] =
TTE_BLUE_TAG "+2 " TTE_BLACK_TAG "Chips for each remaining card in " TTE_YELLOW_TAG TTE_BLACK_TAG "牌组中每张剩余牌\n给予 " TTE_BLUE_TAG "+2 " TTE_BLACK_TAG
"deck" TTE_BLACK_TAG "\n\n(Now " TTE_BLUE_TAG "+%ld" TTE_BLACK_TAG " Chips)"; "筹码\n\n(当前 " TTE_BLUE_TAG "+%ld " TTE_BLACK_TAG "筹码)";
const u32 desc_max_size = 139;
u32 blue_bonus = (get_deck_top() + 1) * 2; u32 blue_bonus = (get_deck_top() + 1) * 2;
char desc[desc_max_size]; char desc[JOKER_DESC_UTF8_BUFFER_SIZE];
snprintf(desc, desc_max_size, desc_format, blue_bonus); 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 int raised_fist_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = static const char desc[] =
TTE_BLACK_TAG "Adds " TTE_YELLOW_TAG "double" TTE_BLACK_TAG " the rank of " TTE_YELLOW_TAG TTE_BLACK_TAG "将手牌中点数" TTE_YELLOW_TAG "最低" TTE_BLACK_TAG "牌的\n点数" TTE_YELLOW_TAG
"lowest" TTE_BLACK_TAG " ranked card held in hand to Mult"; "两倍" 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 reserved_parking_joker_desc(Joker* joker, Rect dest_rect) static int reserved_parking_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = TTE_BLACK_TAG static const char desc[] =
"Each " TTE_YELLOW_TAG "face" TTE_BLACK_TAG " card held in hand has a " TTE_GREEN_TAG TTE_BLACK_TAG "手牌中每张" TTE_YELLOW_TAG "人头牌\n" TTE_BLACK_TAG "有 " TTE_GREEN_TAG
"1 in 2" TTE_BLACK_TAG " chance to give " TTE_YELLOW_TAG "$1"; "1/2 " TTE_BLACK_TAG "几率给予 " TTE_YELLOW_TAG "$1";
return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); return print_joker_desc(desc, dest_rect);
} }
static int business_card_joker_desc(Joker* joker, Rect dest_rect) static int business_card_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = TTE_BLACK_TAG static const char desc[] =
"Played " TTE_YELLOW_TAG "face" TTE_BLACK_TAG " cards have a " TTE_GREEN_TAG TTE_BLACK_TAG "打出的" TTE_YELLOW_TAG "人头牌" TTE_BLACK_TAG "计分时\n有 " TTE_GREEN_TAG
"1 in 2" TTE_BLACK_TAG " chance to give " TTE_YELLOW_TAG "$2" TTE_BLACK_TAG " when scored"; "1/2 " TTE_BLACK_TAG "几率给予 " TTE_YELLOW_TAG "$2";
return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); return print_joker_desc(desc, dest_rect);
} }
static int scholar_joker_desc(Joker* joker, Rect dest_rect) static int scholar_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = TTE_BLACK_TAG static const char desc[] =
"Played " TTE_YELLOW_TAG "Aces" TTE_BLACK_TAG " give " TTE_BLUE_TAG "+20" TTE_BLACK_TAG TTE_BLACK_TAG "打出的 " TTE_YELLOW_TAG "A " TTE_BLACK_TAG "计分时\n给予 " TTE_BLUE_TAG
" Chips and " TTE_RED_TAG "+4" TTE_BLACK_TAG " Mult when scored"; "+20 " TTE_BLACK_TAG "筹码\n和 " TTE_RED_TAG "+4 " 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 scary_face_joker_desc(Joker* joker, Rect dest_rect) static int scary_face_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = static const char desc[] =
TTE_BLACK_TAG "Played " TTE_YELLOW_TAG "face" TTE_BLACK_TAG " cards give " TTE_BLUE_TAG TTE_BLACK_TAG "打出的" TTE_YELLOW_TAG "人头牌" TTE_BLACK_TAG "计分时\n给予 " TTE_BLUE_TAG
"+30" TTE_BLACK_TAG " Chips when scored"; "+30 " 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 abstract_joker_desc(Joker* joker, Rect dest_rect) static int abstract_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc_format[] = static const char desc_format[] = TTE_BLACK_TAG
TTE_RED_TAG "+3" TTE_BLACK_TAG " Mult for each " TTE_YELLOW_TAG "Joker" TTE_BLACK_TAG "每张" TTE_YELLOW_TAG "小丑牌" TTE_BLACK_TAG "给予\n" TTE_RED_TAG "+3 " TTE_BLACK_TAG
" card\n\n(Now " TTE_RED_TAG "+%ld" TTE_BLACK_TAG " Mult)"; "倍率\n\n(当前 " TTE_RED_TAG "+%ld " TTE_BLACK_TAG "倍率)";
const u32 desc_max_size = 125;
u32 abstract_bonus = list_get_len(get_jokers_list()) * 3; u32 abstract_bonus = list_get_len(get_jokers_list()) * 3;
char desc[desc_max_size]; char desc[JOKER_DESC_UTF8_BUFFER_SIZE];
snprintf(desc, desc_max_size, desc_format, abstract_bonus); 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 int bull_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc_format[] = static const char desc_format[] = TTE_BLACK_TAG
TTE_BLUE_TAG "+2" TTE_BLACK_TAG " Chips for each " TTE_YELLOW_TAG "$1" TTE_BLACK_TAG "每拥有 " TTE_YELLOW_TAG "$1\n" TTE_BLACK_TAG "给予 " TTE_BLUE_TAG "+2 " TTE_BLACK_TAG
" you have\n\n(Now " TTE_BLUE_TAG "+%ld" TTE_BLACK_TAG " Chips)"; "筹码\n\n(当前 " TTE_BLUE_TAG "+%ld " TTE_BLACK_TAG "筹码)";
const u32 desc_max_size = 127;
u32 bull_bonus = (g_game_vars.money > 0) ? g_game_vars.money * 2 : 0; u32 bull_bonus = (g_game_vars.money > 0) ? g_game_vars.money * 2 : 0;
char desc[desc_max_size]; char desc[JOKER_DESC_UTF8_BUFFER_SIZE];
snprintf(desc, desc_max_size, desc_format, bull_bonus); 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 int smiley_face_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = static const char desc[] = TTE_BLACK_TAG "打出的" TTE_YELLOW_TAG "人头牌" TTE_BLACK_TAG
TTE_BLACK_TAG "Played " TTE_YELLOW_TAG "face" TTE_BLACK_TAG " cards give " TTE_RED_TAG "计分时\n给予 " TTE_RED_TAG "+5 " TTE_BLACK_TAG "倍率";
"+5" TTE_BLACK_TAG " Mult when scored"; return print_joker_desc(desc, dest_rect);
return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true);
} }
static int even_steven_joker_desc(Joker* joker, Rect dest_rect) static int even_steven_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = static const char desc[] =
TTE_BLACK_TAG "Played cards with " TTE_YELLOW_TAG "even rank give " TTE_RED_TAG TTE_BLACK_TAG "打出的" TTE_YELLOW_TAG "偶数点牌" TTE_BLACK_TAG "计分时\n给予 " TTE_RED_TAG
"+4" TTE_BLACK_TAG " Mult when scored\n(10, 8, 6, 4, 2)"; "+4 " TTE_BLACK_TAG "倍率\n(10、8、6、4、2)";
return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); return print_joker_desc(desc, dest_rect);
} }
static int odd_todd_joker_desc(Joker* joker, Rect dest_rect) static int odd_todd_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = static const char desc[] =
TTE_BLACK_TAG "Played cards with " TTE_YELLOW_TAG "odd rank give " TTE_BLUE_TAG TTE_BLACK_TAG "打出的" TTE_YELLOW_TAG "奇数点牌" TTE_BLACK_TAG "计分时\n给予 " TTE_BLUE_TAG
"+31" TTE_BLACK_TAG " Chips when scored\n(A, 9, 7, 5, 3)"; "+31 " TTE_BLACK_TAG "筹码\n(A、9、7、5、3)";
return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); return print_joker_desc(desc, dest_rect);
} }
static int acrobat_joker_desc(Joker* joker, Rect 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 static const char desc[] = TTE_BLACK_TAG "本回合" TTE_YELLOW_TAG "最后一次出牌" TTE_BLACK_TAG
"final hand" TTE_BLACK_TAG " of round"; "时\n" TTE_RED_TAG "X3 " 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 hanging_chad_joker_desc(Joker* joker, Rect 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 static const char desc[] = TTE_BLACK_TAG "用于计分的" TTE_YELLOW_TAG "第一张牌\n" TTE_BLACK_TAG
" played card used in scoring " TTE_YELLOW_TAG "额外再触发 " TTE_YELLOW_TAG "2 " TTE_BLACK_TAG "次";
"2" TTE_BLACK_TAG " additional times "; return print_joker_desc(desc, dest_rect);
return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true);
} }
static int the_duo_joker_desc(Joker* joker, Rect dest_rect) static int the_duo_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = static const char desc[] = TTE_BLACK_TAG "出牌含有 " TTE_YELLOW_TAG "对子 " TTE_BLACK_TAG
TTE_RED_TAG "X2" TTE_BLACK_TAG " Mult if played hand contains a " TTE_YELLOW_TAG "Pair"; "时\n" TTE_RED_TAG "X2 " 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 the_trio_joker_desc(Joker* joker, Rect dest_rect) static int the_trio_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = TTE_RED_TAG static const char desc[] = TTE_BLACK_TAG "出牌含有 " TTE_YELLOW_TAG "三条 " TTE_BLACK_TAG
"X3" TTE_BLACK_TAG " Mult if played hand contains a " TTE_YELLOW_TAG "Three of a Kind"; "时\n" TTE_RED_TAG "X3 " 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 the_family_joker_desc(Joker* joker, Rect dest_rect) static int the_family_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = TTE_RED_TAG static const char desc[] = TTE_BLACK_TAG "出牌含有 " TTE_YELLOW_TAG "四条 " TTE_BLACK_TAG
"X4" TTE_BLACK_TAG " Mult if played hand contains a " TTE_YELLOW_TAG "Four of a Kind"; "时\n" TTE_RED_TAG "X4 " 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 the_order_joker_desc(Joker* joker, Rect dest_rect) static int the_order_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = static const char desc[] = TTE_BLACK_TAG "出牌含有 " TTE_YELLOW_TAG "顺子 " TTE_BLACK_TAG
TTE_RED_TAG "X3" TTE_BLACK_TAG " Mult if played hand contains a " TTE_YELLOW_TAG "Straight"; "时\n" TTE_RED_TAG "X3 " 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 the_tribe_joker_desc(Joker* joker, Rect dest_rect) static int the_tribe_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = static const char desc[] = TTE_BLACK_TAG "出牌含有 " TTE_YELLOW_TAG "同花 " TTE_BLACK_TAG
TTE_RED_TAG "X2" TTE_BLACK_TAG " Mult if played hand contains a " TTE_YELLOW_TAG "Flush"; "时\n" TTE_RED_TAG "X2 " 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 bootstraps_joker_desc(Joker* joker, Rect dest_rect) static int bootstraps_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc_format[] = static const char desc_format[] = TTE_BLACK_TAG
TTE_RED_TAG "+2" TTE_BLACK_TAG " Mult for every " TTE_YELLOW_TAG "$5" TTE_BLACK_TAG "每拥有 " TTE_YELLOW_TAG "$5\n" TTE_BLACK_TAG "给予 " TTE_RED_TAG "+2 " TTE_BLACK_TAG
" you have\n\n(Now " TTE_RED_TAG "+%ld" TTE_BLACK_TAG " Mult)"; "倍率\n\n(当前 " TTE_RED_TAG "+%ld " TTE_BLACK_TAG "倍率)";
const u32 desc_max_size = 125;
u32 bootstrap_bonus = (g_game_vars.money > 0) ? (g_game_vars.money / 5) * 2 : 0; u32 bootstrap_bonus = (g_game_vars.money > 0) ? (g_game_vars.money / 5) * 2 : 0;
char desc[desc_max_size]; char desc[JOKER_DESC_UTF8_BUFFER_SIZE];
snprintf(desc, desc_max_size, desc_format, bootstrap_bonus); 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 int shoot_the_moon_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = static const char desc[] = TTE_BLACK_TAG "手牌中每张 " TTE_YELLOW_TAG "Q\n" TTE_BLACK_TAG
TTE_BLACK_TAG "Each " TTE_YELLOW_TAG "Queen" TTE_BLACK_TAG "给予 " TTE_RED_TAG "+13 " TTE_BLACK_TAG "倍率";
" held in hand gives " TTE_RED_TAG "+13" TTE_BLACK_TAG " Mult"; return print_joker_desc(desc, dest_rect);
return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true);
} }
static int photograph_joker_desc(Joker* joker, Rect dest_rect) static int photograph_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = static const char desc[] = TTE_BLACK_TAG "打出的" TTE_YELLOW_TAG "第一张人头牌\n" TTE_BLACK_TAG
TTE_BLACK_TAG "First played " TTE_YELLOW_TAG "face" TTE_BLACK_TAG " card gives " TTE_RED_TAG "计分时给予 " TTE_RED_TAG "X2 " TTE_BLACK_TAG "倍率";
"X2" TTE_BLACK_TAG " Mult when scored"; return print_joker_desc(desc, dest_rect);
return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true);
} }
static int dusk_joker_desc(Joker* joker, Rect 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 static const char desc[] =
"final hand" TTE_BLACK_TAG " of the round"; TTE_BLACK_TAG "本回合" TTE_YELLOW_TAG "最后一次出牌\n" 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 brainstorm_joker_desc(Joker* joker, Rect dest_rect) static int brainstorm_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = static const char desc[] =
TTE_BLACK_TAG "Copies ability of the leftmost " TTE_YELLOW_TAG "Joker"; TTE_BLACK_TAG "复制" TTE_YELLOW_TAG "最左侧小丑牌" 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 blueprint_joker_desc(Joker* joker, Rect dest_rect) static int blueprint_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = static const char desc[] =
TTE_BLACK_TAG "Copies ability of " TTE_YELLOW_TAG "Joker" TTE_BLACK_TAG " to the right"; TTE_BLACK_TAG "复制" TTE_YELLOW_TAG "右侧小丑牌" 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 hack_joker_desc(Joker* joker, Rect dest_rect) static int hack_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = TTE_BLACK_TAG static const char desc[] =
"Retrigger each played " TTE_YELLOW_TAG "2" TTE_BLACK_TAG ", " TTE_YELLOW_TAG TTE_BLACK_TAG "打出的 " TTE_YELLOW_TAG "2、3、4、5\n" TTE_BLACK_TAG "均再触发一次";
"3" TTE_BLACK_TAG ", " TTE_YELLOW_TAG "4" TTE_BLACK_TAG ", or " TTE_YELLOW_TAG "5"; return print_joker_desc(desc, dest_rect);
return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true);
} }
static int seltzer_joker_desc(Joker* joker, Rect dest_rect) static int seltzer_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc_format[] = TTE_BLACK_TAG static const char desc_format[] =
"Retrigger all cards played for the next " TTE_YELLOW_TAG "%ld" TTE_BLACK_TAG " hands"; TTE_BLACK_TAG "接下来 " TTE_YELLOW_TAG "%ld " TTE_BLACK_TAG "次出牌中\n所有牌再触发一次";
const u32 desc_max_size = 94;
char desc[desc_max_size]; char desc[JOKER_DESC_UTF8_BUFFER_SIZE];
snprintf(desc, desc_max_size, desc_format, joker->persistent_state); 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 int sock_and_buskin_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = static const char desc[] =
TTE_BLACK_TAG "Retrigger all played " TTE_YELLOW_TAG "face" TTE_BLACK_TAG " cards"; TTE_BLACK_TAG "打出的" TTE_YELLOW_TAG "人头牌\n" 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 pareidolia_joker_desc(Joker* joker, Rect dest_rect) static int pareidolia_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = static const char desc[] = TTE_BLACK_TAG "所有牌均视为" TTE_YELLOW_TAG "人头牌";
TTE_BLACK_TAG "All cards are considered " TTE_YELLOW_TAG "face" TTE_BLACK_TAG " cards"; return print_joker_desc(desc, dest_rect);
return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true);
} }
static int shortcut_joker_desc(Joker* joker, Rect dest_rect) static int shortcut_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = static const char desc[] =
TTE_BLACK_TAG "Allows " TTE_YELLOW_TAG "Straights" TTE_BLACK_TAG TTE_YELLOW_TAG "顺子" TTE_BLACK_TAG "可间隔 " TTE_YELLOW_TAG "1 " TTE_BLACK_TAG
" to be made with gaps of " TTE_YELLOW_TAG "1 rank" TTE_BLACK_TAG "个点数\n\n例如 " TTE_YELLOW_TAG "10 8 6 5 3";
"\n\n(ex: " TTE_YELLOW_TAG "10 8 6 5 3" TTE_BLACK_TAG ")"; return print_joker_desc(desc, dest_rect);
return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true);
} }
static int four_fingers_joker_desc(Joker* joker, Rect dest_rect) static int four_fingers_joker_desc(Joker* joker, Rect dest_rect)
{ {
static const char desc[] = static const char desc[] =
TTE_BLACK_TAG "All " TTE_YELLOW_TAG "Flushes" TTE_BLACK_TAG " and " TTE_YELLOW_TAG TTE_YELLOW_TAG "同花" TTE_BLACK_TAG "和" TTE_YELLOW_TAG "顺子\n" TTE_BLACK_TAG
"Straights" TTE_BLACK_TAG " can be made with 4 cards"; "均可由 " TTE_YELLOW_TAG "4 " TTE_BLACK_TAG "张牌组成";
return tte_printf_justified_in_rect(desc, dest_rect, JUSTIFY_CENTER, SCREEN_LEFT, true); return print_joker_desc(desc, dest_rect);
} }
#pragma endregion #pragma endregion