Files
ac-decomp/src/ac_insect_move.c_inc
T
2024-04-28 20:44:07 -04:00

397 lines
12 KiB
Plaintext

static void aINS_position_move(ACTOR* actorx) {
aINS_INSECT_ACTOR* insect = (aINS_INSECT_ACTOR*)actorx;
s16 angleY = actorx->world.angle.y;
xyz_t_move(&actorx->last_world_position, &actorx->world.position);
chase_f(&actorx->speed, insect->target_speed, insect->speed_step * 0.5f);
actorx->position_speed.x = actorx->speed * sin_s(angleY);
actorx->position_speed.z = actorx->speed * cos_s(angleY);
switch (insect->type) {
case aSOI_INSECT_TYPE_COMMON_BUTTERFLY:
case aSOI_INSECT_TYPE_YELLOW_BUTTERFLY:
case aSOI_INSECT_TYPE_TIGER_BUTTERFLY:
case aSOI_INSECT_TYPE_PURPLE_BUTTERFLY:
case aSOI_INSECT_TYPE_FIREFLY:
case aSOI_INSECT_TYPE_MOSQUITO:
case aSOI_INSECT_TYPE_SPIRIT:
break;
default:
chase_f(&actorx->position_speed.y, actorx->max_velocity_y, actorx->gravity * 0.5f);
break;
}
Actor_position_move(actorx);
}
static void aINS_set_player_info(ACTOR* actorx, PLAYER_ACTOR* player) {
if (player != NULL) {
f32 distXZ;
f32 distY;
distXZ = search_position_distanceXZ(&actorx->world.position, &player->actor_class.world.position);
actorx->player_distance_xz = distXZ;
distY = player->actor_class.world.position.y - actorx->world.position.y;
actorx->player_distance_y = distY;
actorx->player_distance = SQ(distXZ) + SQ(distY);
actorx->player_angle_y = search_position_angleY(&actorx->world.position, &player->actor_class.world.position);
} else {
actorx->player_distance_xz = 0.0f;
actorx->player_distance_y = 0.0f;
actorx->player_distance = 0.0f;
actorx->player_angle_y = 0;
}
}
static void aINS_BGcheck(ACTOR* actorx) {
aINS_INSECT_ACTOR* insect = (aINS_INSECT_ACTOR*)actorx;
switch (insect->bg_type) {
case 1:
mCoBG_BgCheckControll(NULL, actorx, insect->bg_range, insect->bg_height, TRUE, FALSE, 1);
break;
case 2:
mCoBG_BgCheckControll(NULL, actorx, insect->bg_range, insect->bg_height, FALSE, FALSE, 1);
break;
case 3:
mCoBG_BgCheckControll_RemoveDirectedUnitColumn(NULL, actorx, insect->bg_range, insect->bg_height, TRUE,
FALSE, 1, insect->ut_x, insect->ut_z);
break;
case 4:
mCoBG_BgCheckControll_RemoveDirectedUnitColumn(NULL, actorx, insect->bg_range, insect->bg_height, FALSE,
FALSE, 1, insect->ut_x, insect->ut_z);
break;
}
if (insect->insect_flags.bit_2 == FALSE && insect->insect_flags.bit_4 == TRUE) {
mCoBG_UniqueWallCheck(actorx, insect->bg_range, 0.0f);
}
}
// clang-format off
static f32 catch_ME_data[] = {
0.0,
0.0,
0.0,
0.0,
10.0,
10.0,
10.0,
0.0,
10.0,
0.0,
0.0,
0.0,
0.0,
0.0,
20.0,
-20.0,
-20.0,
-20.0,
-20.0,
-20.0,
-20.0,
-20.0,
0.0,
0.0,
-20.0,
-20.0,
-20.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0f,
};
// clang-format on
static void aINS_get_stress_sub(f32* stress, Actor_list* actor_list, xyz_t* pos, aINS_INSECT_ACTOR* insect) {
static f32 calc_table[] = { 0.3f, 1.0f, 2.0f, 5.0f, 10.0f };
f32 min_dist = aINS_MAX_STRESS_DIST;
ACTOR* actor;
min_dist += catch_ME_data[insect->type];
/* Calculate the greatest stress caused by any nearby actors */
for (actor = actor_list->actor; actor != NULL; actor = actor->next_actor) {
f32 dist = search_position_distance(pos, &actor->world.position);
if (dist < min_dist) {
f32 tmp0;
int idx;
f32 dX;
f32 dZ;
f32 calc_stress;
tmp0 = dist - mFI_UNIT_BASE_SIZE_F;
if (tmp0 < 0.0f) {
tmp0 = 0.0f;
}
idx = (int)((min_dist - mFI_UNIT_BASE_SIZE_F) - tmp0) / 20;
if (idx > ARRAY_COUNT(calc_table) - 1) {
idx = ARRAY_COUNT(calc_table) - 1;
}
dX = actor->world.position.x - actor->last_world_position.x;
dZ = actor->world.position.z - actor->last_world_position.z;
calc_stress = sqrtf(SQ(dX) + SQ(dZ)) * calc_table[idx];
/* Stress is modified by the amount of movement over a single frame */
if (calc_stress > *stress) {
*stress = calc_stress;
}
}
}
}
static f32 aINS_get_stress(ACTOR* actorx, GAME* game) {
Actor_info* actor_info = &((GAME_PLAY*)game)->actor_info;
int i;
aINS_INSECT_ACTOR* insect = (aINS_INSECT_ACTOR*)actorx;
f32 stress = 0.0f;
/* Calculate max stress on the insect from specific types of actors */
for (i = 0; i < ACTOR_PART_NUM; i++) {
switch (i) {
case ACTOR_PART_UNUSED:
case ACTOR_PART_PLAYER:
case ACTOR_PART_NPC:
case ACTOR_PART_BG:
aINS_get_stress_sub(&stress, &actor_info->list[i], &actorx->world.position, insect);
break;
}
}
return stress; /* return the max stress */
}
static void aINS_calc_patience(ACTOR* actorx, GAME* game) {
aINS_INSECT_ACTOR* insect = (aINS_INSECT_ACTOR*)actorx;
f32 stress = aINS_get_stress(actorx, game);
if (F32_IS_ZERO(stress)) {
insect->patience -= aINS_PATIENCE_STEP;
if (insect->patience < 0.0f) {
insect->patience = 0.0f;
}
} else {
insect->patience += stress * aINS_PATIENCE_STEP;
if (insect->patience > 100.0f) {
insect->patience = 100.0f;
}
}
}
static void aINS_calc_life_time(aINS_INSECT_ACTOR* insect) {
insect->life_time--;
if (insect->life_time <= 0) {
insect->insect_flags.bit_3 = TRUE;
insect->life_time = 0;
}
}
static void aINS_calc_alpha_time(aINS_INSECT_ACTOR* insect) {
if (insect->life_time != 0) {
return;
}
if (insect->alpha_time <= 0) {
return;
}
insect->alpha_time--;
if (insect->alpha_time >= 24) {
return;
}
switch (insect->type) {
case aSOI_INSECT_TYPE_FIREFLY: {
int alpha = insect->alpha2;
alpha += 11;
if (alpha >= 255) {
alpha = 255;
insect->alpha0 = 0;
insect->alpha1 = 0;
insect->insect_flags.destruct = TRUE;
}
insect->alpha2 = alpha;
break;
}
default: {
int alpha = insect->alpha0;
alpha -= 11;
if (alpha <= 0) {
alpha = 0;
insect->insect_flags.destruct = TRUE;
}
insect->alpha0 = alpha;
}
}
}
static void aINS_cull_check(ACTOR* actorx, GAME* game) {
aINS_INSECT_ACTOR* insect = (aINS_INSECT_ACTOR*)actorx;
GAME_PLAY* play = (GAME_PLAY*)game;
Skin_Matrix_PrjMulVector(&play->projection_matrix, &actorx->world.position, &actorx->camera_position,
&actorx->camera_w);
if (insect->insect_flags.destruct && (ACTOR*)mPlib_Get_item_net_catch_label() != actorx) {
aINS_destruct(actorx, game);
}
if (Actor_draw_actor_no_culling_check(actorx) == FALSE) {
if (actorx->actor_specific == 1) {
if ((ACTOR*)mPlib_Get_item_net_catch_label() != actorx) {
aINS_destruct(actorx, game);
}
} else {
if ((ACTOR*)mPlib_Get_item_net_catch_label() != actorx) {
/* Allow actor to be culled since it's not been caught */
actorx->state_bitfield &= ~ACTOR_STATE_NO_CULL;
}
/* Despawn if player is more than 15 units away and in another acre and has not caught it */
if (actorx->player_distance_xz > 600.0f &&
(actorx->block_x != play->block_table.block_x || actorx->block_z != play->block_table.block_z) &&
(ACTOR*)mPlib_Get_item_net_catch_label() != actorx) {
aINS_destruct(actorx, game);
}
}
} else {
/* Don't cull if the actor is still visible on the camera */
actorx->state_bitfield |= ACTOR_STATE_NO_CULL;
}
}
static f32 aINS_get_catch_range_sub(ACTOR* actorx) {
f32 range = 24.0f;
s16 dAngleY = ABS((s16)(actorx->world.angle.y - actorx->player_angle_y));
/* Player must be facing within 90 degrees of the insect */
if (dAngleY > DEG2SHORT_ANGLE2(90.0f)) {
range = 0.0f;
}
return range;
}
static f32 aINS_get_catch_range(ACTOR* actorx) {
aINS_INSECT_ACTOR* insect = (aINS_INSECT_ACTOR*)actorx;
f32 range = 8.0f;
switch (insect->type) {
case aSOI_INSECT_TYPE_COMMON_BUTTERFLY:
case aSOI_INSECT_TYPE_YELLOW_BUTTERFLY:
range = 24.0f;
break;
case aSOI_INSECT_TYPE_ROBUST_CICADA:
case aSOI_INSECT_TYPE_WALKER_CICADA:
case aSOI_INSECT_TYPE_EVENING_CICADA:
case aSOI_INSECT_TYPE_BROWN_CICADA:
case aSOI_INSECT_TYPE_BEE:
case aSOI_INSECT_TYPE_DRONE_BEETLE:
case aSOI_INSECT_TYPE_DYNASTID_BEETLE:
case aSOI_INSECT_TYPE_FLAT_STAG_BEETLE:
case aSOI_INSECT_TYPE_JEWEL_BEETLE:
case aSOI_INSECT_TYPE_LONGHORN_BEETLE:
case aSOI_INSECT_TYPE_SAW_STAG_BEETLE:
case aSOI_INSECT_TYPE_MOUNTAIN_BEETLE:
case aSOI_INSECT_TYPE_GIANT_BEETLE:
range = aINS_get_catch_range_sub(actorx);
break;
case aSOI_INSECT_TYPE_COCKROACH:
if (insect->flag == 4) {
range = aINS_get_catch_range_sub(actorx);
}
break;
}
return range;
}
static void aINS_set_catch_range(ACTOR* actorx) {
aINS_INSECT_ACTOR* insect = (aINS_INSECT_ACTOR*)actorx;
if (insect->insect_flags.bit_1 == FALSE) {
f32 catch_range = aINS_get_catch_range(actorx);
if (!F32_IS_ZERO(catch_range)) {
GET_PLAYER_ACTOR_NOW()->Set_Item_net_catch_request_table_proc(
(ACTOR*)GET_PLAYER_ACTOR_NOW(), gamePT, (u32)actorx, 0, &actorx->world.position, catch_range);
}
}
}
static void aINS_check_birth_ant(GAME* game) {
GAME_PLAY* play = (GAME_PLAY*)game;
if (aINS_CLIP->ant_spawn_pending == TRUE) {
aINS_Init_c* init = &aINS_CLIP->ant_spawn_info;
ACTOR* actorx = Actor_info_make_actor(&play->actor_info, game, mAc_PROFILE_ANT, init->position.x,
init->position.y, init->position.z, 0, 0, 0, aINS_CLIP->ant_bx,
aINS_CLIP->ant_bz, -1, EMPTY_NO, -1, -1, -1);
if (actorx != NULL) {
aINS_CLIP->ant_spawn_pending = FALSE;
}
}
}
static void aINS_actor_move(ACTOR* actorx, GAME* game) {
aINS_CTRL_ACTOR* ctrl_actor = (aINS_CTRL_ACTOR*)actorx;
GAME_PLAY* play = (GAME_PLAY*)game;
PLAYER_ACTOR* player = GET_PLAYER_ACTOR(play);
aINS_INSECT_ACTOR* insect = ctrl_actor->insect_actor;
int i;
for (i = 0; i < aINS_ACTOR_NUM; i++) {
ACTOR* actorx = (ACTOR*)insect;
if (insect->exist_flag == TRUE) {
actorx->state_bitfield &= ~ACTOR_STATE_24;
if ((actorx->state_bitfield & (ACTOR_STATE_NO_MOVE_WHILE_CULLED | ACTOR_STATE_NO_CULL))) {
if (insect->tools_actor.init_matrix == FALSE) {
(*insect->move_proc)(actorx);
}
aINS_set_player_info(actorx, player);
aINS_BGcheck(actorx);
aINS_calc_patience(actorx, game);
aINS_calc_life_time(insect);
aINS_calc_alpha_time(insect);
(*actorx->mv_proc)(actorx, game);
Actor_world_to_eye(actorx, 0.0f);
aINS_set_catch_range(actorx);
}
aINS_cull_check(actorx, game);
}
insect++;
}
aINS_check_birth_ant(game);
aINS_set_pl_act_tim(0, -1, -1);
}