mirror of
https://github.com/ACreTeam/ac-decomp
synced 2026-06-23 15:25:23 -04:00
397 lines
12 KiB
Plaintext
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);
|
|
}
|