diff --git a/config/rel_slices.yml b/config/rel_slices.yml index 3cbf7cae..d9f3f475 100644 --- a/config/rel_slices.yml +++ b/config/rel_slices.yml @@ -749,6 +749,10 @@ ac_radio.c: ac_reserve.c: .text: [0x805B8C7C, 0x805B9098] .data: [0x806C65A0, 0x806C6608] +ac_s_car.c: + .text: [0x805B9098, 0x805B9644] + .rodata: [0x8064AB68, 0x8064AB88] + .data: [0x806C6608, 0x806C66D0] ac_shrine.c: .text: [0x805BA4D8, 0x805BB8D0] .rodata: [0x8064ABD0, 0x8064AC18] diff --git a/include/ac_s_car.h b/include/ac_s_car.h index 1f5e202d..1b7dca22 100644 --- a/include/ac_s_car.h +++ b/include/ac_s_car.h @@ -2,7 +2,7 @@ #define AC_S_CAR_H #include "types.h" -#include "m_actor.h" +#include "ac_structure.h" #ifdef __cplusplus extern "C" { diff --git a/include/ef_effect_control.h b/include/ef_effect_control.h index 29518dce..317fc64d 100644 --- a/include/ef_effect_control.h +++ b/include/ef_effect_control.h @@ -15,6 +15,7 @@ enum effect_type { eEC_EFFECT_MUKA, eEC_EFFECT_WARAU, /* TODO: finish */ + eEC_EFFECT_CAR_SPARKLE = 90, eEC_DOUZOU_LIGHT = 101, eEC_HEM_LIGHT = 123, diff --git a/include/m_event.h b/include/m_event.h index 1c5244d6..4b219333 100644 --- a/include/m_event.h +++ b/include/m_event.h @@ -379,6 +379,11 @@ typedef struct ghost_event_s { #define mEv_DESGINER_NUM 3 +typedef struct designer_common_s { + int button_presses; + int _04; +} mEv_dsg_common_c; + typedef struct kabu_peddler_event_s { PersonalID_c spoken_pids[TOTAL_PLAYER_NUM]; } mEv_kabu_peddler_c; diff --git a/include/m_lib.h b/include/m_lib.h index 5632eb79..150388ab 100644 --- a/include/m_lib.h +++ b/include/m_lib.h @@ -52,6 +52,10 @@ typedef struct rgba_t { //can be put in other place u8 r, g, b, a; } rgba_t; +typedef struct rgb_t { + uint r, g, b; +} rgb_t; + typedef struct { xyz_t position; s_xyz angle; diff --git a/include/m_name_table.h b/include/m_name_table.h index 86c088a1..67b1609e 100644 --- a/include/m_name_table.h +++ b/include/m_name_table.h @@ -2711,6 +2711,7 @@ extern int mNT_check_unknown(mActor_name_t item_no); #define DUMMY_RESERVE 0xF102 #define DUMMY_SHRINE 0xF103 #define DUMMY_BROKER_SHOP 0xF104 +#define DUMMY_CAR 0xF106 #define DUMMY_RADIO 0xF109 #define DUMMY_YATAI 0xF10A #define DUMMY_TUKIMI 0xF10A diff --git a/src/ac_s_car.c b/src/ac_s_car.c new file mode 100644 index 00000000..866e553c --- /dev/null +++ b/src/ac_s_car.c @@ -0,0 +1,65 @@ +#include "ac_s_car.h" + +#include "m_name_table.h" +#include "sys_matrix.h" +#include "m_lib.h" +#include "m_rcp.h" +#include "m_common_data.h" +#include "m_player_lib.h" + +static void aSCR_actor_ct(ACTOR* actor, GAME* game); +static void aSCR_actor_dt(ACTOR* actor, GAME* game); +static void aSCR_actor_init(ACTOR* actor, GAME* game); +static void aSCR_actor_draw(ACTOR* actor, GAME* game); + +ACTOR_PROFILE S_Car_Profile = { + mAc_PROFILE_S_CAR, + ACTOR_PART_ITEM, + ACTOR_STATE_TA_SET, + DESIGNER_CAR, + ACTOR_OBJ_BANK_KEEP, + sizeof(STRUCTURE_ACTOR), + &aSCR_actor_ct, + &aSCR_actor_dt, + &aSCR_actor_init, + &aSCR_actor_draw, + NULL +}; + +u8 aSCR_shadow_vtx_fix_flg_table0[24] = { + FALSE, FALSE, FALSE, FALSE, + FALSE, FALSE, TRUE, TRUE, + TRUE, TRUE, TRUE, TRUE, + TRUE, TRUE, TRUE, TRUE, + FALSE, FALSE, FALSE, FALSE, + FALSE, FALSE, FALSE, FALSE +}; + +extern Vtx obj_car_shadow_v[]; +extern Gfx obj_car_shadowT_model[]; +bIT_ShadowData_c aSCR_shadow_data = { + 23, aSCR_shadow_vtx_fix_flg_table0, 60.0f, obj_car_shadow_v, obj_car_shadowT_model, +}; + +static void aSCR_set_bgOffset(STRUCTURE_ACTOR* car, int offs); + +static void aSCR_actor_ct(ACTOR* actor, GAME* game) { + aSCR_set_bgOffset((STRUCTURE_ACTOR*)actor, 0); +} + +static void aSCR_actor_dt(ACTOR* actor, GAME* game) { + mEv_dsg_common_c* designer_common; + + designer_common = (mEv_dsg_common_c*)mEv_get_common_area(mEv_EVENT_DESIGNER, FALSE); + if (designer_common != NULL && designer_common->_04 == 2) { + designer_common->button_presses = 0; + } + + if (Save_Get(event_save_data).special.event.designer.used >= 3) { + mEv_special_event_soldout(mEv_EVENT_DESIGNER); + } +} + +#include "../src/ac_s_car_move.c_inc" + +#include "../src/ac_s_car_draw.c_inc" diff --git a/src/ac_s_car_draw.c_inc b/src/ac_s_car_draw.c_inc new file mode 100644 index 00000000..3c24d297 --- /dev/null +++ b/src/ac_s_car_draw.c_inc @@ -0,0 +1,43 @@ +extern Gfx s_car_DL_model[]; + +static void aSCR_set_prim_col(rgb_t* color) { + mEv_dsg_common_c* designer_common; + f32 percentage; + f32 remaining; + + designer_common = (mEv_dsg_common_c*)mEv_get_common_area(mEv_EVENT_DESIGNER, FALSE); + if (designer_common != NULL) { + percentage = designer_common->button_presses / 100.0f; + remaining = (1.0f - percentage); + + color->r = (remaining * 150) + (percentage * 255); + color->g = (remaining * 120) + (percentage * 255); + color->b = (remaining * 100) + (percentage * 255); + } else { + color->r = 150; + color->g = 120; + color->b = 100; + } +} + +static void aSCR_actor_draw(ACTOR* actor, GAME* game) { + GRAPH* graph; + Gfx* gfx; + rgb_t color; + + graph = game->graph; + + aSCR_set_prim_col(&color); + _texture_z_light_fog_prim_npc(graph); + + OPEN_DISP(graph); + gfx = NOW_POLY_OPA_DISP; + gDPSetPrimColor(gfx++, 0, 128, color.r, color.g, color.b, 255); + gSPMatrix(gfx++, _Matrix_to_Mtx_new(graph), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(gfx++, s_car_DL_model); + + SET_POLY_OPA_DISP(gfx); + CLOSE_DISP(graph); + + (*Common_Get(clip).bg_item_clip->draw_shadow_proc)(game, &aSCR_shadow_data, FALSE); +} diff --git a/src/ac_s_car_move.c_inc b/src/ac_s_car_move.c_inc new file mode 100644 index 00000000..3379b5e4 --- /dev/null +++ b/src/ac_s_car_move.c_inc @@ -0,0 +1,79 @@ +static void aSCR_set_bgOffset(STRUCTURE_ACTOR* car, int offs) { + static mCoBG_OffsetTable_c height_table_ct[] = { + { 0x64, 3, 3, 0, 3, 3, 1 }, + { 0x64, 3, 3, 3, 0, 3, 1 }, + { 0x64, 0, 0, 0, 0, 0, 0 }, + { 0x64, 3, 0, 3, 3, 3, 1 }, + { 0x64, 6, 3, 3, 3, 3, 0 }, + { 0x64, 3, 3, 3, 0, 3, 1 }, + { 0x64, 0, 0, 0, 0, 0, 0 }, + { 0x64, 3, 0, 3, 3, 3, 1 }, + { 0x64, 3, 3, 3, 3, 0, 1 } + }; + + static mCoBG_OffsetTable_c* height_table[] = { height_table_ct, height_table_ct }; + + static f32 addX[] = { -40.0f, 0.0f, 40.0f }; + static f32 addZ[] = { 40.0f, 0.0f, -40.0f }; + + mCoBG_OffsetTable_c* offset; + int i; + int j; + xyz_t pos; + + offset = height_table[offs]; + for (i = 0; i < 3; i++) { + pos.z = car->actor_class.home.position.z + addZ[i]; + + for (j = 0; j < 3; j++) { + pos.x = car->actor_class.home.position.x + addX[j]; + + if (j + i * 3 != 2 && j + i * 3 != 6) { + mCoBG_SetPluss5PointOffset_file(pos, *offset, __FILE__, 74); + } + + offset++; + } + } +} + +static void aSCR_actor_move(ACTOR* actor, GAME* game) { + STRUCTURE_ACTOR* car; + PLAYER_ACTOR* player_actor; + mEv_dsg_common_c* designer_common; + int car_bx; + int car_bz; + int player_bx; + int player_bz; + + car = (STRUCTURE_ACTOR*)actor; + player_actor = get_player_actor_withoutCheck((GAME_PLAY*)game); + + mFI_Wpos2BlockNum(&car_bx, &car_bz, actor->world.position); + mFI_Wpos2BlockNum(&player_bx, &player_bz, player_actor->actor_class.world.position); + + if (mDemo_Check(mDemo_TYPE_SCROLL, &player_actor->actor_class) == FALSE && + mDemo_Check(mDemo_TYPE_SCROLL2, &player_actor->actor_class) == FALSE && + mDemo_Check(mDemo_TYPE_SCROLL3, &player_actor->actor_class) == FALSE && + (car_bx != player_bx || car_bz != player_bz)) { + Actor_delete(actor); + return; + } + + designer_common = (mEv_dsg_common_c*)mEv_get_common_area(mEv_EVENT_DESIGNER, FALSE); + if (designer_common != NULL && designer_common->button_presses >= 100) { + if (car->action <= 0) { + (*Common_Get(clip).effect_clip->effect_make_proc)(eEC_EFFECT_CAR_SPARKLE, actor->world.position, 1, 0, game, + actor->npc_id, designer_common->_04 != 0, 0); + car->action = (int)(fqrand() * 3.0f) * 16 + 48; + } else { + car->action--; + } + } +} + +static void aSCR_actor_init(ACTOR* actor, GAME* game) { + mFI_SetFG_common(DUMMY_CAR, actor->home.position, FALSE); + aSCR_actor_move(actor, game); + actor->mv_proc = aSCR_actor_move; +}