@@ -25,6 +25,7 @@ void func_80AA106C(EnMa1* this, GlobalContext* globalCtx);
2525void func_80AA10EC (EnMa1 * this , GlobalContext * globalCtx );
2626void func_80AA1150 (EnMa1 * this , GlobalContext * globalCtx );
2727void EnMa1_DoNothing (EnMa1 * this , GlobalContext * globalCtx );
28+ void EnMa1_WaitForSongGive (EnMa1 * this , GlobalContext * globalCtx );
2829
2930const ActorInit En_Ma1_InitVars = {
3031 ACTOR_EN_MA1 ,
@@ -356,16 +357,20 @@ void func_80AA0EFC(EnMa1* this, GlobalContext* globalCtx) {
356357
357358void GivePlayerRandoRewardMalon (EnMa1 * malon , GlobalContext * globalCtx , RandomizerCheck check ) {
358359 GetItemID getItemId = GetRandomizedItemIdFromKnownCheck (check , GI_EPONAS_SONG );
359-
360+ // Prevents flag from getting set if we weren't able to get the item (i.e. Player is holding shield
361+ // when closing the textbox).
360362 if (malon -> actor .parent != NULL && malon -> actor .parent -> id == GET_PLAYER (globalCtx )-> actor .id &&
361363 !Flags_GetTreasure (globalCtx , 0x1F )) {
362364 Flags_SetTreasure (globalCtx , 0x1F );
363- } else if (! Flags_GetTreasure ( globalCtx , 0x1F ) &&
364- ( INV_CONTENT ( ITEM_OCARINA_FAIRY ) != ITEM_NONE || INV_CONTENT ( ITEM_OCARINA_TIME ) != ITEM_NONE ) &&
365- Actor_TextboxIsClosing ( & malon -> actor , globalCtx ) &&
366- ( globalCtx -> msgCtx . textId == 0x2049 || globalCtx -> msgCtx . textId == 0x204A )) {
365+ // puts malon in the action that vanilla has her in after learning the song
366+ // (confirmed via breakpoints in a vanilla save).
367+ malon -> actionFunc = func_80AA0D88 ;
368+ } else if (! Flags_GetTreasure ( globalCtx , 0x1F )) {
367369 func_8002F434 (& malon -> actor , globalCtx , getItemId , 10000.0f , 100.0f );
368370 }
371+ // make malon sing again after giving the item.
372+ malon -> unk_1E8 .unk_00 = 0 ;
373+ malon -> unk_1E0 = 1 ;
369374}
370375
371376void func_80AA0F44 (EnMa1 * this , GlobalContext * globalCtx ) {
@@ -381,23 +386,28 @@ void func_80AA0F44(EnMa1* this, GlobalContext* globalCtx) {
381386 }
382387 }
383388
384- if (gSaveContext .n64ddFlag ) {
385- GivePlayerRandoRewardMalon (this , globalCtx , RC_SONG_FROM_MALON );
386- return ;
387- }
388-
389389 if (gSaveContext .eventChkInf [1 ] & 0x40 ) {
390+ // When the player pulls out the Ocarina while close to Malon
390391 if (player -> stateFlags2 & 0x1000000 ) {
391392 player -> stateFlags2 |= 0x2000000 ;
392393 player -> unk_6A8 = & this -> actor ;
393394 this -> actor .textId = 0x2061 ;
394395 Message_StartTextbox (globalCtx , this -> actor .textId , NULL );
395396 this -> unk_1E8 .unk_00 = 1 ;
396397 this -> actor .flags |= ACTOR_FLAG_16 ;
397- this -> actionFunc = func_80AA106C ;
398+ // when rando'ed, skip to the Item Giving. Otherwise go to the song teaching code.
399+ this -> actionFunc = gSaveContext .n64ddFlag ? func_80AA1150 : func_80AA106C ;
398400 } else if (this -> actor .xzDistToPlayer < 30.0f + (f32 )this -> collider .dim .radius ) {
401+ // somehow flags that the player is close to malon so that pulling out the Ocarina
402+ // triggers the code above this.
399403 player -> stateFlags2 |= 0x800000 ;
400404 }
405+ // If rando'ed, a textbox is closing, it's malon's 'my mom wrote this song' text, AND we do have an ocarina
406+ // in our inventory. This allows us to grant the check when talking to malon with the ocarina in our inventory.
407+ if (gSaveContext .n64ddFlag && (Actor_TextboxIsClosing (& this -> actor , globalCtx ) && globalCtx -> msgCtx .textId == 0x2049 ) &&
408+ (INV_CONTENT (ITEM_OCARINA_FAIRY ) != ITEM_NONE || INV_CONTENT (ITEM_OCARINA_TIME ) != ITEM_NONE )) {
409+ this -> actionFunc = EnMa1_WaitForSongGive ;
410+ }
401411 }
402412}
403413
@@ -419,14 +429,48 @@ void func_80AA10EC(EnMa1* this, GlobalContext* globalCtx) {
419429 }
420430}
421431
432+ void EnMa1_WaitForSongGive (EnMa1 * this , GlobalContext * globalCtx ) {
433+ // Actually give the song check.
434+ GivePlayerRandoRewardMalon (this , globalCtx , RC_SONG_FROM_MALON );
435+ }
436+
437+ // Sets an Ocarina State necessary to not softlock in rando.
438+ // This function should only be called in rando.
439+ void EnMa1_EndTeachSong (EnMa1 * this , GlobalContext * globalCtx ) {
440+ if (globalCtx -> csCtx .state == CS_STATE_IDLE ) {
441+ this -> actionFunc = func_80AA0F44 ;
442+ globalCtx -> msgCtx .ocarinaMode = OCARINA_MODE_04 ;
443+ }
444+
445+ if (gSaveContext .n64ddFlag ) {
446+ // Transition to the giving the song check on the next update run.
447+ this -> actionFunc = EnMa1_WaitForSongGive ;
448+ }
449+ }
450+
422451void func_80AA1150 (EnMa1 * this , GlobalContext * globalCtx ) {
423452 GET_PLAYER (globalCtx )-> stateFlags2 |= 0x800000 ;
453+
454+ // When rando'ed, trigger the "song learned" Ocarina mode.
455+ if (gSaveContext .n64ddFlag && (Message_GetState (& globalCtx -> msgCtx ) == TEXT_STATE_CLOSING )) {
456+ globalCtx -> msgCtx .ocarinaMode = OCARINA_MODE_03 ;
457+ }
458+
424459 if (globalCtx -> msgCtx .ocarinaMode == OCARINA_MODE_03 ) {
425- globalCtx -> nextEntranceIndex = 0x157 ;
426- gSaveContext .nextCutsceneIndex = 0xFFF1 ;
427- globalCtx -> fadeTransition = 42 ;
428- globalCtx -> sceneLoadFlag = 0x14 ;
429- this -> actionFunc = EnMa1_DoNothing ;
460+ if (!gSaveContext .n64ddFlag ) {
461+ globalCtx -> nextEntranceIndex = 0x157 ;
462+ gSaveContext .nextCutsceneIndex = 0xFFF1 ;
463+ globalCtx -> fadeTransition = 42 ;
464+ globalCtx -> sceneLoadFlag = 0x14 ;
465+ this -> actionFunc = EnMa1_DoNothing ;
466+ } else {
467+ // When rando'ed, skip the cutscene, play the chime, reset some flags,
468+ // and give the song on next update.
469+ func_80078884 (NA_SE_SY_CORRECT_CHIME );
470+ this -> actionFunc = EnMa1_EndTeachSong ;
471+ this -> actor .flags &= ~ACTOR_FLAG_16 ;
472+ globalCtx -> msgCtx .ocarinaMode = OCARINA_MODE_00 ;
473+ }
430474 }
431475}
432476
0 commit comments