mirror of
https://github.com/ACreTeam/ac-decomp
synced 2026-05-23 06:34:18 -04:00
282 lines
8.1 KiB
C
282 lines
8.1 KiB
C
#include "ac_set_manager.h"
|
|
#include "m_name_table.h"
|
|
#include "m_lib.h"
|
|
#include "m_field_info.h"
|
|
#include "m_player_lib.h"
|
|
#include "libultra/libultra.h"
|
|
#include "ac_set_ovl_insect.h"
|
|
#include "ac_set_ovl_gyoei.h"
|
|
|
|
/**
|
|
* @brief Gets the X & Z acre the player is currently in.
|
|
*
|
|
* @param bx Out player X-acre
|
|
* @param bz Out player Z-acre
|
|
* @return TRUE/FALSE successfully updated the acre
|
|
**/
|
|
static int aSetMgr_get_player_block(int* bx, int* bz, GAME_PLAY* play) {
|
|
int res = FALSE;
|
|
PLAYER_ACTOR* player_actor = get_player_actor_withoutCheck(play);
|
|
|
|
if (player_actor != NULL) {
|
|
res = mFI_Wpos2BlockNum(bx, bz, player_actor->actor_class.world_position);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
* @brief Gets the next X & Z acre which the player is currently transitioning into.
|
|
*
|
|
* @param next_bx Out next player X-acre
|
|
* @param next_bz Out next player Z-acre
|
|
* @return TRUE/FALSE successfully updated next acre
|
|
**/
|
|
static int aSetMgr_renewal_player_next_pos(int* next_bx, int* next_bz) {
|
|
int wade_end_pos_res;
|
|
int wpos_2_blocknum_res;
|
|
xyz_t endpos = { 0.0f, 0.0f, 0.0f };
|
|
GAME_PLAY* play = (GAME_PLAY*)gamePT;
|
|
|
|
wade_end_pos_res = get_player_actor_withoutCheck(play)->Get_WadeEndPos_proc((GAME*)play, &endpos); // maybe make this a macro like GET_PLAYER_ACTOR() ?
|
|
wpos_2_blocknum_res = mFI_Wpos2BlockNum(next_bx, next_bz, endpos);
|
|
return wpos_2_blocknum_res | wade_end_pos_res;
|
|
}
|
|
|
|
/**
|
|
* @brief Updates the set manager's internal player acre and updates the previous player acre.
|
|
*
|
|
* @param play GAME_PLAY pointer
|
|
* @param player_pos Pointer to SET_MANAGER internal player position structure
|
|
**/
|
|
static void aSetMgr_renewal_player_pos(GAME_PLAY* play, aSetMgr_player_pos_c* player_pos) {
|
|
int bx, bz;
|
|
|
|
player_pos->last_bx = player_pos->now_bx;
|
|
player_pos->last_bz = player_pos->now_bz;
|
|
|
|
if (aSetMgr_get_player_block(&bx, &bz, play) == TRUE) {
|
|
player_pos->now_bx = bx;
|
|
player_pos->now_bz = bz;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Checks if the player's wade state is 'starting'.
|
|
*
|
|
* @return TRUE when the player is beginning an acre transition, FALSE otherwise
|
|
**/
|
|
static int aSetMgr_check_player_wade_start() {
|
|
return mFI_CheckPlayerWade(mFI_WADE_START);
|
|
}
|
|
|
|
/**
|
|
* @brief Checks if the player's wade state is 'ending'.
|
|
*
|
|
* @return TRUE when the player is finishing an acre transition, FALSE otherwise
|
|
**/
|
|
static int aSetMgr_check_player_wade_end() {
|
|
return mFI_CheckPlayerWade(mFI_WADE_END);
|
|
}
|
|
|
|
/**
|
|
* @brief Clears the set overlay buffer.
|
|
*
|
|
* @param set_ovl Pointer to SET_MANAGER's internal aSetMgr_set_ovl_c overlay structure
|
|
**/
|
|
static void aSetMgr_clear_set_ovl(aSetMgr_set_ovl_c* set_ovl) {
|
|
bzero(set_ovl->buf, aSetMgr_SET_OVERLAY_BUF_SIZE);
|
|
set_ovl->ovl_proc = NULL;
|
|
}
|
|
|
|
/**
|
|
* @brief Updates the SET_MANAGER's current set overlay process.
|
|
*
|
|
* @param set_ovl Pointer to SET_MANAGER's internal aSetMgr_set_ovl_c overlay structure
|
|
* @param type The aSetMgr_OVERLAY_* type which will be executed
|
|
* @return TRUE
|
|
**/
|
|
static int aSetMgr_ovl(aSetMgr_set_ovl_c* set_ovl, int type) {
|
|
static aSetMgr_ovl_proc proc_table[aSetMgr_OVERLAY_NUM] = { &aSOI_insect_set, &aSOG_gyoei_set };
|
|
|
|
if (type < aSetMgr_OVERLAY_BEGIN || type >= aSetMgr_OVERLAY_NUM) {
|
|
type = aSetMgr_OVERLAY_BEGIN;
|
|
}
|
|
|
|
set_ovl->ovl_proc = proc_table[type];
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* @brief Clears the SET_MANAGER's "kept" data buffer.
|
|
*
|
|
* @param keep Pointer to the SET_MANAGER's internal aSetMgr_keep_c structure
|
|
**/
|
|
static void aSetMgr_clear_keep(aSetMgr_keep_c* keep) {
|
|
bzero(keep, sizeof(aSetMgr_keep_c));
|
|
}
|
|
|
|
/**
|
|
* @brief Check if the 'move' func state should be updated to 'check_wait'.
|
|
*
|
|
* This check is succeeded by the player entering an acre transition state.
|
|
*
|
|
* @param play GAME_PLAY pointer
|
|
* @param set_manager SET_MANAGER pointer
|
|
* @return TRUE when updated, FALSE otherwise
|
|
**/
|
|
static int aSetMgr_move_check_set(GAME_PLAY* play, SET_MANAGER* set_manager) {
|
|
int wading = FALSE;
|
|
aSetMgr_renewal_player_pos(play, &set_manager->player_pos);
|
|
|
|
/* update the next acre position if player is starting acre transition state */
|
|
if (aSetMgr_check_player_wade_start() == TRUE) {
|
|
aSetMgr_renewal_player_next_pos(&set_manager->player_pos.next_bx, &set_manager->player_pos.next_bz);
|
|
set_manager->next_move_proc = aSetMgr_MOVE_move_check_wait;
|
|
wading = TRUE;
|
|
}
|
|
|
|
return wading;
|
|
}
|
|
|
|
typedef int (*aSetMgr_move_proc)(GAME_PLAY*, SET_MANAGER*);
|
|
|
|
/**
|
|
* @brief Checks whether or not to update the move proc to 'set'.
|
|
*
|
|
* The SET_MANAGER's internal wait timer must be zero to pass this check.
|
|
*
|
|
* @param play GAME_PLAY pointer
|
|
* @param set_manager SET_MANAGER pointer
|
|
* @return TRUE when updated, FALSE otherwise
|
|
**/
|
|
static int aSetMgr_move_check_wait(GAME_PLAY* play, SET_MANAGER* set_manager) {
|
|
int wait_timer;
|
|
int res = FALSE;
|
|
|
|
if (set_manager->next_move_proc == aSetMgr_MOVE_move_check_wait) {
|
|
if (set_manager->wait_timer == 0) {
|
|
wait_timer = 0;
|
|
}
|
|
else {
|
|
wait_timer = --set_manager->wait_timer;
|
|
}
|
|
|
|
if (wait_timer == 0) {
|
|
set_manager->next_move_proc = aSetMgr_MOVE_move_set;
|
|
set_manager->wait_timer = aSetMgr_WAIT_TIME;
|
|
res = TRUE;
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
* @brief Processes SET_MANAGER's overlay actors & checks whether to update move func state.
|
|
*
|
|
* All SET_MANAGER overlay processes must have been executed OR the player must
|
|
* finish transitioning between acres for this check to pass.
|
|
*
|
|
* @param play GAME_PLAY pointer
|
|
* @param set_manager SET_MANAGER pointer
|
|
* @return TRUE when updated, FALSE otherwise
|
|
**/
|
|
static int aSetMgr_move_set(GAME_PLAY* play, SET_MANAGER* set_manager) {
|
|
int res = FALSE;
|
|
|
|
if (aSetMgr_ovl(&set_manager->set_overlay, set_manager->set_ovl_type) == TRUE &&
|
|
set_manager->set_overlay.ovl_proc != NULL) {
|
|
set_manager->set_overlay.ovl_proc(set_manager, play);
|
|
set_manager->set_ovl_type++;
|
|
}
|
|
else {
|
|
set_manager->set_ovl_type++;
|
|
}
|
|
|
|
if (set_manager->set_ovl_type >= aSetMgr_OVERLAY_NUM) {
|
|
set_manager->next_move_proc = aSetMgr_MOVE_move_check_set;
|
|
set_manager->set_ovl_type = aSetMgr_OVERLAY_BEGIN;
|
|
res = TRUE;
|
|
}
|
|
|
|
if (aSetMgr_check_player_wade_end() == TRUE) {
|
|
set_manager->next_move_proc = aSetMgr_MOVE_move_check_set;
|
|
set_manager->set_ovl_type = aSetMgr_OVERLAY_BEGIN;
|
|
res = TRUE;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
* @brief SET_MANAGER move process.
|
|
*
|
|
* @param actor Pointer to the SET_MANAGER actor
|
|
* @param game GAME pointer
|
|
**/
|
|
static void aSetMgr_move(ACTOR* actor, GAME* game) {
|
|
static aSetMgr_move_proc move[aSetMgr_MOVE_PROC_NUM] = {
|
|
&aSetMgr_move_check_set,
|
|
&aSetMgr_move_check_wait,
|
|
&aSetMgr_move_set
|
|
};
|
|
|
|
SET_MANAGER* set_manager = (SET_MANAGER*)actor;
|
|
GAME_PLAY* play = (GAME_PLAY*)game;
|
|
|
|
if ((*move[set_manager->move_proc])(play, set_manager) == TRUE) {
|
|
set_manager->move_proc = set_manager->next_move_proc;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief SET_MANAGER constructor.
|
|
*
|
|
* @param actor Pointer to the SET_MANAGER actor
|
|
* @param game GAME pointer
|
|
**/
|
|
static void aSetMgr_ct(ACTOR* actor, GAME* game) {
|
|
SET_MANAGER* set_manager = (SET_MANAGER*)actor;
|
|
GAME_PLAY* play = (GAME_PLAY*)game;
|
|
|
|
set_manager->move_proc = aSetMgr_MOVE_move_check_set;
|
|
set_manager->next_move_proc = aSetMgr_MOVE_move_check_set;
|
|
set_manager->set_ovl_type = aSetMgr_OVERLAY_BEGIN;
|
|
|
|
aSetMgr_clear_set_ovl(&set_manager->set_overlay);
|
|
|
|
set_manager->player_pos.next_bx = 0;
|
|
set_manager->player_pos.next_bz = 0;
|
|
set_manager->player_pos.now_bx = 0;
|
|
set_manager->player_pos.now_bz = 0;
|
|
set_manager->player_pos.last_bx = 0;
|
|
set_manager->player_pos.last_bz = 0;
|
|
|
|
set_manager->wait_timer = aSetMgr_WAIT_TIME;
|
|
|
|
aSetMgr_clear_keep(&set_manager->keep);
|
|
}
|
|
|
|
/**
|
|
* @brief SET_MANAGER destructor.
|
|
*
|
|
* @param actor Pointer to the SET_MANAGER actor
|
|
* @param game GAME pointer
|
|
**/
|
|
static void aSetMgr_dt(ACTOR* actor, GAME* game) { }
|
|
|
|
/* actor profile for SET_MANAGER */
|
|
ACTOR_PROFILE Set_Manager_Profile = {
|
|
0x72, /* TODO: replace with enum */
|
|
ACTOR_PART_CONTROL, /* control actor type */
|
|
ACTOR_STATE_NO_MOVE_WHILE_CULLED | ACTOR_STATE_NO_DRAW_WHILE_CULLED | ACTOR_STATE_CAN_MOVE_IN_DEMO_SCENES,
|
|
EMPTY_NO,
|
|
ACTOR_OBJ_BANK_3,
|
|
sizeof(SET_MANAGER),
|
|
aSetMgr_ct,
|
|
aSetMgr_dt,
|
|
aSetMgr_move,
|
|
mActor_NONE_PROC1,
|
|
NULL
|
|
};
|