Randomizer v2 (#1065)

* Revert changes to GetItemFromGet

* Fixes Ganon's Boss Key shuffled while regular boss Keys aren't.

* Enum + combo box

* Add obtainability checks correctly

* combobox title rename + no number tracking

* Fix repeatable purchases and bottles rendering incorrectly

* Move shopsanity option in GUI

* Struct instead of ImVec + basic comportment for all case

* Attempt to fix odd build issue

* Cast randoGet for ganons boss key

* Remove redundancy in KD room

* Update logic Cvar names

* Fix Ganons Trials coming from old save files. Fixes #1365

* Fixes crash when entering Ganon's Castle lobby on linux.

* Makes `Item_Give` safe to use with a NULL globalCtx.

This should allow it's use for giving items to Link's Pocket
during rando save initialization.

* Converts Song from Impa to use `Item_Give`

* Adds more options for Link's starting item.

* Removes unneeded `GiveLinkItem` functions.

* and make it build

* bring back new rando dropdown

* gSaveContext access in GameMenuBar.cpp

* Implement Skip Scarecrow's Song

* Reimplement progressive Bombchus

* Rando-next: Deku Nut and Seed ammo gives a blue rupee
Fixes #1390

* Fixes Link starting with BGS

* Persist item tracker notes

* Adjust Hooks include

* Use SohImGui::RequestCvarSaveOnNextTick

* Fix issues from LUS refactor

* Fix for overriding deku scrub messages

* Fix mistake from merge

oops

* Restore checkboxes to enhancements menu

These got lost in the merge

* Update location access logic

Including MQ locations in Spirit and GC now

* Implement rando bombchu drops

* Missing break

* Simplify mudwall collision check

There was no need to have a second collider specifically for Ice Arrow hits

* Update settings.cpp

* Simplify mudwall collision check

* Restore checkboxes in menu

Accidentally lost these during merge

* Clean up bool

* Update logic Cvar name

* Fixed capacity on ammmo tracking

* Fix for beans obtainability

* Hook into file delete and clear notes

* Incorporate magic arrows in rando settings

* Update tooltip

To inform the player that they might have to reload the room if they're enabling this for the first time.

* Update tooltip

* Add line break in tooltip

* Tooltip wording + line break

* tweak on main logic

* All color logic for all types

* Fix: changes to please new LUS

* Ensure itemTrackerNotes vector is not fully empty

* Implement's Tycoon Wallet.

* Refactor DrawItemCount and Use EnhancementCombobox for tracker capacity options

* small tweaks and rename

* always display XX/YY when in ammo/capacity mode

* Move all merchant messages to be generated on file load

* added hovertext for the number display

* Swap german and french translations for shop messages

* Set key colors to be on by default

* Add another flag to skip mask shop

* Fix Sold Out bug

* Fix gerudo keys, add disabled checkbox

* tooltip line break

* Add trials required and merchant prices to save file instead of loading from active spoiler log

* Remove trialsRequired persisting in save manager

* Adds slotIndex to girla (shop item actor) and uses that for IdentifyShopItem.

* Fix issue when merchantPrices is empty

* Fix for a single zeroed merchantPrice entry

* Fix #1417

* Implements items selling out and fixes issues with purchasing some items.

* Fixes order of operations so Rupees will be spent.

* Fixes sold out items not getting overwritten by the randomized info.

* Clarify var names and comments

Also preserve chain platform cutscene in spirit based on Link's position

* Remove !=0 from cvar check

* Clarify var names and comments

* Rename randomizerMerchantPrices to merchantPrices

* Handle shop items in SaveManager

* Fix merge mistake

* Base whats in the bazaar shop on entranceIndex instead of age

* Tidy up chain platform cutscene check

* Fix merge error

Didn't mean to have Zhora changes in here yet

* Use 3drando item table for parsing spoiler names

* Use another nested method instead of one at the top level to fetch the table

* Add missing newline

* Remove log

* Respect custom draw functions

* Fix issues with rendering songs

* Fix localized item names for shopsanity

* Implements a larger array of Sprites for the Icon Hash.

* Uses the hash instead of seed for spoilerfile name and icons.

* Removes some unused functions and variables in `spoiler_log.cpp`

* Prevents leading 0s added to hash from being in file name

* Changes filename format to icon indexes separated by dashes

* Hopefully makes Jenkins happy

* Hopefully makes Jenkins happy

* [Rando] Child Gerudo Fortress 37th Heartpiece randomized
Fixes #1071

* Add descriptions to save editor flags editor, and added randomizer flags (#1386)

* Add descriptions to save editor flags editor, and added randomizer flags

* Hide randomizer flags when not on a randomizer save

* Move flag descriptions to header file

* Update soh/soh/Enhancements/debugger/debugSaveEditor.h

* Update soh/soh/Enhancements/debugger/debugSaveEditor.h

* Fix merge error

* crash on pause menu on linux (only in appimage)
Fixes #1437

* Applies fix to Song from Impa as well.

* Allow buying tunics as child when shopsanity is on

* Fix for custom draw methods overriding sold out sign

* Simplify logic around shopsanity and fix some issues

* Fix dungeon reward stone rotation and add particles

* Fix some issues with ice traps

* Fix adult wallet having its own max capacity

* Fix amount of keys given for BotW

* format

* Use EnGirlAShopItem enum instead of raw hex values

* [#1434] Renders non-warp songs more consistently with warp songs

* A few changes around merchant messages

* Various changes from PR feedback

* Rando: Junk Hint missing french translation

* Typo

* Fix free scrub being at 0 instead of TEXT_SCRUB_RANDOM

* Replace magic numbers in message handler

* Update soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c

Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com>

* Update soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c

Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com>

* Fix BGS softlock for shopsanity

* Support tycoon wallet on tracker

* Revert "Fix BGS softlock for shopsanity"

This reverts commit 5fdb961ea4.

* [#1053] Resolves an issue with shop items and bombchu bowling where BGS would display two message boxes

* Implements some necessary plumbing and resolves several Ice Trap Softlocks.

Adds a way for an item entry to tell what type of check it came from (NPC vs Chest vs Freestanding, etc.)
Sets this value from chests and item00 actors.

Relocates pendingIceTraps to save context so it can persist through cutscenes and get stored on save init for Link's Pocket and Song from Impa.

Restructures pendingIceTraps into a counter rather than a true or false, so that we can be frozen multiple times in a row if applicable (atm that should only be at the start of a run if Link's Pocket and Song from Impa were both Ice Traps).

Adds a textbox for Ice Traps and a special case of holding up nothing in the get item process. This fixes all the cases where Ice Traps would softlock due to the actor giving the item expecting a closing textbox. After holding the item above his head Link increments the pendingIceTraps counter by one and sets whatever flag he has pending.

None of the above plumbing applies to Ice Traps from chests, those work exactly the same as before, as do freestanding item00 ice traps (thanks to the additional check for ITEM_FROM_FREESTANDING.

OoT and Ruto's Letter count as NPC's, so they get the FOWL text box and set a pending ice trap rather than immediately freezing, since Link weill be in the water. Link will get frozen the next time he touches land, which in the case of OoT is after the fade to white and right before the Song of Time check.

Fixes all the other softlocks I'm aware of, including Fishing, Bombchu Bowling, Skull Kid, and losing the second Gerudo Archery check.

* fix bgs check in player

* move bgs logic for tokensanity into MOD_NONE check

* set bgs flag before `Item_Give`ing

* move bgs flag into `MOD_NONE` check in girla

* use existing check in `z_player`

* Adds comment explaining the decision to default ITEM_FROM_NPC.

* Rename pendingIceTraps to pendingIceTrapCount

* Adds some RANDOTODO comments about cleaning up a couple things.

* Merge branch 'develop-zhora' into ztornn

* manually restore changes to `z_player.c`

* Fix after some ice trap prepwork from earlier

* Actual fix

* Woops

* More rupee names

* Actually fix it

* Add back comment

* Fix Skip Scarecrow Song

* Fix ruto's letter and LH sun stick rendering

* Also fixes it for treasure chest game

* Tweak: Rando French Wallet

* ADD: French Tycoon

* Hide dungeon items/notes by default

* [#1301] Fix issue with UI not restoring after getting an item from biggoron

* Update soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c

* Update soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c

* Fix random crash that only affected one person for some reason

Co-authored-by: Garrett Cox <garrettjcox@gmail.com>
Co-authored-by: Christopher Leggett <chris@leggett.dev>
Co-authored-by: PurpleHato <linkvssangoku.jr@gmail.com>
Co-authored-by: Sarge-117 <adam_branston@outlook.com>
Co-authored-by: briaguya <briaguya@alice>
Co-authored-by: aMannus <mannusmenting@gmail.com>
Co-authored-by: lil David <1337lilDavid@gmail.com>
Co-authored-by: Sarge-117 <108380086+Sarge-117@users.noreply.github.com>
Co-authored-by: louist103 <35883445+louist103@users.noreply.github.com>
This commit is contained in:
briaguya
2022-09-21 00:50:22 -04:00
committed by GitHub
parent 28b7f23769
commit 2b78bea475
123 changed files with 11705 additions and 7375 deletions
+1 -1
View File
@@ -27,7 +27,7 @@ u16 gUpgradeCapacities[][4] = {
{ 0, 20, 30, 40 }, // Bomb Bags
{ 0, 0, 0, 0 }, // Unused (Scale)
{ 0, 0, 0, 0 }, // Unused (Strength)
{ 99, 200, 500, 500 }, // Wallets
{ 99, 200, 500, 999 }, // Wallets
{ 0, 30, 40, 50 }, // Deku Seed Bullet Bags
{ 0, 10, 20, 30 }, // Deku Stick Upgrades
{ 0, 20, 30, 40 }, // Deku Nut Upgrades
+53
View File
@@ -1246,6 +1246,7 @@ void Audio_StepFreqLerp(FreqLerp* lerp);
void func_800F56A8(void);
void Audio_PlayNatureAmbienceSequence(u8 natureAmbienceId);
s32 Audio_SetGanonDistVol(u8 targetVol);
void Audio_PlayFanfare_Rando(GetItemEntry getItem);
// Right stick as virtual C buttons
#define RSTICK_UP 0x100000
@@ -3954,6 +3955,58 @@ void Audio_ResetSfxChannelState(void) {
sAudioCodeReverb = 0;
}
// Function to play "get-item" fanfares according to the type of item obtained (used in rando)
// Longer fanfares for medallions/stones/songs are behind the Cvar
void Audio_PlayFanfare_Rando(GetItemEntry getItem) {
s32 temp1;
s16 getItemId = getItem.getItemId;
s16 itemId = getItem.itemId;
if (getItem.modIndex == MOD_NONE) {
if (((itemId >= ITEM_RUPEE_GREEN) && (itemId <= ITEM_RUPEE_GOLD)) || (itemId == ITEM_HEART)) {
Audio_PlaySoundGeneral(NA_SE_SY_GET_BOXITEM, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
} else {
if (itemId == ITEM_HEART_CONTAINER ||
((itemId == ITEM_HEART_PIECE_2) && ((gSaveContext.inventory.questItems & 0xF0000000) == 0x40000000))) {
temp1 = NA_BGM_HEART_GET | 0x900;
} else {
temp1 = (itemId == ITEM_HEART_PIECE_2) ? NA_BGM_SMALL_ITEM_GET : NA_BGM_ITEM_GET | 0x900;
}
// If we get a skulltula token or the "WINNER" heart, play "get small item"
// Also make sure "WINNER" heart is not the 4th heart piece.
if (itemId == ITEM_SKULL_TOKEN || (getItemId == GI_HEART_PIECE_WIN && itemId == ITEM_HEART_PIECE_2 &&
(gSaveContext.inventory.questItems & 0xF0000000) != 0x40000000)) {
temp1 = NA_BGM_SMALL_ITEM_GET | 0x900;
}
// If the setting is toggled on and we get special quest items (longer fanfares):
if (CVar_GetS32("gRandoQuestItemFanfares", 0) != 0) {
// If we get a medallion, play the "get a medallion" fanfare
if ((itemId >= ITEM_MEDALLION_FOREST) && (itemId <= ITEM_MEDALLION_LIGHT)) {
temp1 = NA_BGM_MEDALLION_GET | 0x900;
}
// If it's a Spiritual Stone, play the "get a spiritual stone" fanfare
if ((itemId >= ITEM_KOKIRI_EMERALD) && (itemId <= ITEM_ZORA_SAPPHIRE)) {
temp1 = NA_BGM_SPIRITUAL_STONE | 0x900;
}
// If the item we're getting is a song, play the "learned a song" fanfare
if ((itemId >= ITEM_SONG_MINUET) && (itemId <= ITEM_SONG_STORMS)) {
temp1 = NA_BGM_OCA_FAIRY_GET | 0x900;
}
}
Audio_PlayFanfare(temp1);
}
} else if (getItem.modIndex == MOD_RANDOMIZER) {
if ((itemId >= RG_BOTTLE_WITH_RED_POTION && itemId <= RG_BOTTLE_WITH_BIG_POE) ||
(itemId >= RG_DEKU_TREE_MAP && itemId <= RG_GANONS_CASTLE_SMALL_KEY)) {
temp1 = NA_BGM_ITEM_GET | 0x900;
} else {
// Just in case nothing else matches.
temp1 = NA_BGM_ITEM_GET | 0x900;
}
Audio_PlayFanfare(temp1);
}
}
void func_800F3F3C(u8 arg0) {
if (gSoundBankMuted[0] != 1) {
Audio_StartSeq(SEQ_PLAYER_BGM_SUB, 0, NA_BGM_VARIOUS_SFX);
+15 -1
View File
@@ -4701,6 +4701,20 @@ void Flags_SetInfTable(s32 flag) {
gSaveContext.infTable[flag >> 4] |= (1 << (flag & 0xF));
}
/**
* Tests if "randomizerInf" flag is set.
*/
s32 Flags_GetRandomizerInf(RandomizerInf flag) {
return gSaveContext.randomizerInf[flag >> 4] & (1 << (flag & 0xF));
}
/**
* Sets "randomizerInf" flag.
*/
void Flags_SetRandomizerInf(RandomizerInf flag) {
gSaveContext.randomizerInf[flag >> 4] |= (1 << (flag & 0xF));
}
u32 func_80035BFC(GlobalContext* globalCtx, s16 arg1) {
u16 retTextId = 0;
@@ -6108,7 +6122,7 @@ GetItemEntry GetChestGameRandoGetItem(s8 room, s16 ogDrawId, GlobalContext* glob
s16 GetChestGameRandoGiDrawId(s8 room, s16 ogDrawId, GlobalContext* globalCtx) {
GetItemEntry randoGetItem = GetChestGameRandoGetItem(room, ogDrawId, globalCtx);
if (randoGetItem.itemId != RG_NONE) {
if (randoGetItem.itemId != ITEM_NONE) {
return randoGetItem.gid;
}
+19 -5
View File
@@ -395,6 +395,20 @@ void GetItem_Draw(GlobalContext* globalCtx, s16 drawId) {
sDrawItemTable[drawId].drawFunc(globalCtx, drawId);
}
/**
* Draw "Get Item" Model from a `GetItemEntry`
* Uses the Custom Draw Function if it exists, or just calls `GetItem_Draw`
*/
void GetItemEntry_Draw(GlobalContext* globalCtx, GetItemEntry getItemEntry) {
// RANDOTODO: Make this more flexible for easier toggling of individual item recolors in the future.
if (getItemEntry.drawFunc != NULL &&
(CVar_GetS32("gRandoMatchKeyColors", 0) || getItemEntry.getItemId == RG_DOUBLE_DEFENSE)) {
getItemEntry.drawFunc(globalCtx, &getItemEntry);
} else {
GetItem_Draw(globalCtx, getItemEntry.gid);
}
}
// All remaining functions in this file are draw functions referenced in the table and called by the function above
/* 0x0178 */ u8 primXluColor[3];
@@ -813,12 +827,12 @@ void GetItem_DrawGenericMusicNote(GlobalContext* globalCtx, s16 drawId) {
OPEN_DISPS(globalCtx->state.gfxCtx);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, __FILE__, __LINE__), G_MTX_MODELVIEW | G_MTX_LOAD);
gsDPSetGrayscaleColor(POLY_OPA_DISP++, colors[color_slot][0], colors[color_slot][1], colors[color_slot][2], 255);
gsSPGrayscale(POLY_OPA_DISP++, true);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, __FILE__, __LINE__), G_MTX_MODELVIEW | G_MTX_LOAD);
gsDPSetGrayscaleColor(POLY_XLU_DISP++, colors[color_slot][0], colors[color_slot][1], colors[color_slot][2], 255);
gsSPGrayscale(POLY_XLU_DISP++, true);
func_80093D18(globalCtx->state.gfxCtx);
gSPDisplayList(POLY_OPA_DISP++, sDrawItemTable[drawId].dlists[0]);
gsSPGrayscale(POLY_OPA_DISP++, false);
gSPDisplayList(POLY_XLU_DISP++, sDrawItemTable[drawId].dlists[0]);
gsSPGrayscale(POLY_XLU_DISP++, false);
CLOSE_DISPS(globalCtx->state.gfxCtx);
}
+24 -12
View File
@@ -519,7 +519,8 @@ void EnItem00_Init(Actor* thisx, GlobalContext* globalCtx) {
if (!gSaveContext.n64ddFlag) {
func_8002F554(&this->actor, globalCtx, getItemId);
} else {
getItem = Randomizer_GetRandomizedItem(getItemId, this->actor.id, this->ogParams, globalCtx->sceneNum);
getItem = Randomizer_GetItemFromActor(this->actor.id, globalCtx->sceneNum, this->ogParams, getItemId);
getItem.getItemFrom = ITEM_FROM_FREESTANDING;
GiveItemEntryFromActorWithFixedRange(&this->actor, globalCtx, getItem);
}
}
@@ -686,7 +687,8 @@ void func_8001E5C8(EnItem00* this, GlobalContext* globalCtx) {
func_8002F434(&this->actor, globalCtx, this->getItemId, 50.0f, 80.0f);
} else {
GetItemEntry getItemEntry =
Randomizer_GetRandomizedItem(this->getItemId, this->actor.id, this->ogParams, globalCtx->sceneNum);
Randomizer_GetItemFromActor(this->actor.id, globalCtx->sceneNum, this->ogParams, this->getItemId);
getItemEntry.getItemFrom = ITEM_FROM_FREESTANDING;
GiveItemEntryFromActor(&this->actor, globalCtx, getItemEntry, 50.0f, 80.0f);
}
this->unk_15A++;
@@ -911,8 +913,9 @@ void EnItem00_Update(Actor* thisx, GlobalContext* globalCtx) {
if (!gSaveContext.n64ddFlag) {
func_8002F554(&this->actor, globalCtx, getItemId);
} else {
getItem = Randomizer_GetRandomizedItem(getItemId, this->actor.id, this->ogParams, globalCtx->sceneNum);
getItem = Randomizer_GetItemFromActor(this->actor.id, globalCtx->sceneNum, this->ogParams, getItemId);
getItemId = getItem.getItemId;
getItem.getItemFrom = ITEM_FROM_FREESTANDING;
GiveItemEntryFromActorWithFixedRange(&this->actor, globalCtx, getItem);
}
}
@@ -1290,10 +1293,11 @@ void EnItem00_CustomItemsParticles(Actor* Parent, GlobalContext* globalCtx, GetI
switch (giEntry.itemId) {
case RG_MAGIC_SINGLE:
case RG_MAGIC_DOUBLE:
case RG_MAGIC_BEAN_PACK:
color_slot = 0;
break;
case RG_DOUBLE_DEFENSE:
color_slot = 1;
color_slot = 8;
break;
default:
return;
@@ -1305,14 +1309,14 @@ void EnItem00_CustomItemsParticles(Actor* Parent, GlobalContext* globalCtx, GetI
s16* colors[9][3] = {
{ 34, 255, 76 }, // Minuet and Magic Upgrades Colors
{ 177, 35, 35 }, // Bolero and Double Defense Colors
{ 177, 35, 35 }, // Bolero Colors
{ 115, 251, 253 }, // Serenade Color
{ 177, 122, 35 }, // Requiem Color
{ 177, 28, 212 }, // Nocturne Color
{ 255, 255, 92 }, // Prelude Color
{ 31, 152, 49 }, // Stick Upgrade Color
{ 222, 182, 20 }, // Nut Upgrade Color
{ 255, 255, 255 } // White Color placeholder
{ 255, 255, 255 } // Double Defense Color
};
s16* colorsEnv[9][3] = {
@@ -1338,8 +1342,15 @@ void EnItem00_CustomItemsParticles(Actor* Parent, GlobalContext* globalCtx, GetI
velocity.y = -0.05f;
accel.y = -0.025f;
pos.x = Rand_CenteredFloat(32.0f) + Parent->world.pos.x;
pos.y = (Rand_ZeroOne() * 6.0f) + Parent->world.pos.y + 25;
// Shop items are rendered at a different height than the rest, so a different y offset is required
if (Parent->id == ACTOR_EN_GIRLA) {
pos.y = (Rand_ZeroOne() * 6.0f) + Parent->world.pos.y + 5;
} else {
pos.y = (Rand_ZeroOne() * 6.0f) + Parent->world.pos.y + 25;
}
pos.z = Rand_CenteredFloat(32.0f) + Parent->world.pos.z;
EffectSsKiraKira_SpawnDispersed(globalCtx, &pos, &velocity, &accel, &primColor, &envColor, 1000, 50);
}
@@ -1379,9 +1390,9 @@ void EnItem00_DrawCollectible(EnItem00* this, GlobalContext* globalCtx) {
f32 mtxScale = 16.0f;
Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY);
GetItemEntry randoGetItemEntry =
Randomizer_GetRandomizedItem(this->getItemId, this->actor.id, this->ogParams, globalCtx->sceneNum);
Randomizer_GetItemFromActor(this->actor.id, globalCtx->sceneNum, this->ogParams, this->getItemId);
EnItem00_CustomItemsParticles(&this->actor, globalCtx, randoGetItemEntry);
GetItem_Draw(globalCtx, randoGetItemEntry.gid);
GetItemEntry_Draw(globalCtx, randoGetItemEntry);
} else {
s32 texIndex = this->actor.params - 3;
@@ -1441,9 +1452,9 @@ void EnItem00_DrawHeartPiece(EnItem00* this, GlobalContext* globalCtx) {
f32 mtxScale = 16.0f;
Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY);
GetItemEntry randoGetItemEntry =
Randomizer_GetRandomizedItem(GI_HEART_PIECE, this->actor.id, this->ogParams, globalCtx->sceneNum);
Randomizer_GetItemFromActor(this->actor.id, globalCtx->sceneNum, this->ogParams, GI_HEART_PIECE);
EnItem00_CustomItemsParticles(&this->actor, globalCtx, randoGetItemEntry);
GetItem_Draw(globalCtx, randoGetItemEntry.gid);
GetItemEntry_Draw(globalCtx, randoGetItemEntry);
} else {
s32 pad;
@@ -1506,7 +1517,8 @@ s16 func_8001F404(s16 dropId) {
}
}
if (CVar_GetS32("gBombchuDrops", 0) &&
if ((CVar_GetS32("gBombchuDrops", 0) ||
(gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_ENABLE_BOMBCHU_DROPS) == 1)) &&
(dropId == ITEM00_BOMBS_A || dropId == ITEM00_BOMBS_B || dropId == ITEM00_BOMBS_SPECIAL)) {
dropId = EnItem00_ConvertBombDropToBombchu(dropId);
}
+11 -9
View File
@@ -33,19 +33,21 @@ void GameOver_Update(GlobalContext* globalCtx) {
gSaveContext.eventInf[1] &= ~1;
// search inventory for spoiling items and revert if necessary
for (i = 0; i < ARRAY_COUNT(gSpoilingItems); i++) {
if (INV_CONTENT(ITEM_POCKET_EGG) == gSpoilingItems[i]) {
INV_CONTENT(gSpoilingItemReverts[i]) = gSpoilingItemReverts[i];
if (!(gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE))) {
for (i = 0; i < ARRAY_COUNT(gSpoilingItems); i++) {
if (INV_CONTENT(ITEM_POCKET_EGG) == gSpoilingItems[i]) {
INV_CONTENT(gSpoilingItemReverts[i]) = gSpoilingItemReverts[i];
// search c buttons for the found spoiling item and revert if necessary
for (j = 1; j < ARRAY_COUNT(gSaveContext.equips.buttonItems); j++) {
if (gSaveContext.equips.buttonItems[j] == gSpoilingItems[i]) {
gSaveContext.equips.buttonItems[j] = gSpoilingItemReverts[i];
Interface_LoadItemIcon1(globalCtx, j);
// search c buttons for the found spoiling item and revert if necessary
for (j = 1; j < ARRAY_COUNT(gSaveContext.equips.buttonItems); j++) {
if (gSaveContext.equips.buttonItems[j] == gSpoilingItems[i]) {
gSaveContext.equips.buttonItems[j] = gSpoilingItemReverts[i];
Interface_LoadItemIcon1(globalCtx, j);
}
}
}
}
}
}
// restore "temporary B" to the B Button if not a sword item
if (gSaveContext.equips.buttonItems[0] != ITEM_SWORD_KOKIRI &&
+1 -1
View File
@@ -2095,7 +2095,7 @@ void func_80075B44(GlobalContext* globalCtx) {
gSaveContext.dogIsLost = true;
func_80078884(NA_SE_EV_CHICKEN_CRY_M);
if ((Inventory_ReplaceItem(globalCtx, ITEM_WEIRD_EGG, ITEM_CHICKEN) ||
Inventory_ReplaceItem(globalCtx, ITEM_POCKET_EGG, ITEM_POCKET_CUCCO)) &&
Inventory_HatchPocketCucco(globalCtx)) &&
globalCtx->csCtx.state == 0 && !Player_InCsMode(globalCtx)) {
Message_StartTextbox(globalCtx, 0x3066, NULL);
}
+2 -1
View File
@@ -1696,7 +1696,7 @@ void Message_OpenText(GlobalContext* globalCtx, u16 textId) {
// Increments text id based on piece of heart count, assumes the piece of heart text is all
// in order and that you don't have more than the intended amount of heart pieces.
textId += (gSaveContext.inventory.questItems & 0xF0000000 & 0xF0000000) >> 0x1C;
} else if (msgCtx->textId == 0xC && CHECK_OWNED_EQUIP(EQUIP_SWORD, 2)) {
} else if (!gSaveContext.n64ddFlag && (msgCtx->textId == 0xC && CHECK_OWNED_EQUIP(EQUIP_SWORD, 2))) {
textId = 0xB; // Traded Giant's Knife for Biggoron Sword
} else if (msgCtx->textId == 0xB4 && (gSaveContext.eventChkInf[9] & 0x40)) {
textId = 0xB5; // Destroyed Gold Skulltula
@@ -1718,6 +1718,7 @@ void Message_OpenText(GlobalContext* globalCtx, u16 textId) {
gSaveContext.eventInf[0] = gSaveContext.eventInf[1] = gSaveContext.eventInf[2] = gSaveContext.eventInf[3] = 0;
}
// RANDOTODO: Use this for ice trap messages
if (CustomMessage_RetrieveIfExists(globalCtx)) {
osSyncPrintf("Found custom message");
} else if (sTextIsCredits) {
+217 -26
View File
@@ -3,6 +3,7 @@
#include "textures/parameter_static/parameter_static.h"
#include "textures/do_action_static/do_action_static.h"
#include "textures/icon_item_static/icon_item_static.h"
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
#ifdef _MSC_VER
#include <stdlib.h>
@@ -1574,6 +1575,17 @@ void func_80084BF4(GlobalContext* globalCtx, u16 flag) {
}
}
/**
* @brief Adds the given item to Link's inventory.
*
* NOTE: This function has been edited to be safe to use with a NULL globalCtx.
* If you need to add to this function, be sure you check if the globalCtx is not
* NULL before doing any operations requiring it.
*
* @param globalCtx
* @param item
* @return u8
*/
u8 Item_Give(GlobalContext* globalCtx, u8 item) {
static s16 sAmmoRefillCounts[] = { 5, 10, 20, 30, 5, 10, 30, 0, 5, 20, 1, 5, 20, 50, 200, 10 };
s16 i;
@@ -1646,15 +1658,21 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
} else if ((item >= ITEM_SWORD_KOKIRI) && (item <= ITEM_SWORD_BGS)) {
gSaveContext.inventory.equipment |= gBitFlags[item - ITEM_SWORD_KOKIRI] << gEquipShifts[EQUIP_SWORD];
// Both Giant's Knife and Biggoron Sword have the same Item ID, so this part handles both of them
if (item == ITEM_SWORD_BGS) {
gSaveContext.swordHealth = 8;
if (ALL_EQUIP_VALUE(EQUIP_SWORD) == 0xF
||(gSaveContext.n64ddFlag && ALL_EQUIP_VALUE(EQUIP_SWORD) == 0xE)) { // In rando, when buying Giant's Knife, also check
gSaveContext.inventory.equipment ^= 8 << gEquipShifts[EQUIP_SWORD]; // for 0xE in case we don't have Kokiri Sword
// In rando, when buying Giant's Knife, also check
// for 0xE in case we don't have Kokiri Sword
if (ALL_EQUIP_VALUE(EQUIP_SWORD) == 0xF || (gSaveContext.n64ddFlag && ALL_EQUIP_VALUE(EQUIP_SWORD) == 0xE)) {
gSaveContext.inventory.equipment ^= 8 << gEquipShifts[EQUIP_SWORD];
if (gSaveContext.equips.buttonItems[0] == ITEM_SWORD_KNIFE) {
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_BGS;
Interface_LoadItemIcon1(globalCtx, 0);
if (globalCtx != NULL) {
Interface_LoadItemIcon1(globalCtx, 0);
}
}
}
@@ -1662,7 +1680,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_MASTER;
gSaveContext.equips.equipment &= 0xFFF0;
gSaveContext.equips.equipment |= 0x0002;
Interface_LoadItemIcon1(globalCtx, 0);
if (globalCtx != NULL) {
Interface_LoadItemIcon1(globalCtx, 0);
}
}
PerformAutosave(globalCtx, item);
@@ -1681,7 +1701,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
return ITEM_NONE;
} else if ((item == ITEM_KEY_BOSS) || (item == ITEM_COMPASS) || (item == ITEM_DUNGEON_MAP)) {
// Boss Key, Compass, and Dungeon Map exceptions for rando.
if (gSaveContext.n64ddFlag) {
// Rando should never be able to get here for Link's Pocket unless something goes wrong,
// but we check for a globalCtx here so the game won't crash if we do somehow get here.
if (gSaveContext.n64ddFlag && globalCtx != NULL) {
if (globalCtx->sceneNum == 13) { // ganon's castle -> ganon's tower
gSaveContext.inventory.dungeonItems[10] |= 1;
} else if (globalCtx->sceneNum == 92) { // Desert Colossus -> Spirit Temple.
@@ -1695,8 +1717,10 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
PerformAutosave(globalCtx, item);
return ITEM_NONE;
} else if (item == ITEM_KEY_SMALL) {
// Small key exceptions for rando.
if (gSaveContext.n64ddFlag) {
// Small key exceptions for rando with keysanity off.
// Rando should never be able to get here for Link's Pocket unless something goes wrong,
// but we check for a globalCtx here so the game won't crash if we do somehow get here.
if (gSaveContext.n64ddFlag && globalCtx != NULL) {
if (globalCtx->sceneNum == 10) { // ganon's tower -> ganon's castle
if (gSaveContext.inventory.dungeonKeys[13] < 0) {
gSaveContext.inventory.dungeonKeys[13] = 1;
@@ -1721,7 +1745,6 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
}
}
}
if (gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex] < 0) {
gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex] = 1;
PerformAutosave(globalCtx, item);
@@ -1859,7 +1882,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
for (i = 1; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) {
if (gSaveContext.equips.buttonItems[i] == ITEM_HOOKSHOT) {
gSaveContext.equips.buttonItems[i] = ITEM_LONGSHOT;
Interface_LoadItemIcon1(globalCtx, i);
if (globalCtx != NULL) {
Interface_LoadItemIcon1(globalCtx, i);
}
}
}
// update the adult/child equips when rando'd (accounting for equp swapped hookshot as child)
@@ -1867,7 +1892,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
for (i = 1; i < ARRAY_COUNT(gSaveContext.adultEquips.buttonItems); i++) {
if (gSaveContext.adultEquips.buttonItems[i] == ITEM_HOOKSHOT) {
gSaveContext.adultEquips.buttonItems[i] = ITEM_LONGSHOT;
Interface_LoadItemIcon1(globalCtx, i);
if (globalCtx != NULL) {
Interface_LoadItemIcon1(globalCtx, i);
}
}
}
}
@@ -1875,7 +1902,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
for (i = 1; i < ARRAY_COUNT(gSaveContext.childEquips.buttonItems); i++) {
if (gSaveContext.childEquips.buttonItems[i] == ITEM_HOOKSHOT) {
gSaveContext.childEquips.buttonItems[i] = ITEM_LONGSHOT;
Interface_LoadItemIcon1(globalCtx, i);
if (globalCtx != NULL) {
Interface_LoadItemIcon1(globalCtx, i);
}
}
}
}
@@ -2034,7 +2063,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
for (i = 1; i < ARRAY_COUNT(gSaveContext.adultEquips.buttonItems); i++) {
if (gSaveContext.adultEquips.buttonItems[i] == ITEM_OCARINA_FAIRY) {
gSaveContext.adultEquips.buttonItems[i] = ITEM_OCARINA_TIME;
Interface_LoadItemIcon1(globalCtx, i);
if (globalCtx != NULL) {
Interface_LoadItemIcon1(globalCtx, i);
}
}
}
}
@@ -2042,7 +2073,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
for (i = 1; i < ARRAY_COUNT(gSaveContext.childEquips.buttonItems); i++) {
if (gSaveContext.childEquips.buttonItems[i] == ITEM_OCARINA_FAIRY) {
gSaveContext.childEquips.buttonItems[i] = ITEM_OCARINA_TIME;
Interface_LoadItemIcon1(globalCtx, i);
if (globalCtx != NULL) {
Interface_LoadItemIcon1(globalCtx, i);
}
}
}
}
@@ -2070,15 +2103,21 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
return ITEM_NONE;
} else if (item == ITEM_HEART) {
osSyncPrintf("回復ハート回復ハート回復ハート\n"); // "Recovery Heart"
Health_ChangeBy(globalCtx, 0x10);
if (globalCtx != NULL) {
Health_ChangeBy(globalCtx, 0x10);
}
PerformAutosave(globalCtx, item);
return item;
} else if (item == ITEM_MAGIC_SMALL) {
if (gSaveContext.unk_13F0 != 10) {
Magic_Fill(globalCtx);
if (globalCtx != NULL) {
Magic_Fill(globalCtx);
}
}
func_80087708(globalCtx, 12, 5);
if (globalCtx != NULL) {
func_80087708(globalCtx, 12, 5);
}
if (!(gSaveContext.infTable[25] & 0x100)) {
gSaveContext.infTable[25] |= 0x100;
@@ -2090,10 +2129,13 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
return item;
} else if (item == ITEM_MAGIC_LARGE) {
if (gSaveContext.unk_13F0 != 10) {
Magic_Fill(globalCtx);
if (globalCtx != NULL) {
Magic_Fill(globalCtx);
}
}
if (globalCtx != NULL) {
func_80087708(globalCtx, 24, 5);
}
func_80087708(globalCtx, 24, 5);
if (!(gSaveContext.infTable[25] & 0x100)) {
gSaveContext.infTable[25] |= 0x100;
@@ -2136,7 +2178,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
for (int buttonIndex = 1; buttonIndex < ARRAY_COUNT(gSaveContext.equips.buttonItems); buttonIndex++) {
if ((temp + i) == gSaveContext.equips.cButtonSlots[buttonIndex - 1]) {
gSaveContext.equips.buttonItems[buttonIndex] = item;
Interface_LoadItemIcon2(globalCtx, buttonIndex);
if (globalCtx != NULL) {
Interface_LoadItemIcon2(globalCtx, buttonIndex);
}
gSaveContext.buttonStatus[BUTTON_STATUS_INDEX(buttonIndex)] = BTN_ENABLED;
break;
}
@@ -2161,6 +2205,10 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
gSaveContext.itemGetInf[1] |= 0x8000;
}
if (item >= ITEM_POCKET_EGG) {
gSaveContext.adultTradeItems |= ADULT_TRADE_FLAG(item);
}
temp = INV_CONTENT(item);
INV_CONTENT(item) = item;
@@ -2169,7 +2217,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
if (temp == gSaveContext.equips.buttonItems[i]) {
if (item != ITEM_SOLD_OUT) {
gSaveContext.equips.buttonItems[i] = item;
Interface_LoadItemIcon1(globalCtx, i);
if (globalCtx != NULL) {
Interface_LoadItemIcon1(globalCtx, i);
}
} else {
gSaveContext.equips.buttonItems[i] = ITEM_NONE;
}
@@ -2214,6 +2264,14 @@ u16 Randomizer_Item_Give(GlobalContext* globalCtx, GetItemEntry giEntry) {
return RG_NONE;
}
if (item == RG_MAGIC_BEAN_PACK) {
if (INV_CONTENT(ITEM_BEAN) == ITEM_NONE) {
INV_CONTENT(ITEM_BEAN) = ITEM_BEAN;
AMMO(ITEM_BEAN) = 10;
}
return RG_NONE;
}
if (item == RG_DOUBLE_DEFENSE) {
gSaveContext.doubleDefense = true;
gSaveContext.inventory.defenseHearts = 20;
@@ -2259,6 +2317,106 @@ u16 Randomizer_Item_Give(GlobalContext* globalCtx, GetItemEntry giEntry) {
return ITEM_NONE;
}
}
} else if ((item >= RG_FOREST_TEMPLE_SMALL_KEY && item <= RG_GANONS_CASTLE_SMALL_KEY) ||
(item >= RG_FOREST_TEMPLE_BOSS_KEY && item <= RG_GANONS_CASTLE_BOSS_KEY) ||
(item >= RG_DEKU_TREE_MAP && item <= RG_ICE_CAVERN_MAP) ||
(item >= RG_DEKU_TREE_COMPASS && item <= RG_ICE_CAVERN_COMPASS)) {
int mapIndex = gSaveContext.mapIndex;
switch (item) {
case RG_DEKU_TREE_MAP:
case RG_DEKU_TREE_COMPASS:
mapIndex = SCENE_YDAN;
break;
case RG_DODONGOS_CAVERN_MAP:
case RG_DODONGOS_CAVERN_COMPASS:
mapIndex = SCENE_DDAN;
break;
case RG_JABU_JABUS_BELLY_MAP:
case RG_JABU_JABUS_BELLY_COMPASS:
mapIndex = SCENE_BDAN;
break;
case RG_FOREST_TEMPLE_MAP:
case RG_FOREST_TEMPLE_COMPASS:
case RG_FOREST_TEMPLE_SMALL_KEY:
case RG_FOREST_TEMPLE_BOSS_KEY:
mapIndex = SCENE_BMORI1;
break;
case RG_FIRE_TEMPLE_MAP:
case RG_FIRE_TEMPLE_COMPASS:
case RG_FIRE_TEMPLE_SMALL_KEY:
case RG_FIRE_TEMPLE_BOSS_KEY:
mapIndex = SCENE_HIDAN;
break;
case RG_WATER_TEMPLE_MAP:
case RG_WATER_TEMPLE_COMPASS:
case RG_WATER_TEMPLE_SMALL_KEY:
case RG_WATER_TEMPLE_BOSS_KEY:
mapIndex = SCENE_MIZUSIN;
break;
case RG_SPIRIT_TEMPLE_MAP:
case RG_SPIRIT_TEMPLE_COMPASS:
case RG_SPIRIT_TEMPLE_SMALL_KEY:
case RG_SPIRIT_TEMPLE_BOSS_KEY:
mapIndex = SCENE_JYASINZOU;
break;
case RG_SHADOW_TEMPLE_MAP:
case RG_SHADOW_TEMPLE_COMPASS:
case RG_SHADOW_TEMPLE_SMALL_KEY:
case RG_SHADOW_TEMPLE_BOSS_KEY:
mapIndex = SCENE_HAKADAN;
break;
case RG_BOTTOM_OF_THE_WELL_MAP:
case RG_BOTTOM_OF_THE_WELL_COMPASS:
case RG_BOTTOM_OF_THE_WELL_SMALL_KEY:
mapIndex = SCENE_HAKADANCH;
break;
case RG_ICE_CAVERN_MAP:
case RG_ICE_CAVERN_COMPASS:
mapIndex = SCENE_ICE_DOUKUTO;
break;
case RG_GANONS_CASTLE_BOSS_KEY:
mapIndex = SCENE_GANON;
break;
case RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY:
mapIndex = SCENE_MEN;
break;
case RG_GERUDO_FORTRESS_SMALL_KEY:
mapIndex = SCENE_GERUDOWAY;
break;
case RG_GANONS_CASTLE_SMALL_KEY:
mapIndex = SCENE_GANONTIKA;
break;
}
if ((item >= RG_FOREST_TEMPLE_SMALL_KEY) && (item <= RG_GANONS_CASTLE_SMALL_KEY)) {
if (gSaveContext.inventory.dungeonKeys[mapIndex] < 0) {
gSaveContext.inventory.dungeonKeys[mapIndex] = 1;
return RG_NONE;
} else {
gSaveContext.inventory.dungeonKeys[mapIndex]++;
return RG_NONE;
}
} else {
int bitmask;
if ((item >= RG_DEKU_TREE_MAP) && (item <= RG_ICE_CAVERN_MAP)) {
bitmask = gBitFlags[2];
} else if ((item >= RG_DEKU_TREE_COMPASS) && (item <= RG_ICE_CAVERN_COMPASS)) {
bitmask = gBitFlags[1];
} else {
bitmask = gBitFlags[0];
}
gSaveContext.inventory.dungeonItems[mapIndex] |= bitmask;
return RG_NONE;
}
}
if (item == RG_TYCOON_WALLET) {
Inventory_ChangeUpgrade(UPG_WALLET, 3);
if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_FULL_WALLETS)) {
Rupees_ChangeBy(999);
}
return RG_NONE;
}
temp = gSaveContext.inventory.items[slot];
@@ -2268,7 +2426,6 @@ u16 Randomizer_Item_Give(GlobalContext* globalCtx, GetItemEntry giEntry) {
return temp;
}
u8 Item_CheckObtainability(u8 item) {
s16 i;
s16 slot = SLOT(item);
@@ -2321,6 +2478,13 @@ u8 Item_CheckObtainability(u8 item) {
} else {
return ITEM_NONE;
}
} else if ( gSaveContext.n64ddFlag &&
((item >= RG_GERUDO_FORTRESS_SMALL_KEY) && (item <= RG_GANONS_CASTLE_SMALL_KEY) ||
(item >= RG_FOREST_TEMPLE_BOSS_KEY) && (item <= RG_GANONS_CASTLE_BOSS_KEY) ||
(item >= RG_DEKU_TREE_MAP) && (item <= RG_ICE_CAVERN_MAP) ||
(item >= RG_DEKU_TREE_COMPASS) && (item <= RG_ICE_CAVERN_COMPASS))
) {
return ITEM_NONE;
} else if ((item == ITEM_KEY_BOSS) || (item == ITEM_COMPASS) || (item == ITEM_DUNGEON_MAP)) {
return ITEM_NONE;
} else if (item == ITEM_KEY_SMALL) {
@@ -2507,6 +2671,17 @@ s32 Inventory_HasEmptyBottle(void) {
}
}
bool Inventory_HasEmptyBottleSlot(void) {
u8* items = gSaveContext.inventory.items;
return (
items[SLOT_BOTTLE_1] == ITEM_NONE ||
items[SLOT_BOTTLE_2] == ITEM_NONE ||
items[SLOT_BOTTLE_3] == ITEM_NONE ||
items[SLOT_BOTTLE_4] == ITEM_NONE
);
}
s32 Inventory_HasSpecificBottle(u8 bottleItem) {
u8* items = gSaveContext.inventory.items;
@@ -2568,6 +2743,21 @@ s32 Inventory_ConsumeFairy(GlobalContext* globalCtx) {
return 0;
}
bool Inventory_HatchPocketCucco(GlobalContext* globalCtx) {
if (!gSaveContext.n64ddFlag) {
return Inventory_ReplaceItem(globalCtx, ITEM_POCKET_EGG, ITEM_POCKET_CUCCO);
}
if (!PLAYER_HAS_SHUFFLED_ADULT_TRADE_ITEM(ITEM_POCKET_EGG)) {
return 0;
}
gSaveContext.adultTradeItems &= ~ADULT_TRADE_FLAG(ITEM_POCKET_EGG);
gSaveContext.adultTradeItems |= ADULT_TRADE_FLAG(ITEM_POCKET_CUCCO);
Inventory_ReplaceItem(globalCtx, ITEM_POCKET_EGG, ITEM_POCKET_CUCCO);
return 1;
}
void func_80086D5C(s32* buf, u16 size) {
u16 i;
@@ -4509,14 +4699,15 @@ void Interface_Draw(GlobalContext* globalCtx) {
static s16 D_80125B1C[][3] = {
{ 0, 150, 0 }, { 100, 255, 0 }, { 255, 255, 255 }, { 0, 0, 0 }, { 255, 255, 255 },
};
static s16 rupeeDigitsFirst[] = { 1, 0, 0 };
static s16 rupeeDigitsCount[] = { 2, 3, 3 };
static s16 rupeeDigitsFirst[] = { 1, 0, 0, 0 };
static s16 rupeeDigitsCount[] = { 2, 3, 3, 3 };
// courtesy of https://github.com/TestRunnerSRL/OoT-Randomizer/blob/Dev/ASM/c/hud_colors.c
static s16 rupeeWalletColors[3][3] = {
static s16 rupeeWalletColors[4][3] = {
{ 0xC8, 0xFF, 0x64 }, // Base Wallet (Green)
{ 0x82, 0x82, 0xFF }, // Adult's Wallet (Blue)
{ 0xFF, 0x64, 0x64 }, // Giant's Wallet (Red)
{ 0xFF, 0x5A, 0xFF }, // Tycoon's Wallet (Purple). Only used in rando shopsanity.
};
Color_RGB8 rColor_ori = { 200, 255, 100 };
Color_RGB8 rColor;
+3 -3
View File
@@ -200,7 +200,7 @@ void GivePlayerRandoRewardSongOfTime(GlobalContext* globalCtx, RandomizerCheck c
Player* player = GET_PLAYER(globalCtx);
if (gSaveContext.entranceIndex == 0x050F && player != NULL && !Player_InBlockingCsMode(globalCtx, player) &&
!Flags_GetTreasure(globalCtx, 0x1F) && gSaveContext.nextTransition == 0xFF) {
!Flags_GetTreasure(globalCtx, 0x1F) && gSaveContext.nextTransition == 0xFF && !gSaveContext.pendingIceTrapCount) {
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, RG_SONG_OF_TIME);
GiveItemEntryWithoutActor(globalCtx, getItemEntry);
player->pendingFlag.flagID = 0x1F;
@@ -245,7 +245,7 @@ void GivePlayerRandoRewardZeldaLightArrowsGift(GlobalContext* globalCtx, Randomi
!Flags_GetTreasure(globalCtx, 0x1E) && player != NULL && !Player_InBlockingCsMode(globalCtx, player) &&
globalCtx->sceneLoadFlag == 0) {
GetItemEntry getItem = Randomizer_GetItemFromKnownCheck(check, GI_ARROW_LIGHT);
if (player->pendingFlag.flagType == FLAG_NONE && GiveItemEntryWithoutActor(globalCtx, getItem)) {
if (GiveItemEntryWithoutActor(globalCtx, getItem)) {
player->pendingFlag.flagID = 0x1E;
player->pendingFlag.flagType = FLAG_SCENE_TREASURE;
}
@@ -401,7 +401,7 @@ void Gameplay_Init(GameState* thisx) {
gSaveContext.bgsDayCount++;
gSaveContext.dogIsLost = true;
if (Inventory_ReplaceItem(globalCtx, ITEM_WEIRD_EGG, ITEM_CHICKEN) ||
Inventory_ReplaceItem(globalCtx, ITEM_POCKET_EGG, ITEM_POCKET_CUCCO)) {
Inventory_HatchPocketCucco(globalCtx)) {
Message_StartTextbox(globalCtx, 0x3066, NULL);
}
gSaveContext.nextDayTime = 0xFFFE;
+9 -1
View File
@@ -1170,7 +1170,15 @@ void Player_DrawGetItemImpl(GlobalContext* globalCtx, Player* this, Vec3f* refPo
Matrix_RotateZYX(0, globalCtx->gameplayFrames * 1000, 0, MTXMODE_APPLY);
Matrix_Scale(0.2f, 0.2f, 0.2f, MTXMODE_APPLY);
GetItem_Draw(globalCtx, drawIdPlusOne - 1);
if (!(this->getItemEntry.modIndex == MOD_RANDOMIZER && this->getItemEntry.getItemId == RG_ICE_TRAP)) {
// RANDOTODO: Make this more flexible for easier toggling of individual item recolors in the future.
if (this->getItemEntry.drawFunc != NULL &&
(CVar_GetS32("gRandoMatchKeyColors", 0) || this->getItemEntry.getItemId == RG_DOUBLE_DEFENSE)) {
this->getItemEntry.drawFunc(globalCtx, &this->getItemEntry);
} else {
GetItem_Draw(globalCtx, drawIdPlusOne - 1);
}
}
CLOSE_DISPS(globalCtx->state.gfxCtx);
}
+7 -1
View File
@@ -23,6 +23,8 @@
#include "overlays/actors/ovl_Bg_Dodoago/z_bg_dodoago.h"
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
#define ENTRANCE(scene, spawn, continueBgm, displayTitleCard, fadeIn, fadeOut) \
{ \
scene, spawn, \
@@ -2136,7 +2138,11 @@ void func_8009EE44(GlobalContext* globalCtx) {
gDPPipeSync(POLY_OPA_DISP++);
gDPSetEnvColor(POLY_OPA_DISP++, 128, 128, 128, 128);
if ((globalCtx->roomCtx.unk_74[0] == 0) && (INV_CONTENT(ITEM_COJIRO) == ITEM_COJIRO)) {
bool playerHasCojiro = INV_CONTENT(ITEM_COJIRO) == ITEM_COJIRO;
if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE)) {
playerHasCojiro = PLAYER_HAS_SHUFFLED_ADULT_TRADE_ITEM(ITEM_COJIRO);
}
if ((globalCtx->roomCtx.unk_74[0] == 0) && playerHasCojiro) {
if (globalCtx->roomCtx.unk_74[1] == 50) {
func_8002F7DC(&GET_PLAYER(globalCtx)->actor, NA_SE_EV_CHICKEN_CRY_M);
globalCtx->roomCtx.unk_74[0] = 1;
+99 -413
View File
@@ -3,9 +3,11 @@
#include <string.h>
#include <soh/Enhancements/randomizer/randomizerTypes.h>
#include <soh/Enhancements/randomizer/randomizer_inf.h>
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
#define NUM_DUNGEONS 8
#define NUM_TRIALS 6
#define NUM_COWS 10
/**
* Initialize new save.
@@ -51,31 +53,6 @@ void GiveLinkRupees(int numOfRupees) {
}
}
void GiveLinkRupeesByGetItemId(GetItemID giid) {
if (giid == GI_RUPEE_GREEN) {
GiveLinkRupees(1);
} else if (giid == GI_RUPEE_BLUE) {
GiveLinkRupees(5);
} else if (giid == GI_RUPEE_RED) {
GiveLinkRupees(20);
} else if (giid == GI_RUPEE_PURPLE) {
GiveLinkRupees(50);
} else if (giid == GI_RUPEE_GOLD) {
GiveLinkRupees(100);
}
}
void GiveLinkBombchus(GetItemID giid) {
INV_CONTENT(ITEM_BOMBCHU) = ITEM_BOMBCHU;
if (giid == GI_BOMBCHUS_5) {
AMMO(ITEM_BOMBCHU) += 5;
} else if (giid == GI_BOMBCHUS_10) {
AMMO(ITEM_BOMBCHU) += 10;
} else if (giid == GI_BOMBCHUS_20) {
AMMO(ITEM_BOMBCHU) += 20;
}
}
void GiveLinkDekuSticks(int howManySticks) {
int maxStickCount;
if (CUR_UPG_VALUE(UPG_STICKS) == 0) {
@@ -97,16 +74,6 @@ void GiveLinkDekuSticks(int howManySticks) {
}
}
void GiveLinkDekuSticksByGetItemId(GetItemID giid) {
if (giid == GI_STICKS_1) {
GiveLinkDekuSticks(1);
} else if (giid == GI_STICKS_5) {
GiveLinkDekuSticks(5);
} else if (giid == GI_STICKS_10) {
GiveLinkDekuSticks(10);
}
}
void GiveLinkDekuNuts(int howManyNuts) {
int maxNutCount;
if (CUR_UPG_VALUE(UPG_NUTS) == 0) {
@@ -128,300 +95,25 @@ void GiveLinkDekuNuts(int howManyNuts) {
}
}
void GiveLinkDekuNutsByGetItemId(GetItemID giid) {
if (giid == GI_NUTS_5) {
GiveLinkDekuNuts(5);
} else if (giid == GI_NUTS_10) {
GiveLinkDekuNuts(10);
void GiveLinksPocketItem() {
if (Randomizer_GetSettingValue(RSK_LINKS_POCKET) < 3) {
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LINKS_POCKET, RG_NONE);
if (getItemEntry.modIndex == MOD_NONE) {
if (getItemEntry.getItemId == GI_SWORD_BGS) {
gSaveContext.bgsFlag = true;
}
Item_Give(NULL, getItemEntry.itemId);
} else if (getItemEntry.modIndex == MOD_RANDOMIZER) {
if (getItemEntry.getItemId == RG_ICE_TRAP) {
gSaveContext.pendingIceTrapCount++;
} else {
Randomizer_Item_Give(NULL, getItemEntry);
}
}
}
}
void GiveLinkBeans() {
INV_CONTENT(ITEM_BEAN) = ITEM_BEAN;
AMMO(ITEM_BEAN)++;
}
void GiveLinkKokiriSword() {
uint32_t bitMask = 1 << 0;
gSaveContext.inventory.equipment |= bitMask;
}
void GiveLinkGiantsKnife() {
gSaveContext.bgsFlag = 0;
gSaveContext.swordHealth = 8;
uint32_t bitMask = 1 << 2;
gSaveContext.inventory.equipment |= bitMask;
}
void GiveLinkBiggoronSword() {
gSaveContext.bgsFlag = 1;
gSaveContext.swordHealth = 8;
uint32_t bitMask = 1 << 2;
gSaveContext.inventory.equipment |= bitMask;
}
void GiveLinkDekuShield() {
uint32_t bitMask = 1 << 4;
gSaveContext.inventory.equipment |= bitMask;
}
void GiveLinkHylianShield() {
uint32_t bitMask = 1 << 5;
gSaveContext.inventory.equipment |= bitMask;
}
void GiveLinkMirrorShield() {
uint32_t bitMask = 1 << 6;
gSaveContext.inventory.equipment |= bitMask;
}
void GiveLinkGoronTunic() {
uint32_t bitMask = 1 << 9;
gSaveContext.inventory.equipment |= bitMask;
}
void GiveLinkZoraTunic() {
uint32_t bitMask = 1 << 10;
gSaveContext.inventory.equipment |= bitMask;
}
void GiveLinkIronBoots() {
uint32_t bitMask = 1 << 13;
gSaveContext.inventory.equipment |= bitMask;
}
void GiveLinkHoverBoots() {
uint32_t bitMask = 1 << 14;
gSaveContext.inventory.equipment |= bitMask;
}
void GiveLinkStoneOfAgony() {
uint32_t bitMask = 1 << QUEST_STONE_OF_AGONY;
gSaveContext.inventory.questItems |= bitMask;
}
void GiveLinkGerudoCard() {
uint32_t bitMask = 1 << QUEST_GERUDO_CARD;
gSaveContext.inventory.questItems |= bitMask;
}
void GiveLinkPieceOfHeart() {
int32_t pohCount = (gSaveContext.inventory.questItems & 0xF0000000) >> 28;
pohCount++;
gSaveContext.inventory.questItems |= (pohCount << 28);
}
void GiveLinkHeartContainer() {
gSaveContext.healthCapacity += 16;
gSaveContext.health += 16;
}
void GiveLinkBulletBagUpgrade(GetItemID giid) {
if (giid == GI_SLINGSHOT) {
INV_CONTENT(ITEM_SLINGSHOT) = ITEM_SLINGSHOT;
AMMO(ITEM_SLINGSHOT) = 30;
Inventory_ChangeUpgrade(UPG_BULLET_BAG, 1);
} else if (giid == GI_BULLET_BAG_40) {
Inventory_ChangeUpgrade(UPG_BULLET_BAG, 2);
AMMO(ITEM_SLINGSHOT) = 40;
} else if (giid == GI_BULLET_BAG_50) {
Inventory_ChangeUpgrade(UPG_BULLET_BAG, 3);
AMMO(ITEM_SLINGSHOT) = 50;
}
}
void GiveLinkQuiverUpgrade(GetItemID giid) {
if (giid == GI_BOW) {
INV_CONTENT(ITEM_BOW) = ITEM_BOW;
Inventory_ChangeUpgrade(UPG_QUIVER, 1);
AMMO(ITEM_BOW) = 30;
} else if (giid == GI_QUIVER_40) {
Inventory_ChangeUpgrade(UPG_QUIVER, 2);
AMMO(ITEM_BOW) = 40;
} else if (giid == GI_QUIVER_50) {
Inventory_ChangeUpgrade(UPG_QUIVER, 3);
AMMO(ITEM_BOW) = 50;
}
}
void GiveLinkBombBagUpgrade(GetItemID giid) {
if (giid == GI_BOMB_BAG_20) {
INV_CONTENT(ITEM_BOMB) = ITEM_BOMB;
Inventory_ChangeUpgrade(UPG_BOMB_BAG, 1);
AMMO(ITEM_BOMB) = 20;
} else if (giid == GI_BOMB_BAG_30) {
Inventory_ChangeUpgrade(UPG_BOMB_BAG, 2);
AMMO(ITEM_BOMB) = 30;
} else if (giid == GI_BOMB_BAG_40) {
Inventory_ChangeUpgrade(UPG_BOMB_BAG, 3);
AMMO(ITEM_BOMB) = 40;
}
}
void GiveLinkStrengthUpgrade(GetItemID giid) {
if (giid == GI_BRACELET) {
Inventory_ChangeUpgrade(UPG_STRENGTH, 1);
} else if (giid == GI_GAUNTLETS_SILVER) {
Inventory_ChangeUpgrade(UPG_STRENGTH, 2);
} else if (giid == GI_GAUNTLETS_GOLD) {
Inventory_ChangeUpgrade(UPG_STRENGTH, 3);
}
}
void GiveLinkScaleUpgrade(GetItemID giid) {
if (giid == GI_SCALE_SILVER) {
Inventory_ChangeUpgrade(UPG_SCALE, 1);
} else if (giid == GI_SCALE_GOLD) {
Inventory_ChangeUpgrade(UPG_SCALE, 2);
}
}
void GiveLinkWalletUpgrade(GetItemID giid) {
if (giid == GI_WALLET_ADULT) {
Inventory_ChangeUpgrade(UPG_WALLET, 1);
} else if (giid == GI_WALLET_GIANT) {
Inventory_ChangeUpgrade(UPG_WALLET, 2);
}
}
void GiveLinkDekuStickUpgrade(GetItemID giid) {
if (giid == GI_STICK_UPGRADE_20) {
INV_CONTENT(ITEM_STICK) = ITEM_STICK;
Inventory_ChangeUpgrade(UPG_STICKS, 2);
AMMO(ITEM_STICK) = 20;
} else if (giid == GI_STICK_UPGRADE_30) {
Inventory_ChangeUpgrade(UPG_STICKS, 3);
AMMO(ITEM_STICK) = 30;
}
}
void GiveLinkDekuNutUpgrade(GetItemID giid) {
if (giid == GI_NUT_UPGRADE_30) {
INV_CONTENT(ITEM_NUT) = ITEM_NUT;
Inventory_ChangeUpgrade(UPG_NUTS, 2);
AMMO(ITEM_NUT) = 30;
} else if (giid == GI_NUT_UPGRADE_40) {
Inventory_ChangeUpgrade(UPG_NUTS, 3);
AMMO(ITEM_NUT) = 40;
}
}
void GiveLinkMagic(GetItemID giid) {
if (giid == RG_MAGIC_SINGLE) {
gSaveContext.magicLevel = 1;
gSaveContext.magicAcquired = true;
gSaveContext.doubleMagic = false;
} else if (giid == RG_MAGIC_DOUBLE) {
gSaveContext.magicLevel = 2;
gSaveContext.magicAcquired = true;
gSaveContext.doubleMagic = true;
}
}
void GiveLinkDoubleDefense() {
gSaveContext.doubleDefense = 1;
gSaveContext.inventory.defenseHearts = 20;
}
void GiveLinkSong(GetItemID getItemId) {
uint32_t bitMask;
switch (getItemId) {
case RG_ZELDAS_LULLABY:
bitMask = 1 << QUEST_SONG_LULLABY;
break;
case RG_SUNS_SONG:
bitMask = 1 << QUEST_SONG_SUN;
break;
case RG_EPONAS_SONG:
bitMask = 1 << QUEST_SONG_EPONA;
break;
case RG_SONG_OF_STORMS:
bitMask = 1 << QUEST_SONG_STORMS;
break;
case RG_SONG_OF_TIME:
bitMask = 1 << QUEST_SONG_TIME;
break;
case RG_SARIAS_SONG:
bitMask = 1 << QUEST_SONG_SARIA;
break;
case RG_MINUET_OF_FOREST:
bitMask = 1 << QUEST_SONG_MINUET;
break;
case RG_BOLERO_OF_FIRE:
bitMask = 1 << QUEST_SONG_BOLERO;
break;
case RG_SERENADE_OF_WATER:
bitMask = 1 << QUEST_SONG_SERENADE;
break;
case RG_NOCTURNE_OF_SHADOW:
bitMask = 1 << QUEST_SONG_NOCTURNE;
break;
case RG_REQUIEM_OF_SPIRIT:
bitMask = 1 << QUEST_SONG_REQUIEM;
break;
case RG_PRELUDE_OF_LIGHT:
bitMask = 1 << QUEST_SONG_PRELUDE;
break;
}
gSaveContext.inventory.questItems |= bitMask;
}
void GiveLinkDungeonReward(uint16_t getItemId) {
s16 item;
u8 medallion = 0;
switch (getItemId) {
case RG_FOREST_MEDALLION:
item = ITEM_MEDALLION_FOREST;
medallion = 1;
break;
case RG_FIRE_MEDALLION:
item = ITEM_MEDALLION_FIRE;
medallion = 1;
break;
case RG_WATER_MEDALLION:
item = ITEM_MEDALLION_WATER;
medallion = 1;
break;
case RG_SHADOW_MEDALLION:
item = ITEM_MEDALLION_SHADOW;
medallion = 1;
break;
case RG_SPIRIT_MEDALLION:
item = ITEM_MEDALLION_SPIRIT;
medallion = 1;
break;
case RG_LIGHT_MEDALLION:
item = ITEM_MEDALLION_LIGHT;
medallion = 1;
break;
case RG_KOKIRI_EMERALD:
item = ITEM_KOKIRI_EMERALD;
break;
case RG_GORON_RUBY:
item = ITEM_GORON_RUBY;
break;
case RG_ZORA_SAPPHIRE:
item = ITEM_ZORA_SAPPHIRE;
break;
}
if (medallion == 1) {
gSaveContext.inventory.questItems |= gBitFlags[item - ITEM_MEDALLION_FOREST + QUEST_MEDALLION_FOREST];
} else {
gSaveContext.inventory.questItems |= gBitFlags[item - ITEM_KOKIRI_EMERALD + QUEST_KOKIRI_EMERALD];
}
}
void GiveLinksPocketMedallion() {
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LINKS_POCKET, RG_NONE);
GiveLinkDungeonReward(getItemEntry.getItemId);
}
/**
* Copy save currently on the buffer to Save Context and complete various tasks to open the save.
* This includes:
@@ -563,13 +255,15 @@ void Sram_OpenSave() {
gSaveContext.equips.equipment |= 2;
}
for (i = 0; i < ARRAY_COUNT(gSpoilingItems); i++) {
if (INV_CONTENT(ITEM_TRADE_ADULT) == gSpoilingItems[i]) {
INV_CONTENT(gSpoilingItemReverts[i]) = gSpoilingItemReverts[i];
if (!(gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE))) {
for (i = 0; i < ARRAY_COUNT(gSpoilingItems); i++) {
if (INV_CONTENT(ITEM_TRADE_ADULT) == gSpoilingItems[i]) {
INV_CONTENT(gSpoilingItemReverts[i]) = gSpoilingItemReverts[i];
for (j = 1; j < ARRAY_COUNT(gSaveContext.equips.buttonItems); j++) {
if (gSaveContext.equips.buttonItems[j] == gSpoilingItems[i]) {
gSaveContext.equips.buttonItems[j] = gSpoilingItemReverts[i];
for (j = 1; j < ARRAY_COUNT(gSaveContext.equips.buttonItems); j++) {
if (gSaveContext.equips.buttonItems[j] == gSpoilingItems[i]) {
gSaveContext.equips.buttonItems[j] = gSpoilingItemReverts[i];
}
}
}
}
@@ -610,14 +304,18 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
fileChooseCtx->n64ddFlag = 1;
gSaveContext.n64ddFlag = 1;
// Sets all the dungeons to incomplete when generating a rando save. Fixes https://github.com/briaguya-ai/rando-issue-tracker/issues/82
for (u8 i = 0; i < NUM_DUNGEONS; i++) {
gSaveContext.dungeonsDone[i] = 0;
// Sets all rando flags to false
for (s32 i = 0; i < ARRAY_COUNT(gSaveContext.randomizerInf); i++) {
gSaveContext.randomizerInf[i] = 0;
}
// Sets all Ganon's Trials to incomplete when generating a rando save. Fixes https://github.com/briaguya-ai/rando-issue-tracker/issues/131
for (u8 i = 0; i < NUM_TRIALS; i++) {
gSaveContext.trialsDone[i] = 0;
// Set all trials to cleared if trial count is random or anything other than 6
if (Randomizer_GetSettingValue(RSK_RANDOM_TRIALS) || (Randomizer_GetSettingValue(RSK_TRIAL_COUNT) != 6)) {
for (u16 i = RAND_INF_TRIALS_DONE_LIGHT_TRIAL; i <= RAND_INF_TRIALS_DONE_SHADOW_TRIAL; i++) {
if (!Randomizer_IsTrialRequired(i)) {
Flags_SetRandomizerInf(i);
}
}
}
// Set Cutscene flags to skip them
@@ -626,8 +324,9 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
gSaveContext.eventChkInf[4] |= 0x20; // master sword pulled
gSaveContext.eventChkInf[4] |= 0x8000; // entered master sword chamber
gSaveContext.infTable[0] |= 1;
// RANDTODO: Don't skip this scene if Don't Skip Glitch Useful Cutscenes is enabled.
gSaveContext.infTable[17] |= 0x400; // Darunia in Fire Temple
if (!Randomizer_GetSettingValue(RSK_ENABLE_GLITCH_CUTSCENES)) {
gSaveContext.infTable[17] |= 0x400; // Darunia in Fire Temple
}
gSaveContext.cutsceneIndex = 0;
Flags_SetEventChkInf(5);
@@ -645,8 +344,16 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
gSaveContext.eventChkInf[3] |= 0x800;
gSaveContext.eventChkInf[12] |= 1;
// shuffle adult trade quest
if (Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE)) {
gSaveContext.adultTradeItems = 0;
}
// Starts pending ice traps out at 0 before potentially incrementing them down the line.
gSaveContext.pendingIceTrapCount = 0;
// Give Link's pocket item
GiveLinksPocketMedallion();
GiveLinksPocketItem();
int openForest = Randomizer_GetSettingValue(RSK_FOREST);
switch (openForest) {
@@ -675,18 +382,19 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
break;
}
if(Randomizer_GetSettingValue(RSK_STARTING_KOKIRI_SWORD)) GiveLinkKokiriSword();
if(Randomizer_GetSettingValue(RSK_STARTING_DEKU_SHIELD)) GiveLinkDekuShield();
if(Randomizer_GetSettingValue(RSK_STARTING_KOKIRI_SWORD)) Item_Give(NULL, ITEM_SWORD_KOKIRI);
if(Randomizer_GetSettingValue(RSK_STARTING_DEKU_SHIELD)) Item_Give(NULL, ITEM_SHIELD_DEKU);
if(Randomizer_GetSettingValue(RSK_STARTING_OCARINA)) {
INV_CONTENT(ITEM_OCARINA_FAIRY) = ITEM_OCARINA_FAIRY;
}
if(Randomizer_GetSettingValue(RSK_STARTING_MAPS_COMPASSES)) {
// "Start with" == 0 for Maps and Compasses
if(Randomizer_GetSettingValue(RSK_STARTING_MAPS_COMPASSES) == 0) {
uint32_t mapBitMask = 1 << 1;
uint32_t compassBitMask = 1 << 2;
uint32_t startingDungeonItemsBitMask = mapBitMask | compassBitMask;
for(int scene = 0; scene <= 9; scene++) {
for(int scene = SCENE_YDAN; scene <= SCENE_ICE_DOUKUTO; scene++) {
gSaveContext.inventory.dungeonItems[scene] |= startingDungeonItemsBitMask;
}
}
@@ -701,71 +409,16 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
s32 giid = getItem.getItemId;
if (getItem.modIndex == MOD_NONE) {
if (getItem.itemId >= ITEM_MEDALLION_FOREST && getItem.itemId <= ITEM_ZORA_SAPPHIRE) {
GiveLinkDungeonReward(getItem.getItemId);
} else if (getItem.itemId >= ITEM_SONG_MINUET && getItem.itemId <= ITEM_SONG_STORMS) {
GiveLinkSong(getItem.getItemId);
} else if (giid == GI_RUPEE_GREEN || giid == GI_RUPEE_BLUE || giid == GI_RUPEE_RED ||
giid == GI_RUPEE_PURPLE || giid == GI_RUPEE_GOLD) {
GiveLinkRupeesByGetItemId(giid);
} else if (giid == GI_BOMBCHUS_10 || giid == GI_BOMBCHUS_5 || giid == GI_BOMBCHUS_20) {
GiveLinkBombchus(giid);
} else if (giid == GI_STICKS_1 || giid == GI_STICKS_5 || giid == GI_STICKS_10) {
GiveLinkDekuSticksByGetItemId(giid);
} else if (giid == GI_NUTS_5 || giid == GI_NUTS_10) {
GiveLinkDekuNutsByGetItemId(giid);
} else if (giid == GI_BEAN) {
GiveLinkBeans();
} else if (giid == GI_SWORD_KOKIRI) {
GiveLinkKokiriSword();
} else if (giid == GI_SWORD_BGS) {
GiveLinkBiggoronSword();
} else if (giid == GI_SWORD_KNIFE) {
GiveLinkGiantsKnife();
} else if (giid == GI_SHIELD_DEKU) {
GiveLinkDekuShield();
} else if (giid == GI_SHIELD_HYLIAN) {
GiveLinkHylianShield();
} else if (giid == GI_SHIELD_MIRROR) {
GiveLinkMirrorShield();
} else if (giid == GI_TUNIC_GORON) {
GiveLinkGoronTunic();
} else if (giid == GI_TUNIC_ZORA) {
GiveLinkZoraTunic();
} else if (giid == GI_BOOTS_IRON) {
GiveLinkIronBoots();
} else if (giid == GI_BOOTS_HOVER) {
GiveLinkHoverBoots();
} else if (giid == GI_SLINGSHOT || giid == GI_BULLET_BAG_40 || giid == GI_BULLET_BAG_50) {
GiveLinkBulletBagUpgrade(giid);
} else if (giid == GI_BOW || giid == GI_QUIVER_40 || giid == GI_QUIVER_50) {
GiveLinkQuiverUpgrade(giid);
} else if (giid == GI_BOMB_BAG_20 || giid == GI_BOMB_BAG_30 || giid == GI_BOMB_BAG_40) {
GiveLinkBombBagUpgrade(giid);
} else if (giid == GI_BRACELET || giid == GI_GAUNTLETS_SILVER || giid == GI_GAUNTLETS_GOLD) {
GiveLinkStrengthUpgrade(giid);
} else if (giid == GI_SCALE_SILVER || giid == GI_SCALE_GOLD) {
GiveLinkScaleUpgrade(giid);
} else if (giid == GI_WALLET_ADULT || giid == GI_WALLET_GIANT) {
GiveLinkWalletUpgrade(giid);
} else if (giid == GI_STONE_OF_AGONY) {
GiveLinkStoneOfAgony();
} else if (giid == GI_GERUDO_CARD) {
GiveLinkGerudoCard();
} else if (giid == GI_HEART_PIECE) {
GiveLinkPieceOfHeart();
} else if (giid == GI_HEART_CONTAINER) {
GiveLinkHeartContainer();
} else if (giid == GI_STICK_UPGRADE_20 || giid == GI_STICK_UPGRADE_30) {
GiveLinkDekuStickUpgrade(giid);
} else if (giid == GI_NUT_UPGRADE_30 || giid == GI_NUT_UPGRADE_40) {
GiveLinkDekuNutUpgrade(giid);
} else {
s32 iid = getItem.itemId;
if (iid != -1) INV_CONTENT(iid) = iid;
if (getItem.getItemId == GI_SWORD_BGS) {
gSaveContext.bgsFlag = true;
}
Item_Give(NULL, getItem.itemId);
} else if (getItem.modIndex == MOD_RANDOMIZER) {
Randomizer_Item_Give(NULL, getItem);
if (getItem.getItemId == RG_ICE_TRAP) {
gSaveContext.pendingIceTrapCount++;
} else {
Randomizer_Item_Give(NULL, getItem);
}
}
// malon/talon back at ranch
@@ -789,9 +442,31 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
GiveLinkRupees(9001);
}
// For Ganon's boss key "Start With" is 0
if(Randomizer_GetSettingValue(RSK_GANONS_BOSS_KEY) == 0) {
gSaveContext.inventory.dungeonItems[10] |= 1;
// "Start with" == 0 for Keysanity
if(Randomizer_GetSettingValue(RSK_KEYSANITY) == 0) {
// TODO: If master quest there are different key counts
gSaveContext.inventory.dungeonKeys[SCENE_BMORI1] = 5; // Forest
gSaveContext.inventory.dungeonKeys[SCENE_HIDAN] = 8; // Fire
gSaveContext.inventory.dungeonKeys[SCENE_MIZUSIN] = 6; // Water
gSaveContext.inventory.dungeonKeys[SCENE_JYASINZOU] = 5; // Spirit
gSaveContext.inventory.dungeonKeys[SCENE_HAKADAN] = 5; // Shadow
gSaveContext.inventory.dungeonKeys[SCENE_HAKADANCH] = 3; // BotW
gSaveContext.inventory.dungeonKeys[SCENE_MEN] = 9; // GTG
gSaveContext.inventory.dungeonKeys[SCENE_GANONTIKA] = 2; // Ganon
}
// "Start with" == 0 for Boss Kesanity
if(Randomizer_GetSettingValue(RSK_BOSS_KEYSANITY) == 0) {
gSaveContext.inventory.dungeonItems[SCENE_BMORI1] |= 1; // Forest
gSaveContext.inventory.dungeonItems[SCENE_HIDAN] |= 1; // Fire
gSaveContext.inventory.dungeonItems[SCENE_MIZUSIN] |= 1; // Water
gSaveContext.inventory.dungeonItems[SCENE_JYASINZOU] |= 1; // Spirit
gSaveContext.inventory.dungeonItems[SCENE_HAKADAN] |= 1; // Shadow
}
// "Start with" == 2 for Ganon's Boss Key
if(Randomizer_GetSettingValue(RSK_GANONS_BOSS_KEY) == 2) {
gSaveContext.inventory.dungeonItems[SCENE_GANON] |= 1;
}
HIGH_SCORE(HS_POE_POINTS) = 1000 - (100 * Randomizer_GetSettingValue(RSK_BIG_POE_COUNT));
@@ -850,9 +525,20 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
gSaveContext.sceneFlags[12].collect |= (1 << 0x0C);
if (!Randomizer_GetSettingValue(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD)) {
GiveLinkGerudoCard();
Item_Give(NULL, ITEM_GERUDO_CARD);
}
}
// complete mask quest
if (Randomizer_GetSettingValue(RSK_COMPLETE_MASK_QUEST)) {
gSaveContext.infTable[7] |= 0x80; // Soldier Wears Keaton Mask
gSaveContext.itemGetInf[3] |= 0x100; // Sold Keaton Mask
gSaveContext.itemGetInf[3] |= 0x200; // Sold Skull Mask
gSaveContext.itemGetInf[3] |= 0x400; // Sold Spooky Mask
gSaveContext.itemGetInf[3] |= 0x800; // bunny hood related
gSaveContext.itemGetInf[3] |= 0x8000; // Obtained Mask of Truth
gSaveContext.eventChkInf[8] |= 0x8000; // sold all masks
}
}
Save_SaveFile();
@@ -106,7 +106,7 @@ void BgBreakwall_Init(Actor* thisx, GlobalContext* globalCtx) {
s32 wallType = ((this->dyna.actor.params >> 13) & 3) & 0xFF;
// Initialize this with the mud wall, so it can't be affected by toggling while the actor is loaded
blueFireArrowsEnabledOnMudwallLoad = (CVar_GetS32("gBlueFireArrows", 0));
blueFireArrowsEnabledOnMudwallLoad = CVar_GetS32("gBlueFireArrows", 0) || (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_BLUE_FIRE_ARROWS));
Actor_ProcessInitChain(&this->dyna.actor, sInitChain);
DynaPolyActor_Init(&this->dyna, DPM_UNK);
@@ -70,7 +70,7 @@ const ActorInit Bg_Dy_Yoseizo_InitVars = {
void GivePlayerRandoRewardGreatFairy(BgDyYoseizo* this, GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
GetItemEntry getItemEntry = Randomizer_GetRandomizedItem(GI_NONE, this->actor.id, this->fountainType + 1, globalCtx->sceneNum);
GetItemEntry getItemEntry = Randomizer_GetItemFromActor(this->actor.id, globalCtx->sceneNum, this->fountainType + 1, GI_NONE);
if (this->actor.parent == GET_PLAYER(globalCtx) && !Flags_GetTreasure(globalCtx, this->fountainType + 1) &&
!Player_InBlockingCsMode(globalCtx, GET_PLAYER(globalCtx))) {
@@ -132,35 +132,35 @@ u8 CheckMedallionCount() {
u8 CheckDungeonCount() {
u8 dungeonCount = 0;
if (gSaveContext.dungeonsDone[0] == 1) {
if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE)) {
dungeonCount++;
}
if (gSaveContext.dungeonsDone[1] == 1) {
if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN)) {
dungeonCount++;
}
if (gSaveContext.dungeonsDone[2] == 1) {
if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY)) {
dungeonCount++;
}
if (gSaveContext.dungeonsDone[3] == 1) {
if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FOREST_TEMPLE)) {
dungeonCount++;
}
if (gSaveContext.dungeonsDone[4] == 1) {
if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE)) {
dungeonCount++;
}
if (gSaveContext.dungeonsDone[5] == 1) {
if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE)) {
dungeonCount++;
}
if (gSaveContext.dungeonsDone[6] == 1) {
if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE)) {
dungeonCount++;
}
if (gSaveContext.dungeonsDone[7] == 1) {
if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE)) {
dungeonCount++;
}
@@ -105,7 +105,7 @@ void func_80890740(BgIceShelter* this, GlobalContext* globalCtx) {
s32 type = (this->dyna.actor.params >> 8) & 7;
// Initialize this with the red ice, so it can't be affected by toggling while the actor is loaded
blueFireArrowsEnabledOnRedIceLoad = (CVar_GetS32("gBlueFireArrows", 0));
blueFireArrowsEnabledOnRedIceLoad = CVar_GetS32("gBlueFireArrows", 0) || (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_BLUE_FIRE_ARROWS));
Collider_InitCylinder(globalCtx, &this->cylinder1);
// If "Blue Fire Arrows" is enabled, set up a collider on the red ice that responds to them
@@ -99,7 +99,8 @@ void BgJyaLift_DelayMove(BgJyaLift* this, GlobalContext* globalCtx) {
// The cutscene of the platform lowering will show the central room in an unloaded state if
// Link is not standing on the platform as it lowers. Therefore check for the Sunlight arrows
// enhancement and if it's enabled, check that Link is on the platform. Otherwise skip it.
if (!CVar_GetS32("gSunlightArrows", 0) || (GET_PLAYER(globalCtx)->actor.world.pos.x > -19.0f &&
if (!(CVar_GetS32("gSunlightArrows", 0) || Randomizer_GetSettingValue(RSK_SUNLIGHT_ARROWS)) ||
(GET_PLAYER(globalCtx)->actor.world.pos.x > -19.0f &&
GET_PLAYER(globalCtx)->actor.world.pos.x < 139.0f &&
GET_PLAYER(globalCtx)->actor.world.pos.z > -1172.0f &&
GET_PLAYER(globalCtx)->actor.world.pos.z < -1009.0f)) {
@@ -152,7 +152,7 @@ void BgSpot06Objects_Init(Actor* thisx, GlobalContext* globalCtx) {
if (LINK_IS_ADULT &&
((!gSaveContext.n64ddFlag && !(gSaveContext.eventChkInf[6] & 0x200)) ||
(gSaveContext.n64ddFlag && !gSaveContext.dungeonsDone[5]))) {
(gSaveContext.n64ddFlag && !Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE)))) {
if (gSaveContext.sceneSetupIndex < 4) {
this->lakeHyliaWaterLevel = -681.0f;
globalCtx->colCtx.colHeader->waterBoxes[LHWB_GERUDO_VALLEY_RIVER_LOWER].ySurface =
@@ -141,6 +141,9 @@ f32 DemoEffect_InterpolateCsFrames(GlobalContext* globalCtx, s32 csActionId) {
*/
void DemoEffect_InitJewel(GlobalContext* globalCtx, DemoEffect* this) {
this->initDrawFunc = DemoEffect_DrawJewel;
if (gSaveContext.n64ddFlag && globalCtx->sceneNum == SCENE_BDAN) {
this->initDrawFunc = DemoEffect_DrawGetItem;
}
if (!LINK_IS_ADULT) {
this->initUpdateFunc = DemoEffect_UpdateJewelChild;
} else {
@@ -152,7 +155,7 @@ void DemoEffect_InitJewel(GlobalContext* globalCtx, DemoEffect* this) {
Actor_SetScale(&this->actor, 0.10f);
}
this->csActionId = 1;
this->actor.shape.rot.x = 16384;
this->actor.shape.rot.x = (gSaveContext.n64ddFlag && globalCtx->sceneNum == SCENE_BDAN) ? 0 : 16384;
DemoEffect_InitJewelColor(this);
this->jewel.alpha = 0;
this->jewelCsRotation.x = this->jewelCsRotation.y = this->jewelCsRotation.z = 0;
@@ -2083,6 +2086,14 @@ void DemoEffect_DrawGetItem(Actor* thisx, GlobalContext* globalCtx) {
this->getItem.isLoaded = 1;
return;
}
if (gSaveContext.n64ddFlag && globalCtx->sceneNum == SCENE_BDAN) {
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_BARINADE, RG_ZORA_SAPPHIRE);
this->getItem.drawId = getItemEntry.gid;
func_8002EBCC(thisx, globalCtx, 0);
func_8002ED80(thisx, globalCtx, 0);
GetItemEntry_Draw(globalCtx, getItemEntry);
return;
}
func_8002EBCC(thisx, globalCtx, 0);
func_8002ED80(thisx, globalCtx, 0);
GetItem_Draw(globalCtx, this->getItem.drawId);
@@ -64,39 +64,60 @@ static u8 sEnergyColors[] = {
/* Forest prim */ 255, 255, 170, /* env */ 0, 200, 0,
};
// Translates from the barrier's actor params to their corresponding randInf flags.
RandomizerInf trialParamToRandInf(u16 params) {
switch (params) {
case KEKKAI_LIGHT:
return RAND_INF_TRIALS_DONE_LIGHT_TRIAL;
case KEKKAI_FOREST:
return RAND_INF_TRIALS_DONE_FOREST_TRIAL;
case KEKKAI_FIRE:
return RAND_INF_TRIALS_DONE_FIRE_TRIAL;
case KEKKAI_WATER:
return RAND_INF_TRIALS_DONE_WATER_TRIAL;
case KEKKAI_SPIRIT:
return RAND_INF_TRIALS_DONE_SPIRIT_TRIAL;
case KEKKAI_SHADOW:
return RAND_INF_TRIALS_DONE_SHADOW_TRIAL;
}
}
s32 DemoKekkai_CheckEventFlag(s32 params) {
static s32 eventFlags[] = { 0xC3, 0xBC, 0xBF, 0xBE, 0xBD, 0xAD, 0xBB };
if ((params < KEKKAI_TOWER) || (params > KEKKAI_FOREST)) {
return true;
}
if (gSaveContext.n64ddFlag && params > KEKKAI_TOWER) {
return Flags_GetRandomizerInf(trialParamToRandInf(params));
}
return Flags_GetEventChkInf(eventFlags[params]);
}
u32 TrialsDoneCount() {
u8 trialCount = 0;
if (gSaveContext.trialsDone[0] == 1) {
if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_LIGHT_TRIAL)) {
trialCount++;
}
if (gSaveContext.trialsDone[1] == 1) {
if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_FOREST_TRIAL)) {
trialCount++;
}
if (gSaveContext.trialsDone[2] == 1) {
if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_FIRE_TRIAL)) {
trialCount++;
}
if (gSaveContext.trialsDone[3] == 1) {
if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_WATER_TRIAL)) {
trialCount++;
}
if (gSaveContext.trialsDone[4] == 1) {
if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_SPIRIT_TRIAL)) {
trialCount++;
}
if (gSaveContext.trialsDone[5] == 1) {
if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_SHADOW_TRIAL)) {
trialCount++;
}
@@ -128,8 +149,7 @@ void DemoKekkai_Init(Actor* thisx, GlobalContext* globalCtx) {
this->collider2.dim.yShift = 300;
if (gSaveContext.n64ddFlag) {
int trialsToComplete = Randomizer_GetSettingValue(RSK_TRIAL_COUNT);
if (trialsToComplete <= TrialsDoneCount()) {
if (TrialsDoneCount() == NUM_TRIALS) {
Actor_Kill(thisx);
return;
}
@@ -141,6 +161,10 @@ void DemoKekkai_Init(Actor* thisx, GlobalContext* globalCtx) {
case KEKKAI_SHADOW:
case KEKKAI_SPIRIT:
case KEKKAI_FOREST:
if (gSaveContext.n64ddFlag && Flags_GetRandomizerInf(trialParamToRandInf(thisx->params))) {
Actor_Kill(thisx);
return;
}
this->energyAlpha = 1.0f;
this->orbScale = 1.0f;
Actor_SetScale(thisx, 0.1f);
@@ -247,27 +271,10 @@ void DemoKekkai_TrialBarrierDispel(Actor* thisx, GlobalContext* globalCtx) {
DemoKekkai* this = (DemoKekkai*)thisx;
if (gSaveContext.n64ddFlag) {
switch (thisx->params) {
case KEKKAI_WATER:
gSaveContext.trialsDone[2] = 1;
break;
case KEKKAI_LIGHT:
gSaveContext.trialsDone[5] = 1;
break;
case KEKKAI_FIRE:
gSaveContext.trialsDone[1] = 1;
break;
case KEKKAI_SHADOW:
gSaveContext.trialsDone[3] = 1;
break;
case KEKKAI_SPIRIT:
gSaveContext.trialsDone[4] = 1;
break;
case KEKKAI_FOREST:
gSaveContext.trialsDone[0] = 1;
break;
}
Flags_SetEventChkInf(eventFlags[thisx->params]);
Flags_SetRandomizerInf(trialParamToRandInf(thisx->params));
// May or may not be needed. Not sure if needed for anything
// that randoInf isn't already covering. Leaving it for safety.
Flags_SetEventChkInf(eventFlags[thisx->params]);
}
if (globalCtx->csCtx.frames == csFrames[this->actor.params]) {
@@ -462,7 +462,7 @@ s32 DoorWarp1_PlayerInRange(DoorWarp1* this, GlobalContext* globalCtx) {
}
void GivePlayerRandoReward(DoorWarp1* this, Player* player, GlobalContext* globalCtx, u8 ruto, u8 adult) {
GetItemEntry getItemEntry = Randomizer_GetRandomizedItem(GI_NONE, this->actor.id, this->actor.params, globalCtx->sceneNum);
GetItemEntry getItemEntry = Randomizer_GetItemFromActor(this->actor.id, globalCtx->sceneNum, this->actor.params, GI_NONE);
if (this->actor.parent != NULL && this->actor.parent->id == GET_PLAYER(globalCtx)->actor.id &&
!Flags_GetTreasure(globalCtx, 0x1F)) {
@@ -546,7 +546,7 @@ void DoorWarp1_ChildWarpOut(DoorWarp1* this, GlobalContext* globalCtx) {
if (globalCtx->sceneNum == SCENE_DDAN_BOSS) {
if (!Flags_GetEventChkInf(0x25)) {
Flags_SetEventChkInf(0x25);
gSaveContext.dungeonsDone[0] = 1;
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN);
if (gSaveContext.n64ddFlag) {
globalCtx->nextEntranceIndex = 0x47A;
gSaveContext.nextCutsceneIndex = 0;
@@ -563,7 +563,7 @@ void DoorWarp1_ChildWarpOut(DoorWarp1* this, GlobalContext* globalCtx) {
if (!Flags_GetEventChkInf(7) || gSaveContext.n64ddFlag) {
Flags_SetEventChkInf(7);
Flags_SetEventChkInf(9);
gSaveContext.dungeonsDone[1] = 1;
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE);
if (gSaveContext.n64ddFlag) {
globalCtx->nextEntranceIndex = 0x0457;
gSaveContext.nextCutsceneIndex = 0;
@@ -671,7 +671,7 @@ void DoorWarp1_RutoWarpOut(DoorWarp1* this, GlobalContext* globalCtx) {
if (this->warpTimer > sWarpTimerTarget && gSaveContext.nextCutsceneIndex == 0xFFEF) {
gSaveContext.eventChkInf[3] |= 0x80;
gSaveContext.dungeonsDone[2] = 1;
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY);
if (gSaveContext.n64ddFlag) {
globalCtx->nextEntranceIndex = 0x10E;
@@ -785,7 +785,7 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, GlobalContext* globalCtx) {
if (globalCtx->sceneNum == SCENE_MORIBOSSROOM) {
if (!(gSaveContext.eventChkInf[4] & 0x100)) {
gSaveContext.eventChkInf[4] |= 0x100;
gSaveContext.dungeonsDone[3] = 1;
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_FOREST_TEMPLE);
if (gSaveContext.n64ddFlag) {
globalCtx->nextEntranceIndex = 0x608;
@@ -807,7 +807,7 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, GlobalContext* globalCtx) {
} else if (globalCtx->sceneNum == SCENE_FIRE_BS) {
if (!(gSaveContext.eventChkInf[4] & 0x200)) {
gSaveContext.eventChkInf[4] |= 0x200;
gSaveContext.dungeonsDone[4] = 1;
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE);
if (gSaveContext.n64ddFlag) {
globalCtx->nextEntranceIndex = 0x564;
@@ -828,7 +828,7 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, GlobalContext* globalCtx) {
} else if (globalCtx->sceneNum == SCENE_MIZUSIN_BS) {
if (!(gSaveContext.eventChkInf[4] & 0x400)) {
gSaveContext.eventChkInf[4] |= 0x400;
gSaveContext.dungeonsDone[5] = 1;
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE);
if (gSaveContext.n64ddFlag) {
globalCtx->nextEntranceIndex = 0x60C;
@@ -849,7 +849,7 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, GlobalContext* globalCtx) {
}
} else if (globalCtx->sceneNum == SCENE_JYASINBOSS) {
if (!CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) || gSaveContext.n64ddFlag) {
gSaveContext.dungeonsDone[6] = 1;
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE);
if (gSaveContext.n64ddFlag) {
globalCtx->nextEntranceIndex = 0x610;
@@ -870,7 +870,7 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, GlobalContext* globalCtx) {
}
} else if (globalCtx->sceneNum == SCENE_HAKADAN_BS) {
if (!CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) || gSaveContext.n64ddFlag) {
gSaveContext.dungeonsDone[7] = 1;
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE);
if (gSaveContext.n64ddFlag) {
globalCtx->nextEntranceIndex = 0x580;
@@ -143,13 +143,15 @@ void EnBomBowMan_BlinkAwake(EnBomBowlMan* this, GlobalContext* globalCtx) {
}
}
// Check for Bomb Bag if Rando is enabled
// RANDOTODO: Check for bombchu pack instead of bomb bag if bombchus are in logic
// In randomizer, only check for bomb bag when bombchus aren't in logic
// and only check for bombchus when bombchus are in logic
if (gSaveContext.n64ddFlag) {
if (INV_CONTENT(ITEM_BOMB) != ITEM_NONE) {
this->actor.textId = 0xBF;
} else {
u8 bombchusInLogic = Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC);
if ((!bombchusInLogic && INV_CONTENT(ITEM_BOMB) == ITEM_NONE) ||
(bombchusInLogic && INV_CONTENT(ITEM_BOMBCHU) == ITEM_NONE)) {
this->actor.textId = 0x7058;
} else {
this->actor.textId = 0xBF;
}
}
}
@@ -177,11 +179,17 @@ void EnBomBowMan_CheckBeatenDC(EnBomBowlMan* this, GlobalContext* globalCtx) {
this->eyeMode = CHU_GIRL_EYES_AWAKE;
this->blinkTimer = (s16)Rand_ZeroFloat(60.0f) + 20;
// Check for beaten Dodongo's Cavern if not rando'd
// check for bomb bag if rando'd
if ((!gSaveContext.n64ddFlag &&
!((gSaveContext.eventChkInf[2] & 0x20) || BREG(2))) ||
(gSaveContext.n64ddFlag && (INV_CONTENT(ITEM_BOMB) == ITEM_NONE))) {
bool bombchuBowlingClosed;
if (gSaveContext.n64ddFlag) {
// when rando'd, check if we have bombchus if chus are in logic
// and check if we have a bomb bag if chus aren't in logic
u8 explosive = Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC) ? ITEM_BOMBCHU : ITEM_BOMB;
bombchuBowlingClosed = (INV_CONTENT(explosive) == ITEM_NONE);
} else {
// if not rando'd, check if we have beaten Dodongo's Cavern
bombchuBowlingClosed = !((gSaveContext.eventChkInf[2] & 0x20) || BREG(2));
}
if (bombchuBowlingClosed) {
this->actionFunc = EnBomBowMan_WaitNotBeatenDC;
} else {
this->actor.textId = 0x18;
@@ -446,7 +446,7 @@ void EnBox_WaitOpen(EnBox* this, GlobalContext* globalCtx) {
func_8002DBD0(&this->dyna.actor, &sp4C, &player->actor.world.pos);
if (sp4C.z > -50.0f && sp4C.z < 0.0f && fabsf(sp4C.y) < 10.0f && fabsf(sp4C.x) < 20.0f &&
Player_IsFacingActor(&this->dyna.actor, 0x3000, globalCtx)) {
sItem = Randomizer_GetRandomizedItem(this->dyna.actor.params >> 5 & 0x7F, this->dyna.actor.id, this->dyna.actor.params, globalCtx->sceneNum);
sItem = Randomizer_GetItemFromActor(this->dyna.actor.id, globalCtx->sceneNum, this->dyna.actor.params, this->dyna.actor.params >> 5 & 0x7F);
GetItemEntry blueRupee = ItemTable_RetrieveEntry(MOD_NONE, GI_RUPEE_BLUE);
// RANDOTODO treasure chest game rando
@@ -483,6 +483,7 @@ void EnBox_WaitOpen(EnBox* this, GlobalContext* globalCtx) {
// when approaching.
if (gSaveContext.n64ddFlag) {
sItem.getItemId = 0 - sItem.getItemId;
sItem.getItemFrom = ITEM_FROM_CHEST;
GiveItemEntryFromActorWithFixedRange(&this->dyna.actor, globalCtx, sItem);
} else {
func_8002F554(&this->dyna.actor, globalCtx, -(this->dyna.actor.params >> 5 & 0x7F));
@@ -18,6 +18,8 @@ void func_809E0070(Actor* thisx, GlobalContext* globalCtx);
void func_809DF494(EnCow* this, GlobalContext* globalCtx);
void func_809DF6BC(EnCow* this, GlobalContext* globalCtx);
CowInfo EnCow_GetInfo(EnCow* this, GlobalContext* globalCtx);
void EnCow_MoveForRandomizer(EnCow* this, GlobalContext* globalCtx);
void func_809DF778(EnCow* this, GlobalContext* globalCtx);
void func_809DF7D8(EnCow* this, GlobalContext* globalCtx);
void func_809DF870(EnCow* this, GlobalContext* globalCtx);
@@ -106,6 +108,10 @@ void EnCow_Init(Actor* thisx, GlobalContext* globalCtx) {
EnCow* this = (EnCow*)thisx;
s32 pad;
if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_COWS)) {
EnCow_MoveForRandomizer(thisx, globalCtx);
}
ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 72.0f);
switch (this->actor.params) {
case 0:
@@ -209,6 +215,85 @@ void func_809DF730(EnCow* this, GlobalContext* globalCtx) {
}
}
CowInfo EnCow_GetInfo(EnCow* this, GlobalContext* globalCtx) {
struct CowInfo cowInfo;
cowInfo.randomizerInf = -1;
cowInfo.randomizerCheck = RC_UNKNOWN_CHECK;
switch (globalCtx->sceneNum) {
case SCENE_SOUKO: // Lon Lon Tower
if (this->actor.world.pos.x == -229 && this->actor.world.pos.z == 157) {
cowInfo.randomizerInf = RAND_INF_COWS_MILKED_LLR_TOWER_LEFT_COW;
cowInfo.randomizerCheck = RC_LLR_TOWER_LEFT_COW;
} else if (this->actor.world.pos.x == -142 && this->actor.world.pos.z == -140) {
cowInfo.randomizerInf = RAND_INF_COWS_MILKED_LLR_TOWER_RIGHT_COW;
cowInfo.randomizerCheck = RC_LLR_TOWER_RIGHT_COW;
}
break;
case SCENE_MALON_STABLE:
if (this->actor.world.pos.x == 116 && this->actor.world.pos.z == -254) {
cowInfo.randomizerInf = RAND_INF_COWS_MILKED_LLR_STABLES_RIGHT_COW;
cowInfo.randomizerCheck = RC_LLR_STABLES_RIGHT_COW;
} else if (this->actor.world.pos.x == -122 && this->actor.world.pos.z == -254) {
cowInfo.randomizerInf = RAND_INF_COWS_MILKED_LLR_STABLES_LEFT_COW;
cowInfo.randomizerCheck = RC_LLR_STABLES_LEFT_COW;
}
break;
case SCENE_KAKUSIANA: // Grotto
if (this->actor.world.pos.x == 2444 && this->actor.world.pos.z == -471) {
cowInfo.randomizerInf = RAND_INF_COWS_MILKED_DMT_COW_GROTTO_COW;
cowInfo.randomizerCheck = RC_DMT_COW_GROTTO_COW;
} else if (this->actor.world.pos.x == 3485 && this->actor.world.pos.z == -291) {
cowInfo.randomizerInf = RAND_INF_COWS_MILKED_HF_COW_GROTTO_COW;
cowInfo.randomizerCheck = RC_HF_COW_GROTTO_COW;
}
break;
case SCENE_LINK_HOME:
cowInfo.randomizerInf = RAND_INF_COWS_MILKED_LINKS_HOUSE_COW;
cowInfo.randomizerCheck = RC_KF_LINKS_HOUSE_COW;
break;
case SCENE_LABO: // Impa's house
cowInfo.randomizerInf = RAND_INF_COWS_MILKED_KAK_IMPAS_HOUSE_COW;
cowInfo.randomizerCheck = RC_KAK_IMPAS_HOUSE_COW;
break;
case SCENE_SPOT09: // Gerudo Valley
cowInfo.randomizerInf = RAND_INF_COWS_MILKED_GV_COW;
cowInfo.randomizerCheck = RC_GV_COW;
break;
case SCENE_BDAN: // Jabu's Belly
cowInfo.randomizerInf = RAND_INF_COWS_MILKED_JABU_JABUS_BELLY_MQ_COW;
cowInfo.randomizerCheck = RC_JABU_JABUS_BELLY_MQ_COW;
break;
}
return cowInfo;
}
void EnCow_MoveForRandomizer(EnCow* this, GlobalContext* globalCtx) {
// Only move the cow body (the tail will be moved with the body)
if (this->actor.params != 0) {
return;
}
// Move left cow in lon lon tower
if (globalCtx->sceneNum == SCENE_SOUKO && this->actor.world.pos.x == -108 && this->actor.world.pos.z == -65) {
this->actor.world.pos.x = -229.0f;
this->actor.world.pos.z = 157.0f;
this->actor.shape.rot.y = 15783.0f;
// Move right cow in lon lon stable
} else if (globalCtx->sceneNum == SCENE_MALON_STABLE && this->actor.world.pos.x == -3 && this->actor.world.pos.z == -254) {
this->actor.world.pos.x += 119.0f;
}
}
void EnCow_SetCowMilked(EnCow* this, GlobalContext* globalCtx) {
CowInfo cowInfo = EnCow_GetInfo(this, globalCtx);
Player* player = GET_PLAYER(globalCtx);
player->pendingFlag.flagID = cowInfo.randomizerInf;
player->pendingFlag.flagType = FLAG_RANDOMIZER_INF;
}
void func_809DF778(EnCow* this, GlobalContext* globalCtx) {
if (Actor_HasParent(&this->actor, globalCtx)) {
this->actor.parent = NULL;
@@ -250,6 +335,23 @@ void func_809DF8FC(EnCow* this, GlobalContext* globalCtx) {
func_809DF494(this, globalCtx);
}
bool EnCow_HasBeenMilked(EnCow* this, GlobalContext* globalCtx) {
CowInfo cowInfo = EnCow_GetInfo(this, globalCtx);
return Flags_GetRandomizerInf(cowInfo.randomizerInf);
}
void EnCow_GivePlayerRandomizedItem(EnCow* this, GlobalContext* globalCtx) {
if (!EnCow_HasBeenMilked(this, globalCtx)) {
CowInfo cowInfo = EnCow_GetInfo(this, globalCtx);
GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(cowInfo.randomizerCheck, GI_MILK);
GiveItemEntryFromActor(&this->actor, globalCtx, itemEntry, 10000.0f, 100.0f);
} else {
// once we've gotten the rando reward from the cow,
// return them to the their default action function
this->actionFunc = func_809DF96C;
}
}
void func_809DF96C(EnCow* this, GlobalContext* globalCtx) {
if ((globalCtx->msgCtx.ocarinaMode == OCARINA_MODE_00) || (globalCtx->msgCtx.ocarinaMode == OCARINA_MODE_04)) {
if (DREG(53) != 0) {
@@ -260,6 +362,19 @@ void func_809DF96C(EnCow* this, GlobalContext* globalCtx) {
if ((this->actor.xzDistToPlayer < 150.0f) &&
(ABS((s16)(this->actor.yawTowardsPlayer - this->actor.shape.rot.y)) < 0x61A8)) {
DREG(53) = 0;
// when randomized with cowsanity, if we haven't gotten the
// reward from this cow yet, give that, otherwise use the
// vanilla cow behavior
if (gSaveContext.n64ddFlag &&
Randomizer_GetSettingValue(RSK_SHUFFLE_COWS) &&
!EnCow_HasBeenMilked(this, globalCtx)) {
EnCow_SetCowMilked(this, globalCtx);
// setting the ocarina mode here prevents intermittent issues
// with the item get not triggering until walking away
globalCtx->msgCtx.ocarinaMode = OCARINA_MODE_00;
this->actionFunc = EnCow_GivePlayerRandomizedItem;
return;
}
this->actionFunc = func_809DF8FC;
this->actor.flags |= ACTOR_FLAG_16;
func_8002F2CC(&this->actor, globalCtx, 170.0f);
@@ -21,4 +21,9 @@ typedef struct EnCow {
/* 0x027C */ EnCowActionFunc actionFunc;
} EnCow; // size = 0x0280
typedef struct CowInfo {
RandomizerInf randomizerInf;
RandomizerCheck randomizerCheck;
} CowInfo;
#endif
+54 -23
View File
@@ -15,6 +15,7 @@ void EnDns_Destroy(Actor* thisx, GlobalContext* globalCtx);
void EnDns_Update(Actor* thisx, GlobalContext* globalCtx);
void EnDns_Draw(Actor* thisx, GlobalContext* globalCtx);
u32 EnDns_RandomizerPurchaseableCheck(EnDns* this);
u32 func_809EF5A4(EnDns* this);
u32 func_809EF658(EnDns* this);
u32 func_809EF70C(EnDns* this);
@@ -24,6 +25,7 @@ u32 func_809EF854(EnDns* this);
u32 func_809EF8F4(EnDns* this);
u32 func_809EF9A4(EnDns* this);
void EnDns_RandomizerPurchase(EnDns* this);
void func_809EF9F8(EnDns* this);
void func_809EFA28(EnDns* this);
void func_809EFA58(EnDns* this);
@@ -155,7 +157,6 @@ void EnDns_Init(Actor* thisx, GlobalContext* globalCtx) {
Collider_InitCylinder(globalCtx, &this->collider);
Collider_SetCylinderType1(globalCtx, &this->collider, &this->actor, &sCylinderInit);
ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 35.0f);
this->actor.textId = D_809F040C[this->actor.params];
Actor_SetScale(&this->actor, 0.01f);
this->actor.colChkInfo.mass = MASS_IMMOVABLE;
this->maintainCollider = 1;
@@ -164,7 +165,27 @@ void EnDns_Init(Actor* thisx, GlobalContext* globalCtx) {
this->actor.speedXZ = 0.0f;
this->actor.velocity.y = 0.0f;
this->actor.gravity = -1.0f;
this->actor.textId = D_809F040C[this->actor.params];
this->dnsItemEntry = sItemEntries[this->actor.params];
if (gSaveContext.n64ddFlag) {
// Ugly, but the best way we can identify which grotto we are in, same method 3DRando uses, but we'll need to account for entrance rando
s16 respawnData = gSaveContext.respawn[RESPAWN_MODE_RETURN].data & ((1 << 8) - 1);
this->scrubIdentity = Randomizer_IdentifyScrub(globalCtx->sceneNum, this->actor.params, respawnData);
if (Randomizer_GetSettingValue(RSK_SHUFFLE_SCRUBS) == 1 || Randomizer_GetSettingValue(RSK_SHUFFLE_SCRUBS) == 3 && this->scrubIdentity.itemPrice != -1) {
this->dnsItemEntry->itemPrice = this->scrubIdentity.itemPrice;
}
if (this->scrubIdentity.isShuffled) {
this->dnsItemEntry->getItemId = this->scrubIdentity.getItemId;
this->dnsItemEntry->purchaseableCheck = EnDns_RandomizerPurchaseableCheck;
this->dnsItemEntry->setRupeesAndFlags = EnDns_RandomizerPurchase;
this->dnsItemEntry->itemAmount = 1;
// Currently the textID is simply identified by the item price since that is the only thing
// unique to it, later on this will change to identifying by scrubIdentity.randomizerInf
this->actor.textId = 0x9000 + this->dnsItemEntry->itemPrice;
}
}
this->actionFunc = EnDns_SetupWait;
}
@@ -185,6 +206,13 @@ void EnDns_ChangeAnim(EnDns* this, u8 index) {
/* Item give checking functions */
u32 EnDns_RandomizerPurchaseableCheck(EnDns* this) {
if (gSaveContext.rupees < this->dnsItemEntry->itemPrice || Flags_GetRandomizerInf(this->scrubIdentity.randomizerInf)) {
return 0;
}
return 4;
}
u32 func_809EF5A4(EnDns* this) {
if ((CUR_CAPACITY(UPG_NUTS) != 0) && (AMMO(ITEM_NUT) >= CUR_CAPACITY(UPG_NUTS))) {
return 1;
@@ -281,6 +309,10 @@ u32 func_809EF9A4(EnDns* this) {
}
/* Paying and flagging functions */
void EnDns_RandomizerPurchase(EnDns* this) {
Rupees_ChangeBy(-this->dnsItemEntry->itemPrice);
Flags_SetRandomizerInf(this->scrubIdentity.randomizerInf);
}
void func_809EF9F8(EnDns* this) {
Rupees_ChangeBy(-this->dnsItemEntry->itemPrice);
@@ -369,31 +401,25 @@ void EnDns_Talk(EnDns* this, GlobalContext* globalCtx) {
}
void func_809EFDD0(EnDns* this, GlobalContext* globalCtx) {
if (this->actor.params == 0x9) {
if (gSaveContext.n64ddFlag) {
GetItemEntry getItemEntry = Randomizer_GetRandomizedItem(GI_STICK_UPGRADE_30, this->actor.id, this->actor.params, globalCtx->sceneNum);
GiveItemEntryFromActor(&this->actor, globalCtx, getItemEntry, 130.0f, 100.0f);
} else if (CUR_UPG_VALUE(UPG_STICKS) < 2) {
func_8002F434(&this->actor, globalCtx, GI_STICK_UPGRADE_20, 130.0f, 100.0f);
if (!gSaveContext.n64ddFlag || !this->scrubIdentity.isShuffled) {
if (this->actor.params == 0x9) {
if (CUR_UPG_VALUE(UPG_STICKS) < 2) {
func_8002F434(&this->actor, globalCtx, GI_STICK_UPGRADE_20, 130.0f, 100.0f);
} else {
func_8002F434(&this->actor, globalCtx, GI_STICK_UPGRADE_30, 130.0f, 100.0f);
}
} else if (this->actor.params == 0xA) {
if (CUR_UPG_VALUE(UPG_NUTS) < 2) {
func_8002F434(&this->actor, globalCtx, GI_NUT_UPGRADE_30, 130.0f, 100.0f);
} else {
func_8002F434(&this->actor, globalCtx, GI_NUT_UPGRADE_40, 130.0f, 100.0f);
}
} else {
func_8002F434(&this->actor, globalCtx, GI_STICK_UPGRADE_30, 130.0f, 100.0f);
}
} else if (this->actor.params == 0xA) {
if (gSaveContext.n64ddFlag) {
GetItemEntry getItemEntry = Randomizer_GetRandomizedItem(GI_NUT_UPGRADE_40, this->actor.id, this->actor.params, globalCtx->sceneNum);
GiveItemEntryFromActor(&this->actor, globalCtx, getItemEntry, 130.0f, 100.0f);
} else if (CUR_UPG_VALUE(UPG_NUTS) < 2) {
func_8002F434(&this->actor, globalCtx, GI_NUT_UPGRADE_30, 130.0f, 100.0f);
} else {
func_8002F434(&this->actor, globalCtx, GI_NUT_UPGRADE_40, 130.0f, 100.0f);
func_8002F434(&this->actor, globalCtx, this->dnsItemEntry->getItemId, 130.0f, 100.0f);
}
} else {
if (!gSaveContext.n64ddFlag) {
func_8002F434(&this->actor, globalCtx, this->dnsItemEntry->getItemId, 130.0f, 100.0f);
} else {
GetItemEntry getItemEntry = Randomizer_GetRandomizedItem(this->dnsItemEntry->getItemId, this->actor.id, this->actor.params, globalCtx->sceneNum);
GiveItemEntryFromActor(&this->actor, globalCtx, getItemEntry, 130.0f, 100.0f);
}
GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(this->scrubIdentity.randomizerCheck, this->scrubIdentity.getItemId);
GiveItemEntryFromActor(&this->actor, globalCtx, itemEntry, 130.0f, 100.0f);
}
}
@@ -489,6 +515,11 @@ void EnDns_Update(Actor* thisx, GlobalContext* globalCtx) {
this->dustTimer++;
this->actor.textId = D_809F040C[this->actor.params];
if (gSaveContext.n64ddFlag && this->scrubIdentity.isShuffled) {
// Currently the textID is simply identified by the item price since that is the only thing
// unique to it, later on this will change to identifying by scrubIdentity.randomizerInf
this->actor.textId = 0x9000 + this->dnsItemEntry->itemPrice;
}
Actor_SetFocus(&this->actor, 60.0f);
Actor_SetScale(&this->actor, 0.01f);
SkelAnime_Update(&this->skelAnime);
@@ -32,6 +32,7 @@ typedef struct EnDns {
/* 0x02BD */ u8 dropCollectible;
/* 0x02C0 */ DnsItemEntry* dnsItemEntry;
/* 0x02C4 */ f32 yInitPos;
/* */ ScrubIdentity scrubIdentity;
} EnDns; // size = 0x02C8
#endif
+20 -5
View File
@@ -6,6 +6,7 @@
#include "z_en_ds.h"
#include "objects/object_ds/object_ds.h"
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
#define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3)
@@ -91,7 +92,14 @@ void EnDs_GiveOddPotion(EnDs* this, GlobalContext* globalCtx) {
this->actionFunc = EnDs_DisplayOddPotionText;
gSaveContext.timer2State = 0;
} else {
func_8002F434(&this->actor, globalCtx, GI_ODD_POTION, 10000.0f, 50.0f);
u32 itemId = GI_ODD_POTION;
if (gSaveContext.n64ddFlag) {
GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_TRADE_ODD_MUSHROOM, GI_ODD_POTION);
GiveItemEntryFromActor(&this->actor, globalCtx, itemEntry, 10000.0f, 50.0f);
Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_ODD_MUSHROOM);
return;
}
func_8002F434(&this->actor, globalCtx, itemId, 10000.0f, 50.0f);
}
}
@@ -99,7 +107,14 @@ void EnDs_TalkAfterBrewOddPotion(EnDs* this, GlobalContext* globalCtx) {
if ((Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(globalCtx)) {
Message_CloseTextbox(globalCtx);
this->actionFunc = EnDs_GiveOddPotion;
func_8002F434(&this->actor, globalCtx, GI_ODD_POTION, 10000.0f, 50.0f);
u32 itemId = GI_ODD_POTION;
if (gSaveContext.n64ddFlag) {
GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_TRADE_ODD_MUSHROOM, GI_ODD_POTION);
GiveItemEntryFromActor(&this->actor, globalCtx, itemEntry, 10000.0f, 50.0f);
Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_ODD_MUSHROOM);
return;
}
func_8002F434(&this->actor, globalCtx, itemId, 10000.0f, 50.0f);
}
}
@@ -120,7 +135,7 @@ void EnDs_BrewOddPotion2(EnDs* this, GlobalContext* globalCtx) {
this->brewTimer -= 1;
} else {
this->actionFunc = EnDs_BrewOddPotion3;
this->brewTimer = 60;
this->brewTimer = gSaveContext.n64ddFlag ? 0 : 60;
Flags_UnsetSwitch(globalCtx, 0x3F);
}
}
@@ -130,7 +145,7 @@ void EnDs_BrewOddPotion1(EnDs* this, GlobalContext* globalCtx) {
this->brewTimer -= 1;
} else {
this->actionFunc = EnDs_BrewOddPotion2;
this->brewTimer = 20;
this->brewTimer = gSaveContext.n64ddFlag ? 0 : 20;
}
Math_StepToF(&this->unk_1E4, 1.0f, 0.01f);
@@ -144,7 +159,7 @@ void EnDs_OfferOddPotion(EnDs* this, GlobalContext* globalCtx) {
switch (globalCtx->msgCtx.choiceIndex) {
case 0: // yes
this->actionFunc = EnDs_BrewOddPotion1;
this->brewTimer = 60;
this->brewTimer = gSaveContext.n64ddFlag ? 0 : 60;
Flags_SetSwitch(globalCtx, 0x3F);
globalCtx->msgCtx.msgMode = MSGMODE_PAUSED;
player->exchangeItemId = EXCH_ITEM_NONE;
@@ -521,9 +521,14 @@ void EnExItem_DrawItems(EnExItem* this, GlobalContext* globalCtx) {
case EXITEM_BOMBCHUS_COUNTER:
randoGetItem = Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS, GI_BOMBCHUS_10);
break;
case EXITEM_BULLET_BAG:
randoGetItem = Randomizer_GetItemFromKnownCheck(RC_LW_TARGET_IN_WOODS, GI_BULLET_BAG_50);
break;
}
EnItem00_CustomItemsParticles(&this->actor, globalCtx, randoGetItem);
GetItemEntry_Draw(globalCtx, randoGetItem);
return;
}
GetItem_Draw(globalCtx, this->giDrawId);
@@ -536,7 +541,7 @@ void EnExItem_DrawHeartPiece(EnExItem* this, GlobalContext* globalCtx) {
GetItemEntry randoGetItem =
Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, GI_HEART_PIECE);
EnItem00_CustomItemsParticles(&this->actor, globalCtx, randoGetItem);
GetItem_Draw(globalCtx, randoGetItem.gid);
GetItemEntry_Draw(globalCtx, randoGetItem);
} else {
GetItem_Draw(globalCtx, GID_HEART_PIECE);
}
+25 -2
View File
@@ -43,6 +43,7 @@ void EnFr_OcarinaMistake(EnFr* this, GlobalContext* globalCtx);
void EnFr_SetupReward(EnFr* this, GlobalContext* globalCtx, u8 unkCondition);
void EnFr_PrintTextBox(EnFr* this, GlobalContext* globalCtx);
void EnFr_TalkBeforeReward(EnFr* this, GlobalContext* globalCtx);
RandomizerCheck EnFr_RandomizerCheckFromSongIndex(u16 songIndex);
void EnFr_SetReward(EnFr* this, GlobalContext* globalCtx);
// Deactivate
@@ -922,6 +923,23 @@ void EnFr_TalkBeforeReward(EnFr* this, GlobalContext* globalCtx) {
}
}
RandomizerCheck EnFr_RandomizerCheckFromSongIndex(u16 songIndex) {
switch (songIndex) {
case FROG_ZL:
return RC_ZR_FROGS_ZELDAS_LULLABY;
case FROG_EPONA:
return RC_ZR_FROGS_EPONAS_SONG;
case FROG_SARIA:
return RC_ZR_FROGS_SARIAS_SONG;
case FROG_SUNS:
return RC_ZR_FROGS_SUNS_SONG;
case FROG_SOT:
return RC_ZR_FROGS_SONG_OF_TIME;
default:
return RC_UNKNOWN_CHECK;
}
}
void EnFr_SetReward(EnFr* this, GlobalContext* globalCtx) {
u16 songIndex;
@@ -933,7 +951,12 @@ void EnFr_SetReward(EnFr* this, GlobalContext* globalCtx) {
if ((songIndex >= FROG_ZL) && (songIndex <= FROG_SOT)) {
if (!(gSaveContext.eventChkInf[13] & sSongIndex[songIndex])) {
gSaveContext.eventChkInf[13] |= sSongIndex[songIndex];
this->reward = GI_RUPEE_PURPLE;
if (!gSaveContext.n64ddFlag) {
this->reward = GI_RUPEE_PURPLE;
} else {
this->getItemEntry = Randomizer_GetItemFromKnownCheck(EnFr_RandomizerCheckFromSongIndex(songIndex), GI_RUPEE_PURPLE);
this->reward = this->getItemEntry.getItemId;
}
} else {
this->reward = GI_RUPEE_BLUE;
}
@@ -1029,7 +1052,7 @@ void EnFr_GiveReward(EnFr* this, GlobalContext* globalCtx) {
}
void EnFr_SetIdle(EnFr* this, GlobalContext* globalCtx) {
if ((Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(globalCtx)) {
if ((Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(globalCtx) || (gSaveContext.n64ddFlag && this->reward == RG_ICE_TRAP)) {
this->actionFunc = EnFr_Idle;
}
}
+162 -13
View File
@@ -45,6 +45,7 @@ s32 EnGirlA_CanBuy_BlueFire(GlobalContext* globalCtx, EnGirlA* this);
s32 EnGirlA_CanBuy_Bugs(GlobalContext* globalCtx, EnGirlA* this);
s32 EnGirlA_CanBuy_Poe(GlobalContext* globalCtx, EnGirlA* this);
s32 EnGirlA_CanBuy_Fairy(GlobalContext* globalCtx, EnGirlA* this);
s32 EnGirlA_CanBuy_Randomizer(GlobalContext* globalCtx, EnGirlA* this);
void EnGirlA_ItemGive_DekuNuts(GlobalContext* globalCtx, EnGirlA* this);
void EnGirlA_ItemGive_Arrows(GlobalContext* globalCtx, EnGirlA* this);
@@ -62,10 +63,12 @@ void EnGirlA_ItemGive_WeirdEgg(GlobalContext* globalCtx, EnGirlA* this);
void EnGirlA_ItemGive_Unk19(GlobalContext* globalCtx, EnGirlA* this);
void EnGirlA_ItemGive_Unk20(GlobalContext* globalCtx, EnGirlA* this);
void EnGirlA_ItemGive_DekuSeeds(GlobalContext* globalCtx, EnGirlA* this);
void EnGirlA_ItemGive_Randomizer(GlobalContext* globalCtx, EnGirlA* this);
void EnGirlA_BuyEvent_ShieldDiscount(GlobalContext* globalCtx, EnGirlA* this);
void EnGirlA_BuyEvent_ObtainBombchuPack(GlobalContext* globalCtx, EnGirlA* this);
void EnGirlA_BuyEvent_GoronTunic(GlobalContext* globalCtx, EnGirlA* this);
void EnGirlA_BuyEvent_ZoraTunic(GlobalContext* globalCtx, EnGirlA* this);
void EnGirlA_BuyEvent_Randomizer(GlobalContext* globalCtx, EnGirlA* this);
const ActorInit En_GirlA_InitVars = {
ACTOR_EN_GIRLA,
@@ -130,7 +133,8 @@ static char* sShopItemDescriptions[] = {
"爆弾×30 ", // "Bomb x30"
"爆弾×5 ", // "Bomb x5"
"赤クスリ ", // "Red medicine"
"赤クスリ " // "Red medicine"
"赤クスリ ", // "Red medicine"
"Random Item " // "Random Item"
};
static s16 sMaskShopItems[8] = {
@@ -304,7 +308,10 @@ static ShopItemEntry shopItemEntries[] = {
EnGirlA_ItemGive_BottledItem, EnGirlA_BuyEvent_ShieldDiscount },
/* SI_RED_POTION_R50 */
{ OBJECT_GI_LIQUID, GID_POTION_RED, func_8002EBCC, 50, 1, 0x0065, 0x0063, GI_POTION_RED, EnGirlA_CanBuy_RedPotion,
EnGirlA_ItemGive_BottledItem, EnGirlA_BuyEvent_ShieldDiscount }
EnGirlA_ItemGive_BottledItem, EnGirlA_BuyEvent_ShieldDiscount },
/* SI_RANDOMIZED_ITEM */
{ OBJECT_INVALID, GID_MAXIMUM, NULL, 40, 1, 0x9100, 0x9100 + NUM_SHOP_ITEMS, GI_NONE, EnGirlA_CanBuy_Randomizer,
EnGirlA_ItemGive_Randomizer, EnGirlA_BuyEvent_Randomizer }
};
// Defines the Hylian Shield discount amount
@@ -314,7 +321,7 @@ void EnGirlA_SetupAction(EnGirlA* this, EnGirlAActionFunc func) {
this->actionFunc = func;
}
s32 EnGirlA_TryChangeShopItem(EnGirlA* this) {
s32 EnGirlA_TryChangeShopItem(EnGirlA* this, GlobalContext* globalCtx) {
switch (this->actor.params) {
case SI_MILK_BOTTLE:
if (gSaveContext.itemGetInf[0] & 0x4) {
@@ -370,7 +377,16 @@ s32 EnGirlA_TryChangeShopItem(EnGirlA* this) {
return true;
}
break;
case SI_RANDOMIZED_ITEM: {
ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(globalCtx->sceneNum, this->randoSlotIndex);
if (Flags_GetRandomizerInf(shopItemIdentity.randomizerInf)) {
this->actor.params = SI_SOLD_OUT;
return true;
}
break;
}
}
return false;
}
@@ -388,7 +404,25 @@ void EnGirlA_InitItem(EnGirlA* this, GlobalContext* globalCtx) {
return;
}
this->objBankIndex = Object_GetIndex(&globalCtx->objectCtx, shopItemEntries[params].objID);
if (!gSaveContext.n64ddFlag || !Randomizer_GetSettingValue(RSK_SHOPSANITY)) {
this->objBankIndex = Object_GetIndex(&globalCtx->objectCtx, shopItemEntries[params].objID);
} else {
s16 objectId = shopItemEntries[params].objID;
if (params == SI_RANDOMIZED_ITEM) {
ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(globalCtx->sceneNum, this->randoSlotIndex);
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheckWithoutObtainabilityCheck(shopItemIdentity.randomizerCheck, shopItemIdentity.ogItemId);
objectId = getItemEntry.objectId;
}
// Weird edge case here, sold out object reports as loaded for Kokiri shop but doesn't render so we force it to load here
if (Object_IsLoaded(&globalCtx->objectCtx, objectId) && (params != SI_SOLD_OUT && globalCtx->sceneNum == SCENE_KOKIRI_SHOP)) {
this->objBankIndex = Object_GetIndex(&globalCtx->objectCtx, objectId);
} else {
this->objBankIndex = Object_Spawn(&globalCtx->objectCtx, objectId);
}
}
if (this->objBankIndex < 0) {
Actor_Kill(&this->actor);
@@ -406,7 +440,7 @@ void EnGirlA_InitItem(EnGirlA* this, GlobalContext* globalCtx) {
void EnGirlA_Init(Actor* thisx, GlobalContext* globalCtx) {
EnGirlA* this = (EnGirlA*)thisx;
EnGirlA_TryChangeShopItem(this);
EnGirlA_TryChangeShopItem(this, globalCtx);
EnGirlA_InitItem(this, globalCtx);
osSyncPrintf("%s(%2d)初期設定\n", sShopItemDescriptions[this->actor.params], this->actor.params);
}
@@ -563,7 +597,7 @@ s32 EnGirlA_CanBuy_DekuShield(GlobalContext* globalCtx, EnGirlA* this) {
}
s32 EnGirlA_CanBuy_GoronTunic(GlobalContext* globalCtx, EnGirlA* this) {
if (LINK_AGE_IN_YEARS == YEARS_CHILD) {
if (LINK_AGE_IN_YEARS == YEARS_CHILD && (!gSaveContext.n64ddFlag || !Randomizer_GetSettingValue(RSK_SHOPSANITY))) {
return CANBUY_RESULT_CANT_GET_NOW;
}
if (gBitFlags[9] & gSaveContext.inventory.equipment) {
@@ -579,7 +613,7 @@ s32 EnGirlA_CanBuy_GoronTunic(GlobalContext* globalCtx, EnGirlA* this) {
}
s32 EnGirlA_CanBuy_ZoraTunic(GlobalContext* globalCtx, EnGirlA* this) {
if (LINK_AGE_IN_YEARS == YEARS_CHILD) {
if (LINK_AGE_IN_YEARS == YEARS_CHILD && (!gSaveContext.n64ddFlag || !Randomizer_GetSettingValue(RSK_SHOPSANITY))) {
return CANBUY_RESULT_CANT_GET_NOW;
}
if (gBitFlags[10] & gSaveContext.inventory.equipment) {
@@ -633,8 +667,16 @@ s32 EnGirlA_CanBuy_Unk20(GlobalContext* globalCtx, EnGirlA* this) {
}
s32 EnGirlA_CanBuy_Bombchus(GlobalContext* globalCtx, EnGirlA* this) {
// When in rando, don't allow buying bombchus when the player doesn't have a bomb bag
if (AMMO(ITEM_BOMBCHU) >= 50 || (gSaveContext.n64ddFlag && CUR_CAPACITY(UPG_BOMB_BAG) == 0)) {
// When in rando, don't allow buying bombchus when the player doesn't have required explosives
// If bombchus are in logic, the player needs to have bombchus; otherwise they need a bomb bag
if (gSaveContext.n64ddFlag) {
u8 bombchusInLogic = Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC);
if ((!bombchusInLogic && CUR_CAPACITY(UPG_BOMB_BAG) == 0) ||
(bombchusInLogic && INV_CONTENT(ITEM_BOMBCHU) == ITEM_NONE)) {
return CANBUY_RESULT_CANT_GET_NOW;
}
}
if (AMMO(ITEM_BOMBCHU) >= 50) {
return CANBUY_RESULT_CANT_GET_NOW;
}
if (gSaveContext.rupees < this->basePrice) {
@@ -715,6 +757,34 @@ s32 EnGirlA_CanBuy_Fairy(GlobalContext* globalCtx, EnGirlA* this) {
return CANBUY_RESULT_SUCCESS;
}
s32 EnGirlA_CanBuy_Randomizer(GlobalContext* globalCtx, EnGirlA* this) {
ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(globalCtx->sceneNum, this->randoSlotIndex);
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheckWithoutObtainabilityCheck(shopItemIdentity.randomizerCheck, shopItemIdentity.ogItemId);
ItemObtainability itemObtainability = Randomizer_GetItemObtainabilityFromRandomizerCheck(shopItemIdentity.randomizerCheck);
if (itemObtainability == CANT_OBTAIN_NEED_EMPTY_BOTTLE) {
return CANBUY_RESULT_NEED_BOTTLE;
}
if (itemObtainability == CANT_OBTAIN_NEED_UPGRADE) {
return CANBUY_RESULT_CANT_GET_NOW_5;
}
if (
Flags_GetRandomizerInf(shopItemIdentity.randomizerInf) ||
itemObtainability == CANT_OBTAIN_ALREADY_HAVE ||
itemObtainability == CANT_OBTAIN_MISC
) {
return CANBUY_RESULT_CANT_GET_NOW;
}
if (gSaveContext.rupees < shopItemIdentity.itemPrice) {
return CANBUY_RESULT_NEED_RUPEES;
}
return CANBUY_RESULT_SUCCESS_FANFARE;
}
void EnGirlA_ItemGive_Arrows(GlobalContext* globalCtx, EnGirlA* this) {
Inventory_ChangeAmmo(ITEM_BOW, this->itemCount);
Rupees_ChangeBy(-this->basePrice);
@@ -842,6 +912,27 @@ void EnGirlA_ItemGive_BottledItem(GlobalContext* globalCtx, EnGirlA* this) {
Rupees_ChangeBy(-this->basePrice);
}
// This is called when EnGirlA_CanBuy_Randomizer returns CANBUY_RESULT_SUCCESS
// The giving of the item is handled here, and no fanfare is played
void EnGirlA_ItemGive_Randomizer(GlobalContext* globalCtx, EnGirlA* this) {
Player* player = GET_PLAYER(globalCtx);
ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(globalCtx->sceneNum, this->randoSlotIndex);
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheckWithoutObtainabilityCheck(shopItemIdentity.randomizerCheck, shopItemIdentity.ogItemId);
if (getItemEntry.modIndex == MOD_NONE) {
// RANDOTOD: Move this into Item_Give() or some other more central location
if (getItemEntry.getItemId == GI_SWORD_BGS) {
gSaveContext.bgsFlag = true;
}
Item_Give(globalCtx, getItemEntry.itemId);
} else if (getItemEntry.modIndex == MOD_RANDOMIZER && getItemEntry.getItemId != RG_ICE_TRAP) {
Randomizer_Item_Give(globalCtx, getItemEntry);
}
Flags_SetRandomizerInf(shopItemIdentity.randomizerInf);
Rupees_ChangeBy(-this->basePrice);
}
void EnGirlA_BuyEvent_ShieldDiscount(GlobalContext* globalCtx, EnGirlA* this) {
if (this->actor.params == SI_HYLIAN_SHIELD) {
if (gSaveContext.infTable[7] & 0x40) {
@@ -861,6 +952,14 @@ void EnGirlA_BuyEvent_ZoraTunic(GlobalContext* globalCtx, EnGirlA* this) {
}
void EnGirlA_BuyEvent_ObtainBombchuPack(GlobalContext* globalCtx, EnGirlA* this) {
Rupees_ChangeBy(-this->basePrice);
// Normally, buying a bombchu pack sets a flag indicating the pack is now sold out
// If they're in logic for rando, skip setting that flag so they can be purchased repeatedly
if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC)) {
return;
}
switch (this->actor.params) {
case SI_BOMBCHU_10_2:
gSaveContext.itemGetInf[0] |= 0x40;
@@ -887,6 +986,13 @@ void EnGirlA_BuyEvent_ObtainBombchuPack(GlobalContext* globalCtx, EnGirlA* this)
gSaveContext.itemGetInf[0] |= 0x20;
break;
}
}
// This is called when EnGirlA_CanBuy_Randomizer returns CANBUY_RESULT_SUCCESS_FANFARE
// The giving of the item is handled in ossan.c, and a fanfare is played
void EnGirlA_BuyEvent_Randomizer(GlobalContext* globalCtx, EnGirlA* this) {
ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(globalCtx->sceneNum, this->randoSlotIndex);
Flags_SetRandomizerInf(shopItemIdentity.randomizerInf);
Rupees_ChangeBy(-this->basePrice);
}
@@ -937,6 +1043,12 @@ void EnGirlA_SetItemDescription(GlobalContext* globalCtx, EnGirlA* this) {
} else {
this->actor.textId = tmp->itemDescTextId;
}
if (params == SI_RANDOMIZED_ITEM) {
ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(globalCtx->sceneNum, this->randoSlotIndex);
this->actor.textId = 0x9100 + (shopItemIdentity.randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1);
}
this->isInvisible = false;
this->actor.draw = EnGirlA_Draw;
}
@@ -944,7 +1056,7 @@ void EnGirlA_SetItemDescription(GlobalContext* globalCtx, EnGirlA* this) {
void EnGirlA_SetItemOutOfStock(GlobalContext* globalCtx, EnGirlA* this) {
this->isInvisible = true;
this->actor.draw = NULL;
if ((this->actor.params >= SI_KEATON_MASK) && (this->actor.params <= SI_GERUDO_MASK)) {
if (((this->actor.params >= SI_KEATON_MASK) && (this->actor.params <= SI_GERUDO_MASK)) || this->actor.params == SI_RANDOMIZED_ITEM) {
this->actor.textId = 0xBD;
}
}
@@ -952,10 +1064,16 @@ void EnGirlA_SetItemOutOfStock(GlobalContext* globalCtx, EnGirlA* this) {
void EnGirlA_UpdateStockedItem(GlobalContext* globalCtx, EnGirlA* this) {
ShopItemEntry* itemEntry;
if (EnGirlA_TryChangeShopItem(this)) {
if (EnGirlA_TryChangeShopItem(this, globalCtx)) {
EnGirlA_InitItem(this, globalCtx);
itemEntry = &shopItemEntries[this->actor.params];
this->actor.textId = itemEntry->itemDescTextId;
if (this->actor.params == SI_RANDOMIZED_ITEM) {
ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(globalCtx->sceneNum, this->randoSlotIndex);
this->actor.textId = 0x9100 + (shopItemIdentity.randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1);
} else {
this->actor.textId = itemEntry->itemDescTextId;
}
} else {
this->isInvisible = false;
this->actor.draw = EnGirlA_Draw;
@@ -1053,7 +1171,13 @@ void EnGirlA_InitializeItemAction(EnGirlA* this, GlobalContext* globalCtx) {
this->canBuyFunc = itemEntry->canBuyFunc;
this->itemGiveFunc = itemEntry->itemGiveFunc;
this->buyEventFunc = itemEntry->buyEventFunc;
this->basePrice = itemEntry->price;
// If chus are in logic, make the 10 pack affordable without a wallet upgrade
if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC) &&
this->getItemId == GI_BOMBCHUS_10) {
this->basePrice = 99;
} else {
this->basePrice = itemEntry->price;
}
this->itemCount = itemEntry->count;
this->hiliteFunc = itemEntry->hiliteFunc;
this->giDrawId = itemEntry->giDrawId;
@@ -1070,6 +1194,21 @@ void EnGirlA_InitializeItemAction(EnGirlA* this, GlobalContext* globalCtx) {
this->isSelected = false;
this->yRotation = 0;
this->yRotationInit = this->actor.shape.rot.y;
if (params == SI_RANDOMIZED_ITEM) {
ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(globalCtx->sceneNum, this->randoSlotIndex);
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheckWithoutObtainabilityCheck(shopItemIdentity.randomizerCheck, shopItemIdentity.ogItemId);
this->actor.textId = 0x9100 + (shopItemIdentity.randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1);
this->itemBuyPromptTextId = 0x9100 + ((shopItemIdentity.randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) + NUM_SHOP_ITEMS);
this->getItemId = getItemEntry.getItemId;
this->basePrice = shopItemIdentity.itemPrice;
this->giDrawId = getItemEntry.gid;
// Correct the rotation for spiritual stones
if (getItemEntry.getItemId >= RG_KOKIRI_EMERALD && getItemEntry.getItemId <= RG_ZORA_SAPPHIRE) {
this->actor.shape.rot.y = this->actor.shape.rot.y + 20000;
}
}
}
}
@@ -1108,5 +1247,15 @@ void EnGirlA_Draw(Actor* thisx, GlobalContext* globalCtx) {
if (this->hiliteFunc != NULL) {
this->hiliteFunc(thisx, globalCtx, 0);
}
if (this->actor.params == SI_RANDOMIZED_ITEM) {
ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(globalCtx->sceneNum, this->randoSlotIndex);
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheckWithoutObtainabilityCheck(shopItemIdentity.randomizerCheck, shopItemIdentity.ogItemId);
EnItem00_CustomItemsParticles(&this->actor, globalCtx, getItemEntry);
GetItemEntry_Draw(globalCtx, getItemEntry);
return;
}
GetItem_Draw(globalCtx, this->giDrawId);
}
@@ -33,6 +33,7 @@ typedef struct EnGirlA {
/* 0x01CA */ s16 itemCount;
/* 0x01CC */ s16 giDrawId;
/* 0x01D0 */ EnGirlA3Func hiliteFunc;
/* 0x01D4 */ u8 randoSlotIndex; // used by randomizer to determine which slot this item is for id purposes.
} EnGirlA; // size = 0x01D4
typedef enum {
@@ -86,7 +87,8 @@ typedef enum {
/* 0x2F */ SI_BOMBS_5_R35,
/* 0x30 */ SI_RED_POTION_R40,
/* 0x31 */ SI_RED_POTION_R50,
/* 0x32 */ SI_MAX
/* 0x32 */ SI_RANDOMIZED_ITEM,
/* 0x33 */ SI_MAX
} EnGirlAShopItem;
typedef enum {
+18 -5
View File
@@ -3,6 +3,7 @@
#include "objects/gameplay_keep/gameplay_keep.h"
#include "objects/object_oF1d_map/object_oF1d_map.h"
#include "soh/frame_interpolation.h"
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
#define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3 | ACTOR_FLAG_4 | ACTOR_FLAG_5)
@@ -94,7 +95,7 @@ u16 EnGo_GetTextID(GlobalContext* globalCtx, Actor* thisx) {
switch (thisx->params & 0xF0) {
case 0x90:
if (gSaveContext.bgsFlag) {
if (!gSaveContext.n64ddFlag && gSaveContext.bgsFlag) {
return 0x305E;
} else if (INV_CONTENT(ITEM_TRADE_ADULT) >= ITEM_CLAIM_CHECK) {
if (Environment_GetBgsDayCount() >= CVar_GetS32("gForgeTime", 3)) {
@@ -113,7 +114,7 @@ u16 EnGo_GetTextID(GlobalContext* globalCtx, Actor* thisx) {
}
case 0x00:
if ((!gSaveContext.n64ddFlag && CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) ||
(gSaveContext.n64ddFlag && gSaveContext.dungeonsDone[4])) {
(gSaveContext.n64ddFlag && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) {
if (gSaveContext.infTable[16] & 0x8000) {
return 0x3042;
} else {
@@ -858,7 +859,7 @@ void func_80A405CC(EnGo* this, GlobalContext* globalCtx) {
void EnGo_BiggoronActionFunc(EnGo* this, GlobalContext* globalCtx) {
if (((this->actor.params & 0xF0) == 0x90) && (this->unk_1E0.unk_00 == 2)) {
if (gSaveContext.bgsFlag) {
if (!gSaveContext.n64ddFlag && gSaveContext.bgsFlag) {
this->unk_1E0.unk_00 = 0;
} else {
if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_EYEDROPS) {
@@ -966,10 +967,22 @@ void EnGo_GetItem(EnGo* this, GlobalContext* globalCtx) {
this->unk_20C = 1;
}
if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_EYEDROPS) {
getItemId = GI_CLAIM_CHECK;
if (gSaveContext.n64ddFlag) {
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_DMT_TRADE_EYEDROPS, GI_CLAIM_CHECK);
getItemId = getItemEntry.getItemId;
Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_EYEDROPS);
} else {
getItemId = GI_CLAIM_CHECK;
}
}
if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_SWORD_BROKEN) {
getItemId = GI_PRESCRIPTION;
if (gSaveContext.n64ddFlag) {
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_DMT_TRADE_BROKEN_SWORD, GI_PRESCRIPTION);
Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_SWORD_BROKEN);
getItemId = getItemEntry.getItemId;
} else {
getItemId = GI_PRESCRIPTION;
}
}
}
+46 -22
View File
@@ -3,6 +3,7 @@
#include "objects/gameplay_keep/gameplay_keep.h"
#include "objects/object_oF1d_map/object_oF1d_map.h"
#include "soh/frame_interpolation.h"
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
#define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3 | ACTOR_FLAG_4 | ACTOR_FLAG_5)
@@ -415,10 +416,10 @@ s16 EnGo2_GetStateGoronDmtRollingSmall(GlobalContext* globalCtx, EnGo2* this) {
u16 EnGo2_GetTextIdGoronDmtDcEntrance(GlobalContext* globalCtx, EnGo2* this) {
if (((!gSaveContext.n64ddFlag && CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) ||
(gSaveContext.n64ddFlag && gSaveContext.dungeonsDone[4])) && LINK_IS_ADULT) {
(gSaveContext.n64ddFlag && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) && LINK_IS_ADULT) {
return 0x3043;
} else if ((!gSaveContext.n64ddFlag && CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) ||
(gSaveContext.n64ddFlag && gSaveContext.dungeonsDone[0])) {
(gSaveContext.n64ddFlag && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN))) {
return 0x3027;
} else {
return gSaveContext.eventChkInf[2] & 0x8 ? 0x3021 : gSaveContext.infTable[14] & 0x1 ? 0x302A : 0x3008;
@@ -438,10 +439,10 @@ s16 EnGo2_GetStateGoronDmtDcEntrance(GlobalContext* globalCtx, EnGo2* this) {
u16 EnGo2_GetTextIdGoronCityEntrance(GlobalContext* globalCtx, EnGo2* this) {
if (((!gSaveContext.n64ddFlag && CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) ||
(gSaveContext.n64ddFlag && gSaveContext.dungeonsDone[4])) && LINK_IS_ADULT) {
(gSaveContext.n64ddFlag && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) && LINK_IS_ADULT) {
return 0x3043;
} else if ((!gSaveContext.n64ddFlag && CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) ||
(gSaveContext.n64ddFlag && gSaveContext.dungeonsDone[0])) {
(gSaveContext.n64ddFlag && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN))) {
return 0x3027;
} else {
return gSaveContext.infTable[15] & 0x1 ? 0x3015 : 0x3014;
@@ -461,10 +462,10 @@ s16 EnGo2_GetStateGoronCityEntrance(GlobalContext* globalCtx, EnGo2* this) {
u16 EnGo2_GetTextIdGoronCityIsland(GlobalContext* globalCtx, EnGo2* this) {
if (((!gSaveContext.n64ddFlag && CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) ||
(gSaveContext.n64ddFlag && gSaveContext.dungeonsDone[4])) && LINK_IS_ADULT) {
(gSaveContext.n64ddFlag && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) && LINK_IS_ADULT) {
return 0x3043;
} else if ((!gSaveContext.n64ddFlag && CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) ||
(gSaveContext.n64ddFlag && gSaveContext.dungeonsDone[0])) {
(gSaveContext.n64ddFlag && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN))) {
return 0x3027;
} else {
return gSaveContext.infTable[15] & 0x10 ? 0x3017 : 0x3016;
@@ -484,10 +485,10 @@ s16 EnGo2_GetStateGoronCityIsland(GlobalContext* globalCtx, EnGo2* this) {
u16 EnGo2_GetTextIdGoronCityLowestFloor(GlobalContext* globalCtx, EnGo2* this) {
if (((!gSaveContext.n64ddFlag && CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) ||
(gSaveContext.n64ddFlag && gSaveContext.dungeonsDone[4])) && LINK_IS_ADULT) {
(gSaveContext.n64ddFlag && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) && LINK_IS_ADULT) {
return 0x3043;
} else if ((!gSaveContext.n64ddFlag && CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) ||
(gSaveContext.n64ddFlag && gSaveContext.dungeonsDone[0])) {
(gSaveContext.n64ddFlag && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN))) {
return 0x3027;
} else {
return CUR_UPG_VALUE(UPG_STRENGTH) != 0 ? 0x302C
@@ -594,7 +595,7 @@ s16 EnGo2_GetStateGoronCityLink(GlobalContext* globalCtx, EnGo2* this) {
u16 EnGo2_GetTextIdGoronDmtBiggoron(GlobalContext* globalCtx, EnGo2* this) {
Player* player = GET_PLAYER(globalCtx);
if (gSaveContext.bgsFlag) {
if (!gSaveContext.n64ddFlag && gSaveContext.bgsFlag) {
player->exchangeItemId = EXCH_ITEM_CLAIM_CHECK;
return 0x305E;
} else if (INV_CONTENT(ITEM_TRADE_ADULT) >= ITEM_CLAIM_CHECK) {
@@ -621,10 +622,6 @@ s16 EnGo2_GetStateGoronDmtBiggoron(GlobalContext* globalCtx, EnGo2* this) {
}
if(gSaveContext.n64ddFlag) {
if (INV_CONTENT(ITEM_CLAIM_CHECK) != ITEM_CLAIM_CHECK) {
return 0;
}
EnGo2_GetItemEntry(this, globalCtx, Randomizer_GetItemFromKnownCheck(RC_DMT_TRADE_CLAIM_CHECK, GI_SWORD_BGS));
Flags_SetTreasure(globalCtx, 0x1F);
} else {
@@ -656,7 +653,14 @@ s16 EnGo2_GetStateGoronDmtBiggoron(GlobalContext* globalCtx, EnGo2* this) {
if (Message_ShouldAdvance(globalCtx)) {
if ((this->actor.textId == 0x3054) || (this->actor.textId == 0x3055)) {
if (globalCtx->msgCtx.choiceIndex == 0) {
EnGo2_GetItem(this, globalCtx, GI_PRESCRIPTION);
if (gSaveContext.n64ddFlag) {
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_DMT_TRADE_BROKEN_SWORD, GI_PRESCRIPTION);
Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_SWORD_BROKEN);
EnGo2_GetItemEntry(this, globalCtx, getItemEntry);
} else {
u32 getItemId = GI_PRESCRIPTION;
EnGo2_GetItem(this, globalCtx, getItemId);
}
this->actionFunc = EnGo2_SetupGetItem;
return 2;
}
@@ -1055,7 +1059,7 @@ void EnGo2_BiggoronSetTextId(EnGo2* this, GlobalContext* globalCtx, Player* play
u16 textId;
if ((this->actor.params & 0x1F) == GORON_DMT_BIGGORON) {
if (gSaveContext.bgsFlag) {
if ((!gSaveContext.n64ddFlag && gSaveContext.bgsFlag)) {
if (func_8002F368(globalCtx) == EXCH_ITEM_CLAIM_CHECK) {
this->actor.textId = 0x3003;
} else {
@@ -1063,16 +1067,20 @@ void EnGo2_BiggoronSetTextId(EnGo2* this, GlobalContext* globalCtx, Player* play
}
player->actor.textId = this->actor.textId;
} else if (!gSaveContext.bgsFlag && (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_CLAIM_CHECK)) {
} else if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_CLAIM_CHECK) {
if (func_8002F368(globalCtx) == EXCH_ITEM_CLAIM_CHECK) {
if (Environment_GetBgsDayCount() >= CVar_GetS32("gForgeTime", 3)) {
if (gSaveContext.n64ddFlag && Flags_GetTreasure(globalCtx, 0x1F)) {
textId = 0x3003;
} else if (Environment_GetBgsDayCount() >= CVar_GetS32("gForgeTime", 3)) {
textId = 0x305E;
} else {
textId = 0x305D;
}
this->actor.textId = textId;
} else {
if (Environment_GetBgsDayCount() >= CVar_GetS32("gForgeTime", 3)) {
if (gSaveContext.n64ddFlag && Flags_GetTreasure(globalCtx, 0x1F)) {
textId = 0x305E;
} else if (Environment_GetBgsDayCount() >= CVar_GetS32("gForgeTime", 3)) {
textId = 0x3002;
} else {
textId = 0x305D;
@@ -1581,7 +1589,7 @@ void EnGo2_Init(Actor* thisx, GlobalContext* globalCtx) {
case GORON_CITY_STAIRWELL:
case GORON_CITY_LOST_WOODS:
if (((!gSaveContext.n64ddFlag && !CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) ||
(gSaveContext.n64ddFlag && !gSaveContext.dungeonsDone[4])) && LINK_IS_ADULT) {
(gSaveContext.n64ddFlag && !Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) && LINK_IS_ADULT) {
Actor_Kill(&this->actor);
}
this->actionFunc = EnGo2_CurledUp;
@@ -1844,6 +1852,13 @@ void EnGo2_SetGetItem(EnGo2* this, GlobalContext* globalCtx) {
this->actionFunc = EnGo2_GoronRollingBigContinueRolling;
return;
}
if (gSaveContext.n64ddFlag) {
// Resolves #1301. unk_13EE is used to set the opacity of the HUD. The trade sequence discussion with Biggoron
// sets the HUD to transparent, and it is restored at z_message_PAL:3549, but by specifically watching for
// trade sequence items, this leaves it transparent for non-trade sequence items (in rando) so we fix that here
gSaveContext.unk_13EE = 0x32;
}
this->actionFunc = func_80A46B40;
}
}
@@ -1855,12 +1870,14 @@ void EnGo2_BiggoronEyedrops(EnGo2* this, GlobalContext* globalCtx) {
this->actor.flags &= ~ACTOR_FLAG_0;
this->actor.shape.rot.y += 0x5B0;
this->unk_26E = 1;
this->animTimer = this->skelAnime.endFrame + 60.0f + 60.0f; // eyeDrops animation timer
this->animTimer = gSaveContext.n64ddFlag ? 0 : (this->skelAnime.endFrame + 60.0f + 60.0f); // eyeDrops animation timer
this->eyeMouthTexState = 2;
this->unk_20C = 0;
this->goronState++;
func_800F483C(0x28, 5);
OnePointCutscene_Init(globalCtx, 4190, -99, &this->actor, MAIN_CAM);
if (!gSaveContext.n64ddFlag) {
OnePointCutscene_Init(globalCtx, 4190, -99, &this->actor, MAIN_CAM);
}
break;
case 1:
if (DECR(this->animTimer)) {
@@ -1887,7 +1904,14 @@ void EnGo2_BiggoronEyedrops(EnGo2* this, GlobalContext* globalCtx) {
this->unk_26E = 2;
this->skelAnime.playSpeed = 0.0f;
this->skelAnime.curFrame = this->skelAnime.endFrame;
EnGo2_GetItem(this, globalCtx, GI_CLAIM_CHECK);
if (gSaveContext.n64ddFlag) {
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_DMT_TRADE_EYEDROPS, GI_CLAIM_CHECK);
Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_EYEDROPS);
EnGo2_GetItemEntry(this, globalCtx, getItemEntry);
} else {
u32 getItemId = GI_CLAIM_CHECK;
EnGo2_GetItem(this, globalCtx, getItemId);
}
this->actionFunc = EnGo2_SetupGetItem;
this->goronState = 0;
}
+39 -4
View File
@@ -7,6 +7,7 @@
#include "z_en_hs.h"
#include "vt.h"
#include "objects/object_hs/object_hs.h"
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
#define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3)
@@ -78,7 +79,25 @@ void EnHs_Init(Actor* thisx, GlobalContext* globalCtx) {
// "chicken shop (adult era)"
osSyncPrintf(VT_FGCOL(CYAN) " ヒヨコの店(大人の時) \n" VT_RST);
func_80A6E3A0(this, func_80A6E9AC);
if (gSaveContext.itemGetInf[3] & 1) {
bool shouldSpawn;
bool tradedMushroom = gSaveContext.itemGetInf[3] & 1;
if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE)) {
// To explain the logic because Fado and Grog are linked:
// - If you have Cojiro, then spawn Grog and not Fado.
// - If you don't have Cojiro but do have Odd Potion, spawn Fado and not Grog.
// - If you don't have either, spawn Grog if you haven't traded the Odd Mushroom.
// - If you don't have either but have traded the mushroom, don't spawn either.
if (PLAYER_HAS_SHUFFLED_ADULT_TRADE_ITEM(ITEM_COJIRO)) {
shouldSpawn = true;
} else if (PLAYER_HAS_SHUFFLED_ADULT_TRADE_ITEM(ITEM_ODD_POTION)) {
shouldSpawn = false;
} else {
shouldSpawn = !tradedMushroom;
}
} else {
shouldSpawn = !tradedMushroom;
}
if (!shouldSpawn) {
// "chicken shop closed"
osSyncPrintf(VT_FGCOL(CYAN) " ヒヨコ屋閉店 \n" VT_RST);
Actor_Kill(&this->actor);
@@ -127,7 +146,9 @@ void func_80A6E5EC(EnHs* this, GlobalContext* globalCtx) {
void func_80A6E630(EnHs* this, GlobalContext* globalCtx) {
if ((Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(globalCtx)) {
func_80088AA0(180);
if (!gSaveContext.n64ddFlag) {
func_80088AA0(180);
}
func_80A6E3A0(this, func_80A6E6B0);
gSaveContext.eventInf[1] &= ~1;
}
@@ -156,7 +177,14 @@ void func_80A6E740(EnHs* this, GlobalContext* globalCtx) {
this->actor.parent = NULL;
func_80A6E3A0(this, func_80A6E630);
} else {
func_8002F434(&this->actor, globalCtx, GI_ODD_MUSHROOM, 10000.0f, 50.0f);
if (gSaveContext.n64ddFlag) {
GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_LW_TRADE_COJIRO, GI_ODD_MUSHROOM);
Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_COJIRO);
GiveItemEntryFromActor(&this->actor, globalCtx, itemEntry, 10000.0f, 50.0f);
} else {
s32 itemId = GI_ODD_MUSHROOM;
func_8002F434(&this->actor, globalCtx, itemId, 10000.0f, 50.0f);
}
}
this->unk_2A8 |= 1;
@@ -167,7 +195,14 @@ void func_80A6E7BC(EnHs* this, GlobalContext* globalCtx) {
switch (globalCtx->msgCtx.choiceIndex) {
case 0:
func_80A6E3A0(this, func_80A6E740);
func_8002F434(&this->actor, globalCtx, GI_ODD_MUSHROOM, 10000.0f, 50.0f);
if (gSaveContext.n64ddFlag) {
GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_LW_TRADE_COJIRO, GI_ODD_MUSHROOM);
Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_COJIRO);
GiveItemEntryFromActor(&this->actor, globalCtx, itemEntry, 10000.0f, 50.0f);
} else {
s32 itemId = GI_ODD_MUSHROOM;
func_8002F434(&this->actor, globalCtx, itemId, 10000.0f, 50.0f);
}
break;
case 1:
Message_ContinueTextbox(globalCtx, 0x10B4);
@@ -117,11 +117,13 @@ void func_80A90264(EnKakasi2* this, GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
this->unk_194++;
bool skipScarecrow = globalCtx->msgCtx.msgMode == MSGMODE_OCARINA_PLAYING &&
((CVar_GetS32("gSkipScarecrow", 0) && gSaveContext.scarecrowSpawnSongSet) ||
(gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SKIP_SCARECROWS_SONG)));
if (((BREG(1) != 0) || ((CVar_GetS32("gSkipScarecrow", 0) != 0) &&
(globalCtx->msgCtx.ocarinaAction == OCARINA_ACTION_FREE_PLAY) && gSaveContext.scarecrowSpawnSongSet)) &&
(this->actor.xzDistToPlayer < this->maxSpawnDistance.x) &&
(fabsf(player->actor.world.pos.y - this->actor.world.pos.y) < this->maxSpawnDistance.y)){
if ((BREG(1) != 0) || skipScarecrow && (this->actor.xzDistToPlayer < this->maxSpawnDistance.x) &&
(fabsf(player->actor.world.pos.y - this->actor.world.pos.y) < this->maxSpawnDistance.y)) {
this->actor.draw = func_80A90948;
Collider_InitCylinder(globalCtx, &this->collider);
Collider_SetCylinder(globalCtx, &this->collider, &this->actor, &sCylinderInit);
+23 -2
View File
@@ -10,6 +10,7 @@
#include "objects/object_km1/object_km1.h"
#include "objects/object_kw1/object_kw1.h"
#include "vt.h"
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
#define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3 | ACTOR_FLAG_4)
@@ -1025,7 +1026,20 @@ s32 EnKo_CanSpawn(EnKo* this, GlobalContext* globalCtx) {
}
case SCENE_SPOT10:
return (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_ODD_POTION) ? true : false;
if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE)) {
// To explain the logic because Fado and Grog are linked:
// - If you have Cojiro, then spawn Grog and not Fado.
// - If you don't have Cojiro but do have Odd Potion, spawn Fado and not Grog.
// - If you don't have either, spawn Grog if you haven't traded the Odd Mushroom.
// - If you don't have either but have traded the mushroom, don't spawn either.
if (PLAYER_HAS_SHUFFLED_ADULT_TRADE_ITEM(ITEM_COJIRO)) {
return false;
} else {
return PLAYER_HAS_SHUFFLED_ADULT_TRADE_ITEM(ITEM_ODD_POTION);
}
} else {
return (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_ODD_POTION) ? true : false;
}
default:
return false;
}
@@ -1216,7 +1230,14 @@ void func_80A99504(EnKo* this, GlobalContext* globalCtx) {
this->actor.parent = NULL;
this->actionFunc = func_80A99560;
} else {
func_8002F434(&this->actor, globalCtx, GI_SAW, 120.0f, 10.0f);
if (gSaveContext.n64ddFlag) {
GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_LW_TRADE_ODD_POTION, GI_SAW);
Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_ODD_POTION);
GiveItemEntryFromActor(&this->actor, globalCtx, itemEntry, 120.0f, 10.0f);
} else {
s32 itemId = GI_SAW;
func_8002F434(&this->actor, globalCtx, itemId, 120.0f, 10.0f);
}
}
}
+4 -2
View File
@@ -6,6 +6,7 @@
#include "z_en_kz.h"
#include "objects/object_kz/object_kz.h"
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
#define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3)
@@ -72,7 +73,7 @@ static AnimationInfo sAnimationInfo[] = {
u16 EnKz_GetTextNoMaskChild(GlobalContext* globalCtx, EnKz* this) {
Player* player = GET_PLAYER(globalCtx);
if ((gSaveContext.n64ddFlag && gSaveContext.dungeonsDone[2]) ||
if ((gSaveContext.n64ddFlag && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY)) ||
(!gSaveContext.n64ddFlag && CHECK_QUEST_ITEM(QUEST_ZORA_SAPPHIRE))) {
return 0x402B;
} else if (gSaveContext.eventChkInf[3] & 8) {
@@ -467,6 +468,7 @@ void EnKz_SetupGetItem(EnKz* this, GlobalContext* globalCtx) {
if (this->isTrading) {
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_ZD_TRADE_PRESCRIPTION, GI_FROG);
getItemId = getItemEntry.getItemId;
Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_PRESCRIPTION);
Flags_SetTreasure(globalCtx, 0x1F);
} else {
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_ZD_KING_ZORA_THAWED, GI_TUNIC_ZORA);
@@ -487,7 +489,7 @@ void EnKz_SetupGetItem(EnKz* this, GlobalContext* globalCtx) {
void EnKz_StartTimer(EnKz* this, GlobalContext* globalCtx) {
if ((Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(globalCtx)) {
if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_FROG) {
if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_FROG && !gSaveContext.n64ddFlag) {
func_80088AA0(180); // start timer2 with 3 minutes
gSaveContext.eventInf[1] &= ~1;
}
+41 -10
View File
@@ -90,7 +90,16 @@ static void* sEyeTextures[] = {
gMalonChildEyeClosedTex,
};
bool Randomizer_ObtainedMalonHCReward() {
return Flags_GetEventChkInf(0x12);
}
u16 EnMa1_GetText(GlobalContext* globalCtx, Actor* thisx) {
// Special case for Malon Hyrule Castle Text. Placing it here at the beginning
// has the added benefit of circumventing mask text if wearing bunny hood.
if (gSaveContext.n64ddFlag && globalCtx->sceneNum == SCENE_SPOT15) {
return Randomizer_ObtainedMalonHCReward() ? 0x2044 : 0x2043;
}
u16 faceReaction = Text_GetFaceReaction(globalCtx, 0x17);
if (faceReaction != 0) {
@@ -191,25 +200,34 @@ s32 func_80AA08C4(EnMa1* this, GlobalContext* globalCtx) {
if (!LINK_IS_CHILD) {
return 0;
}
// Causes Malon to appear in the market if you haven't met her yet.
if (((globalCtx->sceneNum == SCENE_MARKET_NIGHT) || (globalCtx->sceneNum == SCENE_MARKET_DAY)) &&
!(gSaveContext.eventChkInf[1] & 0x10) && !(gSaveContext.infTable[8] & 0x800)) {
return 1;
}
if ((globalCtx->sceneNum == SCENE_SPOT15) && !(gSaveContext.eventChkInf[1] & 0x10)) {
if (gSaveContext.infTable[8] & 0x800) {
return 1;
} else {
gSaveContext.infTable[8] |= 0x800;
return 0;
if ((globalCtx->sceneNum == SCENE_SPOT15) && // if we're at hyrule castle
(!(gSaveContext.eventChkInf[1] & 0x10) || // and talon hasn't left
(gSaveContext.n64ddFlag &&
!Randomizer_ObtainedMalonHCReward()))) { // or we're rando'd and haven't gotten malon's HC check
if (gSaveContext.infTable[8] & 0x800) { // if we've met malon
return 1; // make her appear at the castle
} else { // if we haven't met malon
gSaveContext.infTable[8] |= 0x800; // set the flag for meeting malon
return 0; // don't make her appear at the castle
}
}
// Malon asleep in her bed if Talon has left Hyrule Castle and it is nighttime.
if ((globalCtx->sceneNum == SCENE_SOUKO) && IS_NIGHT && (gSaveContext.eventChkInf[1] & 0x10)) {
return 1;
}
// Don't spawn Malon if none of the above are true and we are not in Lon Lon Ranch.
if (globalCtx->sceneNum != SCENE_SPOT20) {
return 0;
}
if ((this->actor.shape.rot.z == 3) && IS_DAY && (gSaveContext.eventChkInf[1] & 0x10)) {
// If we've gotten this far, we're in Lon Lon Ranch. Spawn Malon if it is daytime, Talon has left Hyrule Castle, and
// either we are not randomized, or we are and we have received Malon's item at Hyrule Castle.
if ((this->actor.shape.rot.z == 3) && IS_DAY && (gSaveContext.eventChkInf[1] & 0x10) &&
((gSaveContext.n64ddFlag && Randomizer_ObtainedMalonHCReward()) || !gSaveContext.n64ddFlag)) {
return 1;
}
return 0;
@@ -290,10 +308,16 @@ void EnMa1_Init(Actor* thisx, GlobalContext* globalCtx) {
this->actor.targetMode = 6;
this->unk_1E8.unk_00 = 0;
if (!(gSaveContext.eventChkInf[1] & 0x10) || (CHECK_QUEST_ITEM(QUEST_SONG_EPONA) && !gSaveContext.n64ddFlag) ||
// To avoid missing a check, we want Malon to have the actionFunc for singing, but not reacting to Ocarina, if any of
// the following are true.
// 1. Talon has not left Hyrule Castle.
// 2. We are Randomized and have not obtained Malon's Weird Egg Check.
// 3. We are not Randomized and have obtained Epona's Song
if (!(gSaveContext.eventChkInf[1] & 0x10) || (gSaveContext.n64ddFlag && !Randomizer_ObtainedMalonHCReward()) || (CHECK_QUEST_ITEM(QUEST_SONG_EPONA) && !gSaveContext.n64ddFlag) ||
(gSaveContext.n64ddFlag && Flags_GetTreasure(globalCtx, 0x1F))) {
this->actionFunc = func_80AA0D88;
EnMa1_ChangeAnim(this, ENMA1_ANIM_2);
// If none of the above conditions were true, set Malon up to teach Epona's Song.
} else {
if (gSaveContext.n64ddFlag) { // Skip straight to "let's sing it together" textbox in the ranch
gSaveContext.eventChkInf[1] |= 0x40;
@@ -322,9 +346,16 @@ void func_80AA0D88(EnMa1* this, GlobalContext* globalCtx) {
}
}
if ((globalCtx->sceneNum == SCENE_SPOT15) && (gSaveContext.eventChkInf[1] & 0x10)) {
// We want to Kill Malon's Actor outside of randomizer when Talon is freed. In Randomizer we don't kill Malon's
// Actor here, otherwise if we wake up Talon first and then get her check she will spontaneously
// disappear.
if ((globalCtx->sceneNum == SCENE_SPOT15) && (!gSaveContext.n64ddFlag && gSaveContext.eventChkInf[1] & 0x10)) {
Actor_Kill(&this->actor);
} else if (!(gSaveContext.eventChkInf[1] & 0x10) || (CHECK_QUEST_ITEM(QUEST_SONG_EPONA) && !gSaveContext.n64ddFlag)) {
// We want Malon to give the Weird Egg Check (see function below) in the following situations:
// 1. Talon as not left Hyrule Castle (Vanilla) OR
// 2. We haven't obtained Malon's Weird Egg Check (Randomizer only) OR
// 3. We have Epona's Song? (Vanilla only, not sure why it's here but I didn't write that one)
} else if ((!(gSaveContext.eventChkInf[1] & 0x10) || (gSaveContext.n64ddFlag && !Randomizer_ObtainedMalonHCReward())) || (CHECK_QUEST_ITEM(QUEST_SONG_EPONA) && !gSaveContext.n64ddFlag)) {
if (this->unk_1E8.unk_00 == 2) {
this->actionFunc = func_80AA0EA0;
globalCtx->msgCtx.stateTimer = 4;
+2 -2
View File
@@ -373,7 +373,7 @@ u16 EnMd_GetTextKokiriForest(GlobalContext* globalCtx, EnMd* this) {
this->unk_209 = TEXT_STATE_NONE;
if ((!gSaveContext.n64ddFlag && CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)) ||
(gSaveContext.n64ddFlag && gSaveContext.dungeonsDone[1])) {
(gSaveContext.n64ddFlag && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE))) {
return 0x1045;
}
@@ -486,7 +486,7 @@ u8 EnMd_ShouldSpawn(EnMd* this, GlobalContext* globalCtx) {
if (gSaveContext.n64ddFlag) {
// if we have beaten deku tree or have open forest turned on
// or have already shown mido we have an equipped sword/shield
if (gSaveContext.dungeonsDone[1] ||
if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE) ||
Randomizer_GetSettingValue(RSK_FOREST) == 1 ||
gSaveContext.eventChkInf[0] & 0x10) {
return 0;
+24 -7
View File
@@ -6,6 +6,7 @@
#include "z_en_mk.h"
#include "objects/object_mk/object_mk.h"
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
#define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3 | ACTOR_FLAG_4)
@@ -93,17 +94,33 @@ void func_80AACA94(EnMk* this, GlobalContext* globalCtx) {
if (Actor_HasParent(&this->actor, globalCtx) != 0) {
this->actor.parent = NULL;
this->actionFunc = func_80AACA40;
func_80088AA0(240);
gSaveContext.eventInf[1] &= ~1;
if (!gSaveContext.n64ddFlag) {
func_80088AA0(240);
gSaveContext.eventInf[1] &= ~1;
}
} else {
func_8002F434(&this->actor, globalCtx, GI_EYEDROPS, 10000.0f, 50.0f);
if (gSaveContext.n64ddFlag) {
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LH_TRADE_FROG, GI_EYEDROPS);
Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_FROG);
GiveItemEntryFromActor(&this->actor, globalCtx, getItemEntry, 10000.0f, 50.0f);
} else {
s32 getItemID = GI_EYEDROPS;
func_8002F434(&this->actor, globalCtx, getItemID, 10000.0f, 50.0f);
}
}
}
void func_80AACB14(EnMk* this, GlobalContext* globalCtx) {
if (Actor_TextboxIsClosing(&this->actor, globalCtx)) {
this->actionFunc = func_80AACA94;
func_8002F434(&this->actor, globalCtx, GI_EYEDROPS, 10000.0f, 50.0f);
if (gSaveContext.n64ddFlag) {
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LH_TRADE_FROG, GI_EYEDROPS);
Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_FROG);
GiveItemEntryFromActor(&this->actor, globalCtx, getItemEntry, 10000.0f, 50.0f);
} else {
s32 getItemID = GI_EYEDROPS;
func_8002F434(&this->actor, globalCtx, getItemID, 10000.0f, 50.0f);
}
}
}
@@ -129,7 +146,7 @@ void func_80AACC04(EnMk* this, GlobalContext* globalCtx) {
if (this->timer > 0) {
this->timer--;
} else {
this->timer = 16;
this->timer = gSaveContext.n64ddFlag ? 0 : 16;
this->actionFunc = func_80AACBAC;
Animation_Change(&this->skelAnime, &object_mk_Anim_000D88, 1.0f, 0.0f,
Animation_GetLastFrame(&object_mk_Anim_000D88), ANIMMODE_LOOP, -4.0f);
@@ -142,7 +159,7 @@ void func_80AACCA0(EnMk* this, GlobalContext* globalCtx) {
this->timer--;
this->actor.shape.rot.y += 0x800;
} else {
this->timer = 120;
this->timer = gSaveContext.n64ddFlag ? 0 : 120;
this->actionFunc = func_80AACC04;
Animation_Change(&this->skelAnime, &object_mk_Anim_000724, 1.0f, 0.0f,
Animation_GetLastFrame(&object_mk_Anim_000724), ANIMMODE_LOOP, -4.0f);
@@ -158,7 +175,7 @@ void func_80AACD48(EnMk* this, GlobalContext* globalCtx) {
this->actionFunc = func_80AACCA0;
globalCtx->msgCtx.msgMode = MSGMODE_PAUSED;
player->exchangeItemId = EXCH_ITEM_NONE;
this->timer = 16;
this->timer = gSaveContext.n64ddFlag ? 0 : 16;
Animation_Change(&this->skelAnime, &object_mk_Anim_000D88, 1.0f, 0.0f,
Animation_GetLastFrame(&object_mk_Anim_000D88), ANIMMODE_LOOP, -4.0f);
this->flags &= ~2;
+20 -5
View File
@@ -125,11 +125,19 @@ void EnMs_Talk(EnMs* this, GlobalContext* globalCtx) {
} else if (Message_ShouldAdvance(globalCtx)) {
switch (globalCtx->msgCtx.choiceIndex) {
case 0: // yes
if (gSaveContext.rupees < sPrices[BEANS_BOUGHT]) {
if (gSaveContext.rupees <
((gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS))
? 60
: sPrices[BEANS_BOUGHT])) {
Message_ContinueTextbox(globalCtx, 0x4069); // not enough rupees text
return;
}
func_8002F434(&this->actor, globalCtx, GI_BEAN, 90.0f, 10.0f);
if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)) {
GiveItemEntryFromActor(&this->actor, globalCtx,
Randomizer_GetItemFromKnownCheck(RC_ZR_MAGIC_BEAN_SALESMAN, GI_BEAN), 90.0f, 10.0f);
} else {
func_8002F434(&this->actor, globalCtx, GI_BEAN, 90.0f, 10.0f);
}
this->actionFunc = EnMs_Sell;
return;
case 1: // no
@@ -142,11 +150,18 @@ void EnMs_Talk(EnMs* this, GlobalContext* globalCtx) {
void EnMs_Sell(EnMs* this, GlobalContext* globalCtx) {
if (Actor_HasParent(&this->actor, globalCtx)) {
Rupees_ChangeBy(-sPrices[BEANS_BOUGHT]);
Rupees_ChangeBy((gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)) ? -60 : -sPrices[BEANS_BOUGHT]);
this->actor.parent = NULL;
this->actionFunc = EnMs_TalkAfterPurchase;
this->actionFunc =
(gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)) ? EnMs_Wait : EnMs_TalkAfterPurchase;
} else {
func_8002F434(&this->actor, globalCtx, GI_BEAN, 90.0f, 10.0f);
if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)) {
GiveItemEntryFromActor(&this->actor, globalCtx,
Randomizer_GetItemFromKnownCheck(RC_ZR_MAGIC_BEAN_SALESMAN, GI_BEAN), 90.0f, 10.0f);
BEANS_BOUGHT = 10;
} else {
func_8002F434(&this->actor, globalCtx, GI_BEAN, 90.0f, 10.0f);
}
}
}
@@ -3,6 +3,7 @@
#include "objects/object_os_anime/object_os_anime.h"
#include "overlays/actors/ovl_En_Niw/z_en_niw.h"
#include "vt.h"
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
#define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3 | ACTOR_FLAG_4)
@@ -456,10 +457,16 @@ void func_80ABAC00(EnNiwLady* this, GlobalContext* globalCtx) {
if (LINK_IS_ADULT) {
getItemId = !(gSaveContext.itemGetInf[2] & 0x1000) ? GI_POCKET_EGG : GI_COJIRO;
if (gSaveContext.n64ddFlag && getItemId == GI_POCKET_EGG) {
// TODO: get-item-rework Adult trade sequence
this->getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_ANJU_AS_ADULT, GI_POCKET_EGG);
GiveItemEntryFromActor(&this->actor, globalCtx, this->getItemEntry, 200.0f, 100.0f);
if (gSaveContext.n64ddFlag) {
if (getItemId == GI_POCKET_EGG) {
// TODO: get-item-rework Adult trade sequence
this->getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_ANJU_AS_ADULT, GI_POCKET_EGG);
GiveItemEntryFromActor(&this->actor, globalCtx, this->getItemEntry, 200.0f, 100.0f);
} else {
this->getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_TRADE_POCKET_CUCCO, GI_COJIRO);
Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_POCKET_CUCCO);
GiveItemEntryFromActor(&this->actor, globalCtx, this->getItemEntry, 200.0f, 100.0f);
}
}
}
if (this->getItemEntry.getItemId == GI_NONE) {
@@ -427,6 +427,16 @@ void EnOssan_SpawnItemsOnShelves(EnOssan* this, GlobalContext* globalCtx, ShopIt
this->shelfSlots[i] = NULL;
} else {
itemParams = sShopItemReplaceFunc[shopItems->shopItemIndex](shopItems->shopItemIndex);
if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHOPSANITY)) {
ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(globalCtx->sceneNum, i);
if (shopItemIdentity.randomizerCheck != RC_UNKNOWN_CHECK) {
itemParams = shopItemIdentity.enGirlAShopItem;
if (Flags_GetRandomizerInf(shopItemIdentity.randomizerInf)) {
itemParams = SI_SOLD_OUT;
}
}
}
if (itemParams < 0) {
this->shelfSlots[i] = NULL;
@@ -437,6 +447,9 @@ void EnOssan_SpawnItemsOnShelves(EnOssan* this, GlobalContext* globalCtx, ShopIt
shelves->actor.world.pos.y + shopItems->yOffset, shelves->actor.world.pos.z + shopItems->zOffset,
shelves->actor.shape.rot.x, shelves->actor.shape.rot.y + sItemShelfRot[i],
shelves->actor.shape.rot.z, itemParams);
if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHOPSANITY)) {
this->shelfSlots[i]->randoSlotIndex = i;
}
}
}
}
@@ -518,7 +531,7 @@ void EnOssan_TalkGoronShopkeeper(GlobalContext* globalCtx) {
Message_ContinueTextbox(globalCtx, 0x300F);
}
} else if ((!gSaveContext.n64ddFlag && !CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) ||
(gSaveContext.n64ddFlag && !gSaveContext.dungeonsDone[4])) {
(gSaveContext.n64ddFlag && !Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) {
Message_ContinueTextbox(globalCtx, 0x3057);
} else {
Message_ContinueTextbox(globalCtx, 0x305B);
@@ -1330,7 +1343,19 @@ void EnOssan_GiveItemWithFanfare(GlobalContext* globalCtx, EnOssan* this) {
Player* player = GET_PLAYER(globalCtx);
osSyncPrintf("\n" VT_FGCOL(YELLOW) "初めて手にいれた!!" VT_RST "\n\n");
func_8002F434(&this->actor, globalCtx, this->shelfSlots[this->cursorIndex]->getItemId, 120.0f, 120.0f);
if (!gSaveContext.n64ddFlag) {
func_8002F434(&this->actor, globalCtx, this->shelfSlots[this->cursorIndex]->getItemId, 120.0f, 120.0f);
} else {
ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(globalCtx->sceneNum, this->cursorIndex);
// en_ossan/en_girla are also used for the happy mask shop, which never has randomized items
// and returns RC_UNKNOWN_CHECK, in which case we should fall back to vanilla logic
if (shopItemIdentity.randomizerCheck != RC_UNKNOWN_CHECK) {
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(shopItemIdentity.randomizerCheck, shopItemIdentity.ogItemId);
GiveItemEntryFromActor(&this->actor, globalCtx, getItemEntry, 120.0f, 120.0f);
} else {
func_8002F434(&this->actor, globalCtx, this->shelfSlots[this->cursorIndex]->getItemId, 120.0f, 120.0f);
}
}
globalCtx->msgCtx.msgMode = MSGMODE_TEXT_CLOSING;
globalCtx->msgCtx.stateTimer = 4;
player->stateFlags2 &= ~0x20000000;
@@ -1665,12 +1690,27 @@ void EnOssan_State_GiveItemWithFanfare(EnOssan* this, GlobalContext* globalCtx,
this->stateFlag = OSSAN_STATE_ITEM_PURCHASED;
return;
}
func_8002F434(&this->actor, globalCtx, this->shelfSlots[this->cursorIndex]->getItemId, 120.0f, 120.0f);
if (!gSaveContext.n64ddFlag) {
func_8002F434(&this->actor, globalCtx, this->shelfSlots[this->cursorIndex]->getItemId, 120.0f, 120.0f);
} else {
ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(globalCtx->sceneNum, this->cursorIndex);
// en_ossan/en_girla are also used for the happy mask shop, which never has randomized items
// and returns RC_UNKNOWN_CHECK, in which case we should fall back to vanilla logic
if (shopItemIdentity.randomizerCheck != RC_UNKNOWN_CHECK) {
GetItemEntry getItemEntry =
Randomizer_GetItemFromKnownCheck(shopItemIdentity.randomizerCheck, shopItemIdentity.ogItemId);
GiveItemEntryFromActor(&this->actor, globalCtx, getItemEntry, 120.0f, 120.0f);
} else {
func_8002F434(&this->actor, globalCtx, this->shelfSlots[this->cursorIndex]->getItemId, 120.0f, 120.0f);
}
}
}
void EnOssan_State_ItemPurchased(EnOssan* this, GlobalContext* globalCtx, Player* player) {
EnGirlA* item;
EnGirlA* itemTemp;
ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(globalCtx->sceneNum, this->cursorIndex);
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(shopItemIdentity.randomizerCheck, shopItemIdentity.ogItemId);
if ((Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(globalCtx)) {
if (this->actor.params == OSSAN_TYPE_MASK) {
@@ -1692,6 +1732,12 @@ void EnOssan_State_ItemPurchased(EnOssan* this, GlobalContext* globalCtx, Player
}
item = this->shelfSlots[this->cursorIndex];
item->buyEventFunc(globalCtx, item);
if (getItemEntry.getItemId == RG_ICE_TRAP && getItemEntry.modIndex == MOD_RANDOMIZER) {
EnOssan_ResetItemPosition(this);
item->updateStockedItemFunc(globalCtx, item);
EnOssan_EndInteraction(globalCtx, this);
return;
}
this->stateFlag = OSSAN_STATE_CONTINUE_SHOPPING_PROMPT;
Message_ContinueTextbox(globalCtx, 0x6B);
}
@@ -183,7 +183,7 @@ void EnPoSisters_Init(Actor* thisx, GlobalContext* globalCtx) {
this->epoch++;
// Skip Poe Intro Cutscene
if (gSaveContext.n64ddFlag && thisx->params == 4124) {
if (gSaveContext.n64ddFlag && thisx->params == 4124 && !Randomizer_GetSettingValue(RSK_ENABLE_GLITCH_CUTSCENES)) {
Flags_SetSwitch(globalCtx, 0x1B);
Actor_Kill(thisx);
}
@@ -69,6 +69,15 @@ void EnShopnuts_Init(Actor* thisx, GlobalContext* globalCtx) {
CollisionCheck_SetInfo(&this->actor.colChkInfo, NULL, &sColChkInfoInit);
Collider_UpdateCylinder(&this->actor, &this->collider);
if (gSaveContext.n64ddFlag) {
s16 respawnData = gSaveContext.respawn[RESPAWN_MODE_RETURN].data & ((1 << 8) - 1);
ScrubIdentity scrubIdentity = Randomizer_IdentifyScrub(globalCtx->sceneNum, this->actor.params, respawnData);
if (scrubIdentity.isShuffled && Flags_GetRandomizerInf(scrubIdentity.randomizerInf)) {
Actor_Kill(&this->actor);
}
}
if (((this->actor.params == 0x0002) && (gSaveContext.itemGetInf[0] & 0x800)) ||
((this->actor.params == 0x0009) && (gSaveContext.infTable[25] & 4)) ||
((this->actor.params == 0x000A) && (gSaveContext.infTable[25] & 8))) {
+84 -10
View File
@@ -17,6 +17,13 @@ s32 func_80AFB748(EnSi* this, GlobalContext* globalCtx);
void func_80AFB768(EnSi* this, GlobalContext* globalCtx);
void func_80AFB89C(EnSi* this, GlobalContext* globalCtx);
void func_80AFB950(EnSi* this, GlobalContext* globalCtx);
void Randomizer_UpdateSkullReward(EnSi* this, GlobalContext* globalCtx);
void Randomizer_GiveSkullReward(EnSi* this, GlobalContext* globalCtx);
s32 textId = 0xB4;
s32 giveItemId = ITEM_SKULL_TOKEN;
s32 getItemId;
GetItemEntry getItem;
static ColliderCylinderInit sCylinderInit = {
{
@@ -93,12 +100,26 @@ void func_80AFB768(EnSi* this, GlobalContext* globalCtx) {
if (this->collider.base.ocFlags2 & OC2_HIT_PLAYER) {
this->collider.base.ocFlags2 &= ~OC2_HIT_PLAYER;
Item_Give(globalCtx, ITEM_SKULL_TOKEN);
if (CVar_GetS32("gSkulltulaFreeze", 0) != 1) {
if (gSaveContext.n64ddFlag) {
Randomizer_UpdateSkullReward(this, globalCtx);
} else {
Item_Give(globalCtx, giveItemId);
}
if ((CVar_GetS32("gSkulltulaFreeze", 0) != 1 || giveItemId != ITEM_SKULL_TOKEN) && getItemId != RG_ICE_TRAP) {
player->actor.freezeTimer = 20;
}
Message_StartTextbox(globalCtx, 0xB4, NULL);
Audio_PlayFanfare(NA_BGM_SMALL_ITEM_GET);
Message_StartTextbox(globalCtx, textId, NULL);
if (gSaveContext.n64ddFlag && getItemId != RG_ICE_TRAP) {
Randomizer_GiveSkullReward(this, globalCtx);
Audio_PlayFanfare_Rando(getItem);
} else {
Audio_PlayFanfare(NA_BGM_SMALL_ITEM_GET);
}
player->getItemEntry = (GetItemEntry)GET_ITEM_NONE;
this->actionFunc = func_80AFB950;
} else {
Collider_UpdateCylinder(&this->actor, &this->collider);
@@ -111,15 +132,27 @@ void func_80AFB768(EnSi* this, GlobalContext* globalCtx) {
void func_80AFB89C(EnSi* this, GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
Math_SmoothStepToF(&this->actor.scale.x, 0.25f, 0.4f, 1.0f, 0.0f);
Actor_SetScale(&this->actor, this->actor.scale.x);
this->actor.shape.rot.y += 0x400;
if (!CHECK_FLAG_ALL(this->actor.flags, ACTOR_FLAG_13)) {
Item_Give(globalCtx, ITEM_SKULL_TOKEN);
Message_StartTextbox(globalCtx, 0xB4, NULL);
Audio_PlayFanfare(NA_BGM_SMALL_ITEM_GET);
if (gSaveContext.n64ddFlag) {
Randomizer_UpdateSkullReward(this, globalCtx);
} else {
Item_Give(globalCtx, giveItemId);
}
Message_StartTextbox(globalCtx, textId, NULL);
if (gSaveContext.n64ddFlag && getItemId != RG_ICE_TRAP) {
Randomizer_GiveSkullReward(this, globalCtx);
Audio_PlayFanfare_Rando(getItem);
} else {
Audio_PlayFanfare(NA_BGM_SMALL_ITEM_GET);
}
player->getItemEntry = (GetItemEntry)GET_ITEM_NONE;
this->actionFunc = func_80AFB950;
}
}
@@ -127,7 +160,8 @@ void func_80AFB89C(EnSi* this, GlobalContext* globalCtx) {
void func_80AFB950(EnSi* this, GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
if (Message_GetState(&globalCtx->msgCtx) != TEXT_STATE_CLOSING && CVar_GetS32("gSkulltulaFreeze", 0) != 1) {
if (Message_GetState(&globalCtx->msgCtx) != TEXT_STATE_CLOSING &&
((CVar_GetS32("gSkulltulaFreeze", 0) != 1 || giveItemId != ITEM_SKULL_TOKEN) && getItemId != RG_ICE_TRAP)) {
player->actor.freezeTimer = 10;
} else {
SET_GS_FLAGS((this->actor.params & 0x1F00) >> 8, this->actor.params & 0xFF);
@@ -150,6 +184,46 @@ void EnSi_Draw(Actor* thisx, GlobalContext* globalCtx) {
if (this->actionFunc != func_80AFB950) {
func_8002ED80(&this->actor, globalCtx, 0);
func_8002EBCC(&this->actor, globalCtx, 0);
GetItem_Draw(globalCtx, GID_SKULL_TOKEN_2);
if (!gSaveContext.n64ddFlag) {
GetItem_Draw(globalCtx, GID_SKULL_TOKEN_2);
} else {
getItem = Randomizer_GetItemFromActor(this->actor.id, globalCtx->sceneNum, this->actor.params, GI_SKULL_TOKEN);
EnItem00_CustomItemsParticles(&this->actor, globalCtx, getItem);
if (getItem.itemId != ITEM_SKULL_TOKEN) {
f32 mtxScale = 1.5f;
Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY);
}
GetItemEntry_Draw(globalCtx, getItem);
}
}
}
void Randomizer_UpdateSkullReward(EnSi* this, GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
getItem = Randomizer_GetItemFromActor(this->actor.id, globalCtx->sceneNum, this->actor.params, GI_SKULL_TOKEN);
getItemId = getItem.getItemId;
if (getItemId == RG_ICE_TRAP) {
gSaveContext.pendingIceTrapCount++;
textId = 0xF8;
} else {
textId = getItem.textId;
giveItemId = getItem.itemId;
}
player->getItemEntry = getItem;
}
void Randomizer_GiveSkullReward(EnSi* this, GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
if (getItem.modIndex == MOD_NONE) {
// RANDOTOD: Move this into Item_Give() or some other more central location
if (getItem.getItemId == GI_SWORD_BGS) {
gSaveContext.bgsFlag = true;
}
Item_Give(globalCtx, giveItemId);
} else if (getItem.modIndex == MOD_RANDOMIZER) {
Randomizer_Item_Give(globalCtx, getItem);
}
}
@@ -1068,7 +1068,7 @@ void EnSkj_SetupPostSariasSong(EnSkj* this) {
}
void EnSkj_ChangeModeAfterSong(EnSkj* this, GlobalContext* globalCtx) {
if (((Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(globalCtx)) || Randomizer_ItemIsIceTrap(RC_LW_SKULL_KID, GI_HEART_PIECE)) {
if ((Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(globalCtx)) {
gSaveContext.itemGetInf[1] |= 0x40;
EnSkj_SetNaviId(this);
EnSkj_SetupWaitInRange(this);
+3 -3
View File
@@ -616,9 +616,9 @@ void func_80B0D878(EnSw* this, GlobalContext* globalCtx) {
x = (this->unk_364.x * 10.0f);
y = (this->unk_364.y * 10.0f);
z = (this->unk_364.z * 10.0f);
temp_v0 =
Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_SI, this->actor.world.pos.x + x,
this->actor.world.pos.y + y, this->actor.world.pos.z + z, 0, 0, 0, this->actor.params);
temp_v0 = Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_SI,
this->actor.world.pos.x + x, this->actor.world.pos.y + y,
this->actor.world.pos.z + z, 0, 0, 0, this->actor.params);
if (temp_v0 != NULL) {
temp_v0->parent = NULL;
}
@@ -349,6 +349,7 @@ void EnSyatekiMan_EndGame(EnSyatekiMan* this, GlobalContext* globalCtx) {
this->getItemId = GI_BULLET_BAG_50;
}
} else {
this->getItemEntry = (GetItemEntry)GET_ITEM_NONE;
this->getItemId = GI_RUPEE_PURPLE;
}
} else {
@@ -371,6 +372,7 @@ void EnSyatekiMan_EndGame(EnSyatekiMan* this, GlobalContext* globalCtx) {
break;
}
} else {
this->getItemEntry = (GetItemEntry)GET_ITEM_NONE;
this->getItemId = GI_RUPEE_PURPLE;
}
}
@@ -6,6 +6,7 @@
#include "z_en_toryo.h"
#include "objects/object_toryo/object_toryo.h"
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
#define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3)
@@ -313,7 +314,14 @@ void func_80B20768(EnToryo* this, GlobalContext* globalCtx) {
this->actor.parent = NULL;
this->unk_1E4 = 5;
} else {
func_8002F434(&this->actor, globalCtx, GI_SWORD_BROKEN, 100.0f, 10.0f);
if (gSaveContext.n64ddFlag) {
GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_GV_TRADE_SAW, GI_SWORD_BROKEN);
Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_SAW);
GiveItemEntryFromActor(&this->actor, globalCtx, itemEntry, 100.0f, 10.0f);
} else {
s32 itemId = GI_SWORD_BROKEN;
func_8002F434(&this->actor, globalCtx, itemId, 100.0f, 10.0f);
}
}
return;
}
+1 -1
View File
@@ -2492,4 +2492,4 @@ void EnXc_Reset(void) {
sEnXcFlameSpawned = false;
D_80B41DA8 = 1;
D_80B41DAC = 1;
}
}
@@ -62,7 +62,7 @@ void ItemBHeart_Update(Actor* thisx, GlobalContext* globalCtx) {
if (!gSaveContext.n64ddFlag) {
func_8002F434(&this->actor, globalCtx, GI_HEART_CONTAINER_2, 30.0f, 40.0f);
} else {
GetItemEntry getItemEntry = Randomizer_GetRandomizedItem(GI_HEART_CONTAINER_2, this->actor.id, this->actor.params, globalCtx->sceneNum);
GetItemEntry getItemEntry = Randomizer_GetItemFromActor(this->actor.id, globalCtx->sceneNum, this->actor.params, GI_HEART_CONTAINER_2);
GiveItemEntryFromActor(&this->actor, globalCtx, getItemEntry, 30.0f, 40.0f);
}
}
@@ -99,8 +99,8 @@ void ItemBHeart_Draw(Actor* thisx, GlobalContext* globalCtx) {
}
if (gSaveContext.n64ddFlag) {
GetItem_Draw(globalCtx, Randomizer_GetRandomizedItem(GI_HEART_CONTAINER_2,
this->actor.id,this->actor.params, globalCtx->sceneNum).gid);
GetItemEntry_Draw(globalCtx, Randomizer_GetItemFromActor(this->actor.id,
globalCtx->sceneNum,this->actor.params, GI_HEART_CONTAINER_2));
} else {
if (flag) {
func_80093D84(globalCtx->state.gfxCtx);
@@ -233,7 +233,7 @@ void ItemEtcetera_DrawThroughLens(Actor* thisx, GlobalContext* globalCtx) {
GetItemEntry randoGetItem = GetChestGameRandoGetItem(this->actor.room, this->giDrawId, globalCtx);
EnItem00_CustomItemsParticles(&this->actor, globalCtx, randoGetItem);
if (randoGetItem.itemId != ITEM_NONE) {
GetItem_Draw(globalCtx, randoGetItem.gid);
GetItemEntry_Draw(globalCtx, randoGetItem);
return;
}
}
@@ -256,8 +256,11 @@ void ItemEtcetera_Draw(Actor* thisx, GlobalContext* globalCtx) {
EnItem00_CustomItemsParticles(&this->actor, globalCtx, randoGetItem);
if (randoGetItem.itemId != RG_NONE) {
this->giDrawId = randoGetItem.gid;
if (randoGetItem.itemId != ITEM_NONE) {
func_8002EBCC(&this->actor, globalCtx, 0);
func_8002ED80(&this->actor, globalCtx, 0);
GetItemEntry_Draw(globalCtx, randoGetItem);
return;
}
}
@@ -168,8 +168,7 @@ void ItemOcarina_DoNothing(ItemOcarina* this, GlobalContext* globalCtx) {
}
void ItemOcarina_StartSoTCutscene(ItemOcarina* this, GlobalContext* globalCtx) {
if (Actor_TextboxIsClosing(&this->actor, globalCtx) ||
Randomizer_ObtainedFreestandingIceTrap(RC_HF_OCARINA_OF_TIME_ITEM, GI_OCARINA_OOT, &this->actor)) {
if (Actor_TextboxIsClosing(&this->actor, globalCtx)) {
if (!gSaveContext.n64ddFlag) {
globalCtx->csCtx.segment = SEGMENTED_TO_VIRTUAL(gHyruleFieldZeldaSongOfTimeCs);
gSaveContext.cutsceneTrigger = 1;
@@ -218,7 +217,7 @@ void ItemOcarina_Draw(Actor* thisx, GlobalContext* globalCtx) {
if (gSaveContext.n64ddFlag) {
GetItemEntry randoGetItem = Randomizer_GetItemFromKnownCheck(RC_HF_OCARINA_OF_TIME_ITEM, GI_OCARINA_OOT);
EnItem00_CustomItemsParticles(&this->actor, globalCtx, randoGetItem);
GetItem_Draw(globalCtx, ABS(randoGetItem.gi) - 1);
GetItemEntry_Draw(globalCtx, randoGetItem);
return;
}
@@ -123,7 +123,7 @@ void ObjLightswitch_InitCollider(ObjLightswitch* this, GlobalContext* globalCtx)
s32 pad;
// Initialize this with the sun switch, so it can't be affected by toggling while the actor is loaded
sunLightArrowsEnabledOnSunSwitchLoad = (CVar_GetS32("gSunlightArrows", 0));
sunLightArrowsEnabledOnSunSwitchLoad = CVar_GetS32("gSunlightArrows", 0) || (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SUNLIGHT_ARROWS));
Collider_InitJntSph(globalCtx, &this->collider);
// If "Sunlight Arrows" is enabled, set up the collider to allow Light Arrow hits
@@ -135,6 +135,27 @@ void ObjectKankyo_Init(Actor* thisx, GlobalContext* globalCtx) {
this->effects[5].size = 0.0f;
}
if (gSaveContext.n64ddFlag) {
if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_FOREST_TRIAL)) {
this->effects[0].size = 0.0f;
}
if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_WATER_TRIAL)) {
this->effects[1].size = 0.0f;
}
if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_SHADOW_TRIAL)) {
this->effects[2].size = 0.0f;
}
if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_FIRE_TRIAL)) {
this->effects[3].size = 0.0f;
}
if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_LIGHT_TRIAL)) {
this->effects[4].size = 0.0f;
}
if (Flags_GetRandomizerInf(RAND_INF_TRIALS_DONE_SPIRIT_TRIAL)) {
this->effects[5].size = 0.0f;
}
}
if (gSaveContext.cutsceneTrigger != 0) {
if (gSaveContext.entranceIndex == 0x0538) {
this->effects[0].size = 0.1f;
@@ -4670,10 +4670,11 @@ void func_8083A434(GlobalContext* globalCtx, Player* this) {
if (this->getItemId == GI_HEART_CONTAINER_2) {
this->unk_850 = 20;
} else if (this->getItemId >= 0) {
} else if (this->getItemId >= 0 || (this->getItemEntry.objectId != OBJECT_INVALID && this->getItemEntry.getItemId >= 0)) {
this->unk_850 = 1;
} else {
this->getItemId = -this->getItemId;
this->getItemEntry.getItemId = -this->getItemEntry.getItemId;
}
}
@@ -6153,8 +6154,7 @@ void func_8083E4C4(GlobalContext* globalCtx, Player* this, GetItemEntry* giEntry
} else {
Item_Give(globalCtx, giEntry->itemId);
}
func_80078884((this->getItemId < 0) ? NA_SE_SY_GET_BOXITEM : NA_SE_SY_GET_ITEM);
func_80078884((this->getItemId < 0 || this->getItemEntry.getItemId < 0) ? NA_SE_SY_GET_BOXITEM : NA_SE_SY_GET_ITEM);
}
// Sets a flag according to which type of flag is specified in player->pendingFlag.flagType
@@ -6173,6 +6173,9 @@ void Player_SetPendingFlag(Player* this, GlobalContext* globalCtx) {
case FLAG_SCENE_TREASURE:
Flags_SetTreasure(globalCtx, this->pendingFlag.flagID);
break;
case FLAG_RANDOMIZER_INF:
Flags_SetRandomizerInf(this->pendingFlag.flagID);
break;
case FLAG_EVENT_CHECK_INF:
Flags_SetEventChkInf(this->pendingFlag.flagID);
break;
@@ -6187,6 +6190,16 @@ void Player_SetPendingFlag(Player* this, GlobalContext* globalCtx) {
s32 func_8083E5A8(Player* this, GlobalContext* globalCtx) {
Actor* interactedActor;
if(gSaveContext.pendingIceTrapCount) {
gSaveContext.pendingIceTrapCount--;
this->stateFlags1 &= ~(PLAYER_STATE1_10 | PLAYER_STATE1_11);
this->actor.colChkInfo.damage = 0;
func_80837C0C(globalCtx, this, 3, 0.0f, 0.0f, 0, 20);
this->getItemId = GI_NONE;
this->getItemEntry = (GetItemEntry) GET_ITEM_NONE;
return 1;
}
if (iREG(67) || (((interactedActor = this->interactRangeActor) != NULL) &&
func_8002D53C(globalCtx, &globalCtx->actorCtx.titleCtx))) {
if (iREG(67) || (this->getItemId > GI_NONE)) {
@@ -6207,14 +6220,17 @@ s32 func_8083E5A8(Player* this, GlobalContext* globalCtx) {
iREG(67) = false;
if (gSaveContext.n64ddFlag && this->getItemId == RG_ICE_TRAP) {
this->stateFlags1 &= ~(PLAYER_STATE1_10 | PLAYER_STATE1_11);
this->actor.colChkInfo.damage = 0;
func_80837C0C(globalCtx, this, 3, 0.0f, 0.0f, 0, 20);
Player_SetPendingFlag(this, globalCtx);
this->getItemId == GI_NONE;
this->getItemEntry = (GetItemEntry)GET_ITEM_NONE;
return 1;
if (gSaveContext.n64ddFlag && giEntry.getItemId == RG_ICE_TRAP) {
if (giEntry.getItemFrom == ITEM_FROM_FREESTANDING) {
// RANDOTODO: Abstract this to a function.
this->stateFlags1 &= ~(PLAYER_STATE1_10 | PLAYER_STATE1_11);
this->actor.colChkInfo.damage = 0;
func_80837C0C(globalCtx, this, 3, 0.0f, 0.0f, 0, 20);
Player_SetPendingFlag(this, globalCtx);
this->getItemId = GI_NONE;
this->getItemEntry = (GetItemEntry) GET_ITEM_NONE;
return 1;
}
}
s32 drop = giEntry.objectId;
@@ -9674,7 +9690,7 @@ void func_808473D4(GlobalContext* globalCtx, Player* this) {
} else if ((!(this->stateFlags1 & PLAYER_STATE1_11) || (heldActor == NULL)) &&
(interactRangeActor != NULL) &&
((!sp1C && (this->getItemId == GI_NONE)) ||
((this->getItemId < 0) && !(this->stateFlags1 & PLAYER_STATE1_27)))) {
(this->getItemId < 0 && !(this->stateFlags1 & PLAYER_STATE1_27)))) {
if (this->getItemId < 0) {
doAction = DO_ACTION_OPEN;
} else if ((interactRangeActor->id == ACTOR_BG_TOKI_SWD) && LINK_IS_ADULT) {
@@ -12458,81 +12474,55 @@ s32 func_8084DFF4(GlobalContext* globalCtx, Player* this) {
}
this->unk_84F = 1;
// make sure we get the BGS instead of giant's knife
if (this->getItemId == GI_SWORD_BGS) {
gSaveContext.bgsFlag = 1;
gSaveContext.swordHealth = 8;
}
Message_StartTextbox(globalCtx, giEntry.textId, &this->actor);
if (giEntry.modIndex == MOD_NONE) {
Item_Give(globalCtx, giEntry.itemId);
} else {
Randomizer_Item_Give(globalCtx, giEntry);
}
Player_SetPendingFlag(this, globalCtx);
if (this->getItemEntry.objectId == OBJECT_INVALID) {
// Use this if player does not have a getItemEntry
// RANDOTODO: Macro this boolean check.
if (!(giEntry.modIndex == MOD_RANDOMIZER && giEntry.itemId == RG_ICE_TRAP)) {
if (giEntry.modIndex == MOD_NONE) {
if (((this->getItemId >= GI_RUPEE_GREEN) && (this->getItemId <= GI_RUPEE_RED)) ||
((this->getItemId >= GI_RUPEE_PURPLE) && (this->getItemId <= GI_RUPEE_GOLD)) ||
((this->getItemId >= GI_RUPEE_GREEN_LOSE) && (this->getItemId <= GI_RUPEE_PURPLE_LOSE)) ||
(this->getItemId == GI_HEART)) {
Audio_PlaySoundGeneral(NA_SE_SY_GET_BOXITEM, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
} else {
if ((this->getItemId == GI_HEART_CONTAINER_2) || (this->getItemId == GI_HEART_CONTAINER) ||
((this->getItemId == GI_HEART_PIECE) &&
((gSaveContext.inventory.questItems & 0xF0000000) == 0x40000000))) {
temp1 = NA_BGM_HEART_GET | 0x900;
} else {
temp1 = temp2 =
(this->getItemId == GI_HEART_PIECE) ? NA_BGM_SMALL_ITEM_GET : NA_BGM_ITEM_GET | 0x900;
}
Audio_PlayFanfare(temp1);
// RANDOTOD: Move this into Item_Give() or some other more central location
if (giEntry.getItemId == GI_SWORD_BGS) {
gSaveContext.bgsFlag = true;
gSaveContext.swordHealth = 8;
}
} else if (giEntry.modIndex == MOD_RANDOMIZER) {
if (this->getItemId == RG_DOUBLE_DEFENSE || this->getItemId == RG_MAGIC_SINGLE ||
this->getItemId == RG_MAGIC_DOUBLE) {
Audio_PlayFanfare(NA_BGM_HEART_GET | 0x900);
Item_Give(globalCtx, giEntry.itemId);
} else {
Randomizer_Item_Give(globalCtx, giEntry);
}
Player_SetPendingFlag(this, globalCtx);
}
// Use this if we do have a getItemEntry
if (giEntry.modIndex == MOD_NONE) {
if (gSaveContext.n64ddFlag) {
Audio_PlayFanfare_Rando(giEntry);
} else if (((giEntry.itemId >= ITEM_RUPEE_GREEN) && (giEntry.itemId <= ITEM_RUPEE_RED)) ||
((giEntry.itemId >= ITEM_RUPEE_PURPLE) && (giEntry.itemId <= ITEM_RUPEE_GOLD)) ||
(giEntry.itemId == ITEM_HEART)) {
Audio_PlaySoundGeneral(NA_SE_SY_GET_BOXITEM, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
} else {
if ((giEntry.itemId == ITEM_HEART_CONTAINER) ||
((giEntry.itemId == ITEM_HEART_PIECE) &&
((gSaveContext.inventory.questItems & 0xF0000000) == 0x40000000))) {
temp1 = NA_BGM_HEART_GET | 0x900;
} else {
Audio_PlayFanfare(NA_BGM_ITEM_GET | 0x900);
temp1 = temp2 =
(giEntry.itemId == ITEM_HEART_PIECE) ? NA_BGM_SMALL_ITEM_GET : NA_BGM_ITEM_GET | 0x900;
}
Audio_PlayFanfare(temp1);
}
} else if (giEntry.modIndex == MOD_RANDOMIZER) {
if (gSaveContext.n64ddFlag) {
Audio_PlayFanfare_Rando(giEntry);
} else if (giEntry.itemId == RG_DOUBLE_DEFENSE || giEntry.itemId == RG_MAGIC_SINGLE ||
giEntry.itemId == RG_MAGIC_DOUBLE) {
Audio_PlayFanfare(NA_BGM_HEART_GET | 0x900);
} else {
// Just in case something weird happens with MOD_INDEX
Audio_PlayFanfare(NA_BGM_ITEM_GET | 0x900);
}
} else {
// Use this if we do have a getItemEntry
if (giEntry.modIndex == MOD_NONE) {
if (((giEntry.itemId >= ITEM_RUPEE_GREEN) && (giEntry.itemId <= ITEM_RUPEE_RED)) ||
((giEntry.itemId >= ITEM_RUPEE_PURPLE) && (giEntry.itemId <= ITEM_RUPEE_GOLD)) ||
(giEntry.itemId == ITEM_HEART)) {
Audio_PlaySoundGeneral(NA_SE_SY_GET_BOXITEM, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
} else {
if ((giEntry.itemId == ITEM_HEART_CONTAINER) ||
((giEntry.itemId == ITEM_HEART_PIECE) &&
((gSaveContext.inventory.questItems & 0xF0000000) == 0x40000000))) {
temp1 = NA_BGM_HEART_GET | 0x900;
} else {
temp1 = temp2 =
(giEntry.itemId == ITEM_HEART_PIECE) ? NA_BGM_SMALL_ITEM_GET : NA_BGM_ITEM_GET | 0x900;
}
Audio_PlayFanfare(temp1);
}
} else if (giEntry.modIndex == MOD_RANDOMIZER) {
if (giEntry.itemId == RG_DOUBLE_DEFENSE || giEntry.itemId == RG_MAGIC_SINGLE ||
giEntry.itemId == RG_MAGIC_DOUBLE) {
Audio_PlayFanfare(NA_BGM_HEART_GET | 0x900);
} else {
Audio_PlayFanfare(NA_BGM_ITEM_GET | 0x900);
}
} else {
// Just in case something weird happens with modIndex.
Audio_PlayFanfare(NA_BGM_ITEM_GET | 0x900);
}
// Just in case something weird happens with modIndex.
Audio_PlayFanfare(NA_BGM_ITEM_GET | 0x900);
}
// this->getItemEntry = (GetItemEntry)GET_ITEM_NONE;
} else {
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CLOSING) {
if (this->getItemId == GI_GAUNTLETS_SILVER && !gSaveContext.n64ddFlag) {
@@ -12543,6 +12533,20 @@ s32 func_8084DFF4(GlobalContext* globalCtx, Player* this) {
this->stateFlags1 &= ~PLAYER_STATE1_29;
func_80852FFC(globalCtx, NULL, 8);
}
// Set unk_862 to 0 early to not have the game draw non-custom colored models for a split second.
// This unk is what the game normally uses to decide what item to draw when holding up an item above Link's head.
// Only do this when the item actually has a custom draw function.
if (this->getItemEntry.drawFunc != NULL) {
this->unk_862 = 0;
}
if (this->getItemEntry.itemId == RG_ICE_TRAP && this->getItemEntry.modIndex == MOD_RANDOMIZER) {
this->unk_862 = 0;
gSaveContext.pendingIceTrapCount++;
Player_SetPendingFlag(this, globalCtx);
}
this->getItemId = GI_NONE;
this->getItemEntry = (GetItemEntry)GET_ITEM_NONE;
}
@@ -12701,18 +12705,18 @@ void func_8084E6D4(Player* this, GlobalContext* globalCtx) {
func_80832DBC(this);
if ((this->getItemId == GI_ICE_TRAP && !gSaveContext.n64ddFlag) ||
(gSaveContext.n64ddFlag && this->getItemId == RG_ICE_TRAP)) {
(gSaveContext.n64ddFlag && (this->getItemId == RG_ICE_TRAP || this->getItemEntry.getItemId == RG_ICE_TRAP))) {
this->stateFlags1 &= ~(PLAYER_STATE1_10 | PLAYER_STATE1_11);
if ((this->getItemId != GI_ICE_TRAP && !gSaveContext.n64ddFlag) ||
(gSaveContext.n64ddFlag && this->getItemId != RG_ICE_TRAP)) {
(gSaveContext.n64ddFlag && (this->getItemId != RG_ICE_TRAP || this->getItemEntry.getItemId != RG_ICE_TRAP))) {
Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_CLEAR_TAG, this->actor.world.pos.x,
this->actor.world.pos.y + 100.0f, this->actor.world.pos.z, 0, 0, 0, 0);
func_8083C0E8(this, globalCtx);
} else {
this->actor.colChkInfo.damage = 0;
func_80837C0C(globalCtx, this, 3, 0.0f, 0.0f, 0, 20);
this->getItemId == GI_NONE;
this->getItemId = GI_NONE;
this->getItemEntry = (GetItemEntry)GET_ITEM_NONE;
}
return;
@@ -433,7 +433,9 @@ void FileChoose_UpdateMainMenu(GameState* thisx) {
const char* fileLoc = CVar_GetString("gSpoilerLog", "");
Randomizer_LoadSettings(fileLoc);
Randomizer_LoadHintLocations(fileLoc);
Randomizer_LoadRequiredTrials(fileLoc);
Randomizer_LoadItemLocations(fileLoc, silent);
Randomizer_LoadMerchantMessages(fileLoc);
fileSelectSpoilerFileLoaded = true;
}
@@ -1728,6 +1730,7 @@ void FileChoose_LoadGame(GameState* thisx) {
Randomizer_LoadSettings("");
Randomizer_LoadHintLocations("");
Randomizer_LoadMerchantMessages("");
Randomizer_LoadItemLocations("", true);
gSaveContext.respawn[0].entranceIndex = -1;
@@ -1,5 +1,7 @@
#include "z_kaleido_scope.h"
#include "textures/parameter_static/parameter_static.h"
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
#include "soh/Enhancements/randomizer/randomizerTypes.h"
u8 gAmmoItems[] = {
ITEM_STICK, ITEM_NUT, ITEM_BOMB, ITEM_BOW, ITEM_NONE, ITEM_NONE, ITEM_SLINGSHOT, ITEM_NONE,
@@ -10,6 +12,7 @@ static s16 sEquipState = 0;
static s16 sEquipAnimTimer = 0;
static s16 sEquipMoveTimer = 10;
bool gSelectingMask;
bool gSelectingAdultTrade;
static s16 sAmmoVtxOffset[] = {
0, 2, 4, 6, 99, 99, 8, 99, 10, 99, 99, 99, 99, 99, 12,
@@ -109,7 +112,7 @@ void KaleidoScope_DrawItemSelect(GlobalContext* globalCtx) {
pauseCtx->nameColorSet = 0;
if ((pauseCtx->state == 6) && (pauseCtx->unk_1E4 == 0) && (pauseCtx->pageIndex == PAUSE_ITEM)) {
moveCursorResult = 0 || gSelectingMask;
moveCursorResult = 0 || gSelectingMask || gSelectingAdultTrade;
oldCursorPoint = pauseCtx->cursorPoint[PAUSE_ITEM];
cursorItem = pauseCtx->cursorItem[PAUSE_ITEM];
@@ -283,7 +286,7 @@ void KaleidoScope_DrawItemSelect(GlobalContext* globalCtx) {
if (pauseCtx->cursorSpecialPos == 0) {
if (cursorItem != PAUSE_ITEM_NONE) {
if ((ABS(pauseCtx->stickRelY) > 30) || (dpad && CHECK_BTN_ANY(input->press.button, BTN_DDOWN | BTN_DUP))) {
moveCursorResult = 0 || gSelectingMask;
moveCursorResult = 0 || gSelectingMask || gSelectingAdultTrade;
cursorPoint = pauseCtx->cursorPoint[PAUSE_ITEM];
cursorY = pauseCtx->cursorY[PAUSE_ITEM];
@@ -351,8 +354,16 @@ void KaleidoScope_DrawItemSelect(GlobalContext* globalCtx) {
KaleidoScope_SetCursorVtx(pauseCtx, index, pauseCtx->itemVtx);
if ((pauseCtx->debugState == 0) && (pauseCtx->state == 6) && (pauseCtx->unk_1E4 == 0)) {
if (CVar_GetS32("gMaskSelect", 0) && (gSaveContext.eventChkInf[8] & 0x8000) &&
cursorSlot == SLOT_TRADE_CHILD && CHECK_BTN_ALL(input->press.button, BTN_A)) {
// only allow mask select when:
// the shop is open:
// * zelda's letter check: gSaveContext.eventChkInf[4] & 1
// * kak gate check: gSaveContext.infTable[7] & 0x40
// and the mask quest is complete: gSaveContext.eventChkInf[8] & 0x8000
if (CVar_GetS32("gMaskSelect", 0) &&
(gSaveContext.eventChkInf[8] & 0x8000) &&
cursorSlot == SLOT_TRADE_CHILD && CHECK_BTN_ALL(input->press.button, BTN_A) &&
(gSaveContext.eventChkInf[4] & 1) &&
(gSaveContext.infTable[7] & 0x40)) {
Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
gSelectingMask = !gSelectingMask;
}
@@ -370,7 +381,11 @@ void KaleidoScope_DrawItemSelect(GlobalContext* globalCtx) {
--INV_CONTENT(ITEM_TRADE_CHILD);
} else if ((pauseCtx->stickRelX < -30 || pauseCtx->stickRelX > 30 || pauseCtx->stickRelY < -30 || pauseCtx->stickRelY > 30) ||
dpad && CHECK_BTN_ANY(input->press.button, BTN_DUP | BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT)) {
INV_CONTENT(ITEM_TRADE_CHILD) ^= ITEM_MASK_KEATON ^ ITEM_MASK_TRUTH;
if (INV_CONTENT(ITEM_TRADE_CHILD) == ITEM_LETTER_ZELDA) {
INV_CONTENT(ITEM_TRADE_CHILD) = ITEM_MASK_KEATON;
} else {
INV_CONTENT(ITEM_TRADE_CHILD) ^= ITEM_MASK_KEATON ^ ITEM_MASK_TRUTH;
}
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
}
for (uint16_t cSlotIndex = 0; cSlotIndex < ARRAY_COUNT(gSaveContext.equips.cButtonSlots); cSlotIndex++) {
@@ -385,6 +400,24 @@ void KaleidoScope_DrawItemSelect(GlobalContext* globalCtx) {
}
gSelectingMask = cursorSlot == SLOT_TRADE_CHILD;
}
if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE) &&
cursorSlot == SLOT_TRADE_ADULT && CHECK_BTN_ALL(input->press.button, BTN_A)) {
Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
gSelectingAdultTrade = !gSelectingAdultTrade;
}
if (gSelectingAdultTrade) {
pauseCtx->cursorColorSet = 8;
if (((pauseCtx->stickRelX > 30 || pauseCtx->stickRelY > 30) ||
dpad && CHECK_BTN_ANY(input->press.button, BTN_DRIGHT | BTN_DUP))) {
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Inventory_ReplaceItem(globalCtx, INV_CONTENT(ITEM_TRADE_ADULT), Randomizer_GetNextAdultTradeItem());
} else if (((pauseCtx->stickRelX < -30 || pauseCtx->stickRelY < -30) ||
dpad && CHECK_BTN_ANY(input->press.button, BTN_DLEFT | BTN_DDOWN))) {
Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
Inventory_ReplaceItem(globalCtx, INV_CONTENT(ITEM_TRADE_ADULT), Randomizer_GetPrevAdultTradeItem());
}
gSelectingAdultTrade = cursorSlot == SLOT_TRADE_ADULT;
}
u16 buttonsToCheck = BTN_CLEFT | BTN_CDOWN | BTN_CRIGHT;
if (CVar_GetS32("gDpadEquips", 0) && (!CVar_GetS32("gDpadPause", 0) || CHECK_BTN_ALL(input->cur.button, BTN_CUP))) {
buttonsToCheck |= BTN_DUP | BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT;
@@ -510,6 +543,7 @@ void KaleidoScope_SetupItemEquip(GlobalContext* globalCtx, u16 item, u16 slot, s
Input* input = &globalCtx->state.input[0];
PauseContext* pauseCtx = &globalCtx->pauseCtx;
gSelectingMask = false;
gSelectingAdultTrade = false;
if (CHECK_BTN_ALL(input->press.button, BTN_CLEFT)) {
pauseCtx->equipTargetCBtn = 0;