Implement & link ac_house_goki

This commit is contained in:
Cuyler36
2025-01-08 15:26:40 -05:00
parent 6bd0c5fc4b
commit 4fed194b37
17 changed files with 493 additions and 14 deletions
+457
View File
@@ -0,0 +1,457 @@
#include "ac_house_goki.h"
#include "m_actor_shadow.h"
#include "m_play.h"
#include "m_player_lib.h"
#include "m_common_data.h"
#include "m_cockroach.h"
#include "sys_matrix.h"
#include "m_rcp.h"
enum {
aHG_ACT_AWAY,
aHG_ACT_JUMP_AWAY,
aHG_ACT_WAIT,
aHG_ACT_MOVE,
aHG_ACT_DEAD,
aHG_ACT_NUM
};
static void aHG_actor_ct(ACTOR* actorx, GAME* game);
static void aHG_actor_move(ACTOR* actorx, GAME* game);
static void aHG_actor_draw(ACTOR* actorx, GAME* game);
// clang-format off
ACTOR_PROFILE House_Goki_Profile = {
mAc_PROFILE_HOUSE_GOKI,
ACTOR_PART_BG,
ACTOR_STATE_NO_MOVE_WHILE_CULLED,
EMPTY_NO,
ACTOR_OBJ_BANK_HOUSE_GOKI,
sizeof(HOUSE_GOKI_ACTOR),
&aHG_actor_ct,
mActor_NONE_PROC1,
&aHG_actor_move,
&aHG_actor_draw,
NULL,
};
// clang-format on
static void aHG_setupAction(HOUSE_GOKI_ACTOR* goki, GAME* game, int action);
static void aHG_actor_ct(ACTOR* actorx, GAME* game) {
HOUSE_GOKI_ACTOR* goki = (HOUSE_GOKI_ACTOR*)actorx;
GAME_PLAY* play = (GAME_PLAY*)game;
goki->alpha = 30.0f;
if (actorx->actor_specific <= 0) {
actorx->actor_specific = 0;
goki->alpha = 255.0f;
}
actorx->scale.x = 0.01f;
actorx->scale.y = 0.01f;
actorx->scale.z = 0.01f;
Shape_Info_init(actorx, 0.0f, &mAc_ActorShadowCircle, 6.0f, 6.0f);
xyz_t_move(&actorx->home.position, &actorx->world.position);
actorx->gravity = -2.0f;
actorx->shape_info.rotation.y = actorx->player_angle_y + DEG2SHORT_ANGLE2(180.0f);
actorx->world.angle.y = actorx->shape_info.rotation.y;
aHG_setupAction(goki, game, aHG_ACT_AWAY);
}
static void aHG_anime_proc(HOUSE_GOKI_ACTOR* goki) {
goki->anm_no += 0.5f;
if (goki->anm_no >= 2.0f) {
goki->anm_no -= 2.0f;
}
}
static void aHG_calc_timer(HOUSE_GOKI_ACTOR* goki) {
goki->timer -= 0.5f;
if (goki->timer < 0.0f) {
goki->timer = 0.0f;
}
goki->timer2 -= 0.5f;
if (goki->timer2 < 0.0f) {
goki->timer2 = 0.0f;
}
}
static s16 aHG_away_bg_hitangle_check_proc(ACTOR* actorx) {
HOUSE_GOKI_ACTOR* goki = (HOUSE_GOKI_ACTOR*)actorx;
s16 angle = 777; // 0x309
s16 wall_angle[2];
int i;
goki->timer2 = 0.0f;
if (actorx->player_distance_xz > 20.0f) {
wall_angle[0] = 777;
wall_angle[1] = 777;
if (actorx->bg_collision_check.result.hit_wall & mCoBG_HIT_WALL_FRONT) {
wall_angle[0] = DEG2SHORT_ANGLE2(-90.0f);
wall_angle[1] = DEG2SHORT_ANGLE2(90.0f);
}
if ((actorx->bg_collision_check.result.hit_wall & mCoBG_HIT_WALL_RIGHT) || (actorx->bg_collision_check.result.hit_wall & mCoBG_HIT_WALL_LEFT)) {
if (wall_angle[0] == 777) {
wall_angle[0] = DEG2SHORT_ANGLE2(180.0f) - actorx->world.angle.y;
if (wall_angle[0] > 0) {
wall_angle[0] = DEG2SHORT_ANGLE2(360.0f) - actorx->world.angle.y;
}
} else if (actorx->bg_collision_check.result.hit_wall & mCoBG_HIT_WALL_RIGHT) {
wall_angle[0] = DEG2SHORT_ANGLE2(90.0f);
} else {
wall_angle[0] = DEG2SHORT_ANGLE2(-90.0f);
}
angle = wall_angle[0];
} else {
i = 0;
if (wall_angle[0] != 777) {
// wall_angle[0] -= actorx->player_angle_y;
angle = ABS((s16)(wall_angle[0] - actorx->player_angle_y));
}
if (wall_angle[1] != 777) {
// wall_angle[1] -= actorx->player_angle_y;
if (angle < (s16)ABS((s16)(wall_angle[1] - actorx->player_angle_y))) {
i = 1;
}
}
angle = wall_angle[i];
}
}
return angle;
}
static void aHG_decide_next_act_idx_wait_move(HOUSE_GOKI_ACTOR* goki, GAME* game) {
GAME_PLAY* play = (GAME_PLAY*)game;
int next_act_idx = aHG_ACT_MOVE;
goki->timer = 5.0f + RANDOM_F(5.0f);
if (play->game_frame % 100 > 20 || RANDOM_F(1.0f) < 0.5f) {
next_act_idx = aHG_ACT_WAIT;
} else if (goki->actor_class.player_distance_xz < 60.0f) {
next_act_idx = aHG_ACT_WAIT;
}
aHG_setupAction(goki, game, next_act_idx);
}
static void aHG_position_move(ACTOR* actorx) {
s16 angleY = actorx->world.angle.y;
actorx->position_speed.x = actorx->speed * sin_s(angleY);
actorx->position_speed.z = actorx->speed * cos_s(angleY);
actorx->position_speed.y += actorx->gravity;
Actor_position_move(actorx);
}
static void aHG_BGcheck(ACTOR* actorx) {
mCoBG_WallCheckOnly(NULL, actorx, 15.0f, 0.0f, 0, 0);
if (actorx->world.position.y < actorx->home.position.y) {
actorx->world.position.y = actorx->home.position.y;
}
}
static int aHG_calc_add_alpha(HOUSE_GOKI_ACTOR* goki) {
int ret = FALSE;
goki->alpha += 3.5f;
if (goki->alpha > 255.0f) {
goki->alpha = 255.0f;
ret = TRUE;
}
return ret;
}
static int aHG_check_dead(ACTOR* actorx, GAME* game) {
ACTOR* playerx = GET_PLAYER_ACTOR_GAME_ACTOR(game);
int ret = FALSE;
if (aMR_CLIP != NULL && aMR_CLIP->check_danna_kill_proc(&actorx->world.position)) {
ret = TRUE;
}
if (actorx->bg_collision_check.result.unk_flag2 || actorx->bg_collision_check.result.unk_flag3) {
ret = TRUE;
}
if (playerx != NULL && !F32_IS_ZERO(playerx->speed) && actorx->player_distance_xz < 9.0f && actorx->world.position.y == actorx->home.position.y) {
ret = TRUE;
}
return ret;
}
static int aHG_player_check(ACTOR* actorx, GAME* game) {
ACTOR* playerx = GET_PLAYER_ACTOR_GAME_ACTOR(game);
int ret = FALSE;
if (playerx != NULL && !F32_IS_ZERO(playerx->speed) && actorx->player_distance_xz < 60.0f) {
ret = TRUE;
}
return ret;
}
static int aHG_check_threshold(ACTOR* actorx) {
mActor_name_t* fg_p = mFI_GetUnitFG(actorx->world.position);
if (fg_p != NULL && *fg_p == RSV_DOOR) {
actorx->shape_info.rotation.y = DEG2SHORT_ANGLE2(180.0f);
actorx->world.angle.y = DEG2SHORT_ANGLE2(180.0f);
}
return FALSE;
}
static void aHG_away(ACTOR* actorx, GAME* game) {
HOUSE_GOKI_ACTOR* goki = (HOUSE_GOKI_ACTOR*)actorx;
GAME_PLAY* play = (GAME_PLAY*)game;
if (goki->timer <= 0.0f && !goki->jump_flag && !aHG_player_check(actorx, game)) {
goki->timer = 20.0f + RANDOM_F(20.0f);
aHG_setupAction(goki, game, aHG_ACT_WAIT);
} else {
if (aHG_check_threshold(actorx) == TRUE) {
goki->jump_flag = TRUE;
goki->timer2 = 4.0f + RANDOM_F(4.0f);
} else {
goki->jump_flag = FALSE;
if (goki->timer2 <= 0.0f) {
if (actorx->bg_collision_check.result.hit_wall != mCoBG_DIDNT_HIT_WALL) {
f32 chance = 0.2f;
s16 angle = aHG_away_bg_hitangle_check_proc(actorx);
if (angle != 777) {
actorx->world.angle.y += angle;
actorx->world.angle.y &= 0xC000; // only allow movement on pure X & Z axes: 0, 90, 180, 270
actorx->shape_info.rotation.y = actorx->world.angle.y;
goki->timer2 = 5.0f + RANDOM_F(5.0f);
} else {
chance = 0.5f;
}
if (RANDOM_F(1.0f) < chance) {
aHG_setupAction(goki, game, aHG_ACT_JUMP_AWAY);
}
} else {
actorx->world.angle.y = actorx->player_angle_y + DEG2SHORT_ANGLE2(180.0f);
actorx->shape_info.rotation.y = actorx->world.angle.y;
}
}
}
sAdo_OngenPos((u32)goki, NA_SE_GOKI_MOVE, &actorx->world.position);
}
}
static void aHG_jump_away(ACTOR* actorx, GAME* game) {
HOUSE_GOKI_ACTOR* goki = (HOUSE_GOKI_ACTOR*)actorx;
GAME_PLAY* play = (GAME_PLAY*)game;
if (actorx->world.position.y == actorx->home.position.y) {
aHG_setupAction(goki, game, aHG_ACT_AWAY);
} else {
aHG_anime_proc(goki);
if (actorx->position_speed.y < 0.0f) {
actorx->gravity = -7.0f;
}
aHG_check_threshold(actorx);
}
}
static void aHG_wait(ACTOR* actorx, GAME* game) {
HOUSE_GOKI_ACTOR* goki = (HOUSE_GOKI_ACTOR*)actorx;
ACTOR* playerx = GET_PLAYER_ACTOR_GAME_ACTOR(game); // @unused
if (aHG_player_check(actorx, game) == TRUE) {
aHG_setupAction(goki, game, aHG_ACT_AWAY);
} else if (goki->timer <= 0.0f) {
aHG_decide_next_act_idx_wait_move(goki, game);
}
}
static void aHG_move(ACTOR* actorx, GAME* game) {
HOUSE_GOKI_ACTOR* goki = (HOUSE_GOKI_ACTOR*)actorx;
if (aHG_player_check(actorx, game) == TRUE) {
aHG_setupAction(goki, game, aHG_ACT_AWAY);
} else {
if (mAc_CHK_HIT_WALL(actorx, mCoBG_HIT_WALL_FRONT) ||
mAc_CHK_HIT_ATR_WALL(actorx, mCoBG_HIT_WALL_FRONT) ||
mAc_CHK_HIT_WALL(actorx, mCoBG_HIT_WALL_RIGHT) ||
mAc_CHK_HIT_ATR_WALL(actorx, mCoBG_HIT_WALL_RIGHT) ||
mAc_CHK_HIT_WALL(actorx, mCoBG_HIT_WALL_LEFT) ||
mAc_CHK_HIT_ATR_WALL(actorx, mCoBG_HIT_WALL_LEFT)) {
if (!goki->jump_flag) {
actorx->shape_info.rotation.y += DEG2SHORT_ANGLE2(180.0f);
actorx->world.angle.y = actorx->shape_info.rotation.y;
}
goki->jump_flag = TRUE;
} else {
if (aHG_check_threshold(actorx) == TRUE) {
goki->timer = 5.0f + RANDOM_F(5.0f);
}
goki->jump_flag = FALSE;
}
if (goki->timer <= 0.0f) {
aHG_decide_next_act_idx_wait_move(goki, game);
} else {
sAdo_OngenPos((u32)goki, NA_SE_GOKI_MOVE, &actorx->world.position);
}
}
}
static void aHG_dead(ACTOR* actorx, GAME* game) {
HOUSE_GOKI_ACTOR* goki = (HOUSE_GOKI_ACTOR*)actorx;
goki->alpha = goki->shadow_alpha;
if (((int)goki->timer & 2) == 0) {
goki->alpha = 0.0f;
}
goki->shadow_alpha -= 2.5f;
if (goki->shadow_alpha < 0.0f) {
goki->shadow_alpha = 0.0f;
}
actorx->shape_info.shadow_alpha_change_rate = goki->shadow_alpha * 0.0015f;
if (goki->timer <= 0.0f) {
Actor_delete(actorx);
}
}
static void aHG_away_init(HOUSE_GOKI_ACTOR* goki, GAME* game) {
goki->timer = 20.0f + RANDOM_F(20.0f);
goki->timer2 = 0.0f;
goki->jump_flag = FALSE;
goki->anm_no = 0.0f;
goki->actor_class.speed = 8.0f;
}
static void aHG_jump_away_init(HOUSE_GOKI_ACTOR* goki, GAME* game) {
// @BUG - incorrect usage of random generator again. Devs clearly intended this to be a random
// binary value (0 or 1), but calling RANDOM(1) will always result in 0 when aliasing to integer.
// Bug results in the cockroach jump movement always being 22.5 degrees more than
// the player angle.
#ifndef BUGFIXES
goki->actor_class.shape_info.rotation.y = goki->actor_class.player_angle_y + (s16)(DEG2SHORT_ANGLE2(22.5f) - ((s16)RANDOM(1) * DEG2SHORT_ANGLE2(45.0f)));
#else
goki->actor_class.shape_info.rotation.y = goki->actor_class.player_angle_y + (s16)(DEG2SHORT_ANGLE2(22.5f) - ((s16)RANDOM(2) * DEG2SHORT_ANGLE2(45.0f)));
#endif
goki->actor_class.world.angle.y = goki->actor_class.shape_info.rotation.y;
goki->actor_class.position_speed.y = 17.0f;
goki->actor_class.gravity = -2.0f;
goki->actor_class.speed = 5.0f;
sAdo_OngenTrgStart(NA_SE_GOKI_JUMP_AWAY, &goki->actor_class.world.position);
}
static void aHG_wait_init(HOUSE_GOKI_ACTOR* goki, GAME* game) {
goki->actor_class.shape_info.rotation.y = goki->actor_class.player_angle_y + DEG2SHORT_ANGLE2(180.0f);
goki->actor_class.world.angle.y = goki->actor_class.shape_info.rotation.y;
goki->actor_class.speed = 0.0f;
goki->anm_no = 0.0f;
}
static void aHG_move_init(HOUSE_GOKI_ACTOR* goki, GAME* game) {
xyz_t pos;
goki->timer = 5.0f + RANDOM_F(5.0f);
goki->jump_flag = FALSE;
xyz_t_move(&pos, &goki->actor_class.world.position);
pos.x += 80.0f - RANDOM_F(160.0f);
pos.z += 80.0f - RANDOM_F(160.0f);
goki->actor_class.shape_info.rotation.y = search_position_angleY(&goki->actor_class.world.position, &pos);
goki->actor_class.world.angle.y = goki->actor_class.shape_info.rotation.y;
goki->actor_class.speed = 4.0f;
}
static void aHG_dead_init(HOUSE_GOKI_ACTOR* goki, GAME* game) {
eEC_CLIP->effect_make_proc(eEC_EFFECT_GOKI, goki->actor_class.world.position, 1, 0, game, EMPTY_NO, 0, 0);
mCkRh_CalcCanLookGokiCount(-1);
sAdo_OngenTrgStart(NA_SE_GOKI_DEAD, &goki->actor_class.world.position);
goki->shadow_alpha = 255.0f;
goki->actor_class.speed = 0.0f;
goki->timer = 40.0f;
}
typedef void (*aHG_INIT_PROC)(HOUSE_GOKI_ACTOR* goki, GAME* game);
static void aHG_setupAction(HOUSE_GOKI_ACTOR* goki, GAME* game, int act) {
static aHG_INIT_PROC init_proc[] = {
&aHG_away_init,
&aHG_jump_away_init,
&aHG_wait_init,
&aHG_move_init,
&aHG_dead_init,
};
static aHG_ACT_PROC act_proc[] = {
&aHG_away,
&aHG_jump_away,
&aHG_wait,
&aHG_move,
&aHG_dead,
};
goki->action = act;
goki->act_proc = act_proc[act];
(*init_proc[act])(goki, game);
}
static void aHG_actor_move(ACTOR* actorx, GAME* game) {
HOUSE_GOKI_ACTOR* goki = (HOUSE_GOKI_ACTOR*)actorx;
aHG_position_move(actorx);
aHG_BGcheck(actorx);
aHG_calc_timer(goki);
if (goki->action != aHG_ACT_DEAD && aHG_calc_add_alpha(goki) == TRUE && aHG_check_dead(actorx, game) == TRUE) {
aHG_setupAction(goki, game, aHG_ACT_DEAD);
}
(*goki->act_proc)(actorx, game);
}
extern Gfx act_m_house_goki1T_model[];
extern Gfx act_m_house_goki2T_model[];
static void aHG_actor_draw(ACTOR* actorx, GAME* game) {
static Gfx* aHG_displayList[] = { act_m_house_goki1T_model, act_m_house_goki2T_model };
GRAPH* graph = game->graph;
HOUSE_GOKI_ACTOR* goki = (HOUSE_GOKI_ACTOR*)actorx;
Matrix_push();
Matrix_translate(actorx->world.position.x, actorx->world.position.y + 2.0f, actorx->world.position.z, 0);
Matrix_scale(actorx->scale.x, actorx->scale.y, actorx->scale.z, 1);
Matrix_RotateX(actorx->shape_info.rotation.x, 1);
Matrix_RotateY(actorx->shape_info.rotation.y, 1);
_texture_z_light_fog_prim_xlu(graph);
OPEN_POLY_XLU_DISP(graph);
gSPMatrix(POLY_XLU_DISP++, _Matrix_to_Mtx_new(graph), G_MTX_LOAD | G_MTX_NOPUSH);
gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 255, (u32)goki->alpha);
gSPDisplayList(POLY_XLU_DISP++, aHG_displayList[(int)goki->anm_no]);
CLOSE_POLY_XLU_DISP(graph);
Matrix_pull();
}
+1 -1
View File
@@ -42,7 +42,7 @@ extern s16 MUSEUM_FOSSIL_ctrl_actor_data[] = {
};
extern s16 MUSEUM_FOSSIL_object_bank[] = {
ACTOR_OBJ_BANK_369, // 0
ACTOR_OBJ_BANK_HOUSE_GOKI, // 0
};
extern Door_data_c MUSEUM_FOSSIL_door_data[] = {
+1 -1
View File
@@ -42,7 +42,7 @@ extern s16 P_ROOM_BM_L_ctrl_actor_data[] = {
};
extern s16 P_ROOM_BM_L_object_bank[] = {
ACTOR_OBJ_BANK_369, // 0
ACTOR_OBJ_BANK_HOUSE_GOKI, // 0
};
extern Door_data_c P_ROOM_BM_L_door_data[] = {
+1 -1
View File
@@ -42,7 +42,7 @@ extern s16 P_ROOM_BM_LL1_ctrl_actor_data[] = {
};
extern s16 P_ROOM_BM_LL1_object_bank[] = {
ACTOR_OBJ_BANK_369, // 0
ACTOR_OBJ_BANK_HOUSE_GOKI, // 0
};
extern Door_data_c P_ROOM_BM_LL1_door_data[] = {
+1 -1
View File
@@ -42,7 +42,7 @@ extern s16 P_ROOM_BM_M_ctrl_actor_data[] = {
};
extern s16 P_ROOM_BM_M_object_bank[] = {
ACTOR_OBJ_BANK_369, // 0
ACTOR_OBJ_BANK_HOUSE_GOKI, // 0
};
extern Door_data_c P_ROOM_BM_M_door_data[] = {
+1 -1
View File
@@ -42,7 +42,7 @@ extern s16 P_ROOM_BM_S_ctrl_actor_data[] = {
};
extern s16 P_ROOM_BM_S_object_bank[] = {
ACTOR_OBJ_BANK_369, // 0
ACTOR_OBJ_BANK_HOUSE_GOKI, // 0
};
extern Door_data_c P_ROOM_BM_S_door_data[] = {
+1 -1
View File
@@ -60,7 +60,7 @@ extern Actor_data PLAYER_ROOM_ISLAND_actor_data[] = {
extern s16 PLAYER_ROOM_ISLAND_object_bank[] = {
ACTOR_OBJ_BANK_ROOM_SUNSHINE, // 0
ACTOR_OBJ_BANK_369, // 1
ACTOR_OBJ_BANK_HOUSE_GOKI, // 1
};
extern Door_data_c PLAYER_ROOM_ISLAND_door_data[] = {
+1 -1
View File
@@ -60,7 +60,7 @@ extern Actor_data PLAYER_ROOM_L_actor_data[] = {
extern s16 PLAYER_ROOM_L_object_bank[] = {
ACTOR_OBJ_BANK_ROOM_SUNSHINE, // 0
ACTOR_OBJ_BANK_369, // 1
ACTOR_OBJ_BANK_HOUSE_GOKI, // 1
};
extern Door_data_c PLAYER_ROOM_L_door_data[] = {
+1 -1
View File
@@ -60,7 +60,7 @@ extern Actor_data PLAYER_ROOM_LL1_actor_data[] = {
extern s16 PLAYER_ROOM_LL1_object_bank[] = {
ACTOR_OBJ_BANK_ROOM_SUNSHINE, // 0
ACTOR_OBJ_BANK_369, // 1
ACTOR_OBJ_BANK_HOUSE_GOKI, // 1
};
extern Door_data_c PLAYER_ROOM_LL1_door_data[] = {
+1 -1
View File
@@ -60,7 +60,7 @@ extern Actor_data PLAYER_ROOM_LL2_actor_data[] = {
extern s16 PLAYER_ROOM_LL2_object_bank[] = {
ACTOR_OBJ_BANK_ROOM_SUNSHINE, // 0
ACTOR_OBJ_BANK_369, // 1
ACTOR_OBJ_BANK_HOUSE_GOKI, // 1
};
extern Door_data_c PLAYER_ROOM_LL2_door_data[] = {
+1 -1
View File
@@ -60,7 +60,7 @@ extern Actor_data PLAYER_ROOM_M_actor_data[] = {
extern s16 PLAYER_ROOM_M_object_bank[] = {
ACTOR_OBJ_BANK_ROOM_SUNSHINE, // 0
ACTOR_OBJ_BANK_369, // 1
ACTOR_OBJ_BANK_HOUSE_GOKI, // 1
};
extern Door_data_c PLAYER_ROOM_M_door_data[] = {
+1 -1
View File
@@ -60,7 +60,7 @@ extern Actor_data PLAYER_ROOM_S_actor_data[] = {
extern s16 PLAYER_ROOM_S_object_bank[] = {
ACTOR_OBJ_BANK_ROOM_SUNSHINE, // 0
ACTOR_OBJ_BANK_369, // 1
ACTOR_OBJ_BANK_HOUSE_GOKI, // 1
};
extern Door_data_c PLAYER_ROOM_S_door_data[] = {