mirror of
https://github.com/Mr-Wiseguy/Zelda64Recomp.git
synced 2024-11-17 19:39:14 +01:00
Compare commits
2 Commits
750866145b
...
1cf6554e0e
Author | SHA1 | Date | |
---|---|---|---|
|
1cf6554e0e | ||
|
a05aac8b34 |
374
patches/better_double_sot.c
Normal file
374
patches/better_double_sot.c
Normal file
@ -0,0 +1,374 @@
|
||||
#include "patches.h"
|
||||
|
||||
void dsot_load_day_number_texture(PlayState* play, s32 day);
|
||||
void dsot_actor_fixes(PlayState* play);
|
||||
|
||||
bool dsot_used = false;
|
||||
u8 choiceHour;
|
||||
|
||||
void dsot_init_hour_selection(PlayState* play) {
|
||||
choiceHour = (u16)(TIME_TO_HOURS_F(CURRENT_TIME - 1)) + 1;
|
||||
if (choiceHour >= 24) {
|
||||
choiceHour = 0;
|
||||
}
|
||||
if (choiceHour == 6) {
|
||||
if (gSaveContext.save.day == 3) {
|
||||
choiceHour = 5;
|
||||
} else {
|
||||
dsot_load_day_number_texture(play, gSaveContext.save.day + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define TIMER_INIT 10
|
||||
#define TIMER_STEP_RESET 0
|
||||
|
||||
void dsot_handle_hour_selection(PlayState* play) {
|
||||
static s8 sAnalogStickTimer = TIMER_INIT;
|
||||
static s8 sPrevStickX = 0;
|
||||
static bool sAnalogStickHeld = false;
|
||||
Input* input = CONTROLLER1(&play->state);
|
||||
|
||||
if ((input->rel.stick_x >= 30) && !sAnalogStickHeld) {
|
||||
u8 prevHour = choiceHour;
|
||||
sAnalogStickHeld = true;
|
||||
|
||||
choiceHour++;
|
||||
if (choiceHour >= 24) {
|
||||
choiceHour = 0;
|
||||
}
|
||||
|
||||
if ((CURRENT_DAY == 3) && (prevHour <= 5) && (choiceHour > 5)) {
|
||||
choiceHour = 5;
|
||||
} else if ((prevHour <= 6) && (choiceHour > 6)) {
|
||||
choiceHour = 6;
|
||||
} else {
|
||||
Audio_PlaySfx(NA_SE_SY_CURSOR);
|
||||
}
|
||||
|
||||
if ((choiceHour == 6) && (choiceHour > prevHour)) {
|
||||
dsot_load_day_number_texture(play, gSaveContext.save.day + 1);
|
||||
}
|
||||
} else if ((input->rel.stick_x <= -30) && !sAnalogStickHeld) {
|
||||
u8 prevHour = choiceHour;
|
||||
sAnalogStickHeld = true;
|
||||
|
||||
choiceHour--;
|
||||
if (choiceHour > 24) {
|
||||
choiceHour = 23;
|
||||
}
|
||||
|
||||
if (((CLOCK_TIME(choiceHour, 0) <= CURRENT_TIME) && (CLOCK_TIME(prevHour, 0) > CURRENT_TIME)
|
||||
|| ((choiceHour > prevHour) && (CURRENT_TIME >= CLOCK_TIME(23, 0)))
|
||||
|| ((choiceHour > prevHour) && (CURRENT_TIME < CLOCK_TIME(1, 0))))) {
|
||||
choiceHour = prevHour;
|
||||
}
|
||||
else {
|
||||
Audio_PlaySfx(NA_SE_SY_CURSOR);
|
||||
}
|
||||
|
||||
if ((prevHour == 6) && (choiceHour < prevHour)) {
|
||||
dsot_load_day_number_texture(play, gSaveContext.save.day);
|
||||
}
|
||||
} else if (ABS_ALT(input->rel.stick_x) < 30) {
|
||||
sAnalogStickHeld = false;
|
||||
sAnalogStickTimer = TIMER_INIT;
|
||||
}
|
||||
|
||||
if (ABS_ALT(input->rel.stick_x) >= 30) {
|
||||
if (!DECR(sAnalogStickTimer)) {
|
||||
sAnalogStickHeld = false;
|
||||
sAnalogStickTimer = TIMER_STEP_RESET;
|
||||
}
|
||||
}
|
||||
|
||||
if (sPrevStickX * input->rel.stick_x < 0) {
|
||||
sAnalogStickHeld = false;
|
||||
sAnalogStickTimer = TIMER_INIT;
|
||||
}
|
||||
|
||||
sPrevStickX = input->rel.stick_x;
|
||||
}
|
||||
|
||||
void dsot_cancel_hour_selection(PlayState* play) {
|
||||
if (choiceHour == 6) {
|
||||
dsot_load_day_number_texture(play, gSaveContext.save.day);
|
||||
}
|
||||
}
|
||||
|
||||
void dsot_advance_hour(PlayState* play) {
|
||||
gSaveContext.save.time = CLOCK_TIME(choiceHour, 0);
|
||||
gSaveContext.skyboxTime = CURRENT_TIME;
|
||||
dsot_used = true;
|
||||
|
||||
// Instantly enable/disable rain on day 2.
|
||||
if ((CURRENT_DAY == 2) && (Environment_GetStormState(play) != STORM_STATE_OFF)) {
|
||||
if ((CURRENT_TIME >= CLOCK_TIME(8, 0)) && (CURRENT_TIME < CLOCK_TIME(18, 00))) {
|
||||
gWeatherMode = WEATHER_MODE_RAIN;
|
||||
play->envCtx.lightningState = LIGHTNING_ON;
|
||||
play->envCtx.precipitation[PRECIP_RAIN_MAX] = 60;
|
||||
play->envCtx.precipitation[PRECIP_RAIN_CUR] = 60;
|
||||
Environment_PlayStormNatureAmbience(play);
|
||||
} else {
|
||||
gWeatherMode = WEATHER_MODE_CLEAR;
|
||||
play->envCtx.lightningState = LIGHTNING_OFF;
|
||||
play->envCtx.precipitation[PRECIP_RAIN_MAX] = 0;
|
||||
play->envCtx.precipitation[PRECIP_RAIN_CUR] = 0;
|
||||
Environment_StopStormNatureAmbience(play);
|
||||
}
|
||||
}
|
||||
|
||||
// Play music/ambience.
|
||||
if ((CURRENT_TIME >= CLOCK_TIME(18, 0)) || (CURRENT_TIME <= CLOCK_TIME(6,0))) {
|
||||
SEQCMD_STOP_SEQUENCE(SEQ_PLAYER_BGM_MAIN, 0);
|
||||
} else if (CURRENT_TIME > CLOCK_TIME(17, 10)) {
|
||||
SEQCMD_STOP_SEQUENCE(SEQ_PLAYER_BGM_MAIN, 240);
|
||||
}
|
||||
|
||||
play->envCtx.timeSeqState = TIMESEQ_NIGHT_BEGIN_SFX;
|
||||
|
||||
if ((CURRENT_TIME >= CLOCK_TIME(18, 0)) || (CURRENT_TIME <= CLOCK_TIME(6, 0))) {
|
||||
Audio_PlayAmbience(play->sequenceCtx.ambienceId);
|
||||
Audio_SetAmbienceChannelIO(AMBIENCE_CHANNEL_CRITTER_0, 1, 1);
|
||||
play->envCtx.timeSeqState = TIMESEQ_NIGHT_DELAY;
|
||||
}
|
||||
|
||||
if ((CURRENT_TIME >= CLOCK_TIME(19, 0)) || (CURRENT_TIME <= CLOCK_TIME(6, 0))) {
|
||||
Audio_SetAmbienceChannelIO(AMBIENCE_CHANNEL_CRITTER_0, 1, 0);
|
||||
Audio_SetAmbienceChannelIO(AMBIENCE_CHANNEL_CRITTER_1 << 4 | AMBIENCE_CHANNEL_CRITTER_3, 1, 1);
|
||||
play->envCtx.timeSeqState = TIMESEQ_DAY_BEGIN_SFX;
|
||||
}
|
||||
|
||||
if ((CURRENT_TIME >= CLOCK_TIME(5, 0)) && (CURRENT_TIME <= CLOCK_TIME(6, 0))) {
|
||||
Audio_SetAmbienceChannelIO(AMBIENCE_CHANNEL_CRITTER_1 << 4 | AMBIENCE_CHANNEL_CRITTER_3, 1, 0);
|
||||
Audio_SetAmbienceChannelIO(AMBIENCE_CHANNEL_CRITTER_4 << 4 | AMBIENCE_CHANNEL_CRITTER_5, 1, 1);
|
||||
play->envCtx.timeSeqState = TIMESEQ_DAY_DELAY;
|
||||
}
|
||||
|
||||
dsot_actor_fixes(play);
|
||||
}
|
||||
|
||||
// Loads day number texture from week_static for the three-day clock
|
||||
void dsot_load_day_number_texture(PlayState* play, s32 day) {
|
||||
s16 i = day - 1;
|
||||
|
||||
if ((i < 0) || (i >= 3)) {
|
||||
i = 0;
|
||||
}
|
||||
|
||||
DmaMgr_SendRequest0((void*)(play->interfaceCtx.doActionSegment + 0x780),
|
||||
SEGMENT_ROM_START_OFFSET(week_static, i * 0x510), 0x510);
|
||||
}
|
||||
|
||||
#include "overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h"
|
||||
|
||||
void Interface_DrawClock(PlayState* play);
|
||||
|
||||
// Wrapper for Interface_DrawClock to display selected hour
|
||||
void dsot_draw_clock(PlayState* play) {
|
||||
MessageContext *msgCtx = &play->msgCtx;
|
||||
|
||||
u8 prev_msgMode = msgCtx->msgMode;
|
||||
msgCtx->msgMode = MSGMODE_NONE;
|
||||
|
||||
PlayState* state = (PlayState*)&play->state;
|
||||
s32 prev_frameAdvanceCtx = state->frameAdvCtx.enabled;
|
||||
state->frameAdvCtx.enabled = 0;
|
||||
|
||||
u16 prev_pauseCtx_state = play->pauseCtx.state;
|
||||
play->pauseCtx.state = PAUSE_STATE_OFF;
|
||||
|
||||
u16 prev_pauseCtx_debugEditor = play->pauseCtx.state;
|
||||
play->pauseCtx.debugEditor = DEBUG_EDITOR_NONE;
|
||||
|
||||
bool flag_modified = false;
|
||||
if (!(play->actorCtx.flags & ACTORCTX_FLAG_TELESCOPE_ON)) {
|
||||
play->actorCtx.flags ^= ACTORCTX_FLAG_TELESCOPE_ON;
|
||||
flag_modified = true;
|
||||
}
|
||||
|
||||
u16 prev_time = gSaveContext.save.time;
|
||||
gSaveContext.save.time = CLOCK_TIME(choiceHour, 0);
|
||||
|
||||
Interface_DrawClock(play);
|
||||
|
||||
gSaveContext.save.time = prev_time;
|
||||
|
||||
if (flag_modified) {
|
||||
play->actorCtx.flags ^= ACTORCTX_FLAG_TELESCOPE_ON;
|
||||
}
|
||||
|
||||
play->pauseCtx.debugEditor == prev_pauseCtx_debugEditor;
|
||||
play->pauseCtx.state = prev_pauseCtx_state;
|
||||
state->frameAdvCtx.enabled = prev_frameAdvanceCtx;
|
||||
msgCtx->msgMode = prev_msgMode;
|
||||
}
|
||||
|
||||
|
||||
#include "overlays/actors/ovl_Obj_Tokeidai/z_obj_tokeidai.h"
|
||||
#include "overlays/actors/ovl_Obj_Tokei_Step/z_obj_tokei_step.h"
|
||||
|
||||
void dsot_ObjTokeidai_fix(ObjTokeidai* this, PlayState* play);
|
||||
void dsot_ObjTokeiStep_fix(ObjTokeiStep* this, PlayState* play);
|
||||
|
||||
// Calls actor specific fixes
|
||||
void dsot_actor_fixes(PlayState* play) {
|
||||
s32 category;
|
||||
Actor* actor;
|
||||
Player* player = GET_PLAYER(play);
|
||||
u32* categoryFreezeMaskP;
|
||||
ActorListEntry* entry;
|
||||
|
||||
ActorContext* actorCtx = &play->actorCtx;
|
||||
|
||||
for (category = 0, entry = actorCtx->actorLists; category < ACTORCAT_MAX;
|
||||
entry++, categoryFreezeMaskP++, category++) {
|
||||
actor = entry->first;
|
||||
|
||||
for (actor = entry->first; actor != NULL; actor = actor->next) {
|
||||
|
||||
switch(actor->id) {
|
||||
case ACTOR_OBJ_TOKEIDAI:
|
||||
dsot_ObjTokeidai_fix(actor, play);
|
||||
break;
|
||||
case ACTOR_OBJ_TOKEI_STEP:
|
||||
dsot_ObjTokeiStep_fix(actor, play);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// z_obj_tokeidai
|
||||
|
||||
#define GET_CURRENT_CLOCK_HOUR(this) ((s32)TIME_TO_HOURS_F((this)->clockTime))
|
||||
#define GET_CLOCK_FACE_ROTATION(currentClockHour) (TRUNCF_BINANG(currentClockHour * (0x10000 / 24.0f)))
|
||||
#define GET_MINUTE_RING_OR_EXTERIOR_GEAR_ROTATION(currentClockMinute) \
|
||||
(TRUNCF_BINANG(currentClockMinute * (0x10000 * 12.0f / 360)))
|
||||
|
||||
s32 ObjTokeidai_GetTargetSunMoonPanelRotation(void);
|
||||
void ObjTokeidai_SetupClockOrExteriorGear(ObjTokeidai* this);
|
||||
void ObjTokeidai_Init(Actor* thisx, PlayState* play);
|
||||
void ObjTokeidai_Draw(Actor* thisx, PlayState* play);
|
||||
void ObjTokeidai_Clock_Init(ObjTokeidai* this);
|
||||
void ObjTokeidai_SetupTowerOpening(ObjTokeidai* this);
|
||||
void ObjTokeidai_DoNothing(ObjTokeidai* this, PlayState* play);
|
||||
void ObjTokeidai_RotateOnMinuteChange(ObjTokeidai* this, s32 playSfx);
|
||||
void ObjTokeidai_RotateOnHourChange(ObjTokeidai* this, PlayState* play);
|
||||
void ObjTokeidai_ExteriorGear_Draw(Actor* thisx, PlayState* play);
|
||||
void ObjTokeidai_Clock_Draw(Actor* thisx, PlayState* play);
|
||||
|
||||
void ObjTokeidai_Counterweight_Idle(ObjTokeidai* this, PlayState* play);
|
||||
void ObjTokeidai_ExteriorGear_Idle(ObjTokeidai* this, PlayState* play);
|
||||
void ObjTokeidai_TowerClock_Idle(ObjTokeidai* this, PlayState* play);
|
||||
|
||||
s32 dsot_ObjTokeidai_get_target_sun_moon_panel_rotation(void) {
|
||||
if (CURRENT_TIME >= CLOCK_TIME(18, 0) || CURRENT_TIME < CLOCK_TIME(6, 0)) {
|
||||
return 0x8000;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dsot_ObjTokeidai_update_clock(ObjTokeidai* this, u16 currentHour, u16 currentMinute) {
|
||||
// @recomp Manual relocation, TODO remove when the recompiler handles this automatically.
|
||||
this->clockTime = CURRENT_TIME;
|
||||
|
||||
// Instantly switch to desired hour
|
||||
u16 clockHour = currentHour;
|
||||
if (currentMinute == 0) {
|
||||
clockHour--;
|
||||
if (clockHour > 23) {
|
||||
clockHour = 23;
|
||||
}
|
||||
}
|
||||
|
||||
this->clockFaceRotation = GET_CLOCK_FACE_ROTATION(clockHour);
|
||||
this->clockHour = clockHour;
|
||||
this->clockFaceAngularVelocity = 0;
|
||||
this->clockFaceRotationTimer = 0;
|
||||
|
||||
// Instantly switch to desired minute
|
||||
u16 clockMinute = currentMinute - 1;
|
||||
if (clockMinute > 59) {
|
||||
clockMinute = 59;
|
||||
}
|
||||
|
||||
this->minuteRingOrExteriorGearRotation = GET_MINUTE_RING_OR_EXTERIOR_GEAR_ROTATION(clockMinute);
|
||||
this->clockMinute = clockMinute;
|
||||
this->minuteRingOrExteriorGearAngularVelocity = 0x5A;
|
||||
this->minuteRingOrExteriorGearRotationTimer = 0;
|
||||
|
||||
// Switch the medalion rotation immediately.
|
||||
if (((currentHour != 6) && (currentHour != 18)) || (currentMinute != 0)) {
|
||||
this->sunMoonPanelRotation = dsot_ObjTokeidai_get_target_sun_moon_panel_rotation();
|
||||
this->sunMoonPanelAngularVelocity = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#define PAST_MIDNIGHT ((CURRENT_DAY == 3) && (CURRENT_TIME < CLOCK_TIME(6, 0)) && (CURRENT_TIME > CLOCK_TIME(0, 0)))
|
||||
|
||||
void dsot_ObjTokeidai_fix(ObjTokeidai* this, PlayState* play) {
|
||||
s32 type = OBJ_TOKEIDAI_TYPE(&this->actor);
|
||||
u16 currentHour = TIME_TO_HOURS_F(CURRENT_TIME);
|
||||
u16 currentMinute = TIME_TO_MINUTES_F(CURRENT_TIME);
|
||||
|
||||
switch(type) {
|
||||
case OBJ_TOKEIDAI_TYPE_COUNTERWEIGHT_TERMINA_FIELD:
|
||||
case OBJ_TOKEIDAI_TYPE_COUNTERWEIGHT_CLOCK_TOWN:
|
||||
if (PAST_MIDNIGHT && (this->actionFunc == actor_relocate(this, ObjTokeidai_Counterweight_Idle))) {
|
||||
this->actor.shape.rot.y = 0;
|
||||
ObjTokeidai_Init(this, play);
|
||||
}
|
||||
break;
|
||||
|
||||
case OBJ_TOKEIDAI_TYPE_EXTERIOR_GEAR_TERMINA_FIELD:
|
||||
case OBJ_TOKEIDAI_TYPE_EXTERIOR_GEAR_CLOCK_TOWN:
|
||||
if (PAST_MIDNIGHT && (this->actionFunc == actor_relocate(this, ObjTokeidai_ExteriorGear_Idle))) {
|
||||
dsot_ObjTokeidai_update_clock(this, 0, 0);
|
||||
// @recomp Manual relocation, TODO remove when the recompiler handles this automatically.
|
||||
this->actor.draw = actor_relocate(this, ObjTokeidai_ExteriorGear_Draw);
|
||||
ObjTokeidai_Init(this, play);
|
||||
} else {
|
||||
dsot_ObjTokeidai_update_clock(this, currentHour, currentMinute);
|
||||
}
|
||||
break;
|
||||
|
||||
case OBJ_TOKEIDAI_TYPE_TOWER_CLOCK_TERMINA_FIELD:
|
||||
case OBJ_TOKEIDAI_TYPE_TOWER_CLOCK_CLOCK_TOWN:
|
||||
if (PAST_MIDNIGHT && (this->actionFunc == actor_relocate(this, ObjTokeidai_TowerClock_Idle))) {
|
||||
dsot_ObjTokeidai_update_clock(this, 0, 0);
|
||||
// @recomp Manual relocation, TODO remove when the recompiler handles this automatically.
|
||||
this->actor.draw = actor_relocate(this, ObjTokeidai_Clock_Draw);
|
||||
ObjTokeidai_Init(this, play);
|
||||
} else {
|
||||
dsot_ObjTokeidai_update_clock(this, currentHour, currentMinute);
|
||||
}
|
||||
break;
|
||||
case OBJ_TOKEIDAI_TYPE_STAIRCASE_TO_ROOFTOP:
|
||||
if (PAST_MIDNIGHT) {
|
||||
// @recomp Manual relocation, TODO remove when the recompiler handles this automatically.
|
||||
this->actor.draw = actor_relocate(this, ObjTokeidai_Draw);
|
||||
}
|
||||
break;
|
||||
case OBJ_TOKEIDAI_TYPE_WALL_CLOCK:
|
||||
case OBJ_TOKEIDAI_TYPE_SMALL_WALL_CLOCK:
|
||||
dsot_ObjTokeidai_update_clock(this, currentHour, currentMinute);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// z_obj_tokei_step
|
||||
|
||||
void ObjTokeiStep_InitStepsOpen(ObjTokeiStep* this);
|
||||
void ObjTokeiStep_SetupDoNothingOpen(ObjTokeiStep* this);
|
||||
void ObjTokeiStep_DrawOpen(Actor* thisx, PlayState* play);
|
||||
|
||||
void dsot_ObjTokeiStep_fix(ObjTokeiStep* this, PlayState* play) {
|
||||
if (PAST_MIDNIGHT) {
|
||||
// @recomp Manual relocation, TODO remove when the recompiler handles this automatically.
|
||||
this->dyna.actor.draw = actor_relocate(this, ObjTokeiStep_DrawOpen);
|
||||
ObjTokeiStep_InitStepsOpen(this);
|
||||
ObjTokeiStep_SetupDoNothingOpen(this);
|
||||
DynaPoly_DisableCollision(play, &play->colCtx.dyna, this->dyna.bgId);
|
||||
}
|
||||
}
|
813
patches/event_patches.c
Normal file
813
patches/event_patches.c
Normal file
@ -0,0 +1,813 @@
|
||||
#include "patches.h"
|
||||
|
||||
#define PAST_MIDNIGHT CLOCK_TIME(0, 1)
|
||||
|
||||
#include "overlays/actors/ovl_En_Test4/z_en_test4.h"
|
||||
#include "z64horse.h"
|
||||
#include "overlays/gamestates/ovl_daytelop/z_daytelop.h"
|
||||
#include "overlays/actors/ovl_En_Horse/z_en_horse.h"
|
||||
|
||||
#define THIS ((EnTest4*)thisx)
|
||||
|
||||
static s16 sCsIdList[THREEDAY_DAYTIME_MAX];
|
||||
|
||||
void func_80A42AB8(EnTest4* this, PlayState* play); // EnTest4_HandleEvents
|
||||
void func_80A42F20(EnTest4* this, PlayState* play); // EnTest4_HandleCutscene
|
||||
|
||||
static s16 sCurCsId;
|
||||
|
||||
void func_800FEAF4(EnvironmentContext* envCtx); // Environment_NewDay
|
||||
|
||||
void func_80A41FA4(EnTest4* this, PlayState* play); // EnTest4_HandleDayNightSwap
|
||||
void func_80A42198(EnTest4* this); // EnTest4_GetBellTimeOnDay3
|
||||
void func_80A425E4(EnTest4* this, PlayState* play); // EnTest4_GetBellTimeAndShrinkScreenBeforeDay3
|
||||
|
||||
// @recomp Patched to perform transitions when Double SoT is used.
|
||||
/**
|
||||
* This function checks for two-specific time-based events:
|
||||
* 1) The day-night transitions
|
||||
* 2) The play bells sfx event, which contains screen shrinking and the clocktown day 3 midnight cutscene trigger
|
||||
*/
|
||||
void func_80A42AB8(EnTest4* this, PlayState* play) { // EnTest4_HandleEvents
|
||||
static u16 sDayNightTransitionTimes[THREEDAY_DAYTIME_MAX] = {
|
||||
CLOCK_TIME(6, 0), // THREEDAY_DAYTIME_NIGHT
|
||||
CLOCK_TIME(18, 0), // THREEDAY_DAYTIME_DAY
|
||||
};
|
||||
Player* player = GET_PLAYER(play);
|
||||
|
||||
if ((play->transitionMode == TRANS_MODE_OFF) && !Play_InCsMode(play) && (play->numSetupActors <= 0) &&
|
||||
(play->roomCtx.status == 0) && !Play_IsDebugCamEnabled()) {
|
||||
u16 transitionTime = sDayNightTransitionTimes[this->daytimeIndex];
|
||||
s16 curTimeUntilTransition;
|
||||
s16 prevTimeUntilTransition;
|
||||
s16 prevTimeUntilBell;
|
||||
s16 curTimeUntilBell;
|
||||
|
||||
curTimeUntilTransition = CURRENT_TIME - transitionTime;
|
||||
prevTimeUntilTransition = this->prevTime - transitionTime;
|
||||
|
||||
prevTimeUntilBell = this->prevBellTime - this->nextBellTime;
|
||||
curTimeUntilBell = CURRENT_TIME - this->nextBellTime;
|
||||
|
||||
extern bool dsot_used;
|
||||
u8 current_hour = TIME_TO_HOURS_F(CURRENT_TIME);
|
||||
|
||||
// @recomp Check for unusual Double SoT time skips.
|
||||
if (dsot_used) {
|
||||
if ((this->daytimeIndex == THREEDAY_DAYTIME_DAY) && (CURRENT_TIME < this->prevTime)) {
|
||||
if (CURRENT_TIME >= CLOCK_TIME(6, 0)) {
|
||||
transitionTime = sDayNightTransitionTimes[0];
|
||||
}
|
||||
curTimeUntilTransition = 0;
|
||||
}
|
||||
|
||||
if ((CURRENT_DAY == 3) && (current_hour == 0)) {
|
||||
curTimeUntilBell = 0;
|
||||
this->nextBellTime = CLOCK_TIME(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// When the day-night transition time is passed:
|
||||
// `curTimeUntilTransition` will be slightly positive (ahead transition time)
|
||||
// `prevTimeUntilTransition` will be slightly negative (behind transition time)
|
||||
// Only when the signs are different will this condition pass
|
||||
if (((curTimeUntilTransition * prevTimeUntilTransition) <= 0)) {
|
||||
// day-night transition is occuring
|
||||
gSaveContext.unk_3CA7 = 1;
|
||||
if (play->actorCtx.flags & ACTORCTX_FLAG_PICTO_BOX_ON) {
|
||||
play->actorCtx.flags &= ~ACTORCTX_FLAG_PICTO_BOX_ON;
|
||||
}
|
||||
|
||||
// @recomp Manual relocation, TODO remove when the recompiler handles this automatically.
|
||||
s16* sCsIdList_reloc = (s16*)actor_relocate(&this->actor, &sCsIdList);
|
||||
|
||||
if (transitionTime != CLOCK_TIME(6, 0)) {
|
||||
// previously day, turning night
|
||||
// @recomp Skip night transition cutscene if Double SoT is used.
|
||||
if ((!dsot_used) || (current_hour == 18)) {
|
||||
func_80A41FA4(this, play);
|
||||
} else {
|
||||
this->daytimeIndex = THREEDAY_DAYTIME_NIGHT;
|
||||
this->prevTime = CURRENT_TIME;
|
||||
// Re-spawn the setup actors.
|
||||
play->numSetupActors = -play->numSetupActors;
|
||||
}
|
||||
} else if (transitionTime == CLOCK_TIME(6, 0)) {
|
||||
// previously night, turning day
|
||||
if (CURRENT_DAY == 3) {
|
||||
// Turn day with mooncrash
|
||||
Interface_StartMoonCrash(play);
|
||||
Actor_Kill(&this->actor);
|
||||
SET_EVENTINF(EVENTINF_17);
|
||||
} else if (((sCsIdList_reloc[this->daytimeIndex] <= CS_ID_NONE) ||
|
||||
(play->actorCtx.flags & ACTORCTX_FLAG_TELESCOPE_ON)) &&
|
||||
(CURRENT_DAY != 3)) {
|
||||
// Turn day without cutscene
|
||||
func_80A41FA4(this, play);
|
||||
} else {
|
||||
// Turn day with DayTelop cutscene
|
||||
gSaveContext.screenScale = 0.0f;
|
||||
Play_SetRespawnData(&play->state, RESPAWN_MODE_DOWN, Entrance_CreateFromSpawn(0), player->unk_3CE,
|
||||
PLAYER_PARAMS(0xFF, PLAYER_INITMODE_B), &player->unk_3C0, player->unk_3CC);
|
||||
func_80169EFC(&play->state);
|
||||
if (player->stateFlags1 & PLAYER_STATE1_800000) {
|
||||
EnHorse* rideActor = (EnHorse*)player->rideActor;
|
||||
|
||||
if ((rideActor->type == HORSE_TYPE_EPONA) || (rideActor->type == HORSE_TYPE_2)) {
|
||||
if (CURRENT_DAY < 3) {
|
||||
gHorseIsMounted = true;
|
||||
} else {
|
||||
gHorseIsMounted = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gSaveContext.respawnFlag = -4;
|
||||
SET_EVENTINF(EVENTINF_TRIGGER_DAYTELOP);
|
||||
Actor_Kill(&this->actor);
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Skip night transition cutscene if Double SoT is used.
|
||||
if ((!dsot_used) || (transitionTime == CLOCK_TIME(6, 0))) {
|
||||
if ((sCsIdList_reloc[this->daytimeIndex] > CS_ID_NONE) && !(play->actorCtx.flags & ACTORCTX_FLAG_TELESCOPE_ON)) {
|
||||
player->stateFlags1 |= PLAYER_STATE1_200;
|
||||
this->prevTime = CURRENT_TIME;
|
||||
} else {
|
||||
if (this->daytimeIndex == THREEDAY_DAYTIME_NIGHT) {
|
||||
this->daytimeIndex = THREEDAY_DAYTIME_DAY;
|
||||
} else {
|
||||
this->daytimeIndex = THREEDAY_DAYTIME_NIGHT;
|
||||
}
|
||||
|
||||
gSaveContext.save.time += CLOCK_TIME_MINUTE;
|
||||
this->prevTime = CURRENT_TIME;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// When the bell sfx time is passed:
|
||||
// `curTimeUntilBell` will be slightly positive (ahead bell time)
|
||||
// `prevTimeUntilBell` will be slightly negative (behind bell time)
|
||||
// Only when the signs are different will this condition pass
|
||||
if ((curTimeUntilBell * prevTimeUntilBell) <= 0) {
|
||||
Audio_PlaySfx_BigBells(&this->actor.projectedPos, THREEDAY_GET_BIG_BELLS_SFX_VOLUME_INDEX(&this->actor));
|
||||
this->prevBellTime = CURRENT_TIME;
|
||||
|
||||
if (CURRENT_DAY == 3) {
|
||||
// @recomp Don't initate cutscene if it's past midnight.
|
||||
if ((this->nextBellTime == CLOCK_TIME(0, 0)) &&
|
||||
(CURRENT_TIME < PAST_MIDNIGHT) &&
|
||||
((gSaveContext.save.saveInfo.inventory.items[SLOT_OCARINA] == ITEM_NONE) ||
|
||||
(play->sceneId == SCENE_CLOCKTOWER))) {
|
||||
// Initiate Clocktown day 3 midnight festival cutscene
|
||||
s32 playerParams;
|
||||
u32 entrance = gSaveContext.save.entrance;
|
||||
|
||||
if (play->actorCtx.flags & ACTORCTX_FLAG_TELESCOPE_ON) {
|
||||
playerParams = PLAYER_PARAMS(0xFF, PLAYER_INITMODE_TELESCOPE);
|
||||
} else {
|
||||
playerParams = PLAYER_PARAMS(0xFF, PLAYER_INITMODE_B);
|
||||
}
|
||||
|
||||
Play_SetRespawnData(&play->state, RESPAWN_MODE_RETURN, entrance, player->unk_3CE, playerParams,
|
||||
&player->unk_3C0, player->unk_3CC);
|
||||
|
||||
if ((play->sceneId == SCENE_TENMON_DAI) || (play->sceneId == SCENE_00KEIKOKU)) {
|
||||
play->nextEntrance = ENTRANCE(TERMINA_FIELD, 0);
|
||||
} else {
|
||||
play->nextEntrance = ENTRANCE(SOUTH_CLOCK_TOWN, 0);
|
||||
}
|
||||
gSaveContext.nextCutsceneIndex = 0xFFF1;
|
||||
play->transitionTrigger = TRANS_TRIGGER_START;
|
||||
play->transitionType = TRANS_TYPE_FADE_BLACK;
|
||||
player->stateFlags1 |= PLAYER_STATE1_200;
|
||||
Actor_Kill(&this->actor);
|
||||
}
|
||||
func_80A42198(this);
|
||||
} else {
|
||||
func_80A425E4(this, play);
|
||||
}
|
||||
}
|
||||
|
||||
dsot_used = false;
|
||||
}
|
||||
}
|
||||
|
||||
u8 func_800FE5D0(struct PlayState* play);
|
||||
|
||||
void Environment_UpdateTimeBasedSequence(PlayState* play) {
|
||||
s32 pad;
|
||||
|
||||
//! FAKE:
|
||||
if (gSaveContext.sceneLayer) {}
|
||||
|
||||
if ((play->csCtx.state == CS_STATE_IDLE) && !(play->actorCtx.flags & ACTORCTX_FLAG_TELESCOPE_ON)) {
|
||||
switch (play->envCtx.timeSeqState) {
|
||||
case TIMESEQ_DAY_BGM:
|
||||
break;
|
||||
|
||||
case TIMESEQ_FADE_DAY_BGM:
|
||||
if (CURRENT_TIME > CLOCK_TIME(17, 10)) {
|
||||
SEQCMD_STOP_SEQUENCE(SEQ_PLAYER_BGM_MAIN, 240);
|
||||
play->envCtx.timeSeqState++;
|
||||
}
|
||||
break;
|
||||
|
||||
case TIMESEQ_NIGHT_BEGIN_SFX:
|
||||
if (CURRENT_TIME >= CLOCK_TIME(18, 0)) {
|
||||
play->envCtx.timeSeqState++;
|
||||
}
|
||||
break;
|
||||
|
||||
case TIMESEQ_EARLY_NIGHT_CRITTERS:
|
||||
if (play->envCtx.precipitation[PRECIP_RAIN_CUR] < 9) {
|
||||
Audio_PlayAmbience(play->sequenceCtx.ambienceId);
|
||||
Audio_SetAmbienceChannelIO(AMBIENCE_CHANNEL_CRITTER_0, 1, 1);
|
||||
}
|
||||
play->envCtx.timeSeqState++;
|
||||
break;
|
||||
|
||||
case TIMESEQ_NIGHT_DELAY:
|
||||
if (CURRENT_TIME >= CLOCK_TIME(19, 0)) {
|
||||
play->envCtx.timeSeqState++;
|
||||
}
|
||||
break;
|
||||
|
||||
case TIMESEQ_NIGHT_CRITTERS:
|
||||
Audio_SetAmbienceChannelIO(AMBIENCE_CHANNEL_CRITTER_0, 1, 0);
|
||||
Audio_SetAmbienceChannelIO(AMBIENCE_CHANNEL_CRITTER_1 << 4 | AMBIENCE_CHANNEL_CRITTER_3, 1, 1);
|
||||
play->envCtx.timeSeqState++;
|
||||
break;
|
||||
|
||||
case TIMESEQ_DAY_BEGIN_SFX:
|
||||
if ((CURRENT_TIME < CLOCK_TIME(19, 0)) && (CURRENT_TIME >= CLOCK_TIME(5, 0))) {
|
||||
play->envCtx.timeSeqState++;
|
||||
}
|
||||
break;
|
||||
|
||||
case TIMESEQ_MORNING_CRITTERS:
|
||||
Audio_SetAmbienceChannelIO(AMBIENCE_CHANNEL_CRITTER_1 << 4 | AMBIENCE_CHANNEL_CRITTER_3, 1, 0);
|
||||
Audio_SetAmbienceChannelIO(AMBIENCE_CHANNEL_CRITTER_4 << 4 | AMBIENCE_CHANNEL_CRITTER_5, 1, 1);
|
||||
play->envCtx.timeSeqState++;
|
||||
break;
|
||||
|
||||
case TIMESEQ_DAY_DELAY:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((play->envCtx.timeSeqState != TIMESEQ_REQUEST) && (((void)0, gSaveContext.save.day) == 3) &&
|
||||
(CURRENT_TIME < CLOCK_TIME(6, 0)) && !func_800FE5D0(play) && (play->transitionTrigger == TRANS_TRIGGER_OFF) &&
|
||||
(play->transitionMode == TRANS_MODE_OFF) && (play->csCtx.state == CS_STATE_IDLE) &&
|
||||
((play->sceneId != SCENE_00KEIKOKU) || (((void)0, gSaveContext.sceneLayer) != 1)) &&
|
||||
(CutsceneManager_GetCurrentCsId() == CS_ID_NONE) &&
|
||||
(AudioSeq_GetActiveSeqId(SEQ_PLAYER_BGM_MAIN) != NA_BGM_FINAL_HOURS) &&
|
||||
(AudioSeq_GetActiveSeqId(SEQ_PLAYER_BGM_MAIN) != NA_BGM_SONG_OF_SOARING)) {
|
||||
// @recomp Don't play final hours until Double SoT finishes.
|
||||
extern bool dsot_used;
|
||||
if (!dsot_used) {
|
||||
SEQCMD_STOP_SEQUENCE(SEQ_PLAYER_AMBIENCE, 0);
|
||||
Audio_PlaySceneSequence(NA_BGM_FINAL_HOURS, 3 - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include "overlays/actors/ovl_En_Test6/z_en_test6.h"
|
||||
#include "z64quake.h"
|
||||
|
||||
void func_800B7298(PlayState* play, Actor* csActor, u8 csAction); // Player_SetCsActionWithHaltedActors
|
||||
|
||||
void EnTest6_SharedSoTCutscene(EnTest6* this, PlayState* play);
|
||||
|
||||
extern CutsceneData sDoubleSoTCsCamData[];
|
||||
static Vec3f sSubCamUp;
|
||||
|
||||
struct SoTCsAmmoDrops;
|
||||
|
||||
typedef void (*SoTCsAmmoDropDrawFunc)(EnTest6*, PlayState*, struct SoTCsAmmoDrops*);
|
||||
|
||||
typedef enum SoTCsAmmoDropType {
|
||||
/* 0 */ SOTCS_AMMO_DROP_NONE,
|
||||
/* 1 */ SOTCS_AMMO_DROP_ARROWS,
|
||||
/* 2 */ SOTCS_AMMO_DROP_BOMB,
|
||||
/* 3 */ SOTCS_AMMO_DROP_DEKU_NUT,
|
||||
/* 4 */ SOTCS_AMMO_DROP_DEKU_STICK,
|
||||
/* 5 */ SOTCS_AMMO_DROP_RUPEE_GREEN,
|
||||
/* 6 */ SOTCS_AMMO_DROP_RUPEE_BLUE
|
||||
} SoTCsAmmoDropType;
|
||||
|
||||
typedef struct SoTCsAmmoDrops {
|
||||
/* 0x00 */ SoTCsAmmoDropType type;
|
||||
/* 0x04 */ f32 scale;
|
||||
/* 0x08 */ Vec3f pos;
|
||||
/* 0x14 */ SoTCsAmmoDropDrawFunc draw;
|
||||
} SoTCsAmmoDrops; // size = 0x18
|
||||
|
||||
extern SoTCsAmmoDrops sSoTCsAmmoDrops[12];
|
||||
|
||||
typedef enum SoTCsDrawType {
|
||||
/* 0 */ SOTCS_DRAW_DOUBLE_SOT,
|
||||
/* 1 */ SOTCS_DRAW_RESET_CYCLE_SOT,
|
||||
/* 2 */ SOTCS_DRAW_INVERTED_SOT,
|
||||
/* 99 */ SOTCS_DRAW_TYPE_NONE = 99
|
||||
} SoTCsDrawType;
|
||||
|
||||
void EnTest6_EnableMotionBlur(s16 alpha);
|
||||
void EnTest6_DisableMotionBlur(void);
|
||||
|
||||
void EnTest6_EnableWhiteFillScreen(PlayState* play, f32 alphaRatio);
|
||||
void EnTest6_DisableWhiteFillScreen(PlayState* play);
|
||||
void EnTest6_StopDoubleSoTCutscene(EnTest6* this, PlayState* play);
|
||||
|
||||
extern Color_RGB8 sDoubleSoTCsFogColor;
|
||||
extern Color_RGB8 sDoubleSoTCsAmbientColor;
|
||||
extern Color_RGB8 sDoubleSoTCsDiffuseColor;
|
||||
extern s16 sDoubleSoTCsFogNear;
|
||||
extern s16 sDoubleSoTCsZFar;
|
||||
|
||||
void EnTest6_DoubleSoTCutscene(EnTest6* this, PlayState* play) {
|
||||
Input* input = CONTROLLER1(&play->state);
|
||||
Player* player = GET_PLAYER(play);
|
||||
Camera* subCam;
|
||||
s32 pad;
|
||||
s16 subCamId;
|
||||
s16 pad2;
|
||||
|
||||
if (this->timer > 115) {
|
||||
this->doubleSoTEnvLerp += 0.2f;
|
||||
EnTest6_EnableWhiteFillScreen(play, this->doubleSoTEnvLerp);
|
||||
} else if (this->timer > 90) {
|
||||
this->doubleSoTEnvLerp -= 0.05f;
|
||||
EnTest6_EnableWhiteFillScreen(play, this->doubleSoTEnvLerp);
|
||||
} else if (this->timer == 90) {
|
||||
this->doubleSoTEnvLerp = 0.0f;
|
||||
EnTest6_DisableWhiteFillScreen(play);
|
||||
}
|
||||
|
||||
if (this->timer == 1) {
|
||||
this->doubleSoTEnvLerp = 0.0f;
|
||||
EnTest6_DisableWhiteFillScreen(play);
|
||||
} else if (this->timer < 17) {
|
||||
this->doubleSoTEnvLerp -= 0.06666666f;
|
||||
EnTest6_EnableWhiteFillScreen(play, this->doubleSoTEnvLerp);
|
||||
} else if (this->timer < 22) {
|
||||
this->doubleSoTEnvLerp += 0.2f;
|
||||
EnTest6_EnableWhiteFillScreen(play, this->doubleSoTEnvLerp);
|
||||
}
|
||||
|
||||
// @recomp Manual relocation, TODO remove when the recompiler handles this automatically.
|
||||
s16* sDoubleSoTCsFogNear_ptr = actor_relocate(&this->actor, &sDoubleSoTCsFogNear);
|
||||
s16* sDoubleSoTCsZFar_ptr = actor_relocate(&this->actor, &sDoubleSoTCsZFar);
|
||||
|
||||
Color_RGB8* sDoubleSoTCsFogColor_ptr = actor_relocate(&this->actor, &sDoubleSoTCsFogColor);
|
||||
Color_RGB8* sDoubleSoTCsAmbientColor_ptr = actor_relocate(&this->actor, &sDoubleSoTCsAmbientColor);
|
||||
Color_RGB8* sDoubleSoTCsDiffuseColor_ptr = actor_relocate(&this->actor, &sDoubleSoTCsDiffuseColor);
|
||||
|
||||
if (this->timer == 115) {
|
||||
Environment_LerpAmbientColor(play, sDoubleSoTCsAmbientColor_ptr, 1.0f);
|
||||
Environment_LerpDiffuseColor(play, sDoubleSoTCsDiffuseColor_ptr, 1.0f);
|
||||
Environment_LerpFogColor(play, sDoubleSoTCsFogColor_ptr, 1.0f);
|
||||
Environment_LerpFog(play, *sDoubleSoTCsFogNear_ptr, *sDoubleSoTCsZFar_ptr, 1.0f);
|
||||
play->unk_18844 = true;
|
||||
}
|
||||
|
||||
if (this->timer == 15) {
|
||||
Environment_LerpAmbientColor(play, sDoubleSoTCsAmbientColor_ptr, 0.0f);
|
||||
Environment_LerpDiffuseColor(play, sDoubleSoTCsDiffuseColor_ptr, 0.0f);
|
||||
Environment_LerpFogColor(play, sDoubleSoTCsFogColor_ptr, 0.0f);
|
||||
Environment_LerpFog(play, *sDoubleSoTCsFogNear_ptr, *sDoubleSoTCsZFar_ptr, 0.0f);
|
||||
play->unk_18844 = false;
|
||||
}
|
||||
|
||||
if (this->screenFillAlpha >= 20) {
|
||||
Environment_LerpAmbientColor(play, sDoubleSoTCsAmbientColor_ptr, this->doubleSoTEnvLerp);
|
||||
Environment_LerpDiffuseColor(play, sDoubleSoTCsDiffuseColor_ptr, this->doubleSoTEnvLerp);
|
||||
Environment_LerpFogColor(play, sDoubleSoTCsFogColor_ptr, this->doubleSoTEnvLerp);
|
||||
Environment_LerpFog(play, *sDoubleSoTCsFogNear_ptr, *sDoubleSoTCsZFar_ptr, this->doubleSoTEnvLerp);
|
||||
play->unk_18844 = false;
|
||||
}
|
||||
|
||||
Actor_PlaySfx_FlaggedCentered1(&player->actor, NA_SE_PL_FLYING_AIR - SFX_FLAG);
|
||||
|
||||
switch (this->timer) {
|
||||
case 119:
|
||||
EnTest6_EnableMotionBlur(50);
|
||||
break;
|
||||
|
||||
case 115:
|
||||
EnTest6_EnableMotionBlur(20);
|
||||
Distortion_Request(DISTORTION_TYPE_SONG_OF_TIME);
|
||||
Distortion_SetDuration(90);
|
||||
this->cueId = SOTCS_CUEID_DOUBLE_INIT;
|
||||
break;
|
||||
|
||||
case 110:
|
||||
Audio_PlayFanfare(NA_BGM_SONG_OF_DOUBLE_TIME);
|
||||
break;
|
||||
|
||||
case 38:
|
||||
case 114:
|
||||
this->cueId = SOTCS_CUEID_DOUBLE_WAIT;
|
||||
break;
|
||||
|
||||
case 76:
|
||||
this->cueId = SOTCS_CUEID_DOUBLE_CLOCKS_INWARD;
|
||||
break;
|
||||
|
||||
case 61:
|
||||
EnTest6_EnableMotionBlur(150);
|
||||
this->cueId = SOTCS_CUEID_DOUBLE_CLOCKS_SPIN;
|
||||
break;
|
||||
|
||||
case 51:
|
||||
EnTest6_EnableMotionBlur(180);
|
||||
this->cueId = SOTCS_CUEID_DOUBLE_CLOCKS_OUTWARD;
|
||||
break;
|
||||
|
||||
case 14:
|
||||
case 15:
|
||||
EnTest6_EnableMotionBlur(50);
|
||||
Distortion_RemoveRequest(DISTORTION_TYPE_SONG_OF_TIME);
|
||||
this->cueId = SOTCS_CUEID_NONE;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
EnTest6_DisableMotionBlur();
|
||||
if (CHECK_EVENTINF(EVENTINF_HAS_DAYTIME_TRANSITION_CS)) {
|
||||
this->cueId = SOTCS_CUEID_DOUBLE_END;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
EnTest6_SharedSoTCutscene(this, play);
|
||||
|
||||
if (this->timer == 115) {
|
||||
subCamId = CutsceneManager_GetCurrentSubCamId(play->playerCsIds[PLAYER_CS_ID_SONG_WARP]);
|
||||
subCam = Play_GetCamera(play, subCamId);
|
||||
|
||||
this->subCamAt = subCam->at;
|
||||
this->subCamEye = subCam->eye;
|
||||
this->subCamFov = subCam->fov;
|
||||
CutsceneCamera_Init(subCam, &this->csCamInfo);
|
||||
}
|
||||
|
||||
if ((this->timer <= 115) && (this->timer >= 16)) {
|
||||
// @recomp Manual relocation, TODO remove when the recompiler handles this automatically.
|
||||
CutsceneData* sDoubleSoTCsCamData_reloc = actor_relocate(&this->actor, sDoubleSoTCsCamData);
|
||||
CutsceneCamera_UpdateSplines((u8*)sDoubleSoTCsCamData_reloc, &this->csCamInfo);
|
||||
} else if (this->timer < 16) {
|
||||
subCamId = CutsceneManager_GetCurrentSubCamId(play->playerCsIds[PLAYER_CS_ID_SONG_WARP]);
|
||||
|
||||
// @recomp Manual relocation, TODO remove when the recompiler handles this automatically.
|
||||
Vec3f* sSubCamUp_ptr = KaleidoManager_GetRamAddr(&sSubCamUp);
|
||||
Play_SetCameraAtEyeUp(play, subCamId, &this->subCamAt, &this->subCamEye, sSubCamUp_ptr);
|
||||
Play_SetCameraFov(play, subCamId, this->subCamFov);
|
||||
Play_SetCameraRoll(play, subCamId, 0);
|
||||
}
|
||||
|
||||
switch (this->timer) {
|
||||
case 116:
|
||||
player->actor.freezeTimer = 2;
|
||||
player->actor.shape.rot.x = 0;
|
||||
player->actor.shape.rot.y = 0;
|
||||
player->actor.world.pos.x = 0.0f;
|
||||
player->actor.world.pos.y = 0.0f;
|
||||
player->actor.world.pos.z = 0.0f;
|
||||
player->actor.home.pos.x = 0.0f;
|
||||
player->actor.home.pos.y = 0.0f;
|
||||
player->actor.home.pos.z = 0.0f;
|
||||
break;
|
||||
|
||||
case 98:
|
||||
func_800B7298(play, NULL, PLAYER_CSACTION_64);
|
||||
break;
|
||||
|
||||
case 68:
|
||||
func_800B7298(play, NULL, PLAYER_CSACTION_65);
|
||||
break;
|
||||
|
||||
case 52:
|
||||
func_800B7298(play, NULL, PLAYER_CSACTION_88);
|
||||
break;
|
||||
|
||||
case 43:
|
||||
func_800B7298(play, NULL, PLAYER_CSACTION_114);
|
||||
break;
|
||||
|
||||
case 38:
|
||||
func_800B7298(play, NULL, PLAYER_CSACTION_WAIT);
|
||||
break;
|
||||
|
||||
case 14:
|
||||
player->actor.freezeTimer = 5;
|
||||
player->actor.world.pos = player->actor.home.pos = this->actor.home.pos;
|
||||
player->actor.shape.rot = this->actor.home.rot;
|
||||
player->actor.focus.rot.y = player->actor.shape.rot.y;
|
||||
player->currentYaw = player->actor.shape.rot.y;
|
||||
player->unk_ABC = 0.0f;
|
||||
player->unk_AC0 = 0.0f;
|
||||
player->actor.shape.yOffset = 0.0f;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ((this->screenFillAlpha > 0) && (this->screenFillAlpha < 20)) {
|
||||
EnTest6_EnableWhiteFillScreen(play, this->screenFillAlpha * 0.05f);
|
||||
this->screenFillAlpha++;
|
||||
if (this->screenFillAlpha >= 20) {
|
||||
this->timer = 15;
|
||||
this->doubleSoTEnvLerp = 0.9333333f;
|
||||
}
|
||||
} else if ((this->timer < 96) && (this->timer > 50) &&
|
||||
(CHECK_BTN_ALL(input->press.button, BTN_A) || CHECK_BTN_ALL(input->press.button, BTN_B))) {
|
||||
this->screenFillAlpha = 1;
|
||||
this->timer = 39;
|
||||
SEQCMD_STOP_SEQUENCE(SEQ_PLAYER_FANFARE, 20);
|
||||
}
|
||||
|
||||
// @recomp Advance hour as Double SoT ends.
|
||||
if (this->timer == 15) {
|
||||
dsot_advance_hour(play);
|
||||
}
|
||||
|
||||
if (DECR(this->timer) == 0) {
|
||||
EnTest6_StopDoubleSoTCutscene(this, play);
|
||||
}
|
||||
}
|
||||
|
||||
void Play_InitScene(PlayState* this, s32 spawn);
|
||||
|
||||
/**
|
||||
* Processes two different cutscenes:
|
||||
* return to "Dawn of the First Day" Cs, and Song of Double Time Cs
|
||||
*/
|
||||
void EnTest6_SharedSoTCutscene(EnTest6* this, PlayState* play) {
|
||||
s32 pad[2];
|
||||
Player* player = GET_PLAYER(play);
|
||||
f32 yDiff;
|
||||
s32 i;
|
||||
s32 cueChannel;
|
||||
|
||||
if (Cutscene_IsCueInChannel(play, CS_CMD_ACTOR_CUE_SOTCS)) {
|
||||
cueChannel = Cutscene_GetCueChannel(play, CS_CMD_ACTOR_CUE_SOTCS);
|
||||
this->cueId = play->csCtx.actorCues[cueChannel]->id;
|
||||
|
||||
switch (this->cueId) {
|
||||
case SOTCS_CUEID_DOUBLE_WAIT:
|
||||
break;
|
||||
|
||||
case SOTCS_CUEID_DOUBLE_INIT:
|
||||
this->drawType = SOTCS_DRAW_DOUBLE_SOT;
|
||||
this->counter = 0;
|
||||
this->clockAngle = 0;
|
||||
player->actor.shape.shadowDraw = NULL;
|
||||
|
||||
if (play->csCtx.actorCues[cueChannel]->startPos.x != 0) {
|
||||
this->clockSpeed = (u32)play->csCtx.actorCues[cueChannel]->startPos.x;
|
||||
} else {
|
||||
this->clockSpeed = 150.0f;
|
||||
}
|
||||
|
||||
if (play->csCtx.actorCues[cueChannel]->startPos.y != 0) {
|
||||
this->clockColorGray = play->csCtx.actorCues[cueChannel]->startPos.y;
|
||||
} else {
|
||||
this->clockColorGray = 38;
|
||||
}
|
||||
|
||||
if (play->csCtx.actorCues[cueChannel]->startPos.z != 0) {
|
||||
this->clockDist = (u32)play->csCtx.actorCues[cueChannel]->startPos.z;
|
||||
} else {
|
||||
this->clockDist = 480.0f;
|
||||
}
|
||||
break;
|
||||
|
||||
case SOTCS_CUEID_DOUBLE_CLOCKS_INWARD:
|
||||
if (play->csCtx.actorCues[cueChannel]->startPos.x != 0) {
|
||||
this->clockSpeed += (u32)play->csCtx.actorCues[cueChannel]->startPos.x;
|
||||
}
|
||||
|
||||
if (play->csCtx.actorCues[cueChannel]->startPos.y != 0) {
|
||||
this->clockColorGray += (s16)play->csCtx.actorCues[cueChannel]->startPos.y;
|
||||
|
||||
} else {
|
||||
this->clockColorGray += 6;
|
||||
}
|
||||
|
||||
if (play->csCtx.actorCues[cueChannel]->startPos.z != 0) {
|
||||
this->clockRadialSpeed = (u32)play->csCtx.actorCues[cueChannel]->startPos.z;
|
||||
} else {
|
||||
this->clockRadialSpeed = -32.0f;
|
||||
}
|
||||
this->clockDist += this->clockRadialSpeed;
|
||||
break;
|
||||
|
||||
case SOTCS_CUEID_DOUBLE_CLOCKS_SPIN:
|
||||
if (play->csCtx.actorCues[cueChannel]->startPos.x != 0) {
|
||||
this->clockSpeed += (u32)play->csCtx.actorCues[cueChannel]->startPos.x;
|
||||
}
|
||||
|
||||
if (play->csCtx.actorCues[cueChannel]->startPos.y != 0) {
|
||||
this->clockColorGray += (s16)play->csCtx.actorCues[cueChannel]->startPos.y;
|
||||
} else {
|
||||
this->clockColorGray -= 4;
|
||||
}
|
||||
break;
|
||||
|
||||
case SOTCS_CUEID_DOUBLE_CLOCKS_OUTWARD:
|
||||
if (play->csCtx.actorCues[cueChannel]->startPos.x != 0) {
|
||||
this->clockSpeed += (u32)play->csCtx.actorCues[cueChannel]->startPos.x;
|
||||
}
|
||||
|
||||
if (play->csCtx.actorCues[cueChannel]->startPos.y != 0) {
|
||||
this->clockColorGray += (s16)play->csCtx.actorCues[cueChannel]->startPos.y;
|
||||
} else {
|
||||
this->clockColorGray -= 8;
|
||||
}
|
||||
|
||||
if (play->csCtx.actorCues[cueChannel]->startPos.z != 0) {
|
||||
this->clockRadialSpeed += (u32)play->csCtx.actorCues[cueChannel]->startPos.z;
|
||||
} else {
|
||||
this->clockRadialSpeed += 20.0f;
|
||||
}
|
||||
|
||||
this->clockDist += this->clockRadialSpeed;
|
||||
if (this->clockDist > 3500.0f) {
|
||||
this->clockDist = 3500.0f;
|
||||
this->cueId = SOTCS_CUEID_NONE;
|
||||
}
|
||||
break;
|
||||
|
||||
case SOTCS_CUEID_RESET_INIT:
|
||||
this->drawType = SOTCS_DRAW_RESET_CYCLE_SOT;
|
||||
this->counter = 0;
|
||||
this->clockAngle = 0;
|
||||
player->actor.shape.shadowDraw = NULL;
|
||||
|
||||
if (play->csCtx.actorCues[cueChannel]->startPos.x != 0) {
|
||||
this->clockSpeed = (u32)play->csCtx.actorCues[cueChannel]->startPos.x;
|
||||
} else {
|
||||
this->clockSpeed = 100.0f;
|
||||
}
|
||||
|
||||
if (play->csCtx.actorCues[cueChannel]->startPos.y != 0) {
|
||||
this->speed = (u32)play->csCtx.actorCues[cueChannel]->startPos.y;
|
||||
} else {
|
||||
this->speed = 20.0f;
|
||||
}
|
||||
|
||||
if (play->csCtx.actorCues[cueChannel]->startPos.z != 0) {
|
||||
this->clockDist = (u32)play->csCtx.actorCues[cueChannel]->startPos.z;
|
||||
} else {
|
||||
this->clockDist = 300.0f;
|
||||
}
|
||||
this->clockAccel = 0.0f;
|
||||
break;
|
||||
|
||||
case SOTCS_CUEID_RESET_CLOCKS_SLOW_DOWN:
|
||||
if (play->csCtx.actorCues[cueChannel]->startPos.x != 0) {
|
||||
this->clockAccel = (u32)play->csCtx.actorCues[cueChannel]->startPos.x;
|
||||
} else {
|
||||
this->clockAccel = -5.0f;
|
||||
}
|
||||
this->clockSpeed += this->clockAccel;
|
||||
break;
|
||||
|
||||
case SOTCS_CUEID_RESET_CLOCKS_SPEED_UP:
|
||||
if (play->csCtx.actorCues[cueChannel]->startPos.x != 0) {
|
||||
this->clockAccel += (u32)play->csCtx.actorCues[cueChannel]->startPos.x;
|
||||
} else {
|
||||
this->clockAccel += 2.0f;
|
||||
}
|
||||
|
||||
this->clockSpeed += this->clockAccel;
|
||||
if (this->clockSpeed > 10000.0f) {
|
||||
this->clockSpeed = 10000.0f;
|
||||
this->cueId = SOTCS_CUEID_NONE;
|
||||
}
|
||||
break;
|
||||
|
||||
case SOTCS_CUEID_NONE:
|
||||
default:
|
||||
this->drawType = SOTCS_DRAW_TYPE_NONE;
|
||||
return;
|
||||
|
||||
case SOTCS_CUEID_DOUBLE_END:
|
||||
Play_SetRespawnData(&play->state, RESPAWN_MODE_RETURN, ((void)0, gSaveContext.save.entrance),
|
||||
player->unk_3CE, PLAYER_PARAMS(0xFF, PLAYER_INITMODE_B), &player->unk_3C0,
|
||||
player->unk_3CC);
|
||||
this->drawType = SOTCS_DRAW_TYPE_NONE;
|
||||
play->transitionTrigger = TRANS_TRIGGER_START;
|
||||
play->nextEntrance = gSaveContext.respawn[RESPAWN_MODE_RETURN].entrance;
|
||||
play->transitionType = TRANS_TYPE_FADE_BLACK;
|
||||
if ((CURRENT_TIME > CLOCK_TIME(18, 0)) || (CURRENT_TIME < CLOCK_TIME(6, 0))) {
|
||||
gSaveContext.respawnFlag = -0x63;
|
||||
SET_EVENTINF(EVENTINF_TRIGGER_DAYTELOP);
|
||||
} else {
|
||||
gSaveContext.respawnFlag = 2;
|
||||
}
|
||||
play->msgCtx.ocarinaMode = OCARINA_MODE_END;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
switch (this->cueId) {
|
||||
case SOTCS_CUEID_DOUBLE_INIT:
|
||||
this->drawType = SOTCS_DRAW_DOUBLE_SOT;
|
||||
this->counter = 0;
|
||||
this->clockAngle = 0;
|
||||
player->actor.shape.shadowDraw = NULL;
|
||||
this->clockColorGray = 38;
|
||||
this->clockSpeed = 150.0f;
|
||||
this->clockDist = 480.0f;
|
||||
|
||||
case SOTCS_CUEID_DOUBLE_WAIT:
|
||||
break;
|
||||
|
||||
case SOTCS_CUEID_DOUBLE_CLOCKS_INWARD:
|
||||
this->clockRadialSpeed = -32.0f;
|
||||
this->clockColorGray += 6;
|
||||
this->clockDist += -32.0f;
|
||||
break;
|
||||
|
||||
case SOTCS_CUEID_DOUBLE_CLOCKS_SPIN:
|
||||
this->clockColorGray -= 4;
|
||||
break;
|
||||
|
||||
case SOTCS_CUEID_DOUBLE_CLOCKS_OUTWARD:
|
||||
this->clockColorGray -= 8;
|
||||
this->clockRadialSpeed += 20.0f;
|
||||
this->clockDist += this->clockRadialSpeed;
|
||||
if (this->clockDist > 3500.0f) {
|
||||
this->clockDist = 3500.0f;
|
||||
this->cueId = SOTCS_CUEID_NONE;
|
||||
}
|
||||
break;
|
||||
|
||||
case SOTCS_CUEID_RESET_INIT:
|
||||
this->drawType = SOTCS_DRAW_RESET_CYCLE_SOT;
|
||||
this->counter = 0;
|
||||
this->clockAngle = 0;
|
||||
player->actor.shape.shadowDraw = NULL;
|
||||
this->clockSpeed = 100.0f;
|
||||
this->speed = 20.0f;
|
||||
this->clockDist = 300.0f;
|
||||
this->clockAccel = 0.0f;
|
||||
break;
|
||||
|
||||
case SOTCS_CUEID_RESET_CLOCKS_SLOW_DOWN:
|
||||
this->clockAccel = -5.0f;
|
||||
this->clockSpeed += -5.0f;
|
||||
break;
|
||||
|
||||
case SOTCS_CUEID_RESET_CLOCKS_SPEED_UP:
|
||||
this->clockAccel += 2.0f;
|
||||
this->clockSpeed += this->clockAccel;
|
||||
if (this->clockSpeed > 10000.0f) {
|
||||
this->clockSpeed = 10000.0f;
|
||||
this->cueId = SOTCS_CUEID_NONE;
|
||||
}
|
||||
break;
|
||||
|
||||
case SOTCS_CUEID_NONE:
|
||||
default:
|
||||
this->drawType = SOTCS_DRAW_TYPE_NONE;
|
||||
return;
|
||||
|
||||
case SOTCS_CUEID_DOUBLE_END:
|
||||
// @recomp Disable scene reset after Double SoT ends.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SoTCsAmmoDrops* sSoTCsAmmoDrops_reloc = KaleidoManager_GetRamAddr(sSoTCsAmmoDrops);
|
||||
if (this->drawType == SOTCS_DRAW_RESET_CYCLE_SOT) {
|
||||
for (i = 0; i < ARRAY_COUNT(sSoTCsAmmoDrops_reloc); i++) {
|
||||
sSoTCsAmmoDrops_reloc[i].pos.x += 2.0f * ((2.0f * Rand_ZeroOne()) - 1.0f);
|
||||
sSoTCsAmmoDrops_reloc[i].pos.z += 2.0f * ((2.0f * Rand_ZeroOne()) - 1.0f);
|
||||
sSoTCsAmmoDrops_reloc[i].pos.y += 3.0f;
|
||||
|
||||
if (player->actor.world.pos.y < sSoTCsAmmoDrops_reloc[i].pos.y) {
|
||||
yDiff = sSoTCsAmmoDrops_reloc[i].pos.y - player->actor.world.pos.y;
|
||||
if (yDiff > 550.0f) {
|
||||
yDiff = 1.0f;
|
||||
} else {
|
||||
yDiff /= 550.0f;
|
||||
}
|
||||
sSoTCsAmmoDrops_reloc[i].scale = SQ(yDiff);
|
||||
} else {
|
||||
sSoTCsAmmoDrops_reloc[i].scale = -10.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
this->counter++;
|
||||
}
|
888
patches/message_patches.c
Normal file
888
patches/message_patches.c
Normal file
@ -0,0 +1,888 @@
|
||||
#include "patches.h"
|
||||
|
||||
extern u8 D_801C6A70;
|
||||
|
||||
extern s32 sCharTexSize;
|
||||
extern s32 sCharTexScale;
|
||||
extern s32 D_801F6B08;
|
||||
|
||||
typedef enum {
|
||||
/* 0 */ PAUSE_ITEM,
|
||||
/* 1 */ PAUSE_MAP,
|
||||
/* 2 */ PAUSE_QUEST,
|
||||
/* 3 */ PAUSE_MASK,
|
||||
/* 4 */ PAUSE_WORLD_MAP
|
||||
} PauseMenuPage;
|
||||
|
||||
typedef enum {
|
||||
/* 0x00 */ PAUSE_STATE_OFF,
|
||||
/* 0x01 */ PAUSE_STATE_OPENING_0,
|
||||
/* 0x02 */ PAUSE_STATE_OPENING_1,
|
||||
/* 0x03 */ PAUSE_STATE_OPENING_2,
|
||||
/* 0x04 */ PAUSE_STATE_OPENING_3,
|
||||
/* 0x05 */ PAUSE_STATE_OPENING_4,
|
||||
/* 0x06 */ PAUSE_STATE_MAIN, // Pause menu ready for player inputs.
|
||||
/* 0x07 */ PAUSE_STATE_SAVEPROMPT,
|
||||
/* 0x08 */ PAUSE_STATE_GAMEOVER_0,
|
||||
/* 0x09 */ PAUSE_STATE_GAMEOVER_1,
|
||||
/* 0x0A */ PAUSE_STATE_GAMEOVER_2,
|
||||
/* 0x0B */ PAUSE_STATE_GAMEOVER_3,
|
||||
/* 0x0C */ PAUSE_STATE_GAMEOVER_4,
|
||||
/* 0x0D */ PAUSE_STATE_GAMEOVER_5,
|
||||
/* 0x0E */ PAUSE_STATE_GAMEOVER_SAVE_PROMPT,
|
||||
/* 0x0F */ PAUSE_STATE_GAMEOVER_7,
|
||||
/* 0x10 */ PAUSE_STATE_GAMEOVER_8,
|
||||
/* 0x11 */ PAUSE_STATE_GAMEOVER_CONTINUE_PROMPT,
|
||||
/* 0x12 */ PAUSE_STATE_GAMEOVER_10,
|
||||
/* 0x13 */ PAUSE_STATE_OWL_WARP_0,
|
||||
/* 0x14 */ PAUSE_STATE_OWL_WARP_1,
|
||||
/* 0x15 */ PAUSE_STATE_OWL_WARP_2,
|
||||
/* 0x16 */ PAUSE_STATE_OWL_WARP_3,
|
||||
/* 0x17 */ PAUSE_STATE_OWL_WARP_SELECT, // Selecting the destination
|
||||
/* 0x18 */ PAUSE_STATE_OWL_WARP_CONFIRM, // Confirming the choice given
|
||||
/* 0x19 */ PAUSE_STATE_OWL_WARP_6,
|
||||
/* 0x1A */ PAUSE_STATE_UNPAUSE_SETUP, // Unpause
|
||||
/* 0x1B */ PAUSE_STATE_UNPAUSE_CLOSE
|
||||
} PauseState;
|
||||
|
||||
extern s16 sLastPlayedSong;
|
||||
|
||||
extern s16 sTextboxUpperYPositions[];
|
||||
extern s16 sTextboxLowerYPositions[];
|
||||
extern s16 sTextboxMidYPositions[];
|
||||
extern s16 sTextboxXPositions[TEXTBOX_TYPE_MAX];
|
||||
|
||||
extern s16 D_801D0464[];
|
||||
extern s16 D_801D045C[];
|
||||
|
||||
void func_80150A84(PlayState* play);
|
||||
void Message_GrowTextbox(PlayState* play);
|
||||
void Message_Decode(PlayState* play);
|
||||
s32 Message_BombersNotebookProcessEventQueue(PlayState* play);
|
||||
void Message_HandleChoiceSelection(PlayState* play, u8 numChoices);
|
||||
bool Message_ShouldAdvanceSilent(PlayState* play);
|
||||
|
||||
void ShrinkWindow_Letterbox_SetSizeTarget(s32 target);
|
||||
s32 ShrinkWindow_Letterbox_GetSizeTarget(void);
|
||||
|
||||
// @recomp Patched to change functionality of Double SoT.
|
||||
void Message_Update(PlayState* play) {
|
||||
static u8 D_801D0468 = 0;
|
||||
MessageContext* msgCtx = &play->msgCtx;
|
||||
SramContext* sramCtx = &play->sramCtx; // Optional
|
||||
PauseContext* pauseCtx = &play->pauseCtx;
|
||||
InterfaceContext* interfaceCtx = &play->interfaceCtx;
|
||||
Input* input = CONTROLLER1(&play->state);
|
||||
s16 avgScreenPosY;
|
||||
s16 screenPosX;
|
||||
u16 temp_v1_2;
|
||||
s16 playerScreenPosY;
|
||||
s16 actorScreenPosY;
|
||||
s16 sp48;
|
||||
s32 sp44;
|
||||
s32 sp40;
|
||||
u16 sp3E;
|
||||
s16 var_v1;
|
||||
u16 temp;
|
||||
|
||||
msgCtx->stickAdjX = input->rel.stick_x;
|
||||
msgCtx->stickAdjY = input->rel.stick_y;
|
||||
|
||||
avgScreenPosY = 0;
|
||||
|
||||
// If stickAdj is held, set a delay to allow the cursor to read the next input.
|
||||
// The first delay is given a longer time than all subsequent delays.
|
||||
if (msgCtx->stickAdjX < -30) {
|
||||
if (msgCtx->stickXRepeatState == -1) {
|
||||
msgCtx->stickXRepeatTimer--;
|
||||
if (msgCtx->stickXRepeatTimer < 0) {
|
||||
// Allow the input to register and apply the delay for all subsequent repeated inputs
|
||||
msgCtx->stickXRepeatTimer = 2;
|
||||
} else {
|
||||
// Cancel the current input
|
||||
msgCtx->stickAdjX = 0;
|
||||
}
|
||||
} else {
|
||||
// Allow the input to register and apply the delay for the first repeated input
|
||||
msgCtx->stickXRepeatTimer = 10;
|
||||
msgCtx->stickXRepeatState = -1;
|
||||
}
|
||||
} else if (msgCtx->stickAdjX > 30) {
|
||||
if (msgCtx->stickXRepeatState == 1) {
|
||||
msgCtx->stickXRepeatTimer--;
|
||||
if (msgCtx->stickXRepeatTimer < 0) {
|
||||
// Allow the input to register and apply the delay for all subsequent repeated inputs
|
||||
msgCtx->stickXRepeatTimer = 2;
|
||||
} else {
|
||||
// Cancel the current input
|
||||
msgCtx->stickAdjX = 0;
|
||||
}
|
||||
} else {
|
||||
// Allow the input to register and apply the delay for the first repeated input
|
||||
msgCtx->stickXRepeatTimer = 10;
|
||||
msgCtx->stickXRepeatState = 1;
|
||||
}
|
||||
} else {
|
||||
msgCtx->stickXRepeatState = 0;
|
||||
}
|
||||
|
||||
if (msgCtx->stickAdjY < -30) {
|
||||
if (msgCtx->stickYRepeatState == -1) {
|
||||
msgCtx->stickYRepeatTimer--;
|
||||
if (msgCtx->stickYRepeatTimer < 0) {
|
||||
// Allow the input to register and apply the delay for all subsequent repeated inputs
|
||||
msgCtx->stickYRepeatTimer = 2;
|
||||
} else {
|
||||
// Cancel the current input
|
||||
msgCtx->stickAdjY = 0;
|
||||
}
|
||||
} else {
|
||||
// Allow the input to register and apply the delay for the first repeated input
|
||||
msgCtx->stickYRepeatTimer = 10;
|
||||
msgCtx->stickYRepeatState = -1;
|
||||
}
|
||||
} else if (msgCtx->stickAdjY > 30) {
|
||||
if (msgCtx->stickYRepeatState == 1) {
|
||||
msgCtx->stickYRepeatTimer--;
|
||||
if (msgCtx->stickYRepeatTimer < 0) {
|
||||
// Allow the input to register and apply the delay for all subsequent repeated inputs
|
||||
msgCtx->stickYRepeatTimer = 2;
|
||||
} else {
|
||||
// Cancel the current input
|
||||
msgCtx->stickAdjY = 0;
|
||||
}
|
||||
} else {
|
||||
// Allow the input to register and apply the delay for the first repeated input
|
||||
msgCtx->stickYRepeatTimer = 10;
|
||||
msgCtx->stickYRepeatState = 1;
|
||||
}
|
||||
} else {
|
||||
msgCtx->stickYRepeatState = 0;
|
||||
}
|
||||
|
||||
if (msgCtx->msgLength == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (msgCtx->msgMode) {
|
||||
case MSGMODE_TEXT_START:
|
||||
D_801C6A70++;
|
||||
|
||||
temp = false;
|
||||
if ((D_801C6A70 >= 4) || ((msgCtx->talkActor == NULL) && (D_801C6A70 >= 2))) {
|
||||
temp = true;
|
||||
}
|
||||
if (temp) {
|
||||
if (msgCtx->talkActor != NULL) {
|
||||
Actor_GetScreenPos(play, &GET_PLAYER(play)->actor, &screenPosX, &playerScreenPosY);
|
||||
Actor_GetScreenPos(play, msgCtx->talkActor, &screenPosX, &actorScreenPosY);
|
||||
if (playerScreenPosY >= actorScreenPosY) {
|
||||
avgScreenPosY = ((playerScreenPosY - actorScreenPosY) / 2) + actorScreenPosY;
|
||||
} else {
|
||||
avgScreenPosY = ((actorScreenPosY - playerScreenPosY) / 2) + playerScreenPosY;
|
||||
}
|
||||
} else {
|
||||
msgCtx->textboxX = msgCtx->textboxXTarget;
|
||||
msgCtx->textboxY = msgCtx->textboxYTarget;
|
||||
}
|
||||
|
||||
var_v1 = msgCtx->textBoxType;
|
||||
|
||||
if ((u32)msgCtx->textBoxPos == 0) {
|
||||
if ((play->sceneId == SCENE_UNSET_04) || (play->sceneId == SCENE_UNSET_05) ||
|
||||
(play->sceneId == SCENE_UNSET_06)) {
|
||||
if (avgScreenPosY < 100) {
|
||||
msgCtx->textboxYTarget = sTextboxLowerYPositions[var_v1];
|
||||
} else {
|
||||
msgCtx->textboxYTarget = sTextboxUpperYPositions[var_v1];
|
||||
}
|
||||
} else {
|
||||
if (avgScreenPosY < 160) {
|
||||
msgCtx->textboxYTarget = sTextboxLowerYPositions[var_v1];
|
||||
} else {
|
||||
msgCtx->textboxYTarget = sTextboxUpperYPositions[var_v1];
|
||||
}
|
||||
}
|
||||
} else if (msgCtx->textBoxPos == 1) {
|
||||
msgCtx->textboxYTarget = sTextboxUpperYPositions[var_v1];
|
||||
} else if (msgCtx->textBoxPos == 2) {
|
||||
msgCtx->textboxYTarget = sTextboxMidYPositions[var_v1];
|
||||
} else if (msgCtx->textBoxPos == 7) {
|
||||
msgCtx->textboxYTarget = 0x9E;
|
||||
} else {
|
||||
msgCtx->textboxYTarget = sTextboxLowerYPositions[var_v1];
|
||||
}
|
||||
|
||||
msgCtx->textboxXTarget = sTextboxXPositions[var_v1];
|
||||
|
||||
if ((gSaveContext.options.language == LANGUAGE_JPN) && !msgCtx->textIsCredits) {
|
||||
msgCtx->unk11FFE[0] = (s16)(msgCtx->textboxYTarget + 7);
|
||||
msgCtx->unk11FFE[1] = (s16)(msgCtx->textboxYTarget + 0x19);
|
||||
msgCtx->unk11FFE[2] = (s16)(msgCtx->textboxYTarget + 0x2B);
|
||||
} else {
|
||||
msgCtx->unk11FFE[0] = (s16)(msgCtx->textboxYTarget + 0x14);
|
||||
msgCtx->unk11FFE[1] = (s16)(msgCtx->textboxYTarget + 0x20);
|
||||
msgCtx->unk11FFE[2] = (s16)(msgCtx->textboxYTarget + 0x2C);
|
||||
}
|
||||
|
||||
if ((msgCtx->textBoxType == TEXTBOX_TYPE_4) || (msgCtx->textBoxType == TEXTBOX_TYPE_5)) {
|
||||
msgCtx->msgMode = MSGMODE_TEXT_STARTING;
|
||||
msgCtx->textboxX = msgCtx->textboxXTarget;
|
||||
msgCtx->textboxY = msgCtx->textboxYTarget;
|
||||
msgCtx->unk12008 = 0x100;
|
||||
msgCtx->unk1200A = 0x40;
|
||||
msgCtx->unk1200C = 0x200;
|
||||
msgCtx->unk1200E = 0x200;
|
||||
break;
|
||||
}
|
||||
|
||||
Message_GrowTextbox(play);
|
||||
Audio_PlaySfx_IfNotInCutscene(NA_SE_NONE);
|
||||
msgCtx->stateTimer = 0;
|
||||
msgCtx->msgMode = MSGMODE_TEXT_BOX_GROWING;
|
||||
|
||||
if (!pauseCtx->itemDescriptionOn) {
|
||||
func_80150A84(play);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MSGMODE_TEXT_BOX_GROWING:
|
||||
Message_GrowTextbox(play);
|
||||
break;
|
||||
|
||||
case MSGMODE_TEXT_STARTING:
|
||||
msgCtx->msgMode = MSGMODE_TEXT_NEXT_MSG;
|
||||
if (!pauseCtx->itemDescriptionOn) {
|
||||
if (msgCtx->currentTextId == 0xFF) {
|
||||
func_8011552C(play, DO_ACTION_STOP);
|
||||
} else if (msgCtx->currentTextId != 0xF8) {
|
||||
func_8011552C(play, DO_ACTION_NEXT);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MSGMODE_TEXT_NEXT_MSG:
|
||||
Message_Decode(play);
|
||||
if (msgCtx->textFade) {
|
||||
Interface_SetHudVisibility(HUD_VISIBILITY_NONE);
|
||||
}
|
||||
if (D_801D0468 != 0) {
|
||||
msgCtx->textDrawPos = msgCtx->decodedTextLen;
|
||||
D_801D0468 = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSGMODE_TEXT_CONTINUING:
|
||||
msgCtx->stateTimer--;
|
||||
if (msgCtx->stateTimer == 0) {
|
||||
Message_Decode(play);
|
||||
}
|
||||
break;
|
||||
|
||||
case MSGMODE_TEXT_DISPLAYING:
|
||||
if (msgCtx->textBoxType != TEXTBOX_TYPE_4) {
|
||||
if (CHECK_BTN_ALL(input->press.button, BTN_B) && !msgCtx->textUnskippable) {
|
||||
msgCtx->textboxSkipped = true;
|
||||
msgCtx->textDrawPos = msgCtx->decodedTextLen;
|
||||
} else if (CHECK_BTN_ALL(input->press.button, BTN_A) && !msgCtx->textUnskippable) {
|
||||
|
||||
while (true) {
|
||||
temp_v1_2 = msgCtx->decodedBuffer.wchar[msgCtx->textDrawPos];
|
||||
if ((temp_v1_2 == 0x10) || (temp_v1_2 == 0x12) || (temp_v1_2 == 0x1B) || (temp_v1_2 == 0x1C) ||
|
||||
(temp_v1_2 == 0x1D) || (temp_v1_2 == 0x19) || (temp_v1_2 == 0xE0) || (temp_v1_2 == 0xBF) ||
|
||||
(temp_v1_2 == 0x15) || (temp_v1_2 == 0x1A)) {
|
||||
break;
|
||||
}
|
||||
msgCtx->textDrawPos++;
|
||||
}
|
||||
}
|
||||
} else if (CHECK_BTN_ALL(input->press.button, BTN_A) && (msgCtx->textUnskippable == 0)) {
|
||||
while (true) {
|
||||
temp_v1_2 = msgCtx->decodedBuffer.wchar[msgCtx->textDrawPos];
|
||||
if ((temp_v1_2 == 0x10) || (temp_v1_2 == 0x12) || (temp_v1_2 == 0x1B) || (temp_v1_2 == 0x1C) ||
|
||||
(temp_v1_2 == 0x1D) || (temp_v1_2 == 0x19) || (temp_v1_2 == 0xE0) || (temp_v1_2 == 0xBF) ||
|
||||
(temp_v1_2 == 0x15) || (temp_v1_2 == 0x1A)) {
|
||||
break;
|
||||
}
|
||||
msgCtx->textDrawPos++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MSGMODE_TEXT_AWAIT_INPUT:
|
||||
if (Message_ShouldAdvance(play)) {
|
||||
msgCtx->msgMode = MSGMODE_TEXT_DISPLAYING;
|
||||
msgCtx->textDrawPos++;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSGMODE_TEXT_DELAYED_BREAK:
|
||||
msgCtx->stateTimer--;
|
||||
if (msgCtx->stateTimer == 0) {
|
||||
msgCtx->msgMode = MSGMODE_TEXT_NEXT_MSG;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSGMODE_TEXT_AWAIT_NEXT:
|
||||
if (Message_ShouldAdvance(play)) {
|
||||
msgCtx->msgMode = MSGMODE_TEXT_NEXT_MSG;
|
||||
msgCtx->msgBufPos++;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSGMODE_TEXT_DONE:
|
||||
if ((msgCtx->textboxEndType == TEXTBOX_ENDTYPE_50) || (msgCtx->textboxEndType == TEXTBOX_ENDTYPE_52)) {
|
||||
msgCtx->stateTimer--;
|
||||
if ((msgCtx->stateTimer == 0) ||
|
||||
((msgCtx->textboxEndType == TEXTBOX_ENDTYPE_52) && Message_ShouldAdvance(play))) {
|
||||
if (msgCtx->nextTextId != 0xFFFF) {
|
||||
Audio_PlaySfx(NA_SE_SY_MESSAGE_PASS);
|
||||
Message_ContinueTextbox(play, msgCtx->nextTextId);
|
||||
} else if (msgCtx->bombersNotebookEventQueueCount != 0) {
|
||||
if (Message_BombersNotebookProcessEventQueue(play) == 0) {
|
||||
Message_CloseTextbox(play);
|
||||
}
|
||||
} else {
|
||||
Message_CloseTextbox(play);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ((msgCtx->textboxEndType == TEXTBOX_ENDTYPE_30) || (msgCtx->textboxEndType == TEXTBOX_ENDTYPE_40) ||
|
||||
(msgCtx->textboxEndType == TEXTBOX_ENDTYPE_42) || (msgCtx->textboxEndType == TEXTBOX_ENDTYPE_41)) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (msgCtx->textboxEndType) {
|
||||
case TEXTBOX_ENDTYPE_55:
|
||||
msgCtx->textColorAlpha += 20;
|
||||
if (msgCtx->textColorAlpha >= 255) {
|
||||
msgCtx->textColorAlpha = 255;
|
||||
msgCtx->textboxEndType = TEXTBOX_ENDTYPE_56;
|
||||
}
|
||||
break;
|
||||
|
||||
case TEXTBOX_ENDTYPE_56:
|
||||
msgCtx->stateTimer--;
|
||||
if (msgCtx->stateTimer == 0) {
|
||||
msgCtx->textboxEndType = TEXTBOX_ENDTYPE_57;
|
||||
}
|
||||
break;
|
||||
|
||||
case TEXTBOX_ENDTYPE_57:
|
||||
msgCtx->textColorAlpha -= 20;
|
||||
if (msgCtx->textColorAlpha <= 0) {
|
||||
msgCtx->textColorAlpha = 0;
|
||||
if (msgCtx->nextTextId != 0xFFFF) {
|
||||
Audio_PlaySfx(NA_SE_SY_MESSAGE_PASS);
|
||||
Message_ContinueTextbox(play, msgCtx->nextTextId);
|
||||
return;
|
||||
}
|
||||
if (msgCtx->bombersNotebookEventQueueCount != 0) {
|
||||
if (Message_BombersNotebookProcessEventQueue(play) == 0) {
|
||||
Message_CloseTextbox(play);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
Message_CloseTextbox(play);
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TEXTBOX_ENDTYPE_10:
|
||||
Message_HandleChoiceSelection(play, 1);
|
||||
break;
|
||||
|
||||
case TEXTBOX_ENDTYPE_11:
|
||||
Message_HandleChoiceSelection(play, 2);
|
||||
break;
|
||||
|
||||
case TEXTBOX_ENDTYPE_12:
|
||||
Message_HandleChoiceSelection(play, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ((msgCtx->textboxEndType == TEXTBOX_ENDTYPE_10) &&
|
||||
(play->msgCtx.ocarinaMode == OCARINA_MODE_ACTIVE)) {
|
||||
if (Message_ShouldAdvance(play)) {
|
||||
if (msgCtx->choiceIndex == 0) {
|
||||
play->msgCtx.ocarinaMode = OCARINA_MODE_WARP;
|
||||
} else {
|
||||
play->msgCtx.ocarinaMode = OCARINA_MODE_END;
|
||||
}
|
||||
Message_CloseTextbox(play);
|
||||
}
|
||||
} else if ((msgCtx->textboxEndType == TEXTBOX_ENDTYPE_10) &&
|
||||
(play->msgCtx.ocarinaMode == OCARINA_MODE_PROCESS_SOT)) {
|
||||
if (Message_ShouldAdvance(play)) {
|
||||
if (msgCtx->choiceIndex == 0) {
|
||||
Audio_PlaySfx_MessageDecide();
|
||||
msgCtx->msgMode = MSGMODE_NEW_CYCLE_0;
|
||||
msgCtx->decodedTextLen -= 3;
|
||||
msgCtx->unk120D6 = 0;
|
||||
msgCtx->unk120D4 = 0;
|
||||
} else {
|
||||
Audio_PlaySfx_MessageCancel();
|
||||
play->msgCtx.ocarinaMode = OCARINA_MODE_END;
|
||||
Message_CloseTextbox(play);
|
||||
}
|
||||
}
|
||||
} else if ((msgCtx->textboxEndType == TEXTBOX_ENDTYPE_10) &&
|
||||
(play->msgCtx.ocarinaMode == OCARINA_MODE_PROCESS_INVERTED_TIME)) {
|
||||
if (Message_ShouldAdvance(play)) {
|
||||
if (msgCtx->choiceIndex == 0) {
|
||||
Audio_PlaySfx_MessageDecide();
|
||||
if (gSaveContext.save.timeSpeedOffset == 0) {
|
||||
play->msgCtx.ocarinaMode = OCARINA_MODE_APPLY_INV_SOT_SLOW;
|
||||
gSaveContext.save.timeSpeedOffset = -2;
|
||||
} else {
|
||||
play->msgCtx.ocarinaMode = OCARINA_MODE_APPLY_INV_SOT_FAST;
|
||||
gSaveContext.save.timeSpeedOffset = 0;
|
||||
}
|
||||
Message_CloseTextbox(play);
|
||||
} else {
|
||||
Audio_PlaySfx_MessageCancel();
|
||||
play->msgCtx.ocarinaMode = OCARINA_MODE_END;
|
||||
Message_CloseTextbox(play);
|
||||
}
|
||||
}
|
||||
} else if ((msgCtx->textboxEndType == TEXTBOX_ENDTYPE_10) &&
|
||||
(play->msgCtx.ocarinaMode == OCARINA_MODE_PROCESS_DOUBLE_TIME)) {
|
||||
// @recomp
|
||||
dsot_handle_hour_selection(play);
|
||||
|
||||
if (Message_ShouldAdvance(play)) {
|
||||
if (msgCtx->choiceIndex == 0) {
|
||||
Audio_PlaySfx_MessageDecide();
|
||||
|
||||
play->msgCtx.ocarinaMode = OCARINA_MODE_APPLY_DOUBLE_SOT;
|
||||
gSaveContext.timerStates[TIMER_ID_MOON_CRASH] = TIMER_STATE_OFF;
|
||||
} else {
|
||||
Audio_PlaySfx_MessageCancel();
|
||||
play->msgCtx.ocarinaMode = OCARINA_MODE_END;
|
||||
|
||||
// @recomp
|
||||
dsot_cancel_hour_selection(play);
|
||||
}
|
||||
Message_CloseTextbox(play);
|
||||
}
|
||||
} else if ((msgCtx->textboxEndType != TEXTBOX_ENDTYPE_10) ||
|
||||
(pauseCtx->state != PAUSE_STATE_OWL_WARP_CONFIRM)) {
|
||||
if ((msgCtx->textboxEndType == TEXTBOX_ENDTYPE_10) &&
|
||||
(play->msgCtx.ocarinaMode == OCARINA_MODE_1B)) {
|
||||
if (Message_ShouldAdvance(play)) {
|
||||
if (msgCtx->choiceIndex == 0) {
|
||||
Audio_PlaySfx_MessageDecide();
|
||||
play->msgCtx.ocarinaMode = OCARINA_MODE_WARP_TO_ENTRANCE;
|
||||
} else {
|
||||
Audio_PlaySfx_MessageCancel();
|
||||
play->msgCtx.ocarinaMode = OCARINA_MODE_END;
|
||||
}
|
||||
Message_CloseTextbox(play);
|
||||
}
|
||||
} else if ((msgCtx->textboxEndType == TEXTBOX_ENDTYPE_60) ||
|
||||
(msgCtx->textboxEndType == TEXTBOX_ENDTYPE_61) ||
|
||||
(msgCtx->textboxEndType == TEXTBOX_ENDTYPE_10) ||
|
||||
(msgCtx->textboxEndType == TEXTBOX_ENDTYPE_11) ||
|
||||
(msgCtx->textboxEndType == TEXTBOX_ENDTYPE_50) ||
|
||||
(msgCtx->textboxEndType == TEXTBOX_ENDTYPE_52) ||
|
||||
(msgCtx->textboxEndType == TEXTBOX_ENDTYPE_55) ||
|
||||
(msgCtx->textboxEndType == TEXTBOX_ENDTYPE_56) ||
|
||||
(msgCtx->textboxEndType == TEXTBOX_ENDTYPE_57) ||
|
||||
(msgCtx->textboxEndType == TEXTBOX_ENDTYPE_62)) {
|
||||
//! FAKE: debug?
|
||||
if (msgCtx->textboxEndType == TEXTBOX_ENDTYPE_50) {}
|
||||
} else if (pauseCtx->itemDescriptionOn) {
|
||||
if ((input->rel.stick_x != 0) || (input->rel.stick_y != 0) ||
|
||||
CHECK_BTN_ALL(input->press.button, BTN_A) || CHECK_BTN_ALL(input->press.button, BTN_B) ||
|
||||
CHECK_BTN_ALL(input->press.button, BTN_START)) {
|
||||
Audio_PlaySfx(NA_SE_SY_DECIDE);
|
||||
Message_CloseTextbox(play);
|
||||
}
|
||||
} else if (play->msgCtx.ocarinaMode == OCARINA_MODE_PROCESS_RESTRICTED_SONG) {
|
||||
if (Message_ShouldAdvanceSilent(play)) {
|
||||
Audio_PlaySfx(NA_SE_SY_DECIDE);
|
||||
Message_CloseTextbox(play);
|
||||
play->msgCtx.ocarinaMode = OCARINA_MODE_END;
|
||||
}
|
||||
} else if ((msgCtx->currentTextId != 0x2790) && Message_ShouldAdvanceSilent(play)) {
|
||||
if (msgCtx->nextTextId != 0xFFFF) {
|
||||
Audio_PlaySfx(NA_SE_SY_MESSAGE_PASS);
|
||||
Message_ContinueTextbox(play, msgCtx->nextTextId);
|
||||
} else if ((msgCtx->bombersNotebookEventQueueCount == 0) ||
|
||||
(Message_BombersNotebookProcessEventQueue(play) != 1)) {
|
||||
if (msgCtx->currentTextId == 0x579) {
|
||||
gSaveContext.hudVisibility = HUD_VISIBILITY_IDLE;
|
||||
}
|
||||
Audio_PlaySfx(NA_SE_SY_DECIDE);
|
||||
Message_CloseTextbox(play);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MSGMODE_TEXT_CLOSING:
|
||||
msgCtx->stateTimer--;
|
||||
if (msgCtx->stateTimer != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (sLastPlayedSong == OCARINA_SONG_SOARING) {
|
||||
if (interfaceCtx->restrictions.songOfSoaring == 0) {
|
||||
if (func_8010A0A4(play) || (play->sceneId == SCENE_SECOM)) {
|
||||
Message_StartTextbox(play, 0x1B93, NULL);
|
||||
play->msgCtx.ocarinaMode = OCARINA_MODE_1B;
|
||||
sLastPlayedSong = 0xFF;
|
||||
} else if (!msgCtx->ocarinaSongEffectActive) {
|
||||
if (gSaveContext.save.saveInfo.playerData.owlActivationFlags != 0) {
|
||||
pauseCtx->unk_2C8 = pauseCtx->pageIndex;
|
||||
pauseCtx->unk_2CA = pauseCtx->cursorPoint[4];
|
||||
pauseCtx->pageIndex = PAUSE_ITEM;
|
||||
pauseCtx->state = PAUSE_STATE_OWL_WARP_0;
|
||||
func_800F4A10(play);
|
||||
pauseCtx->pageIndex = PAUSE_MAP;
|
||||
sLastPlayedSong = 0xFF;
|
||||
Message_CloseTextbox(play);
|
||||
play->msgCtx.ocarinaMode = OCARINA_MODE_END;
|
||||
gSaveContext.prevHudVisibility = HUD_VISIBILITY_A_B;
|
||||
func_80115844(play, DO_ACTION_STOP);
|
||||
GameState_SetFramerateDivisor(&play->state, 2);
|
||||
if (ShrinkWindow_Letterbox_GetSizeTarget() != 0) {
|
||||
ShrinkWindow_Letterbox_SetSizeTarget(0);
|
||||
}
|
||||
Audio_PlaySfx_PauseMenuOpenOrClose(1);
|
||||
break;
|
||||
}
|
||||
sLastPlayedSong = 0xFF;
|
||||
Message_StartTextbox(play, 0xFB, NULL);
|
||||
play->msgCtx.ocarinaMode = OCARINA_MODE_PROCESS_RESTRICTED_SONG;
|
||||
} else {
|
||||
msgCtx->stateTimer = 1;
|
||||
}
|
||||
} else {
|
||||
sLastPlayedSong = 0xFF;
|
||||
Message_StartTextbox(play, 0x1B95, NULL);
|
||||
play->msgCtx.ocarinaMode = OCARINA_MODE_PROCESS_RESTRICTED_SONG;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if ((msgCtx->currentTextId == 0xC) || (msgCtx->currentTextId == 0xD) || (msgCtx->currentTextId == 0xC5) ||
|
||||
(msgCtx->currentTextId == 0xC6) || (msgCtx->currentTextId == 0xC7) ||
|
||||
(msgCtx->currentTextId == 0x2165) || (msgCtx->currentTextId == 0x2166) ||
|
||||
(msgCtx->currentTextId == 0x2167) || (msgCtx->currentTextId == 0x2168)) {
|
||||
gSaveContext.healthAccumulator = 20 * 0x10; // Refill 20 hearts
|
||||
}
|
||||
|
||||
if ((play->csCtx.state == CS_STATE_IDLE) && (gSaveContext.save.cutsceneIndex < 0xFFF0) &&
|
||||
((play->activeCamId == CAM_ID_MAIN) ||
|
||||
((play->transitionTrigger == TRANS_TRIGGER_OFF) && (play->transitionMode == TRANS_MODE_OFF))) &&
|
||||
(play->msgCtx.ocarinaMode == OCARINA_MODE_END)) {
|
||||
if (((u32)gSaveContext.prevHudVisibility == HUD_VISIBILITY_IDLE) ||
|
||||
(gSaveContext.prevHudVisibility == HUD_VISIBILITY_NONE) ||
|
||||
(gSaveContext.prevHudVisibility == HUD_VISIBILITY_NONE_ALT)) {
|
||||
gSaveContext.prevHudVisibility = HUD_VISIBILITY_ALL;
|
||||
}
|
||||
gSaveContext.hudVisibility = HUD_VISIBILITY_IDLE;
|
||||
}
|
||||
|
||||
if ((msgCtx->currentTextId >= 0x1BB2) && (msgCtx->currentTextId <= 0x1BB6) &&
|
||||
(play->actorCtx.flags & ACTORCTX_FLAG_TELESCOPE_ON)) {
|
||||
Message_StartTextbox(play, 0x5E6, NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
if (msgCtx->bombersNotebookEventQueueCount != 0) {
|
||||
if (Message_BombersNotebookProcessEventQueue(play) == 0) {
|
||||
msgCtx->stateTimer = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
msgCtx->msgLength = 0;
|
||||
msgCtx->msgMode = MSGMODE_NONE;
|
||||
msgCtx->currentTextId = 0;
|
||||
msgCtx->stateTimer = 0;
|
||||
XREG(31) = 0;
|
||||
|
||||
if (pauseCtx->itemDescriptionOn) {
|
||||
func_8011552C(play, DO_ACTION_INFO);
|
||||
pauseCtx->itemDescriptionOn = false;
|
||||
}
|
||||
|
||||
if (msgCtx->textboxEndType == TEXTBOX_ENDTYPE_30) {
|
||||
msgCtx->textboxEndType = TEXTBOX_ENDTYPE_00;
|
||||
play->msgCtx.ocarinaMode = OCARINA_MODE_WARP;
|
||||
} else {
|
||||
msgCtx->textboxEndType = TEXTBOX_ENDTYPE_00;
|
||||
}
|
||||
|
||||
if (EQ_MAX_QUEST_HEART_PIECE_COUNT) {
|
||||
RESET_HEART_PIECE_COUNT;
|
||||
gSaveContext.save.saveInfo.playerData.healthCapacity += 0x10;
|
||||
gSaveContext.save.saveInfo.playerData.health += 0x10;
|
||||
}
|
||||
|
||||
if (msgCtx->ocarinaAction != OCARINA_ACTION_CHECK_NOTIME_DONE) {
|
||||
s16 pad;
|
||||
|
||||
if (sLastPlayedSong == OCARINA_SONG_TIME) {
|
||||
if (interfaceCtx->restrictions.songOfTime == 0) {
|
||||
Message_StartTextbox(play, 0x1B8A, NULL);
|
||||
play->msgCtx.ocarinaMode = OCARINA_MODE_PROCESS_SOT;
|
||||
} else {
|
||||
sLastPlayedSong = 0xFF;
|
||||
Message_StartTextbox(play, 0x1B95, NULL);
|
||||
play->msgCtx.ocarinaMode = OCARINA_MODE_PROCESS_RESTRICTED_SONG;
|
||||
}
|
||||
} else if (sLastPlayedSong == OCARINA_SONG_INVERTED_TIME) {
|
||||
if (interfaceCtx->restrictions.invSongOfTime == 0) {
|
||||
if (R_TIME_SPEED != 0) {
|
||||
if (gSaveContext.save.timeSpeedOffset == 0) {
|
||||
Message_StartTextbox(play, 0x1B8C, NULL);
|
||||
} else {
|
||||
Message_StartTextbox(play, 0x1B8D, NULL);
|
||||
}
|
||||
play->msgCtx.ocarinaMode = OCARINA_MODE_PROCESS_INVERTED_TIME;
|
||||
} else {
|
||||
Message_StartTextbox(play, 0x1B8B, NULL);
|
||||
play->msgCtx.ocarinaMode = OCARINA_MODE_END;
|
||||
}
|
||||
} else {
|
||||
sLastPlayedSong = 0xFF;
|
||||
Message_StartTextbox(play, 0x1B95, NULL);
|
||||
play->msgCtx.ocarinaMode = OCARINA_MODE_PROCESS_RESTRICTED_SONG;
|
||||
}
|
||||
} else if (sLastPlayedSong == OCARINA_SONG_DOUBLE_TIME) {
|
||||
// @recomp Patch Song of Double Time.
|
||||
if (interfaceCtx->restrictions.songOfDoubleTime == 0) {
|
||||
if ((CURRENT_DAY != 3) || (CURRENT_TIME < CLOCK_TIME(5, 0)) || (CURRENT_TIME >= CLOCK_TIME(6, 0))) {
|
||||
Message_StartTextbox(play, D_801D0464[0], NULL);
|
||||
|
||||
// @recomp Replace message text.
|
||||
char *buf = play->msgCtx.font.msgBuf.schar;
|
||||
buf[25] = ' ';
|
||||
buf[26] = 1;
|
||||
buf[27] = 'S';
|
||||
buf[28] = 'e';
|
||||
buf[29] = 'l';
|
||||
buf[30] = 'e';
|
||||
buf[31] = 'c';
|
||||
buf[32] = 't';
|
||||
buf[33] = 'e';
|
||||
buf[34] = 'd';
|
||||
buf[35] = ' ';
|
||||
buf[36] = 'H';
|
||||
buf[37] = 'o';
|
||||
buf[38] = 'u';
|
||||
buf[39] = 'r';
|
||||
buf[40] = 0;
|
||||
buf[41] = '?';
|
||||
buf[42] = 17;
|
||||
buf[43] = 17;
|
||||
buf[44] = 2;
|
||||
buf[45] = -62;
|
||||
buf[46] = 'Y';
|
||||
buf[47] = 'e';
|
||||
buf[48] = 's';
|
||||
buf[49] = 17;
|
||||
buf[50] = 'N';
|
||||
buf[51] = 'o';
|
||||
buf[52] = -65;
|
||||
|
||||
play->msgCtx.ocarinaMode = OCARINA_MODE_PROCESS_DOUBLE_TIME;
|
||||
|
||||
// @recomp
|
||||
dsot_init_hour_selection(play);
|
||||
} else {
|
||||
Message_StartTextbox(play, 0x1B94, NULL);
|
||||
play->msgCtx.ocarinaMode = OCARINA_MODE_END;
|
||||
}
|
||||
} else {
|
||||
sLastPlayedSong = 0xFF;
|
||||
Message_StartTextbox(play, 0x1B95, NULL);
|
||||
play->msgCtx.ocarinaMode = OCARINA_MODE_PROCESS_RESTRICTED_SONG;
|
||||
}
|
||||
} else if ((msgCtx->ocarinaAction == OCARINA_ACTION_FREE_PLAY_DONE) &&
|
||||
((play->msgCtx.ocarinaMode == OCARINA_MODE_ACTIVE) ||
|
||||
(play->msgCtx.ocarinaMode == OCARINA_MODE_EVENT) ||
|
||||
(play->msgCtx.ocarinaMode == OCARINA_MODE_PLAYED_SCARECROW_SPAWN) ||
|
||||
(play->msgCtx.ocarinaMode == OCARINA_MODE_PLAYED_FULL_EVAN_SONG))) {
|
||||
play->msgCtx.ocarinaMode = OCARINA_MODE_END;
|
||||
if (msgCtx->lastPlayedSong == OCARINA_SONG_SOARING) {
|
||||
play->msgCtx.ocarinaMode = OCARINA_MODE_ACTIVE;
|
||||
}
|
||||
}
|
||||
sLastPlayedSong = 0xFF;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSGMODE_OCARINA_PLAYING:
|
||||
if (CHECK_BTN_ALL(input->press.button, BTN_B)) {
|
||||
AudioOcarina_SetInstrument(OCARINA_INSTRUMENT_OFF);
|
||||
play->msgCtx.ocarinaMode = OCARINA_MODE_END;
|
||||
Message_CloseTextbox(play);
|
||||
} else {
|
||||
msgCtx->ocarinaButtonIndex = OCARINA_BTN_INVALID;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSGMODE_OCARINA_AWAIT_INPUT:
|
||||
if ((msgCtx->ocarinaAction != OCARINA_ACTION_PROMPT_EVAN_PART1_SECOND_HALF) &&
|
||||
(msgCtx->ocarinaAction != OCARINA_ACTION_PROMPT_EVAN_PART2_SECOND_HALF)) {
|
||||
if (Message_ShouldAdvance(play)) {
|
||||
Message_DisplayOcarinaStaff(play, msgCtx->ocarinaAction);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MSGMODE_SCARECROW_SPAWN_RECORDING_ONGOING:
|
||||
if (CHECK_BTN_ALL(input->press.button, BTN_B)) {
|
||||
AudioOcarina_SetRecordingState(OCARINA_RECORD_OFF);
|
||||
Audio_PlaySfx(NA_SE_SY_OCARINA_ERROR);
|
||||
Message_CloseTextbox(play);
|
||||
msgCtx->msgMode = MSGMODE_SCARECROW_SPAWN_RECORDING_FAILED;
|
||||
} else {
|
||||
msgCtx->ocarinaButtonIndex = OCARINA_BTN_INVALID;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSGMODE_SCENE_TITLE_CARD_FADE_IN_BACKGROUND:
|
||||
msgCtx->textboxColorAlphaCurrent += XREG(73);
|
||||
if (msgCtx->textboxColorAlphaCurrent >= 255) {
|
||||
msgCtx->textboxColorAlphaCurrent = 255;
|
||||
msgCtx->msgMode = MSGMODE_SCENE_TITLE_CARD_FADE_IN_TEXT;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSGMODE_SCENE_TITLE_CARD_FADE_IN_TEXT:
|
||||
msgCtx->textColorAlpha += XREG(73);
|
||||
if (msgCtx->textColorAlpha >= 255) {
|
||||
msgCtx->textColorAlpha = 255;
|
||||
msgCtx->msgMode = MSGMODE_SCENE_TITLE_CARD_DISPLAYING;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSGMODE_SCENE_TITLE_CARD_DISPLAYING:
|
||||
msgCtx->stateTimer--;
|
||||
if (msgCtx->stateTimer == 0) {
|
||||
msgCtx->msgMode = MSGMODE_SCENE_TITLE_CARD_FADE_OUT_TEXT;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSGMODE_SCENE_TITLE_CARD_FADE_OUT_TEXT:
|
||||
msgCtx->textColorAlpha -= XREG(70);
|
||||
if (msgCtx->textColorAlpha <= 0) {
|
||||
msgCtx->textColorAlpha = 0;
|
||||
msgCtx->msgMode = MSGMODE_SCENE_TITLE_CARD_FADE_OUT_BACKGROUND;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSGMODE_SCENE_TITLE_CARD_FADE_OUT_BACKGROUND:
|
||||
msgCtx->textboxColorAlphaCurrent -= XREG(70);
|
||||
if (msgCtx->textboxColorAlphaCurrent <= 0) {
|
||||
if ((msgCtx->currentTextId >= 0x1BB2) && (msgCtx->currentTextId <= 0x1BB6) &&
|
||||
(play->actorCtx.flags & ACTORCTX_FLAG_TELESCOPE_ON)) {
|
||||
Message_StartTextbox(play, 0x5E6, NULL);
|
||||
Interface_SetHudVisibility(HUD_VISIBILITY_NONE_ALT);
|
||||
} else {
|
||||
//! FAKE: debug?
|
||||
if (msgCtx->currentTextId >= 0x100) {
|
||||
if (msgCtx && msgCtx && msgCtx) {}
|
||||
}
|
||||
msgCtx->textboxColorAlphaCurrent = 0;
|
||||
msgCtx->msgLength = 0;
|
||||
msgCtx->msgMode = MSGMODE_NONE;
|
||||
msgCtx->currentTextId = 0;
|
||||
msgCtx->stateTimer = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MSGMODE_NEW_CYCLE_0:
|
||||
play->state.unk_A3 = 1;
|
||||
sp44 = gSaveContext.save.cutsceneIndex;
|
||||
sp3E = CURRENT_TIME;
|
||||
sp40 = gSaveContext.save.day;
|
||||
|
||||
Sram_SaveEndOfCycle(play);
|
||||
gSaveContext.timerStates[TIMER_ID_MOON_CRASH] = TIMER_STATE_OFF;
|
||||
func_8014546C(&play->sramCtx);
|
||||
|
||||
gSaveContext.save.day = sp40;
|
||||
gSaveContext.save.time = sp3E;
|
||||
gSaveContext.save.cutsceneIndex = sp44;
|
||||
|
||||
if (gSaveContext.fileNum != 0xFF) {
|
||||
Sram_SetFlashPagesDefault(&play->sramCtx, gFlashSaveStartPages[gSaveContext.fileNum * 2],
|
||||
gFlashSpecialSaveNumPages[gSaveContext.fileNum * 2]);
|
||||
Sram_StartWriteToFlashDefault(&play->sramCtx);
|
||||
}
|
||||
msgCtx->msgMode = MSGMODE_NEW_CYCLE_1;
|
||||
break;
|
||||
|
||||
case MSGMODE_NEW_CYCLE_1:
|
||||
if (gSaveContext.fileNum != 0xFF) {
|
||||
play->state.unk_A3 = 1;
|
||||
if (play->sramCtx.status == 0) {
|
||||
play->msgCtx.ocarinaMode = OCARINA_MODE_APPLY_SOT;
|
||||
msgCtx->msgMode = MSGMODE_NEW_CYCLE_2;
|
||||
}
|
||||
} else {
|
||||
play->msgCtx.ocarinaMode = OCARINA_MODE_APPLY_SOT;
|
||||
msgCtx->msgMode = MSGMODE_NEW_CYCLE_2;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSGMODE_OWL_SAVE_0:
|
||||
play->state.unk_A3 = 1;
|
||||
gSaveContext.save.isOwlSave = true;
|
||||
Play_SaveCycleSceneFlags(&play->state);
|
||||
func_8014546C(&play->sramCtx);
|
||||
|
||||
if (gSaveContext.fileNum != 0xFF) {
|
||||
Sram_SetFlashPagesOwlSave(&play->sramCtx, gFlashOwlSaveStartPages[gSaveContext.fileNum * 2],
|
||||
gFlashOwlSaveNumPages[gSaveContext.fileNum * 2]);
|
||||
Sram_StartWriteToFlashOwlSave(&play->sramCtx);
|
||||
}
|
||||
msgCtx->msgMode = MSGMODE_OWL_SAVE_1;
|
||||
break;
|
||||
|
||||
case MSGMODE_OWL_SAVE_1:
|
||||
if (gSaveContext.fileNum != 0xFF) {
|
||||
play->state.unk_A3 = 1;
|
||||
if (play->sramCtx.status == 0) {
|
||||
play->msgCtx.ocarinaMode = OCARINA_MODE_APPLY_SOT;
|
||||
msgCtx->msgMode = MSGMODE_OWL_SAVE_2;
|
||||
}
|
||||
} else {
|
||||
play->msgCtx.ocarinaMode = OCARINA_MODE_APPLY_SOT;
|
||||
msgCtx->msgMode = MSGMODE_OWL_SAVE_2;
|
||||
}
|
||||
|
||||
if (msgCtx->msgMode == MSGMODE_OWL_SAVE_2) {
|
||||
gSaveContext.gameMode = GAMEMODE_OWL_SAVE;
|
||||
play->transitionTrigger = TRANS_TRIGGER_START;
|
||||
play->transitionType = TRANS_TYPE_FADE_BLACK;
|
||||
play->nextEntrance = ENTRANCE(CUTSCENE, 0);
|
||||
gSaveContext.save.cutsceneIndex = 0;
|
||||
gSaveContext.sceneLayer = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSGMODE_9:
|
||||
case MSGMODE_PAUSED:
|
||||
case MSGMODE_NEW_CYCLE_2:
|
||||
case MSGMODE_OWL_SAVE_2:
|
||||
break;
|
||||
|
||||
default:
|
||||
msgCtx->ocarinaButtonIndex = OCARINA_BTN_INVALID;
|
||||
break;
|
||||
}
|
||||
}
|
@ -108,4 +108,10 @@ void draw_autosave_icon(PlayState* play);
|
||||
|
||||
void recomp_crash(const char* err);
|
||||
|
||||
void dsot_init_hour_selection(PlayState* play);
|
||||
void dsot_handle_hour_selection(PlayState* play);
|
||||
void dsot_cancel_hour_selection(PlayState* play);
|
||||
void dsot_advance_hour(PlayState* play);
|
||||
void dsot_draw_clock(PlayState* play);
|
||||
|
||||
#endif
|
||||
|
@ -990,6 +990,11 @@ void Message_DrawTextBox(PlayState* play, Gfx** gfxP) {
|
||||
gSPPopMatrix(gfx++, G_MTX_MODELVIEW);
|
||||
}
|
||||
|
||||
// @recomp Draw clock for Double SoT.
|
||||
if (play->msgCtx.ocarinaMode == OCARINA_MODE_PROCESS_DOUBLE_TIME) {
|
||||
dsot_draw_clock(play);
|
||||
}
|
||||
|
||||
// Draw treble clef
|
||||
if (msgCtx->textBoxType == TEXTBOX_TYPE_3) {
|
||||
gDPPipeSync(gfx++);
|
||||
|
Loading…
Reference in New Issue
Block a user