Implement & link ac_gyo_test, ac_gyo_kaseki, link few others & fixes

This commit is contained in:
Cuyler36
2025-01-30 03:46:00 -05:00
parent 0439094cbe
commit 395bea87ab
7 changed files with 1716 additions and 6 deletions
+5 -5
View File
@@ -979,9 +979,9 @@ config.libs = [
Object(Matching, "actor/ac_goza.c"),
Object(Matching, "actor/ac_groundhog_control.c"),
Object(Matching, "actor/ac_gyo_kage.c"),
Object(NonMatching, "actor/ac_gyo_kaseki.c"),
Object(Matching, "actor/ac_gyo_kaseki.c"),
Object(Matching, "actor/ac_gyo_release.c"),
Object(NonMatching, "actor/ac_gyo_test.c"),
Object(Matching, "actor/ac_gyo_test.c"),
Object(Matching, "actor/ac_gyoei.c"),
Object(Matching, "actor/ac_handOverItem.c"),
Object(Matching, "actor/ac_haniwa.c"),
@@ -996,13 +996,13 @@ config.libs = [
Object(Matching, "actor/ac_ins_dango.c"),
Object(Matching, "actor/ac_ins_goki.c"),
Object(Matching, "actor/ac_ins_hitodama.c"),
Object(NonMatching, "actor/ac_ins_hotaru.c"),
Object(Matching, "actor/ac_ins_hotaru.c"),
Object(Matching, "actor/ac_ins_ka.c"),
Object(Matching, "actor/ac_ins_kabuto.c"),
Object(NonMatching, "actor/ac_ins_kera.c"),
Object(Matching, "actor/ac_ins_kera.c"),
Object(Matching, "actor/ac_ins_mino.c"),
Object(Matching, "actor/ac_ins_semi.c"),
Object(NonMatching, "actor/ac_ins_tentou.c"),
Object(Matching, "actor/ac_ins_tentou.c"),
Object(Matching, "actor/ac_ins_tonbo.c"),
Object(Matching, "actor/ac_insect.c"),
Object(Matching, "actor/ac_intro_demo.c"),
+2
View File
@@ -90,6 +90,8 @@ enum fish_type {
#define aGYO_TYPE_INVALID -1
#define aGYO_IS_FISH_TRASH(type) ((type) >= aGYO_TYPE_EMPTY_CAN && (type) <= aGYO_TYPE_OLD_TIRE)
enum {
aGYO_SIZE_XXS,
aGYO_SIZE_XS,
+2
View File
@@ -51,6 +51,7 @@ typedef enum audio_sound_effects {
NA_SE_LIGHT_ON,
NA_SE_LIGHT_OFF,
NA_SE_24 = 0x24,
NA_SE_25 = 0x25,
NA_SE_26 = 0x26,
NA_SE_27 = 0x27,
@@ -153,6 +154,7 @@ typedef enum audio_sound_effects {
NA_SE_114 = 0x114,
NA_SE_SEMI_ESCAPE = 0x115,
NA_SE_11A = 0x11A,
NA_SE_11B = 0x11B,
NA_SE_WEAR = 0x11C,
+2
View File
@@ -106,6 +106,8 @@ typedef u32 unknown;
#define F32_IS_ZERO(v) (fabsf(v) < 0.008f)
#define DECREMENT_TIMER(timer) ((timer) == 0 ? 0 : --(timer))
/* ARGB8 color format (32 bits) to RGB5A3 color format (16 bits) */
#define ARGB8_to_RGB5A3(argb8) \
((u16)(((argb8) & 0xFF000000) >= 0xE0000000 \
+832
View File
@@ -0,0 +1,832 @@
#include "ac_gyoei.h"
#include "m_common_data.h"
#include "m_player_lib.h"
#include "ac_uki.h"
enum {
aGKK_ACTION_SWIM,
aGKK_ACTION_SWIM2,
aGKK_ACTION_SWIM3,
aGKK_ACTION_SWIM4,
aGKK_ACTION_WAIT,
aGKK_ACTION_WAIT_MONSTER,
aGKK_ACTION_ESCAPE,
aGKK_ACTION_NEAR,
aGKK_ACTION_TOUCH,
aGKK_ACTION_BITE,
aGKK_ACTION_COMEBACK,
aGKK_ACTION_NUM
};
static void aGKK_actor_move(ACTOR* actorx, GAME* game);
static void aGKK_setupAction(aGYO_CTRL_ACTOR* gyo, int action);
static void aGKK_set_scale(ACTOR* actorx, f32 scale);
static void aGKK_speed_reset(ACTOR* actorx);
static s16 aGKK_Get_flow_angle(ACTOR* actorx);
static s16 aGKK_Get_flow_angle_rv(ACTOR* actorx);
static void aGKK_set_angle(ACTOR* actorx, s16 angleY);
static f32 aGKK_Get_water_surface_position_y(xyz_t pos);
static int aGKK_check_offing(ACTOR* actorx);
#include "../src/actor/ac_gyoei_type.c_inc"
static f32 aGKK_speed[8] = {
1.0f, 1.25f, 1.25f, 1.5f, 1.75f, 2.0f, 2.2f, 2.2f,
};
static f32 aGKK_back_speed[8] = {
-0.38f, -0.4f, -0.42f, -0.42f, -0.45f, -0.5f, -0.7f, -0.7f,
};
static s16 aGKK_touch_count[8] = {
19, 19, 19, 19, 20, 22, 24, 24,
};
static f32 aGKK_touch_distance[8] = {
12.0f, 13.0f, 15.0f, 15.0f, 20.0f, 25.0f, 30.0f, 30.0f,
};
static f32 aGYO_shadow_scale[8] = {
0.3f, 0.4f, 0.5f, 0.5f, 0.6f, 0.8f, 1.2f, 10.0f,
};
static f32 aGYO_search_area[][5] = {
{40.0f, 40.0f, 40.0f, 50.0f, 60.0f}, // regular rod
{40.0f, 40.0f, 40.0f, 50.0f, 60.0f}, // gold rod
};
static f32 aGYO_search_angle[][5] = {
{3.0f, 7.0f, 30.0f, 50.0f, 180.0f}, // regular rod
{7.5f, 15.0f, 40.0f, 60.0f, 180.0f}, // gold rod
};
static f32 aGYO_bite_time[][5] = {
{10.0f, 11.0f, 12.0f, 15.0f, 45.0f}, // regular rod
{11.0f, 12.0f, 13.0f, 18.0f, 60.0f}, // gold rod
};
extern void aGKK_actor_init(ACTOR* actorx, GAME* game) {
aGYO_CTRL_ACTOR* gyo = (aGYO_CTRL_ACTOR*)actorx;
f32 scale;
u32 attr;
int action;
attr = mCoBG_Wpos2BgAttribute_Original(actorx->world.position);
if (mCoBG_CheckWaterAttribute(attr) == TRUE) {
actorx->world.position.y = aGKK_Get_water_surface_position_y(actorx->world.position);
}
gyo->size_type = gyoei_type[gyo->gyo_type].size;
gyo->action = aGKK_ACTION_SWIM;
gyo->fwork0 = 19.0f;
scale = aGYO_shadow_scale[gyo->size_type] * 0.02f;
aGKK_set_scale(actorx, scale);
aGKK_speed_reset(actorx);
actorx->mv_proc = aGKK_actor_move;
aGKK_set_angle(actorx, aGKK_Get_flow_angle_rv(actorx));
actorx->shape_info.draw_shadow = FALSE;
if (gyo->size_type == aGYO_SIZE_WHALE) {
action = aGKK_ACTION_WAIT_MONSTER;
} else if ((mFI_BkNum2BlockKind(actorx->block_x, actorx->block_z) & mRF_BLOCKKIND_OFFING) == mRF_BLOCKKIND_OFFING) {
action = aGKK_ACTION_WAIT_MONSTER;
} else {
action = aGKK_ACTION_WAIT;
}
aGKK_setupAction(gyo, action);
}
static int aGKK_get_uki_type(void) {
int ret = aGYO_ROD_NORMAL;
if (Now_Private->equipment == ITM_GOLDEN_ROD) {
ret = aGYO_ROD_GOLDEN;
}
return ret;
}
static void aGKK_speed_reset(ACTOR* actorx) {
actorx->speed = 0.0f;
actorx->max_velocity_y = 0.0f;
}
static void aGKK_set_scale(ACTOR* actorx, f32 scale) {
actorx->scale.x = scale;
actorx->scale.y = scale;
actorx->scale.z = scale;
}
static void aGKK_set_angle(ACTOR* actorx, s16 angleY) {
actorx->world.angle.y = angleY;
actorx->shape_info.rotation.y = angleY;
}
static xyz_t aGKK_pos_calc(xyz_t pos, GAME* game, s16 angleY, f32 dist, f32 rr) {
ACTOR* playerx = GET_PLAYER_ACTOR_GAME_ACTOR(game);
xyz_t ret;
f32 sin = sin_s(playerx->world.angle.y) * dist;
f32 cos = cos_s(playerx->world.angle.y) * dist;
f32 cos2 = cos_s(angleY) * -rr;
f32 sin2 = sin_s(angleY) * rr;
ret.x = pos.x + sin + cos2;
ret.z = pos.z + cos + sin2;
return ret;
}
static void aGKK_effect_sibuki(aGYO_CTRL_ACTOR* gyo, GAME* game, s16 arg) {
xyz_t pos = gyo->tools_class.actor_class.world.position;
f32 water_y = mCoBG_GetWaterHeight_File(pos, __FILE__, 356);
s16 flow_angle;
switch (arg) {
case 4:
case 5:
case 6:
case 7:
case 8: {
static f32 rr[] = { 3.0f, 3.5f, 4.0f, 4.0f, 4.5f, 5.0f, 5.0f, 5.0f };
pos = aGKK_pos_calc(gyo->linked_actor->world.position, game, gyo->linked_actor->world.angle.y, 4.0f, rr[gyo->size_type]);
break;
}
}
pos.y = water_y;
flow_angle = aGKK_Get_flow_angle((ACTOR*)gyo);
eEC_CLIP->effect_make_proc(eEC_EFFECT_TURI_MIZU, pos, 1, flow_angle, game, EMPTY_NO, arg, 0);
}
static void aGKK_kage_make_actor(aGYO_CTRL_ACTOR* gyo, GAME* game, u8 state) {
GAME_PLAY* play = (GAME_PLAY*)game;
f32 height;
if (state == 0) {
gyo->gyo_flags |= 0x20;
}
height = aGKK_Get_water_surface_position_y(gyo->tools_class.actor_class.world.position);
Actor_info_make_actor(
// clang-format off
&play->actor_info, game, mAc_PROFILE_GYO_KAGE,
gyo->tools_class.actor_class.world.position.x, height, gyo->tools_class.actor_class.world.position.z,
0, 0, 0,
play->block_table.block_x, play->block_table.block_z,
-1, EMPTY_NO, gyo->size_type, -1, ACTOR_OBJ_BANK_KEEP
// clang-format on
);
}
static void aGKK_fish_make_actor(aGYO_CTRL_ACTOR* gyo, GAME* game) {
GAME_PLAY* play = (GAME_PLAY*)game;
// set uki actor's child actor to the fish actor being created
((UKI_ACTOR*)gyo->linked_actor)->child_actor = Actor_info_make_actor(
// clang-format off
&play->actor_info, game, mAc_PROFILE_GYO_RELEASE,
gyo->tools_class.actor_class.world.position.x, gyo->tools_class.actor_class.world.position.y, gyo->tools_class.actor_class.world.position.z,
0, gyo->swork4, 0,
play->block_table.block_x, play->block_table.block_z,
-1, EMPTY_NO, ITM_FISH_START + gyo->gyo_type, -1, ACTOR_OBJ_BANK_KEEP
// clang-format on
);
}
static void aGKK_effect_hamon(aGYO_CTRL_ACTOR* gyo, GAME* game, s16 arg) {
xyz_t pos = gyo->tools_class.actor_class.world.position;
f32 water_y = mCoBG_GetWaterHeight_File(gyo->tools_class.actor_class.world.position, __FILE__, 474);
s16 flow_angle = aGKK_Get_flow_angle((ACTOR*)gyo);
pos.y = water_y;
eEC_CLIP->effect_make_proc(eEC_EFFECT_TURI_HAMON, pos, 1, flow_angle, game, EMPTY_NO, arg, 0);
}
static int aGKK_random_check(f32 val) {
int ret = FALSE;
if (RANDOM_F(val) < 1.0f) {
ret = TRUE;
}
return ret;
}
static int aGKK_warp_event(aGYO_CTRL_ACTOR* gyo) {
int ret = FALSE;
if (mPlib_check_player_warp_forEvent()) {
((UKI_ACTOR*)gyo->linked_actor)->gyo_command = 0;
aGKK_setupAction(gyo, aGKK_ACTION_ESCAPE);
ret = TRUE;
}
return ret;
}
static f32 aGKK_speed_calc(f32 speed, s16 angle) {
return speed * sin_s(angle);
}
static void aGKK_position_calc(aGYO_CTRL_ACTOR* gyo) {
static f32 hosei[] = {
// clang-format off
-8.0f,
-10.0f,
-12.0f,
-12.0f,
-15.0f,
-20.0f,
-25.0f,
-25.0f,
// clang-format on
};
gyo->tools_class.actor_class.world.position.x += hosei[gyo->size_type] * sin_s(gyo->tools_class.actor_class.world.angle.y);
gyo->tools_class.actor_class.world.position.z += hosei[gyo->size_type] * cos_s(gyo->tools_class.actor_class.world.angle.y);
}
static int aGKK_swim_speed_check(aGYO_CTRL_ACTOR* gyo, f32 target, f32 step, f32 speed) {
int ret = chase_f(&gyo->fwork3, target, step * 0.5f);
gyo->tools_class.actor_class.speed = aGKK_speed_calc(speed, DEG2SHORT_ANGLE2(gyo->fwork3));
return ret;
}
static s16 aGKK_Get_flow_angle(ACTOR* actorx) {
xyz_t flow;
mCoBG_GetWaterFlow(&flow, actorx->bg_collision_check.result.unit_attribute);
return atans_table(flow.z, flow.x);
}
static s16 aGKK_Get_flow_angle_rv(ACTOR* actorx) {
return aGKK_Get_flow_angle(actorx) + DEG2SHORT_ANGLE2(180.0f);
}
static f32 aGKK_Get_water_surface_position_y(xyz_t pos) {
f32 ret = mCoBG_GetWaterHeight_File(pos, __FILE__, 643);
return ret - 8.0f;
}
static int aGKK_search_Uki(aGYO_CTRL_ACTOR* gyo, GAME* game) {
GAME_PLAY* play;
f32 target_dist;
f32 target_y;
f32 escape_dist;
s16 target_angle;
s16 goal_angle;
s16 search_area;
int ret;
play = (GAME_PLAY*)game;
search_area = gyoei_type[gyo->gyo_type].search_area;
ret = FALSE;
{
UKI_ACTOR* uki = (UKI_ACTOR*)Actor_info_name_search(&play->actor_info, mAc_PROFILE_UKI, ACTOR_PART_BG);
gyo->linked_actor = (ACTOR*)uki;
if (uki != NULL) {
target_dist = search_position_distance(&gyo->tools_class.actor_class.world.position, &uki->actor_class.world.position);
target_y = gyo->tools_class.actor_class.world.position.y - uki->actor_class.world.position.y;
target_angle = search_position_angleY(&gyo->tools_class.actor_class.world.position, &uki->actor_class.world.position);
goal_angle = target_angle - gyo->tools_class.actor_class.shape_info.rotation.y;
if (gyo->size_type == aGYO_SIZE_XXS || gyo->size_type == aGYO_SIZE_XS) {
escape_dist = 17.0f;
} else {
escape_dist = 22.0f;
}
if (uki->hit_water_flag && target_dist < escape_dist) {
aGKK_set_angle(((ACTOR*)gyo), target_angle + DEG2SHORT_ANGLE2(180.0f));
aGKK_setupAction(gyo, aGKK_ACTION_ESCAPE);
} else {
int rod_type = aGKK_get_uki_type();
if ((gyo->gyo_flags & 1) == 0 && uki->cast_timer == 0 &&
target_dist < aGYO_search_area[rod_type][search_area] && fabsf(target_y) < 10.0f &&
goal_angle > DEG2SHORT_ANGLE2(-aGYO_search_angle[rod_type][search_area]) &&
goal_angle < DEG2SHORT_ANGLE2(aGYO_search_angle[rod_type][search_area])) {
ret = TRUE;
}
}
}
}
return ret;
}
static int aGKK_player_near(aGYO_CTRL_ACTOR* gyo, GAME* game) {
ACTOR* playerx = GET_PLAYER_ACTOR_GAME_ACTOR(game);
f32 dist;
s16 target_angle;
xyz_t pos;
int ret = FALSE;
dist = search_position_distance(&gyo->tools_class.actor_class.world.position, &playerx->world.position);
target_angle = search_position_angleY(&gyo->tools_class.actor_class.world.position, &playerx->world.position);
if (
// clang-format off
((dist < 110.0f && mPlib_get_player_actor_main_index(game) == mPlayer_INDEX_DASH) ||
(dist < 150.0f && (
mPlib_Check_HitAxe(&pos) ||
mPlib_Check_StopNet(&pos) ||
mPlib_Check_HitScoop(&pos)
))) ||
gyo->escape_flag
// clang-format on
) {
aGKK_set_angle((ACTOR*)gyo, target_angle + DEG2SHORT_ANGLE2(180.0f));
switch (gyo->size_type) {
case aGYO_SIZE_XXS:
case aGYO_SIZE_XS:
case aGYO_SIZE_S:
case aGYO_SIZE_M:
aGKK_effect_hamon(gyo, game, 3);
break;
case aGYO_SIZE_L:
case aGYO_SIZE_XL:
case aGYO_SIZE_XXL:
aGKK_effect_hamon(gyo, game, 2);
break;
}
aGKK_kage_make_actor(gyo, game, 0);
ret = TRUE;
}
return ret;
}
static int aGKK_check_offing(ACTOR* actorx) {
static f32 chkX[] = { 0.0f, 0.0f, -mFI_UT_WORLDSIZE_X_F * 2, mFI_UT_WORLDSIZE_X_F * 2 };
static f32 chkZ[] = { -mFI_UT_WORLDSIZE_Z_F * 2, mFI_UT_WORLDSIZE_Z_F * 2, 0.0f, 0.0f };
int ret = FALSE;
u32 blockkind = mFI_BkNum2BlockKind(actorx->block_x, actorx->block_z);
if ((blockkind & mRF_BLOCKKIND_MARINE) == mRF_BLOCKKIND_MARINE && (blockkind & mRF_BLOCKKIND_OFFING) != mRF_BLOCKKIND_OFFING) {
int i;
for (i = 0; i < 4; i++) {
xyz_t pos = actorx->world.position;
pos.x += chkX[i];
pos.z += chkZ[i];
if (mCoBG_CheckWaterAttribute(mCoBG_Wpos2Attribute(pos, NULL)) == FALSE) {
ret = TRUE;
break;
}
}
}
return ret;
}
static int aGKK_check_wall(ACTOR* actorx) {
aGYO_CTRL_ACTOR* gyo = (aGYO_CTRL_ACTOR*)actorx;
int ret = FALSE;
if (actorx->bg_collision_check.result.hit_wall != mCoBG_DIDNT_HIT_WALL) {
int count = actorx->bg_collision_check.result.hit_wall_count;
if (count != 0) {
int i;
for (i = 0; i < count; i++) {
if (actorx->bg_collision_check.wall_info[i].type == mCoBG_WALL_TYPE0) {
s16 wall_angle = actorx->bg_collision_check.wall_info[i].angleY;
aGKK_set_angle(actorx, wall_angle);
gyo->gyo_flags |= 0x40;
ret = TRUE;
break;
}
}
}
}
if (ret == FALSE) {
xyz_t pos;
u32 attr;
f32 ground_y;
f32 water_y;
f32 diff_y;
pos = actorx->world.position;
pos.z -= 10.0f;
attr = mCoBG_Wpos2Attribute(pos, NULL);
ground_y = mCoBG_GetBgY_AngleS_FromWpos(NULL, pos, 0.0f);
water_y = mCoBG_GetWaterHeight_File(pos, __FILE__, 870);
diff_y = water_y - ground_y;
if (mCoBG_CheckSandUt_ForFish(&pos) == TRUE || diff_y < 20.0f) {
actorx->world.position = actorx->last_world_position;
aGKK_set_angle(actorx, 0);
gyo->gyo_flags |= 0x40;
ret = TRUE;
} else if (aGKK_check_offing(actorx) == FALSE) {
actorx->world.position = actorx->last_world_position;
aGKK_set_angle(actorx, DEG2SHORT_ANGLE2(180.0f));
gyo->gyo_flags |= 0x40;
ret = TRUE;
}
}
return ret;
}
static int aGKK_check_uki(aGYO_CTRL_ACTOR* gyo, GAME* game) {
int ret = FALSE;
if (aGKK_player_near(gyo, game) == FALSE && aGKK_search_Uki(gyo, game) == TRUE) {
aGKK_setupAction(gyo, aGKK_ACTION_NEAR);
ret = TRUE;
}
return ret;
}
static void aGKK_swim(ACTOR* actorx, GAME* game) {
aGYO_CTRL_ACTOR* gyo = (aGYO_CTRL_ACTOR*)actorx;
if (aGKK_check_wall(actorx) == TRUE) {
aGKK_setupAction(gyo, aGKK_ACTION_ESCAPE);
} else if (aGKK_swim_speed_check(gyo, 360.0f, 5.0f, 0.5f) == TRUE) {
aGKK_setupAction(gyo, aGKK_ACTION_WAIT);
} else {
aGKK_check_uki(gyo, game);
}
}
static void aGKK_swim2(ACTOR* actorx, GAME* game) {
aGYO_CTRL_ACTOR* gyo = (aGYO_CTRL_ACTOR*)actorx;
if (aGKK_check_wall(actorx) == TRUE) {
aGKK_setupAction(gyo, aGKK_ACTION_ESCAPE);
} else if (aGKK_swim_speed_check(gyo, 180.0f, 5.0f, 0.5f) == TRUE) {
actorx->world.angle.y = actorx->shape_info.rotation.y;
aGKK_setupAction(gyo, aGKK_ACTION_WAIT);
} else {
aGKK_check_uki(gyo, game);
}
}
static void aGKK_swim3(ACTOR* actorx, GAME* game) {
aGYO_CTRL_ACTOR* gyo = (aGYO_CTRL_ACTOR*)actorx;
if (aGKK_check_wall(actorx) == TRUE) {
aGKK_setupAction(gyo, aGKK_ACTION_ESCAPE);
} else if (chase_angle(&actorx->world.angle.y, gyo->swork3, 0x400) == TRUE) {
actorx->shape_info.rotation.y = actorx->world.angle.y;
aGKK_setupAction(gyo, aGKK_ACTION_SWIM4);
} else {
actorx->shape_info.rotation.y = actorx->world.angle.y;
aGKK_check_uki(gyo, game);
}
}
static void aGKK_swim4(ACTOR* actorx, GAME* game) {
aGYO_CTRL_ACTOR* gyo = (aGYO_CTRL_ACTOR*)actorx;
if (aGKK_check_wall(actorx) == TRUE) {
aGKK_setupAction(gyo, aGKK_ACTION_ESCAPE);
} else {
actorx->shape_info.rotation.y += gyo->swork2;
if (aGKK_swim_speed_check(gyo, 180.0f, 5.0f, 1.0f) == TRUE) {
actorx->world.angle.y = actorx->shape_info.rotation.y;
aGKK_setupAction(gyo, aGKK_ACTION_WAIT);
} else {
aGKK_check_uki(gyo, game);
}
}
}
static void aGKK_wait(ACTOR* actorx, GAME* game) {
static int swim_action[] = { aGKK_ACTION_SWIM, aGKK_ACTION_SWIM2, aGKK_ACTION_SWIM };
aGYO_CTRL_ACTOR* gyo = (aGYO_CTRL_ACTOR*)actorx;
if (DECREMENT_TIMER(gyo->work0) == 0) {
aGKK_speed_reset(actorx);
aGKK_setupAction(gyo, swim_action[RANDOM(ARRAY_COUNT(swim_action))]);
} else if (aGKK_check_wall(actorx) == TRUE) {
aGKK_setupAction(gyo, aGKK_ACTION_ESCAPE);
} else {
aGKK_check_uki((aGYO_CTRL_ACTOR*)actorx, game);
}
}
static void aGKK_near(ACTOR* actorx, GAME* game) {
aGYO_CTRL_ACTOR* gyo = (aGYO_CTRL_ACTOR*)actorx;
f32 target_dist;
f32 target_y;
s16 angle_y;
UKI_ACTOR* uki = (UKI_ACTOR*)gyo->linked_actor;
s16 search_area = gyoei_type[gyo->gyo_type].search_area;
int rod_type = aGKK_get_uki_type();
angle_y = search_position_angleY(&actorx->world.position, &uki->actor_class.world.position);
aGKK_set_angle(actorx, angle_y);
target_dist = search_position_distance(&actorx->world.position, &uki->actor_class.world.position);
target_y = actorx->world.position.y - uki->actor_class.world.position.y;
if (target_dist > aGYO_search_area[rod_type][search_area] || fabsf(target_y) > 10.0f) {
aGKK_setupAction(gyo, aGKK_ACTION_WAIT);
} else if (target_dist < aGKK_touch_distance[gyo->size_type]) {
if (uki->gyo_status == 1) {
uki->gyo_command = 1;
uki->gyo_type = gyo->gyo_type;
uki->child_actor = actorx;
uki->actor_class.world.angle.y = actorx->world.angle.y;
uki->actor_class.shape_info.rotation.y = actorx->shape_info.rotation.y;
aGKK_setupAction(gyo, aGKK_ACTION_TOUCH);
} else {
aGKK_setupAction(gyo, aGKK_ACTION_WAIT);
}
}
}
static void aGKK_touch(ACTOR* actorx, GAME* game) {
aGYO_CTRL_ACTOR* gyo = (aGYO_CTRL_ACTOR*)actorx;
UKI_ACTOR* uki;
if (aGKK_warp_event(gyo)) {
return;
}
uki = (UKI_ACTOR*)gyo->linked_actor;
uki->actor_class.world.angle.y = actorx->world.angle.y;
uki->actor_class.shape_info.rotation.y = actorx->shape_info.rotation.y;
if (DECREMENT_TIMER(gyo->work0) == 0) {
f32 target_dist;
s16 angle;
actorx->speed = aGKK_speed[gyo->size_type];
angle = search_position_angleY(&actorx->world.position, &uki->actor_class.world.position);
aGKK_set_angle(actorx, angle);
target_dist = search_position_distance(&actorx->world.position, &uki->actor_class.world.position);
if (target_dist < aGKK_touch_distance[gyo->size_type]) {
if ((aGKK_random_check(4.0f) == TRUE) || DECREMENT_TIMER(gyo->touch_counter) == 0) {
if (uki->gyo_status == 2) {
uki->gyo_command = 2;
// If a free space exists, 1/20 chance of switching the fish out for trash
if (mPlib_Get_space_putin_item() >= 0 && aGKK_random_check(20.0f) == TRUE) {
static int gomi[] = { aGYO_TYPE_EMPTY_CAN, aGYO_TYPE_EMPTY_CAN, aGYO_TYPE_BOOT, aGYO_TYPE_BOOT, aGYO_TYPE_BOOT, aGYO_TYPE_OLD_TIRE, aGYO_TYPE_OLD_TIRE, aGYO_TYPE_OLD_TIRE };
gyo->gyo_type = gomi[gyo->size_type];
uki->gyo_type = gyo->gyo_type;
}
aGKK_setupAction(gyo, aGKK_ACTION_BITE);
}
} else {
uki->touched_flag = TRUE;
gyo->work0 = (int)((aGKK_touch_count[gyo->size_type] + RANDOM2_F(30.0f)) * 2.0f);
actorx->speed = aGKK_back_speed[gyo->size_type] + RANDOM2_F(0.2f);
}
}
}
if (uki->status == 6) {
uki->gyo_command = 0;
aGKK_effect_sibuki(gyo, game, 0);
aGKK_kage_make_actor(gyo, game, 0);
}
}
static void aGKK_bite(ACTOR* actorx, GAME* game) {
static s16 eff_arg[] = { 8, 7, 4, 4, 5, 6, 6, 6 };
aGYO_CTRL_ACTOR* gyo = (aGYO_CTRL_ACTOR*)actorx;
UKI_ACTOR* uki;
if (aGKK_warp_event(gyo)) {
return;
}
uki = (UKI_ACTOR*)gyo->linked_actor;
if (uki->gyo_status == 4) {
static f32 rr[] = { 6.0f, 7.0f, 8.0f, 8.0f, 9.0f, 10.0f, 15.0f, 15.0f };
xyz_t pos;
pos = aGKK_pos_calc(uki->actor_class.world.position, game, uki->actor_class.world.angle.y, 8.0f, rr[gyo->size_type]);
actorx->world.position.x = pos.x;
actorx->world.position.z = pos.z;
aGKK_set_angle(actorx, uki->actor_class.world.angle.y);
sAdo_OngenPos((u32)actorx, NA_SE_24, &actorx->world.position);
CLIP(gyo_clip)->hitcheck_gyoei_proc(&actorx->world.position, gyo->size_type);
if (DECREMENT_TIMER(gyo->swork0) == 0) {
if (aGKK_random_check(2.0f) == TRUE) {
aGKK_effect_sibuki(gyo, game, eff_arg[gyo->size_type]);
}
gyo->swork0 = 6;
}
} else {
actorx->world.position.x = uki->actor_class.world.position.x;
actorx->world.position.z = uki->actor_class.world.position.z;
aGKK_set_angle(actorx, uki->actor_class.world.angle.y);
aGKK_position_calc(gyo);
if (uki->gyo_status == 5) {
actorx->speed = 0.0f;
aGKK_setupAction(gyo, aGKK_ACTION_COMEBACK);
} else if (DECREMENT_TIMER(gyo->work0) == 0) {
uki->gyo_command = 0;
aGKK_kage_make_actor(gyo, game, 0);
}
}
uki->gyo_pos = actorx->world.position;
}
static void aGKK_comeback(ACTOR* actorx, GAME* game) {
aGYO_CTRL_ACTOR* gyo = (aGYO_CTRL_ACTOR*)actorx;
f32 scale;
UKI_ACTOR* uki = (UKI_ACTOR*)gyo->linked_actor;
actorx->world.position = uki->uki_pos;
aGKK_set_angle(actorx, uki->actor_class.world.angle.y);
if (uki->gyo_status == 3) {
aGKK_position_calc(gyo);
if (aGKK_random_check(10.0f) == TRUE) {
aGKK_effect_hamon(gyo, game, 0);
}
} else if (uki->gyo_status == 5) {
ACTOR* playerx = GET_PLAYER_ACTOR_GAME_ACTOR(game);
if ((gyo->gyo_flags & 4) == 0) {
if (gyo->gyo_type == aGYO_TYPE_OLD_TIRE) {
aGKK_kage_make_actor(gyo, game, 1);
}
gyo->swork4 = playerx->world.angle.y;
gyo->gyo_flags |= 8;
}
} else if (uki->gyo_status == 6) {
gyo->gyo_flags |= 0x200;
if (gyo->anim_frame == 1) {
sAdo_OngenTrgStart(NA_SE_11A, &actorx->world.position);
}
} else if (uki->gyo_status == 8) {
uki->gyo_status = 0;
aGKK_fish_make_actor(gyo, game);
gyo->gyo_flags |= 0x20;
} else if (uki->gyo_status == 7) {
gyo->gyo_flags |= 0x10;
} else if (uki->gyo_status == 0) {
uki->gyo_command = 0;
uki->child_actor = NULL;
gyo->gyo_flags &= ~2;
gyo->gyo_flags |= 0x20;
return;
}
if ((gyo->gyo_flags & 0x10) != 0) {
scale = uki->gyo_scale / 100.0f;
} else if (gyo->draw_type == aGYO_DRAW_TYPE_FISH) {
scale = 0.01f;
} else {
scale = aGYO_shadow_scale[gyo->size_type] * 0.02f;
}
aGKK_set_scale(actorx, scale);
uki->gyo_pos = actorx->world.position;
}
static void aGKK_escape(ACTOR* actorx, GAME* game) {
aGYO_CTRL_ACTOR* gyo = (aGYO_CTRL_ACTOR*)actorx;
if (aGKK_check_uki(gyo, game) == FALSE && ((gyo->gyo_flags & 0x40) != 0 || aGKK_check_wall(actorx) == FALSE)) {
if (DECREMENT_TIMER(gyo->work0) == 0) {
gyo->gyo_flags &= ~0x40;
aGKK_setupAction(gyo, aGKK_ACTION_WAIT);
} else {
chase_f(&actorx->speed, 0.0f, 0.01f);
}
}
}
static void aGKK_swim_init(aGYO_CTRL_ACTOR* gyo) {
gyo->fwork3 = 50.0f;
}
static void aGKK_swim2_init(aGYO_CTRL_ACTOR* gyo) {
gyo->fwork3 = 0.0f;
gyo->tools_class.actor_class.world.angle.y += (int)RANDOM2_F(DEG2SHORT_ANGLE2(180.0f));
}
static void aGKK_swim3_init(aGYO_CTRL_ACTOR* gyo) {
gyo->swork3 = gyo->tools_class.actor_class.world.angle.y + (int)RANDOM2_F(DEG2SHORT_ANGLE2(90.0f));
gyo->tools_class.actor_class.shape_info.rotation.y = gyo->tools_class.actor_class.world.angle.y;
}
static void aGKK_swim4_init(aGYO_CTRL_ACTOR* gyo) {
s16 angle;
gyo->fwork3 = 5.0f;
if (gyo->tools_class.actor_class.shape_info.rotation.y > 0) {
angle = DEG2SHORT_ANGLE2(90.0f);
} else {
angle = DEG2SHORT_ANGLE2(-90.0f);
}
angle -= gyo->tools_class.actor_class.world.angle.y;
gyo->swork2 = angle / 36;
}
static void aGKK_near_init(aGYO_CTRL_ACTOR* gyo) {
gyo->gyo_flags |= 2;
((ACTOR*)gyo)->speed = aGKK_speed[gyo->size_type];
((ACTOR*)gyo)->max_velocity_y = 12.0f;
}
static void aGKK_touch_init(aGYO_CTRL_ACTOR* gyo) {
gyo->work0 = 0;
gyo->range = 12.0f;
gyo->touch_counter = 5;
aGKK_speed_reset((ACTOR*)gyo);
}
static void aGKK_bite_init(aGYO_CTRL_ACTOR* gyo) {
gyo->work0 = (int)(aGYO_bite_time[aGKK_get_uki_type()][gyoei_type[gyo->gyo_type].bite_time] * 2.0f);
gyo->swork0 = 6;
aGKK_speed_reset((ACTOR*)gyo);
}
static void aGKK_comeback_init(aGYO_CTRL_ACTOR* gyo) {
gyo->swork2 = 1 + RANDOM(3);
gyo->swork3 = 15 + RANDOM2(10);
aGKK_speed_reset((ACTOR*)gyo);
}
static void aGKK_wait_init(aGYO_CTRL_ACTOR* gyo) {
gyo->gyo_flags &= ~2;
gyo->work0 = (int)((100.0f + RANDOM_F(30.0f)) * 2.0f);
((ACTOR*)gyo)->speed = -0.15f + RANDOM2_F(0.2f);
((ACTOR*)gyo)->max_velocity_y = 0.0f;
}
static void aGKK_wait_monster_init(aGYO_CTRL_ACTOR* gyo) {
((ACTOR*)gyo)->speed = 0.0f;
((ACTOR*)gyo)->max_velocity_y = 0.0f;
}
static void aGKK_escape_init(aGYO_CTRL_ACTOR* gyo) {
gyo->swork0 = 0;
gyo->work0 = 100;
((ACTOR*)gyo)->speed = 1.0f;
}
typedef void (*aGKK_INIT_PROC)(aGYO_CTRL_ACTOR* gyo);
static void aGKK_setupAction(aGYO_CTRL_ACTOR* gyo, int action) {
static aGKK_INIT_PROC init_proc[] = {
aGKK_swim_init,
aGKK_swim2_init,
aGKK_swim3_init,
aGKK_swim4_init,
aGKK_wait_init,
aGKK_wait_monster_init,
aGKK_escape_init,
aGKK_near_init,
aGKK_touch_init,
aGKK_bite_init,
aGKK_comeback_init,
};
static aGYO_ACT_PROC act_proc[] = {
aGKK_swim,
aGKK_swim2,
aGKK_swim3,
aGKK_swim4,
aGKK_wait,
(aGYO_ACT_PROC)none_proc1,
aGKK_escape,
aGKK_near,
aGKK_touch,
aGKK_bite,
aGKK_comeback,
};
gyo->action = action;
gyo->act_proc = act_proc[action];
init_proc[action](gyo);
}
static void aGKK_actor_move(ACTOR* actorx, GAME* game) {
aGYO_CTRL_ACTOR* gyo = (aGYO_CTRL_ACTOR*)actorx;
actorx->world.position.y = aGKK_Get_water_surface_position_y(actorx->world.position);
(*gyo->act_proc)(actorx, game);
}
+872
View File
@@ -0,0 +1,872 @@
#include "ac_gyoei.h"
#include "m_common_data.h"
#include "m_player_lib.h"
#include "ac_uki.h"
enum {
aGTT_ACTION_SWIM,
aGTT_ACTION_WAIT,
aGTT_ACTION_ESCAPE,
aGTT_ACTION_NEAR,
aGTT_ACTION_TOUCH,
aGTT_ACTION_BITE,
aGTT_ACTION_COMEBACK,
aGTT_ACTION_NUM
};
static void aGTT_actor_move(ACTOR* actorx, GAME* game);
static void aGTT_setupAction(aGYO_CTRL_ACTOR* gyo, int action);
static void aGTT_set_scale(ACTOR* actorx, f32 scale);
static void aGTT_speed_reset(ACTOR* actorx);
static s16 aGTT_Get_flow_angle(ACTOR* actorx);
static s16 aGTT_Get_flow_angle_rv(ACTOR* actorx);
static void aGTT_set_angle(ACTOR* actorx, s16 angleY);
static f32 aGTT_Get_water_surface_position_y(xyz_t pos);
#include "../src/actor/ac_gyoei_type.c_inc"
static f32 aGTT_speed[8] = {
1.0f, 1.25f, 1.25f, 1.5f, 1.75f, 2.0f, 2.2f, 2.2f,
};
static f32 aGTT_back_speed[8] = {
-0.38f, -0.4f, -0.42f, -0.42f, -0.45f, -0.5f, -0.7f, -0.7f,
};
static s16 aGTT_touch_count[8] = {
19, 19, 19, 19, 20, 22, 24, 24,
};
static f32 aGTT_touch_distance[8] = {
12.0f, 13.0f, 15.0f, 15.0f, 20.0f, 25.0f, 30.0f, 30.0f,
};
static f32 aGYO_shadow_scale[8] = {
0.3f, 0.4f, 0.5f, 0.5f, 0.6f, 0.8f, 1.2f, 10.0f,
};
static f32 aGYO_search_area[][5] = {
{40.0f, 40.0f, 40.0f, 50.0f, 60.0f}, // regular rod
{40.0f, 40.0f, 40.0f, 50.0f, 60.0f}, // gold rod
};
static f32 aGYO_search_angle[][5] = {
{3.0f, 7.0f, 30.0f, 50.0f, 180.0f}, // regular rod
{7.5f, 15.0f, 40.0f, 60.0f, 180.0f}, // gold rod
};
static f32 aGYO_bite_time[][5] = {
{10.0f, 11.0f, 12.0f, 15.0f, 45.0f}, // regular rod
{11.0f, 12.0f, 13.0f, 18.0f, 60.0f}, // gold rod
};
extern void aGTT_actor_init(ACTOR* actorx, GAME* game) {
aGYO_CTRL_ACTOR* gyo = (aGYO_CTRL_ACTOR*)actorx;
f32 scale;
u32 attr;
attr = mCoBG_Wpos2BgAttribute_Original(actorx->world.position);
if (mCoBG_CheckWaterAttribute(attr) == TRUE) {
actorx->world.position.y = aGTT_Get_water_surface_position_y(actorx->world.position);
}
gyo->size_type = gyoei_type[gyo->gyo_type].size;
gyo->action = aGTT_ACTION_SWIM;
gyo->fwork0 = 19.0f;
scale = aGYO_shadow_scale[gyo->size_type] * 0.02f;
aGTT_set_scale(actorx, scale);
aGTT_speed_reset(actorx);
actorx->mv_proc = aGTT_actor_move;
aGTT_set_angle(actorx, aGTT_Get_flow_angle_rv(actorx));
actorx->shape_info.draw_shadow = FALSE;
aGTT_setupAction(gyo, aGTT_ACTION_WAIT);
}
static int aGYO_get_uki_type(void) {
int ret = aGYO_ROD_NORMAL;
if (Now_Private->equipment == ITM_GOLDEN_ROD) {
ret = aGYO_ROD_GOLDEN;
}
return ret;
}
static void aGTT_speed_reset(ACTOR* actorx) {
actorx->speed = 0.0f;
actorx->max_velocity_y = 0.0f;
}
static void aGTT_set_scale(ACTOR* actorx, f32 scale) {
actorx->scale.x = scale;
actorx->scale.y = scale;
actorx->scale.z = scale;
}
static void aGTT_set_angle(ACTOR* actorx, s16 angleY) {
actorx->world.angle.y = angleY;
actorx->shape_info.rotation.y = angleY;
}
static xyz_t aGTT_pos_calc(xyz_t pos, GAME* game, s16 angleY, f32 dist, f32 rr) {
ACTOR* playerx = GET_PLAYER_ACTOR_GAME_ACTOR(game);
xyz_t ret;
f32 sin = sin_s(playerx->world.angle.y) * dist;
f32 cos = cos_s(playerx->world.angle.y) * dist;
f32 cos2 = cos_s(angleY) * -rr;
f32 sin2 = sin_s(angleY) * rr;
ret.x = pos.x + sin + cos2;
ret.z = pos.z + cos + sin2;
return ret;
}
static void aGTT_effect_sibuki(aGYO_CTRL_ACTOR* gyo, GAME* game, s16 arg) {
xyz_t pos = gyo->tools_class.actor_class.world.position;
f32 water_y = mCoBG_GetWaterHeight_File(pos, __FILE__, 334);
s16 flow_angle;
switch (arg) {
case 4:
case 5:
case 6:
case 7:
case 8: {
static f32 rr[] = { 3.0f, 3.5f, 4.0f, 4.0f, 4.5f, 5.0f, 5.0f, 5.0f };
pos = aGTT_pos_calc(gyo->linked_actor->world.position, game, gyo->linked_actor->world.angle.y, 4.0f, rr[gyo->size_type]);
break;
}
}
pos.y = water_y;
flow_angle = aGTT_Get_flow_angle((ACTOR*)gyo);
eEC_CLIP->effect_make_proc(eEC_EFFECT_TURI_MIZU, pos, 1, flow_angle, game, EMPTY_NO, arg, 0);
}
static void aGTT_kage_make_actor(aGYO_CTRL_ACTOR* gyo, GAME* game, u8 state) {
GAME_PLAY* play = (GAME_PLAY*)game;
f32 height;
if (state == 0) {
gyo->gyo_flags |= 0x20;
}
height = aGTT_Get_water_surface_position_y(gyo->tools_class.actor_class.world.position);
Actor_info_make_actor(
// clang-format off
&play->actor_info, game, mAc_PROFILE_GYO_KAGE,
gyo->tools_class.actor_class.world.position.x, height, gyo->tools_class.actor_class.world.position.z,
0, 0, 0,
play->block_table.block_x, play->block_table.block_z,
-1, EMPTY_NO, gyo->size_type, -1, ACTOR_OBJ_BANK_KEEP
// clang-format on
);
}
static void aGTT_fish_make_actor(aGYO_CTRL_ACTOR* gyo, GAME* game) {
GAME_PLAY* play = (GAME_PLAY*)game;
// set uki actor's child actor to the fish actor being created
((UKI_ACTOR*)gyo->linked_actor)->child_actor = Actor_info_make_actor(
// clang-format off
&play->actor_info, game, mAc_PROFILE_GYO_RELEASE,
gyo->tools_class.actor_class.world.position.x, gyo->tools_class.actor_class.world.position.y, gyo->tools_class.actor_class.world.position.z,
0, gyo->swork4, 0,
play->block_table.block_x, play->block_table.block_z,
-1, EMPTY_NO, ITM_FISH_START + gyo->gyo_type, -1, ACTOR_OBJ_BANK_KEEP
// clang-format on
);
}
static void aGTT_effect_hamon(aGYO_CTRL_ACTOR* gyo, GAME* game, s16 arg) {
xyz_t pos = gyo->tools_class.actor_class.world.position;
f32 water_y = mCoBG_GetWaterHeight_File(gyo->tools_class.actor_class.world.position, __FILE__, 451);
s16 flow_angle = aGTT_Get_flow_angle((ACTOR*)gyo);
pos.y = water_y;
eEC_CLIP->effect_make_proc(eEC_EFFECT_TURI_HAMON, pos, 1, flow_angle, game, EMPTY_NO, arg, 0);
}
static u8 aGTT_random_check(f32 val) {
u8 ret = FALSE;
if (RANDOM_F(val) < 1.0f) {
ret = TRUE;
}
return ret;
}
static int aGTT_chase_s_angle(aGYO_CTRL_ACTOR* gyo, s16 target, s16 step) {
s16 angle;
chase_angle(&gyo->tools_class.actor_class.world.angle.y, target, step);
gyo->tools_class.actor_class.shape_info.rotation.y = gyo->tools_class.actor_class.world.angle.y;
angle = ABS((s16)(gyo->tools_class.actor_class.world.angle.y - target));
if (angle < step) {
gyo->gyo_flags &= ~0x80;
}
return angle;
}
static int aGTT_warp_event(aGYO_CTRL_ACTOR* gyo) {
int ret = FALSE;
if (mPlib_check_player_warp_forEvent()) {
((UKI_ACTOR*)gyo->linked_actor)->gyo_command = 0;
aGTT_setupAction(gyo, aGTT_ACTION_ESCAPE);
ret = TRUE;
}
return ret;
}
static f32 aGTT_speed_calc(f32 speed, s16 angle) {
return speed * sin_s(angle);
}
static void aGTT_position_calc(aGYO_CTRL_ACTOR* gyo) {
static f32 hosei[] = {
// clang-format off
-8.0f,
-10.0f,
-12.0f,
-12.0f,
-15.0f,
-20.0f,
-25.0f,
-25.0f,
// clang-format on
};
gyo->tools_class.actor_class.world.position.x += hosei[gyo->size_type] * sin_s(gyo->tools_class.actor_class.world.angle.y);
gyo->tools_class.actor_class.world.position.z += hosei[gyo->size_type] * cos_s(gyo->tools_class.actor_class.world.angle.y);
}
static int aGTT_swim_speed_check(aGYO_CTRL_ACTOR* gyo, f32 target, f32 step, f32 speed) {
int ret = chase_f(&gyo->fwork3, target, step * 0.5f);
gyo->tools_class.actor_class.speed = aGTT_speed_calc(speed, DEG2SHORT_ANGLE2(gyo->fwork3));
return ret;
}
static int aGTT_swim_speed_change(aGYO_CTRL_ACTOR* gyo, f32 target, f32 step, f32 speed) {
int ret = chase_f(&gyo->fwork3, target, step * 0.5f);
s16 angle = DEG2SHORT_ANGLE2(gyo->fwork3);
if (gyo->fwork3 > step) {
gyo->tools_class.actor_class.shape_info.rotation.y += gyo->swork2;
} else if (gyo->fwork3 == step) {
gyo->swork2 = (s16)(gyo->swork2 - gyo->tools_class.actor_class.world.angle.y) / (s16)(target / step);
}
gyo->tools_class.actor_class.speed = aGTT_speed_calc(speed, angle);
if (ret == TRUE) {
gyo->tools_class.actor_class.world.angle.y = gyo->tools_class.actor_class.shape_info.rotation.y;
}
return ret;
}
static s16 aGTT_Get_flow_angle(ACTOR* actorx) {
xyz_t flow;
mCoBG_GetWaterFlow(&flow, actorx->bg_collision_check.result.unit_attribute);
return atans_table(flow.z, flow.x);
}
static s16 aGTT_Get_flow_angle_rv(ACTOR* actorx) {
return aGTT_Get_flow_angle(actorx) + DEG2SHORT_ANGLE2(180.0f);
}
static void aGTT_flow_direction(ACTOR* actorx) {
static s16 angl_add_table[] = { 0x100, 0x400 };
s16 flow_rv = aGTT_Get_flow_angle_rv(actorx);
chase_angle(&actorx->world.angle.y, flow_rv, angl_add_table[ABS((s16)(actorx->world.angle.y - flow_rv)) > 0x4000]);
actorx->shape_info.rotation.y = actorx->world.angle.y;
}
static f32 aGTT_Get_water_surface_position_y(xyz_t pos) {
f32 ret = mCoBG_GetWaterHeight_File(pos, __FILE__, 699);
return ret - 8.0f;
}
static int aGTT_search_Uki(ACTOR* actorx, GAME* game) {
aGYO_CTRL_ACTOR* gyo = (aGYO_CTRL_ACTOR*)actorx;
GAME_PLAY* play;
f32 target_dist;
f32 target_y;
f32 escape_dist;
s16 target_angle;
s16 goal_angle;
s16 search_area;
int ret;
play = (GAME_PLAY*)game;
search_area = gyoei_type[gyo->gyo_type].search_area;
ret = FALSE;
{
UKI_ACTOR* uki = (UKI_ACTOR*)Actor_info_name_search(&play->actor_info, mAc_PROFILE_UKI, ACTOR_PART_BG);
gyo->linked_actor = (ACTOR*)uki;
if (uki != NULL) {
target_dist = search_position_distance(&actorx->world.position, &uki->actor_class.world.position);
target_y = actorx->world.position.y - uki->actor_class.world.position.y;
target_angle = search_position_angleY(&actorx->world.position, &uki->actor_class.world.position);
goal_angle = target_angle - actorx->shape_info.rotation.y;
if (gyo->size_type == aGYO_SIZE_XXS || gyo->size_type == aGYO_SIZE_XS) {
escape_dist = 17.0f;
} else {
escape_dist = 22.0f;
}
if (uki->hit_water_flag && target_dist < escape_dist) {
aGTT_set_angle(actorx, target_angle + DEG2SHORT_ANGLE2(180.0f));
aGTT_setupAction(gyo, aGTT_ACTION_ESCAPE);
} else {
int rod_type = aGYO_get_uki_type();
if ((gyo->gyo_flags & 1) == 0 && uki->cast_timer == 0 &&
target_dist < aGYO_search_area[rod_type][search_area] && fabsf(target_y) < 10.0f &&
goal_angle > DEG2SHORT_ANGLE2(-aGYO_search_angle[rod_type][search_area]) &&
goal_angle < DEG2SHORT_ANGLE2(aGYO_search_angle[rod_type][search_area])) {
ret = TRUE;
}
}
}
}
return ret;
}
static int aGTT_player_near(ACTOR* actorx, GAME* game) {
aGYO_CTRL_ACTOR* gyo = (aGYO_CTRL_ACTOR*)actorx;
ACTOR* playerx = GET_PLAYER_ACTOR_GAME_ACTOR(game);
f32 dist;
s16 target_angle;
xyz_t pos;
int ret = FALSE;
dist = search_position_distance(&actorx->world.position, &playerx->world.position);
target_angle = search_position_angleY(&actorx->world.position, &playerx->world.position);
if (
// clang-format off
((dist < 110.0f && mPlib_get_player_actor_main_index(game) == mPlayer_INDEX_DASH) ||
(dist < 150.0f && (
mPlib_Check_HitAxe(&pos) ||
mPlib_Check_StopNet(&pos) ||
mPlib_Check_HitScoop(&pos)
))) ||
gyo->escape_flag
// clang-format on
) {
aGTT_set_angle(actorx, target_angle + DEG2SHORT_ANGLE2(180.0f));
switch (gyo->size_type) {
case aGYO_SIZE_XXS:
case aGYO_SIZE_XS:
case aGYO_SIZE_S:
case aGYO_SIZE_M:
aGTT_effect_hamon(gyo, game, 3);
break;
case aGYO_SIZE_L:
case aGYO_SIZE_XL:
case aGYO_SIZE_XXL:
aGTT_effect_hamon(gyo, game, 2);
break;
}
aGTT_kage_make_actor(gyo, game, 0);
ret = TRUE;
}
return ret;
}
static int aGYO_check_wall(ACTOR* actorx) {
aGYO_CTRL_ACTOR* gyo = (aGYO_CTRL_ACTOR*)actorx;
int ret = FALSE;
if (actorx->bg_collision_check.result.hit_wall != mCoBG_DIDNT_HIT_WALL) {
int count = actorx->bg_collision_check.result.hit_wall_count;
if (count != 0) {
int i;
for (i = 0; i < count; i++) {
if (actorx->bg_collision_check.wall_info[i].type == mCoBG_WALL_TYPE0) {
s16 wall_angle = actorx->bg_collision_check.wall_info[i].angleY;
s16 check_angle = wall_angle - (actorx->world.angle.y + DEG2SHORT_ANGLE2(180.0f));
if (check_angle > 0) {
aGTT_set_angle(actorx, actorx->world.angle.y + DEG2SHORT_ANGLE2(90.0f));
} else {
aGTT_set_angle(actorx, actorx->world.angle.y - DEG2SHORT_ANGLE2(90.0f));
}
gyo->gyo_flags |= 0x40;
ret = TRUE;
break;
}
}
}
}
return ret;
}
static int aGYO_check_bridge(aGYO_CTRL_ACTOR* gyo) {
int ret = FALSE;
if ((gyo->gyo_flags & 0x100) == 0) {
switch (gyo->action) {
case aGTT_ACTION_SWIM:
case aGTT_ACTION_WAIT:
case aGTT_ACTION_NEAR:
if (((ACTOR*)gyo)->bg_collision_check.result.is_in_water) {
switch (mCoBG_Wpos2Attribute(((ACTOR*)gyo)->world.position, NULL)) {
case mCoBG_ATTRIBUTE_STONE:
case mCoBG_ATTRIBUTE_WOOD:
break;
default:
ret = TRUE;
break;
}
} else {
ret = TRUE;
}
break;
default:
ret = TRUE;
break;
}
}
return ret;
}
static int aGYO_check_fall(aGYO_CTRL_ACTOR* gyo) {
int ret = FALSE;
if (gyo->action == aGTT_ACTION_BITE || gyo->action == aGTT_ACTION_COMEBACK) {
ret = TRUE;
} else if ((gyo->gyo_flags & 0x100) == 0) {
f32 now_y = ((ACTOR*)gyo)->world.position.y;
f32 last_y = ((ACTOR*)gyo)->last_world_position.y;
if (((ACTOR*)gyo)->bg_collision_check.result.unit_attribute == mCoBG_ATTRIBUTE_WATERFALL && now_y < last_y) {
if (gyo->action == aGTT_ACTION_BITE || gyo->action == aGTT_ACTION_COMEBACK) {
((UKI_ACTOR*)gyo->linked_actor)->gyo_command = 0;
}
} else {
ret = TRUE;
}
}
return ret;
}
static void aGTT_wait(ACTOR* actorx, GAME* game) {
aGYO_CTRL_ACTOR* gyo = (aGYO_CTRL_ACTOR*)actorx;
f32 rnd;
aGTT_flow_direction(actorx);
if (DECREMENT_TIMER(gyo->work0) == 0) {
rnd = RANDOM_F(3.0f);
if (rnd < 1.0f) {
gyo->swim_flag = 0;
} else if (rnd < 2.0f) {
gyo->swim_flag = 1;
} else {
gyo->swim_flag = 2;
}
aGTT_setupAction(gyo, aGTT_ACTION_SWIM);
} else {
if (aGTT_player_near(actorx, game) == FALSE && aGTT_search_Uki(actorx, game) == TRUE) {
aGTT_setupAction(gyo, aGTT_ACTION_NEAR);
}
}
}
static void aGTT_swim(ACTOR* actorx, GAME* game) {
aGYO_CTRL_ACTOR* gyo = (aGYO_CTRL_ACTOR*)actorx;
int wait_flag = FALSE;
if (aGYO_check_wall(actorx) == TRUE) {
aGTT_setupAction(gyo, aGTT_ACTION_ESCAPE);
} else {
switch (gyo->swim_flag) {
case 0:
wait_flag = aGTT_swim_speed_check(gyo, 360.0f, 5.0f, 0.5f);
break;
case 1:
wait_flag = aGTT_swim_speed_check(gyo, 180.0f, 5.0f, 0.5f);
if (wait_flag == TRUE) {
actorx->world.angle.y = actorx->shape_info.rotation.y;
}
break;
case 2:
if ((gyo->gyo_flags & 0x80) != 0) {
aGTT_chase_s_angle(gyo, gyo->swork3, 0x400);
} else {
wait_flag = aGTT_swim_speed_change(gyo, 180.0f, 5.0f, 1.0f);
}
break;
}
if (wait_flag == TRUE) {
aGTT_setupAction(gyo, aGTT_ACTION_WAIT);
} else {
if (aGTT_player_near(actorx, game) == FALSE && aGTT_search_Uki(actorx, game) == TRUE) {
aGTT_setupAction(gyo, aGTT_ACTION_NEAR);
}
}
}
}
static void aGTT_near(ACTOR* actorx, GAME* game) {
aGYO_CTRL_ACTOR* gyo = (aGYO_CTRL_ACTOR*)actorx;
f32 target_dist;
f32 target_y;
s16 angle_y;
UKI_ACTOR* uki = (UKI_ACTOR*)gyo->linked_actor;
s16 search_area = gyoei_type[gyo->gyo_type].search_area;
int rod_type = aGYO_get_uki_type();
angle_y = search_position_angleY(&actorx->world.position, &uki->actor_class.world.position);
aGTT_set_angle(actorx, angle_y);
target_dist = search_position_distance(&actorx->world.position, &uki->actor_class.world.position);
target_y = actorx->world.position.y - uki->actor_class.world.position.y;
if (target_dist > aGYO_search_area[rod_type][search_area] || fabsf(target_y) > 10.0f) {
aGTT_setupAction(gyo, aGTT_ACTION_WAIT);
} else if (target_dist < aGTT_touch_distance[gyo->size_type]) {
if (uki->gyo_status == 1) {
uki->gyo_command = 1;
uki->gyo_type = gyo->gyo_type;
uki->child_actor = actorx;
uki->actor_class.world.angle.y = actorx->world.angle.y;
uki->actor_class.shape_info.rotation.y = actorx->shape_info.rotation.y;
aGTT_setupAction(gyo, aGTT_ACTION_TOUCH);
} else {
aGTT_setupAction(gyo, aGTT_ACTION_WAIT);
}
}
}
static void aGTT_touch(ACTOR* actorx, GAME* game) {
aGYO_CTRL_ACTOR* gyo = (aGYO_CTRL_ACTOR*)actorx;
UKI_ACTOR* uki;
if (aGTT_warp_event(gyo)) {
return;
}
uki = (UKI_ACTOR*)gyo->linked_actor;
uki->actor_class.world.angle.y = actorx->world.angle.y;
uki->actor_class.shape_info.rotation.y = actorx->shape_info.rotation.y;
if (DECREMENT_TIMER(gyo->work0) == 0) {
f32 target_dist;
s16 angle;
actorx->speed = aGTT_speed[gyo->size_type];
angle = search_position_angleY(&actorx->world.position, &uki->actor_class.world.position);
aGTT_set_angle(actorx, angle);
target_dist = search_position_distance(&actorx->world.position, &uki->actor_class.world.position);
if (target_dist < aGTT_touch_distance[gyo->size_type]) {
if ((aGTT_random_check(4.0f) != FALSE && (aGYO_check_fall(gyo) == TRUE)) || DECREMENT_TIMER(gyo->touch_counter) == 0) {
if (uki->gyo_status == 2) {
uki->gyo_command = 2;
// If a free space exists, 1/20 chance of switching the fish out for trash
if (mPlib_Get_space_putin_item() >= 0 && aGTT_random_check(20.0f) != 0) {
static int gomi[] = { aGYO_TYPE_EMPTY_CAN, aGYO_TYPE_EMPTY_CAN, aGYO_TYPE_BOOT, aGYO_TYPE_BOOT, aGYO_TYPE_BOOT, aGYO_TYPE_OLD_TIRE, aGYO_TYPE_OLD_TIRE, aGYO_TYPE_OLD_TIRE };
gyo->gyo_type = gomi[gyo->size_type];
uki->gyo_type = gyo->gyo_type;
}
aGTT_setupAction(gyo, aGTT_ACTION_BITE);
}
} else {
uki->touched_flag = TRUE;
gyo->work0 = (int)((aGTT_touch_count[gyo->size_type] + RANDOM2_F(30.0f)) * 2.0f);
actorx->speed = aGTT_back_speed[gyo->size_type] + RANDOM2_F(0.2f);
}
}
}
if (uki->status == 6) {
uki->gyo_command = 0;
aGTT_effect_sibuki(gyo, game, 0);
aGTT_kage_make_actor(gyo, game, 0);
}
}
static void aGTT_bite(ACTOR* actorx, GAME* game) {
static s16 eff_arg[] = { 8, 7, 4, 4, 5, 6, 6, 6 };
aGYO_CTRL_ACTOR* gyo = (aGYO_CTRL_ACTOR*)actorx;
UKI_ACTOR* uki = (UKI_ACTOR*)gyo->linked_actor;
f32 now_y = actorx->world.position.y;
f32 last_y = actorx->last_world_position.y;
if (aGTT_warp_event(gyo)) {
return;
}
if (uki->gyo_status == 4) {
if (uki->actor_class.bg_collision_check.result.unit_attribute == mCoBG_ATTRIBUTE_WATERFALL) {
actorx->world.position = uki->actor_class.world.position;
if (now_y < actorx->world.position.y) {
actorx->world.position.y = now_y;
}
sAdo_OngenPos((u32)actorx, NA_SE_24, &actorx->world.position);
} else {
static f32 rr[] = { 6.0f, 7.0f, 8.0f, 8.0f, 9.0f, 10.0f, 15.0f, 15.0f };
xyz_t pos;
pos = aGTT_pos_calc(uki->actor_class.world.position, game, uki->actor_class.world.angle.y, 8.0f, rr[gyo->size_type]);
actorx->world.position.x = pos.x;
actorx->world.position.z = pos.z;
if (now_y < last_y) {
actorx->world.position.y = last_y;
}
aGTT_set_angle(actorx, uki->actor_class.world.angle.y);
sAdo_OngenPos((u32)actorx, NA_SE_24, &actorx->world.position);
CLIP(gyo_clip)->hitcheck_gyoei_proc(&actorx->world.position, gyo->size_type);
if (DECREMENT_TIMER(gyo->swork0) == 0) {
if (aGTT_random_check(2.0f)) {
aGTT_effect_sibuki(gyo, game, eff_arg[gyo->size_type]);
}
gyo->swork0 = 3;
}
}
} else {
f32 now_y = actorx->world.position.y;
f32 last_y = actorx->last_world_position.y;
actorx->world.position.x = uki->actor_class.world.position.x;
actorx->world.position.z = uki->actor_class.world.position.z;
if (uki->actor_class.bg_collision_check.result.unit_attribute == mCoBG_ATTRIBUTE_WATERFALL) {
actorx->world.position = uki->actor_class.world.position;
if (now_y < actorx->world.position.y) {
actorx->world.position.y = now_y;
}
} else {
if (now_y < last_y) {
actorx->world.position.y = last_y;
}
}
aGTT_set_angle(actorx, uki->actor_class.world.angle.y);
aGTT_position_calc(gyo);
if (uki->gyo_status == 5) {
actorx->speed = 0.0f;
aGTT_setupAction(gyo, aGTT_ACTION_COMEBACK);
} else if (DECREMENT_TIMER(gyo->work0) == 0) {
uki->gyo_command = 0;
aGTT_kage_make_actor(gyo, game, 0);
}
}
uki->gyo_pos = actorx->world.position;
}
static void aGTT_comeback(ACTOR* actorx, GAME* game) {
aGYO_CTRL_ACTOR* gyo = (aGYO_CTRL_ACTOR*)actorx;
f32 scale;
UKI_ACTOR* uki = (UKI_ACTOR*)gyo->linked_actor;
actorx->world.position = uki->uki_pos;
aGTT_set_angle(actorx, uki->actor_class.world.angle.y);
if (uki->gyo_status == 3) {
aGTT_position_calc(gyo);
if (aGTT_random_check(10.0f)) {
aGTT_effect_hamon(gyo, game, 0);
}
} else if (uki->gyo_status == 5) {
ACTOR* playerx = GET_PLAYER_ACTOR_GAME_ACTOR(game);
if ((gyo->gyo_flags & 4) == 0) {
switch (gyo->gyo_type) {
case aGYO_TYPE_EMPTY_CAN:
case aGYO_TYPE_BOOT:
case aGYO_TYPE_OLD_TIRE:
aGTT_kage_make_actor(gyo, game, 1);
break;
}
gyo->swork4 = playerx->world.angle.y;
gyo->gyo_flags |= 8;
}
} else if (uki->gyo_status == 6) {
gyo->gyo_flags |= 0x200;
if (gyo->anim_frame == 1) {
sAdo_OngenTrgStart(NA_SE_11A, &actorx->world.position);
}
} else if (uki->gyo_status == 8) {
uki->gyo_status = 0;
aGTT_fish_make_actor(gyo, game);
gyo->gyo_flags |= 0x20;
} else if (uki->gyo_status == 7) {
gyo->gyo_flags |= 0x10;
} else if (uki->gyo_status == 0) {
uki->gyo_command = 0;
uki->child_actor = NULL;
gyo->gyo_flags &= ~2;
gyo->gyo_flags |= 0x20;
return;
}
if ((gyo->gyo_flags & 0x10) != 0) {
scale = uki->gyo_scale / 100.0f;
} else if (gyo->draw_type == aGYO_DRAW_TYPE_FISH) {
scale = 0.01f;
} else {
scale = aGYO_shadow_scale[gyo->size_type] * 0.02f;
}
aGTT_set_scale(actorx, scale);
uki->gyo_pos = actorx->world.position;
}
static void aGTT_escape(ACTOR* actorx, GAME* game) {
aGYO_CTRL_ACTOR* gyo = (aGYO_CTRL_ACTOR*)actorx;
if (aGTT_player_near(actorx, game) == FALSE) {
if (aGTT_search_Uki(actorx, game) == TRUE) {
aGTT_setupAction(gyo, aGTT_ACTION_NEAR);
} else if ((gyo->gyo_flags & 0x40) != 0 || aGYO_check_wall(actorx) == FALSE) {
if (DECREMENT_TIMER(gyo->work0) == 0) {
gyo->gyo_flags &= ~0x40;
aGTT_setupAction(gyo, aGTT_ACTION_WAIT);
} else {
chase_f(&actorx->speed, 0.0f, 0.02f);
}
}
}
}
static void aGTT_swim_init(aGYO_CTRL_ACTOR* gyo) {
switch (gyo->swim_flag) {
case 0:
gyo->fwork3 = 50.0f;
gyo->swork2 = 0;
gyo->swork3 = 0;
break;
case 1:
gyo->fwork3 = 0.0f;
gyo->swork2 = 0;
gyo->swork3 = RANDOM2_F(DEG2SHORT_ANGLE2(180.0f));
gyo->tools_class.actor_class.world.angle.y += gyo->swork3;
break;
case 2:
gyo->gyo_flags |= 0x80;
gyo->fwork3 = 0.0f;
gyo->swork2 = aGTT_Get_flow_angle_rv((ACTOR*)gyo);
gyo->swork3 = ((ACTOR*)gyo)->world.angle.y + (s16)RANDOM2_F(DEG2SHORT_ANGLE2(90.0f));
((ACTOR*)gyo)->shape_info.rotation.y = ((ACTOR*)gyo)->world.angle.y;
break;
}
aGTT_speed_reset((ACTOR*)gyo);
}
static void aGTT_near_init(aGYO_CTRL_ACTOR* gyo) {
gyo->gyo_flags |= 2;
((ACTOR*)gyo)->speed = aGTT_speed[gyo->size_type];
((ACTOR*)gyo)->max_velocity_y = 12.0f;
}
static void aGTT_touch_init(aGYO_CTRL_ACTOR* gyo) {
gyo->work0 = 0;
gyo->range = 12.0f;
gyo->touch_counter = 5;
aGTT_speed_reset((ACTOR*)gyo);
}
static void aGTT_bite_init(aGYO_CTRL_ACTOR* gyo) {
gyo->work0 = (int)(aGYO_bite_time[aGYO_get_uki_type()][gyoei_type[gyo->gyo_type].bite_time] * 2.0f);
gyo->swork0 = 3;
aGTT_speed_reset((ACTOR*)gyo);
}
static void aGTT_comeback_init(aGYO_CTRL_ACTOR* gyo) {
gyo->swork2 = 1 + RANDOM(3);
gyo->swork3 = 15 + RANDOM2(10);
aGTT_speed_reset((ACTOR*)gyo);
}
static void aGTT_wait_init(aGYO_CTRL_ACTOR* gyo) {
gyo->gyo_flags &= ~2;
gyo->work0 = (int)((100.0f + RANDOM_F(30.0f)) * 2.0f);
((ACTOR*)gyo)->speed = -0.15f + RANDOM2_F(0.2f);
((ACTOR*)gyo)->max_velocity_y = 0.0f;
}
static void aGTT_escape_init(aGYO_CTRL_ACTOR* gyo) {
gyo->swork0 = 0;
gyo->work0 = 100;
((ACTOR*)gyo)->speed = 2.0f;
}
typedef void (*aGTT_INIT_PROC)(aGYO_CTRL_ACTOR* gyo);
static void aGTT_setupAction(aGYO_CTRL_ACTOR* gyo, int action) {
static aGTT_INIT_PROC init_proc[] = {
aGTT_swim_init,
aGTT_wait_init,
aGTT_escape_init,
aGTT_near_init,
aGTT_touch_init,
aGTT_bite_init,
aGTT_comeback_init,
};
static aGYO_ACT_PROC act_proc[] = {
aGTT_swim,
aGTT_wait,
aGTT_escape,
aGTT_near,
aGTT_touch,
aGTT_bite,
aGTT_comeback,
};
gyo->action = action;
gyo->act_proc = act_proc[action];
init_proc[action](gyo);
}
static void aGTT_actor_move(ACTOR* actorx, GAME* game) {
aGYO_CTRL_ACTOR* gyo = (aGYO_CTRL_ACTOR*)actorx;
actorx->world.position.y = aGTT_Get_water_surface_position_y(actorx->world.position);
if (aGYO_check_bridge(gyo) == TRUE && aGYO_check_fall(gyo) == TRUE) {
(*gyo->act_proc)(actorx, game);
} else if ((gyo->gyo_flags & 0x100) == 0) {
gyo->work0 = 60;
gyo->gyo_flags |= 0x100;
} else if (DECREMENT_TIMER(gyo->work0) == 0) {
gyo->gyo_flags |= 0x20;
}
}
+1 -1
View File
@@ -441,7 +441,7 @@ static void aIHT_setupAction(aINS_INSECT_ACTOR* insect, int action, GAME* game)
static aINS_ACTION_PROC act_proc[] = {
aIHT_avoid,
(aINS_ACTION_PROC)none_proc1,
aIHT_avoid,
aIHT_fly,
};