mirror of
https://github.com/ACreTeam/ac-decomp
synced 2026-05-23 06:34:18 -04:00
1035 lines
29 KiB
C
1035 lines
29 KiB
C
#include "m_actor.h"
|
|
|
|
#include "m_play.h"
|
|
#include "m_player_lib.h"
|
|
#include "m_name_table.h"
|
|
#include "ac_npc.h"
|
|
#include "m_scene.h"
|
|
#include "m_lib.h"
|
|
#include "m_bg_item.h"
|
|
#include "m_lights.h"
|
|
#include "m_collision_obj.h"
|
|
#include "libforest/gbi_extensions.h"
|
|
#include "sys_matrix.h"
|
|
#include "libultra/libultra.h"
|
|
#include "m_field_info.h"
|
|
#include "m_event.h"
|
|
#include "m_skin_matrix.h"
|
|
#include "m_npc.h"
|
|
#include "m_malloc.h"
|
|
#include "m_common_data.h"
|
|
|
|
#ifdef MUST_MATCH
|
|
#include "ppcdis.h"
|
|
|
|
void _savefpr_29();
|
|
void _restfpr_29();
|
|
//#include "orderstrings/8064d600_8064d604.inc"
|
|
static char lbl_8064d600[] = "";
|
|
#endif
|
|
|
|
#ifdef MUST_MATCH
|
|
/* @unused | necessary for proper float ordering*/
|
|
extern void __declspec(section "forcestrip") projection_pos_set(GAME_PLAY* play, xyz_t* pos, xyz_t* proj_pos, f32* proj_w) {
|
|
Skin_Matrix_PrjMulVector(&play->projection_matrix, pos, proj_pos, proj_w);
|
|
*proj_w = *proj_w < 1.0f ? 1.0f : 1.0f / *proj_w;
|
|
}
|
|
#endif
|
|
|
|
extern void Actor_world_to_eye(ACTOR* actor, f32 eye_height) {
|
|
/* Update position */
|
|
actor->eye.position.x = actor->world.position.x;
|
|
actor->eye.position.y = actor->world.position.y + eye_height;
|
|
actor->eye.position.z = actor->world.position.z;
|
|
|
|
/* Update rotation */
|
|
actor->eye.angle.x = actor->world.angle.x;
|
|
actor->eye.angle.y = actor->world.angle.y;
|
|
actor->eye.angle.z = actor->world.angle.z;
|
|
}
|
|
|
|
extern void Actor_position_move(ACTOR* actor) {
|
|
(*((GAME_PLAY*)gamePT)->kankyo.nature.proc)(actor);
|
|
|
|
/* divide by 2 because of 30fps -> 60fps? */
|
|
actor->world.position.x += 0.5f * actor->position_speed.x + actor->status_data.collision_vec.x;
|
|
actor->world.position.y += 0.5f * actor->position_speed.y + actor->status_data.collision_vec.y;
|
|
actor->world.position.z += 0.5f * actor->position_speed.z + actor->status_data.collision_vec.z;
|
|
}
|
|
|
|
extern void Actor_position_speed_set(ACTOR* actor) {
|
|
actor->position_speed.x = actor->speed * sin_s(actor->world.angle.y);
|
|
actor->position_speed.z = actor->speed * cos_s(actor->world.angle.y);
|
|
|
|
/* divide by 2 because of 30fps -> 60fps? */
|
|
chase_f(&actor->position_speed.y, actor->max_velocity_y, 0.5f * actor->gravity);
|
|
}
|
|
|
|
extern void Actor_position_moveF(ACTOR* actor) {
|
|
Actor_position_speed_set(actor);
|
|
Actor_position_move(actor);
|
|
}
|
|
|
|
extern int Actor_player_look_direction_check(ACTOR* actor, s16 angle, GAME_PLAY* play) {
|
|
s16 player_rot_y = get_player_actor_withoutCheck(play)->actor_class.shape_info.rotation.y;
|
|
s16 inv_angle = actor->player_angle_y - -0x8000;
|
|
s16 diff = inv_angle - player_rot_y;
|
|
int delta = ABS(diff);
|
|
|
|
return delta < angle;
|
|
}
|
|
|
|
/* @unused ? Actor_display_position_set(... ?) */
|
|
|
|
static int Actor_data_bank_dma_end_check(ACTOR* actor, GAME_PLAY* play) {
|
|
switch (ITEM_NAME_GET_TYPE(actor->npc_id)) {
|
|
case NAME_TYPE_SPNPC:
|
|
case NAME_TYPE_NPC:
|
|
return TRUE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
extern void Shape_Info_init(ACTOR* actor, f32 ofs_y, mActor_shadow_proc shadow_proc, f32 shadow_size_x, f32 shadow_size_z) {
|
|
actor->shape_info.ofs_y = ofs_y;
|
|
actor->shape_info.shadow_proc = shadow_proc;
|
|
actor->shape_info.shadow_size_x = shadow_size_x;
|
|
actor->shape_info.shadow_size_z = shadow_size_z;
|
|
actor->shape_info.draw_shadow = TRUE;
|
|
actor->shape_info.shadow_position = &actor->world.position;
|
|
actor->shape_info.unk_20 = 0;
|
|
actor->shape_info.shadow_size_change_rate = 1.0f;
|
|
actor->shape_info.shadow_alpha_change_rate = 1.0f;
|
|
actor->shape_info.force_shadow_position = FALSE;
|
|
|
|
#ifndef BUGFIXES
|
|
actor->shape_info.shadow_position = &actor->world.position; // ???
|
|
#endif
|
|
|
|
actor->shape_info.unk_28 = -1;
|
|
actor->shape_info.unk_2D = 0;
|
|
}
|
|
|
|
extern void Actor_delete(ACTOR* actor) {
|
|
if (actor == NULL) {
|
|
return;
|
|
}
|
|
|
|
actor->mv_proc = NULL;
|
|
actor->dw_proc = NULL;
|
|
}
|
|
|
|
static void Actor_ct(ACTOR* actor, GAME* game) {
|
|
GAME_PLAY* play = (GAME_PLAY*)game;
|
|
Object_Exchange_c* exchange;
|
|
Object_Bank_c* bank;
|
|
|
|
exchange = &play->object_exchange;
|
|
bank = &exchange->banks[actor->data_bank_id];
|
|
|
|
bank->num_exist++;
|
|
if (actor->part == ACTOR_PART_NPC) {
|
|
NPC_ACTOR* npc_actor = (NPC_ACTOR*)actor;
|
|
aNPC_draw_data_c draw_data;
|
|
int tex_bank_id;
|
|
|
|
(*Common_Get(clip).npc_clip->dma_draw_data_proc)(&draw_data, actor->npc_id);
|
|
tex_bank_id = mSc_bank_regist_check(exchange, draw_data.texture_bank);
|
|
npc_actor->draw.texture_bank_idx = tex_bank_id;
|
|
|
|
bank = &exchange->banks[tex_bank_id];
|
|
bank->num_exist++;
|
|
}
|
|
|
|
/* Initialize world position & rotation to home position & rotation */
|
|
actor->world = actor->home;
|
|
actor->shape_info.rotation = actor->world.angle;
|
|
Actor_world_to_eye(actor, 0.0f);
|
|
xyz_t_move(&actor->last_world_position, &actor->world.position);
|
|
|
|
actor->scale.x = 0.01f;
|
|
actor->scale.y = 0.01f;
|
|
actor->scale.z = 0.01f;
|
|
actor->max_velocity_y = -20.0f;
|
|
actor->player_distance = 3.4028235E+38;
|
|
actor->cull_width = 350.0f;
|
|
actor->cull_height = 700.0f;
|
|
actor->cull_distance = 1000.0f;
|
|
actor->cull_radius = 350.0f;
|
|
actor->talk_distance = 55.0f;
|
|
actor->shape_info.shadow_size_change_rate = 1.0f;
|
|
actor->shape_info.shadow_alpha_change_rate = 1.0f;
|
|
CollisionCheck_Status_ct(&actor->status_data);
|
|
Shape_Info_init(actor, 0.0f, NULL, 0.0f, 0.0f);
|
|
|
|
if (Actor_data_bank_dma_end_check(actor, play) == TRUE) {
|
|
(*actor->ct_proc)(actor, game);
|
|
actor->ct_proc = NULL;
|
|
}
|
|
}
|
|
|
|
static void Actor_dt(ACTOR* actor, GAME* game) {
|
|
GAME_PLAY* play = (GAME_PLAY*)game;
|
|
Object_Exchange_c* exchange;
|
|
ACTOR* t;
|
|
|
|
if (actor->sv_proc != NULL) {
|
|
(*actor->sv_proc)(actor, game);
|
|
actor->sv_proc = NULL;
|
|
}
|
|
|
|
if (actor->dt_proc != NULL) {
|
|
(*actor->dt_proc)(actor, game);
|
|
actor->dt_proc = NULL;
|
|
}
|
|
|
|
t = actor->child_actor;
|
|
if (t != NULL && t->parent_actor == actor) {
|
|
t->parent_actor = NULL;
|
|
}
|
|
|
|
t = actor->parent_actor;
|
|
if (t != NULL && t->child_actor == actor) {
|
|
t->child_actor = NULL;
|
|
}
|
|
|
|
exchange = &play->object_exchange;
|
|
if (ITEM_NAME_GET_TYPE(actor->npc_id) >= NAME_TYPE_PAD15 || ITEM_NAME_GET_TYPE(actor->npc_id) < NAME_TYPE_SPNPC) {
|
|
int bank_id = actor->data_bank_id;
|
|
|
|
if (bank_id >= exchange->exchange_id && exchange->banks[bank_id].num_exist > 0) {
|
|
actor->data_bank_id = -1;
|
|
exchange->banks[bank_id].num_exist--;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void Actor_draw_ta_set(ACTOR* actor, GAME_PLAY* play) {
|
|
GRAPH* g;
|
|
|
|
if ((actor->state_bitfield & ACTOR_STATE_TA_SET) == 0) {
|
|
return;
|
|
}
|
|
|
|
g = play->game.graph;
|
|
OPEN_DISP(g);
|
|
|
|
gDPSetTextureAdjustMode(NOW_POLY_OPA_DISP++, G_TA_DOLPHIN);
|
|
gDPSetTextureAdjustMode(NOW_SHADOW_DISP++, G_TA_DOLPHIN);
|
|
gDPSetTextureAdjustMode(NOW_POLY_XLU_DISP++, G_TA_DOLPHIN);
|
|
|
|
gDPSetTexEdgeAlpha(NOW_POLY_OPA_DISP++, 127);
|
|
gDPSetTexEdgeAlpha(NOW_SHADOW_DISP++, 127);
|
|
gDPSetTexEdgeAlpha(NOW_POLY_XLU_DISP++, 127);
|
|
|
|
CLOSE_DISP(g);
|
|
}
|
|
|
|
static void Actor_draw_ta_clr(ACTOR* actor, GAME_PLAY* play) {
|
|
GRAPH* g;
|
|
|
|
if ((actor->state_bitfield & ACTOR_STATE_TA_SET) == 0) {
|
|
return;
|
|
}
|
|
|
|
g = play->game.graph;
|
|
OPEN_DISP(g);
|
|
|
|
gDPSetTextureAdjustMode(NOW_POLY_OPA_DISP++, G_TA_N64);
|
|
gDPSetTextureAdjustMode(NOW_SHADOW_DISP++, G_TA_N64);
|
|
gDPSetTextureAdjustMode(NOW_POLY_XLU_DISP++, G_TA_N64);
|
|
|
|
gDPSetTexEdgeAlpha(NOW_POLY_OPA_DISP++, 144);
|
|
gDPSetTexEdgeAlpha(NOW_SHADOW_DISP++, 144);
|
|
gDPSetTexEdgeAlpha(NOW_POLY_XLU_DISP++, 144);
|
|
|
|
CLOSE_DISP(g);
|
|
}
|
|
|
|
static void Actor_draw(GAME_PLAY* play, ACTOR* actor) {
|
|
LightsN* lights = Global_light_read(&play->global_light, play->game.graph);
|
|
|
|
/* Light actor */
|
|
LightsN_list_check(lights, play->global_light.list, (actor->state_bitfield & ACTOR_STATE_LIGHTING) ? NULL : &actor->world.position);
|
|
LightsN_disp(lights, play->game.graph);
|
|
LightsN_disp_BG(lights, play->game.graph);
|
|
|
|
/* Load actor position/scale matrix */
|
|
Matrix_softcv3_load(&actor->shape_info.rotation, actor->world.position.x, actor->world.position.y + actor->shape_info.ofs_y * actor->scale.y, actor->world.position.z);
|
|
Matrix_scale(actor->scale.x, actor->scale.y, actor->scale.z, 1);
|
|
|
|
/* Draw actor */
|
|
Actor_draw_ta_set(actor, play);
|
|
(*actor->dw_proc)(actor, &play->game);
|
|
Actor_draw_ta_clr(actor, play);
|
|
|
|
/* Draw shadow */
|
|
if (actor->shape_info.shadow_proc != NULL) {
|
|
(*actor->shape_info.shadow_proc)(actor, lights, play);
|
|
}
|
|
}
|
|
|
|
extern int Actor_draw_actor_no_culling_check(ACTOR* actor) {
|
|
return Actor_draw_actor_no_culling_check2(actor, &actor->camera_position, actor->camera_w);
|
|
}
|
|
|
|
extern int Actor_draw_actor_no_culling_check2(ACTOR* actor, xyz_t* camera_pos, f32 camera_w) {
|
|
int res = FALSE;
|
|
|
|
if (-actor->cull_radius < camera_pos->z && camera_pos->z < actor->cull_distance + actor->cull_radius) {
|
|
f32 m = camera_w < 1.0f ? 1.0f : 1.0f / camera_w;
|
|
|
|
if ((m * (fabsf(camera_pos->x) - actor->cull_width)) < 1.0f &&
|
|
(m * (camera_pos->y + actor->cull_height)) > -1.0f &&
|
|
(m * (camera_pos->y - actor->cull_radius) < 1.0f)
|
|
) {
|
|
res = TRUE;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static void Actor_cull_check(ACTOR* actor) {
|
|
if (Actor_draw_actor_no_culling_check(actor) == TRUE) {
|
|
actor->state_bitfield |= ACTOR_STATE_NO_CULL;
|
|
}
|
|
else {
|
|
actor->state_bitfield &= ~ACTOR_STATE_NO_CULL;
|
|
}
|
|
}
|
|
|
|
static void Actor_delete_check(ACTOR* actor, GAME* game) {
|
|
GAME_PLAY* play = (GAME_PLAY*)game;
|
|
|
|
if ((actor->state_bitfield & (ACTOR_STATE_NO_MOVE_WHILE_CULLED | ACTOR_STATE_NO_DRAW_WHILE_CULLED | ACTOR_STATE_NO_CULL)) == 0) {
|
|
if (actor->npc_id != EMPTY_NO) {
|
|
if (actor->block_x >= 0 && actor->block_z >= 0) {
|
|
if (actor->block_x != play->block_table.block_x || actor->block_z != play->block_table.block_z) {
|
|
Actor_delete(actor);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
extern void Actor_info_ct(GAME* game, Actor_info* actor_info, Actor_data* player_data) {
|
|
GAME_PLAY* play = (GAME_PLAY*)game;
|
|
ACTOR* player_actor;
|
|
ACTOR_DLFTBL* dlftbl;
|
|
int i;
|
|
|
|
bzero(actor_info, sizeof(Actor_info));
|
|
actor_dlftbls_init();
|
|
|
|
Matrix_copy_MtxF(&play->billboard_matrix, &MtxF_clear);
|
|
Matrix_copy_MtxF(&play->projection_matrix, &MtxF_clear);
|
|
|
|
/* Reset the actor dlf table info */
|
|
dlftbl = actor_dlftbls;
|
|
for (i = 0; i < mAc_PROFILE_NUM; i++) {
|
|
dlftbl->alloc_buf = NULL;
|
|
dlftbl->num_actors = 0;
|
|
dlftbl++;
|
|
}
|
|
|
|
if (mEv_CheckFirstJob() == TRUE) {
|
|
Common_Set(demo_profiles[0], mAc_PROFILE_INTRO_DEMO); // force intro demo to spawn
|
|
}
|
|
|
|
/* Spawn any demo actors */
|
|
for (i = 0; i < 2; i++) {
|
|
s16 demo_profile = Common_Get(demo_profiles[i]);
|
|
|
|
if (demo_profile != mAc_PROFILE_NUM) {
|
|
Actor_info_make_actor(
|
|
actor_info,
|
|
game,
|
|
demo_profile,
|
|
0.0f, 0.0f, 0.0f,
|
|
0, 0, 0,
|
|
-1, -1,
|
|
-1,
|
|
EMPTY_NO,
|
|
-1,
|
|
-1,
|
|
-1
|
|
);
|
|
}
|
|
|
|
Common_Set(demo_profiles[i], mAc_PROFILE_NUM);
|
|
}
|
|
|
|
/* Try spawning the player actor */
|
|
player_actor = Actor_info_make_actor(
|
|
actor_info,
|
|
game,
|
|
player_data->profile,
|
|
player_data->position.x, player_data->position.y, player_data->position.z,
|
|
player_data->rotation.x, player_data->rotation.y, player_data->rotation.z,
|
|
-1, -1,
|
|
-1,
|
|
EMPTY_NO,
|
|
player_data->arg,
|
|
-1,
|
|
-1
|
|
);
|
|
|
|
if (player_actor != NULL) {
|
|
player_actor->world.position.y = mCoBG_GetBgY_OnlyCenter_FromWpos2(player_actor->world.position, 0.0f);
|
|
mFI_SetBearActor(play, player_actor->world.position, FALSE);
|
|
}
|
|
|
|
/* Spawn the current bg item type actor */
|
|
if (Common_Get(bg_item_profile) != 0) {
|
|
Actor_info_make_actor(
|
|
actor_info,
|
|
game,
|
|
Common_Get(bg_item_profile),
|
|
0.0f, 0.0f, 0.0f,
|
|
0, 0, 0,
|
|
-1, -1,
|
|
-1,
|
|
EMPTY_NO,
|
|
-1,
|
|
-1,
|
|
-1
|
|
);
|
|
}
|
|
|
|
/* Spawn all pending control actors */
|
|
if (play->ctrl_actor_data_num != 0) {
|
|
s16* ctrl_actor_data = play->ctrl_actor_data;
|
|
for (i = 0; i < play->ctrl_actor_data_num; i++) {
|
|
Actor_info_make_actor(
|
|
&play->actor_info,
|
|
game,
|
|
*ctrl_actor_data,
|
|
0.0f, 0.0f, 0.0f,
|
|
0, 0, 0,
|
|
-1, -1,
|
|
-1,
|
|
EMPTY_NO,
|
|
-1,
|
|
-1,
|
|
-1
|
|
);
|
|
|
|
ctrl_actor_data++;
|
|
}
|
|
|
|
play->ctrl_actor_data_num = 0;
|
|
}
|
|
|
|
mSc_regist_initial_exchange_bank(play);
|
|
|
|
/* Spawn all pending actors */
|
|
if (play->actor_data_num != 0) {
|
|
Actor_data* actor_data = play->actor_data;
|
|
for (i = 0; i < play->actor_data_num; i++) {
|
|
|
|
Actor_info_make_actor(
|
|
&play->actor_info,
|
|
(GAME*)play,
|
|
actor_data->profile,
|
|
actor_data->position.x, actor_data->position.y, actor_data->position.z,
|
|
actor_data->rotation.x, actor_data->rotation.y, actor_data->rotation.z,
|
|
-1, -1,
|
|
-1,
|
|
EMPTY_NO,
|
|
actor_data->arg,
|
|
-1,
|
|
-1
|
|
);
|
|
|
|
actor_data++;
|
|
}
|
|
|
|
play->actor_data_num = 0;
|
|
}
|
|
}
|
|
|
|
extern void Actor_info_dt(Actor_info* actor_info, GAME_PLAY* play) {
|
|
int i;
|
|
|
|
for (i = 0; i < ACTOR_PART_NUM; i++) {
|
|
ACTOR* actor;
|
|
|
|
while (actor = actor_info->list[i].actor, actor != NULL) {
|
|
Actor_info_delete(actor_info, actor, (GAME*)play);
|
|
}
|
|
}
|
|
|
|
actor_dlftbls_cleanup();
|
|
}
|
|
|
|
extern void Actor_info_call_actor(GAME_PLAY* play, Actor_info* actor_info) {
|
|
//GAME* game = (GAME*)play;
|
|
PLAYER_ACTOR* player_actor = get_player_actor_withoutCheck(play);
|
|
ACTOR* actor;
|
|
int i;
|
|
|
|
mFI_FieldMove(player_actor->actor_class.world.position);
|
|
mBI_move(play);
|
|
|
|
for (i = 0; i < ACTOR_PART_NUM; i++) {
|
|
ACTOR* next;
|
|
actor = actor_info->list[i].actor;
|
|
|
|
while (actor != NULL) {
|
|
play->game.doing_point = actor->id;
|
|
play->game.doing_point_specific = 151;
|
|
|
|
if (actor->world.position.y < -25000.0f) {
|
|
actor->world.position.y = -25000.0f;
|
|
}
|
|
|
|
if (actor->ct_proc != NULL) {
|
|
if (Actor_data_bank_dma_end_check(actor, play) == TRUE) {
|
|
play->game.doing_point_specific = 152;
|
|
(*actor->ct_proc)(actor, (GAME*)play);
|
|
play->game.doing_point_specific = 153;
|
|
actor->ct_proc = NULL;
|
|
}
|
|
|
|
next = actor->next_actor;
|
|
}
|
|
else {
|
|
if (Actor_data_bank_dma_end_check(actor, play) == FALSE) {
|
|
play->game.doing_point_specific = 154;
|
|
Actor_delete(actor);
|
|
play->game.doing_point_specific = 155;
|
|
next = actor->next_actor;
|
|
}
|
|
else if (actor->mv_proc == NULL) {
|
|
if (actor->drawn == FALSE) {
|
|
play->game.doing_point_specific = 156;
|
|
next = Actor_info_delete(&play->actor_info, actor, (GAME*)play);
|
|
play->game.doing_point_specific = 157;
|
|
}
|
|
else {
|
|
play->game.doing_point_specific = 158;
|
|
Actor_dt(actor, (GAME*)play);
|
|
play->game.doing_point_specific = 159;
|
|
next = actor->next_actor;
|
|
}
|
|
}
|
|
else {
|
|
play->game.doing_point_specific = 160;
|
|
xyz_t_move(&actor->last_world_position, &actor->world.position);
|
|
actor->player_distance_xz = search_position_distanceXZ(&actor->world.position, &player_actor->actor_class.world.position);
|
|
actor->player_distance_y = player_actor->actor_class.world.position.y - actor->world.position.y;
|
|
actor->player_distance = actor->player_distance_xz * actor->player_distance_xz + actor->player_distance_y * actor->player_distance_y;
|
|
actor->player_angle_y = search_position_angleY(&actor->world.position, &player_actor->actor_class.world.position);
|
|
actor->state_bitfield &= ~ACTOR_STATE_24;
|
|
|
|
if ((actor->state_bitfield & (ACTOR_STATE_NO_MOVE_WHILE_CULLED | ACTOR_STATE_NO_CULL)) || actor->part == ACTOR_PART_NPC) {
|
|
play->game.doing_point_specific = 161;
|
|
(*actor->mv_proc)(actor, (GAME*)play);
|
|
play->game.doing_point_specific = 162;
|
|
}
|
|
|
|
CollisionCheck_Status_Clear(&actor->status_data);
|
|
next = actor->next_actor;
|
|
}
|
|
}
|
|
|
|
actor = next;
|
|
}
|
|
}
|
|
|
|
play->game.doing_point_specific = 163;
|
|
}
|
|
|
|
extern void Actor_info_draw_actor(GAME_PLAY* play, Actor_info* actor_info) {
|
|
Actor_list* list;
|
|
ACTOR* actor;
|
|
int i;
|
|
DRAW_CHK_PROC draw_chk_proc = play->draw_chk_proc;
|
|
|
|
list = actor_info->list;
|
|
for (i = 0; i < ACTOR_PART_NUM; i++) {
|
|
int do_not_draw;
|
|
|
|
for (actor = list->actor; actor != NULL; actor = actor->next_actor) {
|
|
/* Apply projection matrix to actor position */
|
|
Skin_Matrix_PrjMulVector(&play->projection_matrix, &actor->world.position, &actor->camera_position, &actor->camera_w);
|
|
|
|
Actor_cull_check(actor);
|
|
do_not_draw = (*draw_chk_proc)(actor, play);
|
|
actor->drawn = FALSE;
|
|
|
|
if (do_not_draw == FALSE && actor->ct_proc == NULL && actor->dw_proc != NULL) {
|
|
if ((actor->state_bitfield & (ACTOR_STATE_NO_DRAW_WHILE_CULLED | ACTOR_STATE_NO_CULL))) {
|
|
if ((actor->state_bitfield & ACTOR_STATE_INVISIBLE) == 0 && actor->cull_while_talking == FALSE && actor->skip_drawing == FALSE) {
|
|
Actor_draw(play, actor);
|
|
actor->drawn = TRUE;
|
|
}
|
|
}
|
|
else {
|
|
Actor_delete_check(actor, (GAME*)play);
|
|
}
|
|
}
|
|
}
|
|
|
|
list++;
|
|
}
|
|
|
|
Light_list_point_draw(play);
|
|
}
|
|
|
|
static void Actor_info_part_new(Actor_info* actor_info, ACTOR* actor, u8 part) {
|
|
ACTOR* next;
|
|
|
|
actor->part = part;
|
|
actor_info->total_num++;
|
|
actor_info->list[part].num_actors++;
|
|
|
|
next = actor_info->list[part].actor;
|
|
if (next != NULL) {
|
|
next->prev_actor = actor;
|
|
}
|
|
|
|
actor_info->list[part].actor = actor;
|
|
actor->next_actor = next;
|
|
}
|
|
|
|
static ACTOR* Actor_info_part_delete(Actor_info* actor_info, ACTOR* actor) {
|
|
ACTOR* next;
|
|
|
|
actor_info->total_num--;
|
|
actor_info->list[actor->part].num_actors--;
|
|
|
|
if (actor->prev_actor != NULL) {
|
|
actor->prev_actor->next_actor = actor->next_actor;
|
|
}
|
|
else {
|
|
actor_info->list[actor->part].actor = actor->next_actor;
|
|
}
|
|
|
|
next = actor->next_actor;
|
|
if (next != NULL) {
|
|
next->prev_actor = actor->prev_actor;
|
|
}
|
|
|
|
actor->prev_actor = NULL;
|
|
actor->next_actor = NULL;
|
|
|
|
return next;
|
|
}
|
|
|
|
extern void Actor_free_overlay_area(ACTOR_DLFTBL* dlftbl) {
|
|
if ((dlftbl->flags & 2) == 0) {
|
|
if ((dlftbl->flags & 1)) {
|
|
dlftbl->alloc_buf = NULL;
|
|
}
|
|
else {
|
|
zelda_free(dlftbl->alloc_buf);
|
|
dlftbl->alloc_buf = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void actor_free_check(ACTOR_DLFTBL* dlftbl, mActor_name_t id) {
|
|
if (dlftbl->num_actors == 0 && dlftbl->alloc_buf != NULL) {
|
|
switch (ITEM_NAME_GET_TYPE(id)) {
|
|
case NAME_TYPE_SPNPC:
|
|
case NAME_TYPE_NPC:
|
|
(*Common_Get(clip).npc_clip->free_overlay_area_proc)(dlftbl);
|
|
break;
|
|
|
|
case NAME_TYPE_STRUCT:
|
|
(*Common_Get(clip).structure_clip->free_overlay_area_proc)(dlftbl);
|
|
break;
|
|
|
|
default:
|
|
Actor_free_overlay_area(dlftbl);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
extern void Actor_get_overlay_area(ACTOR_DLFTBL* dlftbl, int unused, size_t alloc_size) {
|
|
if ((dlftbl->flags & 2)) {
|
|
dlftbl->alloc_buf = (u8*)zelda_malloc_r(alloc_size);
|
|
}
|
|
else {
|
|
dlftbl->alloc_buf = (u8*)zelda_malloc(alloc_size);
|
|
}
|
|
}
|
|
|
|
static int Actor_data_bank_regist_check_npc(int* bank_id, ACTOR_PROFILE* profile, ACTOR_DLFTBL* dlftbl, GAME* game, mActor_name_t name_id) {
|
|
return TRUE;
|
|
}
|
|
|
|
static int Actor_data_bank_regist_check(int* bank_id, ACTOR_PROFILE* profile, ACTOR_DLFTBL* dlftbl, GAME* game, mActor_name_t name_id) {
|
|
int res = TRUE;
|
|
|
|
if (*bank_id == -1) {
|
|
if (profile->part == ACTOR_PART_NPC) {
|
|
res = Actor_data_bank_regist_check_npc(bank_id, profile, dlftbl, game, name_id);
|
|
}
|
|
else {
|
|
// in DnM, this was another func call
|
|
res = TRUE;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int Actor_malloc_actor_class(ACTOR** actor_pp, ACTOR_PROFILE* profile, ACTOR_DLFTBL* dlftbl, const char* unk, mActor_name_t id) {
|
|
aNPC_draw_data_c draw_data;
|
|
|
|
switch (ITEM_NAME_GET_TYPE(id)) {
|
|
case NAME_TYPE_SPNPC:
|
|
case NAME_TYPE_NPC:
|
|
{
|
|
*actor_pp = (*Common_Get(clip).npc_clip->get_actor_area_proc)(profile->class_size, unk, 1);
|
|
(*Common_Get(clip).npc_clip->dma_draw_data_proc)(&draw_data, id); // leftover?
|
|
break;
|
|
}
|
|
|
|
case NAME_TYPE_STRUCT:
|
|
{
|
|
*actor_pp = (ACTOR*)((*Common_Get(clip).structure_clip->get_actor_area_proc)());
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
*actor_pp = (ACTOR*)zelda_malloc(profile->class_size);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (*actor_pp == NULL) {
|
|
actor_free_check(dlftbl, id);
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
extern void Actor_init_actor_class(ACTOR* actor, ACTOR_PROFILE* profile, ACTOR_DLFTBL* dlftbl, GAME_PLAY* play, int bank_idx, f32 x, f32 y, f32 z, s16 rot_x, s16 rot_y, s16 rot_z, s8 block_x, s8 block_z, s16 move_actor_list_idx, mActor_name_t name_id, s16 arg) {
|
|
mem_clear((u8*)actor, profile->class_size, 0);
|
|
actor->dlftbl = dlftbl;
|
|
actor->id = profile->id;
|
|
actor->state_bitfield = profile->initial_flags_state;
|
|
actor->data_bank_id = bank_idx;
|
|
actor->ct_proc = profile->ct_proc;
|
|
actor->dt_proc = profile->dt_proc;
|
|
actor->mv_proc = profile->mv_proc;
|
|
actor->dw_proc = profile->dw_proc;
|
|
actor->sv_proc = profile->sv_proc;
|
|
actor->actor_specific = arg;
|
|
actor->scene_id = play->scene_id;
|
|
actor->home.position.x = x;
|
|
actor->home.position.y = y;
|
|
actor->home.position.z = z;
|
|
actor->home.angle.x = rot_x;
|
|
actor->home.angle.y = rot_y;
|
|
actor->home.angle.z = rot_z;
|
|
actor->block_x = block_x;
|
|
actor->block_z = block_z;
|
|
actor->move_actor_list_idx = move_actor_list_idx;
|
|
actor->npc_id = name_id;
|
|
}
|
|
|
|
#ifndef MUST_MATCH
|
|
/* @nonmatching */
|
|
extern ACTOR* Actor_info_make_actor(Actor_info* actor_info, GAME* game, s16 profile_no, f32 x, f32 y, f32 z, s16 rot_x, s16 rot_y, s16 rot_z, s8 block_x, s8 block_z, s16 move_actor_list_idx, mActor_name_t name_id, s16 arg, s8 npc_info_idx, int data_bank_idx) {
|
|
const char* test = "";
|
|
GAME_PLAY* play = (GAME_PLAY*)game;
|
|
ACTOR* actor;
|
|
ACTOR_PROFILE* profile;
|
|
ACTOR_DLFTBL* dlftbl;
|
|
|
|
test = ""; // removing this line helps a bit...
|
|
|
|
dlftbl = &actor_dlftbls[profile_no];
|
|
|
|
if (actor_info->total_num > mAc_MAX_ACTORS) {
|
|
return NULL;
|
|
}
|
|
|
|
profile = dlftbl->profile;
|
|
if (Actor_data_bank_regist_check(&data_bank_idx, profile, dlftbl, game, name_id) == FALSE) {
|
|
return NULL;
|
|
}
|
|
|
|
if (Actor_malloc_actor_class(&actor, profile, dlftbl, test, name_id) == FALSE) {
|
|
return NULL;
|
|
}
|
|
|
|
dlftbl->num_actors++;
|
|
Actor_init_actor_class(actor, profile, dlftbl, play, data_bank_idx, x, y, z, rot_x, rot_y, rot_z, block_x, block_z, move_actor_list_idx, name_id, arg);
|
|
Actor_info_part_new(actor_info, actor, profile->part);
|
|
mNpc_SetNpcinfo(actor, npc_info_idx);
|
|
Actor_ct(actor, (GAME*)play);
|
|
|
|
return actor;
|
|
}
|
|
#else
|
|
extern asm ACTOR* Actor_info_make_actor(Actor_info* actor_info, GAME* game, s16 profile_no, f32 x, f32 y, f32 z, s16 rot_x, s16 rot_y, s16 rot_z, s8 block_x, s8 block_z, s16 move_actor_list_idx, mActor_name_t name_id, s16 arg, s8 npc_info_idx, int data_bank_idx) {
|
|
#include "asm/80375830.s"
|
|
}
|
|
#endif
|
|
|
|
extern ACTOR* Actor_info_make_child_actor(Actor_info* actor_info, ACTOR* parent_actor, GAME* game, s16 profile, f32 x, f32 y, f32 z, s16 rot_x, s16 rot_y, s16 rot_z, s16 move_actor_list_idx, mActor_name_t name_id, s16 arg, int data_bank_idx) {
|
|
ACTOR* actor = Actor_info_make_actor(actor_info, game, profile, x, y, z, rot_x, rot_y, rot_z, -1, -1, move_actor_list_idx, name_id, arg, -1, data_bank_idx);
|
|
|
|
if (actor != NULL) {
|
|
parent_actor->child_actor = actor;
|
|
actor->parent_actor = parent_actor;
|
|
}
|
|
|
|
return actor;
|
|
}
|
|
|
|
static void restore_fgdata(ACTOR* actor, GAME_PLAY* play) {
|
|
mActor_name_t name = actor->npc_id;
|
|
|
|
if (name != EMPTY_NO && actor->move_actor_list_idx == -1 && actor->block_x >= 0 && actor->block_z >= 0) {
|
|
if (ITEM_NAME_GET_TYPE(name) == NAME_TYPE_ITEM2) {
|
|
xyz_t pos;
|
|
|
|
xyz_t_move(&pos, &actor->home.position);
|
|
if (mFI_search_unit_around(&pos, EMPTY_NO) == TRUE) {
|
|
/* pos now holds the position of the empty unit */
|
|
mFI_SetFG_common(actor->npc_id, pos, FALSE); /* This causes the airplane duplication "bug" */
|
|
}
|
|
}
|
|
else {
|
|
mFI_SetFG_common(name, actor->home.position, FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
static int restore_flag[ACTOR_PART_NUM] = {
|
|
TRUE, /* FG */
|
|
TRUE, /* ITEM */
|
|
FALSE, /* PLAYER */
|
|
FALSE, /* 3 */
|
|
FALSE, /* NPC */
|
|
FALSE, /* BG */
|
|
FALSE, /* EFFECT */
|
|
FALSE /* CONTROL */
|
|
};
|
|
|
|
static void restore_fgdata_one(ACTOR* actor, GAME_PLAY* play) {
|
|
if (restore_flag[actor->part] == TRUE) {
|
|
restore_fgdata(actor, play);
|
|
}
|
|
else if (actor->restore_fg == TRUE) {
|
|
restore_fgdata(actor, play);
|
|
}
|
|
}
|
|
|
|
extern void restore_fgdata_all(GAME_PLAY* play) {
|
|
Actor_info* info;
|
|
ACTOR* actor;
|
|
int i;
|
|
|
|
info = &play->actor_info;
|
|
for (i = 0; i < ACTOR_PART_NUM; i++) {
|
|
if (restore_flag[i] == TRUE) {
|
|
for (actor = info->list[i].actor; actor != NULL; actor = actor->next_actor) {
|
|
restore_fgdata(actor, play);
|
|
}
|
|
}
|
|
else {
|
|
for (actor = info->list[i].actor; actor != NULL; actor = actor->next_actor) {
|
|
if (actor->restore_fg == TRUE) {
|
|
restore_fgdata(actor, play);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
extern void Actor_info_save_actor(GAME_PLAY* play) {
|
|
Actor_info* info;
|
|
ACTOR* actor;
|
|
int i;
|
|
|
|
info = &play->actor_info;
|
|
for (i = 0; i < ACTOR_PART_NUM; i++) {
|
|
for (actor = info->list[i].actor; actor != NULL; actor = actor->next_actor) {
|
|
if (actor->sv_proc != NULL) {
|
|
(*actor->sv_proc)(actor, (GAME*)play);
|
|
actor->sv_proc = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
restore_fgdata_all(play);
|
|
}
|
|
|
|
extern ACTOR* Actor_info_delete(Actor_info* actor_info, ACTOR* actor, GAME* game) {
|
|
mActor_name_t name_id = actor->npc_id;
|
|
ACTOR_DLFTBL* dlftbl = actor->dlftbl;
|
|
ACTOR* next_actor;
|
|
|
|
restore_fgdata_one(actor, (GAME_PLAY*)game);
|
|
Actor_dt(actor, game);
|
|
next_actor = Actor_info_part_delete(actor_info, actor);
|
|
|
|
switch (ITEM_NAME_GET_TYPE(name_id)) {
|
|
case NAME_TYPE_SPNPC:
|
|
case NAME_TYPE_NPC:
|
|
{
|
|
(*Common_Get(clip).npc_clip->free_actor_area_proc)(actor);
|
|
break;
|
|
}
|
|
|
|
case NAME_TYPE_STRUCT:
|
|
{
|
|
(*Common_Get(clip).structure_clip->free_actor_area_proc)((STRUCTURE_ACTOR*)actor);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
zelda_free(actor);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (dlftbl->ram_start == NULL) {
|
|
dlftbl->num_actors--;
|
|
}
|
|
else {
|
|
dlftbl->num_actors--;
|
|
actor_free_check(dlftbl, actor->npc_id);
|
|
}
|
|
|
|
return next_actor;
|
|
}
|
|
|
|
extern ACTOR* Actor_info_name_search_sub(ACTOR* actor, s16 name) {
|
|
while (actor != NULL) {
|
|
if (actor->id == name) {
|
|
return actor;
|
|
}
|
|
|
|
actor = actor->next_actor;
|
|
}
|
|
|
|
return actor;
|
|
}
|
|
|
|
extern ACTOR* Actor_info_name_search(Actor_info* actor_info, s16 name, int part) {
|
|
ACTOR* actor = actor_info->list[part].actor;
|
|
|
|
if (actor != NULL) {
|
|
return Actor_info_name_search_sub(actor, name);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
extern ACTOR* Actor_info_fgName_search_sub(ACTOR* actor, mActor_name_t fgName) {
|
|
while (actor != NULL) {
|
|
if (actor->npc_id == fgName) {
|
|
return actor;
|
|
}
|
|
|
|
actor = actor->next_actor;
|
|
}
|
|
|
|
return actor;
|
|
}
|
|
|
|
extern ACTOR* Actor_info_fgName_search(Actor_info* actor_info, mActor_name_t fgName, int part) {
|
|
ACTOR* actor = actor_info->list[part].actor;
|
|
|
|
if (actor != NULL) {
|
|
return Actor_info_fgName_search_sub(actor, fgName);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
extern Gfx* HiliteReflect_new(xyz_t* pos, xyz_t* eye, xyz_t* light_direction, GRAPH* graph, Gfx* gfx, Hilite** hilite) {
|
|
static Mtx work_view_matrix;
|
|
|
|
LookAt* lookat = GRAPH_ALLOC_TYPE(graph, LookAt, 1);
|
|
int pos_eye_equal = FALSE;
|
|
f32 eye_x = eye->x;
|
|
|
|
if (eye_x == pos->x && eye->z == pos->z) {
|
|
pos_eye_equal = TRUE;
|
|
}
|
|
|
|
if (pos_eye_equal) {
|
|
eye_x = 0.001f + eye_x;
|
|
}
|
|
|
|
*hilite = GRAPH_ALLOC_TYPE(graph, Hilite, 1);
|
|
guLookAtHilite(
|
|
&work_view_matrix,
|
|
lookat,
|
|
*hilite,
|
|
eye_x, eye->y, eye->z,
|
|
pos->x, pos->y, pos->z,
|
|
0.0f, 1.0f, 0.0f,
|
|
light_direction->x, light_direction->y, light_direction->z,
|
|
light_direction->x, light_direction->y, light_direction->z,
|
|
16, 16
|
|
);
|
|
|
|
gSPLookAt(gfx++, lookat);
|
|
gDPPipeSync(gfx++);
|
|
gDPSetTileSize(gfx++, 1, (*hilite)->h.x1, (*hilite)->h.y1, (*hilite)->h.x1 + 60, (*hilite)->h.y1 + 60);
|
|
|
|
return gfx;
|
|
}
|
|
|
|
extern Hilite* HiliteReflect_init(xyz_t* pos, xyz_t* eye, xyz_t* light_direction, GRAPH* graph) {
|
|
Hilite* hilite;
|
|
|
|
OPEN_DISP(graph);
|
|
|
|
SET_POLY_OPA_DISP(HiliteReflect_new(pos, eye, light_direction, graph, NOW_POLY_OPA_DISP, &hilite));
|
|
|
|
CLOSE_DISP(graph);
|
|
|
|
return hilite;
|
|
}
|
|
|
|
extern Hilite* HiliteReflect_xlu_init(xyz_t* pos, xyz_t* eye, xyz_t* light_direction, GRAPH* graph) {
|
|
Hilite* hilite;
|
|
|
|
OPEN_DISP(graph);
|
|
|
|
SET_POLY_XLU_DISP(HiliteReflect_new(pos, eye, light_direction, graph, NOW_POLY_XLU_DISP, &hilite));
|
|
|
|
CLOSE_DISP(graph);
|
|
|
|
return hilite;
|
|
}
|
|
|
|
extern void Setpos_HiliteReflect_init(xyz_t* pos, GAME_PLAY* play) {
|
|
Kankyo* kankyo = &play->kankyo;
|
|
xyz_t sun_pos;
|
|
|
|
sun_pos.x = (int)kankyo->sun_light.lights.diffuse.x;
|
|
sun_pos.y = (int)kankyo->sun_light.lights.diffuse.y;
|
|
sun_pos.z = (int)kankyo->sun_light.lights.diffuse.z;
|
|
|
|
HiliteReflect_init(pos, &play->view.eye, &sun_pos, play->game.graph);
|
|
}
|
|
|
|
extern void Setpos_HiliteReflect_xlu_init(xyz_t* pos, GAME_PLAY* play) {
|
|
Kankyo* kankyo = &play->kankyo;
|
|
xyz_t sun_pos;
|
|
|
|
sun_pos.x = (int)kankyo->sun_light.lights.diffuse.x;
|
|
sun_pos.y = (int)kankyo->sun_light.lights.diffuse.y;
|
|
sun_pos.z = (int)kankyo->sun_light.lights.diffuse.z;
|
|
|
|
HiliteReflect_xlu_init(pos, &play->view.eye, &sun_pos, play->game.graph);
|
|
}
|