mirror of
https://github.com/zeldaret/mm.git
synced 2026-05-29 16:44:37 -04:00
5f6c3df4ce
* Transition docs from OoT * Cleanup * Missed a spot
364 lines
12 KiB
C
364 lines
12 KiB
C
#include "global.h"
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_80165460.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_80165608.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_80165630.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_80165658.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_8016566C.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_80165690.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_801656A4.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_80165DB8.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_80165DCC.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_80165DF0.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_80165E04.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_80165E1C.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_80165E7C.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_80165EC0.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/D_801DFA18.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_80166060.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_801660B8.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/Play_Fini.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_801663C4.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_80166644.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_801668B4.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_80166968.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_80166B30.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_80167814.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_80167DE4.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_80167F0C.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/Play_Draw.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_80168DAC.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/Play_Update.s")
|
|
|
|
s32 Play_InCsMode(PlayState* this) {
|
|
return (this->csCtx.state != 0) || Player_InCsMode(this);
|
|
}
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_80169100.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_801691F0.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/Play_LoadScene.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_8016927C.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_801692C4.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/Play_SceneInit.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_80169474.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/Play_CreateSubCamera.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/Play_GetActiveCamId.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/Play_CameraChangeStatus.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/Play_ClearCamera.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/Play_ClearAllSubCameras.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/Play_GetCamera.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/Play_CameraSetAtEye.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/Play_CameraSetAtEyeUp.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/Play_CameraSetFov.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/Play_CameraSetRoll.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/Play_CopyCamera.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_80169A50.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/Play_CameraChangeSetting.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_80169AFC.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/Play_CameraGetUID.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_80169BF8.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/Play_GetCsCamDataSetting.s")
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/Play_GetCsCamDataVec3s.s")
|
|
|
|
/**
|
|
* Converts the number of a scene to its "original" equivalent, the default version of the area which the player first
|
|
* enters.
|
|
*/
|
|
s16 Play_GetOriginalSceneNumber(s16 sceneNum) {
|
|
// Inverted Stone Tower Temple -> Stone Tower Temple
|
|
if (sceneNum == SCENE_INISIE_R) {
|
|
return SCENE_INISIE_N;
|
|
}
|
|
|
|
// Purified Southern Swamp -> Poisoned Sothern Swamp
|
|
if (sceneNum == SCENE_20SICHITAI2) {
|
|
return SCENE_20SICHITAI;
|
|
}
|
|
|
|
// Spring Mountain Village -> Winter Mountain Village
|
|
if (sceneNum == SCENE_10YUKIYAMANOMURA2) {
|
|
return SCENE_10YUKIYAMANOMURA;
|
|
}
|
|
|
|
// Spring Goron Village -> Winter Goron Village
|
|
if (sceneNum == SCENE_11GORONNOSATO2) {
|
|
return SCENE_11GORONNOSATO;
|
|
}
|
|
|
|
// Spring Path to Goron Village -> Winter Path to Goron Village
|
|
if (sceneNum == SCENE_17SETUGEN2) {
|
|
return SCENE_17SETUGEN;
|
|
}
|
|
|
|
// Inverted Stone Tower -> Stone Tower
|
|
if (sceneNum == SCENE_F41) {
|
|
return SCENE_F40;
|
|
}
|
|
|
|
return sceneNum;
|
|
}
|
|
|
|
/**
|
|
* Copies the flags set in ActorContext over to the current scene's CycleSceneFlags, usually using the original scene
|
|
* number. Exception for Inverted Stone Tower Temple, which uses its own.
|
|
*/
|
|
void Play_SaveCycleSceneFlags(GameState* thisx) {
|
|
PlayState* this = (PlayState*)thisx;
|
|
CycleSceneFlags* cycleSceneFlags;
|
|
|
|
cycleSceneFlags = &gSaveContext.cycleSceneFlags[Play_GetOriginalSceneNumber(this->sceneNum)];
|
|
cycleSceneFlags->chest = this->actorCtx.flags.chest;
|
|
cycleSceneFlags->switch0 = this->actorCtx.flags.switches[0];
|
|
cycleSceneFlags->switch1 = this->actorCtx.flags.switches[1];
|
|
|
|
if (this->sceneNum == SCENE_INISIE_R) { // Inverted Stone Tower Temple
|
|
cycleSceneFlags = &gSaveContext.cycleSceneFlags[this->sceneNum];
|
|
}
|
|
|
|
cycleSceneFlags->collectible = this->actorCtx.flags.collectible[0];
|
|
cycleSceneFlags->clearedRoom = this->actorCtx.flags.clearedRoom;
|
|
}
|
|
|
|
void Play_SetRespawnData(GameState* thisx, s32 respawnMode, u16 entranceIndex, s32 roomIndex, s32 playerParams,
|
|
Vec3f* pos, s16 yaw) {
|
|
PlayState* this = (PlayState*)thisx;
|
|
|
|
gSaveContext.respawn[respawnMode].entranceIndex = Entrance_CreateIndex(entranceIndex >> 9, 0, entranceIndex & 0xF);
|
|
gSaveContext.respawn[respawnMode].roomIndex = roomIndex;
|
|
gSaveContext.respawn[respawnMode].pos = *pos;
|
|
gSaveContext.respawn[respawnMode].yaw = yaw;
|
|
gSaveContext.respawn[respawnMode].playerParams = playerParams;
|
|
gSaveContext.respawn[respawnMode].tempSwitchFlags = this->actorCtx.flags.switches[2];
|
|
gSaveContext.respawn[respawnMode].unk_18 = this->actorCtx.flags.collectible[1];
|
|
gSaveContext.respawn[respawnMode].tempCollectFlags = this->actorCtx.flags.collectible[2];
|
|
}
|
|
|
|
void Play_SetupRespawnPoint(GameState* thisx, s32 respawnMode, s32 playerParams) {
|
|
PlayState* this = (PlayState*)thisx;
|
|
Player* player = GET_PLAYER(this);
|
|
|
|
if (this->sceneNum != SCENE_KAKUSIANA) { // Grottos
|
|
Play_SetRespawnData(&this->state, respawnMode, (u16)((void)0, gSaveContext.save.entranceIndex),
|
|
this->roomCtx.currRoom.num, playerParams, &player->actor.world.pos,
|
|
player->actor.shape.rot.y);
|
|
}
|
|
}
|
|
|
|
// Override respawn data in Sakon's Hideout
|
|
void func_80169ECC(PlayState* this) {
|
|
if (this->sceneNum == SCENE_SECOM) {
|
|
this->nextEntranceIndex = 0x2060;
|
|
gSaveContext.respawnFlag = -7;
|
|
}
|
|
}
|
|
|
|
// Gameplay_TriggerVoidOut ?
|
|
// Used by Player, Ikana_Rotaryroom, Bji01, Kakasi, LiftNuts, Test4, Warptag, WarpUzu, Roomtimer
|
|
void func_80169EFC(GameState* thisx) {
|
|
PlayState* this = (PlayState*)thisx;
|
|
|
|
gSaveContext.respawn[RESPAWN_MODE_DOWN].tempSwitchFlags = this->actorCtx.flags.switches[2];
|
|
gSaveContext.respawn[RESPAWN_MODE_DOWN].unk_18 = this->actorCtx.flags.collectible[1];
|
|
gSaveContext.respawn[RESPAWN_MODE_DOWN].tempCollectFlags = this->actorCtx.flags.collectible[2];
|
|
this->nextEntranceIndex = gSaveContext.respawn[RESPAWN_MODE_DOWN].entranceIndex;
|
|
gSaveContext.respawnFlag = 1;
|
|
func_80169ECC(this);
|
|
this->transitionTrigger = TRANS_TRIGGER_START;
|
|
this->transitionType = TRANS_TYPE_02;
|
|
}
|
|
|
|
// Gameplay_LoadToLastEntrance ?
|
|
// Used by game_over and Test7
|
|
void func_80169F78(GameState* thisx) {
|
|
PlayState* this = (PlayState*)thisx;
|
|
|
|
this->nextEntranceIndex = gSaveContext.respawn[RESPAWN_MODE_TOP].entranceIndex;
|
|
gSaveContext.respawnFlag = -1;
|
|
func_80169ECC(this);
|
|
this->transitionTrigger = TRANS_TRIGGER_START;
|
|
this->transitionType = TRANS_TYPE_02;
|
|
}
|
|
|
|
// Gameplay_TriggerRespawn ?
|
|
// Used for void by Wallmaster, Deku Shrine doors. Also used by Player, Kaleido, DoorWarp1
|
|
void func_80169FDC(GameState* thisx) {
|
|
func_80169F78(thisx);
|
|
}
|
|
|
|
// Used by Kankyo to determine how to change the lighting, e.g. for game over.
|
|
s32 func_80169FFC(GameState* thisx) {
|
|
PlayState* this = (PlayState*)thisx;
|
|
|
|
return this->roomCtx.currRoom.mesh->type0.type != 1;
|
|
}
|
|
|
|
s32 FrameAdvance_IsEnabled(GameState* thisx) {
|
|
PlayState* this = (PlayState*)thisx;
|
|
|
|
return this->frameAdvCtx.enabled != 0;
|
|
}
|
|
|
|
// Unused, unchanged from OoT, which uses it only in one Camera function.
|
|
/**
|
|
* @brief Tests if \p actor is a door and the sides are different rooms.
|
|
*
|
|
* @param[in] thisx GameState, promoted to play inside.
|
|
* @param[in] actor Actor to test.
|
|
* @param[out] yaw Facing angle of the actor, or reverse if in the back room.
|
|
* @return true if \p actor is a door and the sides are in different rooms, false otherwise
|
|
*/
|
|
s32 func_8016A02C(GameState* thisx, Actor* actor, s16* yaw) {
|
|
PlayState* this = (PlayState*)thisx;
|
|
TransitionActorEntry* transitionActor;
|
|
s8 frontRoom;
|
|
|
|
if (actor->category != ACTORCAT_DOOR) {
|
|
return false;
|
|
}
|
|
|
|
transitionActor = &this->doorCtx.transitionActorList[(u16)actor->params >> 10];
|
|
frontRoom = transitionActor->sides[0].room;
|
|
if (frontRoom == transitionActor->sides[1].room) {
|
|
return false;
|
|
}
|
|
|
|
if (frontRoom == actor->room) {
|
|
*yaw = actor->shape.rot.y;
|
|
} else {
|
|
*yaw = actor->shape.rot.y + 0x8000;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Unused
|
|
/**
|
|
* @brief Tests if \p pos is underwater.
|
|
*
|
|
* @param[in] play PlayState
|
|
* @param[in] pos position to test
|
|
* @return true if inside a waterbox and not above a void.
|
|
*/
|
|
s32 Play_IsUnderwater(PlayState* this, Vec3f* pos) {
|
|
WaterBox* waterBox;
|
|
CollisionPoly* poly;
|
|
Vec3f waterSurfacePos;
|
|
s32 bgId;
|
|
|
|
waterSurfacePos = *pos;
|
|
|
|
if ((WaterBox_GetSurface1(this, &this->colCtx, waterSurfacePos.x, waterSurfacePos.z, &waterSurfacePos.y,
|
|
&waterBox) == true) &&
|
|
(pos->y < waterSurfacePos.y) &&
|
|
(BgCheck_EntityRaycastFloor3(&this->colCtx, &poly, &bgId, &waterSurfacePos) != BGCHECK_Y_MIN)) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
s32 Play_IsDebugCamEnabled(void) {
|
|
return gDbgCamEnabled;
|
|
}
|
|
|
|
// A mapping from playerActorCsIds to sGlobalCamDataSettings indices.
|
|
extern s16 D_801D0D64[];
|
|
// s16 D_801D0D64[] = { -3, -2, -4, -5, -7, -11, -8, -9, -6, -16 };
|
|
|
|
// Used by Player
|
|
/**
|
|
* Extract the common actor cutscene ids used by Player from the scene and set the actor cutscene ids in
|
|
* this->playerActorCsIds. If a playerActorCsId is not present in the scene, then that particular id is set
|
|
* to -1. Otherwise, if there is an ActorCutscene where csCamSceneDataId matches the appropriate element of D_801D0D64,
|
|
* set the corresponding playerActorCsId (and possibly change its priority for the zeroth one)
|
|
*/
|
|
void Play_AssignPlayerActorCsIdsFromScene(GameState* thisx, s32 startActorCsId) {
|
|
PlayState* this = (PlayState*)thisx;
|
|
s32 i;
|
|
s16* curPlayerActorCsId = this->playerActorCsIds;
|
|
s16* phi_s1 = D_801D0D64;
|
|
|
|
for (i = 0; i < ARRAY_COUNT(this->playerActorCsIds); i++, curPlayerActorCsId++, phi_s1++) {
|
|
ActorCutscene* actorCutscene;
|
|
s32 curActorCsId;
|
|
|
|
*curPlayerActorCsId = -1;
|
|
|
|
for (curActorCsId = startActorCsId; curActorCsId != -1; curActorCsId = actorCutscene->additionalCutscene) {
|
|
actorCutscene = ActorCutscene_GetCutscene(curActorCsId);
|
|
|
|
if (actorCutscene->csCamSceneDataId == *phi_s1) {
|
|
if ((actorCutscene->csCamSceneDataId == -3) &&
|
|
(actorCutscene->priority == 700)) { // override ocarina cs priority
|
|
actorCutscene->priority = 550;
|
|
}
|
|
*curPlayerActorCsId = curActorCsId;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// These regs are used by Gameplay_Draw, and several actors, purpose as yet unclear.
|
|
void func_8016A268(GameState* thisx, s16 arg1, u8 arg2, u8 arg3, u8 arg4, u8 arg5) {
|
|
MREG(64) = arg1;
|
|
MREG(65) = arg2;
|
|
MREG(66) = arg3;
|
|
MREG(67) = arg4;
|
|
MREG(68) = arg5;
|
|
}
|
|
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/Play_Init.s")
|