mirror of
https://github.com/Mr-Wiseguy/Zelda64Recomp.git
synced 2024-11-16 19:09:15 +01:00
Compare commits
3 Commits
b09f2ba287
...
6fcb75df24
Author | SHA1 | Date | |
---|---|---|---|
|
6fcb75df24 | ||
|
a6e69066b2 | ||
|
2d0ce9f68d |
@ -268,7 +268,7 @@
|
||||
data-checked="analog_camera_invert_mode"
|
||||
value="InvertNone"
|
||||
id="analog_camera_inversion_none"
|
||||
style="nav-up: #analog_cam_enabled;"
|
||||
style="nav-up: #analog_cam_enabled; nav-down: #dsot_enabled"
|
||||
/>
|
||||
<label class="config-option__tab-label" for="analog_camera_inversion_none">None</label>
|
||||
|
||||
@ -280,7 +280,7 @@
|
||||
data-checked="analog_camera_invert_mode"
|
||||
value="InvertX"
|
||||
id="analog_camera_inversion_x"
|
||||
style="nav-up: #analog_cam_disabled;"
|
||||
style="nav-up: #analog_cam_disabled; nav-down: #dsot_disabled"
|
||||
/>
|
||||
<label class="config-option__tab-label" for="analog_camera_inversion_x">Invert X</label>
|
||||
|
||||
@ -292,7 +292,7 @@
|
||||
data-checked="analog_camera_invert_mode"
|
||||
value="InvertY"
|
||||
id="analog_camera_inversion_y"
|
||||
style="nav-up: #analog_cam_disabled;"
|
||||
style="nav-up: #analog_cam_disabled; nav-down: #dsot_disabled"
|
||||
/>
|
||||
<label class="config-option__tab-label" for="analog_camera_inversion_y">Invert Y</label>
|
||||
|
||||
@ -304,11 +304,40 @@
|
||||
data-checked="analog_camera_invert_mode"
|
||||
value="InvertBoth"
|
||||
id="analog_camera_inversion_both"
|
||||
style="nav-up: #analog_cam_disabled;"
|
||||
style="nav-up: #analog_cam_disabled; nav-down: #dsot_disabled"
|
||||
/>
|
||||
<label class="config-option__tab-label" for="analog_camera_inversion_both">Invert Both</label>
|
||||
</div>
|
||||
</div>
|
||||
<!-- better double song of time -->
|
||||
<div class="config-option" data-event-mouseover="set_cur_config_index(10)">
|
||||
<label class="config-option__title">Better Double Song of Time</label>
|
||||
<div class="config-option__list">
|
||||
<input
|
||||
type="radio"
|
||||
data-event-blur="set_cur_config_index(-1)"
|
||||
data-event-focus="set_cur_config_index(10)"
|
||||
name="dsot_mode"
|
||||
data-checked="dsot_mode"
|
||||
value="On"
|
||||
id="dsot_enabled"
|
||||
style="nav-up: #analog_camera_inversion_none"
|
||||
/>
|
||||
<label class="config-option__tab-label" for="dsot_enabled">On</label>
|
||||
|
||||
<input
|
||||
type="radio"
|
||||
data-event-blur="set_cur_config_index(-1)"
|
||||
data-event-focus="set_cur_config_index(10)"
|
||||
name="dsot_mode"
|
||||
data-checked="dsot_mode"
|
||||
value="Off"
|
||||
id="dsot_disabled"
|
||||
style="nav-up: #analog_camera_inversion_x"
|
||||
/>
|
||||
<label class="config-option__tab-label" for="dsot_disabled">Off</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Descriptions -->
|
||||
<div class="config__wrapper">
|
||||
@ -362,6 +391,12 @@
|
||||
<p data-if="cur_config_index == 9">
|
||||
Inverts the camera controls for the analog camera if it's enabled. <b>None</b> is the default.
|
||||
</p>
|
||||
<p data-if="cur_config_index == 10">
|
||||
Enables hour selection for Double Song of Time.
|
||||
<br/>
|
||||
<br/>
|
||||
To select an hour move the left analog stick in horizontal axis.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -79,6 +79,17 @@ namespace zelda64 {
|
||||
{zelda64::AnalogCamMode::Off, "Off"}
|
||||
});
|
||||
|
||||
enum class DsotMode {
|
||||
On,
|
||||
Off,
|
||||
OptionCount
|
||||
};
|
||||
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM(zelda64::DsotMode, {
|
||||
{zelda64::DsotMode::On, "On"},
|
||||
{zelda64::DsotMode::Off, "Off"}
|
||||
});
|
||||
|
||||
AutosaveMode get_autosave_mode();
|
||||
void set_autosave_mode(AutosaveMode mode);
|
||||
|
||||
@ -86,6 +97,9 @@ namespace zelda64 {
|
||||
void set_analog_cam_mode(AnalogCamMode mode);
|
||||
|
||||
void open_quit_game_prompt();
|
||||
|
||||
DsotMode get_dsot_mode();
|
||||
void set_dsot_mode(DsotMode mode);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
403
patches/better_double_sot.c
Normal file
403
patches/better_double_sot.c
Normal file
@ -0,0 +1,403 @@
|
||||
#include "patches.h"
|
||||
|
||||
void dsot_load_day_number_texture(PlayState* play, s32 day);
|
||||
void dsot_actor_fixes(PlayState* play);
|
||||
|
||||
bool dsot_on;
|
||||
|
||||
void dsot_determine_enabled(void) {
|
||||
dsot_on = recomp_dsot_enabled();
|
||||
}
|
||||
|
||||
bool dsot_enabled(void) {
|
||||
return dsot_on;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
// 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.
|
||||
play->envCtx.timeSeqState = TIMESEQ_FADE_DAY_BGM;
|
||||
|
||||
if ((CURRENT_TIME >= CLOCK_TIME(18, 0)) || (CURRENT_TIME <= CLOCK_TIME(6,0))) {
|
||||
SEQCMD_STOP_SEQUENCE(SEQ_PLAYER_BGM_MAIN, 0);
|
||||
play->envCtx.timeSeqState = TIMESEQ_NIGHT_BEGIN_SFX;
|
||||
} 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_En_Test4/z_en_test4.h"
|
||||
#include "overlays/actors/ovl_Obj_Tokei_Step/z_obj_tokei_step.h"
|
||||
#include "overlays/actors/ovl_Obj_Tokeidai/z_obj_tokeidai.h"
|
||||
|
||||
void dsot_ObjEnTest4_fix(EnTest4* this, PlayState* play);
|
||||
void dsot_ObjTokeiStep_fix(ObjTokeiStep* this, PlayState* play);
|
||||
void dsot_ObjTokeidai_fix(ObjTokeidai* 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_EN_TEST4:
|
||||
dsot_ObjEnTest4_fix(actor, play);
|
||||
break;
|
||||
case ACTOR_OBJ_TOKEI_STEP:
|
||||
dsot_ObjTokeiStep_fix(actor, play);
|
||||
break;
|
||||
case ACTOR_OBJ_TOKEIDAI:
|
||||
dsot_ObjTokeidai_fix(actor, play);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define PAST_MIDNIGHT ((CURRENT_DAY == 3) && (CURRENT_TIME < CLOCK_TIME(6, 0)) && (CURRENT_TIME > CLOCK_TIME(0, 0)))
|
||||
|
||||
// z_obj_en_test_4
|
||||
void func_80A42198(EnTest4* this); // EnTest4_GetBellTimeOnDay3
|
||||
|
||||
void dsot_ObjEnTest4_fix(EnTest4* this, PlayState* play) {
|
||||
this->prevTime = CURRENT_TIME;
|
||||
this->prevBellTime = CURRENT_TIME;
|
||||
|
||||
// Change daytime to night manually if necessary.
|
||||
if ((this->daytimeIndex = THREEDAY_DAYTIME_DAY) && (CURRENT_TIME > CLOCK_TIME(18, 0)) || (CURRENT_TIME <= CLOCK_TIME(6, 0))) {
|
||||
this->daytimeIndex = THREEDAY_DAYTIME_NIGHT;
|
||||
// Re-spawn the setup actors.
|
||||
play->numSetupActors = -play->numSetupActors;
|
||||
}
|
||||
|
||||
// Setup next bell time.
|
||||
if (CURRENT_DAY == 3) {
|
||||
gSaveContext.save.time--;
|
||||
func_80A42198(this);
|
||||
gSaveContext.save.time++;
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
// z_obj_tokeidai
|
||||
|
||||
#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_Init(Actor* thisx, PlayState* play);
|
||||
void ObjTokeidai_Draw(Actor* thisx, 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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
626
patches/event_patches.c
Normal file
626
patches/event_patches.c
Normal file
@ -0,0 +1,626 @@
|
||||
#include "patches.h"
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// @recomp Don't play final hours until it's actually past midnight
|
||||
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) &&
|
||||
(CURRENT_TIME > CLOCK_TIME(0, 0))) {
|
||||
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 Replace DSoT functionality if the option for it is enabled.
|
||||
if (dsot_enabled() && 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 Replace DSoT functionality if the option for it is enabled.
|
||||
if (!dsot_enabled() && (CURRENT_TIME > CLOCK_TIME(12, 0))) {
|
||||
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;
|
||||
gSaveContext.respawnFlag = 2;
|
||||
play->msgCtx.ocarinaMode = OCARINA_MODE_END;
|
||||
}
|
||||
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++;
|
||||
}
|
925
patches/message_patches.c
Normal file
925
patches/message_patches.c
Normal file
@ -0,0 +1,925 @@
|
||||
#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 Replace DSoT functionality if the option for it is enabled.
|
||||
if (dsot_enabled()) {
|
||||
// @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 (Message_ShouldAdvance(play)) {
|
||||
if (msgCtx->choiceIndex == 0) {
|
||||
Audio_PlaySfx_MessageDecide();
|
||||
if (gSaveContext.save.isNight != 0) {
|
||||
gSaveContext.save.time = CLOCK_TIME(6, 0);
|
||||
} else {
|
||||
gSaveContext.save.time = CLOCK_TIME(18, 0);
|
||||
}
|
||||
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;
|
||||
}
|
||||
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) {
|
||||
if (interfaceCtx->restrictions.songOfDoubleTime == 0) {
|
||||
// @recomp
|
||||
dsot_determine_enabled();
|
||||
|
||||
// @recomp Replace DSoT functionality if the option for it is enabled.
|
||||
if (dsot_enabled()) {
|
||||
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 {
|
||||
if ((CURRENT_DAY != 3) || (gSaveContext.save.isNight == 0)) {
|
||||
if (gSaveContext.save.isNight) {
|
||||
Message_StartTextbox(play, D_801D0464[CURRENT_DAY - 1], NULL);
|
||||
} else {
|
||||
Message_StartTextbox(play, D_801D045C[CURRENT_DAY - 1], NULL);
|
||||
}
|
||||
play->msgCtx.ocarinaMode = OCARINA_MODE_PROCESS_DOUBLE_TIME;
|
||||
} 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;
|
||||
}
|
||||
}
|
@ -11,5 +11,6 @@ DECLARE_FUNC(void, recomp_handle_quicksave_actions_main, OSMesgQueue* enter_mq,
|
||||
DECLARE_FUNC(u16, recomp_get_pending_warp);
|
||||
DECLARE_FUNC(u32, recomp_get_pending_set_time);
|
||||
DECLARE_FUNC(s32, recomp_autosave_enabled);
|
||||
DECLARE_FUNC(s32, recomp_dsot_enabled);
|
||||
|
||||
#endif
|
||||
|
@ -108,4 +108,12 @@ void draw_autosave_icon(PlayState* play);
|
||||
|
||||
void recomp_crash(const char* err);
|
||||
|
||||
void dsot_determine_enabled(void);
|
||||
bool dsot_enabled(void);
|
||||
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
|
||||
|
@ -60,3 +60,4 @@ recomp_get_inverted_axes = 0x8F0000A4;
|
||||
recomp_high_precision_fb_enabled = 0x8F0000A8;
|
||||
recomp_get_resolution_scale = 0x8F0000AC;
|
||||
recomp_get_analog_inverted_axes = 0x8F0000B0;
|
||||
recomp_dsot_enabled = 0x8F0000B4;
|
||||
|
@ -990,6 +990,11 @@ void Message_DrawTextBox(PlayState* play, Gfx** gfxP) {
|
||||
gSPPopMatrix(gfx++, G_MTX_MODELVIEW);
|
||||
}
|
||||
|
||||
// @recomp Replace DSoT functionality if the option for it is enabled.
|
||||
if (dsot_enabled() && (play->msgCtx.ocarinaMode == OCARINA_MODE_PROCESS_DOUBLE_TIME)) {
|
||||
dsot_draw_clock(play);
|
||||
}
|
||||
|
||||
// Draw treble clef
|
||||
if (msgCtx->textBoxType == TEXTBOX_TYPE_3) {
|
||||
gDPPipeSync(gfx++);
|
||||
|
@ -221,6 +221,7 @@ bool save_general_config(const std::filesystem::path& path) {
|
||||
config_json["analog_cam_mode"] = zelda64::get_analog_cam_mode();
|
||||
config_json["analog_camera_invert_mode"] = zelda64::get_analog_camera_invert_mode();
|
||||
config_json["debug_mode"] = zelda64::get_debug_mode_enabled();
|
||||
config_json["dsot_mode"] = zelda64::get_dsot_mode();
|
||||
|
||||
return save_json_with_backups(path, config_json);
|
||||
}
|
||||
@ -237,6 +238,7 @@ void set_general_settings_from_json(const nlohmann::json& config_json) {
|
||||
zelda64::set_analog_cam_mode(from_or_default(config_json, "analog_cam_mode", zelda64::AnalogCamMode::Off));
|
||||
zelda64::set_analog_camera_invert_mode(from_or_default(config_json, "analog_camera_invert_mode", zelda64::CameraInvertMode::InvertNone));
|
||||
zelda64::set_debug_mode_enabled(from_or_default(config_json, "debug_mode", false));
|
||||
zelda64::set_dsot_mode(from_or_default(config_json, "dsot_mode", zelda64::DsotMode::On));
|
||||
}
|
||||
|
||||
bool load_general_config(const std::filesystem::path& path) {
|
||||
|
@ -95,6 +95,10 @@ extern "C" void recomp_autosave_enabled(uint8_t* rdram, recomp_context* ctx) {
|
||||
_return(ctx, static_cast<s32>(zelda64::get_autosave_mode() == zelda64::AutosaveMode::On));
|
||||
}
|
||||
|
||||
extern "C" void recomp_dsot_enabled(uint8_t* rdram, recomp_context* ctx) {
|
||||
_return(ctx, static_cast<s32>(zelda64::get_dsot_mode() == zelda64::DsotMode::On));
|
||||
}
|
||||
|
||||
extern "C" void recomp_load_overlays(uint8_t * rdram, recomp_context * ctx) {
|
||||
u32 rom = _arg<0, u32>(rdram, ctx);
|
||||
PTR(void) ram = _arg<1, PTR(void)>(rdram, ctx);
|
||||
|
@ -281,6 +281,7 @@ struct ControlOptionsContext {
|
||||
zelda64::CameraInvertMode camera_invert_mode;
|
||||
zelda64::AnalogCamMode analog_cam_mode;
|
||||
zelda64::CameraInvertMode analog_camera_invert_mode;
|
||||
zelda64::DsotMode dsot_mode;
|
||||
};
|
||||
|
||||
ControlOptionsContext control_options_context;
|
||||
@ -401,6 +402,17 @@ void zelda64::set_analog_camera_invert_mode(zelda64::CameraInvertMode mode) {
|
||||
}
|
||||
}
|
||||
|
||||
zelda64::DsotMode zelda64::get_dsot_mode() {
|
||||
return control_options_context.dsot_mode;
|
||||
}
|
||||
|
||||
void zelda64::set_dsot_mode(zelda64::DsotMode mode) {
|
||||
control_options_context.dsot_mode = mode;
|
||||
if (general_model_handle) {
|
||||
general_model_handle.DirtyVariable("dsot_mode");
|
||||
}
|
||||
}
|
||||
|
||||
struct SoundOptionsContext {
|
||||
std::atomic<int> main_volume; // Option to control the volume of all sound
|
||||
std::atomic<int> bgm_volume;
|
||||
@ -903,6 +915,7 @@ public:
|
||||
bind_option(constructor, "camera_invert_mode", &control_options_context.camera_invert_mode);
|
||||
bind_option(constructor, "analog_cam_mode", &control_options_context.analog_cam_mode);
|
||||
bind_option(constructor, "analog_camera_invert_mode", &control_options_context.analog_camera_invert_mode);
|
||||
bind_option(constructor, "dsot_mode", &control_options_context.dsot_mode);
|
||||
|
||||
general_model_handle = constructor.GetModelHandle();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user