mirror of
https://github.com/ACreTeam/ac-decomp
synced 2026-05-22 22:24:16 -04:00
Implement & link ac_gyo_test, ac_gyo_kaseki, link few others & fixes
This commit is contained in:
+5
-5
@@ -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"),
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user