From acf63791f929d60506c9abc1e56406563077f0a1 Mon Sep 17 00:00:00 2001 From: MelonSpeedruns Date: Mon, 30 May 2022 19:00:42 -0400 Subject: [PATCH] impa wip --- soh/include/functions.h | 1 + soh/include/z64item.h | 20 +++++++- soh/soh/Enhancements/randomizer.cpp | 49 ++++++++++++++++++- soh/src/code/z_actor.c | 29 +++++++++++ soh/src/code/z_draw.c | 16 ++++++ .../overlays/actors/ovl_Demo_Im/z_demo_im.c | 2 +- .../actors/ovl_player_actor/z_player.c | 17 +++++++ 7 files changed, 131 insertions(+), 3 deletions(-) diff --git a/soh/include/functions.h b/soh/include/functions.h index 4631cdb92..c89fb85d9 100644 --- a/soh/include/functions.h +++ b/soh/include/functions.h @@ -447,6 +447,7 @@ s8 func_8002F368(GlobalContext* globalCtx); void Actor_GetScreenPos(GlobalContext* globalCtx, Actor* actor, s16* x, s16* y); u32 Actor_HasParent(Actor* actor, GlobalContext* globalCtx); s32 func_8002F434(Actor* actor, GlobalContext* globalCtx, s32 getItemId, f32 xzRange, f32 yRange); +s32 GiveItem_Impa(Actor* actor, GlobalContext* globalCtx, s32 getItemId, f32 xzRange, f32 yRange); void func_8002F554(Actor* actor, GlobalContext* globalCtx, s32 getItemId); void func_8002F580(Actor* actor, GlobalContext* globalCtx); u32 Actor_HasNoParent(Actor* actor, GlobalContext* globalCtx); 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 c6f414811..22b64c76e 100644 --- a/soh/soh/Enhancements/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer.cpp @@ -731,9 +731,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; @@ -1030,6 +1049,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: @@ -1042,12 +1062,39 @@ 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_actor.c b/soh/src/code/z_actor.c index bdb2fe78c..fb8049b13 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -1947,6 +1947,35 @@ s32 func_8002F434(Actor* actor, GlobalContext* globalCtx, s32 getItemId, f32 xzR return false; } +s32 GiveItem_Impa(Actor* actor, GlobalContext* globalCtx, s32 getItemId, f32 xzRange, f32 yRange) { + Player* player = GET_PLAYER(globalCtx); + + if (!(player->stateFlags1 & 0x3C7080) && Player_GetExplosiveHeld(player) < 0) { + if ((((player->heldActor != NULL) || (actor == player->targetActor)) && (getItemId > GI_NONE) && + (getItemId < GI_MAX)) || + (!(player->stateFlags1 & 0x20000800))) { + f32 playerPosX = player->actor.world.pos.x; + f32 thisPosX = actor->world.pos.x; + + if ((thisPosX - (kREG(17) + 130.0f) < playerPosX) && (!Gameplay_InCsMode(globalCtx))) { + s16 yawDiff = actor->yawTowardsPlayer - player->actor.shape.rot.y; + s32 absYawDiff = ABS(yawDiff); + + if ((getItemId != GI_NONE) || (player->getItemDirection < absYawDiff)) { + player->getItemId = getItemId; + player->interactRangeActor = actor; + player->getItemDirection = absYawDiff; + return true; + } + } else { + return false; + } + } + } + + return false; +} + void func_8002F554(Actor* actor, GlobalContext* globalCtx, s32 getItemId) { func_8002F434(actor, globalCtx, getItemId, 50.0f, 10.0f); } 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/overlays/actors/ovl_Demo_Im/z_demo_im.c b/soh/src/overlays/actors/ovl_Demo_Im/z_demo_im.c index 1be0c6351..b56d87024 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 @@ -910,7 +910,7 @@ void GivePlayerRandoRewardImpa(Actor* actor, GlobalContext* globalCtx, Randomize globalCtx->nextEntranceIndex = 0x0594; gSaveContext.nextCutsceneIndex = 0; } else if (!successImpa) { - successImpa = func_8002F434(&actor, globalCtx, getItemId, 10000.0f, 100.0f); + successImpa = GiveItem_Impa(&actor, globalCtx, getItemId, 10000.0f, 100.0f); } } 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, };