4#include "affine_background_gfx.h"
13enum GameRoundEndStates
17 DISPLAY_FINISHED_BLIND,
23 DISMISS_ROUND_END_PANEL,
30 REWARD_TYPE_INVESTMENT,
35static const u32 TM_RESET_STATIC_VARS = 30;
36static const u32 TM_END_POP_MENU_ANIM = 13;
37static const u32 TM_START_ROUND_END_REWARDS_ANIM = 1;
38static const u32 TM_END_DISPLAY_FIN_BLIND = 30;
39static const u32 TM_END_DISPLAY_SCORE_MIN = 4;
40static const u32 TM_DISMISS_ROUND_END_TM = 20;
42static const u32 REWARD_PANEL_BORDER_PID = 19;
44static const u32 ROUND_END_BLACK_PANEL_INIT_BOTTOM_SE = 12;
45static const u32 ROUND_END_REWARD_TEXT_X = 88;
46static const u32 ROUND_END_REWARD_AMOUNT_X = 168;
49static const Rect ROUND_END_BLIND_REQ_RECT = {104, 96, 136, UNDEFINED};
50static const Rect ROUND_END_BLIND_REWARD_RECT = {168, 96, UNDEFINED, UNDEFINED};
51static const Rect CASHOUT_DEST_RECT = {10, 8, 23, 10 };
52static const Rect CASHOUT_TEXT_RECT = {88, 72, UNDEFINED, UNDEFINED};
53static const Rect BLIND_TOKEN_TEXT_RECT = {80, 72, 200, 160 };
54static const Rect ROUND_END_MENU_RECT = {9, 7, 24, 20 };
56static const BG_POINT CASHOUT_SRC_3X3_RECT_POS = {5, 29};
100 [REWARD_TYPE_HAND] = {
102 .text_color = TTE_BLUE_PB,
107 [REWARD_TYPE_INVESTMENT] = {
109 .text_color = TTE_YELLOW_PB,
110 .multiplier = INVESTMENT_TAG_REWARD,
114 [REWARD_TYPE_INTEREST] = {
116 .text_color = TTE_YELLOW_PB,
124static enum RewardType s_current_reward = 0;
125static u32 s_current_reward_start_time = TM_DISPLAY_REWARDS_CONT_WAIT;
126static int s_reward_y_offset = 1;
128static int s_blind_reward = 0;
129static int s_cashout = 0;
131static int calculate_interest_reward(
void);
133static void round_end_start(
void);
134static void round_end_start_expand_popup(
void);
135static void round_end_display_finished_blind(
void);
136static void round_end_display_score_min(
void);
137static void round_end_update_blind_reward(
void);
138static void round_end_panel_exit(
void);
139static void round_end_display_rewards(
void);
140static void round_end_display_cashout(
void);
141static void round_end_dismiss_round_end_panel(
void);
143static void round_end_extend_black_panel_down(
int black_panel_bottom);
148 [ROUND_END_START] = STATE_INFO_UPDATE_FN_ONLY(round_end_start),
149 [START_EXPAND_POPUP] = STATE_INFO_UPDATE_FN_ONLY(round_end_start_expand_popup),
150 [DISPLAY_FINISHED_BLIND] = STATE_INFO_UPDATE_FN_ONLY(round_end_display_finished_blind),
151 [DISPLAY_SCORE_MIN] = STATE_INFO_UPDATE_FN_ONLY(round_end_display_score_min),
152 [UPDATE_BLIND_REWARD] = STATE_INFO_UPDATE_FN_ONLY(round_end_update_blind_reward),
153 [BLIND_PANEL_EXIT] = STATE_INFO_UPDATE_FN_ONLY(round_end_panel_exit),
154 [DISPLAY_REWARDS] = STATE_INFO_UPDATE_FN_ONLY(round_end_display_rewards),
155 [DISPLAY_CASHOUT] = STATE_INFO_UPDATE_FN_ONLY(round_end_display_cashout),
156 [DISMISS_ROUND_END_PANEL] = STATE_INFO_UPDATE_FN_ONLY(round_end_dismiss_round_end_panel),
160static StateMachine round_end_sm = STATE_MACHINE_DEFINE(state_info, ROUND_END_STATES_MAX);
162static int calculate_interest_reward(
void)
164 int reward = (g_game_vars.money / 5) * INTEREST_PER_5;
165 if (reward > MAX_INTEREST)
166 reward = MAX_INTEREST;
170static void round_end_start(
void)
173 if (g_game_vars.timer == TM_RESET_STATIC_VARS)
177 g_game_vars.timer = TM_ZERO;
180 s_current_reward = 0;
181 s_current_reward_start_time = TM_DISPLAY_REWARDS_CONT_WAIT;
182 s_reward_y_offset = 1;
185 s_reward_data[REWARD_TYPE_HAND].
count = g_game_vars.hands;
186 s_reward_data[REWARD_TYPE_INVESTMENT].
count = g_game_vars.current_blind >= BLIND_TYPE_BOSS
189 s_reward_data[REWARD_TYPE_INTEREST].
count = calculate_interest_reward();
192 for (
enum RewardType i = 0; i < REWARD_TYPE_MAX; i++)
200static void round_end_start_expand_popup(
void)
204 if (g_game_vars.timer == TM_END_POP_MENU_ANIM)
207 g_game_vars.timer = TM_ZERO;
211static void round_end_display_finished_blind(
void)
215 int current_ante = g_game_vars.ante;
218 if (g_game_vars.current_blind > BLIND_TYPE_BIG)
221 Rect blind_req_rect = ROUND_END_BLIND_REQ_RECT;
228 char blind_req_str_buff[UINT_MAX_DIGITS + 1];
229 snprintf(blind_req_str_buff,
sizeof(blind_req_str_buff),
"%lu", blind_req);
234 "#{P:%d,%d; cx:0x%X000}%s",
241 if (g_game_vars.timer == TM_START_ROUND_END_REWARDS_ANIM)
243 round_end_extend_black_panel_down(ROUND_END_BLACK_PANEL_INIT_BOTTOM_SE);
246 if (g_game_vars.timer >= TM_END_DISPLAY_FIN_BLIND)
249 g_game_vars.timer = TM_ZERO;
253static void round_end_display_score_min(
void)
255 const int timer_offset = g_game_vars.timer - 1;
256 const int x_from = 0;
257 const int y_from = 29;
262 &se_mem[MAIN_BG_SBB][x_to + timer_offset + 32 * y_to],
263 &se_mem[MAIN_BG_SBB][x_from + timer_offset + 32 * y_from],
267 if (g_game_vars.timer >= TM_END_DISPLAY_SCORE_MIN)
270 g_game_vars.timer = TM_ZERO;
274static void round_end_update_blind_reward(
void)
276 if (g_game_vars.timer % FRAMES(20) != 0)
281 if (s_blind_reward > 0)
285 "#{P:%d,%d; cx:0x%X000}$%d",
286 BLIND_REWARD_RECT.left,
287 BLIND_REWARD_RECT.top,
292 "#{P:%d,%d; cx:0x%X000}$%d",
293 ROUND_END_BLIND_REWARD_RECT.left,
294 ROUND_END_BLIND_REWARD_RECT.top,
299 else if (g_game_vars.timer > FRAMES(20))
306 g_game_vars.timer = TM_ZERO;
310static void round_end_panel_exit(
void)
314 if (g_game_vars.timer < 8)
318 if (g_game_vars.timer == 1)
322 else if (g_game_vars.timer == 2)
325 memset16(&se_mem[MAIN_BG_SBB][32 * (y - 1)], 0x0001, 1);
326 memset16(&se_mem[MAIN_BG_SBB][1 + 32 * (y - 1)], 0x0002, 7);
327 memset16(&se_mem[MAIN_BG_SBB][8 + 32 * (y - 1)], 0x0401, 1);
330 else if (g_game_vars.timer > FRAMES(20))
332 memset16(&pal_bg_mem[REWARD_PANEL_BORDER_PID], 0x1483, 1);
334 g_game_vars.timer = TM_ZERO;
338static inline void round_end_print_separator_ellipsis(
void)
341 (ROUND_END_REWARDS_ELLIPSIS_POS.x + g_game_vars.timer - TM_REWARDS_ELLIPSIS_PRINT_START) *
343 int y = (ROUND_END_REWARDS_ELLIPSIS_POS.y) *
TILE_SIZE;
345 tte_printf(
"#{P:%d,%d; cx:0x%X000}.", x, y, TTE_WHITE_PB);
348static inline bool s_should_increment_curr_reward(
void)
350 switch (s_current_reward)
354 case REWARD_TYPE_HAND:
355 case REWARD_TYPE_INTEREST:
356 return g_game_vars.timer % FRAMES(TM_REWARD_INCREMENT_INTERVAL) == 0;
360 case REWARD_TYPE_INVESTMENT:
368static inline void round_end_print_current_reward(
void)
370 int reward_y = ROUND_END_REWARDS_ELLIPSIS_POS.y + s_reward_y_offset;
371 if (g_game_vars.timer == s_current_reward_start_time)
373 round_end_extend_black_panel_down(reward_y);
376 "#{P:%lu,%d; cx:0x%X000}%d #{cx:0x%X000}%s",
377 ROUND_END_REWARD_TEXT_X,
379 s_reward_data[s_current_reward].text_color,
380 s_reward_data[s_current_reward].count,
382 s_reward_data[s_current_reward].text
385 if (s_current_reward == REWARD_TYPE_INVESTMENT)
390 else if (g_game_vars.timer > s_current_reward_start_time + TM_REWARD_DISPLAY_INTERVAL)
392 if (!s_should_increment_curr_reward())
395 s_reward_data[s_current_reward].
remaining--;
396 int accumulated_reward =
397 s_reward_data[s_current_reward].
count - s_reward_data[s_current_reward].
remaining;
400 "#{P:%lu, %d; cx:0x%X000}$%d",
401 ROUND_END_REWARD_AMOUNT_X,
404 accumulated_reward * s_reward_data[s_current_reward].multiplier
407 if (s_reward_data[s_current_reward].remaining <= 0)
411 s_current_reward_start_time = g_game_vars.timer + TM_REWARD_INCREMENT_INTERVAL;
416static void round_end_display_rewards(
void)
419 if (s_current_reward >= REWARD_TYPE_MAX)
421 g_game_vars.timer = TM_ZERO;
426 if (g_game_vars.timer == TM_START_ROUND_END_REWARDS_ANIM)
428 round_end_extend_black_panel_down(ROUND_END_REWARDS_ELLIPSIS_POS.y);
430 else if (g_game_vars.timer < TM_REWARDS_ELLIPSIS_PRINT_END)
432 round_end_print_separator_ellipsis();
434 else if (g_game_vars.timer >= TM_DISPLAY_REWARDS_CONT_WAIT)
437 while (s_current_reward < REWARD_TYPE_MAX && s_reward_data[s_current_reward].remaining <= 0)
440 if (s_current_reward < REWARD_TYPE_MAX)
441 round_end_print_current_reward();
445static inline void round_end_cashout(
void)
448 g_game_vars.money += s_cashout;
451 g_game_vars.hands = MAX_HANDS;
452 g_game_vars.discards = MAX_DISCARDS;
457 g_game_vars.score = 0;
458 display_score(g_game_vars.score);
461static void round_end_display_cashout()
463 if (g_game_vars.timer == FRAMES(40))
468 bool omit_space = s_cashout >= 10;
470 "#{P:%d, %d; cx:0x%X000}Cash Out:%s$%d",
471 CASHOUT_TEXT_RECT.left,
472 CASHOUT_TEXT_RECT.top,
474 omit_space ?
"" :
" ",
480 else if (g_game_vars.timer > FRAMES(40) && key_hit(SELECT_CARD))
485 g_game_vars.timer = TM_ZERO;
492static void round_end_dismiss_round_end_panel(
void)
494 Rect round_end_down = ROUND_END_MENU_RECT;
495 round_end_down.top--;
498 if (g_game_vars.timer >= TM_DISMISS_ROUND_END_TM)
500 g_game_vars.timer = TM_ZERO;
501 game_change_state(GAME_STATE_SHOP);
505static void round_end_extend_black_panel_down(
int black_panel_bottom)
507 Rect single_line_rect = ROUND_END_MENU_RECT;
508 single_line_rect.bottom = black_panel_bottom;
509 single_line_rect.top = single_line_rect.bottom - 1;
525 g_game_vars.hand_size = DEFAULT_HAND_SIZE;
526 g_game_vars.timer = 0;
527 g_game_vars.nb_unused_discards += g_game_vars.discards;
539 for (
enum RewardType i = 0; i < REWARD_TYPE_MAX; i++)
541 s_reward_data[i].
count = 0;
Utilities for affine background on GBA.
void affine_background_load_palette(const u16 *src)
Set the background palette.
u32 blind_get_requirement(enum BlindType type, int ante)
Get the score required to beat a certain blind (either the Small, Big, or any Boss/Showdown blind) at...
int blind_get_reward(enum BlindType type)
Get the amount of money gained from beating a certain Blind.
void change_background(enum BackgroundId id, bool force_redraw)
void reset_top_left_panel_bottom_row(void)
Restores the bottom row of the top-left panel from the background map.
Game global game variables struct definition.
void main_bg_se_copy_rect_1_tile_vert(Rect se_rect, enum ScreenVertDir direction)
Copies a rect in the main background vertically in direction by a single tile.
void main_bg_se_clear_rect(Rect se_rect)
Clears a rect in the main background.
void toggle_windows(bool win0, bool win1)
Toggles the visibility of the window layers.
void update_text_rect_to_right_align_str(Rect *rect, const char *str, enum OverflowDir overflow_direction)
Changes rect->left so it fits the digits of num exactly when right aligned to rect->right....
#define TILE_SIZE
Tile size in pixels, both height and width as tiles are square.
void main_bg_se_copy_expand_3x3_rect(Rect se_rect_dest, BG_POINT se_rect_src_3x3_top_left)
Copies a 3x3 rect and expands it to fit a passed rect. Special case of the 9-patch.
void tte_erase_rect_wrapper(Rect rect)
A wrapper for tte_erase_rect that would use the rect struct.
Header of shared rects and points needed for ui.
Round end game state functions.
void round_end_change_background(void)
Change to the round end background.
void round_end_on_exit(void)
Round end cleanup.
void round_end_on_init(void)
Round end state initialization.
void round_end_on_update(void)
Round end state update.
Data structures and functions related to the handling of Skip Tags.
void skip_tag_process_start(enum SkipTagEvent checked_tag_event)
Start Skip Tag processing for the specified event.
enum SkipTagProcStage skip_tag_process_get_proc_stage(void)
Recover the current stage of the Tag processing.
int skip_tag_count(enum SkipTagTypes tag_type)
Counts how many tags of a certain type we own.
void sprite_destroy(Sprite **sprite)
Destroy Sprite.
void sprite_hide(Sprite *sprite)
Hides the sprite by manipulating ATTR0_HIDE in OAM.
void sprite_unhide(Sprite *sprite)
Unhides the sprite by manipulating ATTR0_HIDE in OAM. The sprite's ATTR0_MODE is maintained from the ...
void state_machine_remove(StateMachine *state_machine)
Remove a statemachine's update function.
void state_machine_register(StateMachine *state_machine)
Register a statemachine to run it's update function once per frame.
void state_machine_change_state(StateMachine *state_machine, int new_state)
Calls the current state's on_exit, the new state's on_init, and sets the active update fn.
Data struct for the different types of rewards.
const char * text
the name of the reward (i.e. "Hands")
const int multiplier
how many dollars the player recieves every time a certain type of reward is counted towards the total...
int remaining
how many times the reward still needs to be counted for this End of Round
const u8 text_color
the color the name of the reward is printed with
int count
how many times the reward was earned by the player during the last round
Utilities relating around number string representation and protected arithmatic helper functions.