diff --git a/configure.py b/configure.py index 7cab7b31..381dcfe9 100644 --- a/configure.py +++ b/configure.py @@ -1421,7 +1421,7 @@ config.libs = [ Object(Matching, "game/m_gba_ovl.c"), Object(Matching, "game/m_hand_ovl.c"), Object(Matching, "game/m_handbill.c"), - Object(NonMatching, "game/m_haniwa_ovl.c"), + Object(Matching, "game/m_haniwa_ovl.c"), Object(Matching, "game/m_haniwaPortrait_ovl.c"), Object(Matching, "game/m_hboard_ovl.c"), Object(Matching, "game/m_home.c"), diff --git a/include/m_haniwa_ovl.h b/include/m_haniwa_ovl.h index f01de02a..188ed7ff 100644 --- a/include/m_haniwa_ovl.h +++ b/include/m_haniwa_ovl.h @@ -11,6 +11,24 @@ extern "C" { #define mHW_OVL_MSG_SIZE 22 +enum { + mHW_MSG_IKAGA, + mHW_MSG_DONO, + mHW_MSG_DONO2, + mHW_MSG_OIKURA, + mHW_MSG_KASIKO, + mHW_MSG_DOREWO, + mHW_MSG_MOU, // @unused - not actually set anywhere + mHW_MSG_OKANE, + mHW_MSG_MAIDO, + mHW_MSG_TADA, + mHW_MSG_TADA2, + mHW_MSG_MISE, + mHW_MSG_BERU2, + + mHW_MSG_NUM +}; + typedef void (*mHW_SET_INTERRUPT_MESSAGE_PROC)(Submenu*, mTG_tag_c*, int); struct haniwa_ovl_s { diff --git a/src/game/m_haniwa_ovl.c b/src/game/m_haniwa_ovl.c new file mode 100644 index 00000000..4108f240 --- /dev/null +++ b/src/game/m_haniwa_ovl.c @@ -0,0 +1,395 @@ +#include "m_haniwa_ovl.h" + +#include "m_submenu_ovl.h" +#include "m_common_data.h" +#include "sys_matrix.h" +#include "m_tag_ovl.h" +#include "m_player_lib.h" +#include "m_inventory_ovl.h" +#include "m_hand_ovl.h" +#include "m_font.h" +#include "m_haniwaPortrait_ovl.h" + +static mHW_Ovl_c haniwa_ovl_data; + +static void mHW_set_interrupt_message(Submenu* submenu, mTG_tag_c* tag, int msg_idx) { + mHW_Ovl_c* haniwa_ovl = submenu->overlay->haniwa_ovl; + + haniwa_ovl->msg_interrupt_idx = msg_idx; + haniwa_ovl->table_idx = tag->table; + haniwa_ovl->sub_idx = tag->tag_col; + haniwa_ovl->msg_time = 120; +} + +static void mHW_set_price(Submenu* submenu, u8** str) { + mTG_tag_c* tag = &submenu->overlay->tag_ovl->tags[0]; + mSM_MenuInfo_c* menu_info = &submenu->overlay->menu_info[mSM_OVL_HANIWA]; + u8 price_str[6]; + u32 price = Save_Get(homes[menu_info->data1]).haniwa.items[tag->tag_col].extra_data; + int len; + int found; + + submenu->overlay->haniwa_ovl->msg_price = price; + mFont_UnintToString(price_str, sizeof(price_str), price, sizeof(price_str) - 1, TRUE, FALSE, TRUE); + len = mMl_strlen2(&found, price_str, sizeof(price_str), CHAR_SPACE); + if (found == TRUE) { + len--; + } + mem_copy(*str, price_str, len); + (*str)[len] = CHAR_SPACE; + *str += len + 1; +} + +typedef struct { + u8* str; + int len; +} mHW_msg_c; + +static void mHW_make_cond_message(Submenu* submenu, int msg_idx) { + static u8 mes_ikaga[15] = "How can I help?"; + static u8 mes_dono[11] = "Choose one."; + static u8 mes_dono2[15] = "May I help you?"; + static u8 mes_oikura[9] = "How much?"; + static u8 mes_kasiko[7] = "Got it!"; + static u8 mes_dorewo[11] = "Choose one."; + static u8 mes_mou[20] = "You don't have room."; + static u8 mes_okane[22] = "You can't afford that."; + static u8 mes_maido[20] = "Thank you very much!"; + static u8 mes_tada[11] = "That's free"; + static u8 mes_tada2[9] = "Give Away"; + static u8 mes_mise[20] = "That's display only."; + static u8 mes_beru[5] = "It's\xD3"; + static u8 mes_beru2[5] = "Bells"; + + static mHW_msg_c mes_data_tbl[] = { + // clang-format off + {mes_ikaga, sizeof(mes_ikaga)}, + {mes_dono, sizeof(mes_dono)}, + {mes_dono2, sizeof(mes_dono2)}, + {mes_oikura, sizeof(mes_oikura)}, + {mes_kasiko, sizeof(mes_kasiko)}, + {mes_dorewo, sizeof(mes_dorewo)}, + {mes_mou, sizeof(mes_mou)}, + {mes_okane, sizeof(mes_okane)}, + {mes_maido, sizeof(mes_maido)}, + {mes_tada, sizeof(mes_tada)}, + {mes_tada2, sizeof(mes_tada2)}, + {mes_mise, sizeof(mes_mise)}, + {mes_beru2, sizeof(mes_beru2)}, + // clang-format on + }; + + static mHW_msg_c mes_beru_data = { mes_beru, sizeof(mes_beru) }; + + mHW_msg_c* msg_p = &mes_data_tbl[msg_idx]; + u8* str_p = submenu->overlay->haniwa_ovl->msg; + + mem_clear(str_p, mHW_OVL_MSG_SIZE, CHAR_SPACE); + if (msg_idx == mHW_MSG_BERU2) { + mem_copy(str_p, mes_beru_data.str, mes_beru_data.len); + str_p += mes_beru_data.len; + mHW_set_price(submenu, &str_p); + } + + mem_copy(str_p, msg_p->str, msg_p->len); +} + +static int mHW_make_message_interrupt(Submenu* submenu) { + mTG_Ovl_c* tag_ovl = submenu->overlay->tag_ovl; + mTG_tag_c* tag = &tag_ovl->tags[tag_ovl->sel_tag_idx]; + mHW_Ovl_c* haniwa_ovl = submenu->overlay->haniwa_ovl; + int timer = haniwa_ovl->msg_time; + int msg_idx = haniwa_ovl->msg_interrupt_idx; + + if (timer - 1 < 0) { + haniwa_ovl->msg_interrupt_idx = -1; + } + + haniwa_ovl->msg_time = timer - 1; + if (msg_idx != mHW_MSG_DOREWO) { + if (tag_ovl->sel_tag_idx == 0) { + if (tag->table != haniwa_ovl->table_idx || tag->tag_col != haniwa_ovl->sub_idx) { + haniwa_ovl->msg_interrupt_idx = -1; + } + + } else if (tag_ovl->ret_tag_idx == tag_ovl->sel_tag_idx) { + haniwa_ovl->msg_interrupt_idx = -1; + } + } else { + if (tag_ovl->sel_tag_idx != -1) { + if (tag->table != haniwa_ovl->table_idx || tag->tag_col != haniwa_ovl->sub_idx) { + haniwa_ovl->msg_interrupt_idx = -1; + } + } + } + + return msg_idx; +} + +static int mHW_make_message_normal(Submenu* submenu, mSM_MenuInfo_c* menu_info) { + mTG_Ovl_c* tag_ovl = submenu->overlay->tag_ovl; + mTG_tag_c* tag = &tag_ovl->tags[tag_ovl->sel_tag_idx]; + int msg_idx = submenu->overlay->haniwa_ovl->msg_idx; + + switch (tag->type) { + case mTG_TYPE_NONE: + case mTG_TYPE_HANIWA_PUT_ITEM: + if (tag->table == mTG_TABLE_HANIWA) { + Haniwa_Item_c* item = &Save_Get(homes[menu_info->data1]).haniwa.items[tag_ovl->tags[0].tag_col]; + + if (item->item != EMPTY_NO) { + switch (item->exchange_type) { + case mHm_HANIWA_TRADE_0: + if (menu_info->data0 == 0) { + msg_idx = mHW_MSG_TADA; + } else { + msg_idx = mHW_MSG_TADA2; + } + break; + case mHm_HANIWA_TRADE_1: + msg_idx = mHW_MSG_MISE; + break; + case mHm_HANIWA_TRADE_2: + msg_idx = mHW_MSG_BERU2; + break; + default: + msg_idx = mHW_MSG_MISE; + break; + } + } else { + if (menu_info->data0 == 0) { + msg_idx = mHW_MSG_IKAGA; + } else { + msg_idx = mHW_MSG_DONO2; + } + } + } else { + msg_idx = mHW_MSG_IKAGA; + } + break; + case mTG_TYPE_HANIWA_ITEM: + case mTG_TYPE_CATCH_ITEM: + msg_idx = mHW_MSG_DONO; + break; + case mTG_TYPE_HANIWA_PRICE: + msg_idx = mHW_MSG_OIKURA; + break; + } + + return msg_idx; +} + +static void mHW_make_message(Submenu* submenu, mSM_MenuInfo_c* menu_info) { + mTG_tag_c* tag = &submenu->overlay->tag_ovl->tags[0]; + mHW_Ovl_c* haniwa_ovl = submenu->overlay->haniwa_ovl; + int msg_idx; + int msg_idx_bak; + int ctr; + + ctr = haniwa_ovl->msg_counter; + ctr++; + if (ctr > mHW_OVL_MSG_SIZE) { + ctr = mHW_OVL_MSG_SIZE; + } + + haniwa_ovl->msg_counter = ctr; + msg_idx_bak = haniwa_ovl->msg_idx; + if (haniwa_ovl->msg_interrupt_idx != -1) { + msg_idx = mHW_make_message_interrupt(submenu); + } else { + msg_idx = mHW_make_message_normal(submenu, menu_info); + } + + if (msg_idx != msg_idx_bak || (msg_idx == mHW_MSG_BERU2 && + haniwa_ovl->msg_price != Save_Get(homes[menu_info->data1]).haniwa.items[tag->tag_col].extra_data)) { + mHW_make_cond_message(submenu, msg_idx); + haniwa_ovl->msg_idx = msg_idx; + haniwa_ovl->msg_counter = 0; + } +} + +static void mHW_move_Move(Submenu* submenu, mSM_MenuInfo_c* menu_info) { + submenu->overlay->move_Move_proc(submenu, menu_info); +} + +static void mHW_move_Play(Submenu* submenu, mSM_MenuInfo_c* menu_info) { + if (!menu_info->open_flag) { + submenu->overlay->tag_ovl->chg_tag_func_proc(submenu, mTG_TABLE_HANIWA, mTG_TYPE_NONE, 0, 0.0f, 0.0f); + menu_info->open_flag = TRUE; + } + + submenu->overlay->menu_control.tag_move_func(submenu, menu_info); +} + +static void mHW_move_End(Submenu* submenu, mSM_MenuInfo_c* menu_info) { + submenu->overlay->move_End_proc(submenu, menu_info); +} + +static void mHW_haniwa_ovl_move(Submenu* submenu) { + static mSM_MOVE_PROC ovl_move_proc[] = { + // clang-format off + mHW_move_Move, + mHW_move_Play, + (mSM_MOVE_PROC)none_proc1, + (mSM_MOVE_PROC)none_proc1, + mHW_move_End, + // clang-format on + }; + + mSM_MenuInfo_c* menu_info = &submenu->overlay->menu_info[mSM_OVL_HANIWA]; + + menu_info->pre_move_func(submenu); + (*ovl_move_proc[menu_info->proc_status])(submenu, menu_info); + + mHW_make_message(submenu, menu_info); + + switch (menu_info->proc_status) { + case mSM_OVL_PROC_PLAY: + submenu->overlay->hanwiaPortrait_ovl->haniwaPortrait_shape_move_proc(submenu); + submenu->overlay->menu_control.animation_flag = TRUE; + break; + case mSM_OVL_PROC_MOVE: + submenu->overlay->menu_control.animation_flag = FALSE; + break; + } +} + +extern Gfx hni_win_mode[]; +extern Gfx hni_win_modelT[]; + +static void mHW_set_frame_dl(Submenu* submenu, GRAPH* graph, f32 pos_x, f32 pos_y) { + int tex_x; + int tex_y; + + Matrix_scale(16.0f, 16.0f, 1.0f, 0); + Matrix_translate(pos_x, pos_y, -809.0f, 1); + + OPEN_POLY_OPA_DISP(graph); + + gSPDisplayList(POLY_OPA_DISP++, hni_win_mode); + gSPMatrix(POLY_OPA_DISP++, _Matrix_to_Mtx_new(graph), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gDPTileSync(POLY_OPA_DISP++); + tex_x = -submenu->overlay->menu_control.texture_pos[0] * 8; + tex_y = -submenu->overlay->menu_control.texture_pos[1] * 8; + gDPSetTileSize_Dolphin(POLY_OPA_DISP++, G_TX_RENDERTILE, (u8)tex_x, (u8)tex_y, 32, 32); + gSPDisplayList(POLY_OPA_DISP++, hni_win_modelT); + + CLOSE_POLY_OPA_DISP(graph); +} + +extern Gfx inv_item_mode[]; + +static void mHW_set_item(Submenu* submenu, GRAPH* graph, mSM_MenuInfo_c* menu_info, f32 pos_x, f32 pos_y) { + Haniwa_Item_c* item = Save_Get(homes[menu_info->data1]).haniwa.items; + f32 pos[2]; + int i; + + OPEN_POLY_OPA_DISP(graph); + + gSPDisplayList(POLY_OPA_DISP++, inv_item_mode); + + CLOSE_POLY_OPA_DISP(graph); + + for (i = 0; i < HANIWA_ITEM_HOLD_NUM; i++) { + if (item->item != EMPTY_NO) { + submenu->overlay->tag_ovl->set_hand_pos_proc(submenu, pos, mTG_TABLE_HANIWA, i); + submenu->overlay->draw_item_proc(graph, pos_x + pos[0], pos_y + pos[1], 1.0f, item->item, FALSE, TRUE, 0, FALSE, FALSE); + } + + item++; + } +} + +static void mHW_set_message(Submenu* submenu, GAME* game, mSM_MenuInfo_c* menu_info) { + GRAPH* graph = game->graph; + mHW_Ovl_c* haniwa_ovl = submenu->overlay->haniwa_ovl; + + submenu->overlay->set_char_matrix_proc(graph); + // clang-format off + mFont_SetLineStrings( + game, + haniwa_ovl->msg, haniwa_ovl->msg_counter, + 160.0f + (26.0f + (menu_info->position[0] - 89.0f)), 120.0f - ((97.0f + menu_info->position[1]) - 11.0f), + 45, 50, 0, 255, + FALSE, TRUE, + 0.875f, 0.875f, + mFont_MODE_POLY + ); + // clang-format on +} + +static void mHW_set_dl(mSM_MenuInfo_c* menu_info, Submenu* submenu, GAME* game) { + GRAPH* graph = game->graph; + f32 pos_x = menu_info->position[0]; + f32 pos_y = menu_info->position[1]; + + mHW_set_frame_dl(submenu, graph, pos_x, pos_y); + mHW_set_item(submenu, graph, menu_info, pos_x, pos_y); + submenu->overlay->hanwiaPortrait_ovl->set_haniwaPortrait_proc(submenu, menu_info, graph, game, 39.0f + pos_x, 19.0f - pos_y); + mHW_set_message(submenu, game, menu_info); + submenu->overlay->menu_control.tag_draw_func(submenu, game, mSM_OVL_HANIWA); +} + +static void mHW_haniwa_ovl_draw(Submenu* submenu, GAME* game) { + mSM_MenuInfo_c* menu_info = &submenu->overlay->menu_info[mSM_OVL_HANIWA]; + + menu_info->pre_draw_func(submenu, game); + mHW_set_dl(menu_info, submenu, game); +} + +extern void mHW_haniwa_ovl_set_proc(Submenu* submenu) { + mSM_Control_c* ctrl = &submenu->overlay->menu_control; + mSM_MenuInfo_c* menu_info = &submenu->overlay->menu_info[mSM_OVL_HANIWA]; + + ctrl->menu_move_func = mHW_haniwa_ovl_move; + ctrl->menu_draw_func = mHW_haniwa_ovl_draw; + if (submenu->overlay->hand_ovl != NULL) { + submenu->overlay->hand_ovl->set_hand_func(submenu); + } +} + +static void mHW_haniwa_ovl_init(Submenu* submenu) { + mSM_MenuInfo_c* menu_info = &submenu->overlay->menu_info[mSM_OVL_HANIWA]; + mHW_Ovl_c* haniwa_ovl = submenu->overlay->haniwa_ovl; + + submenu->overlay->menu_control.animation_flag = FALSE; + + switch (menu_info->data0) { + case 0: + haniwa_ovl->msg_interrupt_idx = -1; + haniwa_ovl->msg_time = 0; + break; + case 1: + haniwa_ovl->msg_interrupt_idx = mHW_MSG_DOREWO; + haniwa_ovl->table_idx = mTG_TABLE_HANIWA; + haniwa_ovl->sub_idx = 0; + haniwa_ovl->msg_time = 120; + break; + } + + mem_clear(haniwa_ovl->msg, mHW_OVL_MSG_SIZE, CHAR_SPACE); + menu_info->proc_status = mSM_OVL_PROC_MOVE; + menu_info->move_drt = mSM_MOVE_IN_LEFT; + menu_info->next_proc_status = mSM_OVL_PROC_PLAY; +} + +extern void mHW_haniwa_ovl_construct(Submenu* submenu) { + Submenu_Overlay_c* ovl = submenu->overlay; + mHW_Ovl_c* haniwa_ovl = ovl->haniwa_ovl; + + if (haniwa_ovl == NULL) { + mem_clear((u8*)&haniwa_ovl_data, sizeof(haniwa_ovl_data), 0); + ovl->haniwa_ovl = &haniwa_ovl_data; + submenu->overlay->haniwa_ovl->set_interrupt_message_proc = mHW_set_interrupt_message; + haniwa_ovl_data.msg_idx = -1; + haniwa_ovl_data.table_idx = mTG_TABLE_ITEM; + haniwa_ovl_data.sub_idx = 0; + } + + mHW_haniwa_ovl_init(submenu); + mHW_haniwa_ovl_set_proc(submenu); +} + +extern void mHW_haniwa_ovl_destruct(Submenu* submenu) { + submenu->overlay->haniwa_ovl = NULL; +} diff --git a/src/game/m_tag_ovl.c b/src/game/m_tag_ovl.c index 0d490dd0..bab4e407 100644 --- a/src/game/m_tag_ovl.c +++ b/src/game/m_tag_ovl.c @@ -3123,7 +3123,7 @@ static void mTG_set_trade_cond(Submenu* submenu, mSM_MenuInfo_c* menu_info, s16 Save_Get(homes[menu_info->data1]).haniwa.items[tag->tag_col].extra_data = arg; mTG_return_tag_init(submenu, mTG_TYPE_NONE, mTG_RETURN_CLOSE); sAdo_SysTrgStart(NA_SE_33); - submenu->overlay->haniwa_ovl->set_interrupt_message_proc(submenu, tag, 4); + submenu->overlay->haniwa_ovl->set_interrupt_message_proc(submenu, tag, mHW_MSG_KASIKO); } static void mTG_present_open_proc(Submenu* submenu, mSM_MenuInfo_c* menu_info) { @@ -3274,7 +3274,7 @@ static void mTG_get_proc(Submenu* submenu, mSM_MenuInfo_c* menu_info) { changed_money -= haniwa_item_p->extra_data; if (changed_money < 0) { - submenu->overlay->haniwa_ovl->set_interrupt_message_proc(submenu, tag, 7); + submenu->overlay->haniwa_ovl->set_interrupt_message_proc(submenu, tag, mHW_MSG_OKANE); mTG_return_tag_init(submenu, mTG_TYPE_NONE, mTG_RETURN_CLOSE); sAdo_SysTrgStart(MONO(NA_SE_3)); } else { @@ -3300,7 +3300,7 @@ static void mTG_get_proc(Submenu* submenu, mSM_MenuInfo_c* menu_info) { Now_Private->inventory.wallet = keep_money; mPr_SetPossessionItem(Now_Private, idx, haniwa_item_p->item, mPr_ITEM_COND_NORMAL); - submenu->overlay->haniwa_ovl->set_interrupt_message_proc(submenu, tag, 8); + submenu->overlay->haniwa_ovl->set_interrupt_message_proc(submenu, tag, mHW_MSG_MAIDO); mTG_return_tag_init(submenu, mTG_TYPE_NONE, mTG_RETURN_CLOSE); Save_Get(homes[menu_info->data1]).haniwa.bells += haniwa_item_p->extra_data; haniwa_item_p->item = EMPTY_NO;