This commit is contained in:
MelonSpeedruns 2022-05-30 19:00:42 -04:00
commit acf63791f9
7 changed files with 131 additions and 3 deletions

View file

@ -447,6 +447,7 @@ s8 func_8002F368(GlobalContext* globalCtx);
void Actor_GetScreenPos(GlobalContext* globalCtx, Actor* actor, s16* x, s16* y); void Actor_GetScreenPos(GlobalContext* globalCtx, Actor* actor, s16* x, s16* y);
u32 Actor_HasParent(Actor* actor, GlobalContext* globalCtx); u32 Actor_HasParent(Actor* actor, GlobalContext* globalCtx);
s32 func_8002F434(Actor* actor, GlobalContext* globalCtx, s32 getItemId, f32 xzRange, f32 yRange); 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_8002F554(Actor* actor, GlobalContext* globalCtx, s32 getItemId);
void func_8002F580(Actor* actor, GlobalContext* globalCtx); void func_8002F580(Actor* actor, GlobalContext* globalCtx);
u32 Actor_HasNoParent(Actor* actor, GlobalContext* globalCtx); u32 Actor_HasNoParent(Actor* actor, GlobalContext* globalCtx);

View file

@ -380,15 +380,32 @@ typedef enum {
/* 0x7B */ GI_BULLET_BAG_50, /* 0x7B */ GI_BULLET_BAG_50,
/* 0x7C */ GI_ICE_TRAP, // freezes link when opened from a chest /* 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) /* 0x7D */ GI_TEXT_0, // no model appears over Link, shows text id 0 (pocket egg)
/* 0x7E */ GI_MEDALLION_LIGHT, /* 0x7E */ GI_MEDALLION_LIGHT,
/* 0x7F */ GI_MEDALLION_FOREST, /* 0x7F */ GI_MEDALLION_FOREST,
/* 0x80 */ GI_MEDALLION_FIRE, /* 0x80 */ GI_MEDALLION_FIRE,
/* 0x81 */ GI_MEDALLION_WATER, /* 0x81 */ GI_MEDALLION_WATER,
/* 0x82 */ GI_MEDALLION_SHADOW, /* 0x82 */ GI_MEDALLION_SHADOW,
/* 0x83 */ GI_MEDALLION_SPIRIT, /* 0x83 */ GI_MEDALLION_SPIRIT,
/* 0x81 */ GI_STONE_KOKIRI, /* 0x81 */ GI_STONE_KOKIRI,
/* 0x82 */ GI_STONE_GORON, /* 0x82 */ GI_STONE_GORON,
/* 0x83 */ GI_STONE_ZORA, /* 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 /* 0x84 */ GI_MAX
} GetItemID; } GetItemID;
@ -513,7 +530,8 @@ typedef enum {
/* 0x74 */ GID_KOKIRI_EMERALD, /* 0x74 */ GID_KOKIRI_EMERALD,
/* 0x74 */ GID_GORON_RUBY, /* 0x74 */ GID_GORON_RUBY,
/* 0x74 */ GID_ZORA_SAPPHIRE, /* 0x74 */ GID_ZORA_SAPPHIRE,
/* 0x75 */ GID_MAX /* 0x75 */ GID_SONG_GENERIC,
/* 0x76 */ GID_MAX
} GetItemDrawID; } GetItemDrawID;
typedef enum { typedef enum {

View file

@ -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) { void Randomizer::ParseItemLocations(const char* spoilerFileName) {
// todo pull this in from cvar or something // todo pull this in from cvar or something
std::ifstream spoilerFileStream(spoilerFileName); std::ifstream spoilerFileStream(sanitize(spoilerFileName));
if (!spoilerFileStream) if (!spoilerFileStream)
return; return;
@ -1030,6 +1049,7 @@ GetItemID Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId)
return GI_ARROWS_LARGE; return GI_ARROWS_LARGE;
case DEKU_STICK_1: case DEKU_STICK_1:
return GI_STICKS_1; return GI_STICKS_1;
case LIGHT_MEDALLION: case LIGHT_MEDALLION:
return GI_MEDALLION_LIGHT; return GI_MEDALLION_LIGHT;
case FOREST_MEDALLION: case FOREST_MEDALLION:
@ -1042,12 +1062,39 @@ GetItemID Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId)
return GI_MEDALLION_SHADOW; return GI_MEDALLION_SHADOW;
case SPIRIT_MEDALLION: case SPIRIT_MEDALLION:
return GI_MEDALLION_SPIRIT; return GI_MEDALLION_SPIRIT;
case KOKIRI_EMERALD: case KOKIRI_EMERALD:
return GI_STONE_KOKIRI; return GI_STONE_KOKIRI;
case GORON_RUBY: case GORON_RUBY:
return GI_STONE_GORON; return GI_STONE_GORON;
case ZORA_SAPPHIRE: case ZORA_SAPPHIRE:
return GI_STONE_ZORA; 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: default:
return ogItemId; return ogItemId;
} }

View file

@ -1947,6 +1947,35 @@ s32 func_8002F434(Actor* actor, GlobalContext* globalCtx, s32 getItemId, f32 xzR
return false; 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) { void func_8002F554(Actor* actor, GlobalContext* globalCtx, s32 getItemId) {
func_8002F434(actor, globalCtx, getItemId, 50.0f, 10.0f); func_8002F434(actor, globalCtx, getItemId, 50.0f, 10.0f);
} }

View file

@ -109,6 +109,7 @@ void GetItem_DrawJewel(GlobalContext* globalCtx, s16 drawId);
void GetItem_DrawJewelKokiri(GlobalContext* globalCtx, s16 drawId); void GetItem_DrawJewelKokiri(GlobalContext* globalCtx, s16 drawId);
void GetItem_DrawJewelGoron(GlobalContext* globalCtx, s16 drawId); void GetItem_DrawJewelGoron(GlobalContext* globalCtx, s16 drawId);
void GetItem_DrawJewelZora(GlobalContext* globalCtx, s16 drawId); void GetItem_DrawJewelZora(GlobalContext* globalCtx, s16 drawId);
void GetItem_DrawGenericMusicNote(GlobalContext* globalCtx, s16 drawId);
typedef struct { typedef struct {
/* 0x00 */ void (*drawFunc)(GlobalContext*, s16); /* 0x00 */ void (*drawFunc)(GlobalContext*, s16);
@ -375,6 +376,8 @@ DrawItemTableEntry sDrawItemTable[] = {
{ GetItem_DrawJewelKokiri, { gGiKokiriEmeraldGemDL, gGiKokiriEmeraldSettingDL } }, { GetItem_DrawJewelKokiri, { gGiKokiriEmeraldGemDL, gGiKokiriEmeraldSettingDL } },
{ GetItem_DrawJewelGoron, { gGiGoronRubyGemDL, gGiGoronRubySettingDL } }, { GetItem_DrawJewelGoron, { gGiGoronRubyGemDL, gGiGoronRubySettingDL } },
{ GetItem_DrawJewelZora, { gGiZoraSapphireGemDL, gGiZoraSapphireSettingDL } }, { 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); 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) { void GetItem_DrawXlu01(GlobalContext* globalCtx, s16 drawId) {
s32 pad; s32 pad;

View file

@ -910,7 +910,7 @@ void GivePlayerRandoRewardImpa(Actor* actor, GlobalContext* globalCtx, Randomize
globalCtx->nextEntranceIndex = 0x0594; globalCtx->nextEntranceIndex = 0x0594;
gSaveContext.nextCutsceneIndex = 0; gSaveContext.nextCutsceneIndex = 0;
} else if (!successImpa) { } else if (!successImpa) {
successImpa = func_8002F434(&actor, globalCtx, getItemId, 10000.0f, 100.0f); successImpa = GiveItem_Impa(&actor, globalCtx, getItemId, 10000.0f, 100.0f);
} }
} }

View file

@ -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_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(ITEM_ARROW_ICE, OBJECT_GI_M_ARROW, GID_ARROW_ICE, 0x3C, 0x80, CHEST_ANIM_LONG), // Ice Traps
GET_ITEM_NONE, GET_ITEM_NONE,
GET_ITEM(ITEM_MEDALLION_LIGHT, OBJECT_GI_MEDAL, GID_MEDALLION_LIGHT, 0x40, 0x80, CHEST_ANIM_LONG), 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_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_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_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_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_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_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_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_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,
GET_ITEM_NONE, GET_ITEM_NONE,
}; };