diff --git a/configure.py b/configure.py index 05728c17..9b9568da 100644 --- a/configure.py +++ b/configure.py @@ -975,7 +975,7 @@ config.libs = [ Object(NonMatching, "actor/ac_gyo_kaseki.c"), Object(Matching, "actor/ac_gyo_release.c"), Object(NonMatching, "actor/ac_gyo_test.c"), - Object(NonMatching, "actor/ac_gyoei.c"), + Object(Matching, "actor/ac_gyoei.c"), Object(Matching, "actor/ac_handOverItem.c"), Object(Matching, "actor/ac_haniwa.c"), Object(Matching, "actor/ac_hatumode_control.c"), diff --git a/include/ac_gyoei.h b/include/ac_gyoei.h index 57745771..6655284c 100644 --- a/include/ac_gyoei.h +++ b/include/ac_gyoei.h @@ -3,12 +3,14 @@ #include "types.h" #include "ac_tools.h" +#include "ac_gyoei_h.h" #ifdef __cplusplus extern "C" { #endif #define aGYO_MAX_GYOEI 2 +#define aGYO_EXIST_MAX 4 enum { aGYO_GYO_TYPE_TEST, @@ -150,10 +152,13 @@ typedef struct gyoei_actor_s GYOEI_ACTOR; struct gyoei_actor_s { /* 0x000 */ ACTOR actor_class; /* 0x174 */ aGYO_CTRL_ACTOR ctrl[aGYO_MAX_GYOEI]; - /* 0x614 */ u8 exist[4]; - /* 0x618 */ int segment_type[4]; + /* 0x614 */ u8 exist[aGYO_EXIST_MAX]; + /* 0x618 */ int segment_type[aGYO_EXIST_MAX]; }; +extern void aGTT_actor_init(ACTOR* actorx, GAME* game); // ac_gyo_test.c +extern void aGKK_actor_init(ACTOR* actorx, GAME* game); // ac_gyo_kaseki + extern ACTOR_PROFILE Gyoei_Profile; #ifdef __cplusplus diff --git a/src/actor/ac_gyoei.c b/src/actor/ac_gyoei.c new file mode 100644 index 00000000..1b694f32 --- /dev/null +++ b/src/actor/ac_gyoei.c @@ -0,0 +1,90 @@ +#include "ac_gyoei.h" + +#include "m_common_data.h" +#include "m_actor_shadow.h" +#include "libultra/libultra.h" +#include "m_malloc.h" +#include "sys_matrix.h" +#include "m_skin_matrix.h" +#include "m_rcp.h" +#include "m_player_lib.h" + +static void aGYO_actor_ct(ACTOR* actorx, GAME* game); +static void aGYO_actor_dt(ACTOR* actorx, GAME* game); +static void aGYO_actor_move(ACTOR* actorx, GAME* game); +static void aGYO_actor_draw(ACTOR* actorx, GAME* game); + +// clang-format off +ACTOR_PROFILE Gyoei_Profile = { + mAc_PROFILE_GYOEI, + ACTOR_PART_CONTROL, + ACTOR_STATE_NO_DRAW_WHILE_CULLED | ACTOR_STATE_NO_MOVE_WHILE_CULLED, + EMPTY_NO, + ACTOR_OBJ_BANK_KEEP, + sizeof(GYOEI_ACTOR), + &aGYO_actor_ct, + &aGYO_actor_dt, + &aGYO_actor_move, + &aGYO_actor_draw, + NULL, +}; +// clang-format on + +static int aGYO_init_dma_and_clip_area(void); +static void aGYO_free_clip_area(void); + +static ACTOR* aGYO_ctrlActor = NULL; + +typedef struct gyoei_overlay_s { + u8 buf[0x3C00]; +} aGYO_overlay_c ATTRIBUTE_ALIGN(8); + +static aGYO_overlay_c aGYO_overlay[aGYO_MAX_GYOEI]; + +static void aGYO_actor_ct(ACTOR* actorx, GAME* game) { + GYOEI_ACTOR* gyoei = (GYOEI_ACTOR*)actorx; + int i; + aGYO_CTRL_ACTOR* ctrl = gyoei->ctrl; + + for (i = 0; i < aGYO_MAX_GYOEI; i++) { + ctrl->exist = FALSE; + ctrl->overlay_p = aGYO_overlay[i].buf; + ctrl++; + } + + for (i = 0; i < aGYO_EXIST_MAX; i++) { + gyoei->exist[i] = FALSE; + gyoei->segment_type[i] = -1; + } + + aGYO_ctrlActor = (ACTOR*)gyoei; + aGYO_init_dma_and_clip_area(); +} + +static void aGYO_actor_dt(ACTOR* actorx, GAME* game) { + GYOEI_ACTOR* gyoei = (GYOEI_ACTOR*)actorx; + int i; + aGYO_CTRL_ACTOR* ctrl = gyoei->ctrl; + + for (i = 0; i < aGYO_MAX_GYOEI; i++) { + if (ctrl->overlay_p != NULL) { + ctrl->overlay_p = NULL; + } + + ctrl++; + } + + aGYO_free_clip_area(); +} + +#include "../src/actor/ac_gyoei_model.c_inc" + +static mActor_proc aGYO_program_dlftbl[] = { + &aGTT_actor_init, + &aGKK_actor_init, +}; + +#include "../src/actor/ac_gyoei_clip.c_inc" +#include "../src/actor/ac_gyoei_move.c_inc" +#include "../src/actor/ac_gyoei_data.c_inc" +#include "../src/actor/ac_gyoei_draw.c_inc" diff --git a/src/actor/ac_gyoei_clip.c_inc b/src/actor/ac_gyoei_clip.c_inc new file mode 100644 index 00000000..10de8c8e --- /dev/null +++ b/src/actor/ac_gyoei_clip.c_inc @@ -0,0 +1,273 @@ +static int aGYO_searchCastFishNum(void) { + GYOEI_ACTOR* gyoei = (GYOEI_ACTOR*)aGYO_ctrlActor; + aGYO_CTRL_ACTOR* ctrl = gyoei->ctrl; + int i; + + for (i = 0; i < aGYO_MAX_GYOEI; i++) { + if ((ctrl[i].gyo_flags & 4) != 0) { + return i; + } + } + + return -1; +} + +static void aGYO_change_data_area(Object_Exchange_c* exc) { + int idx = aGYO_searchCastFishNum(); + GYOEI_ACTOR* gyoei = (GYOEI_ACTOR*)aGYO_ctrlActor; + // @BUG - idx can be -1... why isn't this bounds checked? + aGYO_CTRL_ACTOR* ctrl = &gyoei->ctrl[idx]; + + ctrl->draw_type = aGYO_DRAW_TYPE_FISH; +} + +static void aGYO_destruct(ACTOR* actorx, GAME* game) { + aGYO_CTRL_ACTOR* ctrl = (aGYO_CTRL_ACTOR*)actorx; + + ctrl->exist = FALSE; + ctrl->gyo_flags = 0; + ClObjPipe_dt(game, &ctrl->col_pipe); +} + +static int aGYO_searchRegistSpace(void) { + GYOEI_ACTOR* gyoei = (GYOEI_ACTOR*)aGYO_ctrlActor; + aGYO_CTRL_ACTOR* ctrl = gyoei->ctrl; + int i; + + for (i = 0; i < aGYO_MAX_GYOEI; i++) { + if (!ctrl[i].exist) { + return i; + } + } + + return -1; +} + +static void aGYO_setupActor(aGYO_Init_c* init_data, int idx) { + // clang-format off + static ACTOR_PROFILE Dummy_Profile = { + mAc_PROFILE_GYOEI, + ACTOR_PART_BG, + ACTOR_STATE_NO_DRAW_WHILE_CULLED | ACTOR_STATE_NO_MOVE_WHILE_CULLED, + EMPTY_NO, + ACTOR_OBJ_BANK_KEEP, + sizeof(ACTOR), + mActor_NONE_PROC1, + mActor_NONE_PROC1, + mActor_NONE_PROC1, + mActor_NONE_PROC1, + NULL, + }; + // clang-format on + + GYOEI_ACTOR* gyoei = (GYOEI_ACTOR*)aGYO_ctrlActor; + aGYO_CTRL_ACTOR* ctrl = &gyoei->ctrl[idx]; + GAME_PLAY* play = (GAME_PLAY*)init_data->game; + Object_Exchange_c* exc = &play->object_exchange; + + bzero(ctrl, sizeof(aGYO_CTRL_ACTOR)); + ctrl->tools_class.actor_class.shape_info.ofs_y = 200.0f; + ctrl->exist = TRUE; + ctrl->draw_type = aGYO_DRAW_TYPE_GYOEI; + ctrl->gyo_type = init_data->fish_type; + ctrl->act_proc = (aGYO_ACT_PROC)&none_proc1; + ctrl->range = 40.0f; + ctrl->col_flags |= 1; + + Actor_init_actor_class((ACTOR*)ctrl, &Dummy_Profile, NULL, play, -1, init_data->position.x, init_data->position.y, + init_data->position.z, 0, 0, 0, play->block_table.block_x, play->block_table.block_z, -1, + EMPTY_NO, 0); + Shape_Info_init((ACTOR*)ctrl, 0.0f, &mAc_ActorShadowCircle, 5.0f, 5.0f); + ctrl->tools_class.actor_class.shape_info.shadow_alpha_change_rate = 0.6f; + ctrl->tools_class.actor_class.world = ctrl->tools_class.actor_class.home; + ctrl->tools_class.actor_class.shape_info.rotation = ctrl->tools_class.actor_class.world.angle; + Actor_world_to_eye((ACTOR*)ctrl, 0.0f); + xyz_t_move(&ctrl->tools_class.actor_class.last_world_position, &ctrl->tools_class.actor_class.world.position); + ctrl->tools_class.actor_class.cull_width = 350.0f; + ctrl->tools_class.actor_class.cull_height = 700.0f; + ctrl->tools_class.actor_class.cull_distance = 1000.0f; + ctrl->tools_class.actor_class.cull_radius = 350.0f; + + if ((mFI_BkNum2BlockKind(ctrl->tools_class.actor_class.block_x, ctrl->tools_class.actor_class.block_z) & + mRF_BLOCKKIND_OFFING) == mRF_BLOCKKIND_OFFING) { + ctrl->col_flags &= ~1; + } + + if (ctrl->gyo_type == aGYO_TYPE_WHALE) { + ctrl->alpha = 50; + ctrl->tools_class.actor_class.cull_width = 450.0f; + ctrl->tools_class.actor_class.cull_radius = 450.0f; + } else { + ctrl->alpha = 120; + } + + { + mActor_proc* init_proc; + + switch (ctrl->gyo_type) { + case aGYO_TYPE_SALMON2: + ctrl->gyo_type = aGYO_TYPE_SALMON; + // fallthrough + case aGYO_TYPE_COELACANTH: + case aGYO_TYPE_JELLYFISH: + case aGYO_TYPE_SEA_BASS: + case aGYO_TYPE_RED_SNAPPER: + case aGYO_TYPE_BARRED_KNIFEJAW: + case aGYO_TYPE_WHALE: + init_proc = &aGYO_program_dlftbl[aGYO_GYO_TYPE_KASEKI]; + break; + default: + init_proc = &aGYO_program_dlftbl[aGYO_GYO_TYPE_TEST]; + break; + } + + ctrl->tools_class.actor_class.mv_proc = *init_proc; + } + + ctrl->tools_class.actor_class.drawn = TRUE; +} + +static int aGYO_make_gyoei(aGYO_Init_c* init_data) { + int idx = aGYO_searchRegistSpace(); + int ret = FALSE; + + if (idx >= 0) { + aGYO_setupActor(init_data, idx); + ret = TRUE; + } + + return ret; +} + +static f32 aGYO_escape_distance(s16 type) { + if (type == 0) { + return 150.0f; + } else { + return 30.0f; + } +} + +static void aGYO_ballcheck(xyz_t* pos_p, f32 r, s16 type) { + GYOEI_ACTOR* gyoei = (GYOEI_ACTOR*)aGYO_ctrlActor; + aGYO_CTRL_ACTOR* ctrl = gyoei->ctrl; + int i; + + for (i = 0; i < aGYO_MAX_GYOEI; i++) { + if (ctrl->exist == TRUE) { + f32 dist; + f32 escape_dist; + + ctrl->escape_flag = FALSE; + dist = search_position_distance(&ctrl->tools_class.actor_class.world.position, pos_p); + escape_dist = aGYO_escape_distance(type); + + if (dist < escape_dist) { + ctrl->escape_flag = TRUE; + } + } + + ctrl++; + } +} + +static void aGYO_hitcheck(xyz_t* pos_p, s16 size_type) { + GYOEI_ACTOR* gyoei = (GYOEI_ACTOR*)aGYO_ctrlActor; + aGYO_CTRL_ACTOR* ctrl = gyoei->ctrl; + int i; + + for (i = 0; i < aGYO_MAX_GYOEI; i++) { + if (ctrl->exist == TRUE && ctrl->escape_flag != TRUE) { + f32 dist; + f32 escape_dist; + + dist = search_position_distance(&ctrl->tools_class.actor_class.world.position, pos_p); + + switch (size_type) { + case aGYO_SIZE_XXS: + escape_dist = 70.0f; + break; + case aGYO_SIZE_XS: + case aGYO_SIZE_S: + case aGYO_SIZE_M: + escape_dist = 85.0f; + break; + default: + escape_dist = 100.0f; + break; + } + + if (dist < escape_dist) { + ctrl->escape_flag = TRUE; + } + } + + ctrl++; + } +} + +static int aGYO_chk_live_gyoei(int bx, int bz, GAME* game) { + GYOEI_ACTOR* gyoei = (GYOEI_ACTOR*)aGYO_ctrlActor; + aGYO_CTRL_ACTOR* ctrl = gyoei->ctrl; + int i; + int ret = FALSE; + + for (i = 0; i < aGYO_MAX_GYOEI; i++) { + if (ctrl->exist == TRUE && ctrl->tools_class.actor_class.block_x == bx && + ctrl->tools_class.actor_class.block_z == bz) { + ret = TRUE; + break; + } + + ctrl++; + } + + return ret; +} + +static ACTOR* aGYO_search_near_gyoei(f32 pos_x, f32 pos_z) { + GYOEI_ACTOR* gyoei = (GYOEI_ACTOR*)aGYO_ctrlActor; + aGYO_CTRL_ACTOR* ctrl = gyoei->ctrl; + int i; + aGYO_CTRL_ACTOR* ret = NULL; + f32 min_dist = 819200.0f; + + for (i = 0; i < aGYO_MAX_GYOEI; i++) { + if (ctrl->exist == TRUE) { + f32 dx = ((ACTOR*)ctrl)->world.position.x - pos_x; + f32 dz = ((ACTOR*)ctrl)->world.position.z - pos_z; + f32 dist = SQ(dx) + SQ(dz); + + if (dist < min_dist) { + ret = ctrl; + min_dist = dist; + } + } + + ctrl++; + } + + return (ACTOR*)ret; +} + +static int aGYO_init_dma_and_clip_area(void) { + int ret = FALSE; + + CLIP(gyo_clip) = (aGYO_Clip_c*)zelda_malloc(sizeof(aGYO_Clip_c)); + if (CLIP(gyo_clip) != NULL) { + CLIP(gyo_clip)->make_gyoei_proc = &aGYO_make_gyoei; + CLIP(gyo_clip)->dt_gyoei_proc = &aGYO_destruct; + CLIP(gyo_clip)->ballcheck_gyoei_proc = &aGYO_ballcheck; + CLIP(gyo_clip)->hitcheck_gyoei_proc = &aGYO_hitcheck; + CLIP(gyo_clip)->chk_live_gyoei_proc = &aGYO_chk_live_gyoei; + CLIP(gyo_clip)->search_near_gyoei_proc = &aGYO_search_near_gyoei; + + ret = TRUE; + } + + return ret; +} + +static void aGYO_free_clip_area(void) { + zelda_free(CLIP(gyo_clip)); + CLIP(gyo_clip) = NULL; +} diff --git a/src/actor/ac_gyoei_draw.c_inc b/src/actor/ac_gyoei_draw.c_inc new file mode 100644 index 00000000..8eb635bd --- /dev/null +++ b/src/actor/ac_gyoei_draw.c_inc @@ -0,0 +1,222 @@ +enum { + aGYO_ANIME_PAT_TYPE_NONE, + aGYO_ANIME_PAT_TYPE_FAST, + aGYO_ANIME_PAT_TYPE_SLOW, + + aGYO_ANIME_PAT_TYPE_NUM +}; + +static int aGYO_anime_ptn[] = { + aGYO_ANIME_PAT_TYPE_FAST, aGYO_ANIME_PAT_TYPE_SLOW, aGYO_ANIME_PAT_TYPE_SLOW, aGYO_ANIME_PAT_TYPE_SLOW, + aGYO_ANIME_PAT_TYPE_SLOW, aGYO_ANIME_PAT_TYPE_FAST, aGYO_ANIME_PAT_TYPE_SLOW, aGYO_ANIME_PAT_TYPE_SLOW, + aGYO_ANIME_PAT_TYPE_FAST, aGYO_ANIME_PAT_TYPE_SLOW, aGYO_ANIME_PAT_TYPE_SLOW, aGYO_ANIME_PAT_TYPE_SLOW, + aGYO_ANIME_PAT_TYPE_SLOW, aGYO_ANIME_PAT_TYPE_FAST, aGYO_ANIME_PAT_TYPE_FAST, aGYO_ANIME_PAT_TYPE_SLOW, + aGYO_ANIME_PAT_TYPE_FAST, aGYO_ANIME_PAT_TYPE_FAST, aGYO_ANIME_PAT_TYPE_FAST, aGYO_ANIME_PAT_TYPE_SLOW, + aGYO_ANIME_PAT_TYPE_SLOW, aGYO_ANIME_PAT_TYPE_SLOW, aGYO_ANIME_PAT_TYPE_SLOW, aGYO_ANIME_PAT_TYPE_FAST, + aGYO_ANIME_PAT_TYPE_FAST, aGYO_ANIME_PAT_TYPE_SLOW, aGYO_ANIME_PAT_TYPE_SLOW, aGYO_ANIME_PAT_TYPE_FAST, + aGYO_ANIME_PAT_TYPE_FAST, aGYO_ANIME_PAT_TYPE_FAST, aGYO_ANIME_PAT_TYPE_FAST, aGYO_ANIME_PAT_TYPE_SLOW, + aGYO_ANIME_PAT_TYPE_FAST, aGYO_ANIME_PAT_TYPE_FAST, aGYO_ANIME_PAT_TYPE_FAST, aGYO_ANIME_PAT_TYPE_SLOW, + aGYO_ANIME_PAT_TYPE_SLOW, aGYO_ANIME_PAT_TYPE_SLOW, aGYO_ANIME_PAT_TYPE_SLOW, aGYO_ANIME_PAT_TYPE_SLOW, + aGYO_ANIME_PAT_TYPE_NONE, aGYO_ANIME_PAT_TYPE_NONE, aGYO_ANIME_PAT_TYPE_NONE, aGYO_ANIME_PAT_TYPE_NONE, + aGYO_ANIME_PAT_TYPE_NONE, +}; + +static int aGYO_anime_frame(aGYO_CTRL_ACTOR* ctrl) { + static int aGYO_frame_ptn1[] = { 1, 1, 0, 0, 2, 2, 0, 0 }; + static int aGYO_frame_ptn2[] = { 1, 1, 1, 1, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0 }; + + int idx = ctrl->anim_frame; + int ret; + + idx++; + switch (aGYO_anime_ptn[ctrl->gyo_type]) { + case aGYO_ANIME_PAT_TYPE_FAST: + if (idx >= ARRAY_COUNT(aGYO_frame_ptn1)) { + idx = 0; + if ((ctrl->gyo_flags & 0x200) != 0) { + ctrl->swork2--; + } + } + + ret = aGYO_frame_ptn1[idx]; + break; + case aGYO_ANIME_PAT_TYPE_SLOW: + if (idx >= ARRAY_COUNT(aGYO_frame_ptn2)) { + idx = 0; + if ((ctrl->gyo_flags & 0x200) != 0) { + ctrl->swork2--; + } + } + + ret = aGYO_frame_ptn2[idx]; + break; + default: + idx = 0; + ret = 0; + break; + } + + ctrl->anim_frame = idx; + return ret; +} + +static void aGYO_actor_draw_fish(GRAPH* graph, aGYO_CTRL_ACTOR* ctrl, GAME* game) { + static f32 aGYO_hosei_y[] = { + 0.0f, 0.0f, 2.2f, 2.2f, 2.2f, 0.0f, 1.5f, 2.2f, 0.0f, 2.2f, 2.2f, 2.2f, 1.5f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, 2.2f, 1.5f, 2.2f, 1.5f, 0.0f, 0.0f, 2.2f, 2.2f, 0.0f, 0.0f, 0.0f, + 0.0f, 2.2f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + }; + + GAME_PLAY* play = (GAME_PLAY*)game; + int frame; + + Matrix_translate(((ACTOR*)ctrl)->world.position.x, ((ACTOR*)ctrl)->world.position.y - aGYO_hosei_y[ctrl->gyo_type], + ((ACTOR*)ctrl)->world.position.z, 0); + Matrix_mult(&play->billboard_matrix, 1); + + if (ctrl->gyo_type < (aGYO_TYPE_WHALE + 1) && (ctrl->gyo_flags & 0x200) != 0) { + int cnt; + + if (ctrl->pattern_subcounter == 0) { + cnt = 0; + } else { + cnt = --ctrl->pattern_subcounter; + } + + if (cnt != 0) { + if (aGYO_anime_ptn[ctrl->gyo_type] == aGYO_ANIME_PAT_TYPE_FAST) { + ctrl->move_counter += 0xE38; + } else { + ctrl->move_counter += 0xAAA; + } + } else { + if (ctrl->pattern_counter == 0) { + cnt = 0; + } else { + cnt = --ctrl->pattern_counter; + } + + if (cnt == 0) { + ctrl->pattern_counter = (s16)RANDOM(15); + + if (aGYO_anime_ptn[ctrl->gyo_type] == aGYO_ANIME_PAT_TYPE_FAST) { + ctrl->pattern_subcounter = 9; + } else { + ctrl->pattern_subcounter = 12; + } + + if (RANDOM_F(2.0f) < 1.0f) { + ctrl->move_counter = DEG2SHORT_ANGLE2(0.0f); + } else { + ctrl->move_counter = DEG2SHORT_ANGLE2(180.0f); + } + } + } + + ctrl->move_angle = DEG2SHORT_ANGLE2(13 * sin_s(ctrl->move_counter)); + Matrix_RotateY(ctrl->move_angle, 1); + } + + Matrix_scale(((ACTOR*)ctrl)->scale.x, ((ACTOR*)ctrl)->scale.y, ((ACTOR*)ctrl)->scale.z, 1); + + if ((ctrl->gyo_flags & 0x200) != 0 && ctrl->swork2 <= 0) { + int cnt; + + if (ctrl->swork3 == 0) { + cnt = 0; + } else { + cnt = --ctrl->swork3; + } + + if (cnt == 0) { + ctrl->swork2 = RANDOM(3) + 1; + ctrl->swork3 = RANDOM2(10) + 15; + } + + frame = 0; + } else { + frame = aGYO_anime_frame(ctrl); + } + + OPEN_POLY_OPA_DISP(graph); + + gSPMatrix(POLY_OPA_DISP++, _Matrix_to_Mtx_new(graph), G_MTX_LOAD | G_MTX_NOPUSH); + gSPDisplayList(POLY_OPA_DISP++, ((Gfx**)aGYO_displayList[ctrl->gyo_type])[(int)(frame * 0.5f)]); + + CLOSE_POLY_OPA_DISP(graph); + + { + static xyz_t offset0 = { 0.0f, 0.0f, 0.0f }; + + mAc_UnagiActorShadow((ACTOR*)ctrl, game, offset0); + } +} + +extern Gfx act_gyoei02_00_modelT[]; + +static void aGYO_actor_draw_gyoei(GRAPH* graph, aGYO_CTRL_ACTOR* ctrl, GAME* game) { + s16 angleX; + s16 angleY; + int idx0; + int idx1; + u32 t; + + angleX = ((ACTOR*)ctrl)->shape_info.rotation.x; + angleY = ((ACTOR*)ctrl)->shape_info.rotation.y + DEG2SHORT_ANGLE2(180.0f); + t = (u32)ctrl->fwork0; + idx0 = aGYO_2tile_texture_idx[t][0]; + idx1 = aGYO_2tile_texture_idx[t][1]; + + if ((ctrl->gyo_flags & 0x100) != 0) { + int alpha = (ctrl->work0 - 10) * 6; + + if (alpha <= 0) { + alpha = 0; + } + + ctrl->alpha = alpha; + } + + Matrix_translate(((ACTOR*)ctrl)->world.position.x, ((ACTOR*)ctrl)->world.position.y, + ((ACTOR*)ctrl)->world.position.z, 0); + Matrix_RotateX(angleX, 1); + Matrix_RotateY(angleY, 1); + Matrix_scale(((ACTOR*)ctrl)->scale.x * 0.4f, ((ACTOR*)ctrl)->scale.y, ((ACTOR*)ctrl)->scale.z, 1); + + OPEN_DISP(graph); + + gSPMatrix(NEXT_POLY_XLU_DISP, _Matrix_to_Mtx_new(graph), G_MTX_LOAD | G_MTX_NOPUSH); + gSPSegment(NEXT_POLY_XLU_DISP, ANIME_1_TXT_SEG, aGYO_texture_table[idx0]); + gSPSegment(NEXT_POLY_XLU_DISP, ANIME_2_TXT_SEG, aGYO_texture_table[idx1]); + gDPSetPrimColor(NEXT_POLY_XLU_DISP, 0, aGYO_prim_f[t], 0, 0, 0, ctrl->alpha); + gSPDisplayList(NEXT_POLY_XLU_DISP, act_gyoei02_00_modelT); + + CLOSE_DISP(graph); +} + +static void aGYO_actor_draw(ACTOR* actorx, GAME* game) { + GYOEI_ACTOR* gyoei = (GYOEI_ACTOR*)actorx; + aGYO_CTRL_ACTOR* ctrl = gyoei->ctrl; + GRAPH* graph = game->graph; + int i; + + Matrix_push(); + _texture_z_light_fog_prim(graph); + _texture_z_light_fog_prim_xlu(graph); + + for (i = 0; i < aGYO_MAX_GYOEI; i++) { + if (ctrl->exist == TRUE && ((ACTOR*)ctrl)->drawn && + (((ACTOR*)ctrl)->state_bitfield & (ACTOR_STATE_NO_CULL | ACTOR_STATE_NO_DRAW_WHILE_CULLED)) == + (ACTOR_STATE_NO_CULL | ACTOR_STATE_NO_DRAW_WHILE_CULLED)) { + if (ctrl->draw_type == aGYO_DRAW_TYPE_FISH) { + aGYO_actor_draw_fish(graph, ctrl, game); + } else { + aGYO_actor_draw_gyoei(graph, ctrl, game); + } + } + + ctrl++; + } + + Matrix_pull(); +} diff --git a/src/actor/ac_gyoei_move.c_inc b/src/actor/ac_gyoei_move.c_inc new file mode 100644 index 00000000..1382b825 --- /dev/null +++ b/src/actor/ac_gyoei_move.c_inc @@ -0,0 +1,104 @@ +static void aGYO_position_move(aGYO_CTRL_ACTOR* ctrl) { + static f32 dec_step[] = { + 1.0f, // aGYO_SIZE_XXS + 1.0f, // aGYO_SIZE_XS + 1.0f, // aGYO_SIZE_S + 1.0f, // aGYO_SIZE_M + 1.0f, // aGYO_SIZE_L + 1.0f, // aGYO_SIZE_XL + 1.0f, // aGYO_SIZE_XXL + 0.0f, // aGYO_SIZE_WHALE + }; + + xyz_t_move(&((ACTOR*)ctrl)->last_world_position, &((ACTOR*)ctrl)->world.position); + + if (ctrl->fwork0 <= 0.0f) { + ctrl->fwork0 += 19.0f; + } else { + ctrl->fwork0 -= dec_step[ctrl->size_type] * 0.5f; + } + + chase_f(&((ACTOR*)ctrl)->speed, ctrl->speed, ctrl->speed_step * 0.5f); + Actor_position_moveF((ACTOR*)ctrl); +} + +static void aGYO_BGcheck(aGYO_CTRL_ACTOR* ctrl) { + if ((ctrl->col_flags & 1) != 0) { + mCoBG_BgCheckControll(NULL, (ACTOR*)ctrl, ctrl->range, 0.0f, FALSE, FALSE, 1); + } +} + +static void aGYO_cull_check(ACTOR* actorx, GAME_PLAY* play) { + Skin_Matrix_PrjMulVector(&play->projection_matrix, &actorx->world.position, &actorx->camera_position, &actorx->camera_w); + if (!Actor_draw_actor_no_culling_check(actorx)) { + f32 dist; + ACTOR* playerx = GET_PLAYER_ACTOR_ACTOR(play); + + actorx->state_bitfield &= ~ACTOR_STATE_NO_CULL; + dist = search_position_distance(&actorx->world.position, &playerx->world.position); + if (dist > 600.0f && (actorx->block_x != play->block_table.block_x || actorx->block_z != play->block_table.block_z)) { + aGYO_destruct(actorx, (GAME*)play); + } + } else { + actorx->state_bitfield |= ACTOR_STATE_NO_CULL; + } +} + +static u8 bite_check(void) { + GYOEI_ACTOR* gyoei = (GYOEI_ACTOR*)aGYO_ctrlActor; + aGYO_CTRL_ACTOR* ctrl = gyoei->ctrl; + s16 i; + u8 ret = FALSE; + + for (i = 0; i < aGYO_MAX_GYOEI; i++) { + if ((ctrl->gyo_flags & 2) != 0) { + ret = TRUE; + break; + } + + ctrl++; + } + + return ret; +} + +static void aGYO_actor_move(ACTOR* actorx, GAME* game) { + GYOEI_ACTOR* gyoei = (GYOEI_ACTOR*)actorx; + aGYO_CTRL_ACTOR* ctrl = gyoei->ctrl; + GAME_PLAY* play = (GAME_PLAY*)game; + int i; + + for (i = 0; i < aGYO_MAX_GYOEI; i++) { + if (ctrl->exist == TRUE) { + ((ACTOR*)ctrl)->state_bitfield &= ~ACTOR_STATE_24; + + if ((((ACTOR*)ctrl)->state_bitfield & (ACTOR_STATE_NO_CULL | ACTOR_STATE_NO_MOVE_WHILE_CULLED)) != 0) { + aGYO_position_move(ctrl); + aGYO_BGcheck(ctrl); + + if (bite_check()) { + ctrl->gyo_flags |= 1; + } else { + ctrl->gyo_flags &= ~1; + } + + if ((ctrl->gyo_flags & 8) != 0) { + ctrl->gyo_flags &= ~8; + ctrl->gyo_flags |= 4; + aGYO_change_data_area(&play->object_exchange); + } + + (*((ACTOR*)ctrl)->mv_proc)((ACTOR*)ctrl, game); + Actor_world_to_eye((ACTOR*)ctrl, 0.0f); + } + + aGYO_cull_check((ACTOR*)ctrl, play); + if ((ctrl->gyo_flags & 0x20) != 0) { + ctrl->gyo_flags &= ~0x20; + aGYO_destruct((ACTOR*)ctrl, game); + } + } + + ctrl++; + } +}