Randomizer: Fixes LACS and Prelude checks under certain conditions (#961)

* Prevents LACS flag from getting set when it shouldn't be.

* Fixes Prelude and LACS checks so they apply immediately if missed.

* Refactors the scene-flag-setting code into its own function.

* Renames new enums and props to be clearer and not specific to scene flags.

* Refactors pendingFlag data into a separate struct.
This commit is contained in:
Christopher Leggett 2022-07-31 21:57:30 -04:00 committed by GitHub
parent 8c25e9a992
commit b59c9cdf02
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 51 additions and 6 deletions

View File

@ -356,7 +356,20 @@ typedef struct {
/* 0x00 */ s32 active;
/* 0x04 */ Vec3f tip;
/* 0x10 */ Vec3f base;
} WeaponInfo; // size = 0x1C
} WeaponInfo; // size = 0x1C\
typedef enum {
FLAG_NONE,
FLAG_SCENE_SWITCH,
FLAG_SCENE_TREASURE,
FLAG_SCENE_CLEAR,
FLAG_SCENE_COLLECTIBLE,
} FlagType;
typedef struct {
/* 0x00 */ s32 flagID; // which flag to set when Player_SetPendingFlag is called
/* 0x04 */ FlagType flagType; // type of flag to set when Player_SetPendingFlag is called
} PendingFlag; // size = 0x06
#define PLAYER_STATE1_0 (1 << 0)
#define PLAYER_STATE1_1 (1 << 1)
@ -612,6 +625,7 @@ typedef struct Player {
/* 0x0A86 */ s8 unk_A86;
/* 0x0A87 */ u8 unk_A87;
/* 0x0A88 */ Vec3f unk_A88; // previous body part 0 position
} Player; // size = 0xA94
/* 0x0A94 */ PendingFlag pendingFlag;
} Player; // size = 0xAA0
#endif

View File

@ -237,10 +237,11 @@ void GivePlayerRandoRewardZeldaLightArrowsGift(GlobalContext* globalCtx, Randomi
if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) && LINK_IS_ADULT &&
(gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_TOKINOMA) &&
!Flags_GetTreasure(globalCtx, 0x1E) && player != NULL && !Player_InBlockingCsMode(globalCtx, player) &&
globalCtx->sceneLoadFlag == 0 && player->getItemId == GI_NONE) {
globalCtx->sceneLoadFlag == 0) {
GetItemID getItemId = Randomizer_GetItemIdFromKnownCheck(check, GI_ARROW_LIGHT);
GiveItemWithoutActor(globalCtx, getItemId);
Flags_SetTreasure(globalCtx, 0x1E);
player->pendingFlag.flagID = 0x1E;
player->pendingFlag.flagType = FLAG_SCENE_TREASURE;
}
}

View File

@ -288,14 +288,16 @@ void func_80B3CA38(EnXc* this, GlobalContext* globalCtx) {
}
void GivePlayerRandoRewardSheikSong(EnXc* sheik, GlobalContext* globalCtx, RandomizerCheck check, int sheikType, GetItemID ogSongId) {
if (sheik->actor.parent != NULL && sheik->actor.parent->id == GET_PLAYER(globalCtx)->actor.id &&
Player* player = GET_PLAYER(globalCtx);
if (sheik->actor.parent != NULL && sheik->actor.parent->id == player->actor.id &&
!(gSaveContext.eventChkInf[5] & sheikType)) {
gSaveContext.eventChkInf[5] |= sheikType;
} else if (!(gSaveContext.eventChkInf[5] & sheikType)) {
GetItemID getItemId = Randomizer_GetItemIdFromKnownCheck(check, ogSongId);
if (check == RC_SHEIK_AT_TEMPLE && !Flags_GetTreasure(globalCtx, 0x1F)) {
if (func_8002F434(&sheik->actor, globalCtx, getItemId, 10000.0f, 100.0f)) {
Flags_SetTreasure(globalCtx, 0x1F);
player->pendingFlag.flagID = 0x1F;
player->pendingFlag.flagType = FLAG_SCENE_TREASURE;
}
} else if (check != RC_SHEIK_AT_TEMPLE) {
func_8002F434(&sheik->actor, globalCtx, getItemId, 10000.0f, 100.0f);

View File

@ -167,6 +167,7 @@ void func_8083CA20(GlobalContext* globalCtx, Player* this);
void func_8083CA54(GlobalContext* globalCtx, Player* this);
void func_8083CA9C(GlobalContext* globalCtx, Player* this);
s32 func_8083E0FC(Player* this, GlobalContext* globalCtx);
void Player_SetPendingFlag(Player* this, GlobalContext* globalCtx);
s32 func_8083E5A8(Player* this, GlobalContext* globalCtx);
s32 func_8083EB44(Player* this, GlobalContext* globalCtx);
s32 func_8083F7BC(Player* this, GlobalContext* globalCtx);
@ -6231,6 +6232,30 @@ void func_8083E4C4(GlobalContext* globalCtx, Player* this, GetItemEntry* giEntry
func_80078884((this->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
// and which flag is specified in player->pendingFlag.flagID.
void Player_SetPendingFlag(Player* this, GlobalContext* globalCtx) {
switch (this->pendingFlag.flagType) {
case FLAG_SCENE_CLEAR:
Flags_SetClear(globalCtx, this->pendingFlag.flagID);
break;
case FLAG_SCENE_COLLECTIBLE:
Flags_SetCollectible(globalCtx, this->pendingFlag.flagID);
break;
case FLAG_SCENE_SWITCH:
Flags_SetSwitch(globalCtx, this->pendingFlag.flagID);
break;
case FLAG_SCENE_TREASURE:
Flags_SetTreasure(globalCtx, this->pendingFlag.flagID);
break;
case FLAG_NONE:
default:
break;
}
this->pendingFlag.flagType = FLAG_NONE;
this->pendingFlag.flagID = 0;
}
s32 func_8083E5A8(Player* this, GlobalContext* globalCtx) {
Actor* interactedActor;
@ -6254,6 +6279,7 @@ s32 func_8083E5A8(Player* this, GlobalContext* globalCtx) {
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);
return;
}
@ -12660,6 +12686,8 @@ s32 func_8084DFF4(GlobalContext* globalCtx, Player* this) {
Message_StartTextbox(globalCtx, giEntry->textId, &this->actor);
Item_Give(globalCtx, giEntry->itemId);
Player_SetPendingFlag(this, globalCtx);
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)) ||