diff --git a/soh/include/z64item.h b/soh/include/z64item.h index 0b5948d35..34061c54c 100644 --- a/soh/include/z64item.h +++ b/soh/include/z64item.h @@ -380,15 +380,32 @@ typedef enum { /* 0x7B */ GI_BULLET_BAG_50, /* 0x7C */ GI_ICE_TRAP, // freezes link when opened from a chest /* 0x7D */ GI_TEXT_0, // no model appears over Link, shows text id 0 (pocket egg) + /* 0x7E */ GI_MEDALLION_LIGHT, /* 0x7F */ GI_MEDALLION_FOREST, /* 0x80 */ GI_MEDALLION_FIRE, /* 0x81 */ GI_MEDALLION_WATER, /* 0x82 */ GI_MEDALLION_SHADOW, /* 0x83 */ GI_MEDALLION_SPIRIT, + /* 0x81 */ GI_STONE_KOKIRI, /* 0x82 */ GI_STONE_GORON, /* 0x83 */ GI_STONE_ZORA, + + /* 0x81 */ GI_ZELDAS_LULLABY, + /* 0x82 */ GI_SUNS_SONG, + /* 0x83 */ GI_EPONAS_SONG, + /* 0x81 */ GI_SONG_OF_STORMS, + /* 0x82 */ GI_SONG_OF_TIME, + /* 0x83 */ GI_SARIAS_SONG, + + /* 0x81 */ GI_MINUET_OF_FOREST, + /* 0x82 */ GI_BOLERO_OF_FIRE, + /* 0x83 */ GI_SERENADE_OF_WATER, + /* 0x81 */ GI_NOCTURNE_OF_SHADOW, + /* 0x82 */ GI_REQUIEM_OF_SPIRIT, + /* 0x83 */ GI_PRELUDE_OF_LIGHT, + /* 0x84 */ GI_MAX } GetItemID; @@ -513,7 +530,8 @@ typedef enum { /* 0x74 */ GID_KOKIRI_EMERALD, /* 0x74 */ GID_GORON_RUBY, /* 0x74 */ GID_ZORA_SAPPHIRE, - /* 0x75 */ GID_MAX + /* 0x75 */ GID_SONG_GENERIC, + /* 0x76 */ GID_MAX } GetItemDrawID; typedef enum { diff --git a/soh/soh/Enhancements/randomizer.cpp b/soh/soh/Enhancements/randomizer.cpp index bcf77375a..0b38a7f3a 100644 --- a/soh/soh/Enhancements/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer.cpp @@ -1148,9 +1148,28 @@ void Randomizer::LoadItemLocations(const char* spoilerFileName) { } } +std::string sanitize(std::string stringValue) { + // Add backslashes. + for (auto i = stringValue.begin();;) { + auto const pos = + std::find_if(i, stringValue.end(), [](char const c) { return '\\' == c || '\'' == c || '"' == c; }); + if (pos == stringValue.end()) { + break; + } + i = std::next(stringValue.insert(pos, '\\'), 2); + } + + // Removes others. + stringValue.erase(std::remove_if(stringValue.begin(), stringValue.end(), + [](char const c) { return '\n' == c || '\r' == c || '\0' == c || '\x1A' == c; }), + stringValue.end()); + + return stringValue; +} + void Randomizer::ParseItemLocations(const char* spoilerFileName) { // todo pull this in from cvar or something - std::ifstream spoilerFileStream(spoilerFileName); + std::ifstream spoilerFileStream(sanitize(spoilerFileName)); if (!spoilerFileStream) return; @@ -1447,6 +1466,7 @@ GetItemID Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId) return GI_ARROWS_LARGE; case DEKU_STICK_1: return GI_STICKS_1; + case LIGHT_MEDALLION: return GI_MEDALLION_LIGHT; case FOREST_MEDALLION: @@ -1459,12 +1479,40 @@ GetItemID Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId) return GI_MEDALLION_SHADOW; case SPIRIT_MEDALLION: return GI_MEDALLION_SPIRIT; + case KOKIRI_EMERALD: return GI_STONE_KOKIRI; case GORON_RUBY: return GI_STONE_GORON; case ZORA_SAPPHIRE: return GI_STONE_ZORA; + + case ZELDAS_LULLABY: + return GI_ZELDAS_LULLABY; + case SUNS_SONG: + return GI_SUNS_SONG; + case EPONAS_SONG: + return GI_EPONAS_SONG; + case SONG_OF_STORMS: + return GI_SONG_OF_STORMS; + case SONG_OF_TIME: + return GI_SONG_OF_TIME; + case SARIAS_SONG: + return GI_SARIAS_SONG; + + case MINUET_OF_FOREST: + return GI_MINUET_OF_FOREST; + case BOLERO_OF_FIRE: + return GI_BOLERO_OF_FIRE; + case SERENADE_OF_WATER: + return GI_SERENADE_OF_WATER; + case NOCTURNE_OF_SHADOW: + return GI_NOCTURNE_OF_SHADOW; + case REQUIEM_OF_SPIRIT: + return GI_REQUIEM_OF_SPIRIT; + case PRELUDE_OF_LIGHT: + return GI_PRELUDE_OF_LIGHT; + default: return ogItemId; } diff --git a/soh/src/code/z_draw.c b/soh/src/code/z_draw.c index 499a4ed4f..b491bec7d 100644 --- a/soh/src/code/z_draw.c +++ b/soh/src/code/z_draw.c @@ -109,6 +109,7 @@ void GetItem_DrawJewel(GlobalContext* globalCtx, s16 drawId); void GetItem_DrawJewelKokiri(GlobalContext* globalCtx, s16 drawId); void GetItem_DrawJewelGoron(GlobalContext* globalCtx, s16 drawId); void GetItem_DrawJewelZora(GlobalContext* globalCtx, s16 drawId); +void GetItem_DrawGenericMusicNote(GlobalContext* globalCtx, s16 drawId); typedef struct { /* 0x00 */ void (*drawFunc)(GlobalContext*, s16); @@ -375,6 +376,8 @@ DrawItemTableEntry sDrawItemTable[] = { { GetItem_DrawJewelKokiri, { gGiKokiriEmeraldGemDL, gGiKokiriEmeraldSettingDL } }, { GetItem_DrawJewelGoron, { gGiGoronRubyGemDL, gGiGoronRubySettingDL } }, { GetItem_DrawJewelZora, { gGiZoraSapphireGemDL, gGiZoraSapphireSettingDL } }, + + { GetItem_DrawGenericMusicNote, { gGiSongNoteDL } }, }; /** @@ -788,6 +791,19 @@ void GetItem_DrawOpa0Xlu1(GlobalContext* globalCtx, s16 drawId) { CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_draw.c", 991); } +void GetItem_DrawGenericMusicNote(GlobalContext* globalCtx, s16 drawId) { + s32 pad; + + OPEN_DISPS(globalCtx->state.gfxCtx, "../z_draw.c", 998); + + func_80093D84(globalCtx->state.gfxCtx); + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_draw.c", 1002), + G_MTX_MODELVIEW | G_MTX_LOAD); + gSPDisplayList(POLY_XLU_DISP++, sDrawItemTable[drawId].dlists[0]); + + CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_draw.c", 1008); +} + void GetItem_DrawXlu01(GlobalContext* globalCtx, s16 drawId) { s32 pad; diff --git a/soh/src/code/z_sram.c b/soh/src/code/z_sram.c index 82437707b..be43498cd 100644 --- a/soh/src/code/z_sram.c +++ b/soh/src/code/z_sram.c @@ -413,7 +413,7 @@ void Sram_OpenSave(SramContext* sramCtx) { } // if zelda cutscene has been watched but lullaby was not obtained, restore cutscene and take away letter - if ((gSaveContext.eventChkInf[4] & 1) && !CHECK_QUEST_ITEM(QUEST_SONG_LULLABY)) { + if ((gSaveContext.eventChkInf[4] & 1) && !CHECK_QUEST_ITEM(QUEST_SONG_LULLABY) && !gSaveContext.n64ddFlag) { i = gSaveContext.eventChkInf[4] & ~1; gSaveContext.eventChkInf[4] = i; diff --git a/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.c b/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.c index 1be0c6351..22ce02c03 100644 --- a/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.c +++ b/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.c @@ -899,18 +899,23 @@ void func_80986BF8(DemoIm* this, GlobalContext* globalCtx) { } u8 successImpa; -void GivePlayerRandoRewardImpa(Actor* actor, GlobalContext* globalCtx, RandomizerCheck check) { - GetItemID getItemId = GetRandomizedItemIdFromKnownCheck(check, GI_NONE); +void GivePlayerRandoRewardImpa(Actor* impa, GlobalContext* globalCtx, RandomizerCheck check) { + if (!Player_InBlockingCsMode(globalCtx, GET_PLAYER(globalCtx))) { + if (successImpa == 0 && (globalCtx->actorCtx.titleCtx.delayTimer == 0) && + (globalCtx->actorCtx.titleCtx.alpha == 0)) { + GetItemID getItemId = GetRandomizedItemIdFromKnownCheck(check, GI_LETTER_ZELDA); - if (successImpa && !Player_InBlockingCsMode(globalCtx, GET_PLAYER(globalCtx))) { - gSaveContext.eventChkInf[5] |= 0x200; - globalCtx->sceneLoadFlag = 0x14; - globalCtx->fadeTransition = 7; - gSaveContext.nextTransition = 3; - globalCtx->nextEntranceIndex = 0x0594; - gSaveContext.nextCutsceneIndex = 0; - } else if (!successImpa) { - successImpa = func_8002F434(&actor, globalCtx, getItemId, 10000.0f, 100.0f); + if (func_8002F434(impa, globalCtx, getItemId, 100.0f, 50.0f) == true) { + successImpa = 1; + } + } else if (successImpa == 1) { + gSaveContext.eventChkInf[5] |= 0x200; + globalCtx->sceneLoadFlag = 0x14; + globalCtx->fadeTransition = 3; + gSaveContext.nextTransition = 3; + globalCtx->nextEntranceIndex = 0x0594; + gSaveContext.nextCutsceneIndex = 0; + } } } diff --git a/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c b/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c index 282a899dd..be8ad6e02 100644 --- a/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c +++ b/soh/src/overlays/actors/ovl_En_Ma1/z_en_ma1.c @@ -271,6 +271,10 @@ void EnMa1_Init(Actor* thisx, GlobalContext* globalCtx) { Collider_SetCylinder(globalCtx, &this->collider, &this->actor, &sCylinderInit); CollisionCheck_SetInfo2(&this->actor.colChkInfo, DamageTable_Get(22), &sColChkInfoInit); + if (gSaveContext.n64ddFlag) { + gSaveContext.infTable[8] |= 0x800; + } + if (!func_80AA08C4(this, globalCtx)) { Actor_Kill(&this->actor); return; @@ -285,6 +289,10 @@ void EnMa1_Init(Actor* thisx, GlobalContext* globalCtx) { this->actionFunc = func_80AA0D88; EnMa1_ChangeAnim(this, ENMA1_ANIM_2); } else { + if (gSaveContext.n64ddFlag) { + gSaveContext.eventChkInf[1] |= 0x40; + } + this->actionFunc = func_80AA0F44; EnMa1_ChangeAnim(this, ENMA1_ANIM_2); } @@ -324,7 +332,12 @@ void func_80AA0EA0(EnMa1* this, GlobalContext* globalCtx) { this->actor.parent = NULL; this->actionFunc = func_80AA0EFC; } else { - func_8002F434(&this->actor, globalCtx, GI_WEIRD_EGG, 120.0f, 10.0f); + if (gSaveContext.n64ddFlag) { + GetItemID getItemId = GetRandomizedItemIdFromKnownCheck(HC_MALON_EGG, GI_WEIRD_EGG); + func_8002F434(&this->actor, globalCtx, getItemId, 120.0f, 10.0f); + } else { + func_8002F434(&this->actor, globalCtx, GI_WEIRD_EGG, 120.0f, 10.0f); + } } } @@ -337,6 +350,23 @@ void func_80AA0EFC(EnMa1* this, GlobalContext* globalCtx) { } } +void GivePlayerRandoRewardMalon(EnMa1* malon, GlobalContext* globalCtx, RandomizerCheck check) { + Player* player = GET_PLAYER(globalCtx); + + if (!Flags_GetTreasure(globalCtx, 0x1F) && + (INV_CONTENT(ITEM_OCARINA_FAIRY) != ITEM_NONE || INV_CONTENT(ITEM_OCARINA_TIME) != ITEM_NONE) && + Actor_TextboxIsClosing(&malon->actor, globalCtx)) { + GetItemID getItemId = GetRandomizedItemIdFromKnownCheck(check, GI_EPONAS_SONG); + + if (func_8002F434(&malon->actor, globalCtx, getItemId, 100.0f, 50.0f) == true) { + Flags_SetTreasure(globalCtx, 0x1F); + } + } else if (Flags_GetTreasure(globalCtx, 0x1F) && !Player_InBlockingCsMode(globalCtx, player)) { + gSaveContext.unk_13EE = 0x32; + gSaveContext.eventChkInf[4] |= 1; + } +} + void func_80AA0F44(EnMa1* this, GlobalContext* globalCtx) { Player* player = GET_PLAYER(globalCtx); @@ -350,6 +380,11 @@ void func_80AA0F44(EnMa1* this, GlobalContext* globalCtx) { } } + if (gSaveContext.n64ddFlag) { + GivePlayerRandoRewardMalon(this, globalCtx, HC_ZELDAS_LETTER); + return; + } + if (gSaveContext.eventChkInf[1] & 0x40) { if (player->stateFlags2 & 0x1000000) { player->stateFlags2 |= 0x2000000; diff --git a/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c b/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c index 93a57561d..520138738 100644 --- a/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c +++ b/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c @@ -305,7 +305,7 @@ void func_80ABA654(EnNiwLady* this, GlobalContext* globalCtx) { this->actor.parent = NULL; if (gSaveContext.n64ddFlag) { - s32 itemId = GetRandomizedItemIdFromKnownCheck(GI_BOTTLE, KAK_ANJU_AS_CHILD); + s32 itemId = GetRandomizedItemIdFromKnownCheck(KAK_ANJU_AS_CHILD, GI_BOTTLE); func_8002F434(&this->actor, globalCtx, itemId, 100.0f, 50.0f); } else { this->getItemId = GI_BOTTLE; @@ -395,7 +395,7 @@ void func_80ABA9B8(EnNiwLady* this, GlobalContext* globalCtx) { this->actor.parent = NULL; if (gSaveContext.n64ddFlag) { - s32 itemId = GetRandomizedItemIdFromKnownCheck(GI_POCKET_EGG, KAK_ANJU_AS_ADULT); + s32 itemId = GetRandomizedItemIdFromKnownCheck(KAK_ANJU_AS_ADULT, GI_POCKET_EGG); func_8002F434(&this->actor, globalCtx, itemId, 200.0f, 100.0f); } else { func_8002F434(&this->actor, globalCtx, GI_POCKET_EGG, 200.0f, 100.0f); @@ -455,7 +455,7 @@ void func_80ABAC00(EnNiwLady* this, GlobalContext* globalCtx) { getItemId = !(gSaveContext.itemGetInf[2] & 0x1000) ? GI_POCKET_EGG : GI_COJIRO; if (gSaveContext.n64ddFlag && getItemId == GI_POCKET_EGG) { - getItemId = GetRandomizedItemIdFromKnownCheck(GI_POCKET_EGG, KAK_ANJU_AS_ADULT); + getItemId = GetRandomizedItemIdFromKnownCheck(KAK_ANJU_AS_ADULT, GI_POCKET_EGG); } } func_8002F434(&this->actor, globalCtx, getItemId, 200.0f, 100.0f); diff --git a/soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.c b/soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.c index 06442186d..5a3f750cf 100644 --- a/soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.c +++ b/soh/src/overlays/actors/ovl_En_Zl4/z_en_zl4.c @@ -227,10 +227,30 @@ u16 EnZl4_GetText(GlobalContext* globalCtx, Actor* thisx) { return ret; } +void GivePlayerRandoRewardZeldaChild(EnZl4* zelda, GlobalContext* globalCtx, RandomizerCheck check) { + if (!Player_InBlockingCsMode(globalCtx, GET_PLAYER(globalCtx))) { + if (!Flags_GetTreasure(globalCtx, 0x1F) && Actor_TextboxIsClosing(&zelda->actor, globalCtx) && + gSaveContext.eventChkInf[4] != 1 && (globalCtx->actorCtx.titleCtx.delayTimer == 0) && + (globalCtx->actorCtx.titleCtx.alpha == 0)) { + GetItemID getItemId = GetRandomizedItemIdFromKnownCheck(check, GI_LETTER_ZELDA); + + if (func_8002F434(&zelda->actor, globalCtx, getItemId, 100.0f, 50.0f) == true) { + Flags_SetTreasure(globalCtx, 0x1F); + } + } else if (Flags_GetTreasure(globalCtx, 0x1F)) { + gSaveContext.unk_13EE = 0x32; + gSaveContext.eventChkInf[4] |= 1; + } + } +} + s16 func_80B5B9B0(GlobalContext* globalCtx, Actor* thisx) { + EnZl4* this = (EnZl4*)thisx; + if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CLOSING) { return false; } + return true; } @@ -372,6 +392,12 @@ void EnZl4_Init(Actor* thisx, GlobalContext* globalCtx) { this->actor.textId = -1; this->eyeExpression = this->mouthExpression = ZL4_MOUTH_NEUTRAL; + if (gSaveContext.n64ddFlag) { + Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ZL4_ANIM_0); + this->actionFunc = EnZl4_Idle; + return; + } + if (gSaveContext.sceneSetupIndex >= 4) { Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ZL4_ANIM_0); this->actionFunc = EnZl4_TheEnd; @@ -389,6 +415,7 @@ void EnZl4_Init(Actor* thisx, GlobalContext* globalCtx) { this->csState = ZL4_CS_LEGEND; this->talkState = 0; } + this->actionFunc = EnZl4_Cutscene; } } @@ -434,6 +461,7 @@ s32 EnZl4_CsWaitForPlayer(EnZl4* this, GlobalContext* globalCtx) { return false; } } + playerx->world.pos = this->actor.world.pos; rotY = this->actor.shape.rot.y; playerx->world.pos.x += 56.0f * Math_SinS(rotY); @@ -1196,7 +1224,13 @@ void EnZl4_Cutscene(EnZl4* this, GlobalContext* globalCtx) { void EnZl4_Idle(EnZl4* this, GlobalContext* globalCtx) { func_800343CC(globalCtx, &this->actor, &this->unk_1E0.unk_00, this->collider.dim.radius + 60.0f, EnZl4_GetText, func_80B5B9B0); + func_80B5BB78(this, globalCtx); + + if (gSaveContext.n64ddFlag) { + GivePlayerRandoRewardZeldaChild(this, globalCtx, HC_ZELDAS_LETTER); + return; + } } void EnZl4_TheEnd(EnZl4* this, GlobalContext* globalCtx) { diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 3830c90d5..75431e8e0 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -621,15 +621,32 @@ static GetItemEntry sGetItemTable[] = { GET_ITEM(ITEM_BULLET_BAG_50, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG_50, 0x6C, 0x80, CHEST_ANIM_LONG), GET_ITEM(ITEM_ARROW_ICE, OBJECT_GI_M_ARROW, GID_ARROW_ICE, 0x3C, 0x80, CHEST_ANIM_LONG), // Ice Traps GET_ITEM_NONE, + GET_ITEM(ITEM_MEDALLION_LIGHT, OBJECT_GI_MEDAL, GID_MEDALLION_LIGHT, 0x40, 0x80, CHEST_ANIM_LONG), GET_ITEM(ITEM_MEDALLION_FOREST, OBJECT_GI_MEDAL, GID_MEDALLION_FOREST, 0x3E, 0x80, CHEST_ANIM_LONG), GET_ITEM(ITEM_MEDALLION_FIRE, OBJECT_GI_MEDAL, GID_MEDALLION_FIRE, 0x3C, 0x80, CHEST_ANIM_LONG), GET_ITEM(ITEM_MEDALLION_WATER, OBJECT_GI_MEDAL, GID_MEDALLION_WATER, 0x3D, 0x80, CHEST_ANIM_LONG), GET_ITEM(ITEM_MEDALLION_SHADOW, OBJECT_GI_MEDAL, GID_MEDALLION_SHADOW, 0x41, 0x80, CHEST_ANIM_LONG), GET_ITEM(ITEM_MEDALLION_SPIRIT, OBJECT_GI_MEDAL, GID_MEDALLION_SPIRIT, 0x3F, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_KOKIRI_EMERALD, OBJECT_GI_JEWEL, GID_KOKIRI_EMERALD, 0x80, 0x80, CHEST_ANIM_LONG), GET_ITEM(ITEM_GORON_RUBY, OBJECT_GI_JEWEL, GID_GORON_RUBY, 0x81, 0x80, CHEST_ANIM_LONG), GET_ITEM(ITEM_ZORA_SAPPHIRE, OBJECT_GI_JEWEL, GID_ZORA_SAPPHIRE, 0x82, 0x80, CHEST_ANIM_LONG), + + GET_ITEM(ITEM_SONG_SARIA, OBJECT_GI_MELODY, GID_SONG_GENERIC, 0xD1, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SONG_EPONA, OBJECT_GI_MELODY, GID_SONG_GENERIC, 0xD2, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SONG_TIME, OBJECT_GI_MELODY, GID_SONG_GENERIC, 0xD5, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SONG_SUN, OBJECT_GI_MELODY, GID_SONG_GENERIC, 0xD3, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SONG_STORMS, OBJECT_GI_MELODY, GID_SONG_GENERIC, 0xD6, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SONG_LULLABY, OBJECT_GI_MELODY, GID_SONG_GENERIC, 0xD4, 0x80, CHEST_ANIM_LONG), + + GET_ITEM(ITEM_SONG_MINUET, OBJECT_GI_MELODY, GID_SONG_MINUET, 0x73, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SONG_BOLERO, OBJECT_GI_MELODY, GID_SONG_BOLERO, 0x74, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SONG_SERENADE, OBJECT_GI_MELODY, GID_SONG_SERENADE, 0x75, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SONG_NOCTURNE, OBJECT_GI_MELODY, GID_SONG_NOCTURNE, 0x77, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SONG_REQUIEM, OBJECT_GI_MELODY, GID_SONG_REQUIEM, 0x76, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SONG_PRELUDE, OBJECT_GI_MELODY, GID_SONG_PRELUDE, 0x78, 0x80, CHEST_ANIM_LONG), + GET_ITEM_NONE, GET_ITEM_NONE, };