mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-01-30 23:10:14 -05:00
Vanilla Behavior Overhaul
Co-authored-by: jordanpg <jordanpg@users.noreply.github.com>
This commit is contained in:
parent
fe9dcf1fc3
commit
596ea5ebbb
@ -183,6 +183,8 @@ void __osSetWatchLo(u32);
|
|||||||
EnItem00* Item_DropCollectible(PlayState* play, Vec3f* spawnPos, s16 params);
|
EnItem00* Item_DropCollectible(PlayState* play, Vec3f* spawnPos, s16 params);
|
||||||
EnItem00* Item_DropCollectible2(PlayState* play, Vec3f* spawnPos, s16 params);
|
EnItem00* Item_DropCollectible2(PlayState* play, Vec3f* spawnPos, s16 params);
|
||||||
void EnItem00_CustomItemsParticles(Actor* Parent, PlayState* play, GetItemEntry giEntry);
|
void EnItem00_CustomItemsParticles(Actor* Parent, PlayState* play, GetItemEntry giEntry);
|
||||||
|
void EnItem00_SetupAction(EnItem00* this, EnItem00ActionFunc actionFunc);
|
||||||
|
void func_8001E5C8(EnItem00* this, PlayState* play);
|
||||||
void Item_DropCollectibleRandom(PlayState* play, Actor* fromActor, Vec3f* spawnPos, s16 params);
|
void Item_DropCollectibleRandom(PlayState* play, Actor* fromActor, Vec3f* spawnPos, s16 params);
|
||||||
void EffectBlure_ChangeType(EffectBlure* this, int type);
|
void EffectBlure_ChangeType(EffectBlure* this, int type);
|
||||||
void EffectBlure_AddVertex(EffectBlure* this, Vec3f* p1, Vec3f* p2);
|
void EffectBlure_AddVertex(EffectBlure* this, Vec3f* p1, Vec3f* p2);
|
||||||
@ -415,6 +417,7 @@ f32 Actor_WorldDistXZToPoint(Actor* actor, Vec3f* refPoint);
|
|||||||
void func_8002DBD0(Actor* actor, Vec3f* result, Vec3f* arg2);
|
void func_8002DBD0(Actor* actor, Vec3f* result, Vec3f* arg2);
|
||||||
f32 Actor_HeightDiff(Actor* actorA, Actor* actorB);
|
f32 Actor_HeightDiff(Actor* actorA, Actor* actorB);
|
||||||
f32 Player_GetHeight(Player* player);
|
f32 Player_GetHeight(Player* player);
|
||||||
|
s32 func_8083E5A8(Player* player, PlayState* play);
|
||||||
f32 func_8002DCE4(Player* player);
|
f32 func_8002DCE4(Player* player);
|
||||||
s32 func_8002DD6C(Player* player);
|
s32 func_8002DD6C(Player* player);
|
||||||
s32 func_8002DD78(Player* player);
|
s32 func_8002DD78(Player* player);
|
||||||
@ -1106,6 +1109,7 @@ s32 FrameAdvance_Update(FrameAdvanceContext* frameAdvCtx, Input* input);
|
|||||||
u8 PlayerGrounded(Player* player);
|
u8 PlayerGrounded(Player* player);
|
||||||
void Player_SetBootData(PlayState* play, Player* player);
|
void Player_SetBootData(PlayState* play, Player* player);
|
||||||
s32 Player_InBlockingCsMode(PlayState* play, Player* player);
|
s32 Player_InBlockingCsMode(PlayState* play, Player* player);
|
||||||
|
s32 Player_TryCsAction(PlayState* play, Actor* actor, s32 csAction);
|
||||||
s32 Player_InCsMode(PlayState* play);
|
s32 Player_InCsMode(PlayState* play);
|
||||||
s32 func_8008E9C4(Player* player);
|
s32 func_8008E9C4(Player* player);
|
||||||
s32 Player_IsChildWithHylianShield(Player* player);
|
s32 Player_IsChildWithHylianShield(Player* player);
|
||||||
|
@ -266,7 +266,12 @@ typedef enum {
|
|||||||
/* 0x17 */ ITEM00_TUNIC_ZORA,
|
/* 0x17 */ ITEM00_TUNIC_ZORA,
|
||||||
/* 0x18 */ ITEM00_TUNIC_GORON,
|
/* 0x18 */ ITEM00_TUNIC_GORON,
|
||||||
/* 0x19 */ ITEM00_BOMBS_SPECIAL,
|
/* 0x19 */ ITEM00_BOMBS_SPECIAL,
|
||||||
/* 0x20 */ ITEM00_BOMBCHU,
|
/* 0x1A */ ITEM00_BOMBCHU,
|
||||||
|
/* 0x1B */ ITEM00_SOH_DUMMY,
|
||||||
|
/* 0x1C */ ITEM00_SOH_GIVE_ITEM_ENTRY,
|
||||||
|
/* 0x1D */ ITEM00_SOH_GIVE_ITEM_ENTRY_GI,
|
||||||
|
/* 0x1E */ ITEM00_MAX,
|
||||||
|
/* 0xFF */ ITEM00_NONE = 0xFF
|
||||||
} Item00Type;
|
} Item00Type;
|
||||||
|
|
||||||
struct EnItem00;
|
struct EnItem00;
|
||||||
@ -284,10 +289,13 @@ typedef struct EnItem00 {
|
|||||||
/* 0x15A */ s16 unk_15A;
|
/* 0x15A */ s16 unk_15A;
|
||||||
/* 0x15C */ f32 scale;
|
/* 0x15C */ f32 scale;
|
||||||
/* 0x160 */ ColliderCylinder collider;
|
/* 0x160 */ ColliderCylinder collider;
|
||||||
s16 ogParams;
|
// #region SOH [Randomizer]
|
||||||
GetItemEntry randoGiEntry;
|
GetItemEntry randoGiEntry;
|
||||||
RandomizerCheck randoCheck;
|
RandomizerCheck randoCheck;
|
||||||
RandomizerInf randoInf;
|
RandomizerInf randoInf;
|
||||||
|
/* */ s16 ogParams;
|
||||||
|
/* */ GetItemEntry itemEntry;
|
||||||
|
// #endregion
|
||||||
} EnItem00; // size = 0x1AC
|
} EnItem00; // size = 0x1AC
|
||||||
|
|
||||||
// Only A_OBJ_SIGNPOST_OBLONG and A_OBJ_SIGNPOST_ARROW are used in room files.
|
// Only A_OBJ_SIGNPOST_OBLONG and A_OBJ_SIGNPOST_ARROW are used in room files.
|
||||||
|
@ -505,6 +505,7 @@ const std::vector<FlagTable> flagTables = {
|
|||||||
{ RAND_INF_CHILD_FISHING, "RAND_INF_CHILD_FISHING" },
|
{ RAND_INF_CHILD_FISHING, "RAND_INF_CHILD_FISHING" },
|
||||||
{ RAND_INF_ADULT_FISHING, "RAND_INF_ADULT_FISHING" },
|
{ RAND_INF_ADULT_FISHING, "RAND_INF_ADULT_FISHING" },
|
||||||
{ RAND_INF_10_BIG_POES, "RAND_INF_10_BIG_POES" },
|
{ RAND_INF_10_BIG_POES, "RAND_INF_10_BIG_POES" },
|
||||||
|
{ RAND_INF_GRANT_GANONS_BOSSKEY, "RAND_INF_GRANT_GANONS_BOSSKEY" },
|
||||||
|
|
||||||
{ RAND_INF_GOHMA_SOUL, "RAND_INF_GOHMA_SOUL" },
|
{ RAND_INF_GOHMA_SOUL, "RAND_INF_GOHMA_SOUL" },
|
||||||
{ RAND_INF_KING_DODONGO_SOUL, "RAND_INF_KING_DODONGO_SOUL" },
|
{ RAND_INF_KING_DODONGO_SOUL, "RAND_INF_KING_DODONGO_SOUL" },
|
||||||
@ -515,7 +516,6 @@ const std::vector<FlagTable> flagTables = {
|
|||||||
{ RAND_INF_BONGO_BONGO_SOUL, "RAND_INF_BONGO_BONGO_SOUL" },
|
{ RAND_INF_BONGO_BONGO_SOUL, "RAND_INF_BONGO_BONGO_SOUL" },
|
||||||
{ RAND_INF_TWINROVA_SOUL, "RAND_INF_TWINROVA_SOUL" },
|
{ RAND_INF_TWINROVA_SOUL, "RAND_INF_TWINROVA_SOUL" },
|
||||||
{ RAND_INF_GANON_SOUL, "RAND_INF_GANON_SOUL" },
|
{ RAND_INF_GANON_SOUL, "RAND_INF_GANON_SOUL" },
|
||||||
{ RAND_INF_GRANT_GANONS_BOSSKEY, "RAND_INF_GRANT_GANONS_BOSSKEY" },
|
|
||||||
|
|
||||||
{ RAND_INF_HAS_OCARINA_A, "RAND_INF_HAS_OCARINA_A"},
|
{ RAND_INF_HAS_OCARINA_A, "RAND_INF_HAS_OCARINA_A"},
|
||||||
{ RAND_INF_HAS_OCARINA_C_UP, "RAND_INF_HAS_OCARINA_C_UP" },
|
{ RAND_INF_HAS_OCARINA_C_UP, "RAND_INF_HAS_OCARINA_C_UP" },
|
||||||
@ -607,7 +607,11 @@ const std::vector<FlagTable> flagTables = {
|
|||||||
{ RAND_INF_ZD_FISH_2, "RAND_INF_ZD_FISH_2" },
|
{ RAND_INF_ZD_FISH_2, "RAND_INF_ZD_FISH_2" },
|
||||||
{ RAND_INF_ZD_FISH_3, "RAND_INF_ZD_FISH_3" },
|
{ RAND_INF_ZD_FISH_3, "RAND_INF_ZD_FISH_3" },
|
||||||
{ RAND_INF_ZD_FISH_4, "RAND_INF_ZD_FISH_4" },
|
{ RAND_INF_ZD_FISH_4, "RAND_INF_ZD_FISH_4" },
|
||||||
{ RAND_INF_ZD_FISH_5, "RAND_INF_ZD_FISH_5" }
|
{ RAND_INF_ZD_FISH_5, "RAND_INF_ZD_FISH_5" },
|
||||||
|
|
||||||
|
{ RAND_INF_LINKS_POCKET, "RAND_INF_LINKS_POCKET" },
|
||||||
|
{ RAND_INF_LEARNED_EPONA_SONG, "RAND_INF_LEARNED_EPONA_SONG" },
|
||||||
|
{ RAND_INF_DARUNIAS_JOY, "RAND_INF_DARUNIAS_JOY" },
|
||||||
} },
|
} },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -34,6 +34,8 @@ std::vector<ValueTableElement> valueTable = {
|
|||||||
{ "Text ID", "play->msgCtx.textId", "TEXTID:", TYPE_U16, true, []() -> void* { return &gPlayState->msgCtx.textId; }, WHITE },
|
{ "Text ID", "play->msgCtx.textId", "TEXTID:", TYPE_U16, true, []() -> void* { return &gPlayState->msgCtx.textId; }, WHITE },
|
||||||
{ "Analog Stick X", "play->state.input->cur.stick_x", "AX:", TYPE_S8, true, []() -> void* { return &gPlayState->state.input->cur.stick_x; }, WHITE },
|
{ "Analog Stick X", "play->state.input->cur.stick_x", "AX:", TYPE_S8, true, []() -> void* { return &gPlayState->state.input->cur.stick_x; }, WHITE },
|
||||||
{ "Analog Stick Y", "play->state.input->cur.stick_y", "AY:", TYPE_S8, true, []() -> void* { return &gPlayState->state.input->cur.stick_y; }, WHITE },
|
{ "Analog Stick Y", "play->state.input->cur.stick_y", "AY:", TYPE_S8, true, []() -> void* { return &gPlayState->state.input->cur.stick_y; }, WHITE },
|
||||||
|
{ "getItemID", "Player->getItemId", "ITEM:", TYPE_S16, true, []() -> void* { return &GET_PLAYER(gPlayState)->getItemId; }, WHITE },
|
||||||
|
{ "getItemEntry", "Player->getItemEntry", "IE:", TYPE_S16, true, []() -> void* { return &GET_PLAYER(gPlayState)->getItemEntry.itemId; }, WHITE },
|
||||||
/* TODO: Find these (from GZ)
|
/* TODO: Find these (from GZ)
|
||||||
"XZ Units Traveled (Camera based speed variable)" f32 0x801C9018
|
"XZ Units Traveled (Camera based speed variable)" f32 0x801C9018
|
||||||
"Movement Angle" x16 0x801DBB1C
|
"Movement Angle" x16 0x801DBB1C
|
||||||
|
@ -14,6 +14,13 @@ typedef enum {
|
|||||||
CSMC_SIZE
|
CSMC_SIZE
|
||||||
} ChestStyleMatchesContentsType;
|
} ChestStyleMatchesContentsType;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SGIA_DISABLED,
|
||||||
|
SGIA_JUNK,
|
||||||
|
SGIA_ALL,
|
||||||
|
SGIA_SIZE
|
||||||
|
} SkipGetItemAnimationType;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
BUNNY_HOOD_VANILLA,
|
BUNNY_HOOD_VANILLA,
|
||||||
BUNNY_HOOD_FAST_AND_JUMP,
|
BUNNY_HOOD_FAST_AND_JUMP,
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#ifndef GameInteractor_h
|
#ifndef GameInteractor_h
|
||||||
#define GameInteractor_h
|
#define GameInteractor_h
|
||||||
|
|
||||||
|
#include "libultraship/libultraship.h"
|
||||||
#include "GameInteractionEffect.h"
|
#include "GameInteractionEffect.h"
|
||||||
#include "soh/Enhancements/item-tables/ItemTableTypes.h"
|
#include "soh/Enhancements/item-tables/ItemTableTypes.h"
|
||||||
#include <z64.h>
|
#include <z64.h>
|
||||||
@ -67,6 +68,272 @@ typedef enum {
|
|||||||
/* */ GI_TP_DEST_PRELUDE = ENTR_TEMPLE_OF_TIME_7,
|
/* */ GI_TP_DEST_PRELUDE = ENTR_TEMPLE_OF_TIME_7,
|
||||||
} GITeleportDestinations;
|
} GITeleportDestinations;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
// Vanilla condition: gSaveContext.showTitleCard
|
||||||
|
GI_VB_SHOW_TITLE_CARD,
|
||||||
|
// Opt: *EnWonderTalk2
|
||||||
|
GI_VB_WONDER_TALK,
|
||||||
|
// Opt: *ElfMsg
|
||||||
|
GI_VB_NAVI_TALK,
|
||||||
|
// Vanilla condition: INFTABLE_GREETED_BY_SARIA
|
||||||
|
GI_VB_NOT_BE_GREETED_BY_SARIA,
|
||||||
|
// Opt: *EnMd
|
||||||
|
// Vanilla condition: EnMd->interactInfo.talkState == NPC_TALK_STATE_ACTION
|
||||||
|
GI_VB_MOVE_MIDO_IN_KOKIRI_FOREST,
|
||||||
|
// Opt: *EnMd
|
||||||
|
// Vanilla condition: CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)
|
||||||
|
GI_VB_MIDO_CONSIDER_DEKU_TREE_DEAD,
|
||||||
|
// Opt: *EnKo
|
||||||
|
// Vanilla condition: CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)
|
||||||
|
GI_VB_OPEN_KOKIRI_FOREST,
|
||||||
|
// Opt: *EnOwl
|
||||||
|
// Vanilla condition: EnOwl->actor.xzDistToPlayer < targetDist
|
||||||
|
GI_VB_OWL_INTERACTION,
|
||||||
|
// Vanilla condition: EVENTCHKINF_TALON_RETURNED_FROM_CASTLE
|
||||||
|
GI_VB_MALON_RETURN_FROM_CASTLE,
|
||||||
|
// Vanilla condition: CUR_UPG_VALUE(UPG_STRENGTH) <= 0
|
||||||
|
GI_VB_BE_ELIGIBLE_FOR_DARUNIAS_JOY_REWARD,
|
||||||
|
/* Vanilla condition:
|
||||||
|
```
|
||||||
|
LINK_IS_ADULT &&
|
||||||
|
(gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_TEMPLE_OF_TIME) &&
|
||||||
|
CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) &&
|
||||||
|
CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) &&
|
||||||
|
!Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS);
|
||||||
|
```
|
||||||
|
*/
|
||||||
|
GI_VB_BE_ELIGIBLE_FOR_LIGHT_ARROWS,
|
||||||
|
// Vanilla condition: !CHECK_QUEST_ITEM(QUEST_SONG_SARIA)
|
||||||
|
GI_VB_BE_ELIGIBLE_FOR_SARIAS_SONG,
|
||||||
|
// Vanilla condition: CHECK_QUEST_ITEM(QUEST_SONG_EPONA)
|
||||||
|
GI_VB_MALON_ALREADY_TAUGHT_EPONAS_SONG,
|
||||||
|
// Vanilla condition: CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER)
|
||||||
|
GI_VB_BE_ELIGIBLE_FOR_SERENADE_OF_WATER,
|
||||||
|
// Vanilla condition: (!CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER)) && LINK_IS_ADULT
|
||||||
|
GI_VB_SHIEK_PREPARE_TO_GIVE_SERENADE_OF_WATER,
|
||||||
|
// Vanilla condition: !EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT and EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP
|
||||||
|
GI_VB_BE_ELIGIBLE_FOR_PRELUDE_OF_LIGHT,
|
||||||
|
/* Vanilla Condition:
|
||||||
|
```
|
||||||
|
LINK_IS_ADULT &&
|
||||||
|
gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_0 &&
|
||||||
|
Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP) &&
|
||||||
|
Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP) &&
|
||||||
|
Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP) &&
|
||||||
|
!Flags_GetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL);
|
||||||
|
```
|
||||||
|
*/
|
||||||
|
GI_VB_BE_ELIGIBLE_FOR_NOCTURNE_OF_SHADOW,
|
||||||
|
// Opt: *EnGo2
|
||||||
|
// Vanilla condition: CUR_CAPACITY(UPG_BOMB_BAG) >= 20 && this->waypoint > 7 && this->waypoint < 12
|
||||||
|
GI_VB_BE_ELIGIBLE_FOR_CHILD_ROLLING_GORON_REWARD,
|
||||||
|
// Vanilla condition: !CHECK_OWNED_EQUIP_ALT(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_BIGGORON)
|
||||||
|
GI_VB_BE_ELIGIBLE_FOR_GIANTS_KNIFE_PURCHASE,
|
||||||
|
// Opt: *EnMs
|
||||||
|
// Vanilla condition: gSaveContext.rupees >= sPrices[BEANS_BOUGHT]
|
||||||
|
GI_VB_BE_ELIGIBLE_FOR_MAGIC_BEANS_PURCHASE,
|
||||||
|
// Opt: *EnItem00
|
||||||
|
// Vanilla condition: Flags_GetCollectible(play, this->collectibleFlag)
|
||||||
|
GI_VB_ITEM00_DESPAWN,
|
||||||
|
// Opt: *EnTk
|
||||||
|
// Vanilla condition: gSaveContext.dayTime <= 0xC000 || gSaveContext.dayTime >= 0xE000 || LINK_IS_ADULT || play->sceneNum != SCENE_GRAVEYARD
|
||||||
|
GI_VB_DAMPE_IN_GRAVEYARD_DESPAWN,
|
||||||
|
// Opt: *EnTk
|
||||||
|
// Vanilla condition: this->validDigHere == 1
|
||||||
|
GI_VB_BE_VALID_GRAVEDIGGING_SPOT,
|
||||||
|
// Opt: *EnTk
|
||||||
|
// Vanilla condition: this->currentReward == 3
|
||||||
|
GI_VB_BE_DAMPE_GRAVEDIGGING_GRAND_PRIZE,
|
||||||
|
// Opt: *EnTk
|
||||||
|
// Vanilla condition: !Flags_GetItemGetInf(ITEMGETINF_1C)
|
||||||
|
GI_VB_DAMPE_GRAVEDIGGING_GRAND_PRIZE_BE_HEART_PIECE,
|
||||||
|
// Opt: *EnShopnuts
|
||||||
|
/* Vanilla Condition:
|
||||||
|
```
|
||||||
|
((this->actor.params == 0x0002) && (Flags_GetItemGetInf(ITEMGETINF_0B))) ||
|
||||||
|
((this->actor.params == 0x0009) && (Flags_GetInfTable(INFTABLE_192))) ||
|
||||||
|
((this->actor.params == 0x000A) && (Flags_GetInfTable(INFTABLE_193)))
|
||||||
|
```
|
||||||
|
*/
|
||||||
|
GI_VB_BUSINESS_SCRUB_DESPAWN,
|
||||||
|
// Opt: *EnCow
|
||||||
|
// Vanilla condition: play->sceneNum == SCENE_LINKS_HOUSE && (!LINK_IS_ADULT || !Flags_GetEventChkInf(EVENTCHKINF_WON_COW_IN_MALONS_RACE))
|
||||||
|
GI_VB_DESPAWN_HORSE_RACE_COW,
|
||||||
|
// Opt: *EnHs
|
||||||
|
// Vanilla condition: Flags_GetItemGetInf(ITEMGETINF_30)
|
||||||
|
GI_VB_DESPAWN_GROG,
|
||||||
|
// Opt: *EnKo
|
||||||
|
// Vanilla condition: (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_ODD_POTION) ? true : false;
|
||||||
|
GI_VB_SPAWN_LW_FADO,
|
||||||
|
// Opt: *EnMk
|
||||||
|
GI_VB_PLAY_EYEDROP_CREATION_ANIM,
|
||||||
|
// Opt: *EnDs
|
||||||
|
GI_VB_PLAY_ODD_POTION_ANIM,
|
||||||
|
// Opt: *EnMk
|
||||||
|
// Vanilla condition: INV_CONTENT(ITEM_ODD_MUSHROOM) == ITEM_EYEDROPS
|
||||||
|
GI_VB_USE_EYEDROP_DIALOGUE,
|
||||||
|
// Opt: *EnMk
|
||||||
|
// Vanilla condition: Flags_GetItemGetInf(ITEMGETINF_30)
|
||||||
|
GI_VB_OFFER_BLUE_POTION,
|
||||||
|
// Vanilla condition: Inventory_HasEmptyBottle() == 0
|
||||||
|
GI_VB_NEED_BOTTLE_FOR_GRANNYS_ITEM,
|
||||||
|
// Opt: *EnNiwLady
|
||||||
|
GI_VB_SET_CUCCO_COUNT,
|
||||||
|
// Opt: *EnKz
|
||||||
|
// Vanilla condition: CHECK_QUEST_ITEM(QUEST_ZORA_SAPPHIRE)
|
||||||
|
GI_VB_KING_ZORA_THANK_CHILD,
|
||||||
|
// Opt: *EnKz
|
||||||
|
// Vanilla condition: this->actor.textId == 0x401A
|
||||||
|
GI_VB_BE_ABLE_TO_EXCHANGE_RUTOS_LETTER,
|
||||||
|
// Opt: *EnKz
|
||||||
|
// Vanilla condition: Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)
|
||||||
|
GI_VB_KING_ZORA_BE_MOVED,
|
||||||
|
// Vanilla condition: gSaveState.bgsFlag
|
||||||
|
GI_VB_BIGGORON_CONSIDER_TRADE_COMPLETE,
|
||||||
|
// Vanilla condition: gSaveState.bgsFlag
|
||||||
|
GI_VB_BIGGORON_CONSIDER_SWORD_COLLECTED,
|
||||||
|
// Vanilla condition: Environment_GetBgsDayCount() >= 3
|
||||||
|
GI_VB_BIGGORON_CONSIDER_SWORD_FORGED,
|
||||||
|
// Vanilla condition: CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)
|
||||||
|
GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED,
|
||||||
|
// Vanilla condition: CHECK_QUEST_ITEM(QUEST_GORON_RUBY)
|
||||||
|
GI_VB_GORONS_CONSIDER_DODONGOS_CAVERN_FINISHED,
|
||||||
|
// Opt: *uint16_t
|
||||||
|
// Vanilla condition: false
|
||||||
|
GI_VB_OVERRIDE_LINK_THE_GORON_DIALOGUE,
|
||||||
|
// Opt: *EnGo2
|
||||||
|
GI_VB_EN_GO2_RESET_AFTER_GET_ITEM,
|
||||||
|
|
||||||
|
/*** Play Cutscenes ***/
|
||||||
|
|
||||||
|
GI_VB_PLAY_TRANSITION_CS,
|
||||||
|
// Opt: *EventChkInf flag
|
||||||
|
GI_VB_PLAY_ENTRANCE_CS,
|
||||||
|
// Opt: *cutsceneId
|
||||||
|
GI_VB_PLAY_ONEPOINT_CS,
|
||||||
|
// Opt: *actor
|
||||||
|
GI_VB_PLAY_ONEPOINT_ACTOR_CS,
|
||||||
|
// Opt: *BgTreemouth
|
||||||
|
GI_VB_PLAY_DEKU_TREE_INTRO_CS,
|
||||||
|
// Vanilla condition: !EventChkInf except for spirit & shadow temple which are !medallion, and Jabu which always is true
|
||||||
|
GI_VB_PLAY_BLUE_WARP_CS,
|
||||||
|
GI_VB_PLAY_DARUNIAS_JOY_CS,
|
||||||
|
GI_VB_PLAY_SHIEK_BLOCK_MASTER_SWORD_CS,
|
||||||
|
// Vanilla condition: !EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL
|
||||||
|
GI_VB_PLAY_PULL_MASTER_SWORD_CS,
|
||||||
|
GI_VB_PLAY_DROP_FISH_FOR_JABU_CS,
|
||||||
|
// Vanilla condition: player->getItemId == GI_GAUNTLETS_SILVER
|
||||||
|
GI_VB_PLAY_NABOORU_CAPTURED_CS,
|
||||||
|
GI_VB_PLAY_ZELDAS_LULLABY_CS,
|
||||||
|
// Opt: *EnSa
|
||||||
|
GI_VB_PLAY_SARIAS_SONG_CS,
|
||||||
|
GI_VB_PLAY_PRELUDE_OF_LIGHT_CS,
|
||||||
|
GI_VB_PLAY_MINUET_OF_FOREST_CS,
|
||||||
|
GI_VB_PLAY_BOLERO_OF_FIRE_CS,
|
||||||
|
GI_VB_PLAY_SERENADE_OF_WATER_CS,
|
||||||
|
GI_VB_PLAY_EYEDROPS_CS,
|
||||||
|
|
||||||
|
/*** Give Items ***/
|
||||||
|
|
||||||
|
GI_VB_GIVE_ITEM_FROM_CHEST,
|
||||||
|
GI_VB_GIVE_ITEM_FROM_BLUE_WARP,
|
||||||
|
// Opt: *EnItem00
|
||||||
|
GI_VB_GIVE_ITEM_FROM_ITEM_00,
|
||||||
|
// Opt: *EnSi
|
||||||
|
GI_VB_GIVE_ITEM_SKULL_TOKEN,
|
||||||
|
// Opt: *EnCow
|
||||||
|
GI_VB_GIVE_ITEM_FROM_COW,
|
||||||
|
// Opt: *EnDns
|
||||||
|
GI_VB_GIVE_ITEM_FROM_BUSINESS_SCRUB,
|
||||||
|
// Opt: *EnMk
|
||||||
|
GI_VB_GIVE_ITEM_FROM_LAB_DIVE,
|
||||||
|
// Opt: *EnDs
|
||||||
|
GI_VB_GIVE_ITEM_FROM_GRANNYS_SHOP,
|
||||||
|
// Opt: *EnNiwLady
|
||||||
|
GI_VB_GIVE_ITEM_FROM_ANJU_AS_CHILD,
|
||||||
|
// Opt: *EnNiwLady
|
||||||
|
GI_VB_GIVE_ITEM_FROM_ANJU_AS_ADULT,
|
||||||
|
// Opt: *EnKz
|
||||||
|
// Vanilla condition: !CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_ZORA)
|
||||||
|
GI_VB_GIVE_ITEM_FROM_THAWING_KING_ZORA,
|
||||||
|
// Opt: *EnGo2
|
||||||
|
GI_VB_GIVE_ITEM_FROM_ROLLING_GORON_AS_CHILD,
|
||||||
|
// Opt: *EnGo2
|
||||||
|
GI_VB_GIVE_ITEM_FROM_ROLLING_GORON_AS_ADULT,
|
||||||
|
// Opt: *EnJs
|
||||||
|
GI_VB_GIVE_ITEM_FROM_CARPET_SALESMAN,
|
||||||
|
// Opt: *EnGm
|
||||||
|
GI_VB_GIVE_ITEM_FROM_MEDIGORON,
|
||||||
|
// Opt: *EnMs
|
||||||
|
GI_VB_GIVE_ITEM_FROM_MAGIC_BEAN_SALESMAN,
|
||||||
|
// Opt: *EnFr
|
||||||
|
GI_VB_GIVE_ITEM_FROM_FROGS,
|
||||||
|
|
||||||
|
GI_VB_GIVE_ITEM_FAIRY_OCARINA,
|
||||||
|
GI_VB_GIVE_ITEM_WEIRD_EGG,
|
||||||
|
GI_VB_GIVE_ITEM_LIGHT_ARROW,
|
||||||
|
GI_VB_GIVE_ITEM_STRENGTH_1,
|
||||||
|
GI_VB_GIVE_ITEM_ZELDAS_LETTER,
|
||||||
|
GI_VB_GIVE_ITEM_MASTER_SWORD,
|
||||||
|
GI_VB_GIVE_ITEM_OCARINA_OF_TIME,
|
||||||
|
GI_VB_GIVE_ITEM_KOKIRI_EMERALD,
|
||||||
|
GI_VB_GIVE_ITEM_GORON_RUBY,
|
||||||
|
GI_VB_GIVE_ITEM_ZORA_SAPPHIRE,
|
||||||
|
GI_VB_GIVE_ITEM_LIGHT_MEDALLION,
|
||||||
|
GI_VB_GIVE_ITEM_FOREST_MEDALLION,
|
||||||
|
GI_VB_GIVE_ITEM_FIRE_MEDALLION,
|
||||||
|
GI_VB_GIVE_ITEM_WATER_MEDALLION,
|
||||||
|
GI_VB_GIVE_ITEM_SPIRIT_MEDALLION,
|
||||||
|
GI_VB_GIVE_ITEM_SHADOW_MEDALLION,
|
||||||
|
|
||||||
|
/*** Give Songs ***/
|
||||||
|
|
||||||
|
GI_VB_GIVE_ITEM_ZELDAS_LULLABY,
|
||||||
|
GI_VB_GIVE_ITEM_SARIAS_SONG,
|
||||||
|
GI_VB_GIVE_ITEM_EPONAS_SONG,
|
||||||
|
GI_VB_GIVE_ITEM_SUNS_SONG,
|
||||||
|
GI_VB_GIVE_ITEM_SONG_OF_TIME,
|
||||||
|
GI_VB_GIVE_ITEM_SONG_OF_STORMS,
|
||||||
|
GI_VB_GIVE_ITEM_MINUET_OF_FOREST,
|
||||||
|
GI_VB_GIVE_ITEM_BOLERO_OF_FIRE,
|
||||||
|
GI_VB_GIVE_ITEM_SERENADE_OF_WATER,
|
||||||
|
GI_VB_GIVE_ITEM_REQUIEM_OF_SPIRIT,
|
||||||
|
GI_VB_GIVE_ITEM_NOCTURNE_OF_SHADOW,
|
||||||
|
GI_VB_GIVE_ITEM_PRELUDE_OF_LIGHT,
|
||||||
|
|
||||||
|
/*** Adult Trade ***/
|
||||||
|
// Opt: *EnNiwLady
|
||||||
|
GI_VB_TRADE_POCKET_CUCCO,
|
||||||
|
// Opt: *EnHs
|
||||||
|
GI_VB_TRADE_COJIRO,
|
||||||
|
// Opt: *EnDs
|
||||||
|
GI_VB_TRADE_ODD_MUSHROOM,
|
||||||
|
// Opt: *EnKo
|
||||||
|
GI_VB_TRADE_ODD_POTION,
|
||||||
|
// Opt: *EnToryo
|
||||||
|
GI_VB_TRADE_SAW,
|
||||||
|
// Opt: *EnGo2
|
||||||
|
GI_VB_TRADE_BROKEN_SWORD,
|
||||||
|
// Opt: *EnKz,
|
||||||
|
GI_VB_TRADE_PRESCRIPTION,
|
||||||
|
// Opt: *EnMk
|
||||||
|
GI_VB_TRADE_FROG,
|
||||||
|
// Opt: *EnGo2
|
||||||
|
GI_VB_TRADE_EYEDROPS,
|
||||||
|
// Opt: *EnGo2
|
||||||
|
GI_VB_TRADE_CLAIM_CHECK,
|
||||||
|
|
||||||
|
GI_VB_TRADE_TIMER_ODD_MUSHROOM,
|
||||||
|
GI_VB_TRADE_TIMER_EYEDROPS,
|
||||||
|
GI_VB_TRADE_TIMER_FROG,
|
||||||
|
// Opt: *EnNiwLady
|
||||||
|
GI_VB_ANJU_SET_OBTAINED_TRADE_ITEM,
|
||||||
|
|
||||||
|
/*** Fixes ***/
|
||||||
|
// Vanilla condition: false
|
||||||
|
GI_VB_FIX_SAW_SOFTLOCK,
|
||||||
|
} GIVanillaBehavior;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
@ -163,11 +430,28 @@ public:
|
|||||||
static GameInteractionEffectQueryResult RemoveEffect(RemovableGameInteractionEffect* effect);
|
static GameInteractionEffectQueryResult RemoveEffect(RemovableGameInteractionEffect* effect);
|
||||||
|
|
||||||
// Game Hooks
|
// Game Hooks
|
||||||
template <typename H> struct RegisteredGameHooks { inline static std::vector<typename H::fn> functions; };
|
uint32_t nextHookId = 0;
|
||||||
template <typename H> void RegisterGameHook(typename H::fn h) { RegisteredGameHooks<H>::functions.push_back(h); }
|
template <typename H> struct RegisteredGameHooks { inline static std::unordered_map<uint32_t, typename H::fn> functions; };
|
||||||
|
template <typename H> struct HooksToUnregister { inline static std::vector<uint32_t> hooks; };
|
||||||
|
template <typename H> uint32_t RegisterGameHook(typename H::fn h) {
|
||||||
|
// Ensure hook id is unique
|
||||||
|
while (RegisteredGameHooks<H>::functions.find(this->nextHookId) != RegisteredGameHooks<H>::functions.end()) {
|
||||||
|
this->nextHookId++;
|
||||||
|
}
|
||||||
|
RegisteredGameHooks<H>::functions[this->nextHookId] = h;
|
||||||
|
return this->nextHookId++;
|
||||||
|
}
|
||||||
|
template <typename H> void UnregisterGameHook(uint32_t id) {
|
||||||
|
HooksToUnregister<H>::hooks.push_back(id);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename H, typename... Args> void ExecuteHooks(Args&&... args) {
|
template <typename H, typename... Args> void ExecuteHooks(Args&&... args) {
|
||||||
for (auto& fn : RegisteredGameHooks<H>::functions) {
|
for (auto& hookId : HooksToUnregister<H>::hooks) {
|
||||||
fn(std::forward<Args>(args)...);
|
RegisteredGameHooks<H>::functions.erase(hookId);
|
||||||
|
}
|
||||||
|
HooksToUnregister<H>::hooks.clear();
|
||||||
|
for (auto& hook : RegisteredGameHooks<H>::functions) {
|
||||||
|
hook.second(std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,6 +478,8 @@ public:
|
|||||||
DEFINE_HOOK(OnPlayDestroy, void());
|
DEFINE_HOOK(OnPlayDestroy, void());
|
||||||
DEFINE_HOOK(OnPlayDrawEnd, void());
|
DEFINE_HOOK(OnPlayDrawEnd, void());
|
||||||
|
|
||||||
|
DEFINE_HOOK(OnVanillaBehavior, void(GIVanillaBehavior flag, bool* result, void* opt));
|
||||||
|
|
||||||
DEFINE_HOOK(OnSaveFile, void(int32_t fileNum));
|
DEFINE_HOOK(OnSaveFile, void(int32_t fileNum));
|
||||||
DEFINE_HOOK(OnLoadFile, void(int32_t fileNum));
|
DEFINE_HOOK(OnLoadFile, void(int32_t fileNum));
|
||||||
DEFINE_HOOK(OnDeleteFile, void(int32_t fileNum));
|
DEFINE_HOOK(OnDeleteFile, void(int32_t fileNum));
|
||||||
|
@ -90,6 +90,11 @@ void GameInteractor_ExecuteOnPlayDrawEnd() {
|
|||||||
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnPlayDrawEnd>();
|
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnPlayDrawEnd>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GameInteractor_Should(GIVanillaBehavior flag, bool result, void* opt) {
|
||||||
|
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnVanillaBehavior>(flag, &result, opt);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Save Files
|
// MARK: - Save Files
|
||||||
|
|
||||||
void GameInteractor_ExecuteOnSaveFile(int32_t fileNum) {
|
void GameInteractor_ExecuteOnSaveFile(int32_t fileNum) {
|
||||||
|
@ -27,6 +27,7 @@ void GameInteractor_ExecuteOnOcarinaSongAction();
|
|||||||
void GameInteractor_ExecuteOnShopSlotChangeHooks(uint8_t cursorIndex, int16_t price);
|
void GameInteractor_ExecuteOnShopSlotChangeHooks(uint8_t cursorIndex, int16_t price);
|
||||||
void GameInteractor_ExecuteOnPlayDestroy();
|
void GameInteractor_ExecuteOnPlayDestroy();
|
||||||
void GameInteractor_ExecuteOnPlayDrawEnd();
|
void GameInteractor_ExecuteOnPlayDrawEnd();
|
||||||
|
bool GameInteractor_Should(GIVanillaBehavior flag, bool result, void* opt);
|
||||||
|
|
||||||
// MARK: - Save Files
|
// MARK: - Save Files
|
||||||
void GameInteractor_ExecuteOnSaveFile(int32_t fileNum);
|
void GameInteractor_ExecuteOnSaveFile(int32_t fileNum);
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
#include "soh/Enhancements/cosmetics/authenticGfxPatches.h"
|
#include "soh/Enhancements/cosmetics/authenticGfxPatches.h"
|
||||||
#include <soh/Enhancements/item-tables/ItemTableManager.h>
|
#include <soh/Enhancements/item-tables/ItemTableManager.h>
|
||||||
#include "soh/Enhancements/nametag.h"
|
#include "soh/Enhancements/nametag.h"
|
||||||
|
#include "soh/Enhancements/timesaver_hook_handlers.h"
|
||||||
|
#include "soh/Enhancements/randomizer/hook_handlers.h"
|
||||||
|
|
||||||
#include "src/overlays/actors/ovl_En_Bb/z_en_bb.h"
|
#include "src/overlays/actors/ovl_En_Bb/z_en_bb.h"
|
||||||
#include "src/overlays/actors/ovl_En_Dekubaba/z_en_dekubaba.h"
|
#include "src/overlays/actors/ovl_En_Dekubaba/z_en_dekubaba.h"
|
||||||
@ -1596,6 +1598,8 @@ void RegisterFishsanity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void InitMods() {
|
void InitMods() {
|
||||||
|
RandomizerRegisterHooks();
|
||||||
|
TimeSaverRegisterHooks();
|
||||||
RegisterTTS();
|
RegisterTTS();
|
||||||
RegisterInfiniteMoney();
|
RegisterInfiniteMoney();
|
||||||
RegisterInfiniteHealth();
|
RegisterInfiniteHealth();
|
||||||
|
@ -1122,7 +1122,19 @@ int Fill() {
|
|||||||
std::vector<RandomizerGet> remainingPool = FilterAndEraseFromPool(ItemPool, [](const auto i) { return true; });
|
std::vector<RandomizerGet> remainingPool = FilterAndEraseFromPool(ItemPool, [](const auto i) { return true; });
|
||||||
FastFill(remainingPool, GetAllEmptyLocations(), false);
|
FastFill(remainingPool, GetAllEmptyLocations(), false);
|
||||||
|
|
||||||
//Add prices for scrubsanity, this is unique to SoH because we write/read scrub prices to/from the spoilerfile.
|
//Add default prices to scrubs
|
||||||
|
for (size_t i = 0; i < Rando::StaticData::scrubLocations.size(); i++) {
|
||||||
|
if (Rando::StaticData::scrubLocations[i] == RC_LW_DEKU_SCRUB_NEAR_BRIDGE || Rando::StaticData::scrubLocations[i] == RC_LW_DEKU_SCRUB_GROTTO_FRONT) {
|
||||||
|
ctx->GetItemLocation(Rando::StaticData::scrubLocations[i])->SetCustomPrice(40);
|
||||||
|
} else if (Rando::StaticData::scrubLocations[i] == RC_HF_DEKU_SCRUB_GROTTO) {
|
||||||
|
ctx->GetItemLocation(Rando::StaticData::scrubLocations[i])->SetCustomPrice(10);
|
||||||
|
} else {
|
||||||
|
auto loc = Rando::StaticData::GetLocation(Rando::StaticData::scrubLocations[i]);
|
||||||
|
auto item = Rando::StaticData::RetrieveItem(loc->GetVanillaItem());
|
||||||
|
ctx->GetItemLocation(Rando::StaticData::scrubLocations[i])->SetCustomPrice(item.GetPrice());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ctx->GetOption(RSK_SHUFFLE_SCRUBS).Is(RO_SCRUBS_AFFORDABLE)) {
|
if (ctx->GetOption(RSK_SHUFFLE_SCRUBS).Is(RO_SCRUBS_AFFORDABLE)) {
|
||||||
for (size_t i = 0; i < Rando::StaticData::scrubLocations.size(); i++) {
|
for (size_t i = 0; i < Rando::StaticData::scrubLocations.size(); i++) {
|
||||||
ctx->GetItemLocation(Rando::StaticData::scrubLocations[i])->SetCustomPrice(10);
|
ctx->GetItemLocation(Rando::StaticData::scrubLocations[i])->SetCustomPrice(10);
|
||||||
|
@ -18,16 +18,12 @@ typedef enum {
|
|||||||
SPOILER_CHK_ITEM_GET_INF,
|
SPOILER_CHK_ITEM_GET_INF,
|
||||||
SPOILER_CHK_EVENT_CHK_INF,
|
SPOILER_CHK_EVENT_CHK_INF,
|
||||||
SPOILER_CHK_INF_TABLE,
|
SPOILER_CHK_INF_TABLE,
|
||||||
SPOILER_CHK_COW,
|
|
||||||
SPOILER_CHK_FISH,
|
SPOILER_CHK_FISH,
|
||||||
SPOILER_CHK_MINIGAME,
|
SPOILER_CHK_MINIGAME,
|
||||||
SPOILER_CHK_SCRUB,
|
|
||||||
SPOILER_CHK_GERUDO_MEMBERSHIP_CARD,
|
SPOILER_CHK_GERUDO_MEMBERSHIP_CARD,
|
||||||
SPOILER_CHK_POE_POINTS,
|
SPOILER_CHK_POE_POINTS,
|
||||||
SPOILER_CHK_SHOP_ITEM,
|
SPOILER_CHK_SHOP_ITEM,
|
||||||
SPOILER_CHK_MAGIC_BEANS,
|
|
||||||
SPOILER_CHK_MASTER_SWORD,
|
SPOILER_CHK_MASTER_SWORD,
|
||||||
SPOILER_CHK_MERCHANT,
|
|
||||||
SPOILER_CHK_GRAVEDIGGER,
|
SPOILER_CHK_GRAVEDIGGER,
|
||||||
SPOILER_CHK_RANDOMIZER_INF,
|
SPOILER_CHK_RANDOMIZER_INF,
|
||||||
} SpoilerCollectionCheckType;
|
} SpoilerCollectionCheckType;
|
||||||
|
975
soh/soh/Enhancements/randomizer/hook_handlers.cpp
Normal file
975
soh/soh/Enhancements/randomizer/hook_handlers.cpp
Normal file
@ -0,0 +1,975 @@
|
|||||||
|
#include <libultraship/bridge.h>
|
||||||
|
#include "soh/OTRGlobals.h"
|
||||||
|
#include "soh/Enhancements/enhancementTypes.h"
|
||||||
|
#include "soh/Enhancements/custom-message/CustomMessageTypes.h"
|
||||||
|
#include "soh/Enhancements/randomizer/randomizerTypes.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "macros.h"
|
||||||
|
#include "functions.h"
|
||||||
|
#include "variables.h"
|
||||||
|
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
|
||||||
|
#include "src/overlays/actors/ovl_En_Si/z_en_si.h"
|
||||||
|
#include "src/overlays/actors/ovl_En_Cow/z_en_cow.h"
|
||||||
|
#include "src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.h"
|
||||||
|
#include "src/overlays/actors/ovl_En_Dns/z_en_dns.h"
|
||||||
|
#include "src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.h"
|
||||||
|
#include "src/overlays/actors/ovl_En_Ko/z_en_ko.h"
|
||||||
|
#include "src/overlays/actors/ovl_En_Mk/z_en_mk.h"
|
||||||
|
#include "src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.h"
|
||||||
|
#include "src/overlays/actors/ovl_En_Kz/z_en_kz.h"
|
||||||
|
#include "src/overlays/actors/ovl_En_Go2/z_en_go2.h"
|
||||||
|
#include "src/overlays/actors/ovl_En_Ms/z_en_ms.h"
|
||||||
|
#include "src/overlays/actors/ovl_En_Fr/z_en_fr.h"
|
||||||
|
#include "adult_trade_shuffle.h"
|
||||||
|
extern SaveContext gSaveContext;
|
||||||
|
extern PlayState* gPlayState;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetSelectedOptionIndex()
|
||||||
|
|
||||||
|
RandomizerCheck GetRandomizerCheckFromFlag(int16_t flagType, int16_t flag) {
|
||||||
|
for (auto& loc : Rando::StaticData::GetLocationTable()) {
|
||||||
|
if (loc.GetCollectionCheck().flag == flag && (
|
||||||
|
(flagType == FLAG_EVENT_CHECK_INF && loc.GetCollectionCheck().type == SPOILER_CHK_EVENT_CHK_INF) ||
|
||||||
|
(flagType == FLAG_ITEM_GET_INF && loc.GetCollectionCheck().type == SPOILER_CHK_ITEM_GET_INF) ||
|
||||||
|
(flagType == FLAG_RANDOMIZER_INF && loc.GetCollectionCheck().type == SPOILER_CHK_RANDOMIZER_INF)
|
||||||
|
) ||
|
||||||
|
(loc.GetActorParams() == flag && flagType == FLAG_GS_TOKEN && loc.GetCollectionCheck().type == SPOILER_CHK_GOLD_SKULLTULA)
|
||||||
|
) {
|
||||||
|
return loc.GetRandomizerCheck();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return RC_UNKNOWN_CHECK;
|
||||||
|
}
|
||||||
|
|
||||||
|
RandomizerCheck GetRandomizerCheckFromSceneFlag(int16_t sceneNum, int16_t flagType, int16_t flag) {
|
||||||
|
for (auto& loc : Rando::StaticData::GetLocationTable()) {
|
||||||
|
if (loc.GetCollectionCheck().scene == sceneNum && loc.GetCollectionCheck().flag == flag && (
|
||||||
|
(flagType == FLAG_SCENE_TREASURE && loc.GetCollectionCheck().type == SPOILER_CHK_CHEST) ||
|
||||||
|
(flagType == FLAG_SCENE_COLLECTIBLE && loc.GetCollectionCheck().type == SPOILER_CHK_COLLECTABLE) ||
|
||||||
|
(flagType == FLAG_GS_TOKEN && loc.GetCollectionCheck().type == SPOILER_CHK_GOLD_SKULLTULA)
|
||||||
|
)) {
|
||||||
|
return loc.GetRandomizerCheck();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return RC_UNKNOWN_CHECK;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MeetsLACSRequirements() {
|
||||||
|
switch (RAND_GET_OPTION(RSK_GANONS_BOSS_KEY)) {
|
||||||
|
case RO_GANON_BOSS_KEY_LACS_STONES:
|
||||||
|
if ((CheckStoneCount() + CheckLACSRewardCount()) >= RAND_GET_OPTION(RSK_LACS_STONE_COUNT)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RO_GANON_BOSS_KEY_LACS_MEDALLIONS:
|
||||||
|
if ((CheckMedallionCount() + CheckLACSRewardCount()) >= RAND_GET_OPTION(RSK_LACS_MEDALLION_COUNT)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RO_GANON_BOSS_KEY_LACS_REWARDS:
|
||||||
|
if ((CheckMedallionCount() + CheckStoneCount() + CheckLACSRewardCount()) >= RAND_GET_OPTION(RSK_LACS_REWARD_COUNT)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RO_GANON_BOSS_KEY_LACS_DUNGEONS:
|
||||||
|
if ((CheckDungeonCount() + CheckLACSRewardCount()) >= RAND_GET_OPTION(RSK_LACS_DUNGEON_COUNT)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RO_GANON_BOSS_KEY_LACS_TOKENS:
|
||||||
|
if (gSaveContext.inventory.gsTokens >= RAND_GET_OPTION(RSK_LACS_TOKEN_COUNT)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Todo Move this to randomizer context, clear it out on save load etc
|
||||||
|
static std::queue<RandomizerCheck> randomizerQueuedChecks;
|
||||||
|
static RandomizerCheck randomizerQueuedCheck = RC_UNKNOWN_CHECK;
|
||||||
|
static GetItemEntry randomizerQueuedItemEntry = GET_ITEM_NONE;
|
||||||
|
|
||||||
|
void RandomizerOnFlagSetHandler(int16_t flagType, int16_t flag) {
|
||||||
|
RandomizerCheck rc = GetRandomizerCheckFromFlag(flagType, flag);
|
||||||
|
if (rc == RC_UNKNOWN_CHECK) return;
|
||||||
|
|
||||||
|
auto loc = Rando::Context::GetInstance()->GetItemLocation(rc);
|
||||||
|
if (loc == nullptr || loc->HasObtained()) return;
|
||||||
|
|
||||||
|
SPDLOG_INFO("Queuing RC: {}", rc);
|
||||||
|
randomizerQueuedChecks.push(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RandomizerOnSceneFlagSetHandler(int16_t sceneNum, int16_t flagType, int16_t flag) {
|
||||||
|
RandomizerCheck rc = GetRandomizerCheckFromSceneFlag(sceneNum, flagType, flag);
|
||||||
|
if (rc == RC_UNKNOWN_CHECK) return;
|
||||||
|
|
||||||
|
auto loc = Rando::Context::GetInstance()->GetItemLocation(rc);
|
||||||
|
if (loc == nullptr || loc->HasObtained()) return;
|
||||||
|
|
||||||
|
SPDLOG_INFO("Queuing RC: {}", rc);
|
||||||
|
randomizerQueuedChecks.push(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Vec3f spawnPos = { 0.0f, -999.0f, 0.0f };
|
||||||
|
|
||||||
|
void RandomizerOnPlayerUpdateForRCQueueHandler() {
|
||||||
|
// If we're already queued, don't queue again
|
||||||
|
if (randomizerQueuedCheck != RC_UNKNOWN_CHECK) return;
|
||||||
|
|
||||||
|
// If there's nothing to queue, don't queue
|
||||||
|
if (randomizerQueuedChecks.size() < 1) return;
|
||||||
|
|
||||||
|
// If we're in a cutscene, don't queue
|
||||||
|
Player* player = GET_PLAYER(gPlayState);
|
||||||
|
if (Player_InBlockingCsMode(gPlayState, player) || player->stateFlags1 & PLAYER_STATE1_IN_ITEM_CS || player->stateFlags1 & PLAYER_STATE1_GETTING_ITEM || player->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RandomizerCheck rc = randomizerQueuedChecks.front();
|
||||||
|
auto loc = Rando::Context::GetInstance()->GetItemLocation(rc);
|
||||||
|
GetItemEntry getItemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(rc, true, (GetItemID)Rando::StaticData::GetLocation(rc)->GetVanillaItem());
|
||||||
|
|
||||||
|
if (loc->HasObtained()) {
|
||||||
|
SPDLOG_INFO("RC {} already obtained, skipping", rc);
|
||||||
|
} else {
|
||||||
|
randomizerQueuedCheck = rc;
|
||||||
|
randomizerQueuedItemEntry = getItemEntry;
|
||||||
|
SPDLOG_INFO("Queueing Item mod {} item {} from RC {}", getItemEntry.modIndex, getItemEntry.itemId, rc);
|
||||||
|
if (
|
||||||
|
// Skipping ItemGet animation incompatible with checks that require closing a text box to finish
|
||||||
|
rc != RC_HF_OCARINA_OF_TIME_ITEM &&
|
||||||
|
rc != RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST &&
|
||||||
|
// Always show ItemGet animation for ice traps
|
||||||
|
!(getItemEntry.modIndex == MOD_RANDOMIZER && getItemEntry.getItemId == RG_ICE_TRAP) &&
|
||||||
|
(
|
||||||
|
CVarGetInteger("gTimeSavers.SkipGetItemAnimation", SGIA_DISABLED) == SGIA_ALL ||
|
||||||
|
(
|
||||||
|
CVarGetInteger("gTimeSavers.SkipGetItemAnimation", SGIA_DISABLED) == SGIA_JUNK &&
|
||||||
|
(
|
||||||
|
getItemEntry.getItemCategory == ITEM_CATEGORY_JUNK ||
|
||||||
|
getItemEntry.getItemCategory == ITEM_CATEGORY_SKULLTULA_TOKEN ||
|
||||||
|
getItemEntry.getItemCategory == ITEM_CATEGORY_LESSER
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Item_DropCollectible(gPlayState, &spawnPos, ITEM00_SOH_GIVE_ITEM_ENTRY | 0x8000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
randomizerQueuedChecks.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RandomizerOnPlayerUpdateForItemQueueHandler() {
|
||||||
|
if (randomizerQueuedCheck == RC_UNKNOWN_CHECK) return;
|
||||||
|
|
||||||
|
Player* player = GET_PLAYER(gPlayState);
|
||||||
|
if (player == NULL || Player_InBlockingCsMode(gPlayState, player) || player->stateFlags1 & PLAYER_STATE1_IN_ITEM_CS || player->stateFlags1 & PLAYER_STATE1_GETTING_ITEM || player->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPDLOG_INFO("Attempting to give Item mod {} item {} from RC {}", randomizerQueuedItemEntry.modIndex, randomizerQueuedItemEntry.itemId, randomizerQueuedCheck);
|
||||||
|
GiveItemEntryWithoutActor(gPlayState, randomizerQueuedItemEntry);
|
||||||
|
if (player->stateFlags1 & PLAYER_STATE1_IN_WATER) {
|
||||||
|
// Allow the player to receive the item while swimming
|
||||||
|
player->stateFlags2 |= PLAYER_STATE2_UNDERWATER;
|
||||||
|
func_8083E5A8(player, gPlayState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RandomizerOnItemReceiveHandler(GetItemEntry receivedItemEntry) {
|
||||||
|
if (randomizerQueuedCheck == RC_UNKNOWN_CHECK) return;
|
||||||
|
|
||||||
|
auto loc = Rando::Context::GetInstance()->GetItemLocation(randomizerQueuedCheck);
|
||||||
|
if (randomizerQueuedItemEntry.modIndex == receivedItemEntry.modIndex && randomizerQueuedItemEntry.itemId == receivedItemEntry.itemId) {
|
||||||
|
SPDLOG_INFO("Item received mod {} item {} from RC {}", receivedItemEntry.modIndex, receivedItemEntry.itemId, randomizerQueuedCheck);
|
||||||
|
loc->MarkAsObtained();
|
||||||
|
randomizerQueuedCheck = RC_UNKNOWN_CHECK;
|
||||||
|
randomizerQueuedItemEntry = GET_ITEM_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
receivedItemEntry.modIndex == MOD_NONE && (
|
||||||
|
receivedItemEntry.itemId == ITEM_HEART_PIECE ||
|
||||||
|
receivedItemEntry.itemId == ITEM_HEART_PIECE_2 ||
|
||||||
|
receivedItemEntry.itemId == ITEM_HEART_CONTAINER
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
gSaveContext.healthAccumulator = 0x140; // Refill 20 hearts
|
||||||
|
if ((s32)(gSaveContext.inventory.questItems & 0xF0000000) == 0x40000000) {
|
||||||
|
gSaveContext.inventory.questItems ^= 0x40000000;
|
||||||
|
gSaveContext.healthCapacity += 0x10;
|
||||||
|
gSaveContext.health += 0x10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loc->GetRandomizerCheck() == RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST && !CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0)) {
|
||||||
|
static uint32_t updateHook;
|
||||||
|
updateHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayerUpdate>([]() {
|
||||||
|
Player* player = GET_PLAYER(gPlayState);
|
||||||
|
if (player == NULL || Player_InBlockingCsMode(gPlayState, player) || player->stateFlags1 & PLAYER_STATE1_IN_ITEM_CS || player->stateFlags1 & PLAYER_STATE1_GETTING_ITEM || player->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gPlayState->nextEntranceIndex = ENTR_DESERT_COLOSSUS_0;
|
||||||
|
gPlayState->transitionTrigger = TRANS_TRIGGER_START;
|
||||||
|
gSaveContext.nextCutsceneIndex = 0xFFF1;
|
||||||
|
gPlayState->transitionType = TRANS_TYPE_SANDSTORM_END;
|
||||||
|
GET_PLAYER(gPlayState)->stateFlags1 &= ~PLAYER_STATE1_IN_CUTSCENE;
|
||||||
|
Player_TryCsAction(gPlayState, NULL, 8);
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnPlayerUpdate>(updateHook);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnItem00_DrawRandomizedItem(EnItem00* enItem00, PlayState* play) {
|
||||||
|
f32 mtxScale = CVarGetFloat("gTimeSavers.SkipGetItemAnimationScale", 10.0f);
|
||||||
|
Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY);
|
||||||
|
EnItem00_CustomItemsParticles(&enItem00->actor, play, enItem00->itemEntry);
|
||||||
|
GetItemEntry_Draw(play, enItem00->itemEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemBHeart_DrawRandomizedItem(ItemBHeart* itemBHeart, PlayState* play) {
|
||||||
|
EnItem00_CustomItemsParticles(&itemBHeart->actor, play, itemBHeart->sohItemEntry);
|
||||||
|
GetItemEntry_Draw(play, itemBHeart->sohItemEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemBHeart_UpdateRandomizedItem(Actor* actor, PlayState* play) {
|
||||||
|
ItemBHeart* itemBHeart = (ItemBHeart*)actor;
|
||||||
|
|
||||||
|
func_80B85264(itemBHeart, play);
|
||||||
|
Actor_UpdateBgCheckInfo(play, &itemBHeart->actor, 0.0f, 0.0f, 0.0f, 4);
|
||||||
|
if ((itemBHeart->actor.xzDistToPlayer < 30.0f) && (fabsf(itemBHeart->actor.yDistToPlayer) < 40.0f)) {
|
||||||
|
Flags_SetCollectible(play, 0x1F);
|
||||||
|
Actor_Kill(&itemBHeart->actor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnCow_MoveForRandomizer(EnCow* enCow, PlayState* play) {
|
||||||
|
bool moved = false;
|
||||||
|
|
||||||
|
// Don't reposition the tail
|
||||||
|
if (enCow->actor.params != 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move left cow in lon lon tower
|
||||||
|
if (play->sceneNum == SCENE_LON_LON_BUILDINGS && enCow->actor.world.pos.x == -108 &&
|
||||||
|
enCow->actor.world.pos.z == -65) {
|
||||||
|
enCow->actor.world.pos.x = -229.0f;
|
||||||
|
enCow->actor.world.pos.z = 157.0f;
|
||||||
|
enCow->actor.shape.rot.y = 15783.0f;
|
||||||
|
moved = true;
|
||||||
|
// Move right cow in lon lon stable
|
||||||
|
} else if (play->sceneNum == SCENE_STABLE && enCow->actor.world.pos.x == -3 && enCow->actor.world.pos.z == -254) {
|
||||||
|
enCow->actor.world.pos.x += 119.0f;
|
||||||
|
moved = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (moved) {
|
||||||
|
// Reposition collider
|
||||||
|
func_809DEE9C(enCow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 EnDs_RandoCanGetGrannyItem() {
|
||||||
|
return RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF &&
|
||||||
|
!Flags_GetRandomizerInf(RAND_INF_MERCHANTS_GRANNYS_SHOP) &&
|
||||||
|
// Traded odd mushroom when adult trade is on
|
||||||
|
((RAND_GET_OPTION(RSK_SHUFFLE_ADULT_TRADE) && Flags_GetItemGetInf(ITEMGETINF_30)) ||
|
||||||
|
// Found claim check when adult trade is off
|
||||||
|
(!RAND_GET_OPTION(RSK_SHUFFLE_ADULT_TRADE) &&
|
||||||
|
INV_CONTENT(ITEM_CLAIM_CHECK) == ITEM_CLAIM_CHECK));
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
case FROG_STORMS:
|
||||||
|
return RC_ZR_FROGS_IN_THE_RAIN;
|
||||||
|
case FROG_CHOIR_SONG:
|
||||||
|
return RC_ZR_FROGS_OCARINA_GAME;
|
||||||
|
default:
|
||||||
|
return RC_UNKNOWN_CHECK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* optionalArg) {
|
||||||
|
switch (id) {
|
||||||
|
case GI_VB_GIVE_ITEM_FROM_CHEST: {
|
||||||
|
Player* player = GET_PLAYER(gPlayState);
|
||||||
|
player->unk_850 = 1;
|
||||||
|
player->getItemId = GI_NONE;
|
||||||
|
player->getItemEntry = GetItemEntry(GET_ITEM_NONE);
|
||||||
|
*should = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_PLAY_NABOORU_CAPTURED_CS:
|
||||||
|
// This behavior is replicated for randomizer in RandomizerOnItemReceiveHandler
|
||||||
|
*should = false;
|
||||||
|
break;
|
||||||
|
case GI_VB_SHIEK_PREPARE_TO_GIVE_SERENADE_OF_WATER: {
|
||||||
|
*should = !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER) && !Flags_GetTreasure(gPlayState, 0x2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_BE_ELIGIBLE_FOR_SERENADE_OF_WATER:
|
||||||
|
*should = !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER) && Flags_GetTreasure(gPlayState, 0x2);
|
||||||
|
break;
|
||||||
|
case GI_VB_BE_ELIGIBLE_FOR_PRELUDE_OF_LIGHT:
|
||||||
|
*should = !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST);
|
||||||
|
break;
|
||||||
|
case GI_VB_MOVE_MIDO_IN_KOKIRI_FOREST:
|
||||||
|
if (RAND_GET_OPTION(RSK_FOREST) == RO_FOREST_OPEN) {
|
||||||
|
*should = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GI_VB_MIDO_CONSIDER_DEKU_TREE_DEAD:
|
||||||
|
*should = Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD);
|
||||||
|
break;
|
||||||
|
case GI_VB_OPEN_KOKIRI_FOREST:
|
||||||
|
*should = Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD) || RAND_GET_OPTION(RSK_FOREST) != RO_FOREST_CLOSED;
|
||||||
|
break;
|
||||||
|
case GI_VB_BE_ELIGIBLE_FOR_DARUNIAS_JOY_REWARD:
|
||||||
|
*should = !Flags_GetRandomizerInf(RAND_INF_DARUNIAS_JOY);
|
||||||
|
break;
|
||||||
|
case GI_VB_BE_ELIGIBLE_FOR_LIGHT_ARROWS:
|
||||||
|
*should = !Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS) && MeetsLACSRequirements();
|
||||||
|
break;
|
||||||
|
case GI_VB_BE_ELIGIBLE_FOR_NOCTURNE_OF_SHADOW:
|
||||||
|
*should =
|
||||||
|
!Flags_GetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL) &&
|
||||||
|
LINK_IS_ADULT &&
|
||||||
|
gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_KAKARIKO_VILLAGE &&
|
||||||
|
CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST) &&
|
||||||
|
CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE) &&
|
||||||
|
CHECK_QUEST_ITEM(QUEST_MEDALLION_WATER);
|
||||||
|
break;
|
||||||
|
case GI_VB_BE_ELIGIBLE_FOR_CHILD_ROLLING_GORON_REWARD: {
|
||||||
|
// Don't require a bomb bag to get prize in rando
|
||||||
|
*should = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_BE_ELIGIBLE_FOR_MAGIC_BEANS_PURCHASE: {
|
||||||
|
if (RAND_GET_OPTION(RSK_SHUFFLE_MAGIC_BEANS)) {
|
||||||
|
*should = gSaveContext.rupees >= 60;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_GIVE_ITEM_MASTER_SWORD:
|
||||||
|
if (RAND_GET_OPTION(RSK_SHUFFLE_MASTER_SWORD)) {
|
||||||
|
*should = false;
|
||||||
|
} else {
|
||||||
|
*should = true;
|
||||||
|
Rando::Context::GetInstance()->GetItemLocation(RC_TOT_MASTER_SWORD)->MarkAsObtained();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GI_VB_ITEM00_DESPAWN: {
|
||||||
|
EnItem00* item00 = static_cast<EnItem00*>(optionalArg);
|
||||||
|
if (item00->actor.params == ITEM00_HEART_PIECE || item00->actor.params == ITEM00_SMALL_KEY) {
|
||||||
|
RandomizerCheck rc = OTRGlobals::Instance->gRandomizer->GetCheckFromActor(item00->actor.id, gPlayState->sceneNum, item00->ogParams);
|
||||||
|
if (rc != RC_UNKNOWN_CHECK) {
|
||||||
|
item00->actor.params = ITEM00_SOH_DUMMY;
|
||||||
|
item00->itemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(rc, true, (GetItemID)Rando::StaticData::GetLocation(rc)->GetVanillaItem());
|
||||||
|
item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem;
|
||||||
|
*should = Rando::Context::GetInstance()->GetItemLocation(rc)->HasObtained();
|
||||||
|
}
|
||||||
|
} else if (item00->actor.params == ITEM00_SOH_GIVE_ITEM_ENTRY || item00->actor.params == ITEM00_SOH_GIVE_ITEM_ENTRY_GI) {
|
||||||
|
GetItemEntry itemEntry = randomizerQueuedItemEntry;
|
||||||
|
item00->itemEntry = itemEntry;
|
||||||
|
item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_MALON_ALREADY_TAUGHT_EPONAS_SONG: {
|
||||||
|
*should = Flags_GetRandomizerInf(RAND_INF_LEARNED_EPONA_SONG);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_SET_CUCCO_COUNT: {
|
||||||
|
EnNiwLady* enNiwLady = static_cast<EnNiwLady*>(optionalArg);
|
||||||
|
// Override starting Cucco count using setting value
|
||||||
|
enNiwLady->cuccosInPen = 7 - RAND_GET_OPTION(RSK_CUCCO_COUNT);
|
||||||
|
*should = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_KING_ZORA_THANK_CHILD: {
|
||||||
|
// Allow turning in Ruto's letter even if you have already rescued her
|
||||||
|
if (!Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) {
|
||||||
|
GET_PLAYER(gPlayState)->exchangeItemId = EXCH_ITEM_LETTER_RUTO;
|
||||||
|
}
|
||||||
|
*should = Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_BE_ABLE_TO_EXCHANGE_RUTOS_LETTER: {
|
||||||
|
*should = LINK_IS_CHILD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_KING_ZORA_BE_MOVED: {
|
||||||
|
*should = false;
|
||||||
|
switch (RAND_GET_OPTION(RSK_ZORAS_FOUNTAIN)) {
|
||||||
|
case RO_ZF_CLOSED:
|
||||||
|
if (Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) {
|
||||||
|
*should = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RO_ZF_CLOSED_CHILD:
|
||||||
|
if (LINK_IS_ADULT) {
|
||||||
|
*should = true;
|
||||||
|
} else if (Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) {
|
||||||
|
*should = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RO_ZF_OPEN:
|
||||||
|
*should = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_BIGGORON_CONSIDER_SWORD_COLLECTED: {
|
||||||
|
*should = Flags_GetRandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_CLAIM_CHECK);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_BIGGORON_CONSIDER_TRADE_COMPLETE: {
|
||||||
|
|
||||||
|
*should = INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_CLAIM_CHECK && Flags_GetRandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_CLAIM_CHECK);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED: {
|
||||||
|
*should = Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_GORONS_CONSIDER_DODONGOS_CAVERN_FINISHED: {
|
||||||
|
*should = Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_OVERRIDE_LINK_THE_GORON_DIALOGUE: {
|
||||||
|
u16* textId = static_cast<u16*>(optionalArg);
|
||||||
|
*should = true;
|
||||||
|
|
||||||
|
// For rando, prioritize opening the doors in GC when Link the goron has been stopped when
|
||||||
|
// the doors are not opened, otherwise let him talk about the DMC exit or that gorons are saved
|
||||||
|
if (!Flags_GetInfTable(INFTABLE_STOPPED_GORON_LINKS_ROLLING)) {
|
||||||
|
*textId = 0x3030;
|
||||||
|
} else if (!Flags_GetInfTable(INFTABLE_GORON_CITY_DOORS_UNLOCKED)) {
|
||||||
|
*textId = 0x3036;
|
||||||
|
} else if (Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP)) {
|
||||||
|
*textId = 0x3041;
|
||||||
|
} else {
|
||||||
|
*textId = Flags_GetInfTable(INFTABLE_SPOKE_TO_GORON_LINK) ? 0x3038 : 0x3037;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_EN_GO2_RESET_AFTER_GET_ITEM: {
|
||||||
|
EnGo2* enGo2 = static_cast<EnGo2*>(optionalArg);
|
||||||
|
// For randomizer, handle updating the states for the gorons after receiving the item based on
|
||||||
|
// the goron type rather then the item being received
|
||||||
|
switch (enGo2->actor.params & 0x1F) {
|
||||||
|
case GORON_DMT_BIGGORON:
|
||||||
|
// 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;
|
||||||
|
break;
|
||||||
|
case GORON_CITY_LINK:
|
||||||
|
EnGo2_GetItemAnimation(enGo2, gPlayState);
|
||||||
|
break;
|
||||||
|
case GORON_CITY_ROLLING_BIG:
|
||||||
|
EnGo2_RollingAnimation(enGo2, gPlayState);
|
||||||
|
enGo2->actionFunc = (EnGo2ActionFunc)EnGo2_GoronRollingBigContinueRolling;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
enGo2->actionFunc = func_80A46B40;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_GIVE_ITEM_FROM_ITEM_00: {
|
||||||
|
EnItem00* item00 = static_cast<EnItem00*>(optionalArg);
|
||||||
|
if (item00->actor.params == ITEM00_SOH_DUMMY) {
|
||||||
|
Flags_SetCollectible(gPlayState, item00->collectibleFlag);
|
||||||
|
Actor_Kill(&item00->actor);
|
||||||
|
*should = false;
|
||||||
|
} else if (item00->actor.params == ITEM00_SOH_GIVE_ITEM_ENTRY) {
|
||||||
|
Audio_PlaySoundGeneral(NA_SE_SY_GET_ITEM, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
|
||||||
|
if (item00->itemEntry.modIndex == MOD_NONE) {
|
||||||
|
if (item00->itemEntry.getItemId == GI_SWORD_BGS) {
|
||||||
|
gSaveContext.bgsFlag = true;
|
||||||
|
}
|
||||||
|
Item_Give(gPlayState, item00->itemEntry.itemId);
|
||||||
|
} else if (item00->itemEntry.modIndex == MOD_RANDOMIZER) {
|
||||||
|
if (item00->itemEntry.getItemId == RG_ICE_TRAP) {
|
||||||
|
gSaveContext.pendingIceTrapCount++;
|
||||||
|
} else {
|
||||||
|
Randomizer_Item_Give(gPlayState, item00->itemEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// EnItem00_SetupAction(item00, func_8001E5C8);
|
||||||
|
// *should = false;
|
||||||
|
} else if (item00->actor.params == ITEM00_SOH_GIVE_ITEM_ENTRY_GI) {
|
||||||
|
if (!Actor_HasParent(&item00->actor, gPlayState)) {
|
||||||
|
GiveItemEntryFromActorWithFixedRange(&item00->actor, gPlayState, item00->itemEntry);
|
||||||
|
}
|
||||||
|
EnItem00_SetupAction(item00, func_8001E5C8);
|
||||||
|
*should = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_BE_ELIGIBLE_FOR_SARIAS_SONG: {
|
||||||
|
*should = !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SARIAS_SONG);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_GIVE_ITEM_FROM_COW: {
|
||||||
|
if (!RAND_GET_OPTION(RSK_SHUFFLE_COWS)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
EnCow* enCow = static_cast<EnCow*>(optionalArg);
|
||||||
|
CowIdentity cowIdentity = OTRGlobals::Instance->gRandomizer->IdentifyCow(gPlayState->sceneNum, enCow->actor.world.pos.x, enCow->actor.world.pos.z);
|
||||||
|
// Has this cow already rewarded an item?
|
||||||
|
if (Flags_GetRandomizerInf(cowIdentity.randomizerInf)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Flags_SetRandomizerInf(cowIdentity.randomizerInf);
|
||||||
|
// setting the ocarina mode here prevents intermittent issues
|
||||||
|
// with the item get not triggering until walking away
|
||||||
|
gPlayState->msgCtx.ocarinaMode = OCARINA_MODE_00;
|
||||||
|
*should = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_GIVE_ITEM_FROM_GRANNYS_SHOP: {
|
||||||
|
if (!EnDs_RandoCanGetGrannyItem()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Only setting the inf if we've actually gotten the rando item and not the vanilla blue potion
|
||||||
|
Flags_SetRandomizerInf(RAND_INF_MERCHANTS_GRANNYS_SHOP);
|
||||||
|
*should = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_GIVE_ITEM_FROM_THAWING_KING_ZORA: {
|
||||||
|
EnKz* enKz = static_cast<EnKz*>(optionalArg);
|
||||||
|
// If we aren't setting up the item offer, then we're just checking if it should be possible.
|
||||||
|
if (enKz->actionFunc != (EnKzActionFunc)EnKz_SetupGetItem) {
|
||||||
|
// Always give the reward in rando
|
||||||
|
*should = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*should = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_GIVE_ITEM_FROM_ANJU_AS_CHILD: {
|
||||||
|
Flags_SetItemGetInf(ITEMGETINF_0C);
|
||||||
|
*should = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_GIVE_ITEM_FROM_ANJU_AS_ADULT: {
|
||||||
|
Flags_SetItemGetInf(ITEMGETINF_2C);
|
||||||
|
*should = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_GIVE_ITEM_FROM_ROLLING_GORON_AS_ADULT: {
|
||||||
|
EnGo2* enGo2 = static_cast<EnGo2*>(optionalArg);
|
||||||
|
*should = false;
|
||||||
|
if (!Flags_GetRandomizerInf(RAND_INF_ROLLING_GORON_AS_ADULT)) {
|
||||||
|
Flags_SetInfTable(INFTABLE_GORON_CITY_DOORS_UNLOCKED);
|
||||||
|
enGo2->interactInfo.talkState = NPC_TALK_STATE_ACTION;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_GIVE_ITEM_FROM_CARPET_SALESMAN: {
|
||||||
|
*should = RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS) == RO_SHUFFLE_MERCHANTS_OFF ||
|
||||||
|
// If the rando check has already been awarded, use vanilla behavior.
|
||||||
|
Flags_GetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_GIVE_ITEM_FROM_MEDIGORON: {
|
||||||
|
// fallthrough
|
||||||
|
case GI_VB_BE_ELIGIBLE_FOR_GIANTS_KNIFE_PURCHASE:
|
||||||
|
if (RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF &&
|
||||||
|
!Flags_GetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON)) {
|
||||||
|
if (id == GI_VB_GIVE_ITEM_FROM_MEDIGORON) {
|
||||||
|
Flags_SetInfTable(INFTABLE_B1);
|
||||||
|
*should = false;
|
||||||
|
} else {
|
||||||
|
// Resets "Talked to Medigoron" flag in infTable to restore initial conversation state
|
||||||
|
Flags_UnsetInfTable(INFTABLE_B1);
|
||||||
|
*should = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_GIVE_ITEM_FROM_MAGIC_BEAN_SALESMAN: {
|
||||||
|
EnMs* enMs = static_cast<EnMs*>(optionalArg);
|
||||||
|
if (RAND_GET_OPTION(RSK_SHUFFLE_MAGIC_BEANS)) {
|
||||||
|
Rupees_ChangeBy(-60);
|
||||||
|
BEANS_BOUGHT = 10;
|
||||||
|
// Only set inf for buying rando check
|
||||||
|
Flags_SetRandomizerInf(RAND_INF_MERCHANTS_MAGIC_BEAN_SALESMAN);
|
||||||
|
enMs->actionFunc = (EnMsActionFunc)EnMs_Wait;
|
||||||
|
*should = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_GIVE_ITEM_FROM_FROGS: {
|
||||||
|
EnFr* enFr = static_cast<EnFr*>(optionalArg);
|
||||||
|
|
||||||
|
// Skip GiveReward+SetIdle action func if the reward is an ice trap
|
||||||
|
if (enFr->actionFunc == (EnFrActionFunc)EnFr_GiveReward) {
|
||||||
|
RandomizerCheck rc = EnFr_RandomizerCheckFromSongIndex(enFr->songIndex);
|
||||||
|
GetItemEntry gi = Rando::Context::GetInstance()->GetFinalGIEntry(rc, true, (GetItemID)Rando::StaticData::GetLocation(rc)->GetVanillaItem());
|
||||||
|
if (gi.getItemId == RG_ICE_TRAP) {
|
||||||
|
enFr->actionFunc = (EnFrActionFunc)EnFr_Idle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*should = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_TRADE_POCKET_CUCCO: {
|
||||||
|
Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_POCKET_CUCCO);
|
||||||
|
// Trigger the reward now
|
||||||
|
Flags_SetItemGetInf(ITEMGETINF_2E);
|
||||||
|
*should = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_TRADE_COJIRO: {
|
||||||
|
Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_COJIRO);
|
||||||
|
*should = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_TRADE_ODD_MUSHROOM: {
|
||||||
|
Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_ODD_MUSHROOM);
|
||||||
|
// Trigger the reward now
|
||||||
|
Flags_SetItemGetInf(ITEMGETINF_30);
|
||||||
|
*should = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_TRADE_ODD_POTION: {
|
||||||
|
EnKo* enKo = static_cast<EnKo*>(optionalArg);
|
||||||
|
Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_ODD_POTION);
|
||||||
|
// Trigger the reward now
|
||||||
|
Flags_SetItemGetInf(ITEMGETINF_31);
|
||||||
|
*should = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_TRADE_SAW: {
|
||||||
|
Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_SAW);
|
||||||
|
*should = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_TRADE_PRESCRIPTION: {
|
||||||
|
EnKz* enKz = static_cast<EnKz*>(optionalArg);
|
||||||
|
// If we aren't setting up the item offer, then we're just checking if it should be possible.
|
||||||
|
if (enKz->actionFunc != (EnKzActionFunc)EnKz_SetupGetItem) {
|
||||||
|
*should = !Flags_GetRandomizerInf(RAND_INF_ADULT_TRADES_ZD_TRADE_PRESCRIPTION);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_PRESCRIPTION);
|
||||||
|
*should = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_TRADE_FROG: {
|
||||||
|
Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_FROG);
|
||||||
|
*should = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_TRADE_BROKEN_SWORD: {
|
||||||
|
Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_SWORD_BROKEN);
|
||||||
|
*should = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_TRADE_EYEDROPS: {
|
||||||
|
Randomizer_ConsumeAdultTradeItem(gPlayState, ITEM_EYEDROPS);
|
||||||
|
*should = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_DESPAWN_HORSE_RACE_COW: {
|
||||||
|
if (!RAND_GET_OPTION(RSK_SHUFFLE_COWS)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
EnCow* enCow = static_cast<EnCow*>(optionalArg);
|
||||||
|
// If this is a cow we have to move, then move it now.
|
||||||
|
EnCow_MoveForRandomizer(enCow, gPlayState);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_BUSINESS_SCRUB_DESPAWN: {
|
||||||
|
EnShopnuts* enShopnuts = static_cast<EnShopnuts*>(optionalArg);
|
||||||
|
s16 respawnData = gSaveContext.respawn[RESPAWN_MODE_RETURN].data & ((1 << 8) - 1);
|
||||||
|
ScrubIdentity scrubIdentity = OTRGlobals::Instance->gRandomizer->IdentifyScrub(gPlayState->sceneNum, enShopnuts->actor.params, respawnData);
|
||||||
|
|
||||||
|
if (scrubIdentity.isShuffled) {
|
||||||
|
*should = Flags_GetRandomizerInf(scrubIdentity.randomizerInf);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_GIVE_ITEM_FROM_BUSINESS_SCRUB: {
|
||||||
|
EnDns* enDns = static_cast<EnDns*>(optionalArg);
|
||||||
|
*should = !enDns->sohScrubIdentity.isShuffled;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// 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.
|
||||||
|
case GI_VB_DESPAWN_GROG: {
|
||||||
|
if (!RAND_GET_OPTION(RSK_SHUFFLE_ADULT_TRADE)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (PLAYER_HAS_SHUFFLED_ADULT_TRADE_ITEM(ITEM_COJIRO)) {
|
||||||
|
*should = false;
|
||||||
|
} else if (PLAYER_HAS_SHUFFLED_ADULT_TRADE_ITEM(ITEM_ODD_POTION)) {
|
||||||
|
*should = true;
|
||||||
|
} else {
|
||||||
|
*should = Flags_GetItemGetInf(ITEMGETINF_30); // Traded odd mushroom
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_SPAWN_LW_FADO: {
|
||||||
|
if (!RAND_GET_OPTION(RSK_SHUFFLE_ADULT_TRADE)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PLAYER_HAS_SHUFFLED_ADULT_TRADE_ITEM(ITEM_COJIRO)) {
|
||||||
|
*should = false;
|
||||||
|
} else {
|
||||||
|
*should = PLAYER_HAS_SHUFFLED_ADULT_TRADE_ITEM(ITEM_ODD_POTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_USE_EYEDROP_DIALOGUE: {
|
||||||
|
// Skip eye drop text on rando if Link went in the water, so you can still receive the dive check
|
||||||
|
EnMk* enMk = static_cast<EnMk*>(optionalArg);
|
||||||
|
*should &= enMk->swimFlag == 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_OFFER_BLUE_POTION: {
|
||||||
|
// Always offer blue potion when adult trade is off
|
||||||
|
*should |= RAND_GET_OPTION(RSK_SHUFFLE_ADULT_TRADE) == RO_GENERIC_OFF;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_NEED_BOTTLE_FOR_GRANNYS_ITEM: {
|
||||||
|
// Allow buying the rando item regardless of having a bottle
|
||||||
|
*should &= !EnDs_RandoCanGetGrannyItem();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_TRADE_CLAIM_CHECK:
|
||||||
|
case GI_VB_TRADE_TIMER_ODD_MUSHROOM:
|
||||||
|
case GI_VB_TRADE_TIMER_EYEDROPS:
|
||||||
|
case GI_VB_TRADE_TIMER_FROG:
|
||||||
|
case GI_VB_ANJU_SET_OBTAINED_TRADE_ITEM:
|
||||||
|
case GI_VB_GIVE_ITEM_FROM_ROLLING_GORON_AS_CHILD:
|
||||||
|
case GI_VB_GIVE_ITEM_FROM_LAB_DIVE:
|
||||||
|
case GI_VB_GIVE_ITEM_SKULL_TOKEN:
|
||||||
|
case GI_VB_GIVE_ITEM_FROM_BLUE_WARP:
|
||||||
|
case GI_VB_GIVE_ITEM_FAIRY_OCARINA:
|
||||||
|
case GI_VB_GIVE_ITEM_WEIRD_EGG:
|
||||||
|
case GI_VB_GIVE_ITEM_LIGHT_ARROW:
|
||||||
|
case GI_VB_GIVE_ITEM_STRENGTH_1:
|
||||||
|
case GI_VB_GIVE_ITEM_ZELDAS_LETTER:
|
||||||
|
case GI_VB_GIVE_ITEM_OCARINA_OF_TIME:
|
||||||
|
case GI_VB_GIVE_ITEM_KOKIRI_EMERALD:
|
||||||
|
case GI_VB_GIVE_ITEM_GORON_RUBY:
|
||||||
|
case GI_VB_GIVE_ITEM_ZORA_SAPPHIRE:
|
||||||
|
case GI_VB_GIVE_ITEM_LIGHT_MEDALLION:
|
||||||
|
case GI_VB_GIVE_ITEM_FOREST_MEDALLION:
|
||||||
|
case GI_VB_GIVE_ITEM_FIRE_MEDALLION:
|
||||||
|
case GI_VB_GIVE_ITEM_WATER_MEDALLION:
|
||||||
|
case GI_VB_GIVE_ITEM_SPIRIT_MEDALLION:
|
||||||
|
case GI_VB_GIVE_ITEM_SHADOW_MEDALLION:
|
||||||
|
*should = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RandomizerOnSceneInitHandler(int16_t sceneNum) {
|
||||||
|
// LACs & Prelude checks
|
||||||
|
static uint32_t updateHook = 0;
|
||||||
|
|
||||||
|
if (updateHook) {
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnPlayerUpdate>(updateHook);
|
||||||
|
updateHook = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
sceneNum != SCENE_TEMPLE_OF_TIME ||
|
||||||
|
(
|
||||||
|
Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) &&
|
||||||
|
Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS)
|
||||||
|
)
|
||||||
|
) return;
|
||||||
|
|
||||||
|
updateHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayerUpdate>([]() {
|
||||||
|
if (!Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && LINK_IS_ADULT && CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST) && gPlayState->roomCtx.curRoom.num == 0) {
|
||||||
|
Flags_SetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS) && MeetsLACSRequirements()) {
|
||||||
|
Flags_SetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) &&
|
||||||
|
Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS)
|
||||||
|
) {
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnPlayerUpdate>(updateHook);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnSi_DrawRandomizedItem(EnSi* enSi, PlayState* play) {
|
||||||
|
func_8002ED80(&enSi->actor, play, 0);
|
||||||
|
func_8002EBCC(&enSi->actor, play, 0);
|
||||||
|
EnItem00_CustomItemsParticles(&enSi->actor, play, enSi->sohGetItemEntry);
|
||||||
|
GetItemEntry_Draw(play, enSi->sohGetItemEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 EnDns_RandomizerPurchaseableCheck(EnDns* enDns) {
|
||||||
|
if (Flags_GetRandomizerInf(enDns->sohScrubIdentity.randomizerInf)) {
|
||||||
|
return 3; // Can't get this now
|
||||||
|
}
|
||||||
|
if (gSaveContext.rupees < enDns->dnsItemEntry->itemPrice) {
|
||||||
|
return 0; // Not enough rupees
|
||||||
|
}
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnDns_RandomizerPurchase(EnDns* enDns) {
|
||||||
|
Rupees_ChangeBy(-enDns->dnsItemEntry->itemPrice);
|
||||||
|
Flags_SetRandomizerInf(enDns->sohScrubIdentity.randomizerInf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RandomizerOnActorInitHandler(void* actorRef) {
|
||||||
|
Actor* actor = static_cast<Actor*>(actorRef);
|
||||||
|
|
||||||
|
if (actor->id == ACTOR_EN_SI) {
|
||||||
|
RandomizerCheck rc = OTRGlobals::Instance->gRandomizer->GetCheckFromActor(actor->id, gPlayState->sceneNum, actor->params);
|
||||||
|
if (rc != RC_UNKNOWN_CHECK) {
|
||||||
|
EnSi* enSi = static_cast<EnSi*>(actorRef);
|
||||||
|
enSi->sohGetItemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(rc, true, (GetItemID)Rando::StaticData::GetLocation(rc)->GetVanillaItem());
|
||||||
|
actor->draw = (ActorFunc)EnSi_DrawRandomizedItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actor->id == ACTOR_ITEM_B_HEART) {
|
||||||
|
ItemBHeart* itemBHeart = static_cast<ItemBHeart*>(actorRef);
|
||||||
|
RandomizerCheck rc = OTRGlobals::Instance->gRandomizer->GetCheckFromActor(itemBHeart->actor.id, gPlayState->sceneNum, itemBHeart->actor.params);
|
||||||
|
if (rc != RC_UNKNOWN_CHECK) {
|
||||||
|
itemBHeart->sohItemEntry = Rando::Context::GetInstance()->GetFinalGIEntry(rc, true, (GetItemID)Rando::StaticData::GetLocation(rc)->GetVanillaItem());
|
||||||
|
itemBHeart->actor.draw = (ActorFunc)ItemBHeart_DrawRandomizedItem;
|
||||||
|
itemBHeart->actor.update = (ActorFunc)ItemBHeart_UpdateRandomizedItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actor->id == ACTOR_EN_DNS) {
|
||||||
|
EnDns* enDns = static_cast<EnDns*>(actorRef);
|
||||||
|
s16 respawnData = gSaveContext.respawn[RESPAWN_MODE_RETURN].data & ((1 << 8) - 1);
|
||||||
|
enDns->sohScrubIdentity = OTRGlobals::Instance->gRandomizer->IdentifyScrub(gPlayState->sceneNum, enDns->actor.params, respawnData);
|
||||||
|
|
||||||
|
if (enDns->sohScrubIdentity.isShuffled) {
|
||||||
|
// DNS uses pointers so we're creating our own entry instead of modifying the original
|
||||||
|
enDns->sohDnsItemEntry = {
|
||||||
|
enDns->dnsItemEntry->itemPrice,
|
||||||
|
1,
|
||||||
|
enDns->sohScrubIdentity.getItemId,
|
||||||
|
EnDns_RandomizerPurchaseableCheck,
|
||||||
|
EnDns_RandomizerPurchase,
|
||||||
|
};
|
||||||
|
enDns->dnsItemEntry = &enDns->sohDnsItemEntry;
|
||||||
|
|
||||||
|
if (enDns->sohScrubIdentity.itemPrice != -1) {
|
||||||
|
enDns->dnsItemEntry->itemPrice = enDns->sohScrubIdentity.itemPrice;
|
||||||
|
}
|
||||||
|
|
||||||
|
enDns->actor.textId = TEXT_SCRUB_RANDOM;
|
||||||
|
|
||||||
|
static uint32_t enDnsUpdateHook = 0;
|
||||||
|
static uint32_t enDnsKillHook = 0;
|
||||||
|
if (!enDnsUpdateHook) {
|
||||||
|
enDnsUpdateHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* innerActorRef) {
|
||||||
|
Actor* innerActor = static_cast<Actor*>(innerActorRef);
|
||||||
|
if (innerActor->id == ACTOR_EN_DNS) {
|
||||||
|
EnDns* innerEnDns = static_cast<EnDns*>(innerActorRef);
|
||||||
|
if (innerEnDns->sohScrubIdentity.isShuffled) {
|
||||||
|
innerActor->textId = TEXT_SCRUB_RANDOM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
enDnsKillHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int16_t sceneNum) {
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorUpdate>(enDnsUpdateHook);
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneInit>(enDnsKillHook);
|
||||||
|
enDnsUpdateHook = 0;
|
||||||
|
enDnsKillHook = 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RandomizerRegisterHooks() {
|
||||||
|
static uint32_t onFlagSetHook = 0;
|
||||||
|
static uint32_t onSceneFlagSetHook = 0;
|
||||||
|
static uint32_t onPlayerUpdateForRCQueueHook = 0;
|
||||||
|
static uint32_t onPlayerUpdateForItemQueueHook = 0;
|
||||||
|
static uint32_t onItemReceiveHook = 0;
|
||||||
|
static uint32_t onVanillaBehaviorHook = 0;
|
||||||
|
static uint32_t onSceneInitHook = 0;
|
||||||
|
static uint32_t onActorInitHook = 0;
|
||||||
|
|
||||||
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnLoadGame>([](int32_t fileNum) {
|
||||||
|
randomizerQueuedChecks = std::queue<RandomizerCheck>();
|
||||||
|
randomizerQueuedCheck = RC_UNKNOWN_CHECK;
|
||||||
|
randomizerQueuedItemEntry = GET_ITEM_NONE;
|
||||||
|
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnFlagSet>(onFlagSetHook);
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneFlagSet>(onSceneFlagSetHook);
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnPlayerUpdate>(onPlayerUpdateForRCQueueHook);
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnPlayerUpdate>(onPlayerUpdateForItemQueueHook);
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnItemReceive>(onItemReceiveHook);
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnVanillaBehavior>(onVanillaBehaviorHook);
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneInit>(onSceneInitHook);
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorInit>(onActorInitHook);
|
||||||
|
|
||||||
|
onFlagSetHook = 0;
|
||||||
|
onSceneFlagSetHook = 0;
|
||||||
|
onPlayerUpdateForRCQueueHook = 0;
|
||||||
|
onPlayerUpdateForItemQueueHook = 0;
|
||||||
|
onItemReceiveHook = 0;
|
||||||
|
onVanillaBehaviorHook = 0;
|
||||||
|
onSceneInitHook = 0;
|
||||||
|
onActorInitHook = 0;
|
||||||
|
|
||||||
|
if (!IS_RANDO) return;
|
||||||
|
|
||||||
|
onFlagSetHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnFlagSet>(RandomizerOnFlagSetHandler);
|
||||||
|
onSceneFlagSetHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneFlagSet>(RandomizerOnSceneFlagSetHandler);
|
||||||
|
onPlayerUpdateForRCQueueHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayerUpdate>(RandomizerOnPlayerUpdateForRCQueueHandler);
|
||||||
|
onPlayerUpdateForItemQueueHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayerUpdate>(RandomizerOnPlayerUpdateForItemQueueHandler);
|
||||||
|
onItemReceiveHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnItemReceive>(RandomizerOnItemReceiveHandler);
|
||||||
|
onVanillaBehaviorHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnVanillaBehavior>(RandomizerOnVanillaBehaviorHandler);
|
||||||
|
onSceneInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>(RandomizerOnSceneInitHandler);
|
||||||
|
onActorInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>(RandomizerOnActorInitHandler);
|
||||||
|
});
|
||||||
|
}
|
6
soh/soh/Enhancements/randomizer/hook_handlers.h
Normal file
6
soh/soh/Enhancements/randomizer/hook_handlers.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef RANDOMIZER_HOOK_HANDLERS_H
|
||||||
|
#define RANDOMIZER_HOOK_HANDLERS_H
|
||||||
|
|
||||||
|
void RandomizerRegisterHooks();
|
||||||
|
|
||||||
|
#endif // RANDOMIZER_HOOK_HANDLERS_H
|
@ -101,6 +101,18 @@ void ItemLocation::SetCustomPrice(const uint16_t price_) {
|
|||||||
hasCustomPrice = true;
|
hasCustomPrice = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ItemLocation::HasObtained() const {
|
||||||
|
return obtained;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemLocation::MarkAsObtained() {
|
||||||
|
obtained = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemLocation::MarkAsNotObtained() {
|
||||||
|
obtained = false;
|
||||||
|
}
|
||||||
|
|
||||||
bool ItemLocation::IsHintable() const {
|
bool ItemLocation::IsHintable() const {
|
||||||
return isHintable;
|
return isHintable;
|
||||||
}
|
}
|
||||||
@ -201,5 +213,6 @@ void ItemLocation::ResetVariables() {
|
|||||||
wothCandidate = false;
|
wothCandidate = false;
|
||||||
barrenCandidate = false;
|
barrenCandidate = false;
|
||||||
area = RA_NONE;
|
area = RA_NONE;
|
||||||
|
obtained = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -31,6 +31,9 @@ class ItemLocation {
|
|||||||
void SetPrice(uint16_t price_);
|
void SetPrice(uint16_t price_);
|
||||||
bool HasCustomPrice() const;
|
bool HasCustomPrice() const;
|
||||||
void SetCustomPrice(uint16_t price_);
|
void SetCustomPrice(uint16_t price_);
|
||||||
|
bool HasObtained() const;
|
||||||
|
void MarkAsObtained();
|
||||||
|
void MarkAsNotObtained();
|
||||||
bool IsHintable() const;
|
bool IsHintable() const;
|
||||||
void SetAsHintable();
|
void SetAsHintable();
|
||||||
bool IsHintedAt() const;
|
bool IsHintedAt() const;
|
||||||
@ -67,5 +70,6 @@ class ItemLocation {
|
|||||||
bool visibleInImGui = false;
|
bool visibleInImGui = false;
|
||||||
bool wothCandidate = false;
|
bool wothCandidate = false;
|
||||||
bool barrenCandidate = false;
|
bool barrenCandidate = false;
|
||||||
|
bool obtained = false;
|
||||||
};
|
};
|
||||||
} // namespace Rando
|
} // namespace Rando
|
@ -51,10 +51,6 @@ class SpoilerCollectionCheck {
|
|||||||
return SpoilerCollectionCheck(SPOILER_CHK_CHEST, scene, flag);
|
return SpoilerCollectionCheck(SPOILER_CHK_CHEST, scene, flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto Cow(const uint8_t scene, const uint8_t flag) {
|
|
||||||
return SpoilerCollectionCheck(SPOILER_CHK_COW, scene, flag);
|
|
||||||
}
|
|
||||||
|
|
||||||
static auto Fish(const uint8_t flag, const uint8_t scene = SCENE_FISHING_POND) {
|
static auto Fish(const uint8_t flag, const uint8_t scene = SCENE_FISHING_POND) {
|
||||||
return SpoilerCollectionCheck(SPOILER_CHK_FISH, scene, flag);
|
return SpoilerCollectionCheck(SPOILER_CHK_FISH, scene, flag);
|
||||||
}
|
}
|
||||||
@ -63,10 +59,6 @@ class SpoilerCollectionCheck {
|
|||||||
return SpoilerCollectionCheck(SPOILER_CHK_MINIGAME, 0x00, bit);
|
return SpoilerCollectionCheck(SPOILER_CHK_MINIGAME, 0x00, bit);
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto Scrub(const uint8_t scene, const uint8_t bit) {
|
|
||||||
return SpoilerCollectionCheck(SPOILER_CHK_SCRUB, scene, bit);
|
|
||||||
}
|
|
||||||
|
|
||||||
static auto GerudoToken() {
|
static auto GerudoToken() {
|
||||||
return SpoilerCollectionCheck(SPOILER_CHK_GERUDO_MEMBERSHIP_CARD, 0x00, 0x00);
|
return SpoilerCollectionCheck(SPOILER_CHK_GERUDO_MEMBERSHIP_CARD, 0x00, 0x00);
|
||||||
}
|
}
|
||||||
@ -83,20 +75,12 @@ class SpoilerCollectionCheck {
|
|||||||
return SpoilerCollectionCheck(SPOILER_CHK_SHOP_ITEM, scene, itemSlot);
|
return SpoilerCollectionCheck(SPOILER_CHK_SHOP_ITEM, scene, itemSlot);
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto MagicBeans(const uint8_t scene, const uint8_t flag) {
|
|
||||||
return SpoilerCollectionCheck(SPOILER_CHK_MAGIC_BEANS, scene, flag);
|
|
||||||
}
|
|
||||||
|
|
||||||
static auto MasterSword() {
|
static auto MasterSword() {
|
||||||
return SpoilerCollectionCheck(SPOILER_CHK_MASTER_SWORD, 0x00, 0x00);
|
return SpoilerCollectionCheck(SPOILER_CHK_MASTER_SWORD, 0x00, 0x00);
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto Merchant(const int8_t scene, const uint8_t flag) {
|
static auto RandomizerInf(const uint8_t flag) {
|
||||||
return SpoilerCollectionCheck(SPOILER_CHK_MERCHANT, scene, flag);
|
return SpoilerCollectionCheck(SPOILER_CHK_RANDOMIZER_INF, 0x00, flag);
|
||||||
}
|
|
||||||
|
|
||||||
static auto RandomizerInf(const int8_t scene, const uint8_t flag) {
|
|
||||||
return SpoilerCollectionCheck(SPOILER_CHK_RANDOMIZER_INF, scene, flag);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -419,11 +419,8 @@ bool HasItemBeenCollected(RandomizerCheck rc) {
|
|||||||
case SpoilerCollectionCheckType::SPOILER_CHK_COLLECTABLE:
|
case SpoilerCollectionCheckType::SPOILER_CHK_COLLECTABLE:
|
||||||
return (gPlayState->sceneNum == scene && gPlayState->actorCtx.flags.collect & (1 << flag)) ||
|
return (gPlayState->sceneNum == scene && gPlayState->actorCtx.flags.collect & (1 << flag)) ||
|
||||||
gSaveContext.sceneFlags[scene].collect & (1 << flag);
|
gSaveContext.sceneFlags[scene].collect & (1 << flag);
|
||||||
case SpoilerCollectionCheckType::SPOILER_CHK_MERCHANT:
|
|
||||||
case SpoilerCollectionCheckType::SPOILER_CHK_SHOP_ITEM:
|
case SpoilerCollectionCheckType::SPOILER_CHK_SHOP_ITEM:
|
||||||
case SpoilerCollectionCheckType::SPOILER_CHK_COW:
|
|
||||||
case SpoilerCollectionCheckType::SPOILER_CHK_FISH:
|
case SpoilerCollectionCheckType::SPOILER_CHK_FISH:
|
||||||
case SpoilerCollectionCheckType::SPOILER_CHK_SCRUB:
|
|
||||||
case SpoilerCollectionCheckType::SPOILER_CHK_RANDOMIZER_INF:
|
case SpoilerCollectionCheckType::SPOILER_CHK_RANDOMIZER_INF:
|
||||||
case SpoilerCollectionCheckType::SPOILER_CHK_MASTER_SWORD:
|
case SpoilerCollectionCheckType::SPOILER_CHK_MASTER_SWORD:
|
||||||
return Flags_GetRandomizerInf(OTRGlobals::Instance->gRandomizer->GetRandomizerInfFromCheck(rc));
|
return Flags_GetRandomizerInf(OTRGlobals::Instance->gRandomizer->GetRandomizerInfFromCheck(rc));
|
||||||
@ -437,8 +434,6 @@ bool HasItemBeenCollected(RandomizerCheck rc) {
|
|||||||
return gSaveContext.infTable[scene] & INDEX_TO_16BIT_LITTLE_ENDIAN_BITMASK(flag);
|
return gSaveContext.infTable[scene] & INDEX_TO_16BIT_LITTLE_ENDIAN_BITMASK(flag);
|
||||||
case SpoilerCollectionCheckType::SPOILER_CHK_ITEM_GET_INF:
|
case SpoilerCollectionCheckType::SPOILER_CHK_ITEM_GET_INF:
|
||||||
return gSaveContext.itemGetInf[flag / 16] & INDEX_TO_16BIT_LITTLE_ENDIAN_BITMASK(flag);
|
return gSaveContext.itemGetInf[flag / 16] & INDEX_TO_16BIT_LITTLE_ENDIAN_BITMASK(flag);
|
||||||
case SpoilerCollectionCheckType::SPOILER_CHK_MAGIC_BEANS:
|
|
||||||
return BEANS_BOUGHT >= 10;
|
|
||||||
case SpoilerCollectionCheckType::SPOILER_CHK_NONE:
|
case SpoilerCollectionCheckType::SPOILER_CHK_NONE:
|
||||||
return false;
|
return false;
|
||||||
case SpoilerCollectionCheckType::SPOILER_CHK_GRAVEDIGGER:
|
case SpoilerCollectionCheckType::SPOILER_CHK_GRAVEDIGGER:
|
||||||
@ -749,11 +744,8 @@ void CheckTrackerFlagSet(int16_t flagType, int32_t flag) {
|
|||||||
Rando::SpoilerCollectionCheck scCheck = loc.GetCollectionCheck();
|
Rando::SpoilerCollectionCheck scCheck = loc.GetCollectionCheck();
|
||||||
SpoilerCollectionCheckType scCheckType = scCheck.type;
|
SpoilerCollectionCheckType scCheckType = scCheck.type;
|
||||||
if (checkMatchType == SpoilerCollectionCheckType::SPOILER_CHK_RANDOMIZER_INF &&
|
if (checkMatchType == SpoilerCollectionCheckType::SPOILER_CHK_RANDOMIZER_INF &&
|
||||||
(scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_MERCHANT ||
|
(scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_SHOP_ITEM ||
|
||||||
scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_SHOP_ITEM ||
|
|
||||||
scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_COW ||
|
|
||||||
scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_FISH ||
|
scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_FISH ||
|
||||||
scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_SCRUB ||
|
|
||||||
scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_MASTER_SWORD ||
|
scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_MASTER_SWORD ||
|
||||||
scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_RANDOMIZER_INF)) {
|
scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_RANDOMIZER_INF)) {
|
||||||
if (flag == OTRGlobals::Instance->gRandomizer->GetRandomizerInfFromCheck(loc.GetRandomizerCheck())) {
|
if (flag == OTRGlobals::Instance->gRandomizer->GetRandomizerInfFromCheck(loc.GetRandomizerCheck())) {
|
||||||
@ -1343,6 +1335,11 @@ void DrawLocation(RandomizerCheck rc) {
|
|||||||
Rando::ItemLocation* itemLoc = OTRGlobals::Instance->gRandoContext->GetItemLocation(rc);
|
Rando::ItemLocation* itemLoc = OTRGlobals::Instance->gRandoContext->GetItemLocation(rc);
|
||||||
RandomizerCheckTrackerData checkData = gSaveContext.checkTrackerData[rc];
|
RandomizerCheckTrackerData checkData = gSaveContext.checkTrackerData[rc];
|
||||||
RandomizerCheckStatus status = checkData.status;
|
RandomizerCheckStatus status = checkData.status;
|
||||||
|
|
||||||
|
if (itemLoc->HasObtained()) {
|
||||||
|
status = RCSHOW_COLLECTED;
|
||||||
|
}
|
||||||
|
|
||||||
bool skipped = checkData.skipped;
|
bool skipped = checkData.skipped;
|
||||||
if (status == RCSHOW_COLLECTED) {
|
if (status == RCSHOW_COLLECTED) {
|
||||||
if (!showHidden && CVarGetInteger("gCheckTrackerCollectedHide", 0)) {
|
if (!showHidden && CVarGetInteger("gCheckTrackerCollectedHide", 0)) {
|
||||||
@ -1677,12 +1674,12 @@ void CheckTrackerWindow::InitElement() {
|
|||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnExitGame>([](uint32_t fileNum) {
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnExitGame>([](uint32_t fileNum) {
|
||||||
Teardown();
|
Teardown();
|
||||||
});
|
});
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnItemReceive>(CheckTrackerItemReceive);
|
// GameInteractor::Instance->RegisterGameHook<GameInteractor::OnItemReceive>(CheckTrackerItemReceive);
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>(CheckTrackerFrame);
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>(CheckTrackerFrame);
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnTransitionEnd>(CheckTrackerTransition);
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnTransitionEnd>(CheckTrackerTransition);
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnShopSlotChange>(CheckTrackerShopSlotChange);
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnShopSlotChange>(CheckTrackerShopSlotChange);
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneFlagSet>(CheckTrackerSceneFlagSet);
|
// GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneFlagSet>(CheckTrackerSceneFlagSet);
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnFlagSet>(CheckTrackerFlagSet);
|
// GameInteractor::Instance->RegisterGameHook<GameInteractor::OnFlagSet>(CheckTrackerFlagSet);
|
||||||
|
|
||||||
hideShopRightChecks = CVarGetInteger("gCheckTrackerOptionHideRightShopChecks", 1);
|
hideShopRightChecks = CVarGetInteger("gCheckTrackerOptionHideRightShopChecks", 1);
|
||||||
alwaysShowGS = CVarGetInteger("gCheckTrackerOptionAlwaysShowGSLocs", 0);
|
alwaysShowGS = CVarGetInteger("gCheckTrackerOptionAlwaysShowGSLocs", 0);
|
||||||
|
@ -461,34 +461,31 @@ void Entrance_SetWarpSongEntrance(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Entrance_OverrideBlueWarp(void) {
|
void Entrance_OverrideBlueWarp(void) {
|
||||||
// Set nextEntranceIndex as a flag so that Grotto_CheckSpecialEntrance
|
// Handles first time entering bluewarp (with item give)
|
||||||
// won't return index 0x7FFF, which can't work to override blue warps.
|
switch (gSaveContext.entranceIndex) {
|
||||||
gPlayState->nextEntranceIndex = 0;
|
case ENTR_KOKIRI_FOREST_11: // Gohma blue warp
|
||||||
|
case ENTR_DEATH_MOUNTAIN_TRAIL_5: // KD blue warp
|
||||||
|
case ENTR_ZORAS_FOUNTAIN_0: // Barinade blue warp
|
||||||
|
case ENTR_SACRED_FOREST_MEADOW_3: // Phantom Ganon blue warp
|
||||||
|
case ENTR_DEATH_MOUNTAIN_CRATER_5: // Volvagia blue warp
|
||||||
|
case ENTR_LAKE_HYLIA_9: // Morpha blue warp
|
||||||
|
case ENTR_DESERT_COLOSSUS_8: // Bongo-Bongo blue warp
|
||||||
|
case ENTR_GRAVEYARD_8: // Twinrova blue warp
|
||||||
|
gSaveContext.entranceIndex = Entrance_OverrideNextIndex(gSaveContext.entranceIndex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (gPlayState->sceneNum) {
|
// Handles second+ times entering bluewarp
|
||||||
case SCENE_DEKU_TREE_BOSS: // Ghoma boss room
|
switch (gPlayState->nextEntranceIndex) {
|
||||||
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(ENTR_KOKIRI_FOREST_11);
|
case ENTR_KOKIRI_FOREST_11: // Gohma blue warp
|
||||||
return;
|
case ENTR_DEATH_MOUNTAIN_TRAIL_5: // KD blue warp
|
||||||
case SCENE_DODONGOS_CAVERN_BOSS: // King Dodongo boss room
|
case ENTR_ZORAS_FOUNTAIN_0: // Barinade blue warp
|
||||||
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(ENTR_DEATH_MOUNTAIN_TRAIL_5);
|
case ENTR_SACRED_FOREST_MEADOW_3: // Phantom Ganon blue warp
|
||||||
return;
|
case ENTR_DEATH_MOUNTAIN_CRATER_5: // Volvagia blue warp
|
||||||
case SCENE_JABU_JABU_BOSS: // Barinade boss room
|
case ENTR_LAKE_HYLIA_9: // Morpha blue warp
|
||||||
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(ENTR_ZORAS_FOUNTAIN_0);
|
case ENTR_DESERT_COLOSSUS_8: // Bongo-Bongo blue warp
|
||||||
return;
|
case ENTR_GRAVEYARD_8: // Twinrova blue warp
|
||||||
case SCENE_FOREST_TEMPLE_BOSS: // Phantom Ganon boss room
|
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(gPlayState->nextEntranceIndex);
|
||||||
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(ENTR_SACRED_FOREST_MEADOW_3);
|
|
||||||
return;
|
|
||||||
case SCENE_FIRE_TEMPLE_BOSS: // Volvagia boss room
|
|
||||||
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(ENTR_DEATH_MOUNTAIN_CRATER_5);
|
|
||||||
return;
|
|
||||||
case SCENE_WATER_TEMPLE_BOSS: // Morpha boss room
|
|
||||||
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(ENTR_LAKE_HYLIA_9);
|
|
||||||
return;
|
|
||||||
case SCENE_SPIRIT_TEMPLE_BOSS: // Twinrova boss room
|
|
||||||
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(ENTR_DESERT_COLOSSUS_8);
|
|
||||||
return;
|
|
||||||
case SCENE_SHADOW_TEMPLE_BOSS: // Bongo-Bongo boss room
|
|
||||||
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(ENTR_GRAVEYARD_8);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,12 +143,15 @@ typedef enum {
|
|||||||
RAND_INF_MERCHANTS_CARPET_SALESMAN,
|
RAND_INF_MERCHANTS_CARPET_SALESMAN,
|
||||||
RAND_INF_MERCHANTS_MEDIGORON,
|
RAND_INF_MERCHANTS_MEDIGORON,
|
||||||
RAND_INF_MERCHANTS_GRANNYS_SHOP,
|
RAND_INF_MERCHANTS_GRANNYS_SHOP,
|
||||||
|
RAND_INF_MERCHANTS_MAGIC_BEAN_SALESMAN,
|
||||||
|
|
||||||
RAND_INF_ADULT_TRADES_LW_TRADE_COJIRO,
|
RAND_INF_ADULT_TRADES_LW_TRADE_COJIRO,
|
||||||
RAND_INF_ADULT_TRADES_GV_TRADE_SAW,
|
RAND_INF_ADULT_TRADES_GV_TRADE_SAW,
|
||||||
RAND_INF_ADULT_TRADES_DMT_TRADE_BROKEN_SWORD,
|
RAND_INF_ADULT_TRADES_DMT_TRADE_BROKEN_SWORD,
|
||||||
|
RAND_INF_ADULT_TRADES_ZD_TRADE_PRESCRIPTION,
|
||||||
RAND_INF_ADULT_TRADES_LH_TRADE_FROG,
|
RAND_INF_ADULT_TRADES_LH_TRADE_FROG,
|
||||||
RAND_INF_ADULT_TRADES_DMT_TRADE_EYEDROPS,
|
RAND_INF_ADULT_TRADES_DMT_TRADE_EYEDROPS,
|
||||||
|
RAND_INF_ADULT_TRADES_DMT_TRADE_CLAIM_CHECK,
|
||||||
|
|
||||||
RAND_INF_KAK_100_GOLD_SKULLTULA_REWARD,
|
RAND_INF_KAK_100_GOLD_SKULLTULA_REWARD,
|
||||||
|
|
||||||
@ -267,6 +270,13 @@ typedef enum {
|
|||||||
RAND_INF_ZD_FISH_4,
|
RAND_INF_ZD_FISH_4,
|
||||||
RAND_INF_ZD_FISH_5,
|
RAND_INF_ZD_FISH_5,
|
||||||
|
|
||||||
|
RAND_INF_LINKS_POCKET,
|
||||||
|
RAND_INF_LEARNED_EPONA_SONG,
|
||||||
|
RAND_INF_DARUNIAS_JOY,
|
||||||
|
RAND_INF_KING_ZORA_THAWED,
|
||||||
|
RAND_INF_ROLLING_GORON_AS_CHILD,
|
||||||
|
RAND_INF_ROLLING_GORON_AS_ADULT,
|
||||||
|
|
||||||
// If you add anything to this list, you need to update the size of randomizerInf in z64save.h to be ceil(RAND_INF_MAX / 16)
|
// If you add anything to this list, you need to update the size of randomizerInf in z64save.h to be ceil(RAND_INF_MAX / 16)
|
||||||
|
|
||||||
RAND_INF_MAX,
|
RAND_INF_MAX,
|
||||||
|
@ -97,6 +97,9 @@ void GiveLinksPocketItem() {
|
|||||||
if (Randomizer_GetSettingValue(RSK_LINKS_POCKET) != RO_LINKS_POCKET_NOTHING) {
|
if (Randomizer_GetSettingValue(RSK_LINKS_POCKET) != RO_LINKS_POCKET_NOTHING) {
|
||||||
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LINKS_POCKET, (GetItemID)RG_NONE);
|
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LINKS_POCKET, (GetItemID)RG_NONE);
|
||||||
StartingItemGive(getItemEntry);
|
StartingItemGive(getItemEntry);
|
||||||
|
Rando::Context::GetInstance()->GetItemLocation(RC_LINKS_POCKET)->MarkAsObtained();
|
||||||
|
// If we re-add the above, we'll get the item on save creation, now it's given on first load
|
||||||
|
Flags_SetRandomizerInf(RAND_INF_LINKS_POCKET);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,40 +205,42 @@ void SetStartingItems() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void Randomizer_InitSaveFile() {
|
extern "C" void Randomizer_InitSaveFile() {
|
||||||
// Sets all rando flags to false
|
// Now handled by cutscene skips
|
||||||
for (s32 i = 0; i < ARRAY_COUNT(gSaveContext.randomizerInf); i++) {
|
// gSaveContext.cutsceneIndex = 0; // no intro cutscene
|
||||||
gSaveContext.randomizerInf[i] = 0;
|
// Starts pending ice traps out at 0 before potentially incrementing them down the line.
|
||||||
}
|
gSaveContext.pendingIceTrapCount = 0;
|
||||||
|
|
||||||
// Reset triforce pieces collected
|
// Reset triforce pieces collected
|
||||||
gSaveContext.triforcePiecesCollected = 0;
|
gSaveContext.triforcePiecesCollected = 0;
|
||||||
|
|
||||||
gSaveContext.cutsceneIndex = 0; // no intro cutscene
|
|
||||||
// Starts pending ice traps out at 0 before potentially incrementing them down the line.
|
|
||||||
gSaveContext.pendingIceTrapCount = 0;
|
|
||||||
|
|
||||||
// Set Cutscene flags and texts to skip them
|
// Set Cutscene flags and texts to skip them
|
||||||
Flags_SetInfTable(INFTABLE_GREETED_BY_SARIA);
|
// Now handled by cutscene skips
|
||||||
|
// Flags_SetInfTable(INFTABLE_GREETED_BY_SARIA);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_FIRST_SPOKE_TO_MIDO);
|
Flags_SetEventChkInf(EVENTCHKINF_FIRST_SPOKE_TO_MIDO);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_MET_DEKU_TREE);
|
// Now handled by cutscene skips
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_DEKU_TREE_OPENED_MOUTH);
|
// Flags_SetEventChkInf(EVENTCHKINF_MET_DEKU_TREE);
|
||||||
|
// Flags_SetEventChkInf(EVENTCHKINF_DEKU_TREE_OPENED_MOUTH);
|
||||||
Flags_SetInfTable(INFTABLE_SPOKE_TO_KAEPORA_IN_LAKE_HYLIA);
|
Flags_SetInfTable(INFTABLE_SPOKE_TO_KAEPORA_IN_LAKE_HYLIA);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_MASTER_SWORD_CHAMBER);
|
// Now handled by cutscene skips
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL);
|
// Flags_SetEventChkInf(EVENTCHKINF_ENTERED_MASTER_SWORD_CHAMBER);
|
||||||
|
// Now using this to grant master sword check
|
||||||
|
// Flags_SetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_SHEIK_SPAWNED_AT_MASTER_SWORD_PEDESTAL);
|
Flags_SetEventChkInf(EVENTCHKINF_SHEIK_SPAWNED_AT_MASTER_SWORD_PEDESTAL);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS);
|
// Now used to give player LACS rewards
|
||||||
|
// Flags_SetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_RENTED_HORSE_FROM_INGO);
|
Flags_SetEventChkInf(EVENTCHKINF_RENTED_HORSE_FROM_INGO);
|
||||||
Flags_SetInfTable(INFTABLE_SPOKE_TO_POE_COLLECTOR_IN_RUINED_MARKET);
|
Flags_SetInfTable(INFTABLE_SPOKE_TO_POE_COLLECTOR_IN_RUINED_MARKET);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_WATCHED_GANONS_CASTLE_COLLAPSE_CAUGHT_BY_GERUDO);
|
Flags_SetEventChkInf(EVENTCHKINF_WATCHED_GANONS_CASTLE_COLLAPSE_CAUGHT_BY_GERUDO);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_NABOORU_IN_SPIRIT_TEMPLE);
|
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_NABOORU_IN_SPIRIT_TEMPLE);
|
||||||
|
|
||||||
Flags_SetInfTable(INFTABLE_MET_CHILD_MALON_AT_CASTLE_OR_MARKET);
|
// Now handled by cutscene skips
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_CASTLE_OR_MARKET);
|
// Flags_SetInfTable(INFTABLE_MET_CHILD_MALON_AT_CASTLE_OR_MARKET);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_INGO_AT_RANCH_BEFORE_TALON_RETURNS);
|
// Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_CASTLE_OR_MARKET);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_RANCH);
|
// Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_INGO_AT_RANCH_BEFORE_TALON_RETURNS);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_INVITED_TO_SING_WITH_CHILD_MALON);
|
// Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_RANCH);
|
||||||
Flags_SetInfTable(INFTABLE_CHILD_MALON_SAID_EPONA_WAS_AFRAID_OF_YOU);
|
// Flags_SetEventChkInf(EVENTCHKINF_INVITED_TO_SING_WITH_CHILD_MALON);
|
||||||
Flags_SetInfTable(INFTABLE_SPOKE_TO_INGO_ONCE_AS_ADULT);
|
// Flags_SetInfTable(INFTABLE_CHILD_MALON_SAID_EPONA_WAS_AFRAID_OF_YOU);
|
||||||
|
// Flags_SetInfTable(INFTABLE_SPOKE_TO_INGO_ONCE_AS_ADULT);
|
||||||
|
|
||||||
// Ruto already met in jabu and spawns down the hole immediately
|
// Ruto already met in jabu and spawns down the hole immediately
|
||||||
Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_MEET_RUTO);
|
Flags_SetInfTable(INFTABLE_RUTO_IN_JJ_MEET_RUTO);
|
||||||
@ -246,51 +251,55 @@ extern "C" void Randomizer_InitSaveFile() {
|
|||||||
Flags_SetEventChkInf(EVENTCHKINF_BEGAN_NABOORU_BATTLE);
|
Flags_SetEventChkInf(EVENTCHKINF_BEGAN_NABOORU_BATTLE);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_NABOORU_ORDERED_TO_FIGHT_BY_TWINROVA);
|
Flags_SetEventChkInf(EVENTCHKINF_NABOORU_ORDERED_TO_FIGHT_BY_TWINROVA);
|
||||||
|
|
||||||
|
// Now handled by cutscene skips
|
||||||
// Skip boss cutscenes
|
// Skip boss cutscenes
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_BEGAN_GOHMA_BATTLE);
|
// Flags_SetEventChkInf(EVENTCHKINF_BEGAN_GOHMA_BATTLE);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_BEGAN_KING_DODONGO_BATTLE);
|
// Flags_SetEventChkInf(EVENTCHKINF_BEGAN_KING_DODONGO_BATTLE);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_BEGAN_PHANTOM_GANON_BATTLE);
|
// Flags_SetEventChkInf(EVENTCHKINF_BEGAN_PHANTOM_GANON_BATTLE);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_BEGAN_VOLVAGIA_BATTLE);
|
// Flags_SetEventChkInf(EVENTCHKINF_BEGAN_VOLVAGIA_BATTLE);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_BEGAN_MORPHA_BATTLE);
|
// Flags_SetEventChkInf(EVENTCHKINF_BEGAN_MORPHA_BATTLE);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_BEGAN_TWINROVA_BATTLE);
|
// Flags_SetEventChkInf(EVENTCHKINF_BEGAN_TWINROVA_BATTLE);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_BEGAN_BARINA_BATTLE);
|
// Flags_SetEventChkInf(EVENTCHKINF_BEGAN_BARINA_BATTLE);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_BEGAN_BONGO_BONGO_BATTLE);
|
// Flags_SetEventChkInf(EVENTCHKINF_BEGAN_BONGO_BONGO_BATTLE);
|
||||||
|
|
||||||
// Entered areas
|
// Now handled by cutscene skips
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_HYRULE_FIELD);
|
// Flags_SetEventChkInf(EVENTCHKINF_ENTERED_HYRULE_FIELD);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DEATH_MOUNTAIN_TRAIL);
|
// Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DEATH_MOUNTAIN_TRAIL);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_KAKARIKO_VILLAGE);
|
// Flags_SetEventChkInf(EVENTCHKINF_ENTERED_KAKARIKO_VILLAGE);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_ZORAS_DOMAIN);
|
// Flags_SetEventChkInf(EVENTCHKINF_ENTERED_ZORAS_DOMAIN);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_HYRULE_CASTLE);
|
// Flags_SetEventChkInf(EVENTCHKINF_ENTERED_HYRULE_CASTLE);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GORON_CITY);
|
// Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GORON_CITY);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_TEMPLE_OF_TIME);
|
// Flags_SetEventChkInf(EVENTCHKINF_ENTERED_TEMPLE_OF_TIME);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DEKU_TREE);
|
// Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DEKU_TREE);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DODONGOS_CAVERN);
|
// Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DODONGOS_CAVERN);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_LAKE_HYLIA);
|
// Flags_SetEventChkInf(EVENTCHKINF_ENTERED_LAKE_HYLIA);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GERUDO_VALLEY);
|
// Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GERUDO_VALLEY);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GERUDOS_FORTRESS);
|
// Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GERUDOS_FORTRESS);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_LON_LON_RANCH);
|
// Flags_SetEventChkInf(EVENTCHKINF_ENTERED_LON_LON_RANCH);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_JABU_JABUS_BELLY);
|
// Flags_SetEventChkInf(EVENTCHKINF_ENTERED_JABU_JABUS_BELLY);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GRAVEYARD);
|
// Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GRAVEYARD);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_ZORAS_FOUNTAIN);
|
// Flags_SetEventChkInf(EVENTCHKINF_ENTERED_ZORAS_FOUNTAIN);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DESERT_COLOSSUS);
|
// Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DESERT_COLOSSUS);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DEATH_MOUNTAIN_CRATER);
|
// Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DEATH_MOUNTAIN_CRATER);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GANONS_CASTLE_EXTERIOR);
|
// Flags_SetEventChkInf(EVENTCHKINF_ENTERED_GANONS_CASTLE_EXTERIOR);
|
||||||
Flags_SetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE);
|
// Ensure Malon appears at castle first time you enter
|
||||||
|
// Flags_SetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE);
|
||||||
|
|
||||||
// skip the z target talk instructions by the kokiri shop
|
// skip the z target talk instructions by the kokiri shop
|
||||||
gSaveContext.sceneFlags[SCENE_KOKIRI_FOREST].swch |= (1 << 0x1F);
|
// Now handled by cutscene skips
|
||||||
|
// gSaveContext.sceneFlags[SCENE_KOKIRI_FOREST].swch |= (1 << 0x1F);
|
||||||
|
|
||||||
// Go away ruto (water temple first cutscene)
|
// Go away ruto (water temple first cutscene)
|
||||||
gSaveContext.sceneFlags[SCENE_WATER_TEMPLE].swch |= (1 << 0x10);
|
gSaveContext.sceneFlags[SCENE_WATER_TEMPLE].swch |= (1 << 0x10);
|
||||||
|
|
||||||
|
// Now handled by cutscene skips
|
||||||
// no more kaepora
|
// no more kaepora
|
||||||
gSaveContext.sceneFlags[SCENE_HYRULE_FIELD].swch |= (1 << 0xC); // hyrule field kaepora outside kokiri forest
|
// gSaveContext.sceneFlags[SCENE_HYRULE_FIELD].swch |= (1 << 0xC); // hyrule field kaepora outside kokiri forest
|
||||||
gSaveContext.sceneFlags[SCENE_HYRULE_FIELD].swch |= (1 << 0xB); // hyrule field kaepora outside lake hylia
|
// gSaveContext.sceneFlags[SCENE_HYRULE_FIELD].swch |= (1 << 0xB); // hyrule field kaepora outside lake hylia
|
||||||
gSaveContext.sceneFlags[SCENE_LOST_WOODS].swch |= (1 << 0x7); // lost woods kaepora pre-saria
|
// gSaveContext.sceneFlags[SCENE_LOST_WOODS].swch |= (1 << 0x7); // lost woods kaepora pre-saria
|
||||||
gSaveContext.sceneFlags[SCENE_LOST_WOODS].swch |= (1 << 0x8); // lost woods kaepora post-saria
|
// gSaveContext.sceneFlags[SCENE_LOST_WOODS].swch |= (1 << 0x8); // lost woods kaepora post-saria
|
||||||
gSaveContext.sceneFlags[SCENE_DESERT_COLOSSUS].swch |= (1 << 0x1F); // desert colossus kaepora
|
// gSaveContext.sceneFlags[SCENE_DESERT_COLOSSUS].swch |= (1 << 0x1F); // desert colossus kaepora
|
||||||
gSaveContext.sceneFlags[SCENE_HYRULE_CASTLE].swch |= (1 << 0x5); // hyrule castle kaepora
|
// gSaveContext.sceneFlags[SCENE_HYRULE_CASTLE].swch |= (1 << 0x5); // hyrule castle kaepora
|
||||||
|
|
||||||
if (!Randomizer_GetSettingValue(RSK_ENABLE_GLITCH_CUTSCENES)) {
|
if (!Randomizer_GetSettingValue(RSK_ENABLE_GLITCH_CUTSCENES)) {
|
||||||
Flags_SetInfTable(INFTABLE_SPOKE_TO_DARUNIA_IN_FIRE_TEMPLE); // Darunia in Fire Temple
|
Flags_SetInfTable(INFTABLE_SPOKE_TO_DARUNIA_IN_FIRE_TEMPLE); // Darunia in Fire Temple
|
||||||
@ -398,15 +407,16 @@ extern "C" void Randomizer_InitSaveFile() {
|
|||||||
gSaveContext.sceneFlags[SCENE_WATER_TEMPLE].swch |= (1 << 0x15);
|
gSaveContext.sceneFlags[SCENE_WATER_TEMPLE].swch |= (1 << 0x15);
|
||||||
}
|
}
|
||||||
|
|
||||||
int openForest = Randomizer_GetSettingValue(RSK_FOREST);
|
// Now handled on the fly
|
||||||
switch (openForest) {
|
// int openForest = Randomizer_GetSettingValue(RSK_FOREST);
|
||||||
case RO_FOREST_OPEN:
|
// switch (openForest) {
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD);
|
// case RO_FOREST_OPEN:
|
||||||
// Fallthrough
|
// Flags_SetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD);
|
||||||
case RO_FOREST_CLOSED_DEKU:
|
// // Fallthrough
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD);
|
// case RO_FOREST_CLOSED_DEKU:
|
||||||
break;
|
// Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD);
|
||||||
}
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
int doorOfTime = Randomizer_GetSettingValue(RSK_DOOR_OF_TIME);
|
int doorOfTime = Randomizer_GetSettingValue(RSK_DOOR_OF_TIME);
|
||||||
switch (doorOfTime) {
|
switch (doorOfTime) {
|
||||||
|
788
soh/soh/Enhancements/timesaver_hook_handlers.cpp
Normal file
788
soh/soh/Enhancements/timesaver_hook_handlers.cpp
Normal file
@ -0,0 +1,788 @@
|
|||||||
|
#include <libultraship/bridge.h>
|
||||||
|
#include "soh/OTRGlobals.h"
|
||||||
|
#include "soh/Enhancements/randomizer/randomizerTypes.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "src/overlays/actors/ovl_En_Wonder_Talk2/z_en_wonder_talk2.h"
|
||||||
|
#include "src/overlays/actors/ovl_Elf_Msg/z_elf_msg.h"
|
||||||
|
#include "src/overlays/actors/ovl_Obj_Switch/z_obj_switch.h"
|
||||||
|
#include "src/overlays/actors/ovl_Bg_Bdan_Switch/z_bg_bdan_switch.h"
|
||||||
|
#include "src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h"
|
||||||
|
#include "src/overlays/actors/ovl_En_Owl/z_en_owl.h"
|
||||||
|
#include "src/overlays/actors/ovl_En_Ko/z_en_ko.h"
|
||||||
|
#include "src/overlays/actors/ovl_En_Ma1/z_en_ma1.h"
|
||||||
|
#include "src/overlays/actors/ovl_En_Zl4/z_en_zl4.h"
|
||||||
|
#include "src/overlays/actors/ovl_Demo_Im/z_demo_im.h"
|
||||||
|
#include "src/overlays/actors/ovl_En_Sa/z_en_sa.h"
|
||||||
|
#include "src/overlays/actors/ovl_Bg_Ddan_Kd/z_bg_ddan_kd.h"
|
||||||
|
#include "src/overlays/actors/ovl_En_Tk/z_en_tk.h"
|
||||||
|
extern SaveContext gSaveContext;
|
||||||
|
extern PlayState* gPlayState;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetSelectedOptionIndex()
|
||||||
|
|
||||||
|
void EnKo_MoveWhenReady(EnKo* enKo, PlayState* play) {
|
||||||
|
func_80A995CC(enKo, play);
|
||||||
|
|
||||||
|
if ((enKo->actor.params & 0xFF) == ENKO_TYPE_CHILD_3) {
|
||||||
|
// Typically this doesn't get get live updated in vanilla, but we need to
|
||||||
|
// live update it if we're skipping a certain cutscene or in randomizer
|
||||||
|
if (GameInteractor_Should(GI_VB_OPEN_KOKIRI_FOREST, CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD), NULL)) {
|
||||||
|
enKo->collider.dim.height -= 200;
|
||||||
|
Path_CopyLastPoint(enKo->path, &enKo->actor.world.pos);
|
||||||
|
enKo->actionFunc = func_80A99384;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnMa1_EndTeachSong(EnMa1* enMa1, PlayState* play) {
|
||||||
|
if (Message_GetState(&gPlayState->msgCtx) == TEXT_STATE_CLOSING) {
|
||||||
|
Flags_SetRandomizerInf(RAND_INF_LEARNED_EPONA_SONG);
|
||||||
|
func_80078884(NA_SE_SY_CORRECT_CHIME);
|
||||||
|
enMa1->actor.flags &= ~ACTOR_FLAG_WILL_TALK;
|
||||||
|
play->msgCtx.ocarinaMode = OCARINA_MODE_04;
|
||||||
|
enMa1->actionFunc = func_80AA0D88;
|
||||||
|
enMa1->unk_1E0 = 1;
|
||||||
|
enMa1->interactInfo.talkState = NPC_TALK_STATE_IDLE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 EnZl4_GiveItemTextId(PlayState* play, Actor* actor) {
|
||||||
|
return 0x207D;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnZl4_SkipToGivingZeldasLetter(EnZl4* enZl4, PlayState* play) {
|
||||||
|
if (enZl4->csState == 0 && enZl4->actor.xzDistToPlayer < 600.0f && EnZl4_SetNextAnim(enZl4, 3)) {
|
||||||
|
Audio_PlayFanfare(NA_BGM_APPEAR);
|
||||||
|
enZl4->csState = 8; // ZL4_CS_PLAN
|
||||||
|
} else {
|
||||||
|
Npc_UpdateTalking(play, &enZl4->actor, &enZl4->interactInfo.talkState, enZl4->collider.dim.radius + 60.0f, EnZl4_GiveItemTextId, func_80B5B9B0);
|
||||||
|
func_80B5BB78(enZl4, play);
|
||||||
|
|
||||||
|
if (enZl4->interactInfo.talkState != NPC_TALK_STATE_IDLE) {
|
||||||
|
enZl4->talkState = 6;
|
||||||
|
enZl4->actionFunc = EnZl4_Cutscene;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int successChimeCooldown = 0;
|
||||||
|
void RateLimitedSuccessChime() {
|
||||||
|
if (successChimeCooldown == 0) {
|
||||||
|
func_80078884(NA_SE_SY_CORRECT_CHIME);
|
||||||
|
successChimeCooldown = 120;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimeSaverOnGameFrameUpdateHandler() {
|
||||||
|
if (successChimeCooldown > 0) {
|
||||||
|
successChimeCooldown--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* opt) {
|
||||||
|
switch (id) {
|
||||||
|
case GI_VB_PLAY_TRANSITION_CS:
|
||||||
|
if (CVarGetInteger("gTimeSavers.SkipCutscene.Intro", 0) && gSaveContext.entranceIndex == ENTR_LINKS_HOUSE_0 && gSaveContext.cutsceneIndex == 0xFFF1) {
|
||||||
|
gSaveContext.cutsceneIndex = 0;
|
||||||
|
*should = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", 0) || IS_RANDO) {
|
||||||
|
// Song of Time
|
||||||
|
if (gSaveContext.entranceIndex == ENTR_TEMPLE_OF_TIME_0 && gSaveContext.cutsceneIndex == 0xFFF7) {
|
||||||
|
gSaveContext.entranceIndex = ENTR_HYRULE_FIELD_16;
|
||||||
|
gSaveContext.cutsceneIndex = 0;
|
||||||
|
gSaveContext.nextTransitionType = 3;
|
||||||
|
*should = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Requiem of Spirit
|
||||||
|
if ((gSaveContext.entranceIndex == ENTR_DESERT_COLOSSUS_1) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT)) {
|
||||||
|
Flags_SetEventChkInf(EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT);
|
||||||
|
// Normally happens in the cutscene
|
||||||
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_REQUIEM_OF_SPIRIT, true, NULL)) {
|
||||||
|
Item_Give(gPlayState, ITEM_SONG_REQUIEM);
|
||||||
|
}
|
||||||
|
*should = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 meetsBurningKakRequirements =
|
||||||
|
LINK_IS_ADULT &&
|
||||||
|
gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_0 &&
|
||||||
|
Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP) &&
|
||||||
|
Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP) &&
|
||||||
|
Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP) &&
|
||||||
|
!Flags_GetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL);
|
||||||
|
if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_NOCTURNE_OF_SHADOW, meetsBurningKakRequirements, NULL)) {
|
||||||
|
Flags_SetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL);
|
||||||
|
// Normally happens in the cutscene
|
||||||
|
Flags_SetEventChkInf(EVENTCHKINF_LEARNED_NOCTURNE_OF_SHADOW);
|
||||||
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_NOCTURNE_OF_SHADOW, true, NULL)) {
|
||||||
|
Item_Give(gPlayState, ITEM_SONG_NOCTURNE);
|
||||||
|
}
|
||||||
|
*should = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0)) {
|
||||||
|
uint8_t isBlueWarp = 0;
|
||||||
|
// Deku Tree Blue warp
|
||||||
|
if (gSaveContext.entranceIndex == ENTR_KOKIRI_FOREST_0 && gSaveContext.cutsceneIndex == 0xFFF1) {
|
||||||
|
gSaveContext.dayTime = gSaveContext.skyboxTime = 0x8000;
|
||||||
|
|
||||||
|
gSaveContext.entranceIndex = ENTR_KOKIRI_FOREST_11;
|
||||||
|
isBlueWarp = 1;
|
||||||
|
// Dodongo's Cavern Blue warp
|
||||||
|
} else if (gSaveContext.entranceIndex == ENTR_DEATH_MOUNTAIN_TRAIL_0 && gSaveContext.cutsceneIndex == 0xFFF1) {
|
||||||
|
gSaveContext.entranceIndex = ENTR_DEATH_MOUNTAIN_TRAIL_5;
|
||||||
|
isBlueWarp = 1;
|
||||||
|
// Jabu Jabu's Blue warp
|
||||||
|
} else if (gSaveContext.entranceIndex == ENTR_ZORAS_FOUNTAIN_0 && gSaveContext.cutsceneIndex == 0xFFF0) {
|
||||||
|
gSaveContext.entranceIndex = ENTR_ZORAS_FOUNTAIN_0;
|
||||||
|
isBlueWarp = 1;
|
||||||
|
// Forest Temple Blue warp
|
||||||
|
} else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_FOREST) {
|
||||||
|
// Normally set in the blue warp cutscene
|
||||||
|
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_DEKU_TREE_SPROUT);
|
||||||
|
gSaveContext.dayTime = gSaveContext.skyboxTime = 0x8000;
|
||||||
|
|
||||||
|
gSaveContext.entranceIndex = ENTR_SACRED_FOREST_MEADOW_3;
|
||||||
|
isBlueWarp = 1;
|
||||||
|
// Fire Temple Blue warp
|
||||||
|
} else if (gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_0 && gSaveContext.cutsceneIndex == 0xFFF3) {
|
||||||
|
gSaveContext.entranceIndex = ENTR_DEATH_MOUNTAIN_CRATER_5;
|
||||||
|
isBlueWarp = 1;
|
||||||
|
// Water Temple Blue warp
|
||||||
|
} else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_WATER) {
|
||||||
|
gSaveContext.entranceIndex = ENTR_LAKE_HYLIA_9;
|
||||||
|
isBlueWarp = 1;
|
||||||
|
// Spirit Temple Blue warp
|
||||||
|
} else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_SPIRIT) {
|
||||||
|
gSaveContext.entranceIndex = ENTR_DESERT_COLOSSUS_8;
|
||||||
|
isBlueWarp = 1;
|
||||||
|
// Shadow Temple Blue warp
|
||||||
|
} else if (gSaveContext.entranceIndex == ENTR_CHAMBER_OF_THE_SAGES_0 && gSaveContext.cutsceneIndex == 0x0 && gSaveContext.chamberCutsceneNum == CHAMBER_CS_SHADOW) {
|
||||||
|
gSaveContext.entranceIndex = ENTR_GRAVEYARD_8;
|
||||||
|
isBlueWarp = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isBlueWarp) {
|
||||||
|
*should = false;
|
||||||
|
gSaveContext.cutsceneIndex = 0;
|
||||||
|
|
||||||
|
if (IS_RANDO && (RAND_GET_OPTION(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF || RAND_GET_OPTION(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF)) {
|
||||||
|
Entrance_OverrideBlueWarp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flee hyrule castle cutscene
|
||||||
|
if (gSaveContext.entranceIndex == ENTR_HYRULE_FIELD_0 && gSaveContext.cutsceneIndex == 0xFFF1) {
|
||||||
|
gSaveContext.cutsceneIndex = 0;
|
||||||
|
*should = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lost Woods Bridge
|
||||||
|
if ((gSaveContext.entranceIndex == ENTR_LOST_WOODS_9) && !Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE)) {
|
||||||
|
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE);
|
||||||
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FAIRY_OCARINA, true, NULL)) {
|
||||||
|
Item_Give(gPlayState, ITEM_OCARINA_FAIRY);
|
||||||
|
}
|
||||||
|
*should = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// LACS
|
||||||
|
u8 meetsLACSRequirements =
|
||||||
|
LINK_IS_ADULT &&
|
||||||
|
(gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_TEMPLE_OF_TIME) &&
|
||||||
|
CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) &&
|
||||||
|
CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) &&
|
||||||
|
!Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS);
|
||||||
|
if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_LIGHT_ARROWS, meetsLACSRequirements, NULL)) {
|
||||||
|
Flags_SetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS);
|
||||||
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_LIGHT_ARROW, true, NULL)) {
|
||||||
|
Item_Give(gPlayState, ITEM_ARROW_LIGHT);
|
||||||
|
}
|
||||||
|
*should = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GI_VB_PLAY_ENTRANCE_CS: {
|
||||||
|
s32* entranceFlag = static_cast<s32*>(opt);
|
||||||
|
if (CVarGetInteger("gTimeSavers.SkipCutscene.Entrances", 0) && (*entranceFlag != EVENTCHKINF_EPONA_OBTAINED)) {
|
||||||
|
*should = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_PLAY_ONEPOINT_CS: {
|
||||||
|
if (CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", 0)) {
|
||||||
|
s16* csId = static_cast<s16*>(opt);
|
||||||
|
switch (*csId) {
|
||||||
|
case 4180:
|
||||||
|
case 4100:
|
||||||
|
*should = false;
|
||||||
|
RateLimitedSuccessChime();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SPDLOG_INFO("GI_VB_PLAY_ONEPOINT_CS {}", *csId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_PLAY_ONEPOINT_ACTOR_CS: {
|
||||||
|
if (CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", 0)) {
|
||||||
|
Actor* actor = static_cast<Actor*>(opt);
|
||||||
|
switch (actor->category) {
|
||||||
|
case ACTORCAT_BG:
|
||||||
|
if (actor->id == ACTOR_BG_DDAN_KD) {
|
||||||
|
BgDdanKd* ddanKd = static_cast<BgDdanKd*>(opt);
|
||||||
|
Flags_SetSwitch(gPlayState, ddanKd->dyna.actor.params);
|
||||||
|
}
|
||||||
|
if (actor->id == ACTOR_BG_MORI_HINERI) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
RateLimitedSuccessChime();
|
||||||
|
*should = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (actor->id) {
|
||||||
|
case ACTOR_OBJ_SWITCH: {
|
||||||
|
ObjSwitch *switchActor = static_cast<ObjSwitch*>(opt);
|
||||||
|
switchActor->cooldownTimer = 0;
|
||||||
|
*should = false;
|
||||||
|
RateLimitedSuccessChime();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ACTOR_BG_BDAN_SWITCH: {
|
||||||
|
BgBdanSwitch* switchActor = static_cast<BgBdanSwitch*>(opt);
|
||||||
|
switchActor->unk_1D8 = 0;
|
||||||
|
switchActor->unk_1DA = 0;
|
||||||
|
*should = false;
|
||||||
|
RateLimitedSuccessChime();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// case ACTOR_PLAYER: // This might cause issues
|
||||||
|
case ACTOR_EN_TA:
|
||||||
|
case ACTOR_DOOR_SHUTTER:
|
||||||
|
case ACTOR_EN_BOX:
|
||||||
|
case ACTOR_OBJ_SYOKUDAI:
|
||||||
|
case ACTOR_OBJ_TIMEBLOCK:
|
||||||
|
case ACTOR_EN_PO_SISTERS:
|
||||||
|
// Prop
|
||||||
|
case ACTOR_OBJ_ICE_POLY:
|
||||||
|
case ACTOR_BG_YDAN_MARUTA:
|
||||||
|
case ACTOR_BG_SPOT18_SHUTTER:
|
||||||
|
case ACTOR_BG_SPOT05_SOKO:
|
||||||
|
case ACTOR_BG_SPOT18_BASKET:
|
||||||
|
// BG
|
||||||
|
// case ACTOR_BG_YDAN_SP:
|
||||||
|
// case ACTOR_BG_YDAN_HASI:
|
||||||
|
// case ACTOR_BG_DODOAGO:
|
||||||
|
// case ACTOR_BG_DDAN_KD:
|
||||||
|
// case ACTOR_BG_DDAN_JD:
|
||||||
|
*should = false;
|
||||||
|
RateLimitedSuccessChime();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (*should) {
|
||||||
|
SPDLOG_INFO("GI_VB_PLAY_ONEPOINT_ACTOR_CS ID:{} Cat:{}", actor->id, actor->category);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_SHOW_TITLE_CARD:
|
||||||
|
if (CVarGetInteger("gTimeSavers.DisableTitleCard", 0)) {
|
||||||
|
*should = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GI_VB_WONDER_TALK: {
|
||||||
|
if (CVarGetInteger("gTimeSavers.NoForcedDialog", 0)) {
|
||||||
|
*should = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_NAVI_TALK: {
|
||||||
|
if (CVarGetInteger("gTimeSavers.NoForcedDialog", 0)) {
|
||||||
|
ElfMsg* naviTalk = static_cast<ElfMsg*>(opt);
|
||||||
|
Flags_SetSwitch(gPlayState, (naviTalk->actor.params >> 8) & 0x3F);
|
||||||
|
Actor_Kill(&naviTalk->actor);
|
||||||
|
*should = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_NOT_BE_GREETED_BY_SARIA:
|
||||||
|
if (CVarGetInteger("gTimeSavers.SkipCutscene.Entrances", 0) && !Flags_GetInfTable(INFTABLE_GREETED_BY_SARIA)) {
|
||||||
|
Flags_SetInfTable(INFTABLE_GREETED_BY_SARIA);
|
||||||
|
*should = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GI_VB_MOVE_MIDO_IN_KOKIRI_FOREST:
|
||||||
|
if (
|
||||||
|
CVarGetInteger("gTimeSavers.SkipMiscInteractions", 0) &&
|
||||||
|
!Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD) &&
|
||||||
|
(CUR_EQUIP_VALUE(EQUIP_TYPE_SHIELD) == EQUIP_VALUE_SHIELD_DEKU) &&
|
||||||
|
(CUR_EQUIP_VALUE(EQUIP_TYPE_SWORD) == EQUIP_VALUE_SWORD_KOKIRI)
|
||||||
|
) {
|
||||||
|
Flags_SetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD);
|
||||||
|
*should = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GI_VB_PLAY_DEKU_TREE_INTRO_CS: {
|
||||||
|
if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0)) {
|
||||||
|
BgTreemouth* treeMouth = static_cast<BgTreemouth*>(opt);
|
||||||
|
Flags_SetEventChkInf(EVENTCHKINF_DEKU_TREE_OPENED_MOUTH);
|
||||||
|
Audio_PlaySoundGeneral(NA_SE_EV_WOODDOOR_OPEN, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
|
||||||
|
BgTreemouth_SetupAction(treeMouth, func_808BC6F8);
|
||||||
|
*should = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_GIVE_ITEM_FROM_BLUE_WARP:
|
||||||
|
case GI_VB_PLAY_SHIEK_BLOCK_MASTER_SWORD_CS:
|
||||||
|
case GI_VB_GIVE_ITEM_FAIRY_OCARINA:
|
||||||
|
case GI_VB_GIVE_ITEM_LIGHT_ARROW:
|
||||||
|
if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0)) {
|
||||||
|
*should = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GI_VB_PLAY_NABOORU_CAPTURED_CS:
|
||||||
|
if (*should == true && CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0)) {
|
||||||
|
Flags_SetEventChkInf(EVENTCHKINF_NABOORU_CAPTURED_BY_TWINROVA);
|
||||||
|
*should = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GI_VB_PLAY_PULL_MASTER_SWORD_CS:
|
||||||
|
if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0)) {
|
||||||
|
if (!Flags_GetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL)) {
|
||||||
|
// Normally, these would be done in the cutscene, but we're skipping it
|
||||||
|
Flags_SetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL);
|
||||||
|
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_MASTER_SWORD_CHAMBER);
|
||||||
|
Flags_SetEventChkInf(EVENTCHKINF_SHEIK_SPAWNED_AT_MASTER_SWORD_PEDESTAL);
|
||||||
|
Flags_SetEventChkInf(EVENTCHKINF_TIME_TRAVELED_TO_ADULT);
|
||||||
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_LIGHT_MEDALLION, true, NULL)) {
|
||||||
|
Item_Give(gPlayState, ITEM_MEDALLION_LIGHT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*should = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GI_VB_OWL_INTERACTION: {
|
||||||
|
if (CVarGetInteger("gTimeSavers.SkipOwlInteractions", 0) && *should) {
|
||||||
|
EnOwl* enOwl = static_cast<EnOwl*>(opt);
|
||||||
|
s32 owlType = (enOwl->actor.params & 0xFC0) >> 6;
|
||||||
|
|
||||||
|
if (((enOwl->actor.params & 0xFC0) >> 6) == 1) {
|
||||||
|
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_KAEPORA_BY_LOST_WOODS);
|
||||||
|
}
|
||||||
|
|
||||||
|
func_80ACA62C(enOwl, gPlayState);
|
||||||
|
*should = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_PLAY_EYEDROP_CREATION_ANIM:
|
||||||
|
case GI_VB_PLAY_EYEDROPS_CS:
|
||||||
|
case GI_VB_PLAY_DROP_FISH_FOR_JABU_CS:
|
||||||
|
case GI_VB_PLAY_DARUNIAS_JOY_CS:
|
||||||
|
if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", 0)) {
|
||||||
|
*should = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GI_VB_PLAY_ZELDAS_LULLABY_CS: {
|
||||||
|
if (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", 0) || IS_RANDO) {
|
||||||
|
DemoIm* demoIm = static_cast<DemoIm*>(opt);
|
||||||
|
Player* player = GET_PLAYER(gPlayState);
|
||||||
|
player->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE;
|
||||||
|
player->stateFlags1 |= PLAYER_STATE1_GETTING_ITEM;
|
||||||
|
func_80986794(demoIm);
|
||||||
|
|
||||||
|
static uint32_t demoImUpdateHook = 0;
|
||||||
|
static uint32_t demoImKillHook = 0;
|
||||||
|
demoImUpdateHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* actorRef) mutable {
|
||||||
|
Actor* actor = static_cast<Actor*>(actorRef);
|
||||||
|
if (actor->id == ACTOR_DEMO_IM && (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", 0) || IS_RANDO)) {
|
||||||
|
DemoIm* demoIm = static_cast<DemoIm*>(actorRef);
|
||||||
|
Player* player = GET_PLAYER(gPlayState);
|
||||||
|
player->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE;
|
||||||
|
player->stateFlags1 |= PLAYER_STATE1_GETTING_ITEM;
|
||||||
|
|
||||||
|
if (Animation_OnFrame(&demoIm->skelAnime, 25.0f)) {
|
||||||
|
Audio_PlaySoundGeneral(NA_SE_IT_DEKU, &demoIm->actor.projectedPos, 4, &D_801333E0, &D_801333E0, &D_801333E8);
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorUpdate>(demoImUpdateHook);
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneInit>(demoImKillHook);
|
||||||
|
demoImUpdateHook = 0;
|
||||||
|
demoImKillHook = 0;
|
||||||
|
} else if (Animation_OnFrame(&demoIm->skelAnime, 15.0f)) {
|
||||||
|
Player* player = GET_PLAYER(gPlayState);
|
||||||
|
// SOH [Randomizer] In entrance rando have impa bring link back to the front of castle grounds
|
||||||
|
if (IS_RANDO && RAND_GET_OPTION(RSK_SHUFFLE_OVERWORLD_ENTRANCES)) {
|
||||||
|
gPlayState->nextEntranceIndex = ENTR_HYRULE_CASTLE_0;
|
||||||
|
} else {
|
||||||
|
gPlayState->nextEntranceIndex = ENTR_HYRULE_FIELD_17;
|
||||||
|
}
|
||||||
|
gPlayState->transitionType = TRANS_TYPE_FADE_WHITE;
|
||||||
|
gPlayState->transitionTrigger = TRANS_TRIGGER_START;
|
||||||
|
gSaveContext.nextTransitionType = 2;
|
||||||
|
func_8002DF54(gPlayState, &player->actor, 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
demoImKillHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int16_t sceneNum) mutable {
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorUpdate>(demoImUpdateHook);
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneInit>(demoImKillHook);
|
||||||
|
demoImUpdateHook = 0;
|
||||||
|
demoImKillHook = 0;
|
||||||
|
});
|
||||||
|
*should = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_PLAY_SARIAS_SONG_CS: {
|
||||||
|
if (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", 0) || IS_RANDO) {
|
||||||
|
EnSa* enSa = static_cast<EnSa*>(opt);
|
||||||
|
enSa->actionFunc = func_80AF6B20;
|
||||||
|
*should = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_DESPAWN_HORSE_RACE_COW: {
|
||||||
|
if (Flags_GetEventChkInf(EVENTCHKINF_WON_COW_IN_MALONS_RACE) && CVarGetInteger("gCowOfTime", 0)) {
|
||||||
|
*should = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GI_VB_GIVE_ITEM_MINUET_OF_FOREST:
|
||||||
|
case GI_VB_GIVE_ITEM_BOLERO_OF_FIRE:
|
||||||
|
case GI_VB_GIVE_ITEM_SERENADE_OF_WATER:
|
||||||
|
case GI_VB_GIVE_ITEM_REQUIEM_OF_SPIRIT:
|
||||||
|
case GI_VB_GIVE_ITEM_NOCTURNE_OF_SHADOW:
|
||||||
|
case GI_VB_GIVE_ITEM_PRELUDE_OF_LIGHT:
|
||||||
|
case GI_VB_GIVE_ITEM_ZELDAS_LULLABY:
|
||||||
|
case GI_VB_GIVE_ITEM_EPONAS_SONG:
|
||||||
|
case GI_VB_GIVE_ITEM_SARIAS_SONG:
|
||||||
|
case GI_VB_GIVE_ITEM_SUNS_SONG:
|
||||||
|
case GI_VB_GIVE_ITEM_SONG_OF_TIME:
|
||||||
|
case GI_VB_GIVE_ITEM_SONG_OF_STORMS:
|
||||||
|
case GI_VB_PLAY_MINUET_OF_FOREST_CS:
|
||||||
|
case GI_VB_PLAY_BOLERO_OF_FIRE_CS:
|
||||||
|
case GI_VB_PLAY_SERENADE_OF_WATER_CS:
|
||||||
|
case GI_VB_PLAY_PRELUDE_OF_LIGHT_CS:
|
||||||
|
if (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", 0) || IS_RANDO) {
|
||||||
|
*should = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GI_VB_DAMPE_IN_GRAVEYARD_DESPAWN:
|
||||||
|
if (CVarGetInteger("gDampeAllNight", 0)) {
|
||||||
|
*should = LINK_IS_ADULT || gPlayState->sceneNum != SCENE_GRAVEYARD;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GI_VB_BE_VALID_GRAVEDIGGING_SPOT:
|
||||||
|
if (CVarGetInteger("gDampeWin", 0)) {
|
||||||
|
EnTk *enTk = static_cast<EnTk*>(opt);
|
||||||
|
enTk->validDigHere = true;
|
||||||
|
*should = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GI_VB_BE_DAMPE_GRAVEDIGGING_GRAND_PRIZE:
|
||||||
|
if (CVarGetInteger("gDampeWin", 0)) {
|
||||||
|
EnTk *enTk = static_cast<EnTk*>(opt);
|
||||||
|
enTk->currentReward = 3;
|
||||||
|
*should = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GI_VB_DAMPE_GRAVEDIGGING_GRAND_PRIZE_BE_HEART_PIECE:
|
||||||
|
if (CVarGetInteger("gGravediggingTourFix", 0) || IS_RANDO) {
|
||||||
|
*should = !Flags_GetCollectible(gPlayState, COLLECTFLAG_GRAVEDIGGING_HEART_PIECE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GI_VB_FIX_SAW_SOFTLOCK:
|
||||||
|
// Animation Count should be no more than 1 to guarantee putaway is complete after giving the saw
|
||||||
|
// As this is vanilla behavior, it only applies with the Fix toggle or Skip Text enabled.
|
||||||
|
*should = (CVarGetInteger("gFixSawSoftlock", 0) != 0 || CVarGetInteger("gSkipText", 0) != 0) ? gPlayState->animationCtx.animationCount > 1 : *should;
|
||||||
|
break;
|
||||||
|
case GI_VB_BIGGORON_CONSIDER_SWORD_FORGED:
|
||||||
|
*should = Environment_GetBgsDayCount() >= CVarGetInteger("gForgeTime", 3);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t enKoUpdateHook = 0;
|
||||||
|
static uint32_t enKoKillHook = 0;
|
||||||
|
static uint32_t itemOcarinaUpdateHook = 0;
|
||||||
|
static uint32_t itemOcarinaframesSinceSpawn = 0;
|
||||||
|
static uint32_t enMa1UpdateHook = 0;
|
||||||
|
static uint32_t enMa1KillHook = 0;
|
||||||
|
void TimeSaverOnActorInitHandler(void* actorRef) {
|
||||||
|
Actor* actor = static_cast<Actor*>(actorRef);
|
||||||
|
|
||||||
|
if (actor->id == ACTOR_EN_KO && (actor->params & 0xFF) == ENKO_TYPE_CHILD_3) {
|
||||||
|
enKoUpdateHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* innerActorRef) mutable {
|
||||||
|
Actor* innerActor = static_cast<Actor*>(innerActorRef);
|
||||||
|
if (innerActor->id == ACTOR_EN_KO && (innerActor->params & 0xFF) == ENKO_TYPE_CHILD_3 && (CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0) || IS_RANDO)) {
|
||||||
|
EnKo* enKo = static_cast<EnKo*>(innerActorRef);
|
||||||
|
// They haven't moved yet, wrap their update function so we check every frame
|
||||||
|
if (enKo->actionFunc == func_80A995CC) {
|
||||||
|
enKo->actionFunc = EnKo_MoveWhenReady;
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorUpdate>(enKoUpdateHook);
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneInit>(enKoKillHook);
|
||||||
|
enKoUpdateHook = 0;
|
||||||
|
enKoKillHook = 0;
|
||||||
|
// They have already moved
|
||||||
|
} else if (enKo->actionFunc == func_80A99384) {
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorUpdate>(enKoUpdateHook);
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneInit>(enKoKillHook);
|
||||||
|
enKoUpdateHook = 0;
|
||||||
|
enKoKillHook = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
enKoKillHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int16_t sceneNum) mutable {
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorUpdate>(enKoUpdateHook);
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneInit>(enKoKillHook);
|
||||||
|
enKoUpdateHook = 0;
|
||||||
|
enKoKillHook = 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actor->id == ACTOR_ITEM_OCARINA && actor->params == 3 && CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0)) {
|
||||||
|
itemOcarinaframesSinceSpawn = 0;
|
||||||
|
itemOcarinaUpdateHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* innerActorRef) mutable {
|
||||||
|
Actor* innerActor = static_cast<Actor*>(innerActorRef);
|
||||||
|
if (innerActor->id != ACTOR_ITEM_OCARINA || innerActor->params != 3) return;
|
||||||
|
itemOcarinaframesSinceSpawn++;
|
||||||
|
if (itemOcarinaframesSinceSpawn > 20) {
|
||||||
|
Audio_PlayActorSound2(innerActor, NA_SE_EV_BOMB_DROP_WATER);
|
||||||
|
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorUpdate>(itemOcarinaUpdateHook);
|
||||||
|
itemOcarinaUpdateHook = 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actor->id == ACTOR_EN_MA1 && gPlayState->sceneNum == SCENE_LON_LON_RANCH) {
|
||||||
|
enMa1UpdateHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorUpdate>([](void* innerActorRef) mutable {
|
||||||
|
Actor* innerActor = static_cast<Actor*>(innerActorRef);
|
||||||
|
if (innerActor->id == ACTOR_EN_MA1 && (CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", 0) || IS_RANDO)) {
|
||||||
|
EnMa1* enMa1 = static_cast<EnMa1*>(innerActorRef);
|
||||||
|
if (enMa1->actionFunc == func_80AA106C) {
|
||||||
|
enMa1->actionFunc = EnMa1_EndTeachSong;
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorUpdate>(enMa1UpdateHook);
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneInit>(enMa1KillHook);
|
||||||
|
enMa1UpdateHook = 0;
|
||||||
|
enMa1KillHook = 0;
|
||||||
|
// They've already learned the song
|
||||||
|
} else if (enMa1->actionFunc == func_80AA0D88) {
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorUpdate>(enMa1UpdateHook);
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneInit>(enMa1KillHook);
|
||||||
|
enMa1UpdateHook = 0;
|
||||||
|
enMa1KillHook = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
enMa1KillHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int16_t sceneNum) mutable {
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorUpdate>(enMa1UpdateHook);
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneInit>(enMa1KillHook);
|
||||||
|
enMa1UpdateHook = 0;
|
||||||
|
enMa1KillHook = 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actor->id == ACTOR_EN_ZL4 && CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0)) {
|
||||||
|
EnZl4* enZl4 = static_cast<EnZl4*>(actorRef);
|
||||||
|
if (enZl4->actionFunc != EnZl4_Cutscene || enZl4->csState != 0) return;
|
||||||
|
|
||||||
|
enZl4->actionFunc = EnZl4_SkipToGivingZeldasLetter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimeSaverOnSceneInitHandler(int16_t sceneNum) {
|
||||||
|
switch (sceneNum) {
|
||||||
|
case SCENE_HYRULE_CASTLE:
|
||||||
|
if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", 0) && !Flags_GetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE)) {
|
||||||
|
Flags_SetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE);
|
||||||
|
Flags_SetInfTable(INFTABLE_MET_CHILD_MALON_AT_CASTLE_OR_MARKET);
|
||||||
|
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_CASTLE_OR_MARKET);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SCENE_LON_LON_RANCH:
|
||||||
|
if (CVarGetInteger("gTimeSavers.SkipMiscInteractions", 0) && GameInteractor_Should(GI_VB_MALON_RETURN_FROM_CASTLE, Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE), NULL)) {
|
||||||
|
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_RANCH);
|
||||||
|
Flags_SetInfTable(INFTABLE_CHILD_MALON_SAID_EPONA_WAS_AFRAID_OF_YOU);
|
||||||
|
Flags_SetEventChkInf(EVENTCHKINF_INVITED_TO_SING_WITH_CHILD_MALON);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SCENE_DEKU_TREE_BOSS:
|
||||||
|
if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", 0)) {
|
||||||
|
if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_GOHMA_BATTLE)) {
|
||||||
|
Flags_SetEventChkInf(EVENTCHKINF_BEGAN_GOHMA_BATTLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SCENE_DODONGOS_CAVERN_BOSS:
|
||||||
|
if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", 0)) {
|
||||||
|
if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_KING_DODONGO_BATTLE)) {
|
||||||
|
Flags_SetEventChkInf(EVENTCHKINF_BEGAN_KING_DODONGO_BATTLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SCENE_JABU_JABU_BOSS:
|
||||||
|
if (CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", 0)) {
|
||||||
|
if (!Flags_GetEventChkInf(EVENTCHKINF_BEGAN_BARINA_BATTLE)) {
|
||||||
|
Flags_SetEventChkInf(EVENTCHKINF_BEGAN_BARINA_BATTLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GetItemEntry vanillaQueuedItemEntry = GET_ITEM_NONE;
|
||||||
|
|
||||||
|
void TimeSaverOnFlagSetHandler(int16_t flagType, int16_t flag) {
|
||||||
|
if (!CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0)) return;
|
||||||
|
|
||||||
|
switch (flagType) {
|
||||||
|
case FLAG_EVENT_CHECK_INF:
|
||||||
|
switch (flag) {
|
||||||
|
case EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE:
|
||||||
|
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_FAIRY_OCARINA).GetGIEntry_Copy();
|
||||||
|
break;
|
||||||
|
case EVENTCHKINF_LEARNED_ZELDAS_LULLABY:
|
||||||
|
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_ZELDAS_LULLABY).GetGIEntry_Copy();
|
||||||
|
break;
|
||||||
|
case EVENTCHKINF_LEARNED_MINUET_OF_FOREST:
|
||||||
|
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_MINUET_OF_FOREST).GetGIEntry_Copy();
|
||||||
|
break;
|
||||||
|
case EVENTCHKINF_LEARNED_BOLERO_OF_FIRE:
|
||||||
|
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_BOLERO_OF_FIRE).GetGIEntry_Copy();
|
||||||
|
break;
|
||||||
|
case EVENTCHKINF_LEARNED_SERENADE_OF_WATER:
|
||||||
|
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SERENADE_OF_WATER).GetGIEntry_Copy();
|
||||||
|
break;
|
||||||
|
case EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT:
|
||||||
|
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_REQUIEM_OF_SPIRIT).GetGIEntry_Copy();
|
||||||
|
break;
|
||||||
|
case EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL:
|
||||||
|
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_NOCTURNE_OF_SHADOW).GetGIEntry_Copy();
|
||||||
|
break;
|
||||||
|
case EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT:
|
||||||
|
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_PRELUDE_OF_LIGHT).GetGIEntry_Copy();
|
||||||
|
break;
|
||||||
|
case EVENTCHKINF_LEARNED_SARIAS_SONG:
|
||||||
|
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SARIAS_SONG).GetGIEntry_Copy();
|
||||||
|
break;
|
||||||
|
case EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD:
|
||||||
|
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_KOKIRI_EMERALD).GetGIEntry_Copy();
|
||||||
|
break;
|
||||||
|
case EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP:
|
||||||
|
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_GORON_RUBY).GetGIEntry_Copy();
|
||||||
|
break;
|
||||||
|
case EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP:
|
||||||
|
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_ZORA_SAPPHIRE).GetGIEntry_Copy();
|
||||||
|
break;
|
||||||
|
case EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP:
|
||||||
|
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_FOREST_MEDALLION).GetGIEntry_Copy();
|
||||||
|
break;
|
||||||
|
case EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP:
|
||||||
|
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_FIRE_MEDALLION).GetGIEntry_Copy();
|
||||||
|
break;
|
||||||
|
case EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP:
|
||||||
|
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_WATER_MEDALLION).GetGIEntry_Copy();
|
||||||
|
break;
|
||||||
|
case EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS:
|
||||||
|
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_LIGHT_ARROWS).GetGIEntry_Copy();
|
||||||
|
break;
|
||||||
|
case EVENTCHKINF_TIME_TRAVELED_TO_ADULT:
|
||||||
|
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_LIGHT_MEDALLION).GetGIEntry_Copy();
|
||||||
|
break;
|
||||||
|
case EVENTCHKINF_LEARNED_SONG_OF_TIME:
|
||||||
|
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SONG_OF_TIME).GetGIEntry_Copy();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FLAG_RANDOMIZER_INF:
|
||||||
|
switch (flag) {
|
||||||
|
case RAND_INF_LEARNED_EPONA_SONG:
|
||||||
|
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_EPONAS_SONG).GetGIEntry_Copy();
|
||||||
|
break;
|
||||||
|
case RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE:
|
||||||
|
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SHADOW_MEDALLION).GetGIEntry_Copy();
|
||||||
|
break;
|
||||||
|
case RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE:
|
||||||
|
vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SPIRIT_MEDALLION).GetGIEntry_Copy();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimeSaverOnPlayerUpdateHandler() {
|
||||||
|
if (vanillaQueuedItemEntry.itemId == ITEM_NONE) return;
|
||||||
|
|
||||||
|
Player* player = GET_PLAYER(gPlayState);
|
||||||
|
if (player == NULL || Player_InBlockingCsMode(gPlayState, player) || player->stateFlags1 & PLAYER_STATE1_IN_ITEM_CS || player->stateFlags1 & PLAYER_STATE1_GETTING_ITEM || player->stateFlags1 & PLAYER_STATE1_ITEM_OVER_HEAD) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPDLOG_INFO("Attempting to give Item: mod {} item {}", vanillaQueuedItemEntry.modIndex, vanillaQueuedItemEntry.itemId);
|
||||||
|
GiveItemEntryWithoutActor(gPlayState, vanillaQueuedItemEntry);
|
||||||
|
if (player->stateFlags1 & PLAYER_STATE1_IN_WATER) {
|
||||||
|
// Allow the player to receive the item while swimming
|
||||||
|
player->stateFlags2 |= PLAYER_STATE2_UNDERWATER;
|
||||||
|
func_8083E5A8(player, gPlayState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimeSaverOnItemReceiveHandler(GetItemEntry receivedItemEntry) {
|
||||||
|
if (vanillaQueuedItemEntry.itemId == ITEM_NONE) return;
|
||||||
|
|
||||||
|
if (vanillaQueuedItemEntry.modIndex == receivedItemEntry.modIndex && vanillaQueuedItemEntry.itemId == receivedItemEntry.itemId) {
|
||||||
|
SPDLOG_INFO("Item received: mod {} item {}", receivedItemEntry.modIndex, receivedItemEntry.itemId);
|
||||||
|
vanillaQueuedItemEntry = GET_ITEM_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t onSceneInitHook = 0;
|
||||||
|
static uint32_t onVanillaBehaviorHook = 0;
|
||||||
|
static uint32_t onActorInitHook = 0;
|
||||||
|
static uint32_t onGameFrameUpdate = 0;
|
||||||
|
static uint32_t onFlagSetHook = 0;
|
||||||
|
static uint32_t onPlayerUpdateHook = 0;
|
||||||
|
static uint32_t onItemReceiveHook = 0;
|
||||||
|
void TimeSaverRegisterHooks() {
|
||||||
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnLoadGame>([](int32_t fileNum) mutable {
|
||||||
|
vanillaQueuedItemEntry = GET_ITEM_NONE;
|
||||||
|
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneInit>(onSceneInitHook);
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnVanillaBehavior>(onVanillaBehaviorHook);
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnActorInit>(onActorInitHook);
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnGameFrameUpdate>(onGameFrameUpdate);
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnFlagSet>(onFlagSetHook);
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnPlayerUpdate>(onPlayerUpdateHook);
|
||||||
|
GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnItemReceive>(onItemReceiveHook);
|
||||||
|
|
||||||
|
onSceneInitHook = 0;
|
||||||
|
onVanillaBehaviorHook = 0;
|
||||||
|
onActorInitHook = 0;
|
||||||
|
onGameFrameUpdate = 0;
|
||||||
|
onFlagSetHook = 0;
|
||||||
|
onPlayerUpdateHook = 0;
|
||||||
|
onItemReceiveHook = 0;
|
||||||
|
|
||||||
|
onSceneInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>(TimeSaverOnSceneInitHandler);
|
||||||
|
onVanillaBehaviorHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnVanillaBehavior>(TimeSaverOnVanillaBehaviorHandler);
|
||||||
|
onActorInitHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnActorInit>(TimeSaverOnActorInitHandler);
|
||||||
|
onGameFrameUpdate = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>(TimeSaverOnGameFrameUpdateHandler);
|
||||||
|
|
||||||
|
if (IS_RANDO) return;
|
||||||
|
|
||||||
|
onFlagSetHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnFlagSet>(TimeSaverOnFlagSetHandler);
|
||||||
|
onPlayerUpdateHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayerUpdate>(TimeSaverOnPlayerUpdateHandler);
|
||||||
|
onItemReceiveHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnItemReceive>(TimeSaverOnItemReceiveHandler);
|
||||||
|
});
|
||||||
|
}
|
6
soh/soh/Enhancements/timesaver_hook_handlers.h
Normal file
6
soh/soh/Enhancements/timesaver_hook_handlers.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef TIMESAVER_HOOK_HANDLERS_H
|
||||||
|
#define TIMESAVER_HOOK_HANDLERS_H
|
||||||
|
|
||||||
|
void TimeSaverRegisterHooks();
|
||||||
|
|
||||||
|
#endif // TIMESAVER_HOOK_HANDLERS_H
|
@ -122,6 +122,10 @@ GameInteractorSail* GameInteractorSail::Instance;
|
|||||||
|
|
||||||
#include "soh/config/ConfigUpdaters.h"
|
#include "soh/config/ConfigUpdaters.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "src/overlays/actors/ovl_En_Dns/z_en_dns.h"
|
||||||
|
}
|
||||||
|
|
||||||
void SoH_ProcessDroppedFiles(std::string filePath);
|
void SoH_ProcessDroppedFiles(std::string filePath);
|
||||||
|
|
||||||
OTRGlobals* OTRGlobals::Instance;
|
OTRGlobals* OTRGlobals::Instance;
|
||||||
@ -2567,9 +2571,9 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) {
|
|||||||
} else if (textId == TEXT_SHEIK_NEED_HOOK || textId == TEXT_SHEIK_HAVE_HOOK) {
|
} else if (textId == TEXT_SHEIK_NEED_HOOK || textId == TEXT_SHEIK_HAVE_HOOK) {
|
||||||
messageEntry = OTRGlobals::Instance->gRandomizer->GetSheikMessage(gPlayState->sceneNum, textId);
|
messageEntry = OTRGlobals::Instance->gRandomizer->GetSheikMessage(gPlayState->sceneNum, textId);
|
||||||
// textId: TEXT_SCRUB_RANDOM + (randomizerInf - RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT)
|
// textId: TEXT_SCRUB_RANDOM + (randomizerInf - RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT)
|
||||||
} else if (textId >= TEXT_SCRUB_RANDOM && textId <= TEXT_SCRUB_RANDOM + NUM_SCRUBS) {
|
} else if (textId == TEXT_SCRUB_RANDOM) {
|
||||||
RandomizerInf randoInf = (RandomizerInf)((textId - TEXT_SCRUB_RANDOM) + RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT);
|
EnDns* enDns = (EnDns*)GET_PLAYER(play)->targetActor;
|
||||||
messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage(randoInf, TEXT_SCRUB_RANDOM, Randomizer_GetSettingValue(RSK_SCRUB_TEXT_HINT) == RO_GENERIC_OFF);
|
messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage(enDns->sohScrubIdentity.randomizerInf, TEXT_SCRUB_RANDOM, Randomizer_GetSettingValue(RSK_SCRUB_TEXT_HINT) == RO_GENERIC_OFF);
|
||||||
// Shop items each have two message entries, second one offset by NUM_SHOP_ITEMS
|
// Shop items each have two message entries, second one offset by NUM_SHOP_ITEMS
|
||||||
// textId: TEXT_SHOP_ITEM_RANDOM + (randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1)
|
// textId: TEXT_SHOP_ITEM_RANDOM + (randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1)
|
||||||
// textId: TEXT_SHOP_ITEM_RANDOM + ((randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) + NUM_SHOP_ITEMS)
|
// textId: TEXT_SHOP_ITEM_RANDOM + ((randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) + NUM_SHOP_ITEMS)
|
||||||
|
@ -351,6 +351,13 @@ void SaveManager::LoadRandomizerVersion3() {
|
|||||||
// all ItemLocations is 0 anyway.
|
// all ItemLocations is 0 anyway.
|
||||||
randoContext->GetItemLocation(i)->SetCustomPrice(price);
|
randoContext->GetItemLocation(i)->SetCustomPrice(price);
|
||||||
}
|
}
|
||||||
|
uint16_t obtained = 0;
|
||||||
|
SaveManager::Instance->LoadData("obtained", obtained, (uint16_t)0);
|
||||||
|
if (obtained) {
|
||||||
|
randoContext->GetItemLocation(i)->MarkAsObtained();
|
||||||
|
} else {
|
||||||
|
randoContext->GetItemLocation(i)->MarkAsNotObtained();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -449,6 +456,7 @@ void SaveManager::SaveRandomizer(SaveContext* saveContext, int sectionID, bool f
|
|||||||
if (randoContext->GetItemLocation(i)->HasCustomPrice()) {
|
if (randoContext->GetItemLocation(i)->HasCustomPrice()) {
|
||||||
SaveManager::Instance->SaveData("price", randoContext->GetItemLocation(i)->GetPrice());
|
SaveManager::Instance->SaveData("price", randoContext->GetItemLocation(i)->GetPrice());
|
||||||
}
|
}
|
||||||
|
SaveManager::Instance->SaveData("obtained", randoContext->GetItemLocation(i)->HasObtained());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -727,6 +735,9 @@ void SaveManager::InitFileNormal() {
|
|||||||
for (int flag = 0; flag < ARRAY_COUNT(gSaveContext.infTable); flag++) {
|
for (int flag = 0; flag < ARRAY_COUNT(gSaveContext.infTable); flag++) {
|
||||||
gSaveContext.infTable[flag] = 0;
|
gSaveContext.infTable[flag] = 0;
|
||||||
}
|
}
|
||||||
|
for (int flag = 0; flag < ARRAY_COUNT(gSaveContext.randomizerInf); flag++) {
|
||||||
|
gSaveContext.randomizerInf[flag] = 0;
|
||||||
|
}
|
||||||
gSaveContext.worldMapAreaData = 0;
|
gSaveContext.worldMapAreaData = 0;
|
||||||
gSaveContext.scarecrowLongSongSet = 0;
|
gSaveContext.scarecrowLongSongSet = 0;
|
||||||
for (int i = 0; i < ARRAY_COUNT(gSaveContext.scarecrowLongSong); i++) {
|
for (int i = 0; i < ARRAY_COUNT(gSaveContext.scarecrowLongSong); i++) {
|
||||||
|
@ -69,6 +69,7 @@ static const char* imguiScaleOptions[4] = { "Small", "Normal", "Large", "X-Large
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const char* chestStyleMatchesContentsOptions[4] = { "Disabled", "Both", "Texture Only", "Size Only" };
|
static const char* chestStyleMatchesContentsOptions[4] = { "Disabled", "Both", "Texture Only", "Size Only" };
|
||||||
|
static const char* skipGetItemAnimationOptions[3] = { "Disabled", "Junk Items", "All Items" };
|
||||||
static const char* bunnyHoodOptions[3] = { "Disabled", "Faster Run & Longer Jump", "Faster Run" };
|
static const char* bunnyHoodOptions[3] = { "Disabled", "Faster Run & Longer Jump", "Faster Run" };
|
||||||
static const char* mirroredWorldModes[9] = {
|
static const char* mirroredWorldModes[9] = {
|
||||||
"Disabled", "Always", "Random", "Random (Seeded)", "Dungeons",
|
"Disabled", "Always", "Random", "Random (Seeded)", "Dungeons",
|
||||||
@ -555,6 +556,83 @@ void DrawEnhancementsMenu() {
|
|||||||
UIWidgets::Spacer(0);
|
UIWidgets::Spacer(0);
|
||||||
ImGui::Text("Speed-ups:");
|
ImGui::Text("Speed-ups:");
|
||||||
UIWidgets::PaddedSeparator();
|
UIWidgets::PaddedSeparator();
|
||||||
|
bool allChecked =
|
||||||
|
CVarGetInteger("gTimeSavers.SkipCutscene.Intro", 0) &&
|
||||||
|
CVarGetInteger("gTimeSavers.SkipCutscene.Entrances", 0) &&
|
||||||
|
CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0) &&
|
||||||
|
CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", 0) &&
|
||||||
|
CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", 0) &&
|
||||||
|
CVarGetInteger("gTimeSavers.SkipCutscene.GlitchAiding", 0) &&
|
||||||
|
CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", 0) &&
|
||||||
|
CVarGetInteger("gTimeSavers.NoForcedDialog", 0) &&
|
||||||
|
CVarGetInteger("gTimeSavers.SkipOwlInteractions", 0) &&
|
||||||
|
CVarGetInteger("gTimeSavers.SkipMiscInteractions", 0) &&
|
||||||
|
CVarGetInteger("gTimeSavers.DisableTitleCard", 0);
|
||||||
|
bool someChecked =
|
||||||
|
CVarGetInteger("gTimeSavers.SkipCutscene.Intro", 0) ||
|
||||||
|
CVarGetInteger("gTimeSavers.SkipCutscene.Entrances", 0) ||
|
||||||
|
CVarGetInteger("gTimeSavers.SkipCutscene.Story", 0) ||
|
||||||
|
CVarGetInteger("gTimeSavers.SkipCutscene.LearnSong", 0) ||
|
||||||
|
CVarGetInteger("gTimeSavers.SkipCutscene.BossIntro", 0) ||
|
||||||
|
CVarGetInteger("gTimeSavers.SkipCutscene.GlitchAiding", 0) ||
|
||||||
|
CVarGetInteger("gTimeSavers.SkipCutscene.OnePoint", 0) ||
|
||||||
|
CVarGetInteger("gTimeSavers.NoForcedDialog", 0) ||
|
||||||
|
CVarGetInteger("gTimeSavers.SkipOwlInteractions", 0) ||
|
||||||
|
CVarGetInteger("gTimeSavers.SkipMiscInteractions", 0) ||
|
||||||
|
CVarGetInteger("gTimeSavers.DisableTitleCard", 0);
|
||||||
|
|
||||||
|
ImGuiContext* g = ImGui::GetCurrentContext();
|
||||||
|
ImGuiItemFlags backup_item_flags = g->CurrentItemFlags;
|
||||||
|
if (!allChecked && someChecked) g->CurrentItemFlags |= ImGuiItemFlags_MixedValue;
|
||||||
|
if (ImGui::Checkbox("All", &allChecked)) {
|
||||||
|
if (allChecked) {
|
||||||
|
CVarSetInteger("gTimeSavers.SkipCutscene.Intro", 1);
|
||||||
|
CVarSetInteger("gTimeSavers.SkipCutscene.Entrances", 1);
|
||||||
|
CVarSetInteger("gTimeSavers.SkipCutscene.Story", 1);
|
||||||
|
CVarSetInteger("gTimeSavers.SkipCutscene.LearnSong", 1);
|
||||||
|
CVarSetInteger("gTimeSavers.SkipCutscene.BossIntro", 1);
|
||||||
|
CVarSetInteger("gTimeSavers.SkipCutscene.GlitchAiding", 1);
|
||||||
|
CVarSetInteger("gTimeSavers.SkipCutscene.OnePoint", 1);
|
||||||
|
CVarSetInteger("gTimeSavers.NoForcedDialog", 1);
|
||||||
|
CVarSetInteger("gTimeSavers.SkipOwlInteractions", 1);
|
||||||
|
CVarSetInteger("gTimeSavers.SkipMiscInteractions", 1);
|
||||||
|
CVarSetInteger("gTimeSavers.DisableTitleCard", 1);
|
||||||
|
} else {
|
||||||
|
CVarSetInteger("gTimeSavers.SkipCutscene.Intro", 0);
|
||||||
|
CVarSetInteger("gTimeSavers.SkipCutscene.Entrances", 0);
|
||||||
|
CVarSetInteger("gTimeSavers.SkipCutscene.Story", 0);
|
||||||
|
CVarSetInteger("gTimeSavers.SkipCutscene.LearnSong", 0);
|
||||||
|
CVarSetInteger("gTimeSavers.SkipCutscene.BossIntro", 0);
|
||||||
|
CVarSetInteger("gTimeSavers.SkipCutscene.GlitchAiding", 0);
|
||||||
|
CVarSetInteger("gTimeSavers.SkipCutscene.OnePoint", 0);
|
||||||
|
CVarSetInteger("gTimeSavers.NoForcedDialog", 0);
|
||||||
|
CVarSetInteger("gTimeSavers.SkipOwlInteractions", 0);
|
||||||
|
CVarSetInteger("gTimeSavers.SkipMiscInteractions", 0);
|
||||||
|
CVarSetInteger("gTimeSavers.DisableTitleCard", 0);
|
||||||
|
}
|
||||||
|
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||||
|
}
|
||||||
|
g->CurrentItemFlags = backup_item_flags;
|
||||||
|
UIWidgets::PaddedEnhancementCheckbox("Skip Intro", "gTimeSavers.SkipCutscene.Intro");
|
||||||
|
UIWidgets::PaddedEnhancementCheckbox("Skip Entrance Cutscenes", "gTimeSavers.SkipCutscene.Entrances");
|
||||||
|
UIWidgets::PaddedEnhancementCheckbox("Skip Story Cutscenes", "gTimeSavers.SkipCutscene.Story");
|
||||||
|
UIWidgets::PaddedEnhancementCheckbox("Skip Song Cutscenes", "gTimeSavers.SkipCutscene.LearnSong");
|
||||||
|
UIWidgets::PaddedEnhancementCheckbox("Skip Boss Introductions", "gTimeSavers.SkipCutscene.BossIntro");
|
||||||
|
UIWidgets::PaddedEnhancementCheckbox("Skip Glitch-Aiding Cutscenes", "gTimeSavers.SkipCutscene.GlitchAiding");
|
||||||
|
UIWidgets::Tooltip("Skip cutscenes that are associated with useful glitches, currently this is only the Fire Temple Darunia CS and Forest Temple Poe Sisters CS");
|
||||||
|
UIWidgets::PaddedEnhancementCheckbox("Skip One Point Cutscenes (Chests, Door Unlocks, etc)", "gTimeSavers.SkipCutscene.OnePoint");
|
||||||
|
UIWidgets::PaddedEnhancementCheckbox("No Forced Dialog", "gTimeSavers.NoForcedDialog");
|
||||||
|
UIWidgets::Tooltip("Prevent forced conversations with Navi or other NPCs");
|
||||||
|
UIWidgets::PaddedEnhancementCheckbox("Skip Owl Interactions", "gTimeSavers.SkipOwlInteractions");
|
||||||
|
UIWidgets::PaddedEnhancementCheckbox("Skip Misc Interactions", "gTimeSavers.SkipMiscInteractions");
|
||||||
|
UIWidgets::PaddedEnhancementCheckbox("Disable Title Card", "gTimeSavers.DisableTitleCard");
|
||||||
|
|
||||||
|
UIWidgets::PaddedText("Skip Get Item Animations", true, false);
|
||||||
|
UIWidgets::EnhancementCombobox("gTimeSavers.SkipGetItemAnimation", skipGetItemAnimationOptions, SGIA_DISABLED);
|
||||||
|
if (CVarGetInteger("gTimeSavers.SkipGetItemAnimation", SGIA_DISABLED) != SGIA_DISABLED) {
|
||||||
|
UIWidgets::EnhancementSliderFloat("Item Scale: %f", "##ItemScale", "gTimeSavers.SkipGetItemAnimationScale", 5.0f, 15.0f, "", 10.0f, false);
|
||||||
|
UIWidgets::Tooltip("The size of the item when it is picked up");
|
||||||
|
}
|
||||||
|
|
||||||
UIWidgets::PaddedEnhancementSliderInt("Text Speed: %dx", "##TEXTSPEED", "gTextSpeed", 1, 5, "", 1, true, false, true);
|
UIWidgets::PaddedEnhancementSliderInt("Text Speed: %dx", "##TEXTSPEED", "gTextSpeed", 1, 5, "", 1, true, false, true);
|
||||||
UIWidgets::PaddedEnhancementCheckbox("Skip Text", "gSkipText", false, true);
|
UIWidgets::PaddedEnhancementCheckbox("Skip Text", "gSkipText", false, true);
|
||||||
@ -565,37 +643,8 @@ void DrawEnhancementsMenu() {
|
|||||||
UIWidgets::PaddedEnhancementSliderInt("Crawl speed %dx", "##CRAWLSPEED", "gCrawlSpeed", 1, 5, "", 1, true, false, true);
|
UIWidgets::PaddedEnhancementSliderInt("Crawl speed %dx", "##CRAWLSPEED", "gCrawlSpeed", 1, 5, "", 1, true, false, true);
|
||||||
UIWidgets::PaddedEnhancementCheckbox("Faster Heavy Block Lift", "gFasterHeavyBlockLift", false, false);
|
UIWidgets::PaddedEnhancementCheckbox("Faster Heavy Block Lift", "gFasterHeavyBlockLift", false, false);
|
||||||
UIWidgets::Tooltip("Speeds up lifting silver rocks and obelisks");
|
UIWidgets::Tooltip("Speeds up lifting silver rocks and obelisks");
|
||||||
UIWidgets::PaddedEnhancementCheckbox("Skip Pickup Messages", "gFastDrops", true, false);
|
UIWidgets::PaddedEnhancementCheckbox("Link as default file name", "gLinkDefaultName", true, false);
|
||||||
UIWidgets::Tooltip("Skip pickup messages for new consumable items and bottle swipes");
|
UIWidgets::Tooltip("Allows you to have \"Link\" as a premade file name");
|
||||||
UIWidgets::PaddedEnhancementCheckbox("Fast Ocarina Playback", "gFastOcarinaPlayback", true, false);
|
|
||||||
UIWidgets::Tooltip("Skip the part where the Ocarina playback is called when you play a song");
|
|
||||||
bool forceSkipScarecrow = IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SKIP_SCARECROWS_SONG);
|
|
||||||
static const char* forceSkipScarecrowText = "This setting is forcefully enabled because a savefile\nwith \"Skip Scarecrow Song\" is loaded";
|
|
||||||
UIWidgets::PaddedEnhancementCheckbox("Skip Scarecrow Song", "gSkipScarecrow", true, false,
|
|
||||||
forceSkipScarecrow, forceSkipScarecrowText, UIWidgets::CheckboxGraphics::Checkmark);
|
|
||||||
UIWidgets::Tooltip("Pierre appears when Ocarina is pulled out. Requires learning scarecrow song.");
|
|
||||||
UIWidgets::PaddedEnhancementCheckbox("Skip Magic Arrow Equip Animation", "gSkipArrowAnimation", true, false);
|
|
||||||
UIWidgets::PaddedEnhancementCheckbox("Skip save confirmation", "gSkipSaveConfirmation", true, false);
|
|
||||||
UIWidgets::Tooltip("Skip the \"Game saved.\" confirmation screen");
|
|
||||||
UIWidgets::PaddedEnhancementCheckbox("Faster Farore's Wind", "gFastFarores", true, false);
|
|
||||||
UIWidgets::Tooltip("Greatly decreases cast time of Farore's Wind magic spell.");
|
|
||||||
UIWidgets::PaddedEnhancementCheckbox("Skip water take breath animation", "gSkipSwimDeepEndAnim", true, false);
|
|
||||||
UIWidgets::Tooltip("Skips Link's taking breath animation after coming up from water. This setting does not interfere with getting items from underwater.");
|
|
||||||
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
UIWidgets::Spacer(0);
|
|
||||||
ImGui::Text("Changes:");
|
|
||||||
UIWidgets::PaddedSeparator();
|
|
||||||
|
|
||||||
UIWidgets::PaddedEnhancementSliderInt("Biggoron Forge Time: %d days", "##FORGETIME", "gForgeTime", 0, 3, "", 3, true, false, true);
|
|
||||||
UIWidgets::Tooltip("Allows you to change the number of days it takes for Biggoron to forge the Biggoron Sword");
|
|
||||||
UIWidgets::PaddedEnhancementCheckbox("Remember Save Location", "gRememberSaveLocation", false, false);
|
|
||||||
UIWidgets::Tooltip("When loading a save, places Link at the last entrance he went through.\n"
|
|
||||||
"This doesn't work if the save was made in a grotto.");
|
|
||||||
UIWidgets::PaddedEnhancementCheckbox("No Forced Navi", "gNoForcedNavi", true, false);
|
|
||||||
UIWidgets::Tooltip("Prevent forced Navi conversations");
|
|
||||||
UIWidgets::PaddedEnhancementCheckbox("Navi Timer Resets", "gEnhancements.ResetNaviTimer", true, false);
|
|
||||||
UIWidgets::Tooltip("Resets the Navi timer on scene change. If you have already talked to her, she will try and talk to you again, instead of needing a save warp or death. ");
|
|
||||||
UIWidgets::PaddedEnhancementCheckbox("No Skulltula Freeze", "gSkulltulaFreeze", true, false);
|
UIWidgets::PaddedEnhancementCheckbox("No Skulltula Freeze", "gSkulltulaFreeze", true, false);
|
||||||
UIWidgets::Tooltip("Stops the game from freezing the player when picking up Gold Skulltulas");
|
UIWidgets::Tooltip("Stops the game from freezing the player when picking up Gold Skulltulas");
|
||||||
UIWidgets::PaddedEnhancementCheckbox("Nighttime GS Always Spawn", "gNightGSAlwaysSpawn", true, false);
|
UIWidgets::PaddedEnhancementCheckbox("Nighttime GS Always Spawn", "gNightGSAlwaysSpawn", true, false);
|
||||||
@ -1164,7 +1213,8 @@ void DrawEnhancementsMenu() {
|
|||||||
UIWidgets::Tooltip("Removes the dungeon entrance icon on the top-left corner of the screen when no dungeon is present on the current map");
|
UIWidgets::Tooltip("Removes the dungeon entrance icon on the top-left corner of the screen when no dungeon is present on the current map");
|
||||||
UIWidgets::PaddedEnhancementCheckbox("Fix Two Handed idle animations", "gTwoHandedIdle", true, false);
|
UIWidgets::PaddedEnhancementCheckbox("Fix Two Handed idle animations", "gTwoHandedIdle", true, false);
|
||||||
UIWidgets::Tooltip("Re-enables the two-handed idle animation, a seemingly finished animation that was disabled on accident in the original game");
|
UIWidgets::Tooltip("Re-enables the two-handed idle animation, a seemingly finished animation that was disabled on accident in the original game");
|
||||||
UIWidgets::PaddedEnhancementCheckbox("Fix the Gravedigging Tour Glitch", "gGravediggingTourFix", true, false);
|
UIWidgets::PaddedEnhancementCheckbox("Fix the Gravedigging Tour Glitch", "gGravediggingTourFix", true, false, SaveManager::Instance->IsRandoFile(),
|
||||||
|
"This setting is always enabled in randomizer files", UIWidgets::CheckboxGraphics::Checkmark);
|
||||||
UIWidgets::Tooltip("Fixes a bug where the Gravedigging Tour Heart Piece disappears if the area reloads");
|
UIWidgets::Tooltip("Fixes a bug where the Gravedigging Tour Heart Piece disappears if the area reloads");
|
||||||
UIWidgets::PaddedEnhancementCheckbox("Fix Deku Nut upgrade", "gDekuNutUpgradeFix", true, false);
|
UIWidgets::PaddedEnhancementCheckbox("Fix Deku Nut upgrade", "gDekuNutUpgradeFix", true, false);
|
||||||
UIWidgets::Tooltip("Prevents the Forest Stage Deku Nut upgrade from becoming unobtainable after receiving the Poacher's Saw");
|
UIWidgets::Tooltip("Prevents the Forest Stage Deku Nut upgrade from becoming unobtainable after receiving the Poacher's Saw");
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "scenes/misc/hakaana_ouke/hakaana_ouke_scene.h"
|
#include "scenes/misc/hakaana_ouke/hakaana_ouke_scene.h"
|
||||||
|
|
||||||
#include "soh/Enhancements/randomizer/randomizer_entrance.h"
|
#include "soh/Enhancements/randomizer/randomizer_entrance.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
u16 D_8011E1C0 = 0;
|
u16 D_8011E1C0 = 0;
|
||||||
u16 D_8011E1C4 = 0;
|
u16 D_8011E1C4 = 0;
|
||||||
@ -485,6 +486,7 @@ void func_80065134(PlayState* play, CutsceneContext* csCtx, CsCmdDayTime* cmd) {
|
|||||||
|
|
||||||
gSaveContext.dayTime = temp1 + temp2;
|
gSaveContext.dayTime = temp1 + temp2;
|
||||||
gSaveContext.skyboxTime = temp1 + temp2;
|
gSaveContext.skyboxTime = temp1 + temp2;
|
||||||
|
LUSLOG_INFO("SET TIME %d", gSaveContext.dayTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -493,11 +495,16 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB
|
|||||||
Player* player = GET_PLAYER(play);
|
Player* player = GET_PLAYER(play);
|
||||||
s32 temp = 0;
|
s32 temp = 0;
|
||||||
|
|
||||||
// Automatically skip certain cutscenes when in rando
|
bool shouldSkipCommand = false;
|
||||||
// cmd->base == 8: Traveling back/forward in time cutscene
|
|
||||||
// cmd->base == 24: Dropping a fish for Jabu Jabu
|
if (cmd->base == 8 && !GameInteractor_Should(GI_VB_PLAY_PULL_MASTER_SWORD_CS, true, NULL)) {
|
||||||
// cmd->base == 33: Zelda escaping with impa cutscene
|
shouldSkipCommand = true;
|
||||||
bool randoCsSkip = (IS_RANDO && (cmd->base == 8 || cmd->base == 24 || cmd->base == 33));
|
}
|
||||||
|
|
||||||
|
if (cmd->base == 24 && !GameInteractor_Should(GI_VB_PLAY_DROP_FISH_FOR_JABU_CS, true, NULL)) {
|
||||||
|
shouldSkipCommand = true;
|
||||||
|
}
|
||||||
|
|
||||||
bool debugCsSkip = (CHECK_BTN_ALL(play->state.input[0].press.button, BTN_START) &&
|
bool debugCsSkip = (CHECK_BTN_ALL(play->state.input[0].press.button, BTN_START) &&
|
||||||
(gSaveContext.fileNum != 0xFEDC) && CVarGetInteger("gDebugEnabled", 0));
|
(gSaveContext.fileNum != 0xFEDC) && CVarGetInteger("gDebugEnabled", 0));
|
||||||
|
|
||||||
@ -558,7 +565,7 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (playCutscene || (temp != 0) || ((csCtx->frames > 20) && (randoCsSkip || debugCsSkip))) {
|
if (playCutscene || (temp != 0) || ((csCtx->frames > 20) && (shouldSkipCommand || debugCsSkip))) {
|
||||||
|
|
||||||
csCtx->state = CS_STATE_UNSKIPPABLE_EXEC;
|
csCtx->state = CS_STATE_UNSKIPPABLE_EXEC;
|
||||||
Audio_SetCutsceneFlag(0);
|
Audio_SetCutsceneFlag(0);
|
||||||
@ -624,7 +631,7 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB
|
|||||||
gSaveContext.fw.set = 0;
|
gSaveContext.fw.set = 0;
|
||||||
gSaveContext.respawn[RESPAWN_MODE_TOP].data = 0;
|
gSaveContext.respawn[RESPAWN_MODE_TOP].data = 0;
|
||||||
}
|
}
|
||||||
if (!Flags_GetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL)) {
|
if (GameInteractor_Should(GI_VB_PLAY_PULL_MASTER_SWORD_CS, !Flags_GetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL), NULL)) {
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL);
|
Flags_SetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL);
|
||||||
play->nextEntranceIndex = ENTR_CUTSCENE_MAP_0;
|
play->nextEntranceIndex = ENTR_CUTSCENE_MAP_0;
|
||||||
play->transitionTrigger = TRANS_TRIGGER_START;
|
play->transitionTrigger = TRANS_TRIGGER_START;
|
||||||
@ -716,7 +723,9 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB
|
|||||||
play->transitionType = TRANS_TYPE_FADE_WHITE;
|
play->transitionType = TRANS_TYPE_FADE_WHITE;
|
||||||
break;
|
break;
|
||||||
case 22:
|
case 22:
|
||||||
Item_Give(play, ITEM_SONG_REQUIEM);
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_REQUIEM_OF_SPIRIT, true, NULL)) {
|
||||||
|
Item_Give(play, ITEM_SONG_REQUIEM);
|
||||||
|
}
|
||||||
play->nextEntranceIndex = ENTR_DESERT_COLOSSUS_0;
|
play->nextEntranceIndex = ENTR_DESERT_COLOSSUS_0;
|
||||||
play->transitionTrigger = TRANS_TRIGGER_START;
|
play->transitionTrigger = TRANS_TRIGGER_START;
|
||||||
gSaveContext.cutsceneIndex = 0xFFF0;
|
gSaveContext.cutsceneIndex = 0xFFF0;
|
||||||
@ -768,7 +777,9 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB
|
|||||||
play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0;
|
play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0;
|
||||||
play->transitionTrigger = TRANS_TRIGGER_START;
|
play->transitionTrigger = TRANS_TRIGGER_START;
|
||||||
play->transitionType = TRANS_TYPE_FADE_WHITE;
|
play->transitionType = TRANS_TYPE_FADE_WHITE;
|
||||||
Item_Give(play, ITEM_MEDALLION_FIRE);
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FIRE_MEDALLION, true, NULL)) {
|
||||||
|
Item_Give(play, ITEM_MEDALLION_FIRE);
|
||||||
|
}
|
||||||
gSaveContext.chamberCutsceneNum = 1;
|
gSaveContext.chamberCutsceneNum = 1;
|
||||||
break;
|
break;
|
||||||
case 31:
|
case 31:
|
||||||
@ -848,7 +859,9 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB
|
|||||||
play->transitionType = TRANS_TYPE_FADE_BLACK_FAST;
|
play->transitionType = TRANS_TYPE_FADE_BLACK_FAST;
|
||||||
break;
|
break;
|
||||||
case 47:
|
case 47:
|
||||||
Item_Give(play, ITEM_SONG_NOCTURNE);
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_NOCTURNE_OF_SHADOW, true, NULL)) {
|
||||||
|
Item_Give(play, ITEM_SONG_NOCTURNE);
|
||||||
|
}
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_LEARNED_NOCTURNE_OF_SHADOW);
|
Flags_SetEventChkInf(EVENTCHKINF_LEARNED_NOCTURNE_OF_SHADOW);
|
||||||
play->nextEntranceIndex = ENTR_KAKARIKO_VILLAGE_0;
|
play->nextEntranceIndex = ENTR_KAKARIKO_VILLAGE_0;
|
||||||
play->transitionTrigger = TRANS_TRIGGER_START;
|
play->transitionTrigger = TRANS_TRIGGER_START;
|
||||||
@ -1292,7 +1305,7 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (randoCsSkip) {
|
if (shouldSkipCommand && IS_RANDO) {
|
||||||
Entrance_OverrideCutsceneEntrance(cmd->base);
|
Entrance_OverrideCutsceneEntrance(cmd->base);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1561,7 +1574,49 @@ void Cutscene_Command_Textbox(PlayState* play, CutsceneContext* csCtx, CsCmdText
|
|||||||
} else if ((cmd->type == 4) && CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) {
|
} else if ((cmd->type == 4) && CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) {
|
||||||
Message_StartTextbox(play, cmd->textId1, NULL);
|
Message_StartTextbox(play, cmd->textId1, NULL);
|
||||||
} else {
|
} else {
|
||||||
|
GetItemEntry getItemEntry = GET_ITEM_NONE;
|
||||||
|
if (IS_RANDO) {
|
||||||
|
switch (cmd->base) {
|
||||||
|
case 0x80:
|
||||||
|
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_QUEEN_GOHMA, RG_KOKIRI_EMERALD);
|
||||||
|
break;
|
||||||
|
case 0x81:
|
||||||
|
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KING_DODONGO, RG_GORON_RUBY);
|
||||||
|
break;
|
||||||
|
case 0x82:
|
||||||
|
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_BARINADE, RG_ZORA_SAPPHIRE);
|
||||||
|
break;
|
||||||
|
case 0x3E:
|
||||||
|
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_PHANTOM_GANON, RG_FOREST_MEDALLION);
|
||||||
|
break;
|
||||||
|
case 0x3C:
|
||||||
|
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_VOLVAGIA, RG_FIRE_MEDALLION);
|
||||||
|
break;
|
||||||
|
case 0x3D:
|
||||||
|
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_MORPHA, RG_WATER_MEDALLION);
|
||||||
|
break;
|
||||||
|
case 0x3F:
|
||||||
|
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_TWINROVA, RG_SPIRIT_MEDALLION);
|
||||||
|
break;
|
||||||
|
case 0x41:
|
||||||
|
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_BONGO_BONGO, RG_SHADOW_MEDALLION);
|
||||||
|
break;
|
||||||
|
case 0x40:
|
||||||
|
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_GIFT_FROM_SAGES, RG_LIGHT_MEDALLION);
|
||||||
|
break;
|
||||||
|
case 0x72:
|
||||||
|
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_TOT_LIGHT_ARROWS_CUTSCENE, RG_LIGHT_ARROWS);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (getItemEntry.getItemId != GI_NONE) {
|
||||||
|
// cmd->base = getItemEntry.textId;
|
||||||
|
// GET_PLAYER(play)->getItemEntry = getItemEntry;
|
||||||
|
}
|
||||||
|
}
|
||||||
Message_StartTextbox(play, cmd->base, NULL);
|
Message_StartTextbox(play, cmd->base, NULL);
|
||||||
|
if (IS_RANDO && getItemEntry.getItemId != GI_NONE) {
|
||||||
|
// GET_PLAYER(play)->getItemEntry = (GetItemEntry)GET_ITEM_NONE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1584,12 +1639,14 @@ void Cutscene_Command_Textbox(PlayState* play, CutsceneContext* csCtx, CsCmdText
|
|||||||
if ((dialogState == TEXT_STATE_CHOICE) && Message_ShouldAdvance(play)) {
|
if ((dialogState == TEXT_STATE_CHOICE) && Message_ShouldAdvance(play)) {
|
||||||
if (play->msgCtx.choiceIndex == 0) {
|
if (play->msgCtx.choiceIndex == 0) {
|
||||||
if (cmd->textId1 != 0xFFFF) {
|
if (cmd->textId1 != 0xFFFF) {
|
||||||
|
// LUSLOG_INFO("Cutscene_Command_Textbox D: base:0x%x textId1:0x%x textId2:0x%x", cmd->base, cmd->textId1, cmd->textId2);
|
||||||
Message_ContinueTextbox(play, cmd->textId1);
|
Message_ContinueTextbox(play, cmd->textId1);
|
||||||
} else {
|
} else {
|
||||||
csCtx->frames++;
|
csCtx->frames++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (cmd->textId2 != 0xFFFF) {
|
if (cmd->textId2 != 0xFFFF) {
|
||||||
|
// LUSLOG_INFO("Cutscene_Command_Textbox E: base:0x%x textId1:0x%x textId2:0x%x", cmd->base, cmd->textId1, cmd->textId2);
|
||||||
Message_ContinueTextbox(play, cmd->textId2);
|
Message_ContinueTextbox(play, cmd->textId2);
|
||||||
} else {
|
} else {
|
||||||
csCtx->frames++;
|
csCtx->frames++;
|
||||||
@ -1599,6 +1656,7 @@ void Cutscene_Command_Textbox(PlayState* play, CutsceneContext* csCtx, CsCmdText
|
|||||||
|
|
||||||
if (dialogState == TEXT_STATE_9) {
|
if (dialogState == TEXT_STATE_9) {
|
||||||
if (cmd->textId1 != 0xFFFF) {
|
if (cmd->textId1 != 0xFFFF) {
|
||||||
|
// LUSLOG_INFO("Cutscene_Command_Textbox F: base:0x%x textId1:0x%x textId2:0x%x", cmd->base, cmd->textId1, cmd->textId2);
|
||||||
Message_ContinueTextbox(play, cmd->textId1);
|
Message_ContinueTextbox(play, cmd->textId1);
|
||||||
} else {
|
} else {
|
||||||
csCtx->frames++;
|
csCtx->frames++;
|
||||||
@ -2113,34 +2171,23 @@ void Cutscene_HandleEntranceTriggers(PlayState* play) {
|
|||||||
u8 requiredAge;
|
u8 requiredAge;
|
||||||
s16 i;
|
s16 i;
|
||||||
|
|
||||||
if (IS_RANDO &&
|
|
||||||
// don't skip epona escape cutscenes
|
|
||||||
gSaveContext.entranceIndex != ENTR_HYRULE_FIELD_11 &&
|
|
||||||
gSaveContext.entranceIndex != ENTR_HYRULE_FIELD_12 &&
|
|
||||||
gSaveContext.entranceIndex != ENTR_HYRULE_FIELD_13 &&
|
|
||||||
gSaveContext.entranceIndex != ENTR_HYRULE_FIELD_15 &&
|
|
||||||
// don't skip nabooru iron knuckle cs
|
|
||||||
gSaveContext.entranceIndex != ENTR_SPIRIT_TEMPLE_BOSS_0) {
|
|
||||||
gSaveContext.showTitleCard = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_COUNT(sEntranceCutsceneTable); i++) {
|
for (i = 0; i < ARRAY_COUNT(sEntranceCutsceneTable); i++) {
|
||||||
entranceCutscene = &sEntranceCutsceneTable[i];
|
entranceCutscene = &sEntranceCutsceneTable[i];
|
||||||
|
|
||||||
requiredAge = entranceCutscene->ageRestriction;
|
requiredAge = entranceCutscene->ageRestriction;
|
||||||
if (requiredAge == 2) {
|
if (requiredAge == 2) {
|
||||||
requiredAge = gSaveContext.linkAge;
|
requiredAge = gSaveContext.linkAge;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((gSaveContext.entranceIndex == entranceCutscene->entrance) &&
|
if ((gSaveContext.entranceIndex == entranceCutscene->entrance) &&
|
||||||
(!Flags_GetEventChkInf(entranceCutscene->flag) || (entranceCutscene->flag == 0x18)) &&
|
(!Flags_GetEventChkInf(entranceCutscene->flag) || (entranceCutscene->flag == EVENTCHKINF_EPONA_OBTAINED)) &&
|
||||||
(gSaveContext.cutsceneIndex < 0xFFF0) && ((u8)gSaveContext.linkAge == requiredAge) &&
|
(gSaveContext.cutsceneIndex < 0xFFF0) && ((u8)gSaveContext.linkAge == requiredAge) &&
|
||||||
(gSaveContext.respawnFlag <= 0)) {
|
(gSaveContext.respawnFlag <= 0)) {
|
||||||
Flags_SetEventChkInf(entranceCutscene->flag);
|
Flags_SetEventChkInf(entranceCutscene->flag);
|
||||||
Cutscene_SetSegment(play, entranceCutscene->segAddr);
|
if (GameInteractor_Should(GI_VB_PLAY_ENTRANCE_CS, true, &entranceCutscene->flag)) {
|
||||||
gSaveContext.cutsceneTrigger = 2;
|
Cutscene_SetSegment(play, entranceCutscene->segAddr);
|
||||||
gSaveContext.showTitleCard = false;
|
gSaveContext.cutsceneTrigger = 2;
|
||||||
|
gSaveContext.showTitleCard = false;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2148,48 +2195,48 @@ void Cutscene_HandleEntranceTriggers(PlayState* play) {
|
|||||||
|
|
||||||
void Cutscene_HandleConditionalTriggers(PlayState* play) {
|
void Cutscene_HandleConditionalTriggers(PlayState* play) {
|
||||||
osSyncPrintf("\ngame_info.mode=[%d] restart_flag", ((void)0, gSaveContext.respawnFlag));
|
osSyncPrintf("\ngame_info.mode=[%d] restart_flag", ((void)0, gSaveContext.respawnFlag));
|
||||||
|
LUSLOG_INFO("Cutscene_HandleConditionalTriggers - entranceIndex: %#x cutsceneIndex: %#x", gSaveContext.entranceIndex, gSaveContext.cutsceneIndex);
|
||||||
|
|
||||||
|
if (!GameInteractor_Should(GI_VB_PLAY_TRANSITION_CS, true, NULL)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ((gSaveContext.gameMode == 0) && (gSaveContext.respawnFlag <= 0) && (gSaveContext.cutsceneIndex < 0xFFF0)) {
|
if ((gSaveContext.gameMode == 0) && (gSaveContext.respawnFlag <= 0) && (gSaveContext.cutsceneIndex < 0xFFF0)) {
|
||||||
const bool bShouldTowerRandoSkip =
|
|
||||||
(IS_RANDO && Randomizer_GetSettingValue(RSK_SKIP_TOWER_ESCAPE));
|
|
||||||
if ((gSaveContext.entranceIndex == ENTR_DESERT_COLOSSUS_1) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT)) {
|
if ((gSaveContext.entranceIndex == ENTR_DESERT_COLOSSUS_1) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT)) {
|
||||||
if (!IS_RANDO) {
|
Flags_SetEventChkInf(EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT);
|
gSaveContext.entranceIndex = ENTR_DESERT_COLOSSUS_0;
|
||||||
gSaveContext.entranceIndex = ENTR_DESERT_COLOSSUS_0;
|
gSaveContext.cutsceneIndex = 0xFFF0;
|
||||||
gSaveContext.cutsceneIndex = 0xFFF0;
|
} else if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_NOCTURNE_OF_SHADOW, (
|
||||||
}
|
(gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_0) &&
|
||||||
} else if ((gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_0) && LINK_IS_ADULT && (Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP)) &&
|
LINK_IS_ADULT &&
|
||||||
(Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP)) && (Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)) &&
|
Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP) &&
|
||||||
!Flags_GetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL)) {
|
Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP) &&
|
||||||
if (!IS_RANDO) {
|
Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP) &&
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL);
|
!Flags_GetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL)
|
||||||
gSaveContext.cutsceneIndex = 0xFFF0;
|
), NULL)) {
|
||||||
}
|
Flags_SetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL);
|
||||||
|
gSaveContext.cutsceneIndex = 0xFFF0;
|
||||||
} else if ((gSaveContext.entranceIndex == ENTR_LOST_WOODS_9) && !Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE)) {
|
} else if ((gSaveContext.entranceIndex == ENTR_LOST_WOODS_9) && !Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE)) {
|
||||||
if (!IS_RANDO) {
|
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE);
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FAIRY_OCARINA, true, NULL)) {
|
||||||
Item_Give(play, ITEM_OCARINA_FAIRY);
|
Item_Give(play, ITEM_OCARINA_FAIRY);
|
||||||
gSaveContext.entranceIndex = ENTR_LOST_WOODS_0;
|
|
||||||
gSaveContext.cutsceneIndex = 0xFFF0;
|
|
||||||
}
|
}
|
||||||
} else if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) &&
|
gSaveContext.entranceIndex = ENTR_LOST_WOODS_0;
|
||||||
LINK_IS_ADULT && !Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS) &&
|
gSaveContext.cutsceneIndex = 0xFFF0;
|
||||||
(gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_TEMPLE_OF_TIME)) {
|
} else if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_LIGHT_ARROWS, (
|
||||||
if (!IS_RANDO) {
|
CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) &&
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS);
|
CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) &&
|
||||||
gSaveContext.entranceIndex = ENTR_TEMPLE_OF_TIME_0;
|
LINK_IS_ADULT &&
|
||||||
gSaveContext.cutsceneIndex = 0xFFF8;
|
!Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS) &&
|
||||||
}
|
(gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_TEMPLE_OF_TIME)
|
||||||
} else if ((!Flags_GetEventChkInf(EVENTCHKINF_WATCHED_GANONS_CASTLE_COLLAPSE_CAUGHT_BY_GERUDO) &&
|
), NULL)) {
|
||||||
gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_GANON_BOSS) ||
|
Flags_SetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS);
|
||||||
(bShouldTowerRandoSkip &&
|
gSaveContext.entranceIndex = ENTR_TEMPLE_OF_TIME_0;
|
||||||
gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR)) {
|
gSaveContext.cutsceneIndex = 0xFFF8;
|
||||||
|
} else if (!Flags_GetEventChkInf(EVENTCHKINF_WATCHED_GANONS_CASTLE_COLLAPSE_CAUGHT_BY_GERUDO) &&
|
||||||
|
(gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_GANON_BOSS)) {
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_WATCHED_GANONS_CASTLE_COLLAPSE_CAUGHT_BY_GERUDO);
|
Flags_SetEventChkInf(EVENTCHKINF_WATCHED_GANONS_CASTLE_COLLAPSE_CAUGHT_BY_GERUDO);
|
||||||
gSaveContext.entranceIndex = ENTR_GANON_BOSS_0;
|
gSaveContext.entranceIndex = ENTR_GANON_BOSS_0;
|
||||||
// In rando, skip the cutscene for the tower falling down after the escape.
|
|
||||||
if (IS_RANDO) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
gSaveContext.cutsceneIndex = 0xFFF0;
|
gSaveContext.cutsceneIndex = 0xFFF0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "objects/gameplay_keep/gameplay_keep.h"
|
#include "objects/gameplay_keep/gameplay_keep.h"
|
||||||
#include "overlays/effects/ovl_Effect_Ss_Dead_Sound/z_eff_ss_dead_sound.h"
|
#include "overlays/effects/ovl_Effect_Ss_Dead_Sound/z_eff_ss_dead_sound.h"
|
||||||
#include "textures/icon_item_static/icon_item_static.h"
|
#include "textures/icon_item_static/icon_item_static.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS 0
|
#define FLAGS 0
|
||||||
|
|
||||||
@ -349,6 +350,7 @@ void EnItem00_Init(Actor* thisx, PlayState* play) {
|
|||||||
s32 getItemId = GI_NONE;
|
s32 getItemId = GI_NONE;
|
||||||
this->randoGiEntry = (GetItemEntry)GET_ITEM_NONE;
|
this->randoGiEntry = (GetItemEntry)GET_ITEM_NONE;
|
||||||
this->randoCheck = (RandomizerCheck)RC_UNKNOWN_CHECK;
|
this->randoCheck = (RandomizerCheck)RC_UNKNOWN_CHECK;
|
||||||
|
this->itemEntry = (GetItemEntry)GET_ITEM_NONE;
|
||||||
s16 spawnParam8000 = this->actor.params & 0x8000;
|
s16 spawnParam8000 = this->actor.params & 0x8000;
|
||||||
s32 pad1;
|
s32 pad1;
|
||||||
|
|
||||||
@ -358,7 +360,7 @@ void EnItem00_Init(Actor* thisx, PlayState* play) {
|
|||||||
|
|
||||||
this->actor.params &= 0xFF;
|
this->actor.params &= 0xFF;
|
||||||
|
|
||||||
if (Flags_GetCollectible(play, this->collectibleFlag)) {
|
if (GameInteractor_Should(GI_VB_ITEM00_DESPAWN, Flags_GetCollectible(play, this->collectibleFlag), this)) {
|
||||||
Actor_Kill(&this->actor);
|
Actor_Kill(&this->actor);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -381,12 +383,7 @@ void EnItem00_Init(Actor* thisx, PlayState* play) {
|
|||||||
this->unk_158 = 0;
|
this->unk_158 = 0;
|
||||||
Actor_SetScale(&this->actor, 0.03f);
|
Actor_SetScale(&this->actor, 0.03f);
|
||||||
this->scale = 0.03f;
|
this->scale = 0.03f;
|
||||||
// Offset keys in randomizer slightly higher for their GID replacement
|
yOffset = 350.0f;
|
||||||
if (!IS_RANDO) {
|
|
||||||
yOffset = 350.0f;
|
|
||||||
} else {
|
|
||||||
yOffset = 430.0f;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case ITEM00_HEART_PIECE:
|
case ITEM00_HEART_PIECE:
|
||||||
this->unk_158 = 0;
|
this->unk_158 = 0;
|
||||||
@ -479,6 +476,14 @@ void EnItem00_Init(Actor* thisx, PlayState* play) {
|
|||||||
Actor_SetScale(&this->actor, 0.03f);
|
Actor_SetScale(&this->actor, 0.03f);
|
||||||
this->scale = 0.03f;
|
this->scale = 0.03f;
|
||||||
break;
|
break;
|
||||||
|
case ITEM00_SOH_GIVE_ITEM_ENTRY:
|
||||||
|
case ITEM00_SOH_GIVE_ITEM_ENTRY_GI:
|
||||||
|
case ITEM00_SOH_DUMMY:
|
||||||
|
this->unk_158 = 0;
|
||||||
|
Actor_SetScale(&this->actor, 0.03f);
|
||||||
|
this->scale = 0.03f;
|
||||||
|
yOffset = 430.0f;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->unk_156 = 0;
|
this->unk_156 = 0;
|
||||||
@ -507,6 +512,10 @@ void EnItem00_Init(Actor* thisx, PlayState* play) {
|
|||||||
this->actor.velocity.y = 0.0f;
|
this->actor.velocity.y = 0.0f;
|
||||||
this->actor.gravity = 0.0f;
|
this->actor.gravity = 0.0f;
|
||||||
|
|
||||||
|
if (!GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_ITEM_00, true, this)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (this->actor.params) {
|
switch (this->actor.params) {
|
||||||
case ITEM00_RUPEE_GREEN:
|
case ITEM00_RUPEE_GREEN:
|
||||||
Item_Give(play, ITEM_RUPEE_GREEN);
|
Item_Give(play, ITEM_RUPEE_GREEN);
|
||||||
@ -576,16 +585,8 @@ void EnItem00_Init(Actor* thisx, PlayState* play) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Actor_HasParent(&this->actor, play)) {
|
if ((getItemId != GI_NONE) && !Actor_HasParent(&this->actor, play)) {
|
||||||
if (getItemId != GI_NONE) {
|
func_8002F554(&this->actor, play, getItemId);
|
||||||
if (!IS_RANDO || this->randoGiEntry.getItemId == GI_NONE) {
|
|
||||||
func_8002F554(&this->actor, play, getItemId);
|
|
||||||
} else {
|
|
||||||
if (GiveItemEntryFromActorWithFixedRange(&this->actor, play, this->randoGiEntry) && this->randoInf != RAND_INF_MAX) {
|
|
||||||
Flags_SetRandomizerInf(this->randoInf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EnItem00_SetupAction(this, func_8001E5C8);
|
EnItem00_SetupAction(this, func_8001E5C8);
|
||||||
@ -603,8 +604,7 @@ void func_8001DFC8(EnItem00* this, PlayState* play) {
|
|||||||
(this->actor.params == ITEM00_HEART_PIECE)) {
|
(this->actor.params == ITEM00_HEART_PIECE)) {
|
||||||
this->actor.shape.rot.y += 960;
|
this->actor.shape.rot.y += 960;
|
||||||
} else {
|
} else {
|
||||||
if ((this->actor.params >= ITEM00_SHIELD_DEKU) && (this->actor.params != ITEM00_BOMBS_SPECIAL) &&
|
if ((this->actor.params >= ITEM00_SHIELD_DEKU) && (this->actor.params < ITEM00_BOMBS_SPECIAL)) {
|
||||||
(this->actor.params != ITEM00_BOMBCHU)) {
|
|
||||||
if (this->unk_15A == -1) {
|
if (this->unk_15A == -1) {
|
||||||
if (Math_SmoothStepToS(&this->actor.shape.rot.x, this->actor.world.rot.x - 0x4000, 2, 3000, 1500) ==
|
if (Math_SmoothStepToS(&this->actor.shape.rot.x, this->actor.world.rot.x - 0x4000, 2, 3000, 1500) ==
|
||||||
0) {
|
0) {
|
||||||
@ -697,8 +697,7 @@ void func_8001E304(EnItem00* this, PlayState* play) {
|
|||||||
|
|
||||||
if (this->actor.params <= ITEM00_RUPEE_RED) {
|
if (this->actor.params <= ITEM00_RUPEE_RED) {
|
||||||
this->actor.shape.rot.y += 960;
|
this->actor.shape.rot.y += 960;
|
||||||
} else if ((this->actor.params >= ITEM00_SHIELD_DEKU) && (this->actor.params != ITEM00_BOMBS_SPECIAL) &&
|
} else if ((this->actor.params >= ITEM00_SHIELD_DEKU) && (this->actor.params < ITEM00_BOMBS_SPECIAL)) {
|
||||||
(this->actor.params != ITEM00_BOMBCHU)) {
|
|
||||||
this->actor.world.rot.x -= 700;
|
this->actor.world.rot.x -= 700;
|
||||||
this->actor.shape.rot.y += 400;
|
this->actor.shape.rot.y += 400;
|
||||||
this->actor.shape.rot.x = this->actor.world.rot.x - 0x4000;
|
this->actor.shape.rot.x = this->actor.world.rot.x - 0x4000;
|
||||||
@ -733,13 +732,7 @@ void func_8001E5C8(EnItem00* this, PlayState* play) {
|
|||||||
Player* player = GET_PLAYER(play);
|
Player* player = GET_PLAYER(play);
|
||||||
if (this->getItemId != GI_NONE) {
|
if (this->getItemId != GI_NONE) {
|
||||||
if (!Actor_HasParent(&this->actor, play)) {
|
if (!Actor_HasParent(&this->actor, play)) {
|
||||||
if (!IS_RANDO) {
|
func_8002F434(&this->actor, play, this->getItemId, 50.0f, 80.0f);
|
||||||
func_8002F434(&this->actor, play, this->getItemId, 50.0f, 80.0f);
|
|
||||||
} else {
|
|
||||||
if (GiveItemEntryFromActor(&this->actor, play, this->randoGiEntry, 50.0f, 80.0f) && this->randoInf != RAND_INF_MAX) {
|
|
||||||
Flags_SetRandomizerInf(this->randoInf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this->unk_15A++;
|
this->unk_15A++;
|
||||||
} else {
|
} else {
|
||||||
this->getItemId = GI_NONE;
|
this->getItemId = GI_NONE;
|
||||||
@ -781,13 +774,15 @@ void EnItem00_Update(Actor* thisx, PlayState* play) {
|
|||||||
s32 pad;
|
s32 pad;
|
||||||
|
|
||||||
// Rotate some drops when 3D drops are on, otherwise reset rotation back to 0 for billboard effect
|
// Rotate some drops when 3D drops are on, otherwise reset rotation back to 0 for billboard effect
|
||||||
if ((this->actor.params == ITEM00_HEART && this->unk_15A >= 0) ||
|
if (
|
||||||
|
(this->actor.params == ITEM00_HEART && this->unk_15A >= 0) ||
|
||||||
(this->actor.params >= ITEM00_ARROWS_SMALL && this->actor.params <= ITEM00_SMALL_KEY) ||
|
(this->actor.params >= ITEM00_ARROWS_SMALL && this->actor.params <= ITEM00_SMALL_KEY) ||
|
||||||
this->actor.params == ITEM00_BOMBS_A || this->actor.params == ITEM00_ARROWS_SINGLE ||
|
this->actor.params == ITEM00_BOMBS_A ||
|
||||||
this->actor.params == ITEM00_BOMBS_SPECIAL || this->actor.params == ITEM00_BOMBCHU) {
|
this->actor.params == ITEM00_ARROWS_SINGLE ||
|
||||||
if (CVarGetInteger("gNewDrops", 0) ||
|
this->actor.params == ITEM00_BOMBS_SPECIAL ||
|
||||||
// Keys in randomizer need to always rotate for their GID replacement
|
(this->actor.params >= ITEM00_BOMBCHU && this->actor.params <= ITEM00_SOH_GIVE_ITEM_ENTRY_GI)
|
||||||
(IS_RANDO && this->actor.params == ITEM00_SMALL_KEY)) {
|
) {
|
||||||
|
if (CVarGetInteger("gNewDrops", 0) || (this->actor.params >= ITEM00_SOH_DUMMY && this->actor.params <= ITEM00_SOH_GIVE_ITEM_ENTRY_GI)) {
|
||||||
this->actor.shape.rot.y += 960;
|
this->actor.shape.rot.y += 960;
|
||||||
} else {
|
} else {
|
||||||
this->actor.shape.rot.y = 0;
|
this->actor.shape.rot.y = 0;
|
||||||
@ -871,6 +866,10 @@ void EnItem00_Update(Actor* thisx, PlayState* play) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_ITEM_00, true, this)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (this->actor.params) {
|
switch (this->actor.params) {
|
||||||
case ITEM00_RUPEE_GREEN:
|
case ITEM00_RUPEE_GREEN:
|
||||||
Item_Give(play, ITEM_RUPEE_GREEN);
|
Item_Give(play, ITEM_RUPEE_GREEN);
|
||||||
@ -955,14 +954,7 @@ void EnItem00_Update(Actor* thisx, PlayState* play) {
|
|||||||
params = &this->actor.params;
|
params = &this->actor.params;
|
||||||
|
|
||||||
if ((getItemId != GI_NONE) && !Actor_HasParent(&this->actor, play)) {
|
if ((getItemId != GI_NONE) && !Actor_HasParent(&this->actor, play)) {
|
||||||
if (!IS_RANDO || this->randoGiEntry.getItemId == GI_NONE) {
|
func_8002F554(&this->actor, play, getItemId);
|
||||||
func_8002F554(&this->actor, play, getItemId);
|
|
||||||
} else {
|
|
||||||
getItemId = this->randoGiEntry.getItemId;
|
|
||||||
if (GiveItemEntryFromActorWithFixedRange(&this->actor, play, this->randoGiEntry) && this->randoInf != RAND_INF_MAX) {
|
|
||||||
Flags_SetRandomizerInf(this->randoInf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (*params) {
|
switch (*params) {
|
||||||
@ -1052,7 +1044,7 @@ void EnItem00_Draw(Actor* thisx, PlayState* play) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ITEM00_HEART_PIECE:
|
case ITEM00_HEART_PIECE:
|
||||||
if (CVarGetInteger("gNewDrops", 0) && !IS_RANDO) {
|
if (CVarGetInteger("gNewDrops", 0)) {
|
||||||
mtxScale = 21.0f;
|
mtxScale = 21.0f;
|
||||||
Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY);
|
Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY);
|
||||||
GetItem_Draw(play, GID_HEART_PIECE);
|
GetItem_Draw(play, GID_HEART_PIECE);
|
||||||
@ -1162,7 +1154,7 @@ void EnItem00_Draw(Actor* thisx, PlayState* play) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ITEM00_SMALL_KEY:
|
case ITEM00_SMALL_KEY:
|
||||||
if (CVarGetInteger("gNewDrops", 0) && !IS_RANDO) {
|
if (CVarGetInteger("gNewDrops", 0)) {
|
||||||
mtxScale = 8.0f;
|
mtxScale = 8.0f;
|
||||||
Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY);
|
Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY);
|
||||||
GetItem_Draw(play, GID_KEY_SMALL);
|
GetItem_Draw(play, GID_KEY_SMALL);
|
||||||
@ -1368,17 +1360,7 @@ static const Vtx customDropVtx[] = {
|
|||||||
* Draw Function used for most collectible types of En_Item00 (ammo, bombs, sticks, nuts, magic...).
|
* Draw Function used for most collectible types of En_Item00 (ammo, bombs, sticks, nuts, magic...).
|
||||||
*/
|
*/
|
||||||
void EnItem00_DrawCollectible(EnItem00* this, PlayState* play) {
|
void EnItem00_DrawCollectible(EnItem00* this, PlayState* play) {
|
||||||
if (IS_RANDO && (this->getItemId != GI_NONE || this->actor.params == ITEM00_SMALL_KEY)) {
|
if (this->actor.params == ITEM00_BOMBCHU) {
|
||||||
if (this->randoCheck != RC_UNKNOWN_CHECK) {
|
|
||||||
this->randoGiEntry = Randomizer_GetItemFromKnownCheck(this->randoCheck, GI_NONE);
|
|
||||||
this->randoGiEntry.getItemFrom = ITEM_FROM_FREESTANDING;
|
|
||||||
}
|
|
||||||
|
|
||||||
f32 mtxScale = 10.67f;
|
|
||||||
Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY);
|
|
||||||
EnItem00_CustomItemsParticles(&this->actor, play, this->randoGiEntry);
|
|
||||||
GetItemEntry_Draw(play, this->randoGiEntry);
|
|
||||||
} else if (this->actor.params == ITEM00_BOMBCHU) {
|
|
||||||
OPEN_DISPS(play->state.gfxCtx);
|
OPEN_DISPS(play->state.gfxCtx);
|
||||||
|
|
||||||
Matrix_ReplaceRotation(&play->billboardMtxF);
|
Matrix_ReplaceRotation(&play->billboardMtxF);
|
||||||
@ -1458,29 +1440,17 @@ void EnItem00_DrawHeartContainer(EnItem00* this, PlayState* play) {
|
|||||||
* Draw Function used for the Piece of Heart type of En_Item00.
|
* Draw Function used for the Piece of Heart type of En_Item00.
|
||||||
*/
|
*/
|
||||||
void EnItem00_DrawHeartPiece(EnItem00* this, PlayState* play) {
|
void EnItem00_DrawHeartPiece(EnItem00* this, PlayState* play) {
|
||||||
if (IS_RANDO) {
|
s32 pad;
|
||||||
if (this->randoCheck != RC_UNKNOWN_CHECK) {
|
|
||||||
this->randoGiEntry = Randomizer_GetItemFromKnownCheck(this->randoCheck, GI_NONE);
|
|
||||||
this->randoGiEntry.getItemFrom = ITEM_FROM_FREESTANDING;
|
|
||||||
}
|
|
||||||
|
|
||||||
f32 mtxScale = 16.0f;
|
OPEN_DISPS(play->state.gfxCtx);
|
||||||
Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY);
|
|
||||||
EnItem00_CustomItemsParticles(&this->actor, play, this->randoGiEntry);
|
|
||||||
GetItemEntry_Draw(play, this->randoGiEntry);
|
|
||||||
} else {
|
|
||||||
s32 pad;
|
|
||||||
|
|
||||||
OPEN_DISPS(play->state.gfxCtx);
|
Gfx_SetupDL_25Xlu(play->state.gfxCtx);
|
||||||
|
func_8002ED80(&this->actor, play, 0);
|
||||||
|
gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
|
||||||
|
G_MTX_MODELVIEW | G_MTX_LOAD);
|
||||||
|
gSPDisplayList(POLY_XLU_DISP++, gHeartPieceInteriorDL);
|
||||||
|
|
||||||
Gfx_SetupDL_25Xlu(play->state.gfxCtx);
|
CLOSE_DISPS(play->state.gfxCtx);
|
||||||
func_8002ED80(&this->actor, play, 0);
|
|
||||||
gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
|
|
||||||
G_MTX_MODELVIEW | G_MTX_LOAD);
|
|
||||||
gSPDisplayList(POLY_XLU_DISP++, gHeartPieceInteriorDL);
|
|
||||||
|
|
||||||
CLOSE_DISPS(play->state.gfxCtx);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2603,8 +2603,23 @@ void Message_DrawMain(PlayState* play, Gfx** p) {
|
|||||||
msgCtx->lastPlayedSong = msgCtx->ocarinaStaff->state;
|
msgCtx->lastPlayedSong = msgCtx->ocarinaStaff->state;
|
||||||
msgCtx->msgMode = MSGMODE_SONG_PLAYBACK_SUCCESS;
|
msgCtx->msgMode = MSGMODE_SONG_PLAYBACK_SUCCESS;
|
||||||
|
|
||||||
if (!IS_RANDO) {
|
u8 songItemId = ITEM_SONG_MINUET + gOcarinaSongItemMap[msgCtx->ocarinaStaff->state];
|
||||||
Item_Give(play, ITEM_SONG_MINUET + gOcarinaSongItemMap[msgCtx->ocarinaStaff->state]);
|
|
||||||
|
if (
|
||||||
|
(songItemId == ITEM_SONG_MINUET && GameInteractor_Should(GI_VB_GIVE_ITEM_MINUET_OF_FOREST, true, NULL)) ||
|
||||||
|
(songItemId == ITEM_SONG_BOLERO && GameInteractor_Should(GI_VB_GIVE_ITEM_BOLERO_OF_FIRE, true, NULL)) ||
|
||||||
|
(songItemId == ITEM_SONG_SERENADE && GameInteractor_Should(GI_VB_GIVE_ITEM_SERENADE_OF_WATER, true, NULL)) ||
|
||||||
|
(songItemId == ITEM_SONG_REQUIEM && GameInteractor_Should(GI_VB_GIVE_ITEM_REQUIEM_OF_SPIRIT, true, NULL)) ||
|
||||||
|
(songItemId == ITEM_SONG_NOCTURNE && GameInteractor_Should(GI_VB_GIVE_ITEM_NOCTURNE_OF_SHADOW, true, NULL)) ||
|
||||||
|
(songItemId == ITEM_SONG_PRELUDE && GameInteractor_Should(GI_VB_GIVE_ITEM_PRELUDE_OF_LIGHT, true, NULL)) ||
|
||||||
|
(songItemId == ITEM_SONG_LULLABY && GameInteractor_Should(GI_VB_GIVE_ITEM_ZELDAS_LULLABY, true, NULL)) ||
|
||||||
|
(songItemId == ITEM_SONG_EPONA && GameInteractor_Should(GI_VB_GIVE_ITEM_EPONAS_SONG, true, NULL)) ||
|
||||||
|
(songItemId == ITEM_SONG_SARIA && GameInteractor_Should(GI_VB_GIVE_ITEM_SARIAS_SONG, true, NULL)) ||
|
||||||
|
(songItemId == ITEM_SONG_SUN && GameInteractor_Should(GI_VB_GIVE_ITEM_SUNS_SONG, true, NULL)) ||
|
||||||
|
(songItemId == ITEM_SONG_TIME && GameInteractor_Should(GI_VB_GIVE_ITEM_SONG_OF_TIME, true, NULL)) ||
|
||||||
|
(songItemId == ITEM_SONG_STORMS && GameInteractor_Should(GI_VB_GIVE_ITEM_SONG_OF_STORMS, true, NULL))
|
||||||
|
) {
|
||||||
|
Item_Give(play, songItemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
osSyncPrintf(VT_FGCOL(YELLOW));
|
osSyncPrintf(VT_FGCOL(YELLOW));
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "vt.h"
|
#include "vt.h"
|
||||||
#include "overlays/actors/ovl_En_Sw/z_en_sw.h"
|
#include "overlays/actors/ovl_En_Sw/z_en_sw.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
static s16 sDisableAttention = false;
|
static s16 sDisableAttention = false;
|
||||||
static s16 sUnused = -1;
|
static s16 sUnused = -1;
|
||||||
@ -810,12 +811,7 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 camIdx, s16 csId, Actor* actor
|
|||||||
break;
|
break;
|
||||||
case 4100:
|
case 4100:
|
||||||
csInfo->keyFrames = D_801225D4;
|
csInfo->keyFrames = D_801225D4;
|
||||||
// RANDO: Waterfall opening cutscene skips to the end of the cutscene data earlier by doing this
|
csInfo->keyFrameCnt = ARRAY_COUNT(D_801225D4);
|
||||||
if (!(IS_RANDO)) {
|
|
||||||
csInfo->keyFrameCnt = 5;
|
|
||||||
} else {
|
|
||||||
csInfo->keyFrameCnt = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
player->actor.shape.rot.y = player->actor.world.rot.y = player->currentYaw = 0x3FFC;
|
player->actor.shape.rot.y = player->actor.world.rot.y = player->currentYaw = 0x3FFC;
|
||||||
func_800C0808(play, camIdx, player, CAM_SET_CS_C);
|
func_800C0808(play, camIdx, player, CAM_SET_CS_C);
|
||||||
@ -1176,6 +1172,16 @@ s16 OnePointCutscene_Init(PlayState* play, s16 csId, s16 timer, Actor* actor, s1
|
|||||||
s16 csCamIdx;
|
s16 csCamIdx;
|
||||||
Camera* csCam;
|
Camera* csCam;
|
||||||
|
|
||||||
|
if (actor != NULL && actor->id != ACTOR_PLAYER) {
|
||||||
|
if (!GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, actor)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!GameInteractor_Should(GI_VB_PLAY_ONEPOINT_CS, true, &csId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (parentCamIdx == SUBCAM_ACTIVE) {
|
if (parentCamIdx == SUBCAM_ACTIVE) {
|
||||||
parentCamIdx = play->activeCamera;
|
parentCamIdx = play->activeCamera;
|
||||||
}
|
}
|
||||||
|
@ -2128,7 +2128,9 @@ u8 Item_Give(PlayState* play, u8 item) {
|
|||||||
AMMO(ITEM_STICK) = CUR_CAPACITY(UPG_STICKS);
|
AMMO(ITEM_STICK) = CUR_CAPACITY(UPG_STICKS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
item = ITEM_STICK;
|
// [SOH] This results in the same behavior as the original code, but also allows us to get an accurate ReceivedItemEntry hook
|
||||||
|
INV_CONTENT(ITEM_STICK) = ITEM_STICK;
|
||||||
|
return Return_Item(item, MOD_NONE, returnItem);
|
||||||
} else if (item == ITEM_NUT) {
|
} else if (item == ITEM_NUT) {
|
||||||
if (gSaveContext.inventory.items[slot] == ITEM_NONE) {
|
if (gSaveContext.inventory.items[slot] == ITEM_NONE) {
|
||||||
Inventory_ChangeUpgrade(UPG_NUTS, 1);
|
Inventory_ChangeUpgrade(UPG_NUTS, 1);
|
||||||
@ -2152,7 +2154,9 @@ u8 Item_Give(PlayState* play, u8 item) {
|
|||||||
AMMO(ITEM_NUT) = CUR_CAPACITY(UPG_NUTS);
|
AMMO(ITEM_NUT) = CUR_CAPACITY(UPG_NUTS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
item = ITEM_NUT;
|
// [SOH] This results in the same behavior as the original code, but also allows us to get an accurate ReceivedItemEntry hook
|
||||||
|
INV_CONTENT(ITEM_NUT) = ITEM_NUT;
|
||||||
|
return Return_Item(item, MOD_NONE, returnItem);
|
||||||
} else if (item == ITEM_BOMB) {
|
} else if (item == ITEM_BOMB) {
|
||||||
// "Bomb Bomb Bomb Bomb Bomb Bomb Bomb"
|
// "Bomb Bomb Bomb Bomb Bomb Bomb Bomb"
|
||||||
osSyncPrintf(" 爆弾 爆弾 爆弾 爆弾 爆弾 爆弾 爆弾 \n");
|
osSyncPrintf(" 爆弾 爆弾 爆弾 爆弾 爆弾 爆弾 爆弾 \n");
|
||||||
|
@ -226,60 +226,6 @@ void Play_Destroy(GameState* thisx) {
|
|||||||
gPlayState = NULL;
|
gPlayState = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GivePlayerRandoRewardSongOfTime(PlayState* play, RandomizerCheck check) {
|
|
||||||
Player* player = GET_PLAYER(play);
|
|
||||||
|
|
||||||
if (gSaveContext.entranceIndex == ENTR_HYRULE_FIELD_16 && player != NULL && !Player_InBlockingCsMode(play, player) &&
|
|
||||||
!Flags_GetTreasure(play, 0x1F) && gSaveContext.nextTransitionType == TRANS_NEXT_TYPE_DEFAULT && !gSaveContext.pendingIceTrapCount) {
|
|
||||||
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, RG_SONG_OF_TIME);
|
|
||||||
GiveItemEntryWithoutActor(play, getItemEntry);
|
|
||||||
player->pendingFlag.flagID = 0x1F;
|
|
||||||
player->pendingFlag.flagType = FLAG_SCENE_TREASURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GivePlayerRandoRewardNocturne(PlayState* play, RandomizerCheck check) {
|
|
||||||
Player* player = GET_PLAYER(play);
|
|
||||||
|
|
||||||
if ((gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_0 ||
|
|
||||||
gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_1 ||
|
|
||||||
gSaveContext.entranceIndex == ENTR_KAKARIKO_VILLAGE_2) && LINK_IS_ADULT && CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST) &&
|
|
||||||
CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE) && CHECK_QUEST_ITEM(QUEST_MEDALLION_WATER) && player != NULL &&
|
|
||||||
!Player_InBlockingCsMode(play, player) && !Flags_GetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL)) {
|
|
||||||
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, RG_NOCTURNE_OF_SHADOW);
|
|
||||||
GiveItemEntryWithoutActor(play, getItemEntry);
|
|
||||||
player->pendingFlag.flagID = 0xAA;
|
|
||||||
player->pendingFlag.flagType = FLAG_EVENT_CHECK_INF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GivePlayerRandoRewardRequiem(PlayState* play, RandomizerCheck check) {
|
|
||||||
Player* player = GET_PLAYER(play);
|
|
||||||
|
|
||||||
if ((gSaveContext.gameMode == 0) && (gSaveContext.respawnFlag <= 0) && (gSaveContext.cutsceneIndex < 0xFFF0)) {
|
|
||||||
if ((gSaveContext.entranceIndex == ENTR_DESERT_COLOSSUS_1) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT) && player != NULL &&
|
|
||||||
!Player_InBlockingCsMode(play, player)) {
|
|
||||||
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, RG_SONG_OF_TIME);
|
|
||||||
GiveItemEntryWithoutActor(play, getItemEntry);
|
|
||||||
player->pendingFlag.flagID = 0xAC;
|
|
||||||
player->pendingFlag.flagType = FLAG_EVENT_CHECK_INF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GivePlayerRandoRewardMasterSword(PlayState* play, RandomizerCheck check) {
|
|
||||||
Player* player = GET_PLAYER(play);
|
|
||||||
|
|
||||||
if (gSaveContext.entranceIndex == ENTR_TEMPLE_OF_TIME_2 && LINK_IS_ADULT && player != NULL &&
|
|
||||||
!Player_InBlockingCsMode(play, player) && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) &&
|
|
||||||
!Flags_GetRandomizerInf(RAND_INF_TOT_MASTER_SWORD)) {
|
|
||||||
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, RG_MASTER_SWORD);
|
|
||||||
GiveItemEntryWithoutActor(play, getItemEntry);
|
|
||||||
player->pendingFlag.flagID = RAND_INF_TOT_MASTER_SWORD;
|
|
||||||
player->pendingFlag.flagType = FLAG_RANDOMIZER_INF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 CheckStoneCount() {
|
u8 CheckStoneCount() {
|
||||||
u8 stoneCount = 0;
|
u8 stoneCount = 0;
|
||||||
|
|
||||||
@ -402,69 +348,6 @@ u8 CheckLACSRewardCount() {
|
|||||||
return lacsRewardCount;
|
return lacsRewardCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GivePlayerRandoRewardZeldaLightArrowsGift(PlayState* play, RandomizerCheck check) {
|
|
||||||
Player* player = GET_PLAYER(play);
|
|
||||||
|
|
||||||
u8 meetsRequirements = 0;
|
|
||||||
|
|
||||||
switch (Randomizer_GetSettingValue(RSK_GANONS_BOSS_KEY)) {
|
|
||||||
case RO_GANON_BOSS_KEY_LACS_STONES:
|
|
||||||
if ((CheckStoneCount() + CheckLACSRewardCount()) >= Randomizer_GetSettingValue(RSK_LACS_STONE_COUNT)) {
|
|
||||||
meetsRequirements = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case RO_GANON_BOSS_KEY_LACS_MEDALLIONS:
|
|
||||||
if ((CheckMedallionCount() + CheckLACSRewardCount()) >= Randomizer_GetSettingValue(RSK_LACS_MEDALLION_COUNT)) {
|
|
||||||
meetsRequirements = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case RO_GANON_BOSS_KEY_LACS_REWARDS:
|
|
||||||
if ((CheckMedallionCount() + CheckStoneCount() + CheckLACSRewardCount()) >= Randomizer_GetSettingValue(RSK_LACS_REWARD_COUNT)) {
|
|
||||||
meetsRequirements = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case RO_GANON_BOSS_KEY_LACS_DUNGEONS:
|
|
||||||
if ((CheckDungeonCount() + CheckLACSRewardCount()) >= Randomizer_GetSettingValue(RSK_LACS_DUNGEON_COUNT)) {
|
|
||||||
meetsRequirements = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case RO_GANON_BOSS_KEY_LACS_TOKENS:
|
|
||||||
if (gSaveContext.inventory.gsTokens >= Randomizer_GetSettingValue(RSK_LACS_TOKEN_COUNT)) {
|
|
||||||
meetsRequirements = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW)) {
|
|
||||||
meetsRequirements = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (meetsRequirements && LINK_IS_ADULT &&
|
|
||||||
(gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_TEMPLE_OF_TIME) &&
|
|
||||||
!Flags_GetTreasure(play, 0x1E) && player != NULL && !Player_InBlockingCsMode(play, player) &&
|
|
||||||
play->transitionTrigger == TRANS_TRIGGER_OFF) {
|
|
||||||
GetItemEntry getItem = Randomizer_GetItemFromKnownCheck(check, GI_ARROW_LIGHT);
|
|
||||||
if (GiveItemEntryWithoutActor(play, getItem)) {
|
|
||||||
player->pendingFlag.flagID = 0x1E;
|
|
||||||
player->pendingFlag.flagType = FLAG_SCENE_TREASURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GivePlayerRandoRewardSariaGift(PlayState* play, RandomizerCheck check) {
|
|
||||||
Player* player = GET_PLAYER(play);
|
|
||||||
if (gSaveContext.entranceIndex == ENTR_LOST_WOODS_9) {
|
|
||||||
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, RG_ZELDAS_LULLABY);
|
|
||||||
|
|
||||||
if (!Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE) && player != NULL && !Player_InBlockingCsMode(play, player)) {
|
|
||||||
GiveItemEntryWithoutActor(play, getItemEntry);
|
|
||||||
player->pendingFlag.flagType = FLAG_EVENT_CHECK_INF;
|
|
||||||
player->pendingFlag.flagID = 0xC1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Play_Init(GameState* thisx) {
|
void Play_Init(GameState* thisx) {
|
||||||
PlayState* play = (PlayState*)thisx;
|
PlayState* play = (PlayState*)thisx;
|
||||||
GraphicsContext* gfxCtx = play->state.gfxCtx;
|
GraphicsContext* gfxCtx = play->state.gfxCtx;
|
||||||
@ -1448,15 +1331,6 @@ skip:
|
|||||||
|
|
||||||
Environment_Update(play, &play->envCtx, &play->lightCtx, &play->pauseCtx, &play->msgCtx,
|
Environment_Update(play, &play->envCtx, &play->lightCtx, &play->pauseCtx, &play->msgCtx,
|
||||||
&play->gameOverCtx, play->state.gfxCtx);
|
&play->gameOverCtx, play->state.gfxCtx);
|
||||||
|
|
||||||
if (IS_RANDO) {
|
|
||||||
GivePlayerRandoRewardSariaGift(play, RC_LW_GIFT_FROM_SARIA);
|
|
||||||
GivePlayerRandoRewardSongOfTime(play, RC_SONG_FROM_OCARINA_OF_TIME);
|
|
||||||
GivePlayerRandoRewardZeldaLightArrowsGift(play, RC_TOT_LIGHT_ARROWS_CUTSCENE);
|
|
||||||
GivePlayerRandoRewardNocturne(play, RC_SHEIK_IN_KAKARIKO);
|
|
||||||
GivePlayerRandoRewardRequiem(play, RC_SHEIK_AT_COLOSSUS);
|
|
||||||
GivePlayerRandoRewardMasterSword(play, RC_TOT_MASTER_SWORD);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Play_DrawOverlayElements(PlayState* play) {
|
void Play_DrawOverlayElements(PlayState* play) {
|
||||||
|
@ -564,8 +564,8 @@ uint8_t Player_IsCustomLinkModel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
s32 Player_InBlockingCsMode(PlayState* play, Player* this) {
|
s32 Player_InBlockingCsMode(PlayState* play, Player* this) {
|
||||||
return (this->stateFlags1 & 0x20000080) || (this->csAction != 0) || (play->transitionTrigger == TRANS_TRIGGER_START) ||
|
return (this->stateFlags1 & (PLAYER_STATE1_DEAD | PLAYER_STATE1_IN_CUTSCENE)) || (this->csAction != 0) || (play->transitionTrigger == TRANS_TRIGGER_START) ||
|
||||||
(this->stateFlags1 & 1) || (this->stateFlags3 & 0x80) ||
|
(this->stateFlags1 & PLAYER_STATE1_LOADING) || (this->stateFlags3 & PLAYER_STATE3_HOOKSHOT_TRAVELLING) ||
|
||||||
((gSaveContext.magicState != MAGIC_STATE_IDLE) && (Player_ActionToMagicSpell(this, this->itemAction) >= 0));
|
((gSaveContext.magicState != MAGIC_STATE_IDLE) && (Player_ActionToMagicSpell(this, this->itemAction) >= 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "z_bg_bdan_switch.h"
|
#include "z_bg_bdan_switch.h"
|
||||||
#include "objects/object_bdan_objects/object_bdan_objects.h"
|
#include "objects/object_bdan_objects/object_bdan_objects.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
|
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
|
||||||
|
|
||||||
@ -224,10 +225,12 @@ void func_8086D4B4(BgBdanSwitch* this, PlayState* play) {
|
|||||||
if (!Flags_GetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F)) {
|
if (!Flags_GetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F)) {
|
||||||
type = this->dyna.actor.params & 0xFF;
|
type = this->dyna.actor.params & 0xFF;
|
||||||
Flags_SetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F);
|
Flags_SetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F);
|
||||||
if (type == BLUE || type == YELLOW_TALL_2) {
|
if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) {
|
||||||
OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR);
|
if (type == BLUE || type == YELLOW_TALL_2) {
|
||||||
} else {
|
OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR);
|
||||||
OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_CORRECT_CHIME);
|
} else {
|
||||||
|
OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_CORRECT_CHIME);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -236,7 +239,9 @@ void func_8086D548(BgBdanSwitch* this, PlayState* play) {
|
|||||||
if (Flags_GetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F)) {
|
if (Flags_GetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F)) {
|
||||||
Flags_UnsetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F);
|
Flags_UnsetSwitch(play, (this->dyna.actor.params >> 8) & 0x3F);
|
||||||
if ((this->dyna.actor.params & 0xFF) == YELLOW_TALL_2) {
|
if ((this->dyna.actor.params & 0xFF) == YELLOW_TALL_2) {
|
||||||
OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR);
|
if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) {
|
||||||
|
OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "scenes/dungeons/ddan/ddan_scene.h"
|
#include "scenes/dungeons/ddan/ddan_scene.h"
|
||||||
#include "objects/object_bwall/object_bwall.h"
|
#include "objects/object_bwall/object_bwall.h"
|
||||||
#include "objects/object_kingdodongo/object_kingdodongo.h"
|
#include "objects/object_kingdodongo/object_kingdodongo.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
|
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
|
||||||
|
|
||||||
@ -300,10 +301,13 @@ void BgBreakwall_Wait(BgBreakwall* this, PlayState* play) {
|
|||||||
|
|
||||||
if ((wallType == BWALL_DC_ENTRANCE) && (!Flags_GetEventChkInf(EVENTCHKINF_ENTERED_DODONGOS_CAVERN))) {
|
if ((wallType == BWALL_DC_ENTRANCE) && (!Flags_GetEventChkInf(EVENTCHKINF_ENTERED_DODONGOS_CAVERN))) {
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DODONGOS_CAVERN);
|
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_DODONGOS_CAVERN);
|
||||||
Cutscene_SetSegment(play, gDcOpeningCs);
|
s32 flag = EVENTCHKINF_ENTERED_DODONGOS_CAVERN;
|
||||||
gSaveContext.cutsceneTrigger = 1;
|
if (GameInteractor_Should(GI_VB_PLAY_ENTRANCE_CS, true, &flag)) {
|
||||||
|
Cutscene_SetSegment(play, gDcOpeningCs);
|
||||||
|
gSaveContext.cutsceneTrigger = 1;
|
||||||
|
func_8002DF54(play, NULL, 0x31);
|
||||||
|
}
|
||||||
Audio_PlaySoundGeneral(NA_SE_SY_CORRECT_CHIME, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
|
Audio_PlaySoundGeneral(NA_SE_SY_CORRECT_CHIME, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
|
||||||
func_8002DF54(play, NULL, 0x31);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->dyna.actor.params < 0) {
|
if (this->dyna.actor.params < 0) {
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "z_bg_mori_bigst.h"
|
#include "z_bg_mori_bigst.h"
|
||||||
#include "objects/object_mori_objects/object_mori_objects.h"
|
#include "objects/object_mori_objects/object_mori_objects.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
|
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
|
||||||
|
|
||||||
@ -149,7 +150,9 @@ void BgMoriBigst_StalfosFight(BgMoriBigst* this, PlayState* play) {
|
|||||||
if ((this->dyna.actor.home.rot.z == 0) &&
|
if ((this->dyna.actor.home.rot.z == 0) &&
|
||||||
((this->dyna.actor.home.pos.y - 5.0f) <= GET_PLAYER(play)->actor.world.pos.y)) {
|
((this->dyna.actor.home.pos.y - 5.0f) <= GET_PLAYER(play)->actor.world.pos.y)) {
|
||||||
BgMoriBigst_SetupFall(this, play);
|
BgMoriBigst_SetupFall(this, play);
|
||||||
OnePointCutscene_Init(play, 3220, 72, &this->dyna.actor, MAIN_CAM);
|
if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) {
|
||||||
|
OnePointCutscene_Init(play, 3220, 72, &this->dyna.actor, MAIN_CAM);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,8 +166,10 @@ void BgMoriBigst_Fall(BgMoriBigst* this, PlayState* play) {
|
|||||||
this->dyna.actor.world.pos.y = this->dyna.actor.home.pos.y;
|
this->dyna.actor.world.pos.y = this->dyna.actor.home.pos.y;
|
||||||
BgMoriBigst_SetupLanding(this, play);
|
BgMoriBigst_SetupLanding(this, play);
|
||||||
Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_STONE_BOUND);
|
Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_STONE_BOUND);
|
||||||
OnePointCutscene_Init(play, 1020, 8, &this->dyna.actor, MAIN_CAM);
|
if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) {
|
||||||
func_8002DF38(play, NULL, 0x3C);
|
OnePointCutscene_Init(play, 1020, 8, &this->dyna.actor, MAIN_CAM);
|
||||||
|
func_8002DF38(play, NULL, 0x3C);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "z_bg_toki_swd.h"
|
#include "z_bg_toki_swd.h"
|
||||||
#include "objects/object_toki_objects/object_toki_objects.h"
|
#include "objects/object_toki_objects/object_toki_objects.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
|
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
|
||||||
|
|
||||||
@ -115,14 +116,17 @@ void func_808BAF40(BgTokiSwd* this, PlayState* play) {
|
|||||||
if (((Flags_GetEventChkInf(EVENTCHKINF_ENTERED_MASTER_SWORD_CHAMBER)) == 0) && (gSaveContext.sceneSetupIndex < 4) &&
|
if (((Flags_GetEventChkInf(EVENTCHKINF_ENTERED_MASTER_SWORD_CHAMBER)) == 0) && (gSaveContext.sceneSetupIndex < 4) &&
|
||||||
Actor_IsFacingAndNearPlayer(&this->actor, 800.0f, 0x7530) && !Play_InCsMode(play)) {
|
Actor_IsFacingAndNearPlayer(&this->actor, 800.0f, 0x7530) && !Play_InCsMode(play)) {
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_MASTER_SWORD_CHAMBER);
|
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_MASTER_SWORD_CHAMBER);
|
||||||
play->csCtx.segment = D_808BBD90;
|
s32 flag = EVENTCHKINF_ENTERED_MASTER_SWORD_CHAMBER;
|
||||||
gSaveContext.cutsceneTrigger = 1;
|
if (GameInteractor_Should(GI_VB_PLAY_ENTRANCE_CS, true, &flag)) {
|
||||||
|
play->csCtx.segment = D_808BBD90;
|
||||||
|
gSaveContext.cutsceneTrigger = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!LINK_IS_ADULT || (Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && !IS_RANDO) || IS_RANDO) {
|
if (!LINK_IS_ADULT || (Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && !IS_RANDO) || IS_RANDO) {
|
||||||
if (Actor_HasParent(&this->actor, play)) {
|
if (Actor_HasParent(&this->actor, play)) {
|
||||||
if (!LINK_IS_ADULT) {
|
if (!LINK_IS_ADULT) {
|
||||||
if (!IS_RANDO || !Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD)) {
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_MASTER_SWORD, true, NULL)) {
|
||||||
Item_Give(play, ITEM_SWORD_MASTER);
|
Item_Give(play, ITEM_SWORD_MASTER);
|
||||||
}
|
}
|
||||||
play->csCtx.segment = D_808BB2F0;
|
play->csCtx.segment = D_808BB2F0;
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "z_bg_treemouth.h"
|
#include "z_bg_treemouth.h"
|
||||||
#include "objects/object_spot04_objects/object_spot04_objects.h"
|
#include "objects/object_spot04_objects/object_spot04_objects.h"
|
||||||
#include "overlays/effects/ovl_Effect_Ss_Hahen/z_eff_ss_hahen.h"
|
#include "overlays/effects/ovl_Effect_Ss_Hahen/z_eff_ss_hahen.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS (ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED)
|
#define FLAGS (ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED)
|
||||||
|
|
||||||
@ -73,11 +74,7 @@ void BgTreemouth_Init(Actor* thisx, PlayState* play) {
|
|||||||
|
|
||||||
if ((gSaveContext.sceneSetupIndex < 4) && !LINK_IS_ADULT) {
|
if ((gSaveContext.sceneSetupIndex < 4) && !LINK_IS_ADULT) {
|
||||||
BgTreemouth_SetupAction(this, func_808BC8B8);
|
BgTreemouth_SetupAction(this, func_808BC8B8);
|
||||||
// If dungeon entrance randomizer is on, keep the tree mouth open
|
} else if (LINK_IS_ADULT || (gSaveContext.sceneSetupIndex == 7)) {
|
||||||
// when Link is adult and sword & shield have been shown to Mido
|
|
||||||
} else if ((LINK_IS_ADULT && (!IS_RANDO ||
|
|
||||||
Randomizer_GetSettingValue(RSK_SHUFFLE_DUNGEON_ENTRANCES) == RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) ||
|
|
||||||
!Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD)) || (gSaveContext.sceneSetupIndex == 7)) {
|
|
||||||
this->unk_168 = 0.0f;
|
this->unk_168 = 0.0f;
|
||||||
BgTreemouth_SetupAction(this, BgTreemouth_DoNothing);
|
BgTreemouth_SetupAction(this, BgTreemouth_DoNothing);
|
||||||
} else {
|
} else {
|
||||||
@ -157,9 +154,11 @@ void func_808BC8B8(BgTreemouth* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
} else if (Actor_IsFacingAndNearPlayer(&this->dyna.actor, 1658.0f, 0x4E20)) {
|
} else if (Actor_IsFacingAndNearPlayer(&this->dyna.actor, 1658.0f, 0x4E20)) {
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_MET_DEKU_TREE);
|
Flags_SetEventChkInf(EVENTCHKINF_MET_DEKU_TREE);
|
||||||
play->csCtx.segment = D_808BCE20;
|
if (GameInteractor_Should(GI_VB_PLAY_DEKU_TREE_INTRO_CS, true, this)) {
|
||||||
gSaveContext.cutsceneTrigger = 1;
|
play->csCtx.segment = D_808BCE20;
|
||||||
BgTreemouth_SetupAction(this, func_808BC9EC);
|
gSaveContext.cutsceneTrigger = 1;
|
||||||
|
BgTreemouth_SetupAction(this, func_808BC9EC);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -15,4 +15,7 @@ typedef struct BgTreemouth {
|
|||||||
/* 0x016C */ BgTreemouthActionFunc actionFunc;
|
/* 0x016C */ BgTreemouthActionFunc actionFunc;
|
||||||
} BgTreemouth; // size = 0x0170
|
} BgTreemouth; // size = 0x0170
|
||||||
|
|
||||||
|
void BgTreemouth_SetupAction(BgTreemouth* actor, BgTreemouthActionFunc actionFunc);
|
||||||
|
void func_808BC6F8(BgTreemouth* actor, PlayState* play);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "overlays/actors/ovl_Demo_Effect/z_demo_effect.h"
|
#include "overlays/actors/ovl_Demo_Effect/z_demo_effect.h"
|
||||||
#include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h"
|
#include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h"
|
||||||
#include "vt.h"
|
#include "vt.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
|
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
|
||||||
|
|
||||||
@ -184,7 +185,9 @@ void func_80969F38(DemoDu* this, PlayState* play) {
|
|||||||
|
|
||||||
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DEMO_EFFECT, posX, posY, posZ, 0, 0, 0,
|
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DEMO_EFFECT, posX, posY, posZ, 0, 0, 0,
|
||||||
DEMO_EFFECT_MEDAL_FIRE);
|
DEMO_EFFECT_MEDAL_FIRE);
|
||||||
Item_Give(play, ITEM_MEDALLION_FIRE);
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FIRE_MEDALLION, true, NULL)) {
|
||||||
|
Item_Give(play, ITEM_MEDALLION_FIRE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void func_80969FB4(DemoDu* this, PlayState* play) {
|
void func_80969FB4(DemoDu* this, PlayState* play) {
|
||||||
@ -201,7 +204,9 @@ void DemoDu_CsFireMedallion_AdvanceTo01(DemoDu* this, PlayState* play) {
|
|||||||
this->updateIndex = CS_FIREMEDALLION_SUBSCENE(1);
|
this->updateIndex = CS_FIREMEDALLION_SUBSCENE(1);
|
||||||
play->csCtx.segment = D_8096C1A4;
|
play->csCtx.segment = D_8096C1A4;
|
||||||
gSaveContext.cutsceneTrigger = 2;
|
gSaveContext.cutsceneTrigger = 2;
|
||||||
Item_Give(play, ITEM_MEDALLION_FIRE);
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FIRE_MEDALLION, true, NULL)) {
|
||||||
|
Item_Give(play, ITEM_MEDALLION_FIRE);
|
||||||
|
}
|
||||||
|
|
||||||
player->actor.world.rot.y = player->actor.shape.rot.y = this->actor.world.rot.y + 0x8000;
|
player->actor.world.rot.y = player->actor.shape.rot.y = this->actor.world.rot.y + 0x8000;
|
||||||
}
|
}
|
||||||
|
@ -142,7 +142,7 @@ f32 DemoEffect_InterpolateCsFrames(PlayState* play, s32 csActionId) {
|
|||||||
*/
|
*/
|
||||||
void DemoEffect_InitJewel(PlayState* play, DemoEffect* this) {
|
void DemoEffect_InitJewel(PlayState* play, DemoEffect* this) {
|
||||||
this->initDrawFunc = DemoEffect_DrawJewel;
|
this->initDrawFunc = DemoEffect_DrawJewel;
|
||||||
if (IS_RANDO && play->sceneNum == SCENE_JABU_JABU) {
|
if (IS_RANDO && (play->sceneNum != SCENE_TEMPLE_OF_TIME || this->actor.params == DEMO_EFFECT_LIGHTARROW)) {
|
||||||
this->initDrawFunc = DemoEffect_DrawGetItem;
|
this->initDrawFunc = DemoEffect_DrawGetItem;
|
||||||
}
|
}
|
||||||
if (!LINK_IS_ADULT) {
|
if (!LINK_IS_ADULT) {
|
||||||
@ -156,7 +156,7 @@ void DemoEffect_InitJewel(PlayState* play, DemoEffect* this) {
|
|||||||
Actor_SetScale(&this->actor, 0.10f);
|
Actor_SetScale(&this->actor, 0.10f);
|
||||||
}
|
}
|
||||||
this->csActionId = 1;
|
this->csActionId = 1;
|
||||||
this->actor.shape.rot.x = (IS_RANDO && play->sceneNum == SCENE_JABU_JABU) ? 0 : 16384;
|
this->actor.shape.rot.x = (IS_RANDO && (play->sceneNum != SCENE_TEMPLE_OF_TIME || this->actor.params == DEMO_EFFECT_LIGHTARROW)) ? 0 : 16384;
|
||||||
DemoEffect_InitJewelColor(this);
|
DemoEffect_InitJewelColor(this);
|
||||||
this->jewel.alpha = 0;
|
this->jewel.alpha = 0;
|
||||||
this->jewelCsRotation.x = this->jewelCsRotation.y = this->jewelCsRotation.z = 0;
|
this->jewelCsRotation.x = this->jewelCsRotation.y = this->jewelCsRotation.z = 0;
|
||||||
@ -2087,13 +2087,48 @@ void DemoEffect_DrawGetItem(Actor* thisx, PlayState* play) {
|
|||||||
this->getItem.isLoaded = 1;
|
this->getItem.isLoaded = 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (IS_RANDO && play->sceneNum == SCENE_JABU_JABU) {
|
if (IS_RANDO && (play->sceneNum != SCENE_TEMPLE_OF_TIME || this->actor.params == DEMO_EFFECT_LIGHTARROW)) {
|
||||||
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_BARINADE, RG_ZORA_SAPPHIRE);
|
GetItemEntry getItemEntry = GET_ITEM_NONE;
|
||||||
this->getItem.drawId = getItemEntry.gid;
|
|
||||||
func_8002EBCC(thisx, play, 0);
|
switch (this->actor.params) {
|
||||||
func_8002ED80(thisx, play, 0);
|
case DEMO_EFFECT_JEWEL_KOKIRI:
|
||||||
GetItemEntry_Draw(play, getItemEntry);
|
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_QUEEN_GOHMA, RG_KOKIRI_EMERALD);
|
||||||
return;
|
break;
|
||||||
|
case DEMO_EFFECT_JEWEL_GORON:
|
||||||
|
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KING_DODONGO, RG_GORON_RUBY);
|
||||||
|
break;
|
||||||
|
case DEMO_EFFECT_JEWEL_ZORA:
|
||||||
|
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_BARINADE, RG_ZORA_SAPPHIRE);
|
||||||
|
break;
|
||||||
|
case DEMO_EFFECT_MEDAL_FOREST:
|
||||||
|
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_PHANTOM_GANON, RG_FOREST_MEDALLION);
|
||||||
|
break;
|
||||||
|
case DEMO_EFFECT_MEDAL_FIRE:
|
||||||
|
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_VOLVAGIA, RG_FIRE_MEDALLION);
|
||||||
|
break;
|
||||||
|
case DEMO_EFFECT_MEDAL_WATER:
|
||||||
|
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_MORPHA, RG_WATER_MEDALLION);
|
||||||
|
break;
|
||||||
|
case DEMO_EFFECT_MEDAL_SPIRIT:
|
||||||
|
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_TWINROVA, RG_SPIRIT_MEDALLION);
|
||||||
|
break;
|
||||||
|
case DEMO_EFFECT_MEDAL_SHADOW:
|
||||||
|
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_BONGO_BONGO, RG_SHADOW_MEDALLION);
|
||||||
|
break;
|
||||||
|
case DEMO_EFFECT_MEDAL_LIGHT:
|
||||||
|
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_GIFT_FROM_SAGES, RG_LIGHT_MEDALLION);
|
||||||
|
break;
|
||||||
|
case DEMO_EFFECT_LIGHTARROW:
|
||||||
|
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_TOT_LIGHT_ARROWS_CUTSCENE, RG_LIGHT_ARROWS);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (getItemEntry.getItemId != GI_NONE) {
|
||||||
|
this->getItem.drawId = getItemEntry.gid;
|
||||||
|
func_8002EBCC(thisx, play, 0);
|
||||||
|
func_8002ED80(thisx, play, 0);
|
||||||
|
GetItemEntry_Draw(play, getItemEntry);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
func_8002EBCC(thisx, play, 0);
|
func_8002EBCC(thisx, play, 0);
|
||||||
func_8002ED80(thisx, play, 0);
|
func_8002ED80(thisx, play, 0);
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "scenes/indoors/nakaniwa/nakaniwa_scene.h"
|
#include "scenes/indoors/nakaniwa/nakaniwa_scene.h"
|
||||||
#include "objects/object_im/object_im.h"
|
#include "objects/object_im/object_im.h"
|
||||||
#include "vt.h"
|
#include "vt.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UPDATE_WHILE_CULLED)
|
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UPDATE_WHILE_CULLED)
|
||||||
|
|
||||||
@ -318,7 +319,9 @@ void func_809853B4(DemoIm* this, PlayState* play) {
|
|||||||
|
|
||||||
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DEMO_EFFECT, playerX, playerY, playerZ, 0,
|
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DEMO_EFFECT, playerX, playerY, playerZ, 0,
|
||||||
0, 0, 0xD);
|
0, 0, 0xD);
|
||||||
Item_Give(play, ITEM_MEDALLION_SHADOW);
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_SHADOW_MEDALLION, true, NULL)) {
|
||||||
|
Item_Give(play, ITEM_MEDALLION_SHADOW);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void func_80985430(DemoIm* this, PlayState* play) {
|
void func_80985430(DemoIm* this, PlayState* play) {
|
||||||
@ -334,7 +337,9 @@ void func_8098544C(DemoIm* this, PlayState* play) {
|
|||||||
this->action = 1;
|
this->action = 1;
|
||||||
play->csCtx.segment = D_8098786C;
|
play->csCtx.segment = D_8098786C;
|
||||||
gSaveContext.cutsceneTrigger = 2;
|
gSaveContext.cutsceneTrigger = 2;
|
||||||
Item_Give(play, ITEM_MEDALLION_SHADOW);
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_SHADOW_MEDALLION, true, NULL)) {
|
||||||
|
Item_Give(play, ITEM_MEDALLION_SHADOW);
|
||||||
|
}
|
||||||
player->actor.world.rot.y = player->actor.shape.rot.y = this->actor.world.rot.y + 0x8000;
|
player->actor.world.rot.y = player->actor.shape.rot.y = this->actor.world.rot.y + 0x8000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -903,40 +908,17 @@ void func_80986BF8(DemoIm* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GivePlayerRandoRewardImpa(Actor* impa, PlayState* play, RandomizerCheck check) {
|
|
||||||
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, RG_ZELDAS_LULLABY);
|
|
||||||
|
|
||||||
if (impa->parent != NULL && impa->parent->id == GET_PLAYER(play)->actor.id &&
|
|
||||||
!Flags_GetTreasure(play, 0x1F)) {
|
|
||||||
Flags_SetTreasure(play, 0x1F);
|
|
||||||
} else if (!Flags_GetTreasure(play, 0x1F) && !Randomizer_GetSettingValue(RSK_SKIP_CHILD_ZELDA)) {
|
|
||||||
GiveItemEntryFromActor(impa, play, getItemEntry, 75.0f, 50.0f);
|
|
||||||
} else if (!Player_InBlockingCsMode(play, GET_PLAYER(play))) {
|
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_LEARNED_ZELDAS_LULLABY);
|
|
||||||
play->transitionTrigger = TRANS_TRIGGER_START;
|
|
||||||
play->transitionType = TRANS_TYPE_FADE_WHITE;
|
|
||||||
gSaveContext.nextTransitionType = TRANS_TYPE_FADE_WHITE;
|
|
||||||
// In entrance rando have impa bring link back to the front of castle grounds
|
|
||||||
if (Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_ENTRANCES)) {
|
|
||||||
play->nextEntranceIndex = ENTR_HYRULE_CASTLE_0;
|
|
||||||
} else {
|
|
||||||
play->nextEntranceIndex = ENTR_HYRULE_FIELD_17;
|
|
||||||
}
|
|
||||||
gSaveContext.nextCutsceneIndex = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void func_80986C30(DemoIm* this, PlayState* play) {
|
void func_80986C30(DemoIm* this, PlayState* play) {
|
||||||
if (func_80986A5C(this, play)) {
|
if (func_80986A5C(this, play)) {
|
||||||
if (IS_RANDO) {
|
if (GameInteractor_Should(GI_VB_PLAY_ZELDAS_LULLABY_CS, true, this)) {
|
||||||
GivePlayerRandoRewardImpa(this, play, RC_SONG_FROM_IMPA);
|
|
||||||
} else {
|
|
||||||
play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gZeldasCourtyardLullabyCs);
|
play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gZeldasCourtyardLullabyCs);
|
||||||
gSaveContext.cutsceneTrigger = 1;
|
gSaveContext.cutsceneTrigger = 1;
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_LEARNED_ZELDAS_LULLABY);
|
|
||||||
Item_Give(play, ITEM_SONG_LULLABY);
|
|
||||||
func_80985F54(this);
|
func_80985F54(this);
|
||||||
}
|
}
|
||||||
|
Flags_SetEventChkInf(EVENTCHKINF_LEARNED_ZELDAS_LULLABY);
|
||||||
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_ZELDAS_LULLABY, true, NULL)) {
|
||||||
|
Item_Give(play, ITEM_SONG_LULLABY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -960,7 +942,7 @@ void func_80986D40(DemoIm* this, PlayState* play) {
|
|||||||
if (gSaveContext.sceneSetupIndex == 6) {
|
if (gSaveContext.sceneSetupIndex == 6) {
|
||||||
this->action = 19;
|
this->action = 19;
|
||||||
this->drawConfig = 1;
|
this->drawConfig = 1;
|
||||||
} else if ((Flags_GetEventChkInf(EVENTCHKINF_ZELDA_FLED_HYRULE_CASTLE)) && !IS_RANDO) {
|
} else if ((Flags_GetEventChkInf(EVENTCHKINF_ZELDA_FLED_HYRULE_CASTLE)) && !IS_RANDO) { // SoH [Randomizer] Not sure why we're not killing impa here.
|
||||||
Actor_Kill(&this->actor);
|
Actor_Kill(&this->actor);
|
||||||
} else if (!Flags_GetEventChkInf(EVENTCHKINF_LEARNED_ZELDAS_LULLABY)) {
|
} else if (!Flags_GetEventChkInf(EVENTCHKINF_LEARNED_ZELDAS_LULLABY)) {
|
||||||
this->action = 23;
|
this->action = 23;
|
||||||
|
@ -51,4 +51,6 @@ typedef struct DemoIm {
|
|||||||
/* 0x02D4 */ NpcInteractInfo interactInfo;
|
/* 0x02D4 */ NpcInteractInfo interactInfo;
|
||||||
} DemoIm; // size = 0x02FC
|
} DemoIm; // size = 0x02FC
|
||||||
|
|
||||||
|
void func_80986794(DemoIm* demoIm);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h"
|
#include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h"
|
||||||
#include "objects/object_sa/object_sa.h"
|
#include "objects/object_sa/object_sa.h"
|
||||||
#include "soh/Enhancements/boss-rush/BossRush.h"
|
#include "soh/Enhancements/boss-rush/BossRush.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#include "vt.h"
|
#include "vt.h"
|
||||||
|
|
||||||
@ -241,7 +242,9 @@ void func_8098E8C8(DemoSa* this, PlayState* play) {
|
|||||||
|
|
||||||
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DEMO_EFFECT, posX, posY, posZ, 0, 0, 0,
|
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DEMO_EFFECT, posX, posY, posZ, 0, 0, 0,
|
||||||
0xB);
|
0xB);
|
||||||
Item_Give(play, ITEM_MEDALLION_FOREST);
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FOREST_MEDALLION, true, NULL)) {
|
||||||
|
Item_Give(play, ITEM_MEDALLION_FOREST);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void func_8098E944(DemoSa* this, PlayState* play) {
|
void func_8098E944(DemoSa* this, PlayState* play) {
|
||||||
@ -258,7 +261,9 @@ void func_8098E960(DemoSa* this, PlayState* play) {
|
|||||||
this->action = 1;
|
this->action = 1;
|
||||||
play->csCtx.segment = D_8099010C;
|
play->csCtx.segment = D_8099010C;
|
||||||
gSaveContext.cutsceneTrigger = 2;
|
gSaveContext.cutsceneTrigger = 2;
|
||||||
Item_Give(play, ITEM_MEDALLION_FOREST);
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FOREST_MEDALLION, true, NULL)) {
|
||||||
|
Item_Give(play, ITEM_MEDALLION_FOREST);
|
||||||
|
}
|
||||||
player->actor.world.rot.y = player->actor.shape.rot.y = this->actor.world.rot.y + 0x8000;
|
player->actor.world.rot.y = player->actor.shape.rot.y = this->actor.world.rot.y + 0x8000;
|
||||||
} else {
|
} else {
|
||||||
this->action = 1;
|
this->action = 1;
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "objects/object_menkuri_objects/object_menkuri_objects.h"
|
#include "objects/object_menkuri_objects/object_menkuri_objects.h"
|
||||||
#include "objects/object_demo_kekkai/object_demo_kekkai.h"
|
#include "objects/object_demo_kekkai/object_demo_kekkai.h"
|
||||||
#include "objects/object_ouke_haka/object_ouke_haka.h"
|
#include "objects/object_ouke_haka/object_ouke_haka.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
|
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
|
||||||
|
|
||||||
@ -354,9 +355,11 @@ void func_80996A54(DoorShutter* this, PlayState* play) {
|
|||||||
if (Flags_GetClear(play, this->dyna.actor.room) || Flags_GetTempClear(play, this->dyna.actor.room)) {
|
if (Flags_GetClear(play, this->dyna.actor.room) || Flags_GetTempClear(play, this->dyna.actor.room)) {
|
||||||
Flags_SetClear(play, this->dyna.actor.room);
|
Flags_SetClear(play, this->dyna.actor.room);
|
||||||
DoorShutter_SetupAction(this, func_80997150);
|
DoorShutter_SetupAction(this, func_80997150);
|
||||||
OnePointCutscene_Attention(play, &this->dyna.actor);
|
if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) {
|
||||||
OnePointCutscene_Attention(play, &GET_PLAYER(play)->actor);
|
OnePointCutscene_Attention(play, &this->dyna.actor);
|
||||||
this->unk_16F = -100;
|
OnePointCutscene_Attention(play, &GET_PLAYER(play)->actor);
|
||||||
|
this->unk_16F = -100;
|
||||||
|
}
|
||||||
} else if (func_809968D4(this, play) != 0) {
|
} else if (func_809968D4(this, play) != 0) {
|
||||||
Player* player = GET_PLAYER(play);
|
Player* player = GET_PLAYER(play);
|
||||||
|
|
||||||
@ -470,8 +473,10 @@ void func_80996EE8(DoorShutter* this, PlayState* play) {
|
|||||||
if (func_80996E08(this, play, 1.0f)) {
|
if (func_80996E08(this, play, 1.0f)) {
|
||||||
if (Flags_GetSwitch(play, this->dyna.actor.params & 0x3F)) {
|
if (Flags_GetSwitch(play, this->dyna.actor.params & 0x3F)) {
|
||||||
DoorShutter_SetupAction(this, func_80997150);
|
DoorShutter_SetupAction(this, func_80997150);
|
||||||
OnePointCutscene_Attention(play, &this->dyna.actor);
|
if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) {
|
||||||
this->unk_16F = -100;
|
OnePointCutscene_Attention(play, &this->dyna.actor);
|
||||||
|
this->unk_16F = -100;
|
||||||
|
}
|
||||||
} else if (func_809968D4(this, play)) {
|
} else if (func_809968D4(this, play)) {
|
||||||
Player* player = GET_PLAYER(play);
|
Player* player = GET_PLAYER(play);
|
||||||
// Jabu navi text for switch doors is different
|
// Jabu navi text for switch doors is different
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "objects/object_warp1/object_warp1.h"
|
#include "objects/object_warp1/object_warp1.h"
|
||||||
#include "soh/Enhancements/randomizer/randomizer_entrance.h"
|
#include "soh/Enhancements/randomizer/randomizer_entrance.h"
|
||||||
#include "soh/Enhancements/boss-rush/BossRush.h"
|
#include "soh/Enhancements/boss-rush/BossRush.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS 0
|
#define FLAGS 0
|
||||||
|
|
||||||
@ -487,44 +488,6 @@ s32 DoorWarp1_PlayerInRange(DoorWarp1* this, PlayState* play) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GivePlayerRandoReward(DoorWarp1* this, Player* player, PlayState* play, u8 ruto, u8 adult) {
|
|
||||||
GetItemEntry getItemEntry = Randomizer_GetItemFromActor(this->actor.id, play->sceneNum, 0x00, GI_NONE);
|
|
||||||
|
|
||||||
if (this->actor.parent != NULL && this->actor.parent->id == GET_PLAYER(play)->actor.id &&
|
|
||||||
!Flags_GetTreasure(play, 0x1F)) {
|
|
||||||
Flags_SetTreasure(play, 0x1F);
|
|
||||||
} else if (!Flags_GetTreasure(play, 0x1F)) {
|
|
||||||
GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 100.0f);
|
|
||||||
} else if (!Player_InBlockingCsMode(play, GET_PLAYER(play))) {
|
|
||||||
if (adult) {
|
|
||||||
OnePointCutscene_Init(play, 0x25E8, 999, &this->actor, MAIN_CAM);
|
|
||||||
func_8002DF54(play, &this->actor, 10);
|
|
||||||
player->unk_450.x = this->actor.world.pos.x;
|
|
||||||
player->unk_450.z = this->actor.world.pos.z;
|
|
||||||
this->unk_1B2 = 20;
|
|
||||||
DoorWarp1_SetupAction(this, func_8099A508);
|
|
||||||
} else {
|
|
||||||
if (ruto) {
|
|
||||||
this->rutoWarpState = WARP_BLUE_RUTO_STATE_ENTERED;
|
|
||||||
func_8002DF54(play, &this->actor, 10);
|
|
||||||
this->unk_1B2 = 1;
|
|
||||||
DoorWarp1_SetupAction(this, func_80999EE0);
|
|
||||||
} else {
|
|
||||||
Audio_PlaySoundGeneral(NA_SE_EV_LINK_WARP, &player->actor.projectedPos, 4, &D_801333E0, &D_801333E0,
|
|
||||||
&D_801333E8);
|
|
||||||
OnePointCutscene_Init(play, 0x25E7, 999, &this->actor, MAIN_CAM);
|
|
||||||
func_8002DF54(play, &this->actor, 10);
|
|
||||||
|
|
||||||
player->unk_450.x = this->actor.world.pos.x;
|
|
||||||
player->unk_450.z = this->actor.world.pos.z;
|
|
||||||
this->unk_1B2 = 1;
|
|
||||||
|
|
||||||
DoorWarp1_SetupAction(this, DoorWarp1_ChildWarpOut);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DoorWarp1_ChildWarpIdle(DoorWarp1* this, PlayState* play) {
|
void DoorWarp1_ChildWarpIdle(DoorWarp1* this, PlayState* play) {
|
||||||
Player* player;
|
Player* player;
|
||||||
|
|
||||||
@ -532,11 +495,6 @@ void DoorWarp1_ChildWarpIdle(DoorWarp1* this, PlayState* play) {
|
|||||||
|
|
||||||
if (DoorWarp1_PlayerInRange(this, play)) {
|
if (DoorWarp1_PlayerInRange(this, play)) {
|
||||||
player = GET_PLAYER(play);
|
player = GET_PLAYER(play);
|
||||||
|
|
||||||
if (IS_RANDO) {
|
|
||||||
GivePlayerRandoReward(this, player, play, 0, 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Audio_PlaySoundGeneral(NA_SE_EV_LINK_WARP, &player->actor.projectedPos, 4, &D_801333E0, &D_801333E0,
|
Audio_PlaySoundGeneral(NA_SE_EV_LINK_WARP, &player->actor.projectedPos, 4, &D_801333E0, &D_801333E0,
|
||||||
&D_801333E8);
|
&D_801333E8);
|
||||||
@ -570,36 +528,26 @@ void DoorWarp1_ChildWarpOut(DoorWarp1* this, PlayState* play) {
|
|||||||
osSyncPrintf("\n\n\nじかんがきたからおーしまい fade_direction=[%d]", play->transitionTrigger, TRANS_TRIGGER_START);
|
osSyncPrintf("\n\n\nじかんがきたからおーしまい fade_direction=[%d]", play->transitionTrigger, TRANS_TRIGGER_START);
|
||||||
|
|
||||||
if (play->sceneNum == SCENE_DODONGOS_CAVERN_BOSS) {
|
if (play->sceneNum == SCENE_DODONGOS_CAVERN_BOSS) {
|
||||||
if (!Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP)) {
|
if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP), EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP)) {
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP);
|
Flags_SetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP);
|
||||||
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN);
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_GORON_RUBY)) {
|
||||||
if (IS_RANDO) {
|
|
||||||
play->nextEntranceIndex = ENTR_DEATH_MOUNTAIN_TRAIL_5;
|
|
||||||
gSaveContext.nextCutsceneIndex = 0;
|
|
||||||
} else {
|
|
||||||
Item_Give(play, ITEM_GORON_RUBY);
|
Item_Give(play, ITEM_GORON_RUBY);
|
||||||
play->nextEntranceIndex = ENTR_DEATH_MOUNTAIN_TRAIL_0;
|
|
||||||
gSaveContext.nextCutsceneIndex = 0xFFF1;
|
|
||||||
}
|
}
|
||||||
|
play->nextEntranceIndex = ENTR_DEATH_MOUNTAIN_TRAIL_0;
|
||||||
|
gSaveContext.nextCutsceneIndex = 0xFFF1;
|
||||||
} else {
|
} else {
|
||||||
play->nextEntranceIndex = ENTR_DEATH_MOUNTAIN_TRAIL_5;
|
play->nextEntranceIndex = ENTR_DEATH_MOUNTAIN_TRAIL_5;
|
||||||
gSaveContext.nextCutsceneIndex = 0;
|
gSaveContext.nextCutsceneIndex = 0;
|
||||||
}
|
}
|
||||||
} else if (play->sceneNum == SCENE_DEKU_TREE_BOSS) {
|
} else if (play->sceneNum == SCENE_DEKU_TREE_BOSS) {
|
||||||
if (!Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD) || IS_RANDO) {
|
if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD), EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD)) {
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD);
|
Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP);
|
Flags_SetEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP);
|
||||||
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE);
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_KOKIRI_EMERALD)) {
|
||||||
if (IS_RANDO) {
|
|
||||||
play->nextEntranceIndex = ENTR_KOKIRI_FOREST_11;
|
|
||||||
gSaveContext.nextCutsceneIndex = 0;
|
|
||||||
// Skip Mido complaining about dead Deku tree
|
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH);
|
|
||||||
} else {
|
|
||||||
Item_Give(play, ITEM_KOKIRI_EMERALD);
|
Item_Give(play, ITEM_KOKIRI_EMERALD);
|
||||||
play->nextEntranceIndex = ENTR_KOKIRI_FOREST_0;
|
|
||||||
gSaveContext.nextCutsceneIndex = 0xFFF1;
|
|
||||||
}
|
}
|
||||||
|
play->nextEntranceIndex = ENTR_KOKIRI_FOREST_0;
|
||||||
|
gSaveContext.nextCutsceneIndex = 0xFFF1;
|
||||||
} else {
|
} else {
|
||||||
play->nextEntranceIndex = ENTR_KOKIRI_FOREST_11;
|
play->nextEntranceIndex = ENTR_KOKIRI_FOREST_11;
|
||||||
gSaveContext.nextCutsceneIndex = 0;
|
gSaveContext.nextCutsceneIndex = 0;
|
||||||
@ -635,12 +583,6 @@ void DoorWarp1_RutoWarpIdle(DoorWarp1* this, PlayState* play) {
|
|||||||
Audio_PlayActorSound2(&this->actor, NA_SE_EV_WARP_HOLE - SFX_FLAG);
|
Audio_PlayActorSound2(&this->actor, NA_SE_EV_WARP_HOLE - SFX_FLAG);
|
||||||
|
|
||||||
if (this->rutoWarpState != WARP_BLUE_RUTO_STATE_INITIAL && DoorWarp1_PlayerInRange(this, play)) {
|
if (this->rutoWarpState != WARP_BLUE_RUTO_STATE_INITIAL && DoorWarp1_PlayerInRange(this, play)) {
|
||||||
|
|
||||||
if (IS_RANDO) {
|
|
||||||
GivePlayerRandoReward(this, GET_PLAYER(play), play, 1, 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->rutoWarpState = WARP_BLUE_RUTO_STATE_ENTERED;
|
this->rutoWarpState = WARP_BLUE_RUTO_STATE_ENTERED;
|
||||||
func_8002DF54(play, &this->actor, 10);
|
func_8002DF54(play, &this->actor, 10);
|
||||||
this->unk_1B2 = 1;
|
this->unk_1B2 = 1;
|
||||||
@ -670,9 +612,8 @@ void func_80999EE0(DoorWarp1* this, PlayState* play) {
|
|||||||
Play_CameraSetAtEye(play, sRutoWarpSubCamId, &at, &eye);
|
Play_CameraSetAtEye(play, sRutoWarpSubCamId, &at, &eye);
|
||||||
Play_CameraSetFov(play, sRutoWarpSubCamId, 90.0f);
|
Play_CameraSetFov(play, sRutoWarpSubCamId, 90.0f);
|
||||||
this->rutoWarpState = WARP_BLUE_RUTO_STATE_TALKING;
|
this->rutoWarpState = WARP_BLUE_RUTO_STATE_TALKING;
|
||||||
if (!IS_RANDO) {
|
// TODO: Why was this disabled in rando?
|
||||||
Message_StartTextbox(play, 0x4022, NULL);
|
Message_StartTextbox(play, 0x4022, NULL);
|
||||||
}
|
|
||||||
DoorWarp1_SetupAction(this, func_80999FE4);
|
DoorWarp1_SetupAction(this, func_80999FE4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -704,17 +645,14 @@ void DoorWarp1_RutoWarpOut(DoorWarp1* this, PlayState* play) {
|
|||||||
this->warpTimer++;
|
this->warpTimer++;
|
||||||
|
|
||||||
if (this->warpTimer > sWarpTimerTarget && gSaveContext.nextCutsceneIndex == 0xFFEF) {
|
if (this->warpTimer > sWarpTimerTarget && gSaveContext.nextCutsceneIndex == 0xFFEF) {
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP);
|
if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, true, EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP)) {
|
||||||
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY);
|
Flags_SetEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP);
|
||||||
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_ZORA_SAPPHIRE)) {
|
||||||
if (IS_RANDO) {
|
Item_Give(play, ITEM_ZORA_SAPPHIRE);
|
||||||
play->nextEntranceIndex = ENTR_ZORAS_FOUNTAIN_0;
|
}
|
||||||
gSaveContext.nextCutsceneIndex = 0;
|
|
||||||
} else {
|
|
||||||
Item_Give(play, ITEM_ZORA_SAPPHIRE);
|
|
||||||
play->nextEntranceIndex = ENTR_ZORAS_FOUNTAIN_0;
|
|
||||||
gSaveContext.nextCutsceneIndex = 0xFFF0;
|
gSaveContext.nextCutsceneIndex = 0xFFF0;
|
||||||
}
|
}
|
||||||
|
play->nextEntranceIndex = ENTR_ZORAS_FOUNTAIN_0;
|
||||||
|
|
||||||
if (IS_RANDO && (Randomizer_GetSettingValue(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF ||
|
if (IS_RANDO && (Randomizer_GetSettingValue(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF ||
|
||||||
Randomizer_GetSettingValue(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF)) {
|
Randomizer_GetSettingValue(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF)) {
|
||||||
@ -767,11 +705,6 @@ void DoorWarp1_AdultWarpIdle(DoorWarp1* this, PlayState* play) {
|
|||||||
|
|
||||||
player = GET_PLAYER(play);
|
player = GET_PLAYER(play);
|
||||||
|
|
||||||
if (IS_RANDO) {
|
|
||||||
GivePlayerRandoReward(this, player, play, 0, 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
OnePointCutscene_Init(play, 0x25E8, 999, &this->actor, MAIN_CAM);
|
OnePointCutscene_Init(play, 0x25E8, 999, &this->actor, MAIN_CAM);
|
||||||
func_8002DF54(play, &this->actor, 10);
|
func_8002DF54(play, &this->actor, 10);
|
||||||
player->unk_450.x = this->actor.world.pos.x;
|
player->unk_450.x = this->actor.world.pos.x;
|
||||||
@ -829,19 +762,14 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, PlayState* play) {
|
|||||||
if (IS_BOSS_RUSH) {
|
if (IS_BOSS_RUSH) {
|
||||||
BossRush_HandleBlueWarp(play, this->actor.world.pos.x, this->actor.world.pos.z);
|
BossRush_HandleBlueWarp(play, this->actor.world.pos.x, this->actor.world.pos.z);
|
||||||
} else if (play->sceneNum == SCENE_FOREST_TEMPLE_BOSS) {
|
} else if (play->sceneNum == SCENE_FOREST_TEMPLE_BOSS) {
|
||||||
if (!Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP)) {
|
if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP), EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP)) {
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP);
|
Flags_SetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP);
|
||||||
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_FOREST_TEMPLE);
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_FOREST)) {
|
||||||
|
|
||||||
if (IS_RANDO) {
|
|
||||||
play->nextEntranceIndex = ENTR_SACRED_FOREST_MEADOW_3;
|
|
||||||
gSaveContext.nextCutsceneIndex = 0;
|
|
||||||
} else {
|
|
||||||
Item_Give(play, ITEM_MEDALLION_FOREST);
|
Item_Give(play, ITEM_MEDALLION_FOREST);
|
||||||
play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0;
|
|
||||||
gSaveContext.nextCutsceneIndex = 0;
|
|
||||||
gSaveContext.chamberCutsceneNum = CHAMBER_CS_FOREST;
|
|
||||||
}
|
}
|
||||||
|
play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0;
|
||||||
|
gSaveContext.nextCutsceneIndex = 0;
|
||||||
|
gSaveContext.chamberCutsceneNum = CHAMBER_CS_FOREST;
|
||||||
} else {
|
} else {
|
||||||
if (!LINK_IS_ADULT) {
|
if (!LINK_IS_ADULT) {
|
||||||
play->nextEntranceIndex = ENTR_SACRED_FOREST_MEADOW_2;
|
play->nextEntranceIndex = ENTR_SACRED_FOREST_MEADOW_2;
|
||||||
@ -851,20 +779,13 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, PlayState* play) {
|
|||||||
gSaveContext.nextCutsceneIndex = 0;
|
gSaveContext.nextCutsceneIndex = 0;
|
||||||
}
|
}
|
||||||
} else if (play->sceneNum == SCENE_FIRE_TEMPLE_BOSS) {
|
} else if (play->sceneNum == SCENE_FIRE_TEMPLE_BOSS) {
|
||||||
if (!Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP)) {
|
if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !Flags_GetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP), EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP)) {
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP);
|
Flags_SetEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP);
|
||||||
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE);
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_FIRE)) {
|
||||||
|
|
||||||
if (IS_RANDO) {
|
|
||||||
play->nextEntranceIndex = ENTR_DEATH_MOUNTAIN_CRATER_5;
|
|
||||||
gSaveContext.nextCutsceneIndex = 0;
|
|
||||||
// Change Death Mountain cloud since we aren't warping to the cutscene
|
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_DEATH_MOUNTAIN_ERUPTED);
|
|
||||||
} else {
|
|
||||||
Item_Give(play, ITEM_MEDALLION_FIRE);
|
Item_Give(play, ITEM_MEDALLION_FIRE);
|
||||||
play->nextEntranceIndex = ENTR_KAKARIKO_VILLAGE_0;
|
|
||||||
gSaveContext.nextCutsceneIndex = 0xFFF3;
|
|
||||||
}
|
}
|
||||||
|
play->nextEntranceIndex = ENTR_KAKARIKO_VILLAGE_0;
|
||||||
|
gSaveContext.nextCutsceneIndex = 0xFFF3;
|
||||||
} else {
|
} else {
|
||||||
if (!LINK_IS_ADULT) {
|
if (!LINK_IS_ADULT) {
|
||||||
play->nextEntranceIndex = ENTR_DEATH_MOUNTAIN_CRATER_4;
|
play->nextEntranceIndex = ENTR_DEATH_MOUNTAIN_CRATER_4;
|
||||||
@ -874,21 +795,14 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, PlayState* play) {
|
|||||||
gSaveContext.nextCutsceneIndex = 0;
|
gSaveContext.nextCutsceneIndex = 0;
|
||||||
}
|
}
|
||||||
} else if (play->sceneNum == SCENE_WATER_TEMPLE_BOSS) {
|
} else if (play->sceneNum == SCENE_WATER_TEMPLE_BOSS) {
|
||||||
if (!Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)) {
|
if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP), EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)) {
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP);
|
Flags_SetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP);
|
||||||
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE);
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_WATER)) {
|
||||||
|
|
||||||
if (IS_RANDO) {
|
|
||||||
play->nextEntranceIndex = ENTR_LAKE_HYLIA_9;
|
|
||||||
gSaveContext.nextCutsceneIndex = 0;
|
|
||||||
// Fill Lake Hylia since we aren't warping to the cutscene
|
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_RAISED_LAKE_HYLIA_WATER);
|
|
||||||
} else {
|
|
||||||
Item_Give(play, ITEM_MEDALLION_WATER);
|
Item_Give(play, ITEM_MEDALLION_WATER);
|
||||||
play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0;
|
|
||||||
gSaveContext.nextCutsceneIndex = 0;
|
|
||||||
gSaveContext.chamberCutsceneNum = CHAMBER_CS_WATER;
|
|
||||||
}
|
}
|
||||||
|
play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0;
|
||||||
|
gSaveContext.nextCutsceneIndex = 0;
|
||||||
|
gSaveContext.chamberCutsceneNum = CHAMBER_CS_WATER;
|
||||||
} else {
|
} else {
|
||||||
if (!LINK_IS_ADULT) {
|
if (!LINK_IS_ADULT) {
|
||||||
play->nextEntranceIndex = ENTR_LAKE_HYLIA_8;
|
play->nextEntranceIndex = ENTR_LAKE_HYLIA_8;
|
||||||
@ -898,18 +812,14 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, PlayState* play) {
|
|||||||
gSaveContext.nextCutsceneIndex = 0;
|
gSaveContext.nextCutsceneIndex = 0;
|
||||||
}
|
}
|
||||||
} else if (play->sceneNum == SCENE_SPIRIT_TEMPLE_BOSS) {
|
} else if (play->sceneNum == SCENE_SPIRIT_TEMPLE_BOSS) {
|
||||||
if (!CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) || IS_RANDO) {
|
if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT), RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE)) {
|
||||||
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE);
|
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE);
|
||||||
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_SPIRIT)) {
|
||||||
if (IS_RANDO) {
|
|
||||||
play->nextEntranceIndex = ENTR_DESERT_COLOSSUS_8;
|
|
||||||
gSaveContext.nextCutsceneIndex = 0;
|
|
||||||
} else {
|
|
||||||
Item_Give(play, ITEM_MEDALLION_SPIRIT);
|
Item_Give(play, ITEM_MEDALLION_SPIRIT);
|
||||||
play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0;
|
|
||||||
gSaveContext.nextCutsceneIndex = 0;
|
|
||||||
gSaveContext.chamberCutsceneNum = CHAMBER_CS_SPIRIT;
|
|
||||||
}
|
}
|
||||||
|
play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0;
|
||||||
|
gSaveContext.nextCutsceneIndex = 0;
|
||||||
|
gSaveContext.chamberCutsceneNum = CHAMBER_CS_SPIRIT;
|
||||||
} else {
|
} else {
|
||||||
if (!LINK_IS_ADULT) {
|
if (!LINK_IS_ADULT) {
|
||||||
play->nextEntranceIndex = ENTR_DESERT_COLOSSUS_5;
|
play->nextEntranceIndex = ENTR_DESERT_COLOSSUS_5;
|
||||||
@ -919,18 +829,14 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, PlayState* play) {
|
|||||||
gSaveContext.nextCutsceneIndex = 0;
|
gSaveContext.nextCutsceneIndex = 0;
|
||||||
}
|
}
|
||||||
} else if (play->sceneNum == SCENE_SHADOW_TEMPLE_BOSS) {
|
} else if (play->sceneNum == SCENE_SHADOW_TEMPLE_BOSS) {
|
||||||
if (!CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) || IS_RANDO) {
|
if (GameInteractor_Should(GI_VB_PLAY_BLUE_WARP_CS, !CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW), RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE)) {
|
||||||
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE);
|
Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE);
|
||||||
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_SHADOW)) {
|
||||||
if (IS_RANDO) {
|
|
||||||
play->nextEntranceIndex = ENTR_GRAVEYARD_8;
|
|
||||||
gSaveContext.nextCutsceneIndex = 0;
|
|
||||||
} else {
|
|
||||||
Item_Give(play, ITEM_MEDALLION_SHADOW);
|
Item_Give(play, ITEM_MEDALLION_SHADOW);
|
||||||
play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0;
|
|
||||||
gSaveContext.nextCutsceneIndex = 0;
|
|
||||||
gSaveContext.chamberCutsceneNum = CHAMBER_CS_SHADOW;
|
|
||||||
}
|
}
|
||||||
|
play->nextEntranceIndex = ENTR_CHAMBER_OF_THE_SAGES_0;
|
||||||
|
gSaveContext.nextCutsceneIndex = 0;
|
||||||
|
gSaveContext.chamberCutsceneNum = CHAMBER_CS_SHADOW;
|
||||||
} else {
|
} else {
|
||||||
if (!LINK_IS_ADULT) {
|
if (!LINK_IS_ADULT) {
|
||||||
play->nextEntranceIndex = ENTR_GRAVEYARD_7;
|
play->nextEntranceIndex = ENTR_GRAVEYARD_7;
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "z_elf_msg.h"
|
#include "z_elf_msg.h"
|
||||||
#include "vt.h"
|
#include "vt.h"
|
||||||
#include "overlays/actors/ovl_En_Elf/z_en_elf.h"
|
#include "overlays/actors/ovl_En_Elf/z_en_elf.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
|
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
|
||||||
|
|
||||||
@ -110,7 +111,7 @@ void ElfMsg_Destroy(Actor* thisx, PlayState* play) {
|
|||||||
|
|
||||||
s32 ElfMsg_GetMessageId(ElfMsg* this) {
|
s32 ElfMsg_GetMessageId(ElfMsg* this) {
|
||||||
// Negative message ID forces link to talk to Navi
|
// Negative message ID forces link to talk to Navi
|
||||||
if (this->actor.params & 0x8000 || CVarGetInteger("gNoForcedNavi", 0) != 0) {
|
if (this->actor.params & 0x8000) {
|
||||||
return (this->actor.params & 0xFF) + 0x100;
|
return (this->actor.params & 0xFF) + 0x100;
|
||||||
} else {
|
} else {
|
||||||
return -((this->actor.params & 0xFF) + 0x100);
|
return -((this->actor.params & 0xFF) + 0x100);
|
||||||
@ -125,8 +126,10 @@ void ElfMsg_CallNaviCuboid(ElfMsg* this, PlayState* play) {
|
|||||||
(this->actor.world.pos.y <= player->actor.world.pos.y) &&
|
(this->actor.world.pos.y <= player->actor.world.pos.y) &&
|
||||||
((player->actor.world.pos.y - this->actor.world.pos.y) < (100.0f * this->actor.scale.y)) &&
|
((player->actor.world.pos.y - this->actor.world.pos.y) < (100.0f * this->actor.scale.y)) &&
|
||||||
(fabsf(player->actor.world.pos.z - this->actor.world.pos.z) < (100.0f * this->actor.scale.z))) {
|
(fabsf(player->actor.world.pos.z - this->actor.world.pos.z) < (100.0f * this->actor.scale.z))) {
|
||||||
player->naviTextId = ElfMsg_GetMessageId(this);
|
if (GameInteractor_Should(GI_VB_NAVI_TALK, true, this)) {
|
||||||
navi->elfMsg = this;
|
player->naviTextId = ElfMsg_GetMessageId(this);
|
||||||
|
navi->elfMsg = this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,8 +148,10 @@ void ElfMsg_CallNaviCylinder(ElfMsg* this, PlayState* play) {
|
|||||||
if (ElfMsg_WithinXZDistance(&player->actor.world.pos, &this->actor.world.pos, this->actor.scale.x * 100.0f) &&
|
if (ElfMsg_WithinXZDistance(&player->actor.world.pos, &this->actor.world.pos, this->actor.scale.x * 100.0f) &&
|
||||||
(this->actor.world.pos.y <= player->actor.world.pos.y) &&
|
(this->actor.world.pos.y <= player->actor.world.pos.y) &&
|
||||||
((player->actor.world.pos.y - this->actor.world.pos.y) < (100.0f * this->actor.scale.y))) {
|
((player->actor.world.pos.y - this->actor.world.pos.y) < (100.0f * this->actor.scale.y))) {
|
||||||
player->naviTextId = ElfMsg_GetMessageId(this);
|
if (GameInteractor_Should(GI_VB_NAVI_TALK, true, this)) {
|
||||||
navi->elfMsg = this;
|
player->naviTextId = ElfMsg_GetMessageId(this);
|
||||||
|
navi->elfMsg = this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "soh_assets.h"
|
#include "soh_assets.h"
|
||||||
#include "soh/Enhancements/enhancementTypes.h"
|
#include "soh/Enhancements/enhancementTypes.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS 0
|
#define FLAGS 0
|
||||||
|
|
||||||
@ -192,10 +193,12 @@ void EnBox_Init(Actor* thisx, PlayState* play2) {
|
|||||||
SkelAnime_Init(play, &this->skelanime, &gTreasureChestSkel, anim, this->jointTable, this->morphTable, 5);
|
SkelAnime_Init(play, &this->skelanime, &gTreasureChestSkel, anim, this->jointTable, this->morphTable, 5);
|
||||||
Animation_Change(&this->skelanime, anim, 1.5f, animFrameStart, endFrame, ANIMMODE_ONCE, 0.0f);
|
Animation_Change(&this->skelanime, anim, 1.5f, animFrameStart, endFrame, ANIMMODE_ONCE, 0.0f);
|
||||||
|
|
||||||
|
this->getItemEntry = ItemTable_RetrieveEntry(MOD_NONE, this->dyna.actor.params >> 5 & 0x7F);
|
||||||
if (IS_RANDO) {
|
if (IS_RANDO) {
|
||||||
this->getItemEntry = Randomizer_GetItemFromActor(this->dyna.actor.id, play->sceneNum, this->dyna.actor.params, this->dyna.actor.params >> 5 & 0x7F);
|
RandomizerCheck rc = Randomizer_GetCheckFromActor(this->dyna.actor.id, play->sceneNum, this->dyna.actor.params);
|
||||||
} else {
|
if (rc != RC_UNKNOWN_CHECK) {
|
||||||
this->getItemEntry = ItemTable_RetrieveEntry(MOD_NONE, this->dyna.actor.params >> 5 & 0x7F);
|
this->getItemEntry = Randomizer_GetItemFromKnownCheck(rc, this->dyna.actor.params >> 5 & 0x7F);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EnBox_UpdateSizeAndTexture(this, play);
|
EnBox_UpdateSizeAndTexture(this, play);
|
||||||
@ -275,7 +278,9 @@ void EnBox_Fall(EnBox* this, PlayState* play) {
|
|||||||
this->dyna.actor.shape.rot.z = 0;
|
this->dyna.actor.shape.rot.z = 0;
|
||||||
this->dyna.actor.world.pos.y = this->dyna.actor.floorHeight;
|
this->dyna.actor.world.pos.y = this->dyna.actor.floorHeight;
|
||||||
EnBox_SetupAction(this, EnBox_WaitOpen);
|
EnBox_SetupAction(this, EnBox_WaitOpen);
|
||||||
OnePointCutscene_EndCutscene(play, this->unk_1AC);
|
if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) {
|
||||||
|
OnePointCutscene_EndCutscene(play, this->unk_1AC);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Audio_PlaySoundGeneral(NA_SE_EV_COFFIN_CAP_BOUND, &this->dyna.actor.projectedPos, 4, &D_801333E0, &D_801333E0,
|
Audio_PlaySoundGeneral(NA_SE_EV_COFFIN_CAP_BOUND, &this->dyna.actor.projectedPos, 4, &D_801333E0, &D_801333E0,
|
||||||
&D_801333E8);
|
&D_801333E8);
|
||||||
@ -445,74 +450,12 @@ void EnBox_WaitOpen(EnBox* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
osSyncPrintf("Actor_Environment_Tbox_On() %d\n", this->dyna.actor.params & 0x1F);
|
osSyncPrintf("Actor_Environment_Tbox_On() %d\n", this->dyna.actor.params & 0x1F);
|
||||||
Flags_SetTreasure(play, this->dyna.actor.params & 0x1F);
|
Flags_SetTreasure(play, this->dyna.actor.params & 0x1F);
|
||||||
|
|
||||||
// treasure chest game rando
|
|
||||||
if (Randomizer_GetSettingValue(RSK_SHUFFLE_CHEST_MINIGAME)) {
|
|
||||||
if (IS_RANDO && play->sceneNum == SCENE_TREASURE_BOX_SHOP && (this->dyna.actor.params & 0x60) != 0x20) {
|
|
||||||
if((this->dyna.actor.params & 0xF) < 2) {
|
|
||||||
Flags_SetCollectible(play, 0x1B);
|
|
||||||
}
|
|
||||||
if((this->dyna.actor.params & 0xF) >= 2 && (this->dyna.actor.params & 0xF) < 4) {
|
|
||||||
Flags_SetCollectible(play, 0x1C);
|
|
||||||
}
|
|
||||||
if((this->dyna.actor.params & 0xF) >= 4 && (this->dyna.actor.params & 0xF) < 6) {
|
|
||||||
Flags_SetCollectible(play, 0x1D);
|
|
||||||
}
|
|
||||||
if((this->dyna.actor.params & 0xF) >= 6 && (this->dyna.actor.params & 0xF) < 8) {
|
|
||||||
Flags_SetCollectible(play, 0x1E);
|
|
||||||
}
|
|
||||||
if((this->dyna.actor.params & 0xF) >= 8 && (this->dyna.actor.params & 0xF) < 10) {
|
|
||||||
Flags_SetCollectible(play, 0x1F);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
player = GET_PLAYER(play);
|
player = GET_PLAYER(play);
|
||||||
func_8002DBD0(&this->dyna.actor, &sp4C, &player->actor.world.pos);
|
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 &&
|
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, play)) {
|
Player_IsFacingActor(&this->dyna.actor, 0x3000, play)) {
|
||||||
GetItemEntry sItem = Randomizer_GetItemFromActor(this->dyna.actor.id, play->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
|
|
||||||
if (Randomizer_GetSettingValue(RSK_SHUFFLE_CHEST_MINIGAME)) {
|
|
||||||
if (IS_RANDO && play->sceneNum == SCENE_TREASURE_BOX_SHOP && (this->dyna.actor.params & 0x60) != 0x20) {
|
|
||||||
if((this->dyna.actor.params & 0xF) < 2) {
|
|
||||||
if(Flags_GetCollectible(play, 0x1B)) {
|
|
||||||
sItem = blueRupee;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if((this->dyna.actor.params & 0xF) >= 2 && (this->dyna.actor.params & 0xF) < 4) {
|
|
||||||
if(Flags_GetCollectible(play, 0x1C)) {
|
|
||||||
sItem = blueRupee;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if((this->dyna.actor.params & 0xF) >= 4 && (this->dyna.actor.params & 0xF) < 6) {
|
|
||||||
if(Flags_GetCollectible(play, 0x1D)) {
|
|
||||||
sItem = blueRupee;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if((this->dyna.actor.params & 0xF) >= 6 && (this->dyna.actor.params & 0xF) < 8) {
|
|
||||||
if(Flags_GetCollectible(play, 0x1E)) {
|
|
||||||
sItem = blueRupee;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if((this->dyna.actor.params & 0xF) >= 8 && (this->dyna.actor.params & 0xF) < 10) {
|
|
||||||
if(Flags_GetCollectible(play, 0x1F)) {
|
|
||||||
sItem = blueRupee;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Chests need to have a negative getItemId in order to not immediately give their item
|
|
||||||
// when approaching.
|
|
||||||
if (IS_RANDO) {
|
|
||||||
sItem.getItemId = 0 - sItem.getItemId;
|
|
||||||
sItem.getItemFrom = ITEM_FROM_CHEST;
|
|
||||||
GiveItemEntryFromActorWithFixedRange(&this->dyna.actor, play, sItem);
|
|
||||||
} else {
|
|
||||||
func_8002F554(&this->dyna.actor, play, -(this->dyna.actor.params >> 5 & 0x7F));
|
func_8002F554(&this->dyna.actor, play, -(this->dyna.actor.params >> 5 & 0x7F));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (Flags_GetTreasure(play, this->dyna.actor.params & 0x1F)) {
|
if (Flags_GetTreasure(play, this->dyna.actor.params & 0x1F)) {
|
||||||
EnBox_SetupAction(this, EnBox_Open);
|
EnBox_SetupAction(this, EnBox_Open);
|
||||||
@ -626,12 +569,9 @@ void EnBox_Update(Actor* thisx, PlayState* play) {
|
|||||||
Actor_SetFocus(&this->dyna.actor, 40.0f);
|
Actor_SetFocus(&this->dyna.actor, 40.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((!IS_RANDO && ((this->dyna.actor.params >> 5 & 0x7F) == 0x7C)) ||
|
if ((this->dyna.actor.params >> 5 & 0x7F) == GI_ICE_TRAP && this->actionFunc == EnBox_Open &&
|
||||||
(IS_RANDO && this->getItemEntry.getItemId == RG_ICE_TRAP)) &&
|
this->skelanime.curFrame > 45 && this->iceSmokeTimer < 100) {
|
||||||
this->actionFunc == EnBox_Open && this->skelanime.curFrame > 45 && this->iceSmokeTimer < 100) {
|
EnBox_SpawnIceSmoke(this, play);
|
||||||
if (!CVarGetInteger("gAddTraps.enabled", 0)) {
|
|
||||||
EnBox_SpawnIceSmoke(this, play);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <libultraship/libultra.h>
|
#include <libultraship/libultra.h>
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
|
|
||||||
|
#define ENBOX_PARAMS(type, itemId, treasureFlag) ((type) << 12 | (itemId) << 5 | (treasureFlag))
|
||||||
#define ENBOX_TREASURE_FLAG_UNK_MIN 20
|
#define ENBOX_TREASURE_FLAG_UNK_MIN 20
|
||||||
#define ENBOX_TREASURE_FLAG_UNK_MAX 32
|
#define ENBOX_TREASURE_FLAG_UNK_MAX 32
|
||||||
|
|
||||||
@ -45,7 +46,7 @@ typedef struct EnBox {
|
|||||||
/* 0x01F9 */ u8 type;
|
/* 0x01F9 */ u8 type;
|
||||||
/* 0x01FA */ u8 iceSmokeTimer;
|
/* 0x01FA */ u8 iceSmokeTimer;
|
||||||
/* 0x01FB */ u8 unk_1FB;
|
/* 0x01FB */ u8 unk_1FB;
|
||||||
/* */ GetItemEntry getItemEntry;
|
/* */ GetItemEntry getItemEntry; // This is only to determine the Chest Style, randomzier item gives are handled elsewhere
|
||||||
/* */ Gfx* boxLidDL;
|
/* */ Gfx* boxLidDL;
|
||||||
/* */ Gfx* boxBodyDL;
|
/* */ Gfx* boxBodyDL;
|
||||||
} EnBox; // size = 0x01FC
|
} EnBox; // size = 0x01FC
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "z_en_cow.h"
|
#include "z_en_cow.h"
|
||||||
#include "objects/object_cow/object_cow.h"
|
#include "objects/object_cow/object_cow.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY)
|
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY)
|
||||||
|
|
||||||
@ -18,7 +19,6 @@ void func_809E0070(Actor* thisx, PlayState* play);
|
|||||||
|
|
||||||
void func_809DF494(EnCow* this, PlayState* play);
|
void func_809DF494(EnCow* this, PlayState* play);
|
||||||
void func_809DF6BC(EnCow* this, PlayState* play);
|
void func_809DF6BC(EnCow* this, PlayState* play);
|
||||||
void EnCow_MoveForRandomizer(EnCow* this, PlayState* play);
|
|
||||||
void func_809DF778(EnCow* this, PlayState* play);
|
void func_809DF778(EnCow* this, PlayState* play);
|
||||||
void func_809DF7D8(EnCow* this, PlayState* play);
|
void func_809DF7D8(EnCow* this, PlayState* play);
|
||||||
void func_809DF870(EnCow* this, PlayState* play);
|
void func_809DF870(EnCow* this, PlayState* play);
|
||||||
@ -107,10 +107,6 @@ void EnCow_Init(Actor* thisx, PlayState* play) {
|
|||||||
EnCow* this = (EnCow*)thisx;
|
EnCow* this = (EnCow*)thisx;
|
||||||
s32 pad;
|
s32 pad;
|
||||||
|
|
||||||
if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_COWS)) {
|
|
||||||
EnCow_MoveForRandomizer(thisx, play);
|
|
||||||
}
|
|
||||||
|
|
||||||
ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 72.0f);
|
ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 72.0f);
|
||||||
switch (this->actor.params) {
|
switch (this->actor.params) {
|
||||||
case 0:
|
case 0:
|
||||||
@ -122,18 +118,15 @@ void EnCow_Init(Actor* thisx, PlayState* play) {
|
|||||||
Collider_SetCylinder(play, &this->colliders[1], &this->actor, &sCylinderInit);
|
Collider_SetCylinder(play, &this->colliders[1], &this->actor, &sCylinderInit);
|
||||||
func_809DEE9C(this);
|
func_809DEE9C(this);
|
||||||
this->actionFunc = func_809DF96C;
|
this->actionFunc = func_809DF96C;
|
||||||
if (play->sceneNum == SCENE_LINKS_HOUSE) {
|
if (GameInteractor_Should(GI_VB_DESPAWN_HORSE_RACE_COW, (
|
||||||
if (!LINK_IS_ADULT && !CVarGetInteger("gCowOfTime", 0)) {
|
play->sceneNum == SCENE_LINKS_HOUSE && (!LINK_IS_ADULT || !Flags_GetEventChkInf(EVENTCHKINF_WON_COW_IN_MALONS_RACE))
|
||||||
Actor_Kill(&this->actor);
|
), this)) {
|
||||||
return;
|
Actor_Kill(&this->actor);
|
||||||
}
|
return;
|
||||||
if (!Flags_GetEventChkInf(EVENTCHKINF_WON_COW_IN_MALONS_RACE)) {
|
|
||||||
Actor_Kill(&this->actor);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_EN_COW, this->actor.world.pos.x,
|
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_EN_COW, this->actor.world.pos.x,
|
||||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, this->actor.shape.rot.y, 0, 1);
|
this->actor.world.pos.y, this->actor.world.pos.z, 0, this->actor.shape.rot.y, 0, 1);
|
||||||
this->unk_278 = Rand_ZeroFloat(1000.0f) + 40.0f;
|
this->unk_278 = Rand_ZeroFloat(1000.0f) + 40.0f;
|
||||||
this->unk_27A = 0;
|
this->unk_27A = 0;
|
||||||
this->actor.targetMode = 6;
|
this->actor.targetMode = 6;
|
||||||
@ -216,30 +209,6 @@ void func_809DF730(EnCow* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnCow_MoveForRandomizer(EnCow* this, PlayState* play) {
|
|
||||||
// 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 (play->sceneNum == SCENE_LON_LON_BUILDINGS && 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 (play->sceneNum == SCENE_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, PlayState* play) {
|
|
||||||
CowIdentity cowIdentity = Randomizer_IdentifyCow(play->sceneNum, this->actor.world.pos.x, this->actor.world.pos.z);
|
|
||||||
Player* player = GET_PLAYER(play);
|
|
||||||
player->pendingFlag.flagID = cowIdentity.randomizerInf;
|
|
||||||
player->pendingFlag.flagType = FLAG_RANDOMIZER_INF;
|
|
||||||
}
|
|
||||||
|
|
||||||
void func_809DF778(EnCow* this, PlayState* play) {
|
void func_809DF778(EnCow* this, PlayState* play) {
|
||||||
if (Actor_HasParent(&this->actor, play)) {
|
if (Actor_HasParent(&this->actor, play)) {
|
||||||
this->actor.parent = NULL;
|
this->actor.parent = NULL;
|
||||||
@ -281,23 +250,6 @@ void func_809DF8FC(EnCow* this, PlayState* play) {
|
|||||||
func_809DF494(this, play);
|
func_809DF494(this, play);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EnCow_HasBeenMilked(EnCow* this, PlayState* play) {
|
|
||||||
CowIdentity cowIdentity = Randomizer_IdentifyCow(play->sceneNum, this->actor.world.pos.x, this->actor.world.pos.z);
|
|
||||||
return Flags_GetRandomizerInf(cowIdentity.randomizerInf);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EnCow_GivePlayerRandomizedItem(EnCow* this, PlayState* play) {
|
|
||||||
if (!EnCow_HasBeenMilked(this, play)) {
|
|
||||||
CowIdentity cowIdentity = Randomizer_IdentifyCow(play->sceneNum, this->actor.world.pos.x, this->actor.world.pos.z);
|
|
||||||
GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(cowIdentity.randomizerCheck, GI_MILK);
|
|
||||||
GiveItemEntryFromActor(&this->actor, play, 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, PlayState* play) {
|
void func_809DF96C(EnCow* this, PlayState* play) {
|
||||||
if ((play->msgCtx.ocarinaMode == OCARINA_MODE_00) || (play->msgCtx.ocarinaMode == OCARINA_MODE_04)) {
|
if ((play->msgCtx.ocarinaMode == OCARINA_MODE_00) || (play->msgCtx.ocarinaMode == OCARINA_MODE_04)) {
|
||||||
if (DREG(53) != 0) {
|
if (DREG(53) != 0) {
|
||||||
@ -308,23 +260,14 @@ void func_809DF96C(EnCow* this, PlayState* play) {
|
|||||||
if ((this->actor.xzDistToPlayer < 150.0f) &&
|
if ((this->actor.xzDistToPlayer < 150.0f) &&
|
||||||
(ABS((s16)(this->actor.yawTowardsPlayer - this->actor.shape.rot.y)) < 0x61A8)) {
|
(ABS((s16)(this->actor.yawTowardsPlayer - this->actor.shape.rot.y)) < 0x61A8)) {
|
||||||
DREG(53) = 0;
|
DREG(53) = 0;
|
||||||
// when randomized with cowsanity, if we haven't gotten the
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_COW, true, this)) {
|
||||||
// reward from this cow yet, give that, otherwise use the
|
this->actionFunc = func_809DF8FC;
|
||||||
// vanilla cow behavior
|
this->actor.flags |= ACTOR_FLAG_WILL_TALK;
|
||||||
if (IS_RANDO &&
|
func_8002F2CC(&this->actor, play, 170.0f);
|
||||||
Randomizer_GetSettingValue(RSK_SHUFFLE_COWS) &&
|
this->actor.textId = 0x2006;
|
||||||
!EnCow_HasBeenMilked(this, play)) {
|
} else {
|
||||||
EnCow_SetCowMilked(this, play);
|
|
||||||
// setting the ocarina mode here prevents intermittent issues
|
|
||||||
// with the item get not triggering until walking away
|
|
||||||
play->msgCtx.ocarinaMode = OCARINA_MODE_00;
|
|
||||||
this->actionFunc = EnCow_GivePlayerRandomizedItem;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this->actionFunc = func_809DF8FC;
|
|
||||||
this->actor.flags |= ACTOR_FLAG_WILL_TALK;
|
|
||||||
func_8002F2CC(&this->actor, play, 170.0f);
|
|
||||||
this->actor.textId = 0x2006;
|
|
||||||
} else {
|
} else {
|
||||||
this->unk_276 |= 4;
|
this->unk_276 |= 4;
|
||||||
}
|
}
|
||||||
|
@ -21,4 +21,6 @@ typedef struct EnCow {
|
|||||||
/* 0x027C */ EnCowActionFunc actionFunc;
|
/* 0x027C */ EnCowActionFunc actionFunc;
|
||||||
} EnCow; // size = 0x0280
|
} EnCow; // size = 0x0280
|
||||||
|
|
||||||
|
void func_809DEE9C(EnCow* enCow);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -16,7 +16,6 @@ void EnDns_Destroy(Actor* thisx, PlayState* play);
|
|||||||
void EnDns_Update(Actor* thisx, PlayState* play);
|
void EnDns_Update(Actor* thisx, PlayState* play);
|
||||||
void EnDns_Draw(Actor* thisx, PlayState* play);
|
void EnDns_Draw(Actor* thisx, PlayState* play);
|
||||||
|
|
||||||
u32 EnDns_RandomizerPurchaseableCheck(EnDns* this);
|
|
||||||
u32 func_809EF5A4(EnDns* this);
|
u32 func_809EF5A4(EnDns* this);
|
||||||
u32 func_809EF658(EnDns* this);
|
u32 func_809EF658(EnDns* this);
|
||||||
u32 func_809EF70C(EnDns* this);
|
u32 func_809EF70C(EnDns* this);
|
||||||
@ -26,7 +25,6 @@ u32 func_809EF854(EnDns* this);
|
|||||||
u32 func_809EF8F4(EnDns* this);
|
u32 func_809EF8F4(EnDns* this);
|
||||||
u32 func_809EF9A4(EnDns* this);
|
u32 func_809EF9A4(EnDns* this);
|
||||||
|
|
||||||
void EnDns_RandomizerPurchase(EnDns* this);
|
|
||||||
void func_809EF9F8(EnDns* this);
|
void func_809EF9F8(EnDns* this);
|
||||||
void func_809EFA28(EnDns* this);
|
void func_809EFA28(EnDns* this);
|
||||||
void func_809EFA58(EnDns* this);
|
void func_809EFA58(EnDns* this);
|
||||||
@ -168,32 +166,6 @@ void EnDns_Init(Actor* thisx, PlayState* play) {
|
|||||||
this->actor.gravity = -1.0f;
|
this->actor.gravity = -1.0f;
|
||||||
this->actor.textId = D_809F040C[this->actor.params];
|
this->actor.textId = D_809F040C[this->actor.params];
|
||||||
this->dnsItemEntry = sItemEntries[this->actor.params];
|
this->dnsItemEntry = sItemEntries[this->actor.params];
|
||||||
if (IS_RANDO) {
|
|
||||||
// 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(play->sceneNum, this->actor.params, respawnData);
|
|
||||||
|
|
||||||
if ((Randomizer_GetSettingValue(RSK_SHUFFLE_SCRUBS) == RO_SCRUBS_AFFORDABLE ||
|
|
||||||
Randomizer_GetSettingValue(RSK_SHUFFLE_SCRUBS) == RO_SCRUBS_RANDOM) &&
|
|
||||||
this->scrubIdentity.itemPrice != -1) {
|
|
||||||
this->dnsItemEntry->itemPrice = this->scrubIdentity.itemPrice;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Randomizer_GetSettingValue(RSK_SHUFFLE_SCRUBS) == RO_SCRUBS_EXPENSIVE) {
|
|
||||||
// temporary workaround: always use 40 rupees as price instead of 70
|
|
||||||
if (this->actor.params == 0x0006) {
|
|
||||||
this->dnsItemEntry->itemPrice = 40;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->scrubIdentity.isShuffled) {
|
|
||||||
this->dnsItemEntry->getItemId = this->scrubIdentity.getItemId;
|
|
||||||
this->dnsItemEntry->purchaseableCheck = EnDns_RandomizerPurchaseableCheck;
|
|
||||||
this->dnsItemEntry->setRupeesAndFlags = EnDns_RandomizerPurchase;
|
|
||||||
this->dnsItemEntry->itemAmount = 1;
|
|
||||||
this->actor.textId = 0x9000 + (this->scrubIdentity.randomizerInf - RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this->actionFunc = EnDns_SetupWait;
|
this->actionFunc = EnDns_SetupWait;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,13 +188,6 @@ void EnDns_ChangeAnim(EnDns* this, u8 index) {
|
|||||||
|
|
||||||
/* Item give checking functions */
|
/* 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) {
|
u32 func_809EF5A4(EnDns* this) {
|
||||||
if ((CUR_CAPACITY(UPG_NUTS) != 0) && (AMMO(ITEM_NUT) >= CUR_CAPACITY(UPG_NUTS))) {
|
if ((CUR_CAPACITY(UPG_NUTS) != 0) && (AMMO(ITEM_NUT) >= CUR_CAPACITY(UPG_NUTS))) {
|
||||||
return 1;
|
return 1;
|
||||||
@ -319,10 +284,6 @@ u32 func_809EF9A4(EnDns* this) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Paying and flagging functions */
|
/* Paying and flagging functions */
|
||||||
void EnDns_RandomizerPurchase(EnDns* this) {
|
|
||||||
Rupees_ChangeBy(-this->dnsItemEntry->itemPrice);
|
|
||||||
Flags_SetRandomizerInf(this->scrubIdentity.randomizerInf);
|
|
||||||
}
|
|
||||||
|
|
||||||
void func_809EF9F8(EnDns* this) {
|
void func_809EF9F8(EnDns* this) {
|
||||||
Rupees_ChangeBy(-this->dnsItemEntry->itemPrice);
|
Rupees_ChangeBy(-this->dnsItemEntry->itemPrice);
|
||||||
@ -412,44 +373,39 @@ void EnDns_Talk(EnDns* this, PlayState* play) {
|
|||||||
|
|
||||||
void func_809EFDD0(EnDns* this, PlayState* play) {
|
void func_809EFDD0(EnDns* this, PlayState* play) {
|
||||||
u16 pendingGetItemId;
|
u16 pendingGetItemId;
|
||||||
if (!IS_RANDO || !this->scrubIdentity.isShuffled) {
|
if (this->actor.params == 0x9) {
|
||||||
if (this->actor.params == 0x9) {
|
if (CUR_UPG_VALUE(UPG_STICKS) < 2) {
|
||||||
if (CUR_UPG_VALUE(UPG_STICKS) < 2) {
|
pendingGetItemId = GI_STICK_UPGRADE_20;
|
||||||
pendingGetItemId = GI_STICK_UPGRADE_20;
|
|
||||||
} else {
|
|
||||||
pendingGetItemId = GI_STICK_UPGRADE_30;
|
|
||||||
}
|
|
||||||
} else if (this->actor.params == 0xA) {
|
|
||||||
if (CUR_UPG_VALUE(UPG_NUTS) < 2) {
|
|
||||||
pendingGetItemId = GI_NUT_UPGRADE_30;
|
|
||||||
} else {
|
|
||||||
pendingGetItemId = GI_NUT_UPGRADE_40;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
pendingGetItemId = this->dnsItemEntry->getItemId;
|
pendingGetItemId = GI_STICK_UPGRADE_30;
|
||||||
|
}
|
||||||
|
} else if (this->actor.params == 0xA) {
|
||||||
|
if (CUR_UPG_VALUE(UPG_NUTS) < 2) {
|
||||||
|
pendingGetItemId = GI_NUT_UPGRADE_30;
|
||||||
|
} else {
|
||||||
|
pendingGetItemId = GI_NUT_UPGRADE_40;
|
||||||
}
|
}
|
||||||
GetItemEntry itemEntry = ItemTable_Retrieve(pendingGetItemId);
|
|
||||||
gSaveContext.pendingSale = itemEntry.itemId;
|
|
||||||
gSaveContext.pendingSaleMod = itemEntry.modIndex;
|
|
||||||
func_8002F434(&this->actor, play, pendingGetItemId, 130.0f, 100.0f);
|
|
||||||
} else {
|
} else {
|
||||||
GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(this->scrubIdentity.randomizerCheck, this->scrubIdentity.getItemId);
|
pendingGetItemId = this->dnsItemEntry->getItemId;
|
||||||
gSaveContext.pendingSale = itemEntry.itemId;
|
|
||||||
gSaveContext.pendingSaleMod = itemEntry.modIndex;
|
|
||||||
GiveItemEntryFromActor(&this->actor, play, itemEntry, 130.0f, 100.0f);
|
|
||||||
}
|
}
|
||||||
|
GetItemEntry itemEntry = ItemTable_Retrieve(pendingGetItemId);
|
||||||
|
gSaveContext.pendingSale = itemEntry.itemId;
|
||||||
|
gSaveContext.pendingSaleMod = itemEntry.modIndex;
|
||||||
|
func_8002F434(&this->actor, play, pendingGetItemId, 130.0f, 100.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void func_809EFEE8(EnDns* this, PlayState* play) {
|
void func_809EFEE8(EnDns* this, PlayState* play) {
|
||||||
if ((Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)) {
|
if ((Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)) {
|
||||||
Message_CloseTextbox(play);
|
Message_CloseTextbox(play);
|
||||||
func_809EFDD0(this, play);
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BUSINESS_SCRUB, true, this)) {
|
||||||
|
func_809EFDD0(this, play);
|
||||||
|
}
|
||||||
this->actionFunc = func_809EFF50;
|
this->actionFunc = func_809EFF50;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void func_809EFF50(EnDns* this, PlayState* play) {
|
void func_809EFF50(EnDns* this, PlayState* play) {
|
||||||
if (Actor_HasParent(&this->actor, play)) {
|
if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_BUSINESS_SCRUB, true, this)) {
|
||||||
this->actor.parent = NULL;
|
this->actor.parent = NULL;
|
||||||
this->actionFunc = func_809EFF98;
|
this->actionFunc = func_809EFF98;
|
||||||
} else {
|
} else {
|
||||||
@ -533,9 +489,6 @@ void EnDns_Update(Actor* thisx, PlayState* play) {
|
|||||||
|
|
||||||
this->dustTimer++;
|
this->dustTimer++;
|
||||||
this->actor.textId = D_809F040C[this->actor.params];
|
this->actor.textId = D_809F040C[this->actor.params];
|
||||||
if (IS_RANDO && this->scrubIdentity.isShuffled) {
|
|
||||||
this->actor.textId = 0x9000 + (this->scrubIdentity.randomizerInf - RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT);
|
|
||||||
}
|
|
||||||
Actor_SetFocus(&this->actor, 60.0f);
|
Actor_SetFocus(&this->actor, 60.0f);
|
||||||
Actor_SetScale(&this->actor, 0.01f);
|
Actor_SetScale(&this->actor, 0.01f);
|
||||||
SkelAnime_Update(&this->skelAnime);
|
SkelAnime_Update(&this->skelAnime);
|
||||||
|
@ -32,7 +32,10 @@ typedef struct EnDns {
|
|||||||
/* 0x02BD */ u8 dropCollectible;
|
/* 0x02BD */ u8 dropCollectible;
|
||||||
/* 0x02C0 */ DnsItemEntry* dnsItemEntry;
|
/* 0x02C0 */ DnsItemEntry* dnsItemEntry;
|
||||||
/* 0x02C4 */ f32 yInitPos;
|
/* 0x02C4 */ f32 yInitPos;
|
||||||
/* */ ScrubIdentity scrubIdentity;
|
// #region SOH [Randomizer]
|
||||||
|
/* */ DnsItemEntry sohDnsItemEntry;
|
||||||
|
/* */ ScrubIdentity sohScrubIdentity;
|
||||||
|
// #endregion
|
||||||
} EnDns; // size = 0x02C8
|
} EnDns; // size = 0x02C8
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#include "z_en_ds.h"
|
#include "z_en_ds.h"
|
||||||
#include "objects/object_ds/object_ds.h"
|
#include "objects/object_ds/object_ds.h"
|
||||||
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY)
|
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY)
|
||||||
|
|
||||||
@ -90,19 +90,12 @@ void EnDs_DisplayOddPotionText(EnDs* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EnDs_GiveOddPotion(EnDs* this, PlayState* play) {
|
void EnDs_GiveOddPotion(EnDs* this, PlayState* play) {
|
||||||
if (Actor_HasParent(&this->actor, play)) {
|
if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_TRADE_ODD_MUSHROOM, true, this)) {
|
||||||
this->actor.parent = NULL;
|
this->actor.parent = NULL;
|
||||||
this->actionFunc = EnDs_DisplayOddPotionText;
|
this->actionFunc = EnDs_DisplayOddPotionText;
|
||||||
gSaveContext.timer2State = 0;
|
gSaveContext.timer2State = 0;
|
||||||
} else {
|
} else {
|
||||||
u32 itemId = GI_ODD_POTION;
|
func_8002F434(&this->actor, play, GI_ODD_POTION, 10000.0f, 50.0f);
|
||||||
if (IS_RANDO) {
|
|
||||||
GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_TRADE_ODD_MUSHROOM, GI_ODD_POTION);
|
|
||||||
GiveItemEntryFromActor(&this->actor, play, itemEntry, 10000.0f, 50.0f);
|
|
||||||
Randomizer_ConsumeAdultTradeItem(play, ITEM_ODD_MUSHROOM);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
func_8002F434(&this->actor, play, itemId, 10000.0f, 50.0f);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,13 +104,9 @@ void EnDs_TalkAfterBrewOddPotion(EnDs* this, PlayState* play) {
|
|||||||
Message_CloseTextbox(play);
|
Message_CloseTextbox(play);
|
||||||
this->actionFunc = EnDs_GiveOddPotion;
|
this->actionFunc = EnDs_GiveOddPotion;
|
||||||
u32 itemId = GI_ODD_POTION;
|
u32 itemId = GI_ODD_POTION;
|
||||||
if (IS_RANDO) {
|
if (GameInteractor_Should(GI_VB_TRADE_ODD_MUSHROOM, true, this)) {
|
||||||
GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_TRADE_ODD_MUSHROOM, GI_ODD_POTION);
|
func_8002F434(&this->actor, play, itemId, 10000.0f, 50.0f);
|
||||||
GiveItemEntryFromActor(&this->actor, play, itemEntry, 10000.0f, 50.0f);
|
|
||||||
Randomizer_ConsumeAdultTradeItem(play, ITEM_ODD_MUSHROOM);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
func_8002F434(&this->actor, play, itemId, 10000.0f, 50.0f);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +127,7 @@ void EnDs_BrewOddPotion2(EnDs* this, PlayState* play) {
|
|||||||
this->brewTimer -= 1;
|
this->brewTimer -= 1;
|
||||||
} else {
|
} else {
|
||||||
this->actionFunc = EnDs_BrewOddPotion3;
|
this->actionFunc = EnDs_BrewOddPotion3;
|
||||||
this->brewTimer = IS_RANDO ? 0 : 60;
|
this->brewTimer = GameInteractor_Should(GI_VB_PLAY_EYEDROP_CREATION_ANIM, true, this) ? 60 : 0;
|
||||||
Flags_UnsetSwitch(play, 0x3F);
|
Flags_UnsetSwitch(play, 0x3F);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -148,7 +137,7 @@ void EnDs_BrewOddPotion1(EnDs* this, PlayState* play) {
|
|||||||
this->brewTimer -= 1;
|
this->brewTimer -= 1;
|
||||||
} else {
|
} else {
|
||||||
this->actionFunc = EnDs_BrewOddPotion2;
|
this->actionFunc = EnDs_BrewOddPotion2;
|
||||||
this->brewTimer = IS_RANDO ? 0 : 20;
|
this->brewTimer = GameInteractor_Should(GI_VB_PLAY_EYEDROP_CREATION_ANIM, true, this) ? 20 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Math_StepToF(&this->unk_1E4, 1.0f, 0.01f);
|
Math_StepToF(&this->unk_1E4, 1.0f, 0.01f);
|
||||||
@ -162,7 +151,7 @@ void EnDs_OfferOddPotion(EnDs* this, PlayState* play) {
|
|||||||
switch (play->msgCtx.choiceIndex) {
|
switch (play->msgCtx.choiceIndex) {
|
||||||
case 0: // yes
|
case 0: // yes
|
||||||
this->actionFunc = EnDs_BrewOddPotion1;
|
this->actionFunc = EnDs_BrewOddPotion1;
|
||||||
this->brewTimer = IS_RANDO ? 0 : 60;
|
this->brewTimer = GameInteractor_Should(GI_VB_PLAY_EYEDROP_CREATION_ANIM, true, this) ? 60 : 0;
|
||||||
Flags_SetSwitch(play, 0x3F);
|
Flags_SetSwitch(play, 0x3F);
|
||||||
play->msgCtx.msgMode = MSGMODE_PAUSED;
|
play->msgCtx.msgMode = MSGMODE_PAUSED;
|
||||||
player->exchangeItemId = EXCH_ITEM_NONE;
|
player->exchangeItemId = EXCH_ITEM_NONE;
|
||||||
@ -174,22 +163,10 @@ void EnDs_OfferOddPotion(EnDs* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 EnDs_RandoCanGetGrannyItem() {
|
|
||||||
return IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF &&
|
|
||||||
!Flags_GetRandomizerInf(RAND_INF_MERCHANTS_GRANNYS_SHOP) &&
|
|
||||||
// Traded odd mushroom when adult trade is on
|
|
||||||
((Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE) && Flags_GetItemGetInf(ITEMGETINF_30)) ||
|
|
||||||
// Found claim check when adult trade is off
|
|
||||||
(!Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE) &&
|
|
||||||
INV_CONTENT(ITEM_CLAIM_CHECK) == ITEM_CLAIM_CHECK));
|
|
||||||
}
|
|
||||||
|
|
||||||
s32 EnDs_CheckRupeesAndBottle() {
|
s32 EnDs_CheckRupeesAndBottle() {
|
||||||
if (gSaveContext.rupees < 100) {
|
if (gSaveContext.rupees < 100) {
|
||||||
return 0;
|
return 0;
|
||||||
} else if (EnDs_RandoCanGetGrannyItem()) { // Allow buying the rando item regardless of having a bottle
|
} else if (GameInteractor_Should(GI_VB_NEED_BOTTLE_FOR_GRANNYS_ITEM, Inventory_HasEmptyBottle() == 0, NULL)) {
|
||||||
return 2;
|
|
||||||
} else if (Inventory_HasEmptyBottle() == 0) {
|
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
return 2;
|
return 2;
|
||||||
@ -197,20 +174,11 @@ s32 EnDs_CheckRupeesAndBottle() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EnDs_GiveBluePotion(EnDs* this, PlayState* play) {
|
void EnDs_GiveBluePotion(EnDs* this, PlayState* play) {
|
||||||
if (Actor_HasParent(&this->actor, play)) {
|
if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_GRANNYS_SHOP, true, this)) {
|
||||||
if (EnDs_RandoCanGetGrannyItem()) {
|
|
||||||
Flags_SetRandomizerInf(RAND_INF_MERCHANTS_GRANNYS_SHOP);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->actor.parent = NULL;
|
this->actor.parent = NULL;
|
||||||
this->actionFunc = EnDs_Talk;
|
this->actionFunc = EnDs_Talk;
|
||||||
} else {
|
} else {
|
||||||
if (EnDs_RandoCanGetGrannyItem()) {
|
func_8002F434(&this->actor, play, GI_POTION_BLUE, 10000.0f, 50.0f);
|
||||||
GetItemEntry entry = Randomizer_GetItemFromKnownCheck(RC_KAK_GRANNYS_SHOP, GI_POTION_BLUE);
|
|
||||||
GiveItemEntryFromActor(&this->actor, play, entry, 10000.0f, 50.0f);
|
|
||||||
} else {
|
|
||||||
func_8002F434(&this->actor, play, GI_POTION_BLUE, 10000.0f, 50.0f);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,18 +197,14 @@ void EnDs_OfferBluePotion(EnDs* this, PlayState* play) {
|
|||||||
case 2: // have 100 rupees and empty bottle
|
case 2: // have 100 rupees and empty bottle
|
||||||
Rupees_ChangeBy(-100);
|
Rupees_ChangeBy(-100);
|
||||||
this->actor.flags &= ~ACTOR_FLAG_WILL_TALK;
|
this->actor.flags &= ~ACTOR_FLAG_WILL_TALK;
|
||||||
GetItemEntry itemEntry;
|
|
||||||
|
|
||||||
if (EnDs_RandoCanGetGrannyItem()) {
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_GRANNYS_SHOP, true, this)) {
|
||||||
itemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_GRANNYS_SHOP, GI_POTION_BLUE);
|
GetItemEntry itemEntry = ItemTable_Retrieve(GI_POTION_BLUE);
|
||||||
GiveItemEntryFromActor(&this->actor, play, itemEntry, 10000.0f, 50.0f);
|
|
||||||
} else {
|
|
||||||
itemEntry = ItemTable_Retrieve(GI_POTION_BLUE);
|
|
||||||
func_8002F434(&this->actor, play, GI_POTION_BLUE, 10000.0f, 50.0f);
|
func_8002F434(&this->actor, play, GI_POTION_BLUE, 10000.0f, 50.0f);
|
||||||
|
gSaveContext.pendingSale = itemEntry.itemId;
|
||||||
|
gSaveContext.pendingSaleMod = itemEntry.modIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
gSaveContext.pendingSale = itemEntry.itemId;
|
|
||||||
gSaveContext.pendingSaleMod = itemEntry.modIndex;
|
|
||||||
this->actionFunc = EnDs_GiveBluePotion;
|
this->actionFunc = EnDs_GiveBluePotion;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -261,10 +225,7 @@ void EnDs_Wait(EnDs* this, PlayState* play) {
|
|||||||
Audio_PlaySoundGeneral(NA_SE_SY_TRE_BOX_APPEAR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
|
Audio_PlaySoundGeneral(NA_SE_SY_TRE_BOX_APPEAR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
|
||||||
player->actor.textId = 0x504A;
|
player->actor.textId = 0x504A;
|
||||||
this->actionFunc = EnDs_OfferOddPotion;
|
this->actionFunc = EnDs_OfferOddPotion;
|
||||||
} else if (
|
} else if (GameInteractor_Should(GI_VB_OFFER_BLUE_POTION, Flags_GetItemGetInf(ITEMGETINF_30), this)) { // Traded odd mushroom
|
||||||
// Always offer blue potion when adult trade is off
|
|
||||||
(IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE) == RO_GENERIC_OFF) ||
|
|
||||||
Flags_GetItemGetInf(ITEMGETINF_30)) { // Traded odd mushroom
|
|
||||||
player->actor.textId = 0x500C;
|
player->actor.textId = 0x500C;
|
||||||
this->actionFunc = EnDs_OfferBluePotion;
|
this->actionFunc = EnDs_OfferBluePotion;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "z_en_du.h"
|
#include "z_en_du.h"
|
||||||
#include "objects/object_du/object_du.h"
|
#include "objects/object_du/object_du.h"
|
||||||
#include "scenes/overworld/spot18/spot18_scene.h"
|
#include "scenes/overworld/spot18/spot18_scene.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_NO_FREEZE_OCARINA)
|
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_NO_FREEZE_OCARINA)
|
||||||
|
|
||||||
@ -376,7 +377,7 @@ void func_809FE4A4(EnDu* this, PlayState* play) {
|
|||||||
play->msgCtx.ocarinaMode = OCARINA_MODE_00;
|
play->msgCtx.ocarinaMode = OCARINA_MODE_00;
|
||||||
EnDu_SetupAction(this, func_809FE3C0);
|
EnDu_SetupAction(this, func_809FE3C0);
|
||||||
} else if (play->msgCtx.ocarinaMode >= OCARINA_MODE_06) {
|
} else if (play->msgCtx.ocarinaMode >= OCARINA_MODE_06) {
|
||||||
if (!IS_RANDO) {
|
if (GameInteractor_Should(GI_VB_PLAY_DARUNIAS_JOY_CS, true, NULL)) {
|
||||||
play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gGoronCityDaruniaWrongCs);
|
play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gGoronCityDaruniaWrongCs);
|
||||||
gSaveContext.cutsceneTrigger = 1;
|
gSaveContext.cutsceneTrigger = 1;
|
||||||
}
|
}
|
||||||
@ -385,7 +386,7 @@ void func_809FE4A4(EnDu* this, PlayState* play) {
|
|||||||
play->msgCtx.ocarinaMode = OCARINA_MODE_04;
|
play->msgCtx.ocarinaMode = OCARINA_MODE_04;
|
||||||
} else if (play->msgCtx.ocarinaMode == OCARINA_MODE_03) {
|
} else if (play->msgCtx.ocarinaMode == OCARINA_MODE_03) {
|
||||||
Audio_PlaySoundGeneral(NA_SE_SY_CORRECT_CHIME, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
|
Audio_PlaySoundGeneral(NA_SE_SY_CORRECT_CHIME, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
|
||||||
if (!IS_RANDO) {
|
if (GameInteractor_Should(GI_VB_PLAY_DARUNIAS_JOY_CS, true, NULL)) {
|
||||||
play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gGoronCityDaruniaCorrectCs);
|
play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gGoronCityDaruniaCorrectCs);
|
||||||
gSaveContext.cutsceneTrigger = 1;
|
gSaveContext.cutsceneTrigger = 1;
|
||||||
}
|
}
|
||||||
@ -474,10 +475,7 @@ void func_809FE890(EnDu* this, PlayState* play) {
|
|||||||
Vec3f velocity = { 0.0f, 0.0f, 0.0f };
|
Vec3f velocity = { 0.0f, 0.0f, 0.0f };
|
||||||
CsCmdActorAction* csAction;
|
CsCmdActorAction* csAction;
|
||||||
|
|
||||||
if (play->csCtx.state == CS_STATE_IDLE || IS_RANDO) {
|
if (play->csCtx.state == CS_STATE_IDLE) {
|
||||||
if (IS_RANDO) {
|
|
||||||
play->csCtx.state = CS_STATE_IDLE;
|
|
||||||
}
|
|
||||||
func_8002DF54(play, &this->actor, 1);
|
func_8002DF54(play, &this->actor, 1);
|
||||||
EnDu_SetupAction(this, func_809FEB08);
|
EnDu_SetupAction(this, func_809FEB08);
|
||||||
return;
|
return;
|
||||||
@ -556,11 +554,8 @@ void func_809FEB08(EnDu* this, PlayState* play) {
|
|||||||
EnDu_SetupAction(this, func_809FE3C0);
|
EnDu_SetupAction(this, func_809FE3C0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((!IS_RANDO && CUR_UPG_VALUE(UPG_STRENGTH) <= 0) ||
|
if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_DARUNIAS_JOY_REWARD, CUR_UPG_VALUE(UPG_STRENGTH) <= 0, NULL)) {
|
||||||
(IS_RANDO && !Flags_GetTreasure(play, 0x1E))) {
|
Flags_SetRandomizerInf(RAND_INF_DARUNIAS_JOY);
|
||||||
if (IS_RANDO) {
|
|
||||||
Flags_SetTreasure(play, 0x1E);
|
|
||||||
}
|
|
||||||
this->actor.textId = 0x301C;
|
this->actor.textId = 0x301C;
|
||||||
EnDu_SetupAction(this, func_809FEC14);
|
EnDu_SetupAction(this, func_809FEC14);
|
||||||
} else {
|
} else {
|
||||||
@ -581,17 +576,13 @@ void func_809FEC14(EnDu* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void func_809FEC70(EnDu* this, PlayState* play) {
|
void func_809FEC70(EnDu* this, PlayState* play) {
|
||||||
if (Actor_HasParent(&this->actor, play)) {
|
if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_STRENGTH_1, true, NULL)) {
|
||||||
this->actor.parent = NULL;
|
this->actor.parent = NULL;
|
||||||
EnDu_SetupAction(this, func_809FECE4);
|
EnDu_SetupAction(this, func_809FECE4);
|
||||||
} else {
|
} else {
|
||||||
f32 xzRange = this->actor.xzDistToPlayer + 1.0f;
|
f32 xzRange = this->actor.xzDistToPlayer + 1.0f;
|
||||||
if (!IS_RANDO) {
|
|
||||||
func_8002F434(&this->actor, play, GI_BRACELET, xzRange, fabsf(this->actor.yDistToPlayer) + 1.0f);
|
func_8002F434(&this->actor, play, GI_BRACELET, xzRange, fabsf(this->actor.yDistToPlayer) + 1.0f);
|
||||||
} else {
|
|
||||||
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_GC_DARUNIAS_JOY, GI_BRACELET);
|
|
||||||
GiveItemEntryFromActor(&this->actor, play, getItemEntry, xzRange, fabsf(this->actor.yDistToPlayer) + 1.0f);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +45,6 @@ void EnFr_OcarinaMistake(EnFr* this, PlayState* play);
|
|||||||
void EnFr_SetupReward(EnFr* this, PlayState* play, u8 unkCondition);
|
void EnFr_SetupReward(EnFr* this, PlayState* play, u8 unkCondition);
|
||||||
void EnFr_PrintTextBox(EnFr* this, PlayState* play);
|
void EnFr_PrintTextBox(EnFr* this, PlayState* play);
|
||||||
void EnFr_TalkBeforeReward(EnFr* this, PlayState* play);
|
void EnFr_TalkBeforeReward(EnFr* this, PlayState* play);
|
||||||
RandomizerCheck EnFr_RandomizerCheckFromSongIndex(u16 songIndex);
|
|
||||||
void EnFr_SetReward(EnFr* this, PlayState* play);
|
void EnFr_SetReward(EnFr* this, PlayState* play);
|
||||||
|
|
||||||
// Deactivate
|
// Deactivate
|
||||||
@ -618,7 +617,6 @@ void EnFr_Idle(EnFr* this, PlayState* play) {
|
|||||||
player->actor.world.pos.z = this->actor.world.pos.z; // z = -1220.0f
|
player->actor.world.pos.z = this->actor.world.pos.z; // z = -1220.0f
|
||||||
player->currentYaw = player->actor.world.rot.y = player->actor.shape.rot.y = this->actor.world.rot.y;
|
player->currentYaw = player->actor.world.rot.y = player->actor.shape.rot.y = this->actor.world.rot.y;
|
||||||
this->reward = GI_NONE;
|
this->reward = GI_NONE;
|
||||||
this->getItemEntry = (GetItemEntry)GET_ITEM_NONE;
|
|
||||||
this->actionFunc = EnFr_Activate;
|
this->actionFunc = EnFr_Activate;
|
||||||
} else if (EnFr_IsAboveAndWithin30DistXZ(player, this)) {
|
} else if (EnFr_IsAboveAndWithin30DistXZ(player, this)) {
|
||||||
player->unk_6A8 = &this->actor;
|
player->unk_6A8 = &this->actor;
|
||||||
@ -854,7 +852,6 @@ s32 EnFr_IsFrogSongComplete(EnFr* this, PlayState* play) {
|
|||||||
void EnFr_OcarinaMistake(EnFr* this, PlayState* play) {
|
void EnFr_OcarinaMistake(EnFr* this, PlayState* play) {
|
||||||
Message_CloseTextbox(play);
|
Message_CloseTextbox(play);
|
||||||
this->reward = GI_NONE;
|
this->reward = GI_NONE;
|
||||||
this->getItemEntry = (GetItemEntry)GET_ITEM_NONE;
|
|
||||||
func_80078884(NA_SE_SY_OCARINA_ERROR);
|
func_80078884(NA_SE_SY_OCARINA_ERROR);
|
||||||
Audio_OcaSetInstrument(0);
|
Audio_OcaSetInstrument(0);
|
||||||
sEnFrPointers.flags = 12;
|
sEnFrPointers.flags = 12;
|
||||||
@ -939,23 +936,6 @@ void EnFr_TalkBeforeReward(EnFr* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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, PlayState* play) {
|
void EnFr_SetReward(EnFr* this, PlayState* play) {
|
||||||
u16 songIndex;
|
u16 songIndex;
|
||||||
|
|
||||||
@ -963,16 +943,12 @@ void EnFr_SetReward(EnFr* this, PlayState* play) {
|
|||||||
songIndex = this->songIndex;
|
songIndex = this->songIndex;
|
||||||
this->actionFunc = EnFr_Deactivate;
|
this->actionFunc = EnFr_Deactivate;
|
||||||
this->reward = GI_NONE;
|
this->reward = GI_NONE;
|
||||||
this->getItemEntry = (GetItemEntry)GET_ITEM_NONE;
|
|
||||||
if ((songIndex >= FROG_ZL) && (songIndex <= FROG_SOT)) {
|
if ((songIndex >= FROG_ZL) && (songIndex <= FROG_SOT)) {
|
||||||
if (!(gSaveContext.eventChkInf[13] & sSongIndex[songIndex])) {
|
if (!(gSaveContext.eventChkInf[13] & sSongIndex[songIndex])) {
|
||||||
gSaveContext.eventChkInf[13] |= sSongIndex[songIndex];
|
gSaveContext.eventChkInf[13] |= sSongIndex[songIndex];
|
||||||
GameInteractor_ExecuteOnFlagSet(FLAG_EVENT_CHECK_INF, (EVENTCHKINF_SONGS_FOR_FROGS_INDEX << 4) + sSongIndexShift[songIndex]);
|
GameInteractor_ExecuteOnFlagSet(FLAG_EVENT_CHECK_INF, (EVENTCHKINF_SONGS_FOR_FROGS_INDEX << 4) + sSongIndexShift[songIndex]);
|
||||||
if (!IS_RANDO) {
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_FROGS, true, this)) {
|
||||||
this->reward = GI_RUPEE_PURPLE;
|
this->reward = GI_RUPEE_PURPLE;
|
||||||
} else {
|
|
||||||
this->getItemEntry = Randomizer_GetItemFromKnownCheck(EnFr_RandomizerCheckFromSongIndex(songIndex), GI_RUPEE_PURPLE);
|
|
||||||
this->reward = this->getItemEntry.getItemId;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this->reward = GI_RUPEE_BLUE;
|
this->reward = GI_RUPEE_BLUE;
|
||||||
@ -981,11 +957,8 @@ void EnFr_SetReward(EnFr* this, PlayState* play) {
|
|||||||
if (!(gSaveContext.eventChkInf[13] & sSongIndex[songIndex])) {
|
if (!(gSaveContext.eventChkInf[13] & sSongIndex[songIndex])) {
|
||||||
gSaveContext.eventChkInf[13] |= sSongIndex[songIndex];
|
gSaveContext.eventChkInf[13] |= sSongIndex[songIndex];
|
||||||
GameInteractor_ExecuteOnFlagSet(FLAG_EVENT_CHECK_INF, (EVENTCHKINF_SONGS_FOR_FROGS_INDEX << 4) + sSongIndexShift[songIndex]);
|
GameInteractor_ExecuteOnFlagSet(FLAG_EVENT_CHECK_INF, (EVENTCHKINF_SONGS_FOR_FROGS_INDEX << 4) + sSongIndexShift[songIndex]);
|
||||||
if (!IS_RANDO) {
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_FROGS, true, this)) {
|
||||||
this->reward = GI_HEART_PIECE;
|
this->reward = GI_HEART_PIECE;
|
||||||
} else {
|
|
||||||
this->getItemEntry = Randomizer_GetItemFromKnownCheck(RC_ZR_FROGS_IN_THE_RAIN, GI_HEART_PIECE);
|
|
||||||
this->reward = this->getItemEntry.getItemId;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this->reward = GI_RUPEE_BLUE;
|
this->reward = GI_RUPEE_BLUE;
|
||||||
@ -994,11 +967,8 @@ void EnFr_SetReward(EnFr* this, PlayState* play) {
|
|||||||
if (!(gSaveContext.eventChkInf[13] & sSongIndex[songIndex])) {
|
if (!(gSaveContext.eventChkInf[13] & sSongIndex[songIndex])) {
|
||||||
gSaveContext.eventChkInf[13] |= sSongIndex[songIndex];
|
gSaveContext.eventChkInf[13] |= sSongIndex[songIndex];
|
||||||
GameInteractor_ExecuteOnFlagSet(FLAG_EVENT_CHECK_INF, (EVENTCHKINF_SONGS_FOR_FROGS_INDEX << 4) + sSongIndexShift[songIndex]);
|
GameInteractor_ExecuteOnFlagSet(FLAG_EVENT_CHECK_INF, (EVENTCHKINF_SONGS_FOR_FROGS_INDEX << 4) + sSongIndexShift[songIndex]);
|
||||||
if (!IS_RANDO) {
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_FROGS, true, this)) {
|
||||||
this->reward = GI_HEART_PIECE;
|
this->reward = GI_HEART_PIECE;
|
||||||
} else {
|
|
||||||
this->getItemEntry = Randomizer_GetItemFromKnownCheck(RC_ZR_FROGS_OCARINA_GAME, GI_HEART_PIECE);
|
|
||||||
this->reward = this->getItemEntry.getItemId;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this->reward = GI_RUPEE_PURPLE;
|
this->reward = GI_RUPEE_PURPLE;
|
||||||
@ -1049,29 +1019,23 @@ void EnFr_Deactivate(EnFr* this, PlayState* play) {
|
|||||||
this->actionFunc = EnFr_Idle;
|
this->actionFunc = EnFr_Idle;
|
||||||
} else {
|
} else {
|
||||||
this->actionFunc = EnFr_GiveReward;
|
this->actionFunc = EnFr_GiveReward;
|
||||||
if (!IS_RANDO || this->getItemEntry.getItemId == GI_NONE) {
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_FROGS, true, this)) {
|
||||||
func_8002F434(&this->actor, play, this->reward, 30.0f, 100.0f);
|
func_8002F434(&this->actor, play, this->reward, 30.0f, 100.0f);
|
||||||
} else {
|
|
||||||
GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, 30.0f, 100.0f);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnFr_GiveReward(EnFr* this, PlayState* play) {
|
void EnFr_GiveReward(EnFr* this, PlayState* play) {
|
||||||
if (Actor_HasParent(&this->actor, play)) {
|
if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_FROGS, true, this)) {
|
||||||
this->actor.parent = NULL;
|
this->actor.parent = NULL;
|
||||||
this->actionFunc = EnFr_SetIdle;
|
this->actionFunc = EnFr_SetIdle;
|
||||||
} else {
|
} else {
|
||||||
if (!IS_RANDO || this->getItemEntry.getItemId == GI_NONE) {
|
func_8002F434(&this->actor, play, this->reward, 30.0f, 100.0f);
|
||||||
func_8002F434(&this->actor, play, this->reward, 30.0f, 100.0f);
|
|
||||||
} else {
|
|
||||||
GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, 30.0f, 100.0f);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnFr_SetIdle(EnFr* this, PlayState* play) {
|
void EnFr_SetIdle(EnFr* this, PlayState* play) {
|
||||||
if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play) || (IS_RANDO && this->reward == RG_ICE_TRAP)) {
|
if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) {
|
||||||
this->actionFunc = EnFr_Idle;
|
this->actionFunc = EnFr_Idle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,6 @@ typedef struct EnFr {
|
|||||||
/* 0x03AA */ s16 xyAngleButterfly; // Butterfly Travels along random angles in the x-y plane
|
/* 0x03AA */ s16 xyAngleButterfly; // Butterfly Travels along random angles in the x-y plane
|
||||||
/* 0x03AC */ Vec3f posButterfly; // Position/Coordinates of the Butterfly
|
/* 0x03AC */ Vec3f posButterfly; // Position/Coordinates of the Butterfly
|
||||||
/* 0x03B8 */ Vec3f posButterflyLight; // Used in Lights_PointNoGlowSetInfo()
|
/* 0x03B8 */ Vec3f posButterflyLight; // Used in Lights_PointNoGlowSetInfo()
|
||||||
/* */ GetItemEntry getItemEntry;
|
|
||||||
} EnFr; // size = 0x03C4
|
} EnFr; // size = 0x03C4
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -81,4 +80,7 @@ typedef struct {
|
|||||||
EnFr* frogs[5];
|
EnFr* frogs[5];
|
||||||
} EnFrPointers;
|
} EnFrPointers;
|
||||||
|
|
||||||
|
void EnFr_Idle(EnFr* enFr, PlayState* play);
|
||||||
|
void EnFr_GiveReward(EnFr* enFr, PlayState* play);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "objects/object_oF1d_map/object_oF1d_map.h"
|
#include "objects/object_oF1d_map/object_oF1d_map.h"
|
||||||
#include "objects/object_gm/object_gm.h"
|
#include "objects/object_gm/object_gm.h"
|
||||||
#include "vt.h"
|
#include "vt.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED)
|
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED)
|
||||||
@ -96,10 +97,9 @@ void EnGm_Destroy(Actor* thisx, PlayState* play) {
|
|||||||
s32 func_80A3D7C8(void) {
|
s32 func_80A3D7C8(void) {
|
||||||
if (LINK_AGE_IN_YEARS == YEARS_CHILD) {
|
if (LINK_AGE_IN_YEARS == YEARS_CHILD) {
|
||||||
return 0;
|
return 0;
|
||||||
} else if ((IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF) &&
|
} else if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_GIANTS_KNIFE_PURCHASE, (
|
||||||
!Flags_GetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON)) {
|
!CHECK_OWNED_EQUIP_ALT(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_BIGGORON) // Don't have giant's knife
|
||||||
return 1;
|
), NULL)) {
|
||||||
} else if (!CHECK_OWNED_EQUIP_ALT(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_BIGGORON)) { // Don't have giant's knife
|
|
||||||
return 1;
|
return 1;
|
||||||
} else if (CHECK_OWNED_EQUIP_ALT(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_BROKENGIANTKNIFE)) { // Have broken giant's knife
|
} else if (CHECK_OWNED_EQUIP_ALT(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_BROKENGIANTKNIFE)) { // Have broken giant's knife
|
||||||
return 2;
|
return 2;
|
||||||
@ -215,11 +215,6 @@ void func_80A3DC44(EnGm* this, PlayState* play) {
|
|||||||
return;
|
return;
|
||||||
case 1:
|
case 1:
|
||||||
Flags_SetInfTable(INFTABLE_B1);
|
Flags_SetInfTable(INFTABLE_B1);
|
||||||
if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF &&
|
|
||||||
!Flags_GetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON)) {
|
|
||||||
//Resets "Talked to Medigoron" flag in infTable to restore initial conversation state
|
|
||||||
Flags_UnsetInfTable(INFTABLE_B1);
|
|
||||||
}
|
|
||||||
case 2:
|
case 2:
|
||||||
this->actionFunc = EnGm_ProcessChoiceIndex;
|
this->actionFunc = EnGm_ProcessChoiceIndex;
|
||||||
default:
|
default:
|
||||||
@ -254,20 +249,10 @@ void EnGm_ProcessChoiceIndex(EnGm* this, PlayState* play) {
|
|||||||
Message_ContinueTextbox(play, 0xC8);
|
Message_ContinueTextbox(play, 0xC8);
|
||||||
this->actionFunc = func_80A3DD7C;
|
this->actionFunc = func_80A3DD7C;
|
||||||
} else {
|
} else {
|
||||||
GetItemEntry itemEntry;
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_MEDIGORON, true, this)) {
|
||||||
|
|
||||||
if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF &&
|
|
||||||
!Flags_GetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON)) {
|
|
||||||
itemEntry = Randomizer_GetItemFromKnownCheck(RC_GC_MEDIGORON, GI_SWORD_KNIFE);
|
|
||||||
GiveItemEntryFromActor(&this->actor, play, itemEntry, 415.0f, 10.0f);
|
|
||||||
Flags_SetInfTable(INFTABLE_B1);
|
|
||||||
} else {
|
|
||||||
itemEntry = ItemTable_Retrieve(GI_SWORD_KNIFE);
|
|
||||||
func_8002F434(&this->actor, play, GI_SWORD_KNIFE, 415.0f, 10.0f);
|
func_8002F434(&this->actor, play, GI_SWORD_KNIFE, 415.0f, 10.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
gSaveContext.pendingSale = itemEntry.itemId;
|
|
||||||
gSaveContext.pendingSaleMod = itemEntry.modIndex;
|
|
||||||
this->actionFunc = func_80A3DF00;
|
this->actionFunc = func_80A3DF00;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -280,24 +265,12 @@ void EnGm_ProcessChoiceIndex(EnGm* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void func_80A3DF00(EnGm* this, PlayState* play) {
|
void func_80A3DF00(EnGm* this, PlayState* play) {
|
||||||
if (Actor_HasParent(&this->actor, play)) {
|
if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_MEDIGORON, true, this)) {
|
||||||
if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF &&
|
Flags_SetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON);
|
||||||
!Flags_GetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON)) {
|
|
||||||
Flags_SetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->actor.parent = NULL;
|
this->actor.parent = NULL;
|
||||||
this->actionFunc = func_80A3DF60;
|
this->actionFunc = func_80A3DF60;
|
||||||
} else {
|
} else {
|
||||||
if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF &&
|
func_8002F434(&this->actor, play, GI_SWORD_KNIFE, 415.0f, 10.0f);
|
||||||
!Flags_GetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON)) {
|
|
||||||
GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_GC_MEDIGORON, GI_SWORD_KNIFE);
|
|
||||||
GiveItemEntryFromActor(&this->actor, play, itemEntry, 415.0f, 10.0f);
|
|
||||||
Flags_SetInfTable(INFTABLE_B1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
func_8002F434(&this->actor, play, GI_SWORD_KNIFE, 415.0f, 10.0f);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
#include "objects/gameplay_keep/gameplay_keep.h"
|
#include "objects/gameplay_keep/gameplay_keep.h"
|
||||||
#include "objects/object_oF1d_map/object_oF1d_map.h"
|
#include "objects/object_oF1d_map/object_oF1d_map.h"
|
||||||
#include "soh/frame_interpolation.h"
|
#include "soh/frame_interpolation.h"
|
||||||
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
|
|
||||||
|
|
||||||
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED)
|
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED)
|
||||||
|
|
||||||
@ -31,9 +30,11 @@ void func_80A40C78(EnGo* this, PlayState* play);
|
|||||||
void EnGo_Eyedrops(EnGo* this, PlayState* play);
|
void EnGo_Eyedrops(EnGo* this, PlayState* play);
|
||||||
void func_80A40DCC(EnGo* this, PlayState* play);
|
void func_80A40DCC(EnGo* this, PlayState* play);
|
||||||
|
|
||||||
void EnGo_AddDust(EnGo* this, Vec3f* pos, Vec3f* velocity, Vec3f* accel, u8 initialTimer, f32 scale, f32 scaleStep);
|
|
||||||
void EnGo_UpdateDust(EnGo* this);
|
void EnGo_SpawnEffectDust(EnGo* this, Vec3f* pos, Vec3f* velocity, Vec3f* accel, u8 initialTimer, f32 scale,
|
||||||
void EnGo_DrawDust(EnGo* this, PlayState* play);
|
f32 scaleStep);
|
||||||
|
void EnGo_UpdateEffects(EnGo* this);
|
||||||
|
void EnGo_DrawEffects(EnGo* this, PlayState* play);
|
||||||
|
|
||||||
const ActorInit En_Go_InitVars = {
|
const ActorInit En_Go_InitVars = {
|
||||||
ACTOR_EN_GO,
|
ACTOR_EN_GO,
|
||||||
@ -95,10 +96,10 @@ u16 EnGo_GetTextID(PlayState* play, Actor* thisx) {
|
|||||||
|
|
||||||
switch (thisx->params & 0xF0) {
|
switch (thisx->params & 0xF0) {
|
||||||
case 0x90:
|
case 0x90:
|
||||||
if (!IS_RANDO && gSaveContext.bgsFlag) {
|
if (gSaveContext.bgsFlag) {
|
||||||
return 0x305E;
|
return 0x305E;
|
||||||
} else if (INV_CONTENT(ITEM_TRADE_ADULT) >= ITEM_CLAIM_CHECK) {
|
} else if (INV_CONTENT(ITEM_TRADE_ADULT) >= ITEM_CLAIM_CHECK) {
|
||||||
if (Environment_GetBgsDayCount() >= CVarGetInteger("gForgeTime", 3)) {
|
if (Environment_GetBgsDayCount() >= 3) {
|
||||||
return 0x305E;
|
return 0x305E;
|
||||||
} else {
|
} else {
|
||||||
return 0x305D;
|
return 0x305D;
|
||||||
@ -113,8 +114,7 @@ u16 EnGo_GetTextID(PlayState* play, Actor* thisx) {
|
|||||||
return 0x3053;
|
return 0x3053;
|
||||||
}
|
}
|
||||||
case 0x00:
|
case 0x00:
|
||||||
if ((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) ||
|
if (CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) {
|
||||||
(IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) {
|
|
||||||
if (Flags_GetInfTable(INFTABLE_10F)) {
|
if (Flags_GetInfTable(INFTABLE_10F)) {
|
||||||
return 0x3042;
|
return 0x3042;
|
||||||
} else {
|
} else {
|
||||||
@ -199,7 +199,7 @@ u16 EnGo_GetTextID(PlayState* play, Actor* thisx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
s16 EnGo_UpdateTalkState(PlayState* play, Actor* thisx) {
|
s16 EnGo_UpdateTalkState(PlayState* play, Actor* thisx) {
|
||||||
s16 unkState = NPC_TALK_STATE_TALKING;
|
s16 talkState = NPC_TALK_STATE_TALKING;
|
||||||
f32 xzRange;
|
f32 xzRange;
|
||||||
f32 yRange = fabsf(thisx->yDistToPlayer) + 1.0f;
|
f32 yRange = fabsf(thisx->yDistToPlayer) + 1.0f;
|
||||||
|
|
||||||
@ -210,51 +210,51 @@ s16 EnGo_UpdateTalkState(PlayState* play, Actor* thisx) {
|
|||||||
switch (thisx->textId) {
|
switch (thisx->textId) {
|
||||||
case 0x3008:
|
case 0x3008:
|
||||||
Flags_SetInfTable(INFTABLE_E0);
|
Flags_SetInfTable(INFTABLE_E0);
|
||||||
unkState = NPC_TALK_STATE_IDLE;
|
talkState = NPC_TALK_STATE_IDLE;
|
||||||
break;
|
break;
|
||||||
case 0x300B:
|
case 0x300B:
|
||||||
Flags_SetInfTable(INFTABLE_EB);
|
Flags_SetInfTable(INFTABLE_EB);
|
||||||
unkState = NPC_TALK_STATE_IDLE;
|
talkState = NPC_TALK_STATE_IDLE;
|
||||||
break;
|
break;
|
||||||
case 0x3014:
|
case 0x3014:
|
||||||
Flags_SetInfTable(INFTABLE_F0);
|
Flags_SetInfTable(INFTABLE_F0);
|
||||||
unkState = NPC_TALK_STATE_IDLE;
|
talkState = NPC_TALK_STATE_IDLE;
|
||||||
break;
|
break;
|
||||||
case 0x3016:
|
case 0x3016:
|
||||||
Flags_SetInfTable(INFTABLE_F4);
|
Flags_SetInfTable(INFTABLE_F4);
|
||||||
unkState = NPC_TALK_STATE_IDLE;
|
talkState = NPC_TALK_STATE_IDLE;
|
||||||
break;
|
break;
|
||||||
case 0x3018:
|
case 0x3018:
|
||||||
Flags_SetInfTable(INFTABLE_F8);
|
Flags_SetInfTable(INFTABLE_F8);
|
||||||
unkState = NPC_TALK_STATE_IDLE;
|
talkState = NPC_TALK_STATE_IDLE;
|
||||||
break;
|
break;
|
||||||
case 0x3036:
|
case 0x3036:
|
||||||
func_8002F434(thisx, play, GI_TUNIC_GORON, xzRange, yRange);
|
func_8002F434(thisx, play, GI_TUNIC_GORON, xzRange, yRange);
|
||||||
Flags_SetInfTable(INFTABLE_10D); // EnGo exclusive flag
|
Flags_SetInfTable(INFTABLE_10D); // EnGo exclusive flag
|
||||||
unkState = NPC_TALK_STATE_ACTION;
|
talkState = NPC_TALK_STATE_ACTION;
|
||||||
break;
|
break;
|
||||||
case 0x3037:
|
case 0x3037:
|
||||||
Flags_SetInfTable(INFTABLE_SPOKE_TO_GORON_LINK);
|
Flags_SetInfTable(INFTABLE_SPOKE_TO_GORON_LINK);
|
||||||
unkState = NPC_TALK_STATE_IDLE;
|
talkState = NPC_TALK_STATE_IDLE;
|
||||||
break;
|
break;
|
||||||
case 0x3041:
|
case 0x3041:
|
||||||
Flags_SetInfTable(INFTABLE_10F);
|
Flags_SetInfTable(INFTABLE_10F);
|
||||||
unkState = NPC_TALK_STATE_IDLE;
|
talkState = NPC_TALK_STATE_IDLE;
|
||||||
break;
|
break;
|
||||||
case 0x3059:
|
case 0x3059:
|
||||||
unkState = NPC_TALK_STATE_ACTION;
|
talkState = NPC_TALK_STATE_ACTION;
|
||||||
break;
|
break;
|
||||||
case 0x3052:
|
case 0x3052:
|
||||||
case 0x3054:
|
case 0x3054:
|
||||||
case 0x3055:
|
case 0x3055:
|
||||||
case 0x305A:
|
case 0x305A:
|
||||||
unkState = NPC_TALK_STATE_ACTION;
|
talkState = NPC_TALK_STATE_ACTION;
|
||||||
break;
|
break;
|
||||||
case 0x305E:
|
case 0x305E:
|
||||||
unkState = NPC_TALK_STATE_ACTION;
|
talkState = NPC_TALK_STATE_ACTION;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
unkState = NPC_TALK_STATE_IDLE;
|
talkState = NPC_TALK_STATE_IDLE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -272,7 +272,7 @@ s16 EnGo_UpdateTalkState(PlayState* play, Actor* thisx) {
|
|||||||
thisx->textId = 0x300D;
|
thisx->textId = 0x300D;
|
||||||
}
|
}
|
||||||
Message_ContinueTextbox(play, thisx->textId);
|
Message_ContinueTextbox(play, thisx->textId);
|
||||||
unkState = NPC_TALK_STATE_TALKING;
|
talkState = NPC_TALK_STATE_TALKING;
|
||||||
break;
|
break;
|
||||||
case 0x3034:
|
case 0x3034:
|
||||||
if (play->msgCtx.choiceIndex == 0) {
|
if (play->msgCtx.choiceIndex == 0) {
|
||||||
@ -287,16 +287,16 @@ s16 EnGo_UpdateTalkState(PlayState* play, Actor* thisx) {
|
|||||||
thisx->textId = 0x3033;
|
thisx->textId = 0x3033;
|
||||||
}
|
}
|
||||||
Message_ContinueTextbox(play, thisx->textId);
|
Message_ContinueTextbox(play, thisx->textId);
|
||||||
unkState = NPC_TALK_STATE_TALKING;
|
talkState = NPC_TALK_STATE_TALKING;
|
||||||
break;
|
break;
|
||||||
case 0x3054:
|
case 0x3054:
|
||||||
case 0x3055:
|
case 0x3055:
|
||||||
if (play->msgCtx.choiceIndex == 0) {
|
if (play->msgCtx.choiceIndex == 0) {
|
||||||
unkState = NPC_TALK_STATE_ACTION;
|
talkState = NPC_TALK_STATE_ACTION;
|
||||||
} else {
|
} else {
|
||||||
thisx->textId = 0x3056;
|
thisx->textId = 0x3056;
|
||||||
Message_ContinueTextbox(play, thisx->textId);
|
Message_ContinueTextbox(play, thisx->textId);
|
||||||
unkState = NPC_TALK_STATE_TALKING;
|
talkState = NPC_TALK_STATE_TALKING;
|
||||||
}
|
}
|
||||||
Flags_SetInfTable(INFTABLE_B4);
|
Flags_SetInfTable(INFTABLE_B4);
|
||||||
break;
|
break;
|
||||||
@ -312,17 +312,17 @@ s16 EnGo_UpdateTalkState(PlayState* play, Actor* thisx) {
|
|||||||
case 0x3033:
|
case 0x3033:
|
||||||
thisx->textId = 0x3034;
|
thisx->textId = 0x3034;
|
||||||
Message_ContinueTextbox(play, thisx->textId);
|
Message_ContinueTextbox(play, thisx->textId);
|
||||||
unkState = NPC_TALK_STATE_TALKING;
|
talkState = NPC_TALK_STATE_TALKING;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
unkState = NPC_TALK_STATE_ACTION;
|
talkState = NPC_TALK_STATE_ACTION;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TEXT_STATE_DONE:
|
case TEXT_STATE_DONE:
|
||||||
if (Message_ShouldAdvance(play)) {
|
if (Message_ShouldAdvance(play)) {
|
||||||
unkState = NPC_TALK_STATE_ITEM_GIVEN;
|
talkState = NPC_TALK_STATE_ITEM_GIVEN;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TEXT_STATE_NONE:
|
case TEXT_STATE_NONE:
|
||||||
@ -332,21 +332,21 @@ s16 EnGo_UpdateTalkState(PlayState* play, Actor* thisx) {
|
|||||||
case TEXT_STATE_9:
|
case TEXT_STATE_9:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return unkState;
|
return talkState;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 func_80A3ED24(PlayState* play, EnGo* this, NpcInteractInfo* interactInfo, f32 arg3, NpcGetTextIdFunc getTextId,
|
s32 EnGo_UpdateTalking(PlayState* play, Actor* thisx, s16* talkState, f32 interactRange, NpcGetTextIdFunc getTextId,
|
||||||
NpcUpdateTalkStateFunc updateTalkState) {
|
NpcUpdateTalkStateFunc updateTalkState) {
|
||||||
if (interactInfo->talkState != NPC_TALK_STATE_IDLE) {
|
if (*talkState != NPC_TALK_STATE_IDLE) {
|
||||||
interactInfo->talkState = updateTalkState(play, &this->actor);
|
*talkState = updateTalkState(play, thisx);
|
||||||
return false;
|
return false;
|
||||||
} else if (Actor_ProcessTalkRequest(&this->actor, play)) {
|
} else if (Actor_ProcessTalkRequest(thisx, play)) {
|
||||||
interactInfo->talkState = NPC_TALK_STATE_TALKING;
|
*talkState = NPC_TALK_STATE_TALKING;
|
||||||
return true;
|
return true;
|
||||||
} else if (!func_8002F2CC(&this->actor, play, arg3)) {
|
} else if (!func_8002F2CC(thisx, play, interactRange)) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
this->actor.textId = getTextId(play, &this->actor);
|
thisx->textId = getTextId(play, thisx);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -379,7 +379,7 @@ s32 EnGo_IsActorSpawned(EnGo* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
f32 EnGo_GetGoronSize(EnGo* this) {
|
f32 EnGo_GetPlayerTrackingYOffset(EnGo* this) {
|
||||||
switch (this->actor.params & 0xF0) {
|
switch (this->actor.params & 0xF0) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
return 10.0f;
|
return 10.0f;
|
||||||
@ -398,16 +398,16 @@ f32 EnGo_GetGoronSize(EnGo* this) {
|
|||||||
|
|
||||||
void func_80A3F060(EnGo* this, PlayState* play) {
|
void func_80A3F060(EnGo* this, PlayState* play) {
|
||||||
Player* player = GET_PLAYER(play);
|
Player* player = GET_PLAYER(play);
|
||||||
s16 npcTrackingMode;
|
s16 trackingMode;
|
||||||
|
|
||||||
if (this->actionFunc != EnGo_BiggoronActionFunc && this->actionFunc != EnGo_FireGenericActionFunc &&
|
if (this->actionFunc != EnGo_BiggoronActionFunc && this->actionFunc != EnGo_FireGenericActionFunc &&
|
||||||
this->actionFunc != func_80A40B1C) {
|
this->actionFunc != func_80A40B1C) {
|
||||||
npcTrackingMode = NPC_TRACKING_NONE;
|
trackingMode = NPC_TRACKING_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->interactInfo.trackPos = player->actor.world.pos;
|
this->interactInfo.trackPos = player->actor.world.pos;
|
||||||
this->interactInfo.yOffset = EnGo_GetGoronSize(this);
|
this->interactInfo.yOffset = EnGo_GetPlayerTrackingYOffset(this);
|
||||||
Npc_TrackPoint(&this->actor, &this->interactInfo, 4, npcTrackingMode);
|
Npc_TrackPoint(&this->actor, &this->interactInfo, 4, trackingMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void func_80A3F0E4(EnGo* this) {
|
void func_80A3F0E4(EnGo* this) {
|
||||||
@ -421,23 +421,23 @@ void func_80A3F0E4(EnGo* this) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
s32 EnGo_IsCameraModified(EnGo* this, PlayState* play) {
|
s32 EnGo_IsCameraModified(EnGo* this, PlayState* play) {
|
||||||
f32 xyzDist;
|
f32 xyzDistSq;
|
||||||
s16 yawDiff = this->actor.yawTowardsPlayer - this->actor.shape.rot.y;
|
s16 yawDiff = this->actor.yawTowardsPlayer - this->actor.shape.rot.y;
|
||||||
Camera* camera = play->cameraPtrs[MAIN_CAM];
|
Camera* mainCam = play->cameraPtrs[MAIN_CAM];
|
||||||
|
|
||||||
if (fabsf(yawDiff) > 10920.0f) {
|
if (fabsf(yawDiff) > 10920.0f) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
xyzDist = (this->actor.scale.x / 0.01f) * 10000.0f;
|
xyzDistSq = (this->actor.scale.x / 0.01f) * SQ(100.0f);
|
||||||
if ((this->actor.params & 0xF0) == 0x90) {
|
if ((this->actor.params & 0xF0) == 0x90) {
|
||||||
Camera_ChangeSetting(camera, CAM_SET_DIRECTED_YAW);
|
Camera_ChangeSetting(mainCam, CAM_SET_DIRECTED_YAW);
|
||||||
xyzDist *= 4.8f;
|
xyzDistSq *= 4.8f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fabsf(this->actor.xyzDistToPlayerSq) > xyzDist) {
|
if (fabsf(this->actor.xyzDistToPlayerSq) > xyzDistSq) {
|
||||||
if (camera->setting == CAM_SET_DIRECTED_YAW) {
|
if (mainCam->setting == CAM_SET_DIRECTED_YAW) {
|
||||||
Camera_ChangeSetting(camera, CAM_SET_NORMAL0);
|
Camera_ChangeSetting(mainCam, CAM_SET_NORMAL0);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
@ -480,7 +480,7 @@ s32 EnGo_FollowPath(EnGo* this, PlayState* play) {
|
|||||||
pointPos += this->unk_218;
|
pointPos += this->unk_218;
|
||||||
xDist = pointPos->x - this->actor.world.pos.x;
|
xDist = pointPos->x - this->actor.world.pos.x;
|
||||||
zDist = pointPos->z - this->actor.world.pos.z;
|
zDist = pointPos->z - this->actor.world.pos.z;
|
||||||
Math_SmoothStepToS(&this->actor.world.rot.y, (s16)(Math_FAtan2F(xDist, zDist) * ((f32)0x8000 / M_PI)), 10, 1000, 1);
|
Math_SmoothStepToS(&this->actor.world.rot.y, RADF_TO_BINANG(Math_FAtan2F(xDist, zDist)), 10, 1000, 1);
|
||||||
|
|
||||||
if ((SQ(xDist) + SQ(zDist)) < 600.0f) {
|
if ((SQ(xDist) + SQ(zDist)) < 600.0f) {
|
||||||
this->unk_218++;
|
this->unk_218++;
|
||||||
@ -536,7 +536,7 @@ s32 EnGo_SpawnDust(EnGo* this, u8 initialTimer, f32 scale, f32 scaleStep, s32 nu
|
|||||||
accel.z = (Rand_ZeroOne() - 0.5f) * xzAccel;
|
accel.z = (Rand_ZeroOne() - 0.5f) * xzAccel;
|
||||||
pos.x = (Math_SinS(angle) * radius) + this->actor.world.pos.x;
|
pos.x = (Math_SinS(angle) * radius) + this->actor.world.pos.x;
|
||||||
pos.z = (Math_CosS(angle) * radius) + this->actor.world.pos.z;
|
pos.z = (Math_CosS(angle) * radius) + this->actor.world.pos.z;
|
||||||
EnGo_AddDust(this, &pos, &velocity, &accel, initialTimer, scale, scaleStep);
|
EnGo_SpawnEffectDust(this, &pos, &velocity, &accel, initialTimer, scale, scaleStep);
|
||||||
angle += (s16)(0x10000 / numDustEffects);
|
angle += (s16)(0x10000 / numDustEffects);
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
@ -549,7 +549,7 @@ s32 EnGo_IsRollingOnGround(EnGo* this, s16 unkArg1, f32 unkArg2) {
|
|||||||
} else if (this->interactInfo.talkState != NPC_TALK_STATE_IDLE) {
|
} else if (this->interactInfo.talkState != NPC_TALK_STATE_IDLE) {
|
||||||
return true;
|
return true;
|
||||||
} else if (DECR(this->unk_21C)) {
|
} else if (DECR(this->unk_21C)) {
|
||||||
if ((this->unk_21C & 1)) {
|
if (this->unk_21C & 1) {
|
||||||
this->actor.world.pos.y += 1.5f;
|
this->actor.world.pos.y += 1.5f;
|
||||||
} else {
|
} else {
|
||||||
this->actor.world.pos.y -= 1.5f;
|
this->actor.world.pos.y -= 1.5f;
|
||||||
@ -573,29 +573,29 @@ s32 EnGo_IsRollingOnGround(EnGo* this, s16 unkArg1, f32 unkArg2) {
|
|||||||
|
|
||||||
void func_80A3F908(EnGo* this, PlayState* play) {
|
void func_80A3F908(EnGo* this, PlayState* play) {
|
||||||
Player* player = GET_PLAYER(play);
|
Player* player = GET_PLAYER(play);
|
||||||
f32 float1;
|
f32 interactRange;
|
||||||
s32 isUnkCondition;
|
s32 dialogStarted;
|
||||||
|
|
||||||
if (this->actionFunc == EnGo_BiggoronActionFunc || this->actionFunc == EnGo_GoronLinkRolling ||
|
if (this->actionFunc == EnGo_BiggoronActionFunc || this->actionFunc == EnGo_GoronLinkRolling ||
|
||||||
this->actionFunc == EnGo_FireGenericActionFunc || this->actionFunc == EnGo_Eyedrops ||
|
this->actionFunc == EnGo_FireGenericActionFunc || this->actionFunc == EnGo_Eyedrops ||
|
||||||
this->actionFunc == func_80A40DCC || this->actionFunc == EnGo_GetItem || this->actionFunc == func_80A40C78 ||
|
this->actionFunc == func_80A40DCC || this->actionFunc == EnGo_GetItem || this->actionFunc == func_80A40C78 ||
|
||||||
this->actionFunc == func_80A40B1C) {
|
this->actionFunc == func_80A40B1C) {
|
||||||
|
|
||||||
float1 = (this->collider.dim.radius + 30.0f);
|
interactRange = (this->collider.dim.radius + 30.0f);
|
||||||
float1 *= (this->actor.scale.x / 0.01f);
|
interactRange *= (this->actor.scale.x / 0.01f);
|
||||||
if ((this->actor.params & 0xF0) == 0x90) {
|
if ((this->actor.params & 0xF0) == 0x90) {
|
||||||
float1 *= 4.8f;
|
interactRange *= 4.8f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((this->actor.params & 0xF0) == 0x90) {
|
if ((this->actor.params & 0xF0) == 0x90) {
|
||||||
isUnkCondition =
|
dialogStarted =
|
||||||
func_80A3ED24(play, this, &this->interactInfo, float1, EnGo_GetTextID, EnGo_UpdateTalkState);
|
EnGo_UpdateTalking(play, &this->actor, &this->interactInfo.talkState, interactRange, EnGo_GetTextID, EnGo_UpdateTalkState);
|
||||||
} else {
|
} else {
|
||||||
isUnkCondition = Npc_UpdateTalking(play, &this->actor, &this->interactInfo.talkState, float1,
|
dialogStarted = Npc_UpdateTalking(play, &this->actor, &this->interactInfo.talkState, interactRange,
|
||||||
EnGo_GetTextID, EnGo_UpdateTalkState);
|
EnGo_GetTextID, EnGo_UpdateTalkState);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((this->actor.params & 0xF0) == 0x90) && (isUnkCondition == true)) {
|
if (((this->actor.params & 0xF0) == 0x90) && (dialogStarted == true)) {
|
||||||
if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_SWORD_BROKEN) {
|
if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_SWORD_BROKEN) {
|
||||||
if (func_8002F368(play) == EXCH_ITEM_SWORD_BROKEN) {
|
if (func_8002F368(play) == EXCH_ITEM_SWORD_BROKEN) {
|
||||||
if (Flags_GetInfTable(INFTABLE_B4)) {
|
if (Flags_GetInfTable(INFTABLE_B4)) {
|
||||||
@ -628,7 +628,7 @@ void EnGo_Init(Actor* thisx, PlayState* play) {
|
|||||||
Vec3f D_80A41BA8 = { 0.0f, 0.0f, 0.0f }; // unused
|
Vec3f D_80A41BA8 = { 0.0f, 0.0f, 0.0f }; // unused
|
||||||
|
|
||||||
ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 30.0f);
|
ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 30.0f);
|
||||||
SkelAnime_InitFlex(play, &this->skelAnime, &gGoronSkel, NULL, 0, 0, 0);
|
SkelAnime_InitFlex(play, &this->skelAnime, &gGoronSkel, NULL, NULL, NULL, 0);
|
||||||
Collider_InitCylinder(play, &this->collider);
|
Collider_InitCylinder(play, &this->collider);
|
||||||
Collider_SetCylinder(play, &this->collider, &this->actor, &sCylinderInit);
|
Collider_SetCylinder(play, &this->collider, &this->actor, &sCylinderInit);
|
||||||
CollisionCheck_SetInfo2(&this->actor.colChkInfo, DamageTable_Get(0x16), &sColChkInfoInit);
|
CollisionCheck_SetInfo2(&this->actor.colChkInfo, DamageTable_Get(0x16), &sColChkInfoInit);
|
||||||
@ -711,8 +711,8 @@ void EnGo_StopRolling(EnGo* this, PlayState* play) {
|
|||||||
EnBom* bomb;
|
EnBom* bomb;
|
||||||
|
|
||||||
if (DECR(this->unk_20E) == 0) {
|
if (DECR(this->unk_20E) == 0) {
|
||||||
if (this->collider.base.ocFlags2 & 1) {
|
if (this->collider.base.ocFlags2 & OC2_HIT_PLAYER) {
|
||||||
this->collider.base.ocFlags2 &= ~1;
|
this->collider.base.ocFlags2 &= ~OC2_HIT_PLAYER;
|
||||||
play->damagePlayer(play, -4);
|
play->damagePlayer(play, -4);
|
||||||
func_8002F71C(play, &this->actor, 4.0f, this->actor.yawTowardsPlayer, 6.0f);
|
func_8002F71C(play, &this->actor, 4.0f, this->actor.yawTowardsPlayer, 6.0f);
|
||||||
this->unk_20E = 0x10;
|
this->unk_20E = 0x10;
|
||||||
@ -859,7 +859,7 @@ void func_80A405CC(EnGo* this, PlayState* play) {
|
|||||||
|
|
||||||
void EnGo_BiggoronActionFunc(EnGo* this, PlayState* play) {
|
void EnGo_BiggoronActionFunc(EnGo* this, PlayState* play) {
|
||||||
if (((this->actor.params & 0xF0) == 0x90) && (this->interactInfo.talkState == NPC_TALK_STATE_ACTION)) {
|
if (((this->actor.params & 0xF0) == 0x90) && (this->interactInfo.talkState == NPC_TALK_STATE_ACTION)) {
|
||||||
if (!IS_RANDO && gSaveContext.bgsFlag) {
|
if (gSaveContext.bgsFlag) {
|
||||||
this->interactInfo.talkState = NPC_TALK_STATE_IDLE;
|
this->interactInfo.talkState = NPC_TALK_STATE_IDLE;
|
||||||
} else {
|
} else {
|
||||||
if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_EYEDROPS) {
|
if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_EYEDROPS) {
|
||||||
@ -958,45 +958,25 @@ void EnGo_GetItem(EnGo* this, PlayState* play) {
|
|||||||
this->unk_20C = 0;
|
this->unk_20C = 0;
|
||||||
if ((this->actor.params & 0xF0) == 0x90) {
|
if ((this->actor.params & 0xF0) == 0x90) {
|
||||||
if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_CLAIM_CHECK) {
|
if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_CLAIM_CHECK) {
|
||||||
if (!IS_RANDO) {
|
getItemId = GI_SWORD_BGS;
|
||||||
getItemId = GI_SWORD_BGS;
|
|
||||||
} else {
|
|
||||||
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_DMT_TRADE_CLAIM_CHECK, GI_SWORD_BGS);
|
|
||||||
getItemId = getItemEntry.getItemId;
|
|
||||||
}
|
|
||||||
this->unk_20C = 1;
|
this->unk_20C = 1;
|
||||||
}
|
}
|
||||||
if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_EYEDROPS) {
|
if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_EYEDROPS) {
|
||||||
if (IS_RANDO) {
|
getItemId = GI_CLAIM_CHECK;
|
||||||
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_DMT_TRADE_EYEDROPS, GI_CLAIM_CHECK);
|
|
||||||
getItemId = getItemEntry.getItemId;
|
|
||||||
Randomizer_ConsumeAdultTradeItem(play, ITEM_EYEDROPS);
|
|
||||||
} else {
|
|
||||||
getItemId = GI_CLAIM_CHECK;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_SWORD_BROKEN) {
|
if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_SWORD_BROKEN) {
|
||||||
if (IS_RANDO) {
|
getItemId = GI_PRESCRIPTION;
|
||||||
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_DMT_TRADE_BROKEN_SWORD, GI_PRESCRIPTION);
|
|
||||||
Randomizer_ConsumeAdultTradeItem(play, ITEM_SWORD_BROKEN);
|
|
||||||
getItemId = getItemEntry.getItemId;
|
|
||||||
} else {
|
|
||||||
getItemId = GI_PRESCRIPTION;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((this->actor.params & 0xF0) == 0) {
|
if ((this->actor.params & 0xF0) == 0) {
|
||||||
getItemId = GI_TUNIC_GORON;
|
getItemId = GI_TUNIC_GORON;
|
||||||
|
Flags_SetRandomizerInf(RAND_INF_ROLLING_GORON_AS_ADULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
yDist = fabsf(this->actor.yDistToPlayer) + 1.0f;
|
yDist = fabsf(this->actor.yDistToPlayer) + 1.0f;
|
||||||
xzDist = this->actor.xzDistToPlayer + 1.0f;
|
xzDist = this->actor.xzDistToPlayer + 1.0f;
|
||||||
if (!IS_RANDO || getItemEntry.getItemId == GI_NONE) {
|
func_8002F434(&this->actor, play, getItemId, xzDist, yDist);
|
||||||
func_8002F434(&this->actor, play, getItemId, xzDist, yDist);
|
|
||||||
} else {
|
|
||||||
GiveItemEntryFromActor(&this->actor, play, getItemEntry, xzDist, yDist);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1105,32 +1085,30 @@ void EnGo_DrawRolling(EnGo* this, PlayState* play) {
|
|||||||
|
|
||||||
s32 EnGo_OverrideLimbDraw(PlayState* play, s32 limb, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx) {
|
s32 EnGo_OverrideLimbDraw(PlayState* play, s32 limb, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx) {
|
||||||
EnGo* this = (EnGo*)thisx;
|
EnGo* this = (EnGo*)thisx;
|
||||||
Vec3s vec1;
|
Vec3s limbRot;
|
||||||
f32 float1;
|
f32 float1;
|
||||||
|
|
||||||
if (limb == 17) {
|
if (limb == 17) {
|
||||||
Matrix_Translate(2800.0f, 0.0f, 0.0f, MTXMODE_APPLY);
|
Matrix_Translate(2800.0f, 0.0f, 0.0f, MTXMODE_APPLY);
|
||||||
vec1 = this->interactInfo.headRot;
|
limbRot = this->interactInfo.headRot;
|
||||||
float1 = (vec1.y / (f32)0x8000) * M_PI;
|
float1 = (limbRot.y / (f32)0x8000) * M_PI;
|
||||||
Matrix_RotateX(float1, MTXMODE_APPLY);
|
Matrix_RotateX(float1, MTXMODE_APPLY);
|
||||||
float1 = (vec1.x / (f32)0x8000) * M_PI;
|
float1 = (limbRot.x / (f32)0x8000) * M_PI;
|
||||||
Matrix_RotateZ(float1, MTXMODE_APPLY);
|
Matrix_RotateZ(float1, MTXMODE_APPLY);
|
||||||
Matrix_Translate(-2800.0f, 0.0f, 0.0f, MTXMODE_APPLY);
|
Matrix_Translate(-2800.0f, 0.0f, 0.0f, MTXMODE_APPLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (limb == 10) {
|
if (limb == 10) {
|
||||||
vec1 = this->interactInfo.torsoRot;
|
limbRot = this->interactInfo.torsoRot;
|
||||||
float1 = (vec1.y / (f32)0x8000) * M_PI;
|
float1 = (limbRot.y / (f32)0x8000) * M_PI;
|
||||||
Matrix_RotateY(float1, MTXMODE_APPLY);
|
Matrix_RotateY(float1, MTXMODE_APPLY);
|
||||||
float1 = (vec1.x / (f32)0x8000) * M_PI;
|
float1 = (limbRot.x / (f32)0x8000) * M_PI;
|
||||||
Matrix_RotateX(float1, MTXMODE_APPLY);
|
Matrix_RotateX(float1, MTXMODE_APPLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((limb == 10) || (limb == 11) || (limb == 14)) {
|
if ((limb == 10) || (limb == 11) || (limb == 14)) {
|
||||||
float1 = Math_SinS(this->jointTable[limb]);
|
rot->y += Math_SinS(this->jointTable[limb]) * 200.0f;
|
||||||
rot->y += float1 * 200.0f;
|
rot->z += Math_CosS(this->morphTable[limb]) * 200.0f;
|
||||||
float1 = Math_CosS(this->morphTable[limb]);
|
|
||||||
rot->z += float1 * 200.0f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -1150,9 +1128,9 @@ void EnGo_Draw(Actor* thisx, PlayState* play) {
|
|||||||
|
|
||||||
OPEN_DISPS(play->state.gfxCtx);
|
OPEN_DISPS(play->state.gfxCtx);
|
||||||
|
|
||||||
EnGo_UpdateDust(this);
|
EnGo_UpdateEffects(this);
|
||||||
Matrix_Push();
|
Matrix_Push();
|
||||||
EnGo_DrawDust(this, play);
|
EnGo_DrawEffects(this, play);
|
||||||
Matrix_Pop();
|
Matrix_Pop();
|
||||||
|
|
||||||
if (this->actionFunc == EnGo_CurledUp) {
|
if (this->actionFunc == EnGo_CurledUp) {
|
||||||
@ -1167,39 +1145,36 @@ void EnGo_Draw(Actor* thisx, PlayState* play) {
|
|||||||
gSPSegment(POLY_OPA_DISP++, 0x09, SEGMENTED_TO_VIRTUAL(gGoronCsMouthNeutralTex));
|
gSPSegment(POLY_OPA_DISP++, 0x09, SEGMENTED_TO_VIRTUAL(gGoronCsMouthNeutralTex));
|
||||||
|
|
||||||
SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, EnGo_OverrideLimbDraw, EnGo_PostLimbDraw, &this->actor);
|
SkelAnime_DrawSkeletonOpa(play, &this->skelAnime, EnGo_OverrideLimbDraw, EnGo_PostLimbDraw, &this->actor);
|
||||||
EnGo_DrawDust(this, play);
|
EnGo_DrawEffects(this, play);
|
||||||
}
|
}
|
||||||
CLOSE_DISPS(play->state.gfxCtx);
|
CLOSE_DISPS(play->state.gfxCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnGo_AddDust(EnGo* this, Vec3f* pos, Vec3f* velocity, Vec3f* accel, u8 initialTimer, f32 scale, f32 scaleStep) {
|
void EnGo_SpawnEffectDust(EnGo* this, Vec3f* pos, Vec3f* velocity, Vec3f* accel, u8 initialTimer, f32 scale, f32 scaleStep) {
|
||||||
EnGoEffect* dustEffect = this->dustEffects;
|
EnGoEffect* dustEffect = this->effects;
|
||||||
s16 i;
|
s16 i;
|
||||||
s16 timer;
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_COUNT(this->dustEffects); i++, dustEffect++) {
|
for (i = 0; i < EN_GO_EFFECT_COUNT; i++, dustEffect++) {
|
||||||
if (dustEffect->type != 1) {
|
if (dustEffect->type != 1) {
|
||||||
dustEffect->epoch++;
|
dustEffect->epoch++;
|
||||||
dustEffect->scale = scale;
|
dustEffect->scale = scale;
|
||||||
dustEffect->scaleStep = scaleStep;
|
dustEffect->scaleStep = scaleStep;
|
||||||
timer = initialTimer;
|
dustEffect->initialTimer = dustEffect->timer = initialTimer;
|
||||||
dustEffect->timer = timer;
|
|
||||||
dustEffect->type = 1;
|
dustEffect->type = 1;
|
||||||
dustEffect->initialTimer = initialTimer;
|
|
||||||
dustEffect->pos = *pos;
|
dustEffect->pos = *pos;
|
||||||
dustEffect->accel = *accel;
|
dustEffect->accel = *accel;
|
||||||
dustEffect->velocity = *velocity;
|
dustEffect->velocity = *velocity;
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnGo_UpdateDust(EnGo* this) {
|
void EnGo_UpdateEffects(EnGo* this) {
|
||||||
EnGoEffect* dustEffect = this->dustEffects;
|
EnGoEffect* dustEffect = this->effects;
|
||||||
f32 randomNumber;
|
f32 randomNumber;
|
||||||
s16 i;
|
s16 i;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_COUNT(this->dustEffects); i++, dustEffect++) {
|
for (i = 0; i < EN_GO_EFFECT_COUNT; i++, dustEffect++) {
|
||||||
if (dustEffect->type) {
|
if (dustEffect->type) {
|
||||||
dustEffect->timer--;
|
dustEffect->timer--;
|
||||||
if (dustEffect->timer == 0) {
|
if (dustEffect->timer == 0) {
|
||||||
@ -1220,24 +1195,24 @@ void EnGo_UpdateDust(EnGo* this) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnGo_DrawDust(EnGo* this, PlayState* play) {
|
void EnGo_DrawEffects(EnGo* this, PlayState* play) {
|
||||||
static void* dustTex[] = { gDust8Tex, gDust7Tex, gDust6Tex, gDust5Tex, gDust4Tex, gDust3Tex, gDust2Tex, gDust1Tex };
|
static void* dustTex[] = { gDust8Tex, gDust7Tex, gDust6Tex, gDust5Tex, gDust4Tex, gDust3Tex, gDust2Tex, gDust1Tex };
|
||||||
EnGoEffect* dustEffect = this->dustEffects;
|
EnGoEffect* dustEffect = this->effects;
|
||||||
s16 alpha;
|
s16 alpha;
|
||||||
s16 firstDone;
|
s16 materialFlag;
|
||||||
s16 index;
|
s16 index;
|
||||||
s16 i;
|
s16 i;
|
||||||
|
|
||||||
OPEN_DISPS(play->state.gfxCtx);
|
OPEN_DISPS(play->state.gfxCtx);
|
||||||
firstDone = false;
|
materialFlag = false;
|
||||||
Gfx_SetupDL_25Xlu(play->state.gfxCtx);
|
Gfx_SetupDL_25Xlu(play->state.gfxCtx);
|
||||||
for (i = 0; i < ARRAY_COUNT(this->dustEffects); i++, dustEffect++) {
|
for (i = 0; i < EN_GO_EFFECT_COUNT; i++, dustEffect++) {
|
||||||
if (dustEffect->type) {
|
if (dustEffect->type) {
|
||||||
if (!firstDone) {
|
if (!materialFlag) {
|
||||||
POLY_XLU_DISP = Gfx_SetupDL(POLY_XLU_DISP, 0);
|
POLY_XLU_DISP = Gfx_SetupDL(POLY_XLU_DISP, 0);
|
||||||
gSPDisplayList(POLY_XLU_DISP++, gGoronDL_00FD40);
|
gSPDisplayList(POLY_XLU_DISP++, gGoronDL_00FD40);
|
||||||
gDPSetEnvColor(POLY_XLU_DISP++, 100, 60, 20, 0);
|
gDPSetEnvColor(POLY_XLU_DISP++, 100, 60, 20, 0);
|
||||||
firstDone = true;
|
materialFlag = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
FrameInterpolation_RecordOpenChild(dustEffect, dustEffect->epoch);
|
FrameInterpolation_RecordOpenChild(dustEffect, dustEffect->epoch);
|
||||||
|
@ -16,12 +16,13 @@ typedef s16 (*callback2_80A3ED24)(PlayState*, struct EnGo*);
|
|||||||
// /* 0x20 */ GORON1_DMT_DC_ENTRANCE,
|
// /* 0x20 */ GORON1_DMT_DC_ENTRANCE,
|
||||||
// /* 0x30 */ GORON1_DMT_ROLLING_SMALL,
|
// /* 0x30 */ GORON1_DMT_ROLLING_SMALL,
|
||||||
// /* 0x40 */ GORON1_DMT_BOMB_FLOWER,
|
// /* 0x40 */ GORON1_DMT_BOMB_FLOWER,
|
||||||
// /* 0x50 */ GORON1_CITY_ENTRANCE,
|
// /* 0x50 */ GORON1_CITY_ENTRANCE,
|
||||||
// /* 0x60 */ GORON1_CITY_ISLAND,
|
// /* 0x60 */ GORON1_CITY_ISLAND,
|
||||||
// /* 0x70 */ GORON1_CITY_LOST_WOODS,
|
// /* 0x70 */ GORON1_CITY_LOST_WOODS,
|
||||||
// /* 0x80 */ // Not Used
|
// /* 0x80 */ // Not Used
|
||||||
// /* 0x90 */ GORON1_DMT_BIGGORON,
|
// /* 0x90 */ GORON1_DMT_BIGGORON,
|
||||||
|
|
||||||
|
#define EN_GO_EFFECT_COUNT 20
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* 0x0000 */ u8 type;
|
/* 0x0000 */ u8 type;
|
||||||
@ -56,7 +57,7 @@ typedef struct EnGo {
|
|||||||
/* 0x021E */ s16 unk_21E;
|
/* 0x021E */ s16 unk_21E;
|
||||||
/* 0x0220 */ s16 jointTable[18];
|
/* 0x0220 */ s16 jointTable[18];
|
||||||
/* 0x0244 */ s16 morphTable[18];
|
/* 0x0244 */ s16 morphTable[18];
|
||||||
/* 0x0268 */ EnGoEffect dustEffects[20];
|
/* 0x0268 */ EnGoEffect effects[EN_GO_EFFECT_COUNT];
|
||||||
} EnGo; // size = 0x06C8
|
} EnGo; // size = 0x06C8
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#include "objects/gameplay_keep/gameplay_keep.h"
|
#include "objects/gameplay_keep/gameplay_keep.h"
|
||||||
#include "objects/object_oF1d_map/object_oF1d_map.h"
|
#include "objects/object_oF1d_map/object_oF1d_map.h"
|
||||||
#include "soh/frame_interpolation.h"
|
#include "soh/frame_interpolation.h"
|
||||||
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED)
|
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED)
|
||||||
|
|
||||||
@ -335,7 +335,8 @@ u16 EnGo2_GoronFireGenericGetTextId(EnGo2* this) {
|
|||||||
u16 EnGo2_GetTextIdGoronCityRollingBig(PlayState* play, EnGo2* this) {
|
u16 EnGo2_GetTextIdGoronCityRollingBig(PlayState* play, EnGo2* this) {
|
||||||
if (Flags_GetInfTable(INFTABLE_11E)) {
|
if (Flags_GetInfTable(INFTABLE_11E)) {
|
||||||
return 0x3013;
|
return 0x3013;
|
||||||
} else if ((CUR_CAPACITY(UPG_BOMB_BAG) >= 20 || IS_RANDO) && this->waypoint > 7 && this->waypoint < 12) {
|
} else if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_CHILD_ROLLING_GORON_REWARD, CUR_CAPACITY(UPG_BOMB_BAG) >= 2, this)
|
||||||
|
&& this->waypoint > 7 && this->waypoint < 12) {
|
||||||
return 0x3012;
|
return 0x3012;
|
||||||
} else {
|
} else {
|
||||||
return 0x3011;
|
return 0x3011;
|
||||||
@ -350,13 +351,14 @@ s16 EnGo2_UpdateTalkStateGoronCityRollingBig(PlayState* play, EnGo2* this) {
|
|||||||
if (Message_ShouldAdvance(play)) {
|
if (Message_ShouldAdvance(play)) {
|
||||||
if (this->actor.textId == 0x3012) {
|
if (this->actor.textId == 0x3012) {
|
||||||
this->actionFunc = EnGo2_SetupGetItem;
|
this->actionFunc = EnGo2_SetupGetItem;
|
||||||
if(!IS_RANDO) {
|
if(GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_ROLLING_GORON_AS_CHILD, true, this)) {
|
||||||
EnGo2_GetItem(this, play, CUR_CAPACITY(UPG_BOMB_BAG) == 30 ? GI_BOMB_BAG_40 : GI_BOMB_BAG_30);
|
EnGo2_GetItem(this, play, CUR_CAPACITY(UPG_BOMB_BAG) == 30 ? GI_BOMB_BAG_40 : GI_BOMB_BAG_30);
|
||||||
} else {
|
} else {
|
||||||
EnGo2_GetItemEntry(this, play, Randomizer_GetItemFromKnownCheck(RC_GC_ROLLING_GORON_AS_CHILD, GI_BOMB_BAG_40));
|
this->actionFunc = EnGo2_SetGetItem;
|
||||||
}
|
}
|
||||||
Message_CloseTextbox(play);
|
Message_CloseTextbox(play);
|
||||||
Flags_SetInfTable(INFTABLE_11E);
|
Flags_SetInfTable(INFTABLE_11E);
|
||||||
|
Flags_SetRandomizerInf(RAND_INF_ROLLING_GORON_AS_CHILD);
|
||||||
return NPC_TALK_STATE_ACTION;
|
return NPC_TALK_STATE_ACTION;
|
||||||
} else {
|
} else {
|
||||||
return NPC_TALK_STATE_ACTION;
|
return NPC_TALK_STATE_ACTION;
|
||||||
@ -416,11 +418,9 @@ s16 EnGo2_UpdateTalkStateGoronDmtRollingSmall(PlayState* play, EnGo2* this) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
u16 EnGo2_GetTextIdGoronDmtDcEntrance(PlayState* play, EnGo2* this) {
|
u16 EnGo2_GetTextIdGoronDmtDcEntrance(PlayState* play, EnGo2* this) {
|
||||||
if (((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) ||
|
if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && LINK_IS_ADULT) {
|
||||||
(IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) && LINK_IS_ADULT) {
|
|
||||||
return 0x3043;
|
return 0x3043;
|
||||||
} else if ((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) ||
|
} else if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_DODONGOS_CAVERN_FINISHED, CHECK_QUEST_ITEM(QUEST_GORON_RUBY), NULL)) {
|
||||||
(IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN))) {
|
|
||||||
return 0x3027;
|
return 0x3027;
|
||||||
} else {
|
} else {
|
||||||
return Flags_GetEventChkInf(EVENTCHKINF_BOMBED_DODONGOS_CAVERN_ENTRANCE) ? 0x3021 : Flags_GetInfTable(INFTABLE_E0) ? 0x302A : 0x3008;
|
return Flags_GetEventChkInf(EVENTCHKINF_BOMBED_DODONGOS_CAVERN_ENTRANCE) ? 0x3021 : Flags_GetInfTable(INFTABLE_E0) ? 0x302A : 0x3008;
|
||||||
@ -439,11 +439,9 @@ s16 EnGo2_UpdateTalkStateGoronDmtDcEntrance(PlayState* play, EnGo2* this) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
u16 EnGo2_GetTextIdGoronCityEntrance(PlayState* play, EnGo2* this) {
|
u16 EnGo2_GetTextIdGoronCityEntrance(PlayState* play, EnGo2* this) {
|
||||||
if (((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) ||
|
if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && LINK_IS_ADULT) {
|
||||||
(IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) && LINK_IS_ADULT) {
|
|
||||||
return 0x3043;
|
return 0x3043;
|
||||||
} else if ((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) ||
|
} else if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_DODONGOS_CAVERN_FINISHED, CHECK_QUEST_ITEM(QUEST_GORON_RUBY), NULL)) {
|
||||||
(IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN))) {
|
|
||||||
return 0x3027;
|
return 0x3027;
|
||||||
} else {
|
} else {
|
||||||
return Flags_GetInfTable(INFTABLE_F0) ? 0x3015 : 0x3014;
|
return Flags_GetInfTable(INFTABLE_F0) ? 0x3015 : 0x3014;
|
||||||
@ -462,11 +460,9 @@ s16 EnGo2_UpdateTalkStateGoronCityEntrance(PlayState* play, EnGo2* this) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
u16 EnGo2_GetTextIdGoronCityIsland(PlayState* play, EnGo2* this) {
|
u16 EnGo2_GetTextIdGoronCityIsland(PlayState* play, EnGo2* this) {
|
||||||
if (((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) ||
|
if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && LINK_IS_ADULT) {
|
||||||
(IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) && LINK_IS_ADULT) {
|
|
||||||
return 0x3043;
|
return 0x3043;
|
||||||
} else if ((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) ||
|
} else if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_DODONGOS_CAVERN_FINISHED, CHECK_QUEST_ITEM(QUEST_GORON_RUBY), NULL)) {
|
||||||
(IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN))) {
|
|
||||||
return 0x3027;
|
return 0x3027;
|
||||||
} else {
|
} else {
|
||||||
return Flags_GetInfTable(INFTABLE_F4) ? 0x3017 : 0x3016;
|
return Flags_GetInfTable(INFTABLE_F4) ? 0x3017 : 0x3016;
|
||||||
@ -485,11 +481,9 @@ s16 EnGo2_UpdateTalkStateGoronCityIsland(PlayState* play, EnGo2* this) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
u16 EnGo2_GetTextIdGoronCityLowestFloor(PlayState* play, EnGo2* this) {
|
u16 EnGo2_GetTextIdGoronCityLowestFloor(PlayState* play, EnGo2* this) {
|
||||||
if (((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) ||
|
if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && LINK_IS_ADULT) {
|
||||||
(IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) && LINK_IS_ADULT) {
|
|
||||||
return 0x3043;
|
return 0x3043;
|
||||||
} else if ((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) ||
|
} else if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_DODONGOS_CAVERN_FINISHED, CHECK_QUEST_ITEM(QUEST_GORON_RUBY), NULL)) {
|
||||||
(IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DODONGOS_CAVERN))) {
|
|
||||||
return 0x3027;
|
return 0x3027;
|
||||||
} else {
|
} else {
|
||||||
return CUR_UPG_VALUE(UPG_STRENGTH) != 0 ? 0x302C
|
return CUR_UPG_VALUE(UPG_STRENGTH) != 0 ? 0x302C
|
||||||
@ -511,18 +505,10 @@ s16 EnGo2_UpdateTalkStateGoronCityLowestFloor(PlayState* play, EnGo2* this) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
u16 EnGo2_GetTextIdGoronCityLink(PlayState* play, EnGo2* this) {
|
u16 EnGo2_GetTextIdGoronCityLink(PlayState* play, EnGo2* this) {
|
||||||
// For rando, prioritize opening the doors in GC when Link the goron has been stopped when
|
// In case a hook neglects to set the override, fall back to the first dialogue
|
||||||
// the doors are not opened, otherwise let him talk about the DMC exit or that gorons are saved
|
u16 overrideTextId = 0x3030;
|
||||||
if (IS_RANDO) {
|
if (GameInteractor_Should(GI_VB_OVERRIDE_LINK_THE_GORON_DIALOGUE, false, &overrideTextId)) {
|
||||||
if (!Flags_GetInfTable(INFTABLE_STOPPED_GORON_LINKS_ROLLING)) {
|
return overrideTextId;
|
||||||
return 0x3030;
|
|
||||||
} else if (!Flags_GetInfTable(INFTABLE_GORON_CITY_DOORS_UNLOCKED)) {
|
|
||||||
return 0x3036;
|
|
||||||
} else if (Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE)) {
|
|
||||||
return 0x3041;
|
|
||||||
} else {
|
|
||||||
return Flags_GetInfTable(INFTABLE_SPOKE_TO_GORON_LINK) ? 0x3038 : 0x3037;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) {
|
if (CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) {
|
||||||
@ -543,20 +529,15 @@ s16 EnGo2_UpdateTalkStateGoronCityLink(PlayState* play, EnGo2* this) {
|
|||||||
case TEXT_STATE_CLOSING:
|
case TEXT_STATE_CLOSING:
|
||||||
switch (this->actor.textId) {
|
switch (this->actor.textId) {
|
||||||
case 0x3036:
|
case 0x3036:
|
||||||
if (!IS_RANDO) {
|
Flags_SetRandomizerInf(RAND_INF_ROLLING_GORON_AS_ADULT);
|
||||||
|
this->interactInfo.talkState = NPC_TALK_STATE_IDLE;
|
||||||
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_ROLLING_GORON_AS_ADULT, true, this)) {
|
||||||
EnGo2_GetItem(this, play, GI_TUNIC_GORON);
|
EnGo2_GetItem(this, play, GI_TUNIC_GORON);
|
||||||
this->actionFunc = EnGo2_SetupGetItem;
|
this->actionFunc = EnGo2_SetupGetItem;
|
||||||
return NPC_TALK_STATE_ACTION;
|
return NPC_TALK_STATE_ACTION;
|
||||||
} else {
|
} else {
|
||||||
if (Flags_GetTreasure(play, 0x1F)) {
|
this->actionFunc = EnGo2_SetGetItem;
|
||||||
return NPC_TALK_STATE_IDLE;
|
return this->interactInfo.talkState;
|
||||||
}
|
|
||||||
|
|
||||||
Flags_SetInfTable(INFTABLE_GORON_CITY_DOORS_UNLOCKED);
|
|
||||||
EnGo2_GetItemEntry(this, play, Randomizer_GetItemFromKnownCheck(RC_GC_ROLLING_GORON_AS_ADULT, GI_TUNIC_GORON));
|
|
||||||
this->actionFunc = EnGo2_SetupGetItem;
|
|
||||||
Flags_SetTreasure(play, 0x1F);
|
|
||||||
return NPC_TALK_STATE_ACTION;
|
|
||||||
}
|
}
|
||||||
case 0x3037:
|
case 0x3037:
|
||||||
Flags_SetInfTable(INFTABLE_SPOKE_TO_GORON_LINK);
|
Flags_SetInfTable(INFTABLE_SPOKE_TO_GORON_LINK);
|
||||||
@ -605,7 +586,7 @@ s16 EnGo2_UpdateTalkStateGoronCityLink(PlayState* play, EnGo2* this) {
|
|||||||
u16 EnGo2_GetTextIdGoronDmtBiggoron(PlayState* play, EnGo2* this) {
|
u16 EnGo2_GetTextIdGoronDmtBiggoron(PlayState* play, EnGo2* this) {
|
||||||
Player* player = GET_PLAYER(play);
|
Player* player = GET_PLAYER(play);
|
||||||
|
|
||||||
if (!IS_RANDO && gSaveContext.bgsFlag) {
|
if (GameInteractor_Should(GI_VB_BIGGORON_CONSIDER_TRADE_COMPLETE, gSaveContext.bgsFlag, NULL)) {
|
||||||
player->exchangeItemId = EXCH_ITEM_CLAIM_CHECK;
|
player->exchangeItemId = EXCH_ITEM_CLAIM_CHECK;
|
||||||
return 0x305E;
|
return 0x305E;
|
||||||
} else if (INV_CONTENT(ITEM_TRADE_ADULT) >= ITEM_CLAIM_CHECK) {
|
} else if (INV_CONTENT(ITEM_TRADE_ADULT) >= ITEM_CLAIM_CHECK) {
|
||||||
@ -627,17 +608,17 @@ s16 EnGo2_UpdateTalkStateGoronDmtBiggoron(PlayState* play, EnGo2* this) {
|
|||||||
switch (EnGo2_GetDialogState(this, play)) {
|
switch (EnGo2_GetDialogState(this, play)) {
|
||||||
case TEXT_STATE_DONE:
|
case TEXT_STATE_DONE:
|
||||||
if (this->actor.textId == 0x305E) {
|
if (this->actor.textId == 0x305E) {
|
||||||
if((!IS_RANDO && gSaveContext.bgsFlag) || (IS_RANDO && Flags_GetTreasure(play, 0x1F))) {
|
if (GameInteractor_Should(GI_VB_BIGGORON_CONSIDER_SWORD_COLLECTED, gSaveContext.bgsFlag, NULL)) {
|
||||||
return NPC_TALK_STATE_IDLE;
|
return NPC_TALK_STATE_IDLE;
|
||||||
}
|
}
|
||||||
|
Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_CLAIM_CHECK);
|
||||||
if(IS_RANDO) {
|
if (GameInteractor_Should(GI_VB_TRADE_CLAIM_CHECK, true, this)) {
|
||||||
EnGo2_GetItemEntry(this, play, Randomizer_GetItemFromKnownCheck(RC_DMT_TRADE_CLAIM_CHECK, GI_SWORD_BGS));
|
|
||||||
Flags_SetTreasure(play, 0x1F);
|
|
||||||
} else {
|
|
||||||
EnGo2_GetItem(this, play, GI_SWORD_BGS);
|
EnGo2_GetItem(this, play, GI_SWORD_BGS);
|
||||||
|
this->actionFunc = EnGo2_SetupGetItem;
|
||||||
|
} else {
|
||||||
|
this->actionFunc = EnGo2_SetGetItem;
|
||||||
}
|
}
|
||||||
this->actionFunc = EnGo2_SetupGetItem;
|
|
||||||
return NPC_TALK_STATE_ACTION;
|
return NPC_TALK_STATE_ACTION;
|
||||||
} else {
|
} else {
|
||||||
return NPC_TALK_STATE_IDLE;
|
return NPC_TALK_STATE_IDLE;
|
||||||
@ -663,16 +644,13 @@ s16 EnGo2_UpdateTalkStateGoronDmtBiggoron(PlayState* play, EnGo2* this) {
|
|||||||
if (Message_ShouldAdvance(play)) {
|
if (Message_ShouldAdvance(play)) {
|
||||||
if ((this->actor.textId == 0x3054) || (this->actor.textId == 0x3055)) {
|
if ((this->actor.textId == 0x3054) || (this->actor.textId == 0x3055)) {
|
||||||
if (play->msgCtx.choiceIndex == 0) {
|
if (play->msgCtx.choiceIndex == 0) {
|
||||||
if (IS_RANDO) {
|
Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_BROKEN_SWORD);
|
||||||
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_DMT_TRADE_BROKEN_SWORD, GI_PRESCRIPTION);
|
if (GameInteractor_Should(GI_VB_TRADE_BROKEN_SWORD, true, this)) {
|
||||||
Randomizer_ConsumeAdultTradeItem(play, ITEM_SWORD_BROKEN);
|
EnGo2_GetItem(this, play, GI_PRESCRIPTION);
|
||||||
EnGo2_GetItemEntry(this, play, getItemEntry);
|
this->actionFunc = EnGo2_SetupGetItem;
|
||||||
Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_BROKEN_SWORD);
|
|
||||||
} else {
|
} else {
|
||||||
u32 getItemId = GI_PRESCRIPTION;
|
this->actionFunc = EnGo2_SetGetItem;
|
||||||
EnGo2_GetItem(this, play, getItemId);
|
|
||||||
}
|
}
|
||||||
this->actionFunc = EnGo2_SetupGetItem;
|
|
||||||
return NPC_TALK_STATE_ACTION;
|
return NPC_TALK_STATE_ACTION;
|
||||||
}
|
}
|
||||||
this->actor.textId = 0x3056;
|
this->actor.textId = 0x3056;
|
||||||
@ -1070,7 +1048,7 @@ void EnGo2_BiggoronSetTextId(EnGo2* this, PlayState* play, Player* player) {
|
|||||||
u16 textId;
|
u16 textId;
|
||||||
|
|
||||||
if ((this->actor.params & 0x1F) == GORON_DMT_BIGGORON) {
|
if ((this->actor.params & 0x1F) == GORON_DMT_BIGGORON) {
|
||||||
if ((!IS_RANDO && gSaveContext.bgsFlag)) {
|
if (GameInteractor_Should(GI_VB_BIGGORON_CONSIDER_TRADE_COMPLETE, gSaveContext.bgsFlag, NULL)) {
|
||||||
if (func_8002F368(play) == EXCH_ITEM_CLAIM_CHECK) {
|
if (func_8002F368(play) == EXCH_ITEM_CLAIM_CHECK) {
|
||||||
this->actor.textId = 0x3003;
|
this->actor.textId = 0x3003;
|
||||||
} else {
|
} else {
|
||||||
@ -1080,18 +1058,14 @@ void EnGo2_BiggoronSetTextId(EnGo2* this, PlayState* play, Player* player) {
|
|||||||
|
|
||||||
} else if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_CLAIM_CHECK) {
|
} else if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_CLAIM_CHECK) {
|
||||||
if (func_8002F368(play) == EXCH_ITEM_CLAIM_CHECK) {
|
if (func_8002F368(play) == EXCH_ITEM_CLAIM_CHECK) {
|
||||||
if (IS_RANDO && Flags_GetTreasure(play, 0x1F)) {
|
if (GameInteractor_Should(GI_VB_BIGGORON_CONSIDER_SWORD_FORGED, Environment_GetBgsDayCount() >= 3, NULL)) {
|
||||||
textId = 0x3003;
|
|
||||||
} else if (Environment_GetBgsDayCount() >= CVarGetInteger("gForgeTime", 3)) {
|
|
||||||
textId = 0x305E;
|
textId = 0x305E;
|
||||||
} else {
|
} else {
|
||||||
textId = 0x305D;
|
textId = 0x305D;
|
||||||
}
|
}
|
||||||
this->actor.textId = textId;
|
this->actor.textId = textId;
|
||||||
} else {
|
} else {
|
||||||
if (IS_RANDO && Flags_GetTreasure(play, 0x1F)) {
|
if (GameInteractor_Should(GI_VB_BIGGORON_CONSIDER_SWORD_FORGED, Environment_GetBgsDayCount() >= 3, NULL)) {
|
||||||
textId = 0x305E;
|
|
||||||
} else if (Environment_GetBgsDayCount() >= CVarGetInteger("gForgeTime", 3)) {
|
|
||||||
textId = 0x3002;
|
textId = 0x3002;
|
||||||
} else {
|
} else {
|
||||||
textId = 0x305D;
|
textId = 0x305D;
|
||||||
@ -1219,8 +1193,7 @@ s32 EnGo2_IsCameraModified(EnGo2* this, PlayState* play) {
|
|||||||
(this->actor.params & 0x1F) == GORON_CITY_STAIRWELL || (this->actor.params & 0x1F) == GORON_DMT_BIGGORON ||
|
(this->actor.params & 0x1F) == GORON_CITY_STAIRWELL || (this->actor.params & 0x1F) == GORON_DMT_BIGGORON ||
|
||||||
(this->actor.params & 0x1F) == GORON_MARKET_BAZAAR) {
|
(this->actor.params & 0x1F) == GORON_MARKET_BAZAAR) {
|
||||||
return true;
|
return true;
|
||||||
} else if (((!IS_RANDO && !CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) ||
|
} else if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) &&
|
||||||
(IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) &&
|
|
||||||
CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON)) {
|
CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON)) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@ -1278,8 +1251,7 @@ void EnGo2_SelectGoronWakingUp(EnGo2* this) {
|
|||||||
EnGo2_BiggoronWakingUp(this);
|
EnGo2_BiggoronWakingUp(this);
|
||||||
break;
|
break;
|
||||||
case GORON_CITY_LINK:
|
case GORON_CITY_LINK:
|
||||||
if (((!IS_RANDO && !CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) ||
|
if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) &&
|
||||||
(IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) &&
|
|
||||||
CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON)) {
|
CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON)) {
|
||||||
EnGo2_WakingUp(this);
|
EnGo2_WakingUp(this);
|
||||||
break;
|
break;
|
||||||
@ -1624,8 +1596,7 @@ void EnGo2_Init(Actor* thisx, PlayState* play) {
|
|||||||
case GORON_CITY_LOWEST_FLOOR:
|
case GORON_CITY_LOWEST_FLOOR:
|
||||||
case GORON_CITY_STAIRWELL:
|
case GORON_CITY_STAIRWELL:
|
||||||
case GORON_CITY_LOST_WOODS:
|
case GORON_CITY_LOST_WOODS:
|
||||||
if (((!IS_RANDO && !CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) ||
|
if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) && LINK_IS_ADULT) {
|
||||||
(IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) && LINK_IS_ADULT) {
|
|
||||||
Actor_Kill(&this->actor);
|
Actor_Kill(&this->actor);
|
||||||
}
|
}
|
||||||
this->actionFunc = EnGo2_CurledUp;
|
this->actionFunc = EnGo2_CurledUp;
|
||||||
@ -1640,8 +1611,7 @@ void EnGo2_Init(Actor* thisx, PlayState* play) {
|
|||||||
if ((Flags_GetInfTable(INFTABLE_GORON_CITY_DOORS_UNLOCKED))) {
|
if ((Flags_GetInfTable(INFTABLE_GORON_CITY_DOORS_UNLOCKED))) {
|
||||||
Path_CopyLastPoint(this->path, &this->actor.world.pos);
|
Path_CopyLastPoint(this->path, &this->actor.world.pos);
|
||||||
this->actor.home.pos = this->actor.world.pos;
|
this->actor.home.pos = this->actor.world.pos;
|
||||||
if (((!IS_RANDO && !CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) ||
|
if (GameInteractor_Should(GI_VB_GORONS_CONSIDER_FIRE_TEMPLE_FINISHED, CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE), NULL) &&
|
||||||
(IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_FIRE_TEMPLE))) &&
|
|
||||||
CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON)) {
|
CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_GORON)) {
|
||||||
EnGo2_GetItemAnimation(this, play);
|
EnGo2_GetItemAnimation(this, play);
|
||||||
} else {
|
} else {
|
||||||
@ -1862,11 +1832,7 @@ void EnGo2_SetupGetItem(EnGo2* this, PlayState* play) {
|
|||||||
this->actor.parent = NULL;
|
this->actor.parent = NULL;
|
||||||
this->actionFunc = EnGo2_SetGetItem;
|
this->actionFunc = EnGo2_SetGetItem;
|
||||||
} else {
|
} else {
|
||||||
if (!IS_RANDO || this->getItemEntry.getItemId == GI_NONE) {
|
func_8002F434(&this->actor, play, this->getItemId, this->actor.xzDistToPlayer + 1.0f, fabsf(this->actor.yDistToPlayer) + 1.0f);
|
||||||
func_8002F434(&this->actor, play, this->getItemId, this->actor.xzDistToPlayer + 1.0f, fabsf(this->actor.yDistToPlayer) + 1.0f);
|
|
||||||
} else {
|
|
||||||
GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, this->actor.xzDistToPlayer + 1.0f, fabsf(this->actor.yDistToPlayer) + 1.0f);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1874,47 +1840,27 @@ void EnGo2_SetGetItem(EnGo2* this, PlayState* play) {
|
|||||||
if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) {
|
if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) {
|
||||||
this->interactInfo.talkState = NPC_TALK_STATE_IDLE;
|
this->interactInfo.talkState = NPC_TALK_STATE_IDLE;
|
||||||
|
|
||||||
// For randomizer, handle updating the states for the gorons after receiving the item based on
|
if (GameInteractor_Should(GI_VB_EN_GO2_RESET_AFTER_GET_ITEM, true, this)) {
|
||||||
// the goron type rather then the item being received
|
switch (this->getItemId) {
|
||||||
if (IS_RANDO) {
|
case GI_CLAIM_CHECK:
|
||||||
switch (this->actor.params & 0x1F) {
|
Environment_ClearBgsDayCount();
|
||||||
case GORON_DMT_BIGGORON:
|
|
||||||
// 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;
|
|
||||||
return;
|
|
||||||
case GORON_CITY_LINK:
|
|
||||||
EnGo2_GetItemAnimation(this, play);
|
EnGo2_GetItemAnimation(this, play);
|
||||||
return;
|
return;
|
||||||
case GORON_CITY_ROLLING_BIG:
|
case GI_TUNIC_GORON:
|
||||||
|
Flags_SetInfTable(INFTABLE_GORON_CITY_DOORS_UNLOCKED);
|
||||||
|
EnGo2_GetItemAnimation(this, play);
|
||||||
|
return;
|
||||||
|
case GI_SWORD_BGS:
|
||||||
|
gSaveContext.bgsFlag = true;
|
||||||
|
break;
|
||||||
|
case GI_BOMB_BAG_30:
|
||||||
|
case GI_BOMB_BAG_40:
|
||||||
EnGo2_RollingAnimation(this, play);
|
EnGo2_RollingAnimation(this, play);
|
||||||
this->actionFunc = EnGo2_GoronRollingBigContinueRolling;
|
this->actionFunc = EnGo2_GoronRollingBigContinueRolling;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this->actionFunc = func_80A46B40;
|
this->actionFunc = func_80A46B40;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (this->getItemId) {
|
|
||||||
case GI_CLAIM_CHECK:
|
|
||||||
Environment_ClearBgsDayCount();
|
|
||||||
EnGo2_GetItemAnimation(this, play);
|
|
||||||
return;
|
|
||||||
case GI_TUNIC_GORON:
|
|
||||||
Flags_SetInfTable(INFTABLE_GORON_CITY_DOORS_UNLOCKED);
|
|
||||||
EnGo2_GetItemAnimation(this, play);
|
|
||||||
return;
|
|
||||||
case GI_SWORD_BGS:
|
|
||||||
gSaveContext.bgsFlag = true;
|
|
||||||
break;
|
|
||||||
case GI_BOMB_BAG_30:
|
|
||||||
case GI_BOMB_BAG_40:
|
|
||||||
EnGo2_RollingAnimation(this, play);
|
|
||||||
this->actionFunc = EnGo2_GoronRollingBigContinueRolling;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->actionFunc = func_80A46B40;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1925,12 +1871,12 @@ void EnGo2_BiggoronEyedrops(EnGo2* this, PlayState* play) {
|
|||||||
this->actor.flags &= ~ACTOR_FLAG_TARGETABLE;
|
this->actor.flags &= ~ACTOR_FLAG_TARGETABLE;
|
||||||
this->actor.shape.rot.y += 0x5B0;
|
this->actor.shape.rot.y += 0x5B0;
|
||||||
this->trackingMode = NPC_TRACKING_NONE;
|
this->trackingMode = NPC_TRACKING_NONE;
|
||||||
this->animTimer = IS_RANDO ? 0 : (this->skelAnime.endFrame + 60.0f + 60.0f); // eyeDrops animation timer
|
this->animTimer = !GameInteractor_Should(GI_VB_PLAY_EYEDROPS_CS, true, NULL) ? 0 : (this->skelAnime.endFrame + 60.0f + 60.0f); // eyeDrops animation timer
|
||||||
this->eyeMouthTexState = 2;
|
this->eyeMouthTexState = 2;
|
||||||
this->unk_20C = 0;
|
this->unk_20C = 0;
|
||||||
this->goronState++;
|
this->goronState++;
|
||||||
func_800F483C(0x28, 5);
|
func_800F483C(0x28, 5);
|
||||||
if (!IS_RANDO) {
|
if (GameInteractor_Should(GI_VB_PLAY_EYEDROPS_CS, true, NULL)) {
|
||||||
OnePointCutscene_Init(play, 4190, -99, &this->actor, MAIN_CAM);
|
OnePointCutscene_Init(play, 4190, -99, &this->actor, MAIN_CAM);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1959,16 +1905,15 @@ void EnGo2_BiggoronEyedrops(EnGo2* this, PlayState* play) {
|
|||||||
this->trackingMode = NPC_TRACKING_HEAD_AND_TORSO;
|
this->trackingMode = NPC_TRACKING_HEAD_AND_TORSO;
|
||||||
this->skelAnime.playSpeed = 0.0f;
|
this->skelAnime.playSpeed = 0.0f;
|
||||||
this->skelAnime.curFrame = this->skelAnime.endFrame;
|
this->skelAnime.curFrame = this->skelAnime.endFrame;
|
||||||
if (IS_RANDO) {
|
|
||||||
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_DMT_TRADE_EYEDROPS, GI_CLAIM_CHECK);
|
Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_EYEDROPS);
|
||||||
Randomizer_ConsumeAdultTradeItem(play, ITEM_EYEDROPS);
|
if(GameInteractor_Should(GI_VB_TRADE_EYEDROPS, true, this)) {
|
||||||
EnGo2_GetItemEntry(this, play, getItemEntry);
|
|
||||||
Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_DMT_TRADE_EYEDROPS);
|
|
||||||
} else {
|
|
||||||
u32 getItemId = GI_CLAIM_CHECK;
|
u32 getItemId = GI_CLAIM_CHECK;
|
||||||
EnGo2_GetItem(this, play, getItemId);
|
EnGo2_GetItem(this, play, getItemId);
|
||||||
|
this->actionFunc = EnGo2_SetupGetItem;
|
||||||
|
} else {
|
||||||
|
this->actionFunc = EnGo2_SetGetItem;
|
||||||
}
|
}
|
||||||
this->actionFunc = EnGo2_SetupGetItem;
|
|
||||||
this->goronState = 0;
|
this->goronState = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -107,4 +107,9 @@ typedef struct EnGo2 {
|
|||||||
/* */ GetItemEntry getItemEntry;
|
/* */ GetItemEntry getItemEntry;
|
||||||
} EnGo2; // size = 0x05A0
|
} EnGo2; // size = 0x05A0
|
||||||
|
|
||||||
|
void EnGo2_GetItemAnimation(EnGo2* enGo2, PlayState* play);
|
||||||
|
void EnGo2_RollingAnimation(EnGo2* enGo2, PlayState* play);
|
||||||
|
void EnGo2_GoronRollingBigContinueRolling(EnGo2* enGo2, PlayState* play);
|
||||||
|
void func_80A46B40(EnGo2* enGo2, PlayState* play);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
#include "z_en_hs.h"
|
#include "z_en_hs.h"
|
||||||
#include "vt.h"
|
#include "vt.h"
|
||||||
#include "objects/object_hs/object_hs.h"
|
#include "objects/object_hs/object_hs.h"
|
||||||
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY)
|
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY)
|
||||||
|
|
||||||
@ -79,25 +79,7 @@ void EnHs_Init(Actor* thisx, PlayState* play) {
|
|||||||
// "chicken shop (adult era)"
|
// "chicken shop (adult era)"
|
||||||
osSyncPrintf(VT_FGCOL(CYAN) " ヒヨコの店(大人の時) \n" VT_RST);
|
osSyncPrintf(VT_FGCOL(CYAN) " ヒヨコの店(大人の時) \n" VT_RST);
|
||||||
func_80A6E3A0(this, func_80A6E9AC);
|
func_80A6E3A0(this, func_80A6E9AC);
|
||||||
bool shouldSpawn;
|
if (GameInteractor_Should(GI_VB_DESPAWN_GROG, Flags_GetItemGetInf(ITEMGETINF_30), this)) {
|
||||||
bool tradedMushroom = Flags_GetItemGetInf(ITEMGETINF_30);
|
|
||||||
if (IS_RANDO && 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"
|
// "chicken shop closed"
|
||||||
osSyncPrintf(VT_FGCOL(CYAN) " ヒヨコ屋閉店 \n" VT_RST);
|
osSyncPrintf(VT_FGCOL(CYAN) " ヒヨコ屋閉店 \n" VT_RST);
|
||||||
Actor_Kill(&this->actor);
|
Actor_Kill(&this->actor);
|
||||||
@ -148,11 +130,11 @@ void func_80A6E5EC(EnHs* this, PlayState* play) {
|
|||||||
|
|
||||||
void func_80A6E630(EnHs* this, PlayState* play) {
|
void func_80A6E630(EnHs* this, PlayState* play) {
|
||||||
if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) {
|
if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) {
|
||||||
if (!IS_RANDO) {
|
if (GameInteractor_Should(GI_VB_TRADE_TIMER_ODD_MUSHROOM, true, NULL)) {
|
||||||
func_80088AA0(180);
|
func_80088AA0(180);
|
||||||
|
gSaveContext.eventInf[1] &= ~1;
|
||||||
}
|
}
|
||||||
func_80A6E3A0(this, func_80A6E6B0);
|
func_80A6E3A0(this, func_80A6E6B0);
|
||||||
gSaveContext.eventInf[1] &= ~1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this->unk_2A8 |= 1;
|
this->unk_2A8 |= 1;
|
||||||
@ -175,19 +157,12 @@ void func_80A6E70C(EnHs* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void func_80A6E740(EnHs* this, PlayState* play) {
|
void func_80A6E740(EnHs* this, PlayState* play) {
|
||||||
if (Actor_HasParent(&this->actor, play)) {
|
if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_TRADE_COJIRO, true, this)) {
|
||||||
this->actor.parent = NULL;
|
this->actor.parent = NULL;
|
||||||
|
Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_LW_TRADE_COJIRO);
|
||||||
func_80A6E3A0(this, func_80A6E630);
|
func_80A6E3A0(this, func_80A6E630);
|
||||||
} else {
|
} else {
|
||||||
if (IS_RANDO) {
|
func_8002F434(&this->actor, play, GI_ODD_MUSHROOM, 10000.0f, 50.0f);
|
||||||
GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_LW_TRADE_COJIRO, GI_ODD_MUSHROOM);
|
|
||||||
Randomizer_ConsumeAdultTradeItem(play, ITEM_COJIRO);
|
|
||||||
GiveItemEntryFromActor(&this->actor, play, itemEntry, 10000.0f, 50.0f);
|
|
||||||
Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_LW_TRADE_COJIRO);
|
|
||||||
} else {
|
|
||||||
s32 itemId = GI_ODD_MUSHROOM;
|
|
||||||
func_8002F434(&this->actor, play, itemId, 10000.0f, 50.0f);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this->unk_2A8 |= 1;
|
this->unk_2A8 |= 1;
|
||||||
@ -198,14 +173,8 @@ void func_80A6E7BC(EnHs* this, PlayState* play) {
|
|||||||
switch (play->msgCtx.choiceIndex) {
|
switch (play->msgCtx.choiceIndex) {
|
||||||
case 0:
|
case 0:
|
||||||
func_80A6E3A0(this, func_80A6E740);
|
func_80A6E3A0(this, func_80A6E740);
|
||||||
if (IS_RANDO) {
|
if (GameInteractor_Should(GI_VB_TRADE_COJIRO, true, this)) {
|
||||||
GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_LW_TRADE_COJIRO, GI_ODD_MUSHROOM);
|
func_8002F434(&this->actor, play, GI_ODD_MUSHROOM, 10000.0f, 50.0f);
|
||||||
Randomizer_ConsumeAdultTradeItem(play, ITEM_COJIRO);
|
|
||||||
GiveItemEntryFromActor(&this->actor, play, itemEntry, 10000.0f, 50.0f);
|
|
||||||
Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_LW_TRADE_COJIRO);
|
|
||||||
} else {
|
|
||||||
s32 itemId = GI_ODD_MUSHROOM;
|
|
||||||
func_8002F434(&this->actor, play, itemId, 10000.0f, 50.0f);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "z_en_js.h"
|
#include "z_en_js.h"
|
||||||
#include "objects/object_js/object_js.h"
|
#include "objects/object_js/object_js.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY)
|
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY)
|
||||||
|
|
||||||
@ -127,23 +128,15 @@ void func_80A8910C(EnJs* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void func_80A89160(EnJs* this, PlayState* play) {
|
void func_80A89160(EnJs* this, PlayState* play) {
|
||||||
if (Actor_HasParent(&this->actor, play)) {
|
if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_CARPET_SALESMAN, true, this)) {
|
||||||
this->actor.parent = NULL;
|
this->actor.parent = NULL;
|
||||||
En_Js_SetupAction(this, func_80A8910C);
|
En_Js_SetupAction(this, func_80A8910C);
|
||||||
|
Flags_SetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN);
|
||||||
} else {
|
} else {
|
||||||
if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF &&
|
GetItemEntry itemEntry = ItemTable_Retrieve(GI_BOMBCHUS_10);
|
||||||
!Flags_GetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN)) {
|
gSaveContext.pendingSale = itemEntry.itemId;
|
||||||
GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_WASTELAND_BOMBCHU_SALESMAN, GI_BOMBCHUS_10);
|
gSaveContext.pendingSaleMod = itemEntry.modIndex;
|
||||||
gSaveContext.pendingSale = itemEntry.itemId;
|
func_8002F434(&this->actor, play, GI_BOMBCHUS_10, 10000.0f, 50.0f);
|
||||||
gSaveContext.pendingSaleMod = itemEntry.modIndex;
|
|
||||||
GiveItemEntryFromActor(&this->actor, play, itemEntry, 10000.0f, 50.0f);
|
|
||||||
Flags_SetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN);
|
|
||||||
} else {
|
|
||||||
GetItemEntry itemEntry = ItemTable_Retrieve(GI_BOMBCHUS_10);
|
|
||||||
gSaveContext.pendingSale = itemEntry.itemId;
|
|
||||||
gSaveContext.pendingSaleMod = itemEntry.modIndex;
|
|
||||||
func_8002F434(&this->actor, play, GI_BOMBCHUS_10, 10000.0f, 50.0f);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#include "objects/object_km1/object_km1.h"
|
#include "objects/object_km1/object_km1.h"
|
||||||
#include "objects/object_kw1/object_kw1.h"
|
#include "objects/object_kw1/object_kw1.h"
|
||||||
#include "vt.h"
|
#include "vt.h"
|
||||||
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED)
|
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED)
|
||||||
|
|
||||||
@ -1027,20 +1027,9 @@ s32 EnKo_CanSpawn(EnKo* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case SCENE_LOST_WOODS:
|
case SCENE_LOST_WOODS:
|
||||||
if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE)) {
|
return GameInteractor_Should(GI_VB_SPAWN_LW_FADO, (
|
||||||
// To explain the logic because Fado and Grog are linked:
|
(INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_ODD_POTION) ? true : false
|
||||||
// - If you have Cojiro, then spawn Grog and not Fado.
|
), this);
|
||||||
// - 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:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1186,18 +1175,10 @@ void func_80A99048(EnKo* this, PlayState* play) {
|
|||||||
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_EN_ELF, this->actor.world.pos.x,
|
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_EN_ELF, this->actor.world.pos.x,
|
||||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 3);
|
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 3);
|
||||||
if (ENKO_TYPE == ENKO_TYPE_CHILD_3) {
|
if (ENKO_TYPE == ENKO_TYPE_CHILD_3) {
|
||||||
if (!IS_RANDO) {
|
if (!GameInteractor_Should(GI_VB_OPEN_KOKIRI_FOREST, CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD), this)) {
|
||||||
if (!CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)) {
|
this->collider.dim.height += 200;
|
||||||
this->collider.dim.height += 200;
|
this->actionFunc = func_80A995CC;
|
||||||
this->actionFunc = func_80A995CC;
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD)) {
|
|
||||||
this->collider.dim.height += 200;
|
|
||||||
this->actionFunc = func_80A995CC;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Path_CopyLastPoint(this->path, &this->actor.world.pos);
|
Path_CopyLastPoint(this->path, &this->actor.world.pos);
|
||||||
}
|
}
|
||||||
@ -1230,18 +1211,11 @@ void func_80A99438(EnKo* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void func_80A99504(EnKo* this, PlayState* play) {
|
void func_80A99504(EnKo* this, PlayState* play) {
|
||||||
if (Actor_HasParent(&this->actor, play)) {
|
if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_TRADE_ODD_POTION, true, this)) {
|
||||||
this->actor.parent = NULL;
|
this->actor.parent = NULL;
|
||||||
this->actionFunc = func_80A99560;
|
this->actionFunc = func_80A99560;
|
||||||
} else {
|
} else {
|
||||||
if (IS_RANDO) {
|
func_8002F434(&this->actor, play, GI_SAW, 120.0f, 10.0f);
|
||||||
GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_LW_TRADE_ODD_POTION, GI_SAW);
|
|
||||||
Randomizer_ConsumeAdultTradeItem(play, ITEM_ODD_POTION);
|
|
||||||
GiveItemEntryFromActor(&this->actor, play, itemEntry, 120.0f, 10.0f);
|
|
||||||
} else {
|
|
||||||
s32 itemId = GI_SAW;
|
|
||||||
func_8002F434(&this->actor, play, itemId, 120.0f, 10.0f);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,4 +57,8 @@ typedef enum {
|
|||||||
ENKO_FQS_ADULT_SAVED
|
ENKO_FQS_ADULT_SAVED
|
||||||
} KokiriForestQuestState;
|
} KokiriForestQuestState;
|
||||||
|
|
||||||
|
void func_80A995CC(EnKo* actor, PlayState* play);
|
||||||
|
void func_80A99384(EnKo* actor, PlayState* play);
|
||||||
|
void func_80A99560(EnKo* actor, PlayState* play);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#include "z_en_kz.h"
|
#include "z_en_kz.h"
|
||||||
#include "objects/object_kz/object_kz.h"
|
#include "objects/object_kz/object_kz.h"
|
||||||
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY)
|
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY)
|
||||||
|
|
||||||
@ -73,12 +73,9 @@ static AnimationInfo sAnimationInfo[] = {
|
|||||||
u16 EnKz_GetTextNoMaskChild(PlayState* play, EnKz* this) {
|
u16 EnKz_GetTextNoMaskChild(PlayState* play, EnKz* this) {
|
||||||
Player* player = GET_PLAYER(play);
|
Player* player = GET_PLAYER(play);
|
||||||
|
|
||||||
if ((IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_JABU_JABUS_BELLY)) ||
|
if (GameInteractor_Should(GI_VB_KING_ZORA_THANK_CHILD, (
|
||||||
(!IS_RANDO && CHECK_QUEST_ITEM(QUEST_ZORA_SAPPHIRE))) {
|
CHECK_QUEST_ITEM(QUEST_ZORA_SAPPHIRE)
|
||||||
// Allow turning in Ruto's letter even if you have already rescued her
|
), this)) {
|
||||||
if (IS_RANDO && !Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) {
|
|
||||||
player->exchangeItemId = EXCH_ITEM_LETTER_RUTO;
|
|
||||||
}
|
|
||||||
return 0x402B;
|
return 0x402B;
|
||||||
} else if (Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) {
|
} else if (Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) {
|
||||||
return 0x401C;
|
return 0x401C;
|
||||||
@ -94,8 +91,10 @@ u16 EnKz_GetTextNoMaskAdult(PlayState* play, EnKz* this) {
|
|||||||
// this works because both ITEM_NONE and later trade items are > ITEM_FROG
|
// this works because both ITEM_NONE and later trade items are > ITEM_FROG
|
||||||
if (INV_CONTENT(ITEM_TRADE_ADULT) >= ITEM_FROG) {
|
if (INV_CONTENT(ITEM_TRADE_ADULT) >= ITEM_FROG) {
|
||||||
if (!Flags_GetInfTable(INFTABLE_139)) {
|
if (!Flags_GetInfTable(INFTABLE_139)) {
|
||||||
if (!IS_RANDO) {
|
if (!GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_THAWING_KING_ZORA, (
|
||||||
return CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_ZORA) ? 0x401F : 0x4012;
|
!CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_ZORA)
|
||||||
|
), this)) {
|
||||||
|
return 0x401F;
|
||||||
} else {
|
} else {
|
||||||
return 0x4012;
|
return 0x4012;
|
||||||
}
|
}
|
||||||
@ -243,7 +242,9 @@ void func_80A9CB18(EnKz* this, PlayState* play) {
|
|||||||
Player* player = GET_PLAYER(play);
|
Player* player = GET_PLAYER(play);
|
||||||
|
|
||||||
if (func_80A9C95C(play, this, &this->interactInfo.talkState, 340.0f, EnKz_GetText, func_80A9C6C0)) {
|
if (func_80A9C95C(play, this, &this->interactInfo.talkState, 340.0f, EnKz_GetText, func_80A9C6C0)) {
|
||||||
if (((IS_RANDO && LINK_IS_CHILD) || this->actor.textId == 0x401A) && !Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) {
|
if (GameInteractor_Should(GI_VB_BE_ABLE_TO_EXCHANGE_RUTOS_LETTER, (this->actor.textId == 0x401A), this) &&
|
||||||
|
!Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED))
|
||||||
|
{
|
||||||
if (func_8002F368(play) == EXCH_ITEM_LETTER_RUTO) {
|
if (func_8002F368(play) == EXCH_ITEM_LETTER_RUTO) {
|
||||||
this->actor.textId = 0x401B;
|
this->actor.textId = 0x401B;
|
||||||
this->sfxPlayed = false;
|
this->sfxPlayed = false;
|
||||||
@ -257,7 +258,7 @@ void func_80A9CB18(EnKz* this, PlayState* play) {
|
|||||||
if (LINK_IS_ADULT) {
|
if (LINK_IS_ADULT) {
|
||||||
if ((INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_PRESCRIPTION) &&
|
if ((INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_PRESCRIPTION) &&
|
||||||
(func_8002F368(play) == EXCH_ITEM_PRESCRIPTION)) {
|
(func_8002F368(play) == EXCH_ITEM_PRESCRIPTION)) {
|
||||||
if (!IS_RANDO || !Flags_GetTreasure(play, 0x1F)) {
|
if (GameInteractor_Should(GI_VB_TRADE_PRESCRIPTION, true, this)) {
|
||||||
this->actor.textId = 0x4014;
|
this->actor.textId = 0x4014;
|
||||||
this->sfxPlayed = false;
|
this->sfxPlayed = false;
|
||||||
player->actor.textId = this->actor.textId;
|
player->actor.textId = this->actor.textId;
|
||||||
@ -271,11 +272,11 @@ void func_80A9CB18(EnKz* this, PlayState* play) {
|
|||||||
this->actor.textId = CHECK_QUEST_ITEM(QUEST_SONG_SERENADE) ? 0x4045 : 0x401A;
|
this->actor.textId = CHECK_QUEST_ITEM(QUEST_SONG_SERENADE) ? 0x4045 : 0x401A;
|
||||||
player->actor.textId = this->actor.textId;
|
player->actor.textId = this->actor.textId;
|
||||||
} else {
|
} else {
|
||||||
if (!IS_RANDO) {
|
this->actor.textId =
|
||||||
this->actor.textId = CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_ZORA) ? 0x401F : 0x4012;
|
!GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_THAWING_KING_ZORA,
|
||||||
} else {
|
(!CHECK_OWNED_EQUIP(EQUIP_TYPE_TUNIC, EQUIP_INV_TUNIC_ZORA)), this)
|
||||||
this->actor.textId = 0x4012;
|
? 0x401F
|
||||||
}
|
: 0x4012;
|
||||||
|
|
||||||
player->actor.textId = this->actor.textId;
|
player->actor.textId = this->actor.textId;
|
||||||
}
|
}
|
||||||
@ -344,29 +345,10 @@ void EnKz_Init(Actor* thisx, PlayState* play) {
|
|||||||
this->interactInfo.talkState = NPC_TALK_STATE_IDLE;
|
this->interactInfo.talkState = NPC_TALK_STATE_IDLE;
|
||||||
Animation_ChangeByInfo(&this->skelanime, sAnimationInfo, ENKZ_ANIM_0);
|
Animation_ChangeByInfo(&this->skelanime, sAnimationInfo, ENKZ_ANIM_0);
|
||||||
|
|
||||||
if (!IS_RANDO) {
|
if (GameInteractor_Should(GI_VB_KING_ZORA_BE_MOVED, (
|
||||||
if (Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) {
|
Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)
|
||||||
EnKz_SetMovedPos(this, play);
|
), this)) {
|
||||||
}
|
EnKz_SetMovedPos(this, play);
|
||||||
} else {
|
|
||||||
int zorasFountain = Randomizer_GetSettingValue(RSK_ZORAS_FOUNTAIN);
|
|
||||||
switch (zorasFountain) {
|
|
||||||
case 0:
|
|
||||||
if (Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) {
|
|
||||||
EnKz_SetMovedPos(this, play);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
if (LINK_IS_ADULT) {
|
|
||||||
EnKz_SetMovedPos(this, play);
|
|
||||||
} else if (Flags_GetEventChkInf(EVENTCHKINF_KING_ZORA_MOVED)) {
|
|
||||||
EnKz_SetMovedPos(this, play);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
EnKz_SetMovedPos(this, play);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LINK_IS_ADULT) {
|
if (LINK_IS_ADULT) {
|
||||||
@ -465,37 +447,29 @@ void EnKz_SetupGetItem(EnKz* this, PlayState* play) {
|
|||||||
f32 xzRange;
|
f32 xzRange;
|
||||||
f32 yRange;
|
f32 yRange;
|
||||||
|
|
||||||
if (Actor_HasParent(&this->actor, play)) {
|
if (Actor_HasParent(&this->actor, play) || (
|
||||||
|
(this->isTrading && !GameInteractor_Should(GI_VB_TRADE_PRESCRIPTION, true, this)) ||
|
||||||
|
(!this->isTrading && !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_THAWING_KING_ZORA, true, this))
|
||||||
|
)) {
|
||||||
this->actor.parent = NULL;
|
this->actor.parent = NULL;
|
||||||
this->interactInfo.talkState = NPC_TALK_STATE_TALKING;
|
this->interactInfo.talkState = NPC_TALK_STATE_TALKING;
|
||||||
this->actionFunc = EnKz_StartTimer;
|
this->actionFunc = EnKz_StartTimer;
|
||||||
} else {
|
if (!this->isTrading) {
|
||||||
if (IS_RANDO) {
|
Flags_SetRandomizerInf(RAND_INF_KING_ZORA_THAWED);
|
||||||
if (this->isTrading) {
|
|
||||||
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_ZD_TRADE_PRESCRIPTION, GI_FROG);
|
|
||||||
getItemId = getItemEntry.getItemId;
|
|
||||||
Randomizer_ConsumeAdultTradeItem(play, ITEM_PRESCRIPTION);
|
|
||||||
Flags_SetTreasure(play, 0x1F);
|
|
||||||
} else {
|
|
||||||
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_ZD_KING_ZORA_THAWED, GI_TUNIC_ZORA);
|
|
||||||
getItemId = getItemEntry.getItemId;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
getItemId = this->isTrading ? GI_FROG : GI_TUNIC_ZORA;
|
Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_ZD_TRADE_PRESCRIPTION);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
getItemId = this->isTrading ? GI_FROG : GI_TUNIC_ZORA;
|
||||||
yRange = fabsf(this->actor.yDistToPlayer) + 1.0f;
|
yRange = fabsf(this->actor.yDistToPlayer) + 1.0f;
|
||||||
xzRange = this->actor.xzDistToPlayer + 1.0f;
|
xzRange = this->actor.xzDistToPlayer + 1.0f;
|
||||||
if (!IS_RANDO || getItemEntry.getItemId == GI_NONE) {
|
func_8002F434(&this->actor, play, getItemId, xzRange, yRange);
|
||||||
func_8002F434(&this->actor, play, getItemId, xzRange, yRange);
|
|
||||||
} else {
|
|
||||||
GiveItemEntryFromActor(&this->actor, play, getItemEntry, xzRange, yRange);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnKz_StartTimer(EnKz* this, PlayState* play) {
|
void EnKz_StartTimer(EnKz* this, PlayState* play) {
|
||||||
if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) {
|
if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) {
|
||||||
if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_FROG && !IS_RANDO) {
|
if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_FROG && GameInteractor_Should(GI_VB_TRADE_TIMER_FROG, true, NULL)) {
|
||||||
func_80088AA0(180); // start timer2 with 3 minutes
|
func_80088AA0(180); // start timer2 with 3 minutes
|
||||||
gSaveContext.eventInf[1] &= ~1;
|
gSaveContext.eventInf[1] &= ~1;
|
||||||
}
|
}
|
||||||
|
@ -28,4 +28,6 @@ typedef struct EnKz {
|
|||||||
/* 0x02BE */ s16 unk_2BE[12];
|
/* 0x02BE */ s16 unk_2BE[12];
|
||||||
} EnKz; // size = 0x02D8
|
} EnKz; // size = 0x02D8
|
||||||
|
|
||||||
|
void EnKz_SetupGetItem(EnKz* enKz, PlayState* play);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "z_en_ma1.h"
|
#include "z_en_ma1.h"
|
||||||
#include "objects/object_ma1/object_ma1.h"
|
#include "objects/object_ma1/object_ma1.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED | ACTOR_FLAG_NO_FREEZE_OCARINA)
|
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_DRAW_WHILE_CULLED | ACTOR_FLAG_NO_FREEZE_OCARINA)
|
||||||
|
|
||||||
@ -25,7 +26,6 @@ void func_80AA106C(EnMa1* this, PlayState* play);
|
|||||||
void func_80AA10EC(EnMa1* this, PlayState* play);
|
void func_80AA10EC(EnMa1* this, PlayState* play);
|
||||||
void func_80AA1150(EnMa1* this, PlayState* play);
|
void func_80AA1150(EnMa1* this, PlayState* play);
|
||||||
void EnMa1_DoNothing(EnMa1* this, PlayState* play);
|
void EnMa1_DoNothing(EnMa1* this, PlayState* play);
|
||||||
void EnMa1_WaitForSongGive(EnMa1* this, PlayState* play);
|
|
||||||
|
|
||||||
const ActorInit En_Ma1_InitVars = {
|
const ActorInit En_Ma1_InitVars = {
|
||||||
ACTOR_EN_MA1,
|
ACTOR_EN_MA1,
|
||||||
@ -90,25 +90,16 @@ static void* sEyeTextures[] = {
|
|||||||
gMalonChildEyeClosedTex,
|
gMalonChildEyeClosedTex,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool Randomizer_ObtainedMalonHCReward() {
|
|
||||||
return Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_POCKET_EGG);
|
|
||||||
}
|
|
||||||
|
|
||||||
u16 EnMa1_GetText(PlayState* play, Actor* thisx) {
|
u16 EnMa1_GetText(PlayState* play, Actor* thisx) {
|
||||||
// Special case for Malon Hyrule Castle Text. Placing it here at the beginning
|
bool malonReturnedFromCastle = GameInteractor_Should(GI_VB_MALON_RETURN_FROM_CASTLE, Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE), NULL);
|
||||||
// has the added benefit of circumventing mask text if wearing bunny hood.
|
bool malonTaughtEponasSong = GameInteractor_Should(GI_VB_MALON_ALREADY_TAUGHT_EPONAS_SONG, CHECK_QUEST_ITEM(QUEST_SONG_EPONA), NULL);
|
||||||
if (IS_RANDO && play->sceneNum == SCENE_HYRULE_CASTLE) {
|
|
||||||
return Randomizer_ObtainedMalonHCReward() ? 0x2044 : 0x2043;
|
|
||||||
}
|
|
||||||
u16 faceReaction = Text_GetFaceReaction(play, 0x17);
|
u16 faceReaction = Text_GetFaceReaction(play, 0x17);
|
||||||
|
|
||||||
if (faceReaction != 0) {
|
if (faceReaction != 0) {
|
||||||
return faceReaction;
|
return faceReaction;
|
||||||
}
|
}
|
||||||
if (!IS_RANDO) {
|
if (malonTaughtEponasSong) {
|
||||||
if (CHECK_QUEST_ITEM(QUEST_SONG_EPONA)) {
|
return 0x204A;
|
||||||
return 0x204A;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (Flags_GetEventChkInf(EVENTCHKINF_INVITED_TO_SING_WITH_CHILD_MALON)) {
|
if (Flags_GetEventChkInf(EVENTCHKINF_INVITED_TO_SING_WITH_CHILD_MALON)) {
|
||||||
return 0x2049;
|
return 0x2049;
|
||||||
@ -120,7 +111,7 @@ u16 EnMa1_GetText(PlayState* play, Actor* thisx) {
|
|||||||
return 0x2048;
|
return 0x2048;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE)) {
|
if (malonReturnedFromCastle) {
|
||||||
return 0x2047;
|
return 0x2047;
|
||||||
}
|
}
|
||||||
if (Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_POCKET_EGG)) {
|
if (Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_POCKET_EGG)) {
|
||||||
@ -194,6 +185,8 @@ s16 func_80AA0778(PlayState* play, Actor* thisx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
s32 func_80AA08C4(EnMa1* this, PlayState* play) {
|
s32 func_80AA08C4(EnMa1* this, PlayState* play) {
|
||||||
|
bool malonReturnedFromCastle = GameInteractor_Should(GI_VB_MALON_RETURN_FROM_CASTLE, Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE), NULL);
|
||||||
|
|
||||||
if ((this->actor.shape.rot.z == 3) && (gSaveContext.sceneSetupIndex == 5)) {
|
if ((this->actor.shape.rot.z == 3) && (gSaveContext.sceneSetupIndex == 5)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -202,32 +195,24 @@ s32 func_80AA08C4(EnMa1* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
// Causes Malon to appear in the market if you haven't met her yet.
|
// Causes Malon to appear in the market if you haven't met her yet.
|
||||||
if (((play->sceneNum == SCENE_MARKET_NIGHT) || (play->sceneNum == SCENE_MARKET_DAY)) &&
|
if (((play->sceneNum == SCENE_MARKET_NIGHT) || (play->sceneNum == SCENE_MARKET_DAY)) &&
|
||||||
!Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE) && !Flags_GetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE)) {
|
!malonReturnedFromCastle && !Flags_GetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if ((play->sceneNum == SCENE_HYRULE_CASTLE) && // if we're at hyrule castle
|
if ((play->sceneNum == SCENE_HYRULE_CASTLE) && !malonReturnedFromCastle) {
|
||||||
(!Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE) || // and talon hasn't left
|
if (Flags_GetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE)) {
|
||||||
(IS_RANDO &&
|
return 1;
|
||||||
!Randomizer_ObtainedMalonHCReward()))) { // or we're rando'd and haven't gotten malon's HC check
|
} else {
|
||||||
if (Flags_GetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE)) { // if we've met malon
|
Flags_SetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE);
|
||||||
return 1; // make her appear at the castle
|
return 0;
|
||||||
} else { // if we haven't met malon
|
|
||||||
Flags_SetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE); // 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 ((play->sceneNum == SCENE_LON_LON_BUILDINGS) && IS_NIGHT && malonReturnedFromCastle) {
|
||||||
if ((play->sceneNum == SCENE_LON_LON_BUILDINGS) && IS_NIGHT && (Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE))) {
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
// Don't spawn Malon if none of the above are true and we are not in Lon Lon Ranch.
|
|
||||||
if (play->sceneNum != SCENE_LON_LON_RANCH) {
|
if (play->sceneNum != SCENE_LON_LON_RANCH) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// If we've gotten this far, we're in Lon Lon Ranch. Spawn Malon if it is daytime, Talon has left Hyrule Castle, and
|
if ((this->actor.shape.rot.z == 3) && IS_DAY && malonReturnedFromCastle) {
|
||||||
// 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 && (Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE)) &&
|
|
||||||
((IS_RANDO && Randomizer_ObtainedMalonHCReward()) || !IS_RANDO)) {
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -284,6 +269,8 @@ void func_80AA0B74(EnMa1* this) {
|
|||||||
|
|
||||||
void EnMa1_Init(Actor* thisx, PlayState* play) {
|
void EnMa1_Init(Actor* thisx, PlayState* play) {
|
||||||
EnMa1* this = (EnMa1*)thisx;
|
EnMa1* this = (EnMa1*)thisx;
|
||||||
|
bool malonReturnedFromCastle = GameInteractor_Should(GI_VB_MALON_RETURN_FROM_CASTLE, Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE), NULL);
|
||||||
|
bool malonTaughtEponasSong = GameInteractor_Should(GI_VB_MALON_ALREADY_TAUGHT_EPONAS_SONG, CHECK_QUEST_ITEM(QUEST_SONG_EPONA), NULL);
|
||||||
s32 pad;
|
s32 pad;
|
||||||
|
|
||||||
ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 18.0f);
|
ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 18.0f);
|
||||||
@ -292,12 +279,6 @@ void EnMa1_Init(Actor* thisx, PlayState* play) {
|
|||||||
Collider_SetCylinder(play, &this->collider, &this->actor, &sCylinderInit);
|
Collider_SetCylinder(play, &this->collider, &this->actor, &sCylinderInit);
|
||||||
CollisionCheck_SetInfo2(&this->actor.colChkInfo, DamageTable_Get(22), &sColChkInfoInit);
|
CollisionCheck_SetInfo2(&this->actor.colChkInfo, DamageTable_Get(22), &sColChkInfoInit);
|
||||||
|
|
||||||
if (IS_RANDO) { // Skip Malon's multiple textboxes before getting an item
|
|
||||||
Flags_SetInfTable(INFTABLE_ENTERED_HYRULE_CASTLE);
|
|
||||||
Flags_SetInfTable(INFTABLE_MET_CHILD_MALON_AT_CASTLE_OR_MARKET);
|
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_CHILD_MALON_AT_CASTLE_OR_MARKET);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!func_80AA08C4(this, play)) {
|
if (!func_80AA08C4(this, play)) {
|
||||||
Actor_Kill(&this->actor);
|
Actor_Kill(&this->actor);
|
||||||
return;
|
return;
|
||||||
@ -308,21 +289,10 @@ void EnMa1_Init(Actor* thisx, PlayState* play) {
|
|||||||
this->actor.targetMode = 6;
|
this->actor.targetMode = 6;
|
||||||
this->interactInfo.talkState = NPC_TALK_STATE_IDLE;
|
this->interactInfo.talkState = NPC_TALK_STATE_IDLE;
|
||||||
|
|
||||||
// To avoid missing a check, we want Malon to have the actionFunc for singing, but not reacting to Ocarina, if any of
|
if (!malonReturnedFromCastle || malonTaughtEponasSong) {
|
||||||
// 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 (!Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE) || (IS_RANDO && !Randomizer_ObtainedMalonHCReward()) || (CHECK_QUEST_ITEM(QUEST_SONG_EPONA) && !IS_RANDO) ||
|
|
||||||
(IS_RANDO && Flags_GetTreasure(play, 0x1F))) {
|
|
||||||
this->actionFunc = func_80AA0D88;
|
this->actionFunc = func_80AA0D88;
|
||||||
EnMa1_ChangeAnim(this, ENMA1_ANIM_2);
|
EnMa1_ChangeAnim(this, ENMA1_ANIM_2);
|
||||||
// If none of the above conditions were true, set Malon up to teach Epona's Song.
|
|
||||||
} else {
|
} else {
|
||||||
if (IS_RANDO) { // Skip straight to "let's sing it together" textbox in the ranch
|
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_INVITED_TO_SING_WITH_CHILD_MALON);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->actionFunc = func_80AA0F44;
|
this->actionFunc = func_80AA0F44;
|
||||||
EnMa1_ChangeAnim(this, ENMA1_ANIM_2);
|
EnMa1_ChangeAnim(this, ENMA1_ANIM_2);
|
||||||
}
|
}
|
||||||
@ -336,6 +306,9 @@ void EnMa1_Destroy(Actor* thisx, PlayState* play) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void func_80AA0D88(EnMa1* this, PlayState* play) {
|
void func_80AA0D88(EnMa1* this, PlayState* play) {
|
||||||
|
bool malonReturnedFromCastle = GameInteractor_Should(GI_VB_MALON_RETURN_FROM_CASTLE, Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE), NULL);
|
||||||
|
bool malonTaughtEponasSong = GameInteractor_Should(GI_VB_MALON_ALREADY_TAUGHT_EPONAS_SONG, CHECK_QUEST_ITEM(QUEST_SONG_EPONA), NULL);
|
||||||
|
|
||||||
if (this->interactInfo.talkState != NPC_TALK_STATE_IDLE) {
|
if (this->interactInfo.talkState != NPC_TALK_STATE_IDLE) {
|
||||||
if (this->skelAnime.animation != &gMalonChildIdleAnim) {
|
if (this->skelAnime.animation != &gMalonChildIdleAnim) {
|
||||||
EnMa1_ChangeAnim(this, ENMA1_ANIM_1);
|
EnMa1_ChangeAnim(this, ENMA1_ANIM_1);
|
||||||
@ -346,16 +319,9 @@ void func_80AA0D88(EnMa1* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We want to Kill Malon's Actor outside of randomizer when Talon is freed. In Randomizer we don't kill Malon's
|
if ((play->sceneNum == SCENE_HYRULE_CASTLE) && malonReturnedFromCastle) {
|
||||||
// Actor here, otherwise if we wake up Talon first and then get her check she will spontaneously
|
|
||||||
// disappear.
|
|
||||||
if ((play->sceneNum == SCENE_HYRULE_CASTLE) && (!IS_RANDO && Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE))) {
|
|
||||||
Actor_Kill(&this->actor);
|
Actor_Kill(&this->actor);
|
||||||
// We want Malon to give the Weird Egg Check (see function below) in the following situations:
|
} else if (!malonReturnedFromCastle || malonTaughtEponasSong) {
|
||||||
// 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 ((!Flags_GetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE) || (IS_RANDO && !Randomizer_ObtainedMalonHCReward())) || (CHECK_QUEST_ITEM(QUEST_SONG_EPONA) && !IS_RANDO)) {
|
|
||||||
if (this->interactInfo.talkState == NPC_TALK_STATE_ACTION) {
|
if (this->interactInfo.talkState == NPC_TALK_STATE_ACTION) {
|
||||||
this->actionFunc = func_80AA0EA0;
|
this->actionFunc = func_80AA0EA0;
|
||||||
play->msgCtx.stateTimer = 4;
|
play->msgCtx.stateTimer = 4;
|
||||||
@ -365,21 +331,16 @@ void func_80AA0D88(EnMa1* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void func_80AA0EA0(EnMa1* this, PlayState* play) {
|
void func_80AA0EA0(EnMa1* this, PlayState* play) {
|
||||||
if (Actor_HasParent(&this->actor, play)) {
|
if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_WEIRD_EGG, true, NULL)) {
|
||||||
this->actor.parent = NULL;
|
this->actor.parent = NULL;
|
||||||
this->actionFunc = func_80AA0EFC;
|
this->actionFunc = func_80AA0EFC;
|
||||||
} else {
|
} else {
|
||||||
if (!IS_RANDO) {
|
func_8002F434(&this->actor, play, GI_WEIRD_EGG, 120.0f, 10.0f);
|
||||||
func_8002F434(&this->actor, play, GI_WEIRD_EGG, 120.0f, 10.0f);
|
|
||||||
} else {
|
|
||||||
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_HC_MALON_EGG, GI_WEIRD_EGG);
|
|
||||||
GiveItemEntryFromActor(&this->actor, play, getItemEntry, 120.0f, 10.0f);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void func_80AA0EFC(EnMa1* this, PlayState* play) {
|
void func_80AA0EFC(EnMa1* this, PlayState* play) {
|
||||||
if (this->interactInfo.talkState == NPC_TALK_STATE_ITEM_GIVEN) {
|
if (this->interactInfo.talkState == NPC_TALK_STATE_ITEM_GIVEN || !GameInteractor_Should(GI_VB_GIVE_ITEM_WEIRD_EGG, true, NULL)) {
|
||||||
this->interactInfo.talkState = NPC_TALK_STATE_IDLE;
|
this->interactInfo.talkState = NPC_TALK_STATE_IDLE;
|
||||||
this->actionFunc = func_80AA0D88;
|
this->actionFunc = func_80AA0D88;
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_POCKET_EGG);
|
Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_POCKET_EGG);
|
||||||
@ -387,24 +348,6 @@ void func_80AA0EFC(EnMa1* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GivePlayerRandoRewardMalon(EnMa1* malon, PlayState* play, RandomizerCheck check) {
|
|
||||||
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, RG_EPONAS_SONG);
|
|
||||||
// Prevents flag from getting set if we weren't able to get the item (i.e. Player is holding shield
|
|
||||||
// when closing the textbox).
|
|
||||||
if (malon->actor.parent != NULL && malon->actor.parent->id == GET_PLAYER(play)->actor.id &&
|
|
||||||
!Flags_GetTreasure(play, 0x1F)) {
|
|
||||||
Flags_SetTreasure(play, 0x1F);
|
|
||||||
// puts malon in the action that vanilla has her in after learning the song
|
|
||||||
// (confirmed via breakpoints in a vanilla save).
|
|
||||||
malon->actionFunc = func_80AA0D88;
|
|
||||||
} else if (!Flags_GetTreasure(play, 0x1F)) {
|
|
||||||
GiveItemEntryFromActor(&malon->actor, play, getItemEntry, 10000.0f, 100.0f);
|
|
||||||
}
|
|
||||||
// make malon sing again after giving the item.
|
|
||||||
malon->interactInfo.talkState = NPC_TALK_STATE_IDLE;
|
|
||||||
malon->unk_1E0 = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void func_80AA0F44(EnMa1* this, PlayState* play) {
|
void func_80AA0F44(EnMa1* this, PlayState* play) {
|
||||||
Player* player = GET_PLAYER(play);
|
Player* player = GET_PLAYER(play);
|
||||||
|
|
||||||
@ -419,7 +362,6 @@ void func_80AA0F44(EnMa1* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Flags_GetEventChkInf(EVENTCHKINF_INVITED_TO_SING_WITH_CHILD_MALON)) {
|
if (Flags_GetEventChkInf(EVENTCHKINF_INVITED_TO_SING_WITH_CHILD_MALON)) {
|
||||||
// When the player pulls out the Ocarina while close to Malon
|
|
||||||
if (player->stateFlags2 & 0x1000000) {
|
if (player->stateFlags2 & 0x1000000) {
|
||||||
player->stateFlags2 |= 0x2000000;
|
player->stateFlags2 |= 0x2000000;
|
||||||
player->unk_6A8 = &this->actor;
|
player->unk_6A8 = &this->actor;
|
||||||
@ -427,19 +369,10 @@ void func_80AA0F44(EnMa1* this, PlayState* play) {
|
|||||||
Message_StartTextbox(play, this->actor.textId, NULL);
|
Message_StartTextbox(play, this->actor.textId, NULL);
|
||||||
this->interactInfo.talkState = NPC_TALK_STATE_TALKING;
|
this->interactInfo.talkState = NPC_TALK_STATE_TALKING;
|
||||||
this->actor.flags |= ACTOR_FLAG_WILL_TALK;
|
this->actor.flags |= ACTOR_FLAG_WILL_TALK;
|
||||||
// when rando'ed, skip to the Item Giving. Otherwise go to the song teaching code.
|
this->actionFunc = func_80AA106C;
|
||||||
this->actionFunc = IS_RANDO ? func_80AA1150 : func_80AA106C;
|
|
||||||
} else if (this->actor.xzDistToPlayer < 30.0f + (f32)this->collider.dim.radius) {
|
} else if (this->actor.xzDistToPlayer < 30.0f + (f32)this->collider.dim.radius) {
|
||||||
// somehow flags that the player is close to malon so that pulling out the Ocarina
|
|
||||||
// triggers the code above this.
|
|
||||||
player->stateFlags2 |= 0x800000;
|
player->stateFlags2 |= 0x800000;
|
||||||
}
|
}
|
||||||
// If rando'ed, a textbox is closing, it's malon's 'my mom wrote this song' text, AND we do have an ocarina
|
|
||||||
// in our inventory. This allows us to grant the check when talking to malon with the ocarina in our inventory.
|
|
||||||
if (IS_RANDO && (Actor_TextboxIsClosing(&this->actor, play) && play->msgCtx.textId == 0x2049) &&
|
|
||||||
(INV_CONTENT(ITEM_OCARINA_FAIRY) != ITEM_NONE || INV_CONTENT(ITEM_OCARINA_TIME) != ITEM_NONE)) {
|
|
||||||
this->actionFunc = EnMa1_WaitForSongGive;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -461,48 +394,16 @@ void func_80AA10EC(EnMa1* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnMa1_WaitForSongGive(EnMa1* this, PlayState* play) {
|
|
||||||
// Actually give the song check.
|
|
||||||
GivePlayerRandoRewardMalon(this, play, RC_SONG_FROM_MALON);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sets an Ocarina State necessary to not softlock in rando.
|
|
||||||
// This function should only be called in rando.
|
|
||||||
void EnMa1_EndTeachSong(EnMa1* this, PlayState* play) {
|
|
||||||
if (play->csCtx.state == CS_STATE_IDLE) {
|
|
||||||
this->actionFunc = func_80AA0F44;
|
|
||||||
play->msgCtx.ocarinaMode = OCARINA_MODE_04;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IS_RANDO) {
|
|
||||||
// Transition to the giving the song check on the next update run.
|
|
||||||
this->actionFunc = EnMa1_WaitForSongGive;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void func_80AA1150(EnMa1* this, PlayState* play) {
|
void func_80AA1150(EnMa1* this, PlayState* play) {
|
||||||
GET_PLAYER(play)->stateFlags2 |= 0x800000;
|
GET_PLAYER(play)->stateFlags2 |= 0x800000;
|
||||||
|
|
||||||
// When rando'ed, trigger the "song learned" Ocarina mode.
|
|
||||||
if (IS_RANDO && (Message_GetState(&play->msgCtx) == TEXT_STATE_CLOSING)) {
|
|
||||||
play->msgCtx.ocarinaMode = OCARINA_MODE_03;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (play->msgCtx.ocarinaMode == OCARINA_MODE_03) {
|
if (play->msgCtx.ocarinaMode == OCARINA_MODE_03) {
|
||||||
if (!IS_RANDO) {
|
Flags_SetRandomizerInf(RAND_INF_LEARNED_EPONA_SONG);
|
||||||
play->nextEntranceIndex = ENTR_LON_LON_RANCH_0;
|
play->nextEntranceIndex = ENTR_LON_LON_RANCH_0;
|
||||||
gSaveContext.nextCutsceneIndex = 0xFFF1;
|
gSaveContext.nextCutsceneIndex = 0xFFF1;
|
||||||
play->transitionType = TRANS_TYPE_CIRCLE(TCA_WAVE, TCC_WHITE, TCS_FAST);
|
play->transitionType = TRANS_TYPE_CIRCLE(TCA_WAVE, TCC_WHITE, TCS_FAST);
|
||||||
play->transitionTrigger = TRANS_TRIGGER_START;
|
play->transitionTrigger = TRANS_TRIGGER_START;
|
||||||
this->actionFunc = EnMa1_DoNothing;
|
this->actionFunc = EnMa1_DoNothing;
|
||||||
} else {
|
|
||||||
// When rando'ed, skip the cutscene, play the chime, reset some flags,
|
|
||||||
// and give the song on next update.
|
|
||||||
func_80078884(NA_SE_SY_CORRECT_CHIME);
|
|
||||||
this->actionFunc = EnMa1_EndTeachSong;
|
|
||||||
this->actor.flags &= ~ACTOR_FLAG_WILL_TALK;
|
|
||||||
play->msgCtx.ocarinaMode = OCARINA_MODE_00;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,4 +20,7 @@ typedef struct EnMa1 {
|
|||||||
/* 0x01E8 */ NpcInteractInfo interactInfo;
|
/* 0x01E8 */ NpcInteractInfo interactInfo;
|
||||||
} EnMa1; // size = 0x0210
|
} EnMa1; // size = 0x0210
|
||||||
|
|
||||||
|
void func_80AA106C(EnMa1* enMa1, PlayState* play);
|
||||||
|
void func_80AA0D88(EnMa1* enMa1, PlayState* play);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "z_en_md.h"
|
#include "z_en_md.h"
|
||||||
#include "objects/object_md/object_md.h"
|
#include "objects/object_md/object_md.h"
|
||||||
#include "overlays/actors/ovl_En_Elf/z_en_elf.h"
|
#include "overlays/actors/ovl_En_Elf/z_en_elf.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_NO_FREEZE_OCARINA)
|
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_NO_FREEZE_OCARINA)
|
||||||
|
|
||||||
@ -372,11 +373,7 @@ u16 EnMd_GetTextKokiriForest(PlayState* play, EnMd* this) {
|
|||||||
this->unk_208 = 0;
|
this->unk_208 = 0;
|
||||||
this->unk_209 = TEXT_STATE_NONE;
|
this->unk_209 = TEXT_STATE_NONE;
|
||||||
|
|
||||||
// In rando, skip talking about the tree being dead so we can have the prompt for sword and shield instead
|
if (GameInteractor_Should(GI_VB_MIDO_CONSIDER_DEKU_TREE_DEAD, CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD), this)) {
|
||||||
if ((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)) ||
|
|
||||||
(IS_RANDO && Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD) &&
|
|
||||||
Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE) &&
|
|
||||||
!Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH))) {
|
|
||||||
return 0x1045;
|
return 0x1045;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -486,25 +483,6 @@ s16 func_80AAAF04(PlayState* play, Actor* thisx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
u8 EnMd_ShouldSpawn(EnMd* this, PlayState* play) {
|
u8 EnMd_ShouldSpawn(EnMd* this, PlayState* play) {
|
||||||
// In rando, Mido's spawn logic is adjusted to support closed deku/forest options
|
|
||||||
// He will spawn in the forest if you haven't showed the sword and shield, and will remain
|
|
||||||
// in the forest until you've obtained Zelda's letter or Deku Tree dies
|
|
||||||
// This is to ensure Deku Tree can still be opened in dungeon entrance rando even if Ghoma is defeated
|
|
||||||
if (IS_RANDO) {
|
|
||||||
if (play->sceneNum == SCENE_LOST_WOODS) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD) &&
|
|
||||||
Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH) &&
|
|
||||||
(Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER) ||
|
|
||||||
Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD))) {
|
|
||||||
return play->sceneNum == SCENE_MIDOS_HOUSE && !LINK_IS_ADULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return play->sceneNum == SCENE_KOKIRI_FOREST;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (play->sceneNum == SCENE_KOKIRI_FOREST) {
|
if (play->sceneNum == SCENE_KOKIRI_FOREST) {
|
||||||
if (!Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH) && !Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER)) {
|
if (!Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH) && !Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER)) {
|
||||||
return 1;
|
return 1;
|
||||||
@ -512,7 +490,7 @@ u8 EnMd_ShouldSpawn(EnMd* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (play->sceneNum == SCENE_MIDOS_HOUSE) {
|
if (play->sceneNum == SCENE_MIDOS_HOUSE) {
|
||||||
if (((Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH)) != 0) || ((Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER)) != 0)) {
|
if (Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH) || Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER)) {
|
||||||
if (!LINK_IS_ADULT) {
|
if (!LINK_IS_ADULT) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -681,9 +659,8 @@ void EnMd_Init(Actor* thisx, PlayState* play) {
|
|||||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, FAIRY_KOKIRI);
|
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, FAIRY_KOKIRI);
|
||||||
|
|
||||||
if (((play->sceneNum == SCENE_KOKIRI_FOREST) && !Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD)) ||
|
if (((play->sceneNum == SCENE_KOKIRI_FOREST) && !Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD)) ||
|
||||||
((play->sceneNum == SCENE_KOKIRI_FOREST) && (Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD)) &&
|
((play->sceneNum == SCENE_KOKIRI_FOREST) && Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD) &&
|
||||||
((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)) ||
|
CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)) ||
|
||||||
(IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE)))) ||
|
|
||||||
((play->sceneNum == SCENE_LOST_WOODS) && !Flags_GetEventChkInf(EVENTCHKINF_PLAYED_SARIAS_SONG_FOR_MIDO_AS_ADULT))) {
|
((play->sceneNum == SCENE_LOST_WOODS) && !Flags_GetEventChkInf(EVENTCHKINF_PLAYED_SARIAS_SONG_FOR_MIDO_AS_ADULT))) {
|
||||||
this->actor.home.pos = this->actor.world.pos;
|
this->actor.home.pos = this->actor.world.pos;
|
||||||
this->actionFunc = func_80AAB948;
|
this->actionFunc = func_80AAB948;
|
||||||
@ -745,10 +722,11 @@ void func_80AAB948(EnMd* this, PlayState* play) {
|
|||||||
this->skelAnime.playSpeed = CLAMP(temp, 1.0f, 3.0f);
|
this->skelAnime.playSpeed = CLAMP(temp, 1.0f, 3.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->interactInfo.talkState == NPC_TALK_STATE_ACTION) {
|
if (
|
||||||
if ((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) ||
|
(GameInteractor_Should(GI_VB_MOVE_MIDO_IN_KOKIRI_FOREST, this->interactInfo.talkState == NPC_TALK_STATE_ACTION, this) && play->sceneNum == SCENE_KOKIRI_FOREST) ||
|
||||||
IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE) &&
|
this->interactInfo.talkState == NPC_TALK_STATE_ACTION
|
||||||
Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD)) && !Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH) &&
|
) {
|
||||||
|
if (CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) && !Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH) &&
|
||||||
(play->sceneNum == SCENE_KOKIRI_FOREST)) {
|
(play->sceneNum == SCENE_KOKIRI_FOREST)) {
|
||||||
play->msgCtx.msgMode = MSGMODE_PAUSED;
|
play->msgCtx.msgMode = MSGMODE_PAUSED;
|
||||||
}
|
}
|
||||||
@ -815,9 +793,7 @@ void func_80AABD0C(EnMd* this, PlayState* play) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((!IS_RANDO && CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) ||
|
if (CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) && !Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH) &&
|
||||||
IS_RANDO && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_DEKU_TREE) &&
|
|
||||||
Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD)) && !Flags_GetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH) &&
|
|
||||||
(play->sceneNum == SCENE_KOKIRI_FOREST)) {
|
(play->sceneNum == SCENE_KOKIRI_FOREST)) {
|
||||||
Message_CloseTextbox(play);
|
Message_CloseTextbox(play);
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH);
|
Flags_SetEventChkInf(EVENTCHKINF_SPOKE_TO_MIDO_AFTER_DEKU_TREES_DEATH);
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#include "z_en_mk.h"
|
#include "z_en_mk.h"
|
||||||
#include "objects/object_mk/object_mk.h"
|
#include "objects/object_mk/object_mk.h"
|
||||||
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED)
|
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED)
|
||||||
|
|
||||||
@ -93,37 +93,24 @@ void func_80AACA40(EnMk* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void func_80AACA94(EnMk* this, PlayState* play) {
|
void func_80AACA94(EnMk* this, PlayState* play) {
|
||||||
if (Actor_HasParent(&this->actor, play) != 0) {
|
if (Actor_HasParent(&this->actor, play) != 0 || !GameInteractor_Should(GI_VB_TRADE_FROG, true, this)) {
|
||||||
this->actor.parent = NULL;
|
this->actor.parent = NULL;
|
||||||
this->actionFunc = func_80AACA40;
|
this->actionFunc = func_80AACA40;
|
||||||
if (!IS_RANDO) {
|
Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_LH_TRADE_FROG);
|
||||||
|
if (GameInteractor_Should(GI_VB_TRADE_TIMER_EYEDROPS, true, NULL)) {
|
||||||
func_80088AA0(240);
|
func_80088AA0(240);
|
||||||
gSaveContext.eventInf[1] &= ~1;
|
gSaveContext.eventInf[1] &= ~1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (IS_RANDO) {
|
func_8002F434(&this->actor, play, GI_EYEDROPS, 10000.0f, 50.0f);
|
||||||
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LH_TRADE_FROG, GI_EYEDROPS);
|
|
||||||
Randomizer_ConsumeAdultTradeItem(play, ITEM_FROG);
|
|
||||||
GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f);
|
|
||||||
Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_LH_TRADE_FROG);
|
|
||||||
} else {
|
|
||||||
s32 getItemID = GI_EYEDROPS;
|
|
||||||
func_8002F434(&this->actor, play, getItemID, 10000.0f, 50.0f);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void func_80AACB14(EnMk* this, PlayState* play) {
|
void func_80AACB14(EnMk* this, PlayState* play) {
|
||||||
if (Actor_TextboxIsClosing(&this->actor, play)) {
|
if (Actor_TextboxIsClosing(&this->actor, play)) {
|
||||||
this->actionFunc = func_80AACA94;
|
this->actionFunc = func_80AACA94;
|
||||||
if (IS_RANDO) {
|
if (GameInteractor_Should(GI_VB_TRADE_FROG, true, this)) {
|
||||||
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LH_TRADE_FROG, GI_EYEDROPS);
|
func_8002F434(&this->actor, play, GI_EYEDROPS, 10000.0f, 50.0f);
|
||||||
Randomizer_ConsumeAdultTradeItem(play, ITEM_FROG);
|
|
||||||
GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f);
|
|
||||||
Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_LH_TRADE_FROG);
|
|
||||||
} else {
|
|
||||||
s32 getItemID = GI_EYEDROPS;
|
|
||||||
func_8002F434(&this->actor, play, getItemID, 10000.0f, 50.0f);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -150,7 +137,7 @@ void func_80AACC04(EnMk* this, PlayState* play) {
|
|||||||
if (this->timer > 0) {
|
if (this->timer > 0) {
|
||||||
this->timer--;
|
this->timer--;
|
||||||
} else {
|
} else {
|
||||||
this->timer = IS_RANDO ? 0 : 16;
|
this->timer = GameInteractor_Should(GI_VB_PLAY_EYEDROP_CREATION_ANIM, true, this) ? 16 : 0;
|
||||||
this->actionFunc = func_80AACBAC;
|
this->actionFunc = func_80AACBAC;
|
||||||
Animation_Change(&this->skelAnime, &object_mk_Anim_000D88, 1.0f, 0.0f,
|
Animation_Change(&this->skelAnime, &object_mk_Anim_000D88, 1.0f, 0.0f,
|
||||||
Animation_GetLastFrame(&object_mk_Anim_000D88), ANIMMODE_LOOP, -4.0f);
|
Animation_GetLastFrame(&object_mk_Anim_000D88), ANIMMODE_LOOP, -4.0f);
|
||||||
@ -163,7 +150,7 @@ void func_80AACCA0(EnMk* this, PlayState* play) {
|
|||||||
this->timer--;
|
this->timer--;
|
||||||
this->actor.shape.rot.y += 0x800;
|
this->actor.shape.rot.y += 0x800;
|
||||||
} else {
|
} else {
|
||||||
this->timer = IS_RANDO ? 0 : 120;
|
this->timer = GameInteractor_Should(GI_VB_PLAY_EYEDROP_CREATION_ANIM, true, this) ? 120 : 0;
|
||||||
this->actionFunc = func_80AACC04;
|
this->actionFunc = func_80AACC04;
|
||||||
Animation_Change(&this->skelAnime, &object_mk_Anim_000724, 1.0f, 0.0f,
|
Animation_Change(&this->skelAnime, &object_mk_Anim_000724, 1.0f, 0.0f,
|
||||||
Animation_GetLastFrame(&object_mk_Anim_000724), ANIMMODE_LOOP, -4.0f);
|
Animation_GetLastFrame(&object_mk_Anim_000724), ANIMMODE_LOOP, -4.0f);
|
||||||
@ -179,7 +166,7 @@ void func_80AACD48(EnMk* this, PlayState* play) {
|
|||||||
this->actionFunc = func_80AACCA0;
|
this->actionFunc = func_80AACCA0;
|
||||||
play->msgCtx.msgMode = MSGMODE_PAUSED;
|
play->msgCtx.msgMode = MSGMODE_PAUSED;
|
||||||
player->exchangeItemId = EXCH_ITEM_NONE;
|
player->exchangeItemId = EXCH_ITEM_NONE;
|
||||||
this->timer = IS_RANDO ? 0 : 16;
|
this->timer = GameInteractor_Should(GI_VB_PLAY_EYEDROP_CREATION_ANIM, true, this) ? 16 : 0;
|
||||||
Animation_Change(&this->skelAnime, &object_mk_Anim_000D88, 1.0f, 0.0f,
|
Animation_Change(&this->skelAnime, &object_mk_Anim_000D88, 1.0f, 0.0f,
|
||||||
Animation_GetLastFrame(&object_mk_Anim_000D88), ANIMMODE_LOOP, -4.0f);
|
Animation_GetLastFrame(&object_mk_Anim_000D88), ANIMMODE_LOOP, -4.0f);
|
||||||
this->flags &= ~2;
|
this->flags &= ~2;
|
||||||
@ -213,29 +200,20 @@ void func_80AACEE8(EnMk* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void func_80AACFA0(EnMk* this, PlayState* play) {
|
void func_80AACFA0(EnMk* this, PlayState* play) {
|
||||||
if (Actor_HasParent(&this->actor, play)) {
|
if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_LAB_DIVE, true, this)) {
|
||||||
this->actor.parent = NULL;
|
this->actor.parent = NULL;
|
||||||
this->actionFunc = func_80AACA40;
|
this->actionFunc = func_80AACA40;
|
||||||
Flags_SetItemGetInf(ITEMGETINF_10);
|
Flags_SetItemGetInf(ITEMGETINF_10);
|
||||||
} else {
|
} else {
|
||||||
// not sure when/how/if this is getting called
|
func_8002F434(&this->actor, play, GI_HEART_PIECE, 10000.0f, 50.0f);
|
||||||
if (!IS_RANDO) {
|
|
||||||
func_8002F434(&this->actor, play, GI_HEART_PIECE, 10000.0f, 50.0f);
|
|
||||||
} else {
|
|
||||||
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LH_LAB_DIVE, GI_HEART_PIECE);
|
|
||||||
GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void func_80AAD014(EnMk* this, PlayState* play) {
|
void func_80AAD014(EnMk* this, PlayState* play) {
|
||||||
if (Actor_TextboxIsClosing(&this->actor, play)) {
|
if (Actor_TextboxIsClosing(&this->actor, play)) {
|
||||||
this->actionFunc = func_80AACFA0;
|
this->actionFunc = func_80AACFA0;
|
||||||
if (!IS_RANDO) {
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_LAB_DIVE, true, this)) {
|
||||||
func_8002F434(&this->actor, play, GI_HEART_PIECE, 10000.0f, 50.0f);
|
func_8002F434(&this->actor, play, GI_HEART_PIECE, 10000.0f, 50.0f);
|
||||||
} else {
|
|
||||||
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LH_LAB_DIVE, GI_HEART_PIECE);
|
|
||||||
GiveItemEntryFromActor(&this->actor, play, getItemEntry, 10000.0f, 50.0f);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,9 +233,9 @@ void EnMk_Wait(EnMk* this, PlayState* play) {
|
|||||||
player->actor.textId = this->actor.textId;
|
player->actor.textId = this->actor.textId;
|
||||||
this->actionFunc = func_80AACA40;
|
this->actionFunc = func_80AACA40;
|
||||||
} else {
|
} else {
|
||||||
// Skip eye drop text on rando if Link went in the water, so you can still receive the dive check
|
if (GameInteractor_Should(GI_VB_USE_EYEDROP_DIALOGUE, (
|
||||||
if (INV_CONTENT(ITEM_ODD_MUSHROOM) == ITEM_EYEDROPS &&
|
INV_CONTENT(ITEM_ODD_MUSHROOM) == ITEM_EYEDROPS
|
||||||
(!IS_RANDO || this->swimFlag == 0)) {
|
), this)) {
|
||||||
player->actor.textId = 0x4032;
|
player->actor.textId = 0x4032;
|
||||||
this->actionFunc = func_80AACA40;
|
this->actionFunc = func_80AACA40;
|
||||||
} else {
|
} else {
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "z_en_ms.h"
|
#include "z_en_ms.h"
|
||||||
#include "objects/object_ms/object_ms.h"
|
#include "objects/object_ms/object_ms.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY)
|
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY)
|
||||||
|
|
||||||
@ -127,20 +128,16 @@ void EnMs_Talk(EnMs* this, PlayState* play) {
|
|||||||
} else if (Message_ShouldAdvance(play)) {
|
} else if (Message_ShouldAdvance(play)) {
|
||||||
switch (play->msgCtx.choiceIndex) {
|
switch (play->msgCtx.choiceIndex) {
|
||||||
case 0: // yes
|
case 0: // yes
|
||||||
if (gSaveContext.rupees <
|
if (!GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_MAGIC_BEANS_PURCHASE, (
|
||||||
((IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS))
|
gSaveContext.rupees >= sPrices[BEANS_BOUGHT]), this)) {
|
||||||
? 60
|
|
||||||
: sPrices[BEANS_BOUGHT])) {
|
|
||||||
Message_ContinueTextbox(play, 0x4069); // not enough rupees text
|
Message_ContinueTextbox(play, 0x4069); // not enough rupees text
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)) {
|
|
||||||
GiveItemEntryFromActor(&this->actor, play,
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_MAGIC_BEAN_SALESMAN, true, this)) {
|
||||||
Randomizer_GetItemFromKnownCheck(RC_ZR_MAGIC_BEAN_SALESMAN, GI_BEAN), 90.0f, 10.0f);
|
|
||||||
} else {
|
|
||||||
func_8002F434(&this->actor, play, GI_BEAN, 90.0f, 10.0f);
|
func_8002F434(&this->actor, play, GI_BEAN, 90.0f, 10.0f);
|
||||||
|
this->actionFunc = EnMs_Sell;
|
||||||
}
|
}
|
||||||
this->actionFunc = EnMs_Sell;
|
|
||||||
return;
|
return;
|
||||||
case 1: // no
|
case 1: // no
|
||||||
Message_ContinueTextbox(play, 0x4068);
|
Message_ContinueTextbox(play, 0x4068);
|
||||||
@ -152,23 +149,14 @@ void EnMs_Talk(EnMs* this, PlayState* play) {
|
|||||||
|
|
||||||
void EnMs_Sell(EnMs* this, PlayState* play) {
|
void EnMs_Sell(EnMs* this, PlayState* play) {
|
||||||
if (Actor_HasParent(&this->actor, play)) {
|
if (Actor_HasParent(&this->actor, play)) {
|
||||||
Rupees_ChangeBy((IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)) ? -60 : -sPrices[BEANS_BOUGHT]);
|
Rupees_ChangeBy(-sPrices[BEANS_BOUGHT]);
|
||||||
this->actor.parent = NULL;
|
this->actor.parent = NULL;
|
||||||
this->actionFunc =
|
this->actionFunc = EnMs_TalkAfterPurchase;
|
||||||
(IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)) ? EnMs_Wait : EnMs_TalkAfterPurchase;
|
|
||||||
} else {
|
} else {
|
||||||
if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)) {
|
GetItemEntry entry = ItemTable_Retrieve(GI_BEAN);
|
||||||
GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_ZR_MAGIC_BEAN_SALESMAN, GI_BEAN);
|
gSaveContext.pendingSaleMod = entry.modIndex;
|
||||||
gSaveContext.pendingSale = itemEntry.itemId;
|
gSaveContext.pendingSale = entry.itemId;
|
||||||
gSaveContext.pendingSaleMod = itemEntry.modIndex;
|
func_8002F434(&this->actor, play, GI_BEAN, 90.0f, 10.0f);
|
||||||
GiveItemEntryFromActor(&this->actor, play, itemEntry, 90.0f, 10.0f);
|
|
||||||
BEANS_BOUGHT = 10;
|
|
||||||
} else {
|
|
||||||
GetItemEntry entry = ItemTable_Retrieve(GI_BEAN);
|
|
||||||
gSaveContext.pendingSaleMod = entry.modIndex;
|
|
||||||
gSaveContext.pendingSale = entry.itemId;
|
|
||||||
func_8002F434(&this->actor, play, GI_BEAN, 90.0f, 10.0f);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,4 +18,7 @@ typedef struct EnMs {
|
|||||||
/* 0x024C */ s16 activeTimer;
|
/* 0x024C */ s16 activeTimer;
|
||||||
} EnMs; // size = 0x0250
|
} EnMs; // size = 0x0250
|
||||||
|
|
||||||
|
void EnMs_TalkAfterPurchase(EnMs* enMs, PlayState* play);
|
||||||
|
void EnMs_Wait(EnMs* enMs, PlayState* play);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "vt.h"
|
#include "vt.h"
|
||||||
#include "objects/object_nb/object_nb.h"
|
#include "objects/object_nb/object_nb.h"
|
||||||
#include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h"
|
#include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
|
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
|
||||||
|
|
||||||
@ -326,7 +327,9 @@ void EnNb_GiveMedallion(EnNb* this, PlayState* play) {
|
|||||||
|
|
||||||
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DEMO_EFFECT, posX, posY, posZ, 0, 0, 0,
|
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DEMO_EFFECT, posX, posY, posZ, 0, 0, 0,
|
||||||
0xC);
|
0xC);
|
||||||
Item_Give(play, ITEM_MEDALLION_SPIRIT);
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_SPIRIT_MEDALLION, true, NULL)) {
|
||||||
|
Item_Give(play, ITEM_MEDALLION_SPIRIT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnNb_ComeUpImpl(EnNb* this, PlayState* play) {
|
void EnNb_ComeUpImpl(EnNb* this, PlayState* play) {
|
||||||
@ -342,7 +345,9 @@ void EnNb_SetupChamberCsImpl(EnNb* this, PlayState* play) {
|
|||||||
this->action = NB_CHAMBER_UNDERGROUND;
|
this->action = NB_CHAMBER_UNDERGROUND;
|
||||||
play->csCtx.segment = &D_80AB431C;
|
play->csCtx.segment = &D_80AB431C;
|
||||||
gSaveContext.cutsceneTrigger = 2;
|
gSaveContext.cutsceneTrigger = 2;
|
||||||
Item_Give(play, ITEM_MEDALLION_SPIRIT);
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_SPIRIT_MEDALLION, true, NULL)) {
|
||||||
|
Item_Give(play, ITEM_MEDALLION_SPIRIT);
|
||||||
|
}
|
||||||
player->actor.world.rot.y = player->actor.shape.rot.y = this->actor.world.rot.y + 0x8000;
|
player->actor.world.rot.y = player->actor.shape.rot.y = this->actor.world.rot.y + 0x8000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#include "objects/object_os_anime/object_os_anime.h"
|
#include "objects/object_os_anime/object_os_anime.h"
|
||||||
#include "overlays/actors/ovl_En_Niw/z_en_niw.h"
|
#include "overlays/actors/ovl_En_Niw/z_en_niw.h"
|
||||||
#include "vt.h"
|
#include "vt.h"
|
||||||
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED)
|
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED)
|
||||||
|
|
||||||
@ -204,7 +204,9 @@ void func_80ABA244(EnNiwLady* this, PlayState* play) {
|
|||||||
EnNiw* currentCucco;
|
EnNiw* currentCucco;
|
||||||
s32 phi_s1;
|
s32 phi_s1;
|
||||||
|
|
||||||
this->cuccosInPen = IS_RANDO ? (7 - Randomizer_GetSettingValue(RSK_CUCCO_COUNT)) : 0;
|
if (GameInteractor_Should(GI_VB_SET_CUCCO_COUNT, true, this)) {
|
||||||
|
this->cuccosInPen = 0;
|
||||||
|
}
|
||||||
currentCucco = (EnNiw*)play->actorCtx.actorLists[ACTORCAT_PROP].head;
|
currentCucco = (EnNiw*)play->actorCtx.actorLists[ACTORCAT_PROP].head;
|
||||||
while (currentCucco != NULL) {
|
while (currentCucco != NULL) {
|
||||||
if (currentCucco->actor.id == ACTOR_EN_NIW) {
|
if (currentCucco->actor.id == ACTOR_EN_NIW) {
|
||||||
@ -239,9 +241,11 @@ void func_80ABA244(EnNiwLady* this, PlayState* play) {
|
|||||||
phi_s1 = 7;
|
phi_s1 = 7;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Completed minigame and then threw Cucco(s) out of the pen
|
||||||
if ((this->unk_26C != 0) && (phi_s1 < 7)) {
|
if ((this->unk_26C != 0) && (phi_s1 < 7)) {
|
||||||
phi_s1 = 9;
|
phi_s1 = 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->actor.textId = sMissingCuccoTextIds[phi_s1];
|
this->actor.textId = sMissingCuccoTextIds[phi_s1];
|
||||||
if (Text_GetFaceReaction(play, 8) != 0) {
|
if (Text_GetFaceReaction(play, 8) != 0) {
|
||||||
this->actor.textId = Text_GetFaceReaction(play, 8);
|
this->actor.textId = Text_GetFaceReaction(play, 8);
|
||||||
@ -308,16 +312,18 @@ void func_80ABA654(EnNiwLady* this, PlayState* play) {
|
|||||||
if (!Flags_GetItemGetInf(ITEMGETINF_0C)) {
|
if (!Flags_GetItemGetInf(ITEMGETINF_0C)) {
|
||||||
this->actor.parent = NULL;
|
this->actor.parent = NULL;
|
||||||
|
|
||||||
if (!IS_RANDO) {
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_ANJU_AS_CHILD, true, this)) {
|
||||||
this->getItemId = GI_BOTTLE;
|
this->getItemId = GI_BOTTLE;
|
||||||
func_8002F434(&this->actor, play, GI_BOTTLE, 100.0f, 50.0f);
|
func_8002F434(&this->actor, play, GI_BOTTLE, 100.0f, 50.0f);
|
||||||
} else {
|
} else {
|
||||||
this->getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_ANJU_AS_CHILD, GI_BOTTLE);
|
// Circumvent the item offer action
|
||||||
GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, 100.0f, 50.0f);
|
this->actionFunc = func_80ABAC84;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->actionFunc = func_80ABAC00;
|
this->actionFunc = func_80ABAC00;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
if (this->unk_26C == 1) {
|
if (this->unk_26C == 1) {
|
||||||
this->getItemId = GI_RUPEE_PURPLE;
|
this->getItemId = GI_RUPEE_PURPLE;
|
||||||
@ -398,15 +404,15 @@ void func_80ABA9B8(EnNiwLady* this, PlayState* play) {
|
|||||||
Message_CloseTextbox(play);
|
Message_CloseTextbox(play);
|
||||||
this->actor.parent = NULL;
|
this->actor.parent = NULL;
|
||||||
|
|
||||||
if (!IS_RANDO) {
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_ANJU_AS_ADULT, true, this)) {
|
||||||
func_8002F434(&this->actor, play, GI_POCKET_EGG, 200.0f, 100.0f);
|
func_8002F434(&this->actor, play, GI_POCKET_EGG, 200.0f, 100.0f);
|
||||||
|
this->actionFunc = func_80ABAC00;
|
||||||
} else {
|
} else {
|
||||||
this->getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_ANJU_AS_ADULT, GI_POCKET_EGG);
|
// Circumvent the item offer action
|
||||||
GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, 200.0f, 100.0f);
|
this->actionFunc = func_80ABAC84;
|
||||||
Flags_SetItemGetInf(ITEMGETINF_2C);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->actionFunc = func_80ABAC00;
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
this->actor.textId = sTradeItemTextIds[3];
|
this->actor.textId = sTradeItemTextIds[3];
|
||||||
@ -433,15 +439,14 @@ void func_80ABAB08(EnNiwLady* this, PlayState* play) {
|
|||||||
case 0:
|
case 0:
|
||||||
Message_CloseTextbox(play);
|
Message_CloseTextbox(play);
|
||||||
this->actor.parent = NULL;
|
this->actor.parent = NULL;
|
||||||
if (!IS_RANDO) {
|
if (GameInteractor_Should(GI_VB_TRADE_POCKET_CUCCO, true, this)) {
|
||||||
func_8002F434(&this->actor, play, GI_COJIRO, 200.0f, 100.0f);
|
func_8002F434(&this->actor, play, GI_COJIRO, 200.0f, 100.0f);
|
||||||
|
this->actionFunc = func_80ABAC00;
|
||||||
} else {
|
} else {
|
||||||
this->getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_TRADE_POCKET_CUCCO, GI_COJIRO);
|
// Circumvent the item offer action
|
||||||
Randomizer_ConsumeAdultTradeItem(play, ITEM_POCKET_CUCCO);
|
this->actionFunc = func_80ABAC84;
|
||||||
GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, 200.0f, 100.0f);
|
return;
|
||||||
Flags_SetItemGetInf(ITEMGETINF_2E);
|
|
||||||
}
|
}
|
||||||
this->actionFunc = func_80ABAC00;
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
Message_CloseTextbox(play);
|
Message_CloseTextbox(play);
|
||||||
@ -462,12 +467,6 @@ void func_80ABAC00(EnNiwLady* this, PlayState* play) {
|
|||||||
if (Actor_HasParent(&this->actor, play)) {
|
if (Actor_HasParent(&this->actor, play)) {
|
||||||
this->actionFunc = func_80ABAC84;
|
this->actionFunc = func_80ABAC84;
|
||||||
} else {
|
} else {
|
||||||
if (IS_RANDO) {
|
|
||||||
getItemId = this->getItemEntry.getItemId;
|
|
||||||
GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, 200.0f, 100.0f);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
getItemId = this->getItemId;
|
getItemId = this->getItemId;
|
||||||
if (LINK_IS_ADULT) {
|
if (LINK_IS_ADULT) {
|
||||||
getItemId = !Flags_GetItemGetInf(ITEMGETINF_2C) ? GI_POCKET_EGG : GI_COJIRO;
|
getItemId = !Flags_GetItemGetInf(ITEMGETINF_2C) ? GI_POCKET_EGG : GI_COJIRO;
|
||||||
@ -482,8 +481,7 @@ void func_80ABAC84(EnNiwLady* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 正常終了 ☆☆☆☆☆ \n" VT_RST);
|
osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 正常終了 ☆☆☆☆☆ \n" VT_RST);
|
||||||
if (LINK_IS_ADULT) {
|
if (LINK_IS_ADULT) {
|
||||||
// Flags for randomizer gives are set in the original message prompt choice handling
|
if (GameInteractor_Should(GI_VB_ANJU_SET_OBTAINED_TRADE_ITEM, true, this)) {
|
||||||
if (!IS_RANDO) {
|
|
||||||
if (!Flags_GetItemGetInf(ITEMGETINF_2C)) {
|
if (!Flags_GetItemGetInf(ITEMGETINF_2C)) {
|
||||||
Flags_SetItemGetInf(ITEMGETINF_2C);
|
Flags_SetItemGetInf(ITEMGETINF_2C);
|
||||||
} else {
|
} else {
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "scenes/overworld/spot16/spot16_scene.h"
|
#include "scenes/overworld/spot16/spot16_scene.h"
|
||||||
#include "vt.h"
|
#include "vt.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED)
|
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED)
|
||||||
|
|
||||||
@ -42,6 +43,7 @@ void func_80ACAF74(EnOwl* this, PlayState* play);
|
|||||||
void func_80ACC30C(EnOwl* this, PlayState* play);
|
void func_80ACC30C(EnOwl* this, PlayState* play);
|
||||||
void func_80ACB4FC(EnOwl* this, PlayState* play);
|
void func_80ACB4FC(EnOwl* this, PlayState* play);
|
||||||
void func_80ACB680(EnOwl* this, PlayState* play);
|
void func_80ACB680(EnOwl* this, PlayState* play);
|
||||||
|
void func_80ACA62C(EnOwl* this, PlayState* play);
|
||||||
void func_80ACC460(EnOwl* this);
|
void func_80ACC460(EnOwl* this);
|
||||||
void func_80ACBEA0(EnOwl*, PlayState*);
|
void func_80ACBEA0(EnOwl*, PlayState*);
|
||||||
|
|
||||||
@ -137,9 +139,7 @@ void EnOwl_Init(Actor* thisx, PlayState* play) {
|
|||||||
// "conversation owl %4x no = %d, sv = %d"
|
// "conversation owl %4x no = %d, sv = %d"
|
||||||
osSyncPrintf(VT_FGCOL(CYAN) " 会話フクロウ %4x no = %d, sv = %d\n" VT_RST, this->actor.params, owlType, switchFlag);
|
osSyncPrintf(VT_FGCOL(CYAN) " 会話フクロウ %4x no = %d, sv = %d\n" VT_RST, this->actor.params, owlType, switchFlag);
|
||||||
|
|
||||||
if (((owlType != OWL_DEFAULT) && (switchFlag < 0x20) && Flags_GetSwitch(play, switchFlag)) ||
|
if ((owlType != OWL_DEFAULT) && (switchFlag < 0x20) && Flags_GetSwitch(play, switchFlag)) {
|
||||||
// Owl shortcuts at SPOT06: Lake Hylia and SPOT16: Death Mountain Trail
|
|
||||||
(IS_RANDO && !(play->sceneNum == SCENE_LAKE_HYLIA || play->sceneNum == SCENE_DEATH_MOUNTAIN_TRAIL))) {
|
|
||||||
osSyncPrintf("savebitでフクロウ退避\n"); // "Save owl with savebit"
|
osSyncPrintf("savebitでフクロウ退避\n"); // "Save owl with savebit"
|
||||||
Actor_Kill(&this->actor);
|
Actor_Kill(&this->actor);
|
||||||
return;
|
return;
|
||||||
@ -283,7 +283,7 @@ s32 EnOwl_CheckInitTalk(EnOwl* this, PlayState* play, u16 textId, f32 targetDist
|
|||||||
} else {
|
} else {
|
||||||
this->actor.textId = textId;
|
this->actor.textId = textId;
|
||||||
distCheck = (flags & 2) ? 200.0f : 1000.0f;
|
distCheck = (flags & 2) ? 200.0f : 1000.0f;
|
||||||
if (this->actor.xzDistToPlayer < targetDist) {
|
if (GameInteractor_Should(GI_VB_OWL_INTERACTION, this->actor.xzDistToPlayer < targetDist, this)) {
|
||||||
this->actor.flags |= ACTOR_FLAG_WILL_TALK;
|
this->actor.flags |= ACTOR_FLAG_WILL_TALK;
|
||||||
func_8002F1C4(&this->actor, play, targetDist, distCheck, 0);
|
func_8002F1C4(&this->actor, play, targetDist, distCheck, 0);
|
||||||
}
|
}
|
||||||
|
@ -43,4 +43,6 @@ typedef struct EnOwl {
|
|||||||
/* 0x0410 */ OwlFunc unk_410;
|
/* 0x0410 */ OwlFunc unk_410;
|
||||||
} EnOwl; // size = 0x0414
|
} EnOwl; // size = 0x0414
|
||||||
|
|
||||||
|
void func_80ACA62C(EnOwl* enOwl, PlayState* play);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "z_en_rl.h"
|
#include "z_en_rl.h"
|
||||||
#include "vt.h"
|
#include "vt.h"
|
||||||
#include "objects/object_rl/object_rl.h"
|
#include "objects/object_rl/object_rl.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
|
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
|
||||||
|
|
||||||
@ -126,7 +127,9 @@ void func_80AE7590(EnRl* this, PlayState* play) {
|
|||||||
pos.y = player->actor.world.pos.y + 80.0f;
|
pos.y = player->actor.world.pos.y + 80.0f;
|
||||||
pos.z = player->actor.world.pos.z;
|
pos.z = player->actor.world.pos.z;
|
||||||
Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT, pos.x, pos.y, pos.z, 0, 0, 0, 0xE, true);
|
Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT, pos.x, pos.y, pos.z, 0, 0, 0, 0xE, true);
|
||||||
Item_Give(play, ITEM_MEDALLION_LIGHT);
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_LIGHT_MEDALLION, true, NULL)) {
|
||||||
|
Item_Give(play, ITEM_MEDALLION_LIGHT);
|
||||||
|
}
|
||||||
this->lightMedallionGiven = 1;
|
this->lightMedallionGiven = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "objects/object_ru2/object_ru2.h"
|
#include "objects/object_ru2/object_ru2.h"
|
||||||
#include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h"
|
#include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h"
|
||||||
#include "vt.h"
|
#include "vt.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
|
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
|
||||||
|
|
||||||
@ -260,7 +261,9 @@ void func_80AF2A38(EnRu2* this, PlayState* play) {
|
|||||||
f32 posZ = player->actor.world.pos.z;
|
f32 posZ = player->actor.world.pos.z;
|
||||||
|
|
||||||
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DEMO_EFFECT, posX, posY, posZ, 0, 0, 0, 10);
|
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DEMO_EFFECT, posX, posY, posZ, 0, 0, 0, 10);
|
||||||
Item_Give(play, ITEM_MEDALLION_WATER);
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_WATER_MEDALLION, true, NULL)) {
|
||||||
|
Item_Give(play, ITEM_MEDALLION_WATER);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void func_80AF2AB4(EnRu2* this, PlayState* play) {
|
void func_80AF2AB4(EnRu2* this, PlayState* play) {
|
||||||
@ -273,7 +276,9 @@ void func_80AF2AB4(EnRu2* this, PlayState* play) {
|
|||||||
this->action = 1;
|
this->action = 1;
|
||||||
play->csCtx.segment = &D_80AF411C;
|
play->csCtx.segment = &D_80AF411C;
|
||||||
gSaveContext.cutsceneTrigger = 2;
|
gSaveContext.cutsceneTrigger = 2;
|
||||||
Item_Give(play, ITEM_MEDALLION_WATER);
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_WATER_MEDALLION, true, NULL)) {
|
||||||
|
Item_Give(play, ITEM_MEDALLION_WATER);
|
||||||
|
}
|
||||||
temp = this->actor.world.rot.y + 0x8000;
|
temp = this->actor.world.rot.y + 0x8000;
|
||||||
player->actor.shape.rot.y = temp;
|
player->actor.shape.rot.y = temp;
|
||||||
player->actor.world.rot.y = temp;
|
player->actor.world.rot.y = temp;
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "objects/object_sa/object_sa.h"
|
#include "objects/object_sa/object_sa.h"
|
||||||
#include "scenes/overworld/spot04/spot04_scene.h"
|
#include "scenes/overworld/spot04/spot04_scene.h"
|
||||||
#include "scenes/overworld/spot05/spot05_scene.h"
|
#include "scenes/overworld/spot05/spot05_scene.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_NO_FREEZE_OCARINA)
|
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_NO_FREEZE_OCARINA)
|
||||||
|
|
||||||
@ -390,13 +391,10 @@ s32 func_80AF5DFC(EnSa* this, PlayState* play) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (play->sceneNum == SCENE_SACRED_FOREST_MEADOW && (Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER))) {
|
if (play->sceneNum == SCENE_SACRED_FOREST_MEADOW && (Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER))) {
|
||||||
if (IS_RANDO) {
|
return GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_SARIAS_SONG, !CHECK_QUEST_ITEM(QUEST_SONG_SARIA), NULL) ? 5 : 2;
|
||||||
return 5;
|
|
||||||
}
|
|
||||||
return CHECK_QUEST_ITEM(QUEST_SONG_SARIA) ? 2 : 5;
|
|
||||||
}
|
}
|
||||||
if (play->sceneNum == SCENE_KOKIRI_FOREST && !CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)) {
|
if (play->sceneNum == SCENE_KOKIRI_FOREST && !CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)) {
|
||||||
if (Flags_GetInfTable(INFTABLE_GREETED_BY_SARIA)) {
|
if (GameInteractor_Should(GI_VB_NOT_BE_GREETED_BY_SARIA, Flags_GetInfTable(INFTABLE_GREETED_BY_SARIA), NULL)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 4;
|
return 4;
|
||||||
@ -622,28 +620,17 @@ void func_80AF67D0(EnSa* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GivePlayerRandoRewardSaria(EnSa* saria, PlayState* play, RandomizerCheck check) {
|
|
||||||
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, RG_SARIAS_SONG);
|
|
||||||
if (saria->actor.parent != NULL && saria->actor.parent->id == GET_PLAYER(play)->actor.id &&
|
|
||||||
!Flags_GetTreasure(play, 0x1F)) {
|
|
||||||
Flags_SetTreasure(play, 0x1F);
|
|
||||||
} else if (!Flags_GetTreasure(play, 0x1F)) {
|
|
||||||
GiveItemEntryFromActor(&saria->actor, play, getItemEntry, 10000.0f, 100.0f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void func_80AF683C(EnSa* this, PlayState* play) {
|
void func_80AF683C(EnSa* this, PlayState* play) {
|
||||||
Player* player = GET_PLAYER(play);
|
Player* player = GET_PLAYER(play);
|
||||||
|
|
||||||
if (!(player->actor.world.pos.z >= -2220.0f) && !Play_InCsMode(play)) {
|
if (!(player->actor.world.pos.z >= -2220.0f) && !Play_InCsMode(play)) {
|
||||||
if (IS_RANDO) {
|
// SOH [General] This flag was previously unused, but was named accordingly so we will make use of it. (Normally we should opt for soh_inf)
|
||||||
GivePlayerRandoRewardSaria(this, play, RC_SONG_FROM_SARIA);
|
Flags_SetEventChkInf(EVENTCHKINF_LEARNED_SARIAS_SONG);
|
||||||
return;
|
if (GameInteractor_Should(GI_VB_PLAY_SARIAS_SONG_CS, true, this)) {
|
||||||
|
play->csCtx.segment = SEGMENTED_TO_VIRTUAL(spot05_scene_Cs_005730);
|
||||||
|
gSaveContext.cutsceneTrigger = 1;
|
||||||
|
this->actionFunc = func_80AF68E4;
|
||||||
}
|
}
|
||||||
|
|
||||||
play->csCtx.segment = SEGMENTED_TO_VIRTUAL(spot05_scene_Cs_005730);
|
|
||||||
gSaveContext.cutsceneTrigger = 1;
|
|
||||||
this->actionFunc = func_80AF68E4;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -721,7 +708,9 @@ void func_80AF68E4(EnSa* this, PlayState* play) {
|
|||||||
|
|
||||||
void func_80AF6B20(EnSa* this, PlayState* play) {
|
void func_80AF6B20(EnSa* this, PlayState* play) {
|
||||||
if (play->sceneNum == SCENE_SACRED_FOREST_MEADOW) {
|
if (play->sceneNum == SCENE_SACRED_FOREST_MEADOW) {
|
||||||
Item_Give(play, ITEM_SONG_SARIA);
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_SARIAS_SONG, true, NULL)) {
|
||||||
|
Item_Give(play, ITEM_SONG_SARIA);
|
||||||
|
}
|
||||||
EnSa_ChangeAnim(this, ENSA_ANIM1_6);
|
EnSa_ChangeAnim(this, ENSA_ANIM1_6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,4 +30,6 @@ typedef struct EnSa {
|
|||||||
/* 0x0286 */ Vec3s morphTable[17];
|
/* 0x0286 */ Vec3s morphTable[17];
|
||||||
} EnSa; // size = 0x02EC
|
} EnSa; // size = 0x02EC
|
||||||
|
|
||||||
|
void func_80AF6B20(EnSa* enSa, PlayState* play);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "z_en_shopnuts.h"
|
#include "z_en_shopnuts.h"
|
||||||
#include "objects/object_shopnuts/object_shopnuts.h"
|
#include "objects/object_shopnuts/object_shopnuts.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE)
|
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOSTILE)
|
||||||
|
|
||||||
@ -69,18 +70,11 @@ void EnShopnuts_Init(Actor* thisx, PlayState* play) {
|
|||||||
CollisionCheck_SetInfo(&this->actor.colChkInfo, NULL, &sColChkInfoInit);
|
CollisionCheck_SetInfo(&this->actor.colChkInfo, NULL, &sColChkInfoInit);
|
||||||
Collider_UpdateCylinder(&this->actor, &this->collider);
|
Collider_UpdateCylinder(&this->actor, &this->collider);
|
||||||
|
|
||||||
if (IS_RANDO) {
|
if (GameInteractor_Should(GI_VB_BUSINESS_SCRUB_DESPAWN,
|
||||||
s16 respawnData = gSaveContext.respawn[RESPAWN_MODE_RETURN].data & ((1 << 8) - 1);
|
((this->actor.params == 0x0002) && (Flags_GetItemGetInf(ITEMGETINF_0B))) ||
|
||||||
ScrubIdentity scrubIdentity = Randomizer_IdentifyScrub(play->sceneNum, this->actor.params, respawnData);
|
|
||||||
|
|
||||||
if (scrubIdentity.isShuffled && Flags_GetRandomizerInf(scrubIdentity.randomizerInf)) {
|
|
||||||
Actor_Kill(&this->actor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (((this->actor.params == 0x0002) && (Flags_GetItemGetInf(ITEMGETINF_0B))) ||
|
|
||||||
((this->actor.params == 0x0009) && (Flags_GetInfTable(INFTABLE_192))) ||
|
((this->actor.params == 0x0009) && (Flags_GetInfTable(INFTABLE_192))) ||
|
||||||
((this->actor.params == 0x000A) && (Flags_GetInfTable(INFTABLE_193)))) {
|
((this->actor.params == 0x000A) && (Flags_GetInfTable(INFTABLE_193))),
|
||||||
|
this)) {
|
||||||
Actor_Kill(&this->actor);
|
Actor_Kill(&this->actor);
|
||||||
} else {
|
} else {
|
||||||
EnShopnuts_SetupWait(this);
|
EnShopnuts_SetupWait(this);
|
||||||
|
@ -7,9 +7,6 @@
|
|||||||
#include "z_en_si.h"
|
#include "z_en_si.h"
|
||||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
extern void func_8083C148(Player*, PlayState*);
|
|
||||||
extern void func_80078884(uint16_t);
|
|
||||||
|
|
||||||
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOOKSHOT_DRAGS)
|
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_HOOKSHOT_DRAGS)
|
||||||
|
|
||||||
void EnSi_Init(Actor* thisx, PlayState* play);
|
void EnSi_Init(Actor* thisx, PlayState* play);
|
||||||
@ -21,13 +18,6 @@ s32 func_80AFB748(EnSi* this, PlayState* play);
|
|||||||
void func_80AFB768(EnSi* this, PlayState* play);
|
void func_80AFB768(EnSi* this, PlayState* play);
|
||||||
void func_80AFB89C(EnSi* this, PlayState* play);
|
void func_80AFB89C(EnSi* this, PlayState* play);
|
||||||
void func_80AFB950(EnSi* this, PlayState* play);
|
void func_80AFB950(EnSi* this, PlayState* play);
|
||||||
void Randomizer_UpdateSkullReward(EnSi* this, PlayState* play);
|
|
||||||
void Randomizer_GiveSkullReward(EnSi* this, PlayState* play);
|
|
||||||
|
|
||||||
s32 textId = 0xB4;
|
|
||||||
s32 giveItemId = ITEM_SKULL_TOKEN;
|
|
||||||
s32 getItemId;
|
|
||||||
GetItemEntry getItem;
|
|
||||||
|
|
||||||
static ColliderCylinderInit sCylinderInit = {
|
static ColliderCylinderInit sCylinderInit = {
|
||||||
{
|
{
|
||||||
@ -104,36 +94,12 @@ void func_80AFB768(EnSi* this, PlayState* play) {
|
|||||||
|
|
||||||
if (this->collider.base.ocFlags2 & OC2_HIT_PLAYER) {
|
if (this->collider.base.ocFlags2 & OC2_HIT_PLAYER) {
|
||||||
this->collider.base.ocFlags2 &= ~OC2_HIT_PLAYER;
|
this->collider.base.ocFlags2 &= ~OC2_HIT_PLAYER;
|
||||||
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_SKULL_TOKEN, true, this)) {
|
||||||
if (IS_RANDO) {
|
Item_Give(play, ITEM_SKULL_TOKEN);
|
||||||
Randomizer_UpdateSkullReward(this, play);
|
|
||||||
} else {
|
|
||||||
Item_Give(play, giveItemId);
|
|
||||||
}
|
|
||||||
if ((!CVarGetInteger("gSkulltulaFreeze", 0) || giveItemId != ITEM_SKULL_TOKEN) &&
|
|
||||||
getItemId != RG_ICE_TRAP) {
|
|
||||||
player->actor.freezeTimer = 20;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getItemId == RG_ICE_TRAP && Message_GetState(&play->msgCtx) != TEXT_STATE_CLOSING) {
|
|
||||||
player->actor.freezeTimer = 10;
|
player->actor.freezeTimer = 10;
|
||||||
}
|
Message_StartTextbox(play, 0xB4, NULL);
|
||||||
|
|
||||||
Message_StartTextbox(play, textId, NULL);
|
|
||||||
|
|
||||||
if (IS_RANDO) {
|
|
||||||
if (getItemId != RG_ICE_TRAP) {
|
|
||||||
Randomizer_GiveSkullReward(this, play);
|
|
||||||
Audio_PlayFanfare_Rando(getItem);
|
|
||||||
} else {
|
|
||||||
gSaveContext.pendingIceTrapCount++;
|
|
||||||
Audio_PlayFanfare(NA_BGM_SMALL_ITEM_GET);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Audio_PlayFanfare(NA_BGM_SMALL_ITEM_GET);
|
Audio_PlayFanfare(NA_BGM_SMALL_ITEM_GET);
|
||||||
}
|
}
|
||||||
|
|
||||||
player->getItemEntry = (GetItemEntry)GET_ITEM_NONE;
|
|
||||||
this->actionFunc = func_80AFB950;
|
this->actionFunc = func_80AFB950;
|
||||||
} else {
|
} else {
|
||||||
Collider_UpdateCylinder(&this->actor, &this->collider);
|
Collider_UpdateCylinder(&this->actor, &this->collider);
|
||||||
@ -146,32 +112,18 @@ void func_80AFB768(EnSi* this, PlayState* play) {
|
|||||||
|
|
||||||
void func_80AFB89C(EnSi* this, PlayState* play) {
|
void func_80AFB89C(EnSi* this, PlayState* play) {
|
||||||
Player* player = GET_PLAYER(play);
|
Player* player = GET_PLAYER(play);
|
||||||
|
|
||||||
Math_SmoothStepToF(&this->actor.scale.x, 0.25f, 0.4f, 1.0f, 0.0f);
|
Math_SmoothStepToF(&this->actor.scale.x, 0.25f, 0.4f, 1.0f, 0.0f);
|
||||||
Actor_SetScale(&this->actor, this->actor.scale.x);
|
Actor_SetScale(&this->actor, this->actor.scale.x);
|
||||||
this->actor.shape.rot.y += 0x400;
|
this->actor.shape.rot.y += 0x400;
|
||||||
|
|
||||||
if (!CHECK_FLAG_ALL(this->actor.flags, ACTOR_FLAG_HOOKSHOT_ATTACHED)) {
|
if (!CHECK_FLAG_ALL(this->actor.flags, ACTOR_FLAG_HOOKSHOT_ATTACHED)) {
|
||||||
if (IS_RANDO) {
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_SKULL_TOKEN, true, this)) {
|
||||||
Randomizer_UpdateSkullReward(this, play);
|
Item_Give(play, ITEM_SKULL_TOKEN);
|
||||||
} else {
|
player->actor.freezeTimer = 10;
|
||||||
Item_Give(play, giveItemId);
|
Message_StartTextbox(play, 0xB4, NULL);
|
||||||
}
|
|
||||||
|
|
||||||
Message_StartTextbox(play, textId, NULL);
|
|
||||||
|
|
||||||
if (IS_RANDO) {
|
|
||||||
if (getItemId != RG_ICE_TRAP) {
|
|
||||||
Randomizer_GiveSkullReward(this, play);
|
|
||||||
Audio_PlayFanfare_Rando(getItem);
|
|
||||||
} else {
|
|
||||||
gSaveContext.pendingIceTrapCount++;
|
|
||||||
Audio_PlayFanfare(NA_BGM_SMALL_ITEM_GET);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Audio_PlayFanfare(NA_BGM_SMALL_ITEM_GET);
|
Audio_PlayFanfare(NA_BGM_SMALL_ITEM_GET);
|
||||||
}
|
}
|
||||||
|
|
||||||
player->getItemEntry = (GetItemEntry)GET_ITEM_NONE;
|
|
||||||
this->actionFunc = func_80AFB950;
|
this->actionFunc = func_80AFB950;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -179,19 +131,12 @@ void func_80AFB89C(EnSi* this, PlayState* play) {
|
|||||||
void func_80AFB950(EnSi* this, PlayState* play) {
|
void func_80AFB950(EnSi* this, PlayState* play) {
|
||||||
Player* player = GET_PLAYER(play);
|
Player* player = GET_PLAYER(play);
|
||||||
|
|
||||||
if (Message_GetState(&play->msgCtx) != TEXT_STATE_CLOSING &&
|
if (Message_GetState(&play->msgCtx) != TEXT_STATE_CLOSING && GameInteractor_Should(GI_VB_GIVE_ITEM_SKULL_TOKEN, true, this)) {
|
||||||
(!CVarGetInteger("gSkulltulaFreeze", 0) || getItemId == RG_ICE_TRAP || giveItemId != ITEM_SKULL_TOKEN)) {
|
|
||||||
player->actor.freezeTimer = 10;
|
player->actor.freezeTimer = 10;
|
||||||
} else {
|
} else {
|
||||||
SET_GS_FLAGS((this->actor.params & 0x1F00) >> 8, this->actor.params & 0xFF);
|
SET_GS_FLAGS((this->actor.params & 0x1F00) >> 8, this->actor.params & 0xFF);
|
||||||
GameInteractor_ExecuteOnFlagSet(FLAG_GS_TOKEN, this->actor.params);
|
GameInteractor_ExecuteOnFlagSet(FLAG_GS_TOKEN, this->actor.params);
|
||||||
Actor_Kill(&this->actor);
|
Actor_Kill(&this->actor);
|
||||||
if (gSaveContext.pendingIceTrapCount > 0 && player->heldItemId == 11) {
|
|
||||||
player->actor.freezeTimer = 0;
|
|
||||||
func_8083C148(GET_PLAYER(play), play);
|
|
||||||
func_80078884(NA_SE_SY_CAMERA_ZOOM_UP);
|
|
||||||
player->currentYaw = player->actor.shape.rot.y;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,44 +155,6 @@ void EnSi_Draw(Actor* thisx, PlayState* play) {
|
|||||||
if (this->actionFunc != func_80AFB950) {
|
if (this->actionFunc != func_80AFB950) {
|
||||||
func_8002ED80(&this->actor, play, 0);
|
func_8002ED80(&this->actor, play, 0);
|
||||||
func_8002EBCC(&this->actor, play, 0);
|
func_8002EBCC(&this->actor, play, 0);
|
||||||
if (!IS_RANDO) {
|
GetItem_Draw(play, GID_SKULL_TOKEN_2);
|
||||||
GetItem_Draw(play, GID_SKULL_TOKEN_2);
|
|
||||||
} else {
|
|
||||||
getItem = Randomizer_GetItemFromActor(this->actor.id, play->sceneNum, this->actor.params, GI_SKULL_TOKEN);
|
|
||||||
EnItem00_CustomItemsParticles(&this->actor, play, getItem);
|
|
||||||
if (getItem.itemId != ITEM_SKULL_TOKEN) {
|
|
||||||
f32 mtxScale = 1.5f;
|
|
||||||
Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY);
|
|
||||||
}
|
|
||||||
GetItemEntry_Draw(play, getItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Randomizer_UpdateSkullReward(EnSi* this, PlayState* play) {
|
|
||||||
Player* player = GET_PLAYER(play);
|
|
||||||
|
|
||||||
getItem = Randomizer_GetItemFromActor(this->actor.id, play->sceneNum, this->actor.params, GI_SKULL_TOKEN);
|
|
||||||
getItemId = getItem.getItemId;
|
|
||||||
if (getItemId == RG_ICE_TRAP) {
|
|
||||||
textId = 0xF8;
|
|
||||||
} else {
|
|
||||||
textId = getItem.textId;
|
|
||||||
giveItemId = getItem.itemId;
|
|
||||||
}
|
|
||||||
player->getItemEntry = getItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Randomizer_GiveSkullReward(EnSi* this, PlayState* play) {
|
|
||||||
Player* player = GET_PLAYER(play);
|
|
||||||
|
|
||||||
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(play, giveItemId);
|
|
||||||
} else if (getItem.modIndex == MOD_RANDOMIZER) {
|
|
||||||
Randomizer_Item_Give(play, getItem);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,9 @@ typedef struct EnSi {
|
|||||||
/* 0x014C */ EnSiActionFunc actionFunc;
|
/* 0x014C */ EnSiActionFunc actionFunc;
|
||||||
/* 0x0150 */ ColliderCylinder collider;
|
/* 0x0150 */ ColliderCylinder collider;
|
||||||
/* 0x019C */ u8 unk_19C;
|
/* 0x019C */ u8 unk_19C;
|
||||||
|
// #region SOH [Randomizer] Caching the get item entry for the draw function for performance
|
||||||
|
/* */ GetItemEntry sohGetItemEntry;
|
||||||
|
// #endregion
|
||||||
} EnSi; // size = 0x01A0
|
} EnSi; // size = 0x01A0
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "z_en_ta.h"
|
#include "z_en_ta.h"
|
||||||
#include "vt.h"
|
#include "vt.h"
|
||||||
#include "objects/object_ta/object_ta.h"
|
#include "objects/object_ta/object_ta.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY)
|
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY)
|
||||||
|
|
||||||
@ -466,7 +467,7 @@ void func_80B14B6C(EnTa* this, PlayState* play) {
|
|||||||
func_80B13AA0(this, func_80B14AF4, func_80B167C0);
|
func_80B13AA0(this, func_80B14AF4, func_80B167C0);
|
||||||
this->unk_2CC = 5;
|
this->unk_2CC = 5;
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE);
|
Flags_SetEventChkInf(EVENTCHKINF_TALON_RETURNED_FROM_CASTLE);
|
||||||
if (IS_RANDO) {
|
if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) {
|
||||||
OnePointCutscene_EndCutscene(play, csCamIdx);
|
OnePointCutscene_EndCutscene(play, csCamIdx);
|
||||||
}
|
}
|
||||||
Animation_PlayOnce(&this->skelAnime, &gTalonRunTransitionAnim);
|
Animation_PlayOnce(&this->skelAnime, &gTalonRunTransitionAnim);
|
||||||
|
@ -8,12 +8,9 @@
|
|||||||
#include "objects/gameplay_keep/gameplay_keep.h"
|
#include "objects/gameplay_keep/gameplay_keep.h"
|
||||||
#include "objects/object_tk/object_tk.h"
|
#include "objects/object_tk/object_tk.h"
|
||||||
#include "soh/frame_interpolation.h"
|
#include "soh/frame_interpolation.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY)
|
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY)
|
||||||
#define COLLECTFLAG_GRAVEDIGGING_HEART_PIECE 0x19
|
|
||||||
#define ITEMGETINFFLAG_GRAVEDIGGING_HEART_PIECE 0x1000
|
|
||||||
|
|
||||||
bool heartPieceSpawned;
|
|
||||||
|
|
||||||
void EnTk_Init(Actor* thisx, PlayState* play);
|
void EnTk_Init(Actor* thisx, PlayState* play);
|
||||||
void EnTk_Destroy(Actor* thisx, PlayState* play);
|
void EnTk_Destroy(Actor* thisx, PlayState* play);
|
||||||
@ -408,10 +405,6 @@ s32 EnTk_ChooseReward(EnTk* this) {
|
|||||||
f32 luck;
|
f32 luck;
|
||||||
s32 reward;
|
s32 reward;
|
||||||
|
|
||||||
if ((IS_RANDO || CVarGetInteger("gDampeWin", 0)) && !Flags_GetCollectible(gPlayState, COLLECTFLAG_GRAVEDIGGING_HEART_PIECE) && this->heartPieceSpawned == 0) {
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
luck = Rand_ZeroOne();
|
luck = Rand_ZeroOne();
|
||||||
|
|
||||||
if (luck < 0.4f) {
|
if (luck < 0.4f) {
|
||||||
@ -502,12 +495,7 @@ void EnTk_Init(Actor* thisx, PlayState* play) {
|
|||||||
|
|
||||||
CollisionCheck_SetInfo2(&this->actor.colChkInfo, NULL, &sColChkInfoInit);
|
CollisionCheck_SetInfo2(&this->actor.colChkInfo, NULL, &sColChkInfoInit);
|
||||||
|
|
||||||
if (CVarGetInteger("gDampeAllNight", 0)) {
|
if (GameInteractor_Should(GI_VB_DAMPE_IN_GRAVEYARD_DESPAWN, gSaveContext.dayTime <= 0xC000 || gSaveContext.dayTime >= 0xE000 || LINK_IS_ADULT || play->sceneNum != SCENE_GRAVEYARD, this)) {
|
||||||
if (!!LINK_IS_ADULT || play->sceneNum != SCENE_GRAVEYARD) {
|
|
||||||
Actor_Kill(&this->actor);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (gSaveContext.dayTime <= 0xC000 || gSaveContext.dayTime >= 0xE000 || !!LINK_IS_ADULT || play->sceneNum != SCENE_GRAVEYARD) {
|
|
||||||
Actor_Kill(&this->actor);
|
Actor_Kill(&this->actor);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -519,7 +507,6 @@ void EnTk_Init(Actor* thisx, PlayState* play) {
|
|||||||
this->currentReward = -1;
|
this->currentReward = -1;
|
||||||
this->currentSpot = NULL;
|
this->currentSpot = NULL;
|
||||||
this->actionFunc = EnTk_Rest;
|
this->actionFunc = EnTk_Rest;
|
||||||
heartPieceSpawned = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnTk_Destroy(Actor* thisx, PlayState* play) {
|
void EnTk_Destroy(Actor* thisx, PlayState* play) {
|
||||||
@ -599,7 +586,11 @@ void EnTk_Dig(EnTk* this, PlayState* play) {
|
|||||||
Vec3f rewardOrigin;
|
Vec3f rewardOrigin;
|
||||||
Vec3f rewardPos;
|
Vec3f rewardPos;
|
||||||
s32 rewardParams[] = {
|
s32 rewardParams[] = {
|
||||||
ITEM00_RUPEE_GREEN, ITEM00_RUPEE_BLUE, ITEM00_RUPEE_RED, ITEM00_RUPEE_PURPLE, ITEM00_HEART_PIECE,
|
ITEM00_RUPEE_GREEN, ITEM00_RUPEE_BLUE, ITEM00_RUPEE_RED, ITEM00_RUPEE_PURPLE,
|
||||||
|
// #region SOH [General] Typically this heart piece would have no collectible flag set when it's picked up, but for both randomizer
|
||||||
|
// and gGravediggingTourFix we want to set one, and rely on it instead of the ItemGetInf flag that is set when the heart is spawned
|
||||||
|
((COLLECTFLAG_GRAVEDIGGING_HEART_PIECE & 0x3F) << 8) | ITEM00_HEART_PIECE,
|
||||||
|
// #endregion
|
||||||
};
|
};
|
||||||
|
|
||||||
EnTk_DigEff(this);
|
EnTk_DigEff(this);
|
||||||
@ -610,7 +601,7 @@ void EnTk_Dig(EnTk* this, PlayState* play) {
|
|||||||
|
|
||||||
this->rewardTimer = 0;
|
this->rewardTimer = 0;
|
||||||
|
|
||||||
if (this->validDigHere == 1 || IS_RANDO || CVarGetInteger("gDampeWin", 0)) {
|
if (GameInteractor_Should(GI_VB_BE_VALID_GRAVEDIGGING_SPOT, this->validDigHere == 1, this)) {
|
||||||
rewardOrigin.x = 0.0f;
|
rewardOrigin.x = 0.0f;
|
||||||
rewardOrigin.y = 0.0f;
|
rewardOrigin.y = 0.0f;
|
||||||
rewardOrigin.z = -40.0f;
|
rewardOrigin.z = -40.0f;
|
||||||
@ -624,51 +615,24 @@ void EnTk_Dig(EnTk* this, PlayState* play) {
|
|||||||
|
|
||||||
this->currentReward = EnTk_ChooseReward(this);
|
this->currentReward = EnTk_ChooseReward(this);
|
||||||
|
|
||||||
if (this->currentReward == 3) {
|
if (GameInteractor_Should(GI_VB_BE_DAMPE_GRAVEDIGGING_GRAND_PRIZE, this->currentReward == 3, this)) {
|
||||||
if (IS_RANDO || CVarGetInteger("gDampeWin", 0)) {
|
|
||||||
/*
|
|
||||||
* Upgrade the purple rupee reward to the heart piece if this
|
|
||||||
* is the first grand prize dig.
|
|
||||||
*/
|
|
||||||
if (!Flags_GetItemGetInf(ITEMGETINF_1C) && !(IS_RANDO || CVarGetInteger("gDampeWin", 0))) {
|
|
||||||
Flags_SetItemGetInf(ITEMGETINF_1C);
|
|
||||||
this->currentReward = 4;
|
|
||||||
} else if ((IS_RANDO || CVarGetInteger("gDampeWin", 0)) && !Flags_GetCollectible(gPlayState, COLLECTFLAG_GRAVEDIGGING_HEART_PIECE) && this->heartPieceSpawned == 0) {
|
|
||||||
this->currentReward = 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
* Upgrade the purple rupee reward to the heart piece if this
|
* Upgrade the purple rupee reward to the heart piece if this
|
||||||
* is the first grand prize dig.
|
* is the first grand prize dig.
|
||||||
*/
|
*/
|
||||||
// If vanilla itemGetInf flag is not set, it's impossible for the new flag to be set, so return true.
|
if (GameInteractor_Should(GI_VB_DAMPE_GRAVEDIGGING_GRAND_PRIZE_BE_HEART_PIECE, !Flags_GetItemGetInf(ITEMGETINF_1C), this)) {
|
||||||
// Otherwise if the gGravediggingTourFix is enabled and the new flag hasn't been set, return true.
|
Flags_SetItemGetInf(ITEMGETINF_1C);
|
||||||
// If true, spawn the heart piece and set the vanilla itemGetInf flag and new temp clear flag.
|
|
||||||
if (!heartPieceSpawned &&
|
|
||||||
(!(gSaveContext.itemGetInf[1] & ITEMGETINFFLAG_GRAVEDIGGING_HEART_PIECE) ||
|
|
||||||
CVarGetInteger("gGravediggingTourFix", 0) &&
|
|
||||||
!Flags_GetCollectible(play, COLLECTFLAG_GRAVEDIGGING_HEART_PIECE))) {
|
|
||||||
this->currentReward = 4;
|
this->currentReward = 4;
|
||||||
gSaveContext.itemGetInf[1] |= ITEMGETINFFLAG_GRAVEDIGGING_HEART_PIECE;
|
|
||||||
heartPieceSpawned = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_RANDO && this->currentReward == 4) {
|
Item_DropCollectible(play, &rewardPos, rewardParams[this->currentReward]);
|
||||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ITEM00, rewardPos.x, rewardPos.y, rewardPos.z, 0, 0, 0, 0x1906, true);
|
|
||||||
this->heartPieceSpawned = 1;
|
|
||||||
} else {
|
|
||||||
EnItem00* reward = Item_DropCollectible(play, &rewardPos, rewardParams[this->currentReward]);
|
|
||||||
if (this->currentReward == 4) {
|
|
||||||
reward->collectibleFlag = COLLECTFLAG_GRAVEDIGGING_HEART_PIECE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->skelAnime.curFrame >= 32.0f && this->rewardTimer == 10) {
|
if (this->skelAnime.curFrame >= 32.0f && this->rewardTimer == 10) {
|
||||||
/* Play a reward sound shortly after digging */
|
/* Play a reward sound shortly after digging */
|
||||||
if (!(IS_RANDO || CVarGetInteger("gDampeWin", 0)) && this->validDigHere == 0) {
|
if (this->validDigHere == 0) {
|
||||||
/* Bad dig spot */
|
/* Bad dig spot */
|
||||||
Audio_PlayActorSound2(&this->actor, NA_SE_SY_ERROR);
|
Audio_PlayActorSound2(&this->actor, NA_SE_SY_ERROR);
|
||||||
} else if (this->currentReward == 4) {
|
} else if (this->currentReward == 4) {
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
/* Dirt particle effect */
|
/* Dirt particle effect */
|
||||||
struct EnTkEff;
|
struct EnTkEff;
|
||||||
|
|
||||||
|
#define COLLECTFLAG_GRAVEDIGGING_HEART_PIECE 0x19
|
||||||
|
|
||||||
typedef struct EnTkEff {
|
typedef struct EnTkEff {
|
||||||
/* 0x0000 */ u8 active;
|
/* 0x0000 */ u8 active;
|
||||||
/* 0x0001 */ u8 timeLeft;
|
/* 0x0001 */ u8 timeLeft;
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#include "z_en_toryo.h"
|
#include "z_en_toryo.h"
|
||||||
#include "objects/object_toryo/object_toryo.h"
|
#include "objects/object_toryo/object_toryo.h"
|
||||||
#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY)
|
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY)
|
||||||
|
|
||||||
@ -291,10 +291,7 @@ void func_80B20768(EnToryo* this, PlayState* play) {
|
|||||||
s16 sp32;
|
s16 sp32;
|
||||||
s16 sp30;
|
s16 sp30;
|
||||||
|
|
||||||
// Animation Count should be no more than 1 to guarantee putaway is complete after giving the saw
|
if (this->unk_1E4 == 3 && !GameInteractor_Should(GI_VB_FIX_SAW_SOFTLOCK, false, NULL)) {
|
||||||
// As this is vanilla behavior, it only applies with the Fix toggle or Skip Text enabled.
|
|
||||||
bool checkAnim = (CVarGetInteger("gFixSawSoftlock", 0) != 0 || CVarGetInteger("gSkipText", 0) != 0) ? play->animationCtx.animationCount <= 1 : true;
|
|
||||||
if (this->unk_1E4 == 3 && checkAnim) {
|
|
||||||
Actor_ProcessTalkRequest(&this->actor, play);
|
Actor_ProcessTalkRequest(&this->actor, play);
|
||||||
Message_ContinueTextbox(play, this->actor.textId);
|
Message_ContinueTextbox(play, this->actor.textId);
|
||||||
this->unk_1E4 = 1;
|
this->unk_1E4 = 1;
|
||||||
@ -315,19 +312,12 @@ void func_80B20768(EnToryo* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this->unk_1E4 == 4) {
|
if (this->unk_1E4 == 4) {
|
||||||
if (Actor_HasParent(&this->actor, play)) {
|
if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_TRADE_SAW, true, this)) {
|
||||||
this->actor.parent = NULL;
|
this->actor.parent = NULL;
|
||||||
this->unk_1E4 = 5;
|
this->unk_1E4 = 5;
|
||||||
|
Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_GV_TRADE_SAW);
|
||||||
} else {
|
} else {
|
||||||
if (IS_RANDO) {
|
func_8002F434(&this->actor, play, GI_SWORD_BROKEN, 100.0f, 10.0f);
|
||||||
GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_GV_TRADE_SAW, GI_SWORD_BROKEN);
|
|
||||||
Randomizer_ConsumeAdultTradeItem(play, ITEM_SAW);
|
|
||||||
GiveItemEntryFromActor(&this->actor, play, itemEntry, 100.0f, 10.0f);
|
|
||||||
Flags_SetRandomizerInf(RAND_INF_ADULT_TRADES_GV_TRADE_SAW);
|
|
||||||
} else {
|
|
||||||
s32 itemId = GI_SWORD_BROKEN;
|
|
||||||
func_8002F434(&this->actor, play, itemId, 100.0f, 10.0f);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "z_en_wonder_talk2.h"
|
#include "z_en_wonder_talk2.h"
|
||||||
#include "vt.h"
|
#include "vt.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_NO_LOCKON)
|
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_NO_LOCKON)
|
||||||
|
|
||||||
@ -194,7 +195,9 @@ void func_80B3A3D4(EnWonderTalk2* this, PlayState* play) {
|
|||||||
this->unk_15A = true;
|
this->unk_15A = true;
|
||||||
}
|
}
|
||||||
this->actor.flags &= ~(ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UPDATE_WHILE_CULLED);
|
this->actor.flags &= ~(ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UPDATE_WHILE_CULLED);
|
||||||
func_8002DF54(play, NULL, 7);
|
if (GameInteractor_Should(GI_VB_WONDER_TALK, true, this)) {
|
||||||
|
func_8002DF54(play, NULL, 7);
|
||||||
|
}
|
||||||
this->unk_156 = true;
|
this->unk_156 = true;
|
||||||
this->actionFunc = func_80B3A4F8;
|
this->actionFunc = func_80B3A4F8;
|
||||||
break;
|
break;
|
||||||
@ -252,42 +255,12 @@ void func_80B3A4F8(EnWonderTalk2* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
this->unk_158 = 0;
|
this->unk_158 = 0;
|
||||||
if (!this->unk_156) {
|
if (!this->unk_156) {
|
||||||
// Whether or not to skip the text in rando
|
if (GameInteractor_Should(GI_VB_WONDER_TALK, true, this)) {
|
||||||
bool randoSkipText = false;
|
|
||||||
if (IS_RANDO) {
|
|
||||||
// Scenes for which all of this type of wonder talk should be skipped.
|
|
||||||
switch (play->sceneNum) {
|
|
||||||
case SCENE_SHADOW_TEMPLE: // Shadow Temple
|
|
||||||
randoSkipText = true;
|
|
||||||
break;
|
|
||||||
case SCENE_GERUDO_TRAINING_GROUND: // Gerudo Training Grounds
|
|
||||||
randoSkipText = true;
|
|
||||||
break;
|
|
||||||
case SCENE_THIEVES_HIDEOUT: // Inside Gerudo Fortress
|
|
||||||
randoSkipText = true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// individual textIds that should be skipped, or that should be preserved
|
|
||||||
// in a scene that otherwise has all wonder talk skipped.
|
|
||||||
//switch (this->actor.textId) {
|
|
||||||
// case: 0x023c //textId we want to skip
|
|
||||||
// randoSkipText = true;
|
|
||||||
// break;
|
|
||||||
// case 0x023c: // textId in a skipped scene that we don't want to skip
|
|
||||||
// randoSkipText = false;
|
|
||||||
// break;
|
|
||||||
// default:
|
|
||||||
// break;
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
if (!(randoSkipText)) {
|
|
||||||
Message_StartTextbox(play, this->actor.textId, NULL);
|
Message_StartTextbox(play, this->actor.textId, NULL);
|
||||||
func_8002DF54(play, NULL, 8);
|
func_8002DF54(play, NULL, 8);
|
||||||
this->actor.flags |= ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UPDATE_WHILE_CULLED;
|
|
||||||
this->actionFunc = func_80B3A3D4;
|
|
||||||
}
|
}
|
||||||
|
this->actor.flags |= ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UPDATE_WHILE_CULLED;
|
||||||
|
this->actionFunc = func_80B3A3D4;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "scenes/indoors/tokinoma/tokinoma_scene.h"
|
#include "scenes/indoors/tokinoma/tokinoma_scene.h"
|
||||||
#include "scenes/dungeons/ice_doukutu/ice_doukutu_scene.h"
|
#include "scenes/dungeons/ice_doukutu/ice_doukutu_scene.h"
|
||||||
#include "vt.h"
|
#include "vt.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
|
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
|
||||||
|
|
||||||
@ -277,6 +278,7 @@ void func_80B3C9EC(EnXc* this) {
|
|||||||
this->action = SHEIK_ACTION_BLOCK_PEDESTAL;
|
this->action = SHEIK_ACTION_BLOCK_PEDESTAL;
|
||||||
this->drawMode = SHEIK_DRAW_DEFAULT;
|
this->drawMode = SHEIK_DRAW_DEFAULT;
|
||||||
this->unk_30C = 1;
|
this->unk_30C = 1;
|
||||||
|
// SOH [Randomizer] We don't want sheik blocking the pedestal in randomizer
|
||||||
if (IS_RANDO) {
|
if (IS_RANDO) {
|
||||||
Actor_Kill(&this->actor);
|
Actor_Kill(&this->actor);
|
||||||
}
|
}
|
||||||
@ -292,24 +294,6 @@ void func_80B3CA38(EnXc* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GivePlayerRandoRewardSheikSong(EnXc* sheik, PlayState* play, RandomizerCheck check, int sheikType, GetItemID ogSongId) {
|
|
||||||
Player* player = GET_PLAYER(play);
|
|
||||||
if (!(gSaveContext.eventChkInf[5] & sheikType)) {
|
|
||||||
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, ogSongId);
|
|
||||||
if (check == RC_SHEIK_AT_TEMPLE && !Flags_GetTreasure(play, 0x1F)) {
|
|
||||||
if (GiveItemEntryFromActor(&sheik->actor, play, getItemEntry, 10000.0f, 100.0f)) {
|
|
||||||
player->pendingFlag.flagID = 0x1F;
|
|
||||||
player->pendingFlag.flagType = FLAG_SCENE_TREASURE;
|
|
||||||
}
|
|
||||||
} else if (check != RC_SHEIK_AT_TEMPLE) {
|
|
||||||
if (GiveItemEntryFromActor(&sheik->actor, play, getItemEntry, 10000.0f, 100.0f)) {
|
|
||||||
player->pendingFlag.flagID = (0x5 << 4) | (sheikType & 0xF) >> 1;
|
|
||||||
player->pendingFlag.flagType = FLAG_EVENT_CHECK_INF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
s32 EnXc_MinuetCS(EnXc* this, PlayState* play) {
|
s32 EnXc_MinuetCS(EnXc* this, PlayState* play) {
|
||||||
if (this->actor.params == SHEIK_TYPE_MINUET) {
|
if (this->actor.params == SHEIK_TYPE_MINUET) {
|
||||||
Player* player = GET_PLAYER(play);
|
Player* player = GET_PLAYER(play);
|
||||||
@ -317,16 +301,17 @@ s32 EnXc_MinuetCS(EnXc* this, PlayState* play) {
|
|||||||
|
|
||||||
if (z < -2225.0f) {
|
if (z < -2225.0f) {
|
||||||
if (!Play_InCsMode(play)) {
|
if (!Play_InCsMode(play)) {
|
||||||
if (!IS_RANDO) {
|
if (GameInteractor_Should(GI_VB_PLAY_MINUET_OF_FOREST_CS, true, NULL)) {
|
||||||
play->csCtx.segment = SEGMENTED_TO_VIRTUAL(&gMinuetCs);
|
play->csCtx.segment = SEGMENTED_TO_VIRTUAL(&gMinuetCs);
|
||||||
gSaveContext.cutsceneTrigger = 1;
|
gSaveContext.cutsceneTrigger = 1;
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_LEARNED_MINUET_OF_FOREST);
|
|
||||||
Item_Give(play, ITEM_SONG_MINUET);
|
|
||||||
} else {
|
|
||||||
GivePlayerRandoRewardSheikSong(this, play, RC_SHEIK_IN_FOREST, 1, RG_MINUET_OF_FOREST);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return true;
|
Flags_SetEventChkInf(EVENTCHKINF_LEARNED_MINUET_OF_FOREST);
|
||||||
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_MINUET_OF_FOREST, true, NULL)) {
|
||||||
|
Item_Give(play, ITEM_SONG_MINUET);
|
||||||
|
}
|
||||||
|
if (GameInteractor_Should(GI_VB_PLAY_MINUET_OF_FOREST_CS, true, NULL)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -353,16 +338,17 @@ s32 EnXc_BoleroCS(EnXc* this, PlayState* play) {
|
|||||||
if ((posRot->pos.x > -784.0f) && (posRot->pos.x < -584.0f) && (posRot->pos.y > 447.0f) &&
|
if ((posRot->pos.x > -784.0f) && (posRot->pos.x < -584.0f) && (posRot->pos.y > 447.0f) &&
|
||||||
(posRot->pos.y < 647.0f) && (posRot->pos.z > -446.0f) && (posRot->pos.z < -246.0f) &&
|
(posRot->pos.y < 647.0f) && (posRot->pos.z > -446.0f) && (posRot->pos.z < -246.0f) &&
|
||||||
!Play_InCsMode(play)) {
|
!Play_InCsMode(play)) {
|
||||||
if (!IS_RANDO) {
|
if (GameInteractor_Should(GI_VB_PLAY_BOLERO_OF_FIRE_CS, true, NULL)) {
|
||||||
play->csCtx.segment = SEGMENTED_TO_VIRTUAL(&gDeathMountainCraterBoleroCs);
|
play->csCtx.segment = SEGMENTED_TO_VIRTUAL(&gDeathMountainCraterBoleroCs);
|
||||||
gSaveContext.cutsceneTrigger = 1;
|
gSaveContext.cutsceneTrigger = 1;
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_LEARNED_BOLERO_OF_FIRE);
|
|
||||||
Item_Give(play, ITEM_SONG_BOLERO);
|
|
||||||
} else {
|
|
||||||
GivePlayerRandoRewardSheikSong(this, play, RC_SHEIK_IN_CRATER, 2, RG_BOLERO_OF_FIRE);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return true;
|
Flags_SetEventChkInf(EVENTCHKINF_LEARNED_BOLERO_OF_FIRE);
|
||||||
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_BOLERO_OF_FIRE, true, NULL)) {
|
||||||
|
Item_Give(play, ITEM_SONG_BOLERO);
|
||||||
|
}
|
||||||
|
if (GameInteractor_Should(GI_VB_PLAY_BOLERO_OF_FIRE_CS, true, NULL)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -370,13 +356,8 @@ s32 EnXc_BoleroCS(EnXc* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EnXc_SetupSerenadeAction(EnXc* this, PlayState* play) {
|
void EnXc_SetupSerenadeAction(EnXc* this, PlayState* play) {
|
||||||
if (IS_RANDO) {
|
|
||||||
this->action = SHEIK_ACTION_SERENADE;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Player is adult and does not have iron boots and has not learned Serenade
|
// Player is adult and does not have iron boots and has not learned Serenade
|
||||||
if ((!CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER)) && LINK_IS_ADULT) {
|
if (GameInteractor_Should(GI_VB_SHIEK_PREPARE_TO_GIVE_SERENADE_OF_WATER, (!CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER)) && LINK_IS_ADULT, NULL)) {
|
||||||
this->action = SHEIK_ACTION_SERENADE;
|
this->action = SHEIK_ACTION_SERENADE;
|
||||||
osSyncPrintf("水のセレナーデ シーク誕生!!!!!!!!!!!!!!!!!!\n");
|
osSyncPrintf("水のセレナーデ シーク誕生!!!!!!!!!!!!!!!!!!\n");
|
||||||
} else {
|
} else {
|
||||||
@ -389,22 +370,20 @@ s32 EnXc_SerenadeCS(EnXc* this, PlayState* play) {
|
|||||||
if (this->actor.params == SHEIK_TYPE_SERENADE) {
|
if (this->actor.params == SHEIK_TYPE_SERENADE) {
|
||||||
Player* player = GET_PLAYER(play);
|
Player* player = GET_PLAYER(play);
|
||||||
s32 stateFlags = player->stateFlags1;
|
s32 stateFlags = player->stateFlags1;
|
||||||
|
if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_SERENADE_OF_WATER, CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER), NULL) &&
|
||||||
if (((CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, EQUIP_INV_BOOTS_IRON) && !IS_RANDO) ||
|
!(stateFlags & PLAYER_STATE1_IN_CUTSCENE) && !Play_InCsMode(play)) {
|
||||||
(Flags_GetTreasure(play, 2) && IS_RANDO)) &&
|
if (GameInteractor_Should(GI_VB_PLAY_SERENADE_OF_WATER_CS, true, NULL)) {
|
||||||
!Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER) && !(stateFlags & 0x20000000) &&
|
|
||||||
!Play_InCsMode(play)) {
|
|
||||||
if (!IS_RANDO) {
|
|
||||||
Cutscene_SetSegment(play, &gIceCavernSerenadeCs);
|
Cutscene_SetSegment(play, &gIceCavernSerenadeCs);
|
||||||
gSaveContext.cutsceneTrigger = 1;
|
gSaveContext.cutsceneTrigger = 1;
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER); // Learned Serenade of Water Flag
|
}
|
||||||
|
Flags_SetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER); // Learned Serenade of Water Flag
|
||||||
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_SERENADE_OF_WATER, true, NULL)) {
|
||||||
Item_Give(play, ITEM_SONG_SERENADE);
|
Item_Give(play, ITEM_SONG_SERENADE);
|
||||||
} else {
|
|
||||||
GivePlayerRandoRewardSheikSong(this, play, RC_SHEIK_IN_ICE_CAVERN, 4, RG_SERENADE_OF_WATER);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
osSyncPrintf("ブーツを取った!!!!!!!!!!!!!!!!!!\n");
|
osSyncPrintf("ブーツを取った!!!!!!!!!!!!!!!!!!\n");
|
||||||
return true;
|
if (GameInteractor_Should(GI_VB_PLAY_SERENADE_OF_WATER_CS, true, NULL)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
osSyncPrintf("はやくブーツを取るべし!!!!!!!!!!!!!!!!!!\n");
|
osSyncPrintf("はやくブーツを取るべし!!!!!!!!!!!!!!!!!!\n");
|
||||||
return false;
|
return false;
|
||||||
@ -415,7 +394,7 @@ s32 EnXc_SerenadeCS(EnXc* this, PlayState* play) {
|
|||||||
void EnXc_DoNothing(EnXc* this, PlayState* play) {
|
void EnXc_DoNothing(EnXc* this, PlayState* play) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnXc_RandoStand(EnXc* this, PlayState* play) {
|
void SoH_EnXc_RandoStand(EnXc* this, PlayState* play) {
|
||||||
//Replaces Ganondorf Light Arrow hint. also stands in ToT
|
//Replaces Ganondorf Light Arrow hint. also stands in ToT
|
||||||
if (play->sceneNum == SCENE_TEMPLE_OF_TIME) {
|
if (play->sceneNum == SCENE_TEMPLE_OF_TIME) {
|
||||||
EnXc_ChangeAnimation(this, &gSheikArmsCrossedIdleAnim, ANIMMODE_LOOP, 0.0f, false);
|
EnXc_ChangeAnimation(this, &gSheikArmsCrossedIdleAnim, ANIMMODE_LOOP, 0.0f, false);
|
||||||
@ -2209,22 +2188,21 @@ void EnXc_InitTempleOfTime(EnXc* this, PlayState* play) {
|
|||||||
if (LINK_IS_ADULT) {
|
if (LINK_IS_ADULT) {
|
||||||
if (!Flags_GetEventChkInf(EVENTCHKINF_SHEIK_SPAWNED_AT_MASTER_SWORD_PEDESTAL)) {
|
if (!Flags_GetEventChkInf(EVENTCHKINF_SHEIK_SPAWNED_AT_MASTER_SWORD_PEDESTAL)) {
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_SHEIK_SPAWNED_AT_MASTER_SWORD_PEDESTAL);
|
Flags_SetEventChkInf(EVENTCHKINF_SHEIK_SPAWNED_AT_MASTER_SWORD_PEDESTAL);
|
||||||
play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gTempleOfTimeFirstAdultCs);
|
if (GameInteractor_Should(GI_VB_PLAY_SHIEK_BLOCK_MASTER_SWORD_CS, true, NULL)) {
|
||||||
gSaveContext.cutsceneTrigger = 1;
|
play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gTempleOfTimeFirstAdultCs);
|
||||||
|
gSaveContext.cutsceneTrigger = 1;
|
||||||
|
}
|
||||||
func_80B3EBF0(this, play);
|
func_80B3EBF0(this, play);
|
||||||
} else if ((!Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && (Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP)) &&
|
} else if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_PRELUDE_OF_LIGHT, !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP), NULL)) {
|
||||||
!IS_RANDO) ||
|
Flags_SetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT);
|
||||||
(!Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST) &&
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_PRELUDE_OF_LIGHT, true, NULL)) {
|
||||||
IS_RANDO)) {
|
|
||||||
if (!IS_RANDO) {
|
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT);
|
|
||||||
Item_Give(play, ITEM_SONG_PRELUDE);
|
Item_Give(play, ITEM_SONG_PRELUDE);
|
||||||
|
}
|
||||||
|
if (GameInteractor_Should(GI_VB_PLAY_PRELUDE_OF_LIGHT_CS, true, NULL)) {
|
||||||
play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gTempleOfTimePreludeCs);
|
play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gTempleOfTimePreludeCs);
|
||||||
gSaveContext.cutsceneTrigger = 1;
|
gSaveContext.cutsceneTrigger = 1;
|
||||||
this->action = SHEIK_ACTION_30;
|
|
||||||
} else {
|
|
||||||
GivePlayerRandoRewardSheikSong(this, play, RC_SHEIK_AT_TEMPLE, 0x20, RG_PRELUDE_OF_LIGHT);
|
|
||||||
}
|
}
|
||||||
|
this->action = SHEIK_ACTION_30; // Not sure what this does exactly
|
||||||
} else if (!Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT)) {
|
} else if (!Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT)) {
|
||||||
func_80B3C9EC(this);
|
func_80B3C9EC(this);
|
||||||
} else {
|
} else {
|
||||||
@ -2378,14 +2356,6 @@ void EnXc_Update(Actor* thisx, PlayState* play) {
|
|||||||
EnXc* this = (EnXc*)thisx;
|
EnXc* this = (EnXc*)thisx;
|
||||||
s32 action = this->action;
|
s32 action = this->action;
|
||||||
|
|
||||||
if (this->actor.params == SHEIK_TYPE_9) {
|
|
||||||
if (IS_RANDO && LINK_IS_ADULT) {
|
|
||||||
if (CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST) && !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT)) {
|
|
||||||
GivePlayerRandoRewardSheikSong(this, play, RC_SHEIK_AT_TEMPLE, 0x20, RG_PRELUDE_OF_LIGHT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((action < 0) || (action >= ARRAY_COUNT(sActionFuncs)) || (sActionFuncs[action] == NULL)) {
|
if ((action < 0) || (action >= ARRAY_COUNT(sActionFuncs)) || (sActionFuncs[action] == NULL)) {
|
||||||
osSyncPrintf(VT_FGCOL(RED) "メインモードがおかしい!!!!!!!!!!!!!!!!!!!!!!!!!\n" VT_RST);
|
osSyncPrintf(VT_FGCOL(RED) "メインモードがおかしい!!!!!!!!!!!!!!!!!!!!!!!!!\n" VT_RST);
|
||||||
} else {
|
} else {
|
||||||
@ -2433,7 +2403,7 @@ void EnXc_Init(Actor* thisx, PlayState* play) {
|
|||||||
EnXc_DoNothing(this, play);
|
EnXc_DoNothing(this, play);
|
||||||
break;
|
break;
|
||||||
case SHEIK_TYPE_RANDO:
|
case SHEIK_TYPE_RANDO:
|
||||||
EnXc_RandoStand(this, play);
|
SoH_EnXc_RandoStand(this, play);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
osSyncPrintf(VT_FGCOL(RED) " En_Oa2 の arg_data がおかしい!!!!!!!!!!!!!!!!!!!!!!!!!\n" VT_RST);
|
osSyncPrintf(VT_FGCOL(RED) " En_Oa2 の arg_data がおかしい!!!!!!!!!!!!!!!!!!!!!!!!!\n" VT_RST);
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h"
|
#include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h"
|
||||||
#include "objects/object_zl2/object_zl2.h"
|
#include "objects/object_zl2/object_zl2.h"
|
||||||
#include "objects/object_zl2_anime1/object_zl2_anime1.h"
|
#include "objects/object_zl2_anime1/object_zl2_anime1.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
|
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
|
||||||
|
|
||||||
@ -633,7 +634,9 @@ void EnZl2_GiveLightArrows(EnZl2* this, PlayState* play) {
|
|||||||
posY = player->actor.world.pos.y + 80.0f;
|
posY = player->actor.world.pos.y + 80.0f;
|
||||||
posZ = player->actor.world.pos.z;
|
posZ = player->actor.world.pos.z;
|
||||||
Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT, posX, posY, posZ, 0, 0, 0, 0x17, true);
|
Actor_Spawn(&play->actorCtx, play, ACTOR_DEMO_EFFECT, posX, posY, posZ, 0, 0, 0, 0x17, true);
|
||||||
Item_Give(play, ITEM_ARROW_LIGHT);
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_LIGHT_ARROW, true, NULL)) {
|
||||||
|
Item_Give(play, ITEM_ARROW_LIGHT);
|
||||||
|
}
|
||||||
this->unk_244 = 1;
|
this->unk_244 = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "z_en_zl4.h"
|
#include "z_en_zl4.h"
|
||||||
#include "objects/object_zl4/object_zl4.h"
|
#include "objects/object_zl4/object_zl4.h"
|
||||||
#include "scenes/indoors/nakaniwa/nakaniwa_scene.h"
|
#include "scenes/indoors/nakaniwa/nakaniwa_scene.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED)
|
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED)
|
||||||
|
|
||||||
@ -227,20 +228,6 @@ u16 EnZl4_GetText(PlayState* play, Actor* thisx) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GivePlayerRandoRewardZeldaChild(EnZl4* zelda, PlayState* play, RandomizerCheck check) {
|
|
||||||
if (zelda->actor.parent != NULL && zelda->actor.parent->id == GET_PLAYER(play)->actor.id &&
|
|
||||||
!Flags_GetTreasure(play, 0x1E)) {
|
|
||||||
Flags_SetTreasure(play, 0x1E);
|
|
||||||
} else if (!Flags_GetTreasure(play, 0x1E) && !Randomizer_GetSettingValue(RSK_SKIP_CHILD_ZELDA) && Actor_TextboxIsClosing(&zelda->actor, play) &&
|
|
||||||
(play->msgCtx.textId == 0x703C || play->msgCtx.textId == 0x703D)) {
|
|
||||||
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, GI_LETTER_ZELDA);
|
|
||||||
GiveItemEntryFromActor(&zelda->actor, play, getItemEntry, 10000.0f, 100.0f);
|
|
||||||
} else if (Flags_GetTreasure(play, 0x1E) && !Player_InBlockingCsMode(play, GET_PLAYER(play))) {
|
|
||||||
gSaveContext.unk_13EE = 0x32;
|
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
s16 func_80B5B9B0(PlayState* play, Actor* thisx) {
|
s16 func_80B5B9B0(PlayState* play, Actor* thisx) {
|
||||||
EnZl4* this = (EnZl4*)thisx;
|
EnZl4* this = (EnZl4*)thisx;
|
||||||
|
|
||||||
@ -389,12 +376,6 @@ void EnZl4_Init(Actor* thisx, PlayState* play) {
|
|||||||
this->actor.textId = -1;
|
this->actor.textId = -1;
|
||||||
this->eyeExpression = this->mouthExpression = ZL4_MOUTH_NEUTRAL;
|
this->eyeExpression = this->mouthExpression = ZL4_MOUTH_NEUTRAL;
|
||||||
|
|
||||||
if (IS_RANDO) {
|
|
||||||
Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ZL4_ANIM_0);
|
|
||||||
this->actionFunc = EnZl4_Idle;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gSaveContext.sceneSetupIndex >= 4) {
|
if (gSaveContext.sceneSetupIndex >= 4) {
|
||||||
Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ZL4_ANIM_0);
|
Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ZL4_ANIM_0);
|
||||||
this->actionFunc = EnZl4_TheEnd;
|
this->actionFunc = EnZl4_TheEnd;
|
||||||
@ -1127,14 +1108,16 @@ s32 EnZl4_CsMakePlan(EnZl4* this, PlayState* play) {
|
|||||||
Camera_ChangeSetting(GET_ACTIVE_CAM(play), 1);
|
Camera_ChangeSetting(GET_ACTIVE_CAM(play), 1);
|
||||||
this->talkState = 7;
|
this->talkState = 7;
|
||||||
play->talkWithPlayer(play, &this->actor);
|
play->talkWithPlayer(play, &this->actor);
|
||||||
func_8002F434(&this->actor, play, GI_LETTER_ZELDA, fabsf(this->actor.xzDistToPlayer) + 1.0f,
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_ZELDAS_LETTER, true, NULL)) {
|
||||||
fabsf(this->actor.yDistToPlayer) + 1.0f);
|
func_8002F434(&this->actor, play, GI_LETTER_ZELDA, fabsf(this->actor.xzDistToPlayer) + 1.0f,
|
||||||
|
fabsf(this->actor.yDistToPlayer) + 1.0f);
|
||||||
|
}
|
||||||
play->msgCtx.stateTimer = 4;
|
play->msgCtx.stateTimer = 4;
|
||||||
play->msgCtx.msgMode = MSGMODE_TEXT_CLOSING;
|
play->msgCtx.msgMode = MSGMODE_TEXT_CLOSING;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
if (Actor_HasParent(&this->actor, play)) {
|
if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_ZELDAS_LETTER, true, NULL)) {
|
||||||
Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ZL4_ANIM_0);
|
Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ZL4_ANIM_0);
|
||||||
this->talkState++;
|
this->talkState++;
|
||||||
} else {
|
} else {
|
||||||
@ -1225,11 +1208,6 @@ void EnZl4_Idle(EnZl4* this, PlayState* play) {
|
|||||||
Npc_UpdateTalking(play, &this->actor, &this->interactInfo.talkState, this->collider.dim.radius + 60.0f,
|
Npc_UpdateTalking(play, &this->actor, &this->interactInfo.talkState, this->collider.dim.radius + 60.0f,
|
||||||
EnZl4_GetText, func_80B5B9B0);
|
EnZl4_GetText, func_80B5B9B0);
|
||||||
func_80B5BB78(this, play);
|
func_80B5BB78(this, play);
|
||||||
|
|
||||||
if (IS_RANDO) {
|
|
||||||
GivePlayerRandoRewardZeldaChild(this, play, RC_HC_ZELDAS_LETTER);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnZl4_TheEnd(EnZl4* this, PlayState* play) {
|
void EnZl4_TheEnd(EnZl4* this, PlayState* play) {
|
||||||
|
@ -31,4 +31,9 @@ typedef struct EnZl4 {
|
|||||||
/* 0x0284 */ Vec3s morphTable[18];
|
/* 0x0284 */ Vec3s morphTable[18];
|
||||||
} EnZl4; // size = 0x02F0
|
} EnZl4; // size = 0x02F0
|
||||||
|
|
||||||
|
s16 func_80B5B9B0(PlayState* play, Actor* actor);
|
||||||
|
void func_80B5BB78(EnZl4* enZl4, PlayState* play);
|
||||||
|
void EnZl4_Cutscene(EnZl4* enZl4, PlayState* play);
|
||||||
|
s32 EnZl4_SetNextAnim(EnZl4* enZl4, s32 nextAnim);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -59,12 +59,7 @@ void ItemBHeart_Update(Actor* thisx, PlayState* play) {
|
|||||||
Flags_SetCollectible(play, 0x1F);
|
Flags_SetCollectible(play, 0x1F);
|
||||||
Actor_Kill(&this->actor);
|
Actor_Kill(&this->actor);
|
||||||
} else {
|
} else {
|
||||||
if (!IS_RANDO) {
|
func_8002F434(&this->actor, play, GI_HEART_CONTAINER_2, 30.0f, 40.0f);
|
||||||
func_8002F434(&this->actor, play, GI_HEART_CONTAINER_2, 30.0f, 40.0f);
|
|
||||||
} else {
|
|
||||||
GetItemEntry getItemEntry = Randomizer_GetItemFromActor(this->actor.id, play->sceneNum, this->actor.params, GI_HEART_CONTAINER_2);
|
|
||||||
GiveItemEntryFromActor(&this->actor, play, getItemEntry, 30.0f, 40.0f);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,23 +93,18 @@ void ItemBHeart_Draw(Actor* thisx, PlayState* play) {
|
|||||||
actorIt = actorIt->next;
|
actorIt = actorIt->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_RANDO) {
|
if (flag) {
|
||||||
GetItemEntry_Draw(play, Randomizer_GetItemFromActor(this->actor.id,
|
Gfx_SetupDL_25Xlu(play->state.gfxCtx);
|
||||||
play->sceneNum,this->actor.params, GI_HEART_CONTAINER_2));
|
gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
|
||||||
|
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||||
|
gSPDisplayList(POLY_XLU_DISP++, gGiHeartBorderDL);
|
||||||
|
gSPDisplayList(POLY_XLU_DISP++, gGiHeartContainerDL);
|
||||||
} else {
|
} else {
|
||||||
if (flag) {
|
Gfx_SetupDL_25Opa(play->state.gfxCtx);
|
||||||
Gfx_SetupDL_25Xlu(play->state.gfxCtx);
|
gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
|
||||||
gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
|
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||||
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
gSPDisplayList(POLY_OPA_DISP++, gGiHeartBorderDL);
|
||||||
gSPDisplayList(POLY_XLU_DISP++, gGiHeartBorderDL);
|
gSPDisplayList(POLY_OPA_DISP++, gGiHeartContainerDL);
|
||||||
gSPDisplayList(POLY_XLU_DISP++, gGiHeartContainerDL);
|
|
||||||
} else {
|
|
||||||
Gfx_SetupDL_25Opa(play->state.gfxCtx);
|
|
||||||
gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
|
|
||||||
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
|
||||||
gSPDisplayList(POLY_OPA_DISP++, gGiHeartBorderDL);
|
|
||||||
gSPDisplayList(POLY_OPA_DISP++, gGiHeartContainerDL);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CLOSE_DISPS(play->state.gfxCtx);
|
CLOSE_DISPS(play->state.gfxCtx);
|
||||||
|
@ -13,6 +13,11 @@ typedef struct ItemBHeart {
|
|||||||
/* 0x015C */ char unk_15C[0x8];
|
/* 0x015C */ char unk_15C[0x8];
|
||||||
/* 0x0164 */ s16 unk_164;
|
/* 0x0164 */ s16 unk_164;
|
||||||
/* 0x0166 */ char unk_166[0x6];
|
/* 0x0166 */ char unk_166[0x6];
|
||||||
|
// #region SOH [Randomizer] Cached for drawing for performance
|
||||||
|
/* */ GetItemEntry sohItemEntry;
|
||||||
|
// #endregion
|
||||||
} ItemBHeart; // size = 0x016C
|
} ItemBHeart; // size = 0x016C
|
||||||
|
|
||||||
|
void func_80B85264(ItemBHeart* itemBHeart, PlayState* play);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "z_item_ocarina.h"
|
#include "z_item_ocarina.h"
|
||||||
#include "scenes/overworld/spot00/spot00_scene.h"
|
#include "scenes/overworld/spot00/spot00_scene.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
|
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
|
||||||
|
|
||||||
@ -169,31 +170,27 @@ void ItemOcarina_DoNothing(ItemOcarina* this, PlayState* play) {
|
|||||||
|
|
||||||
void ItemOcarina_StartSoTCutscene(ItemOcarina* this, PlayState* play) {
|
void ItemOcarina_StartSoTCutscene(ItemOcarina* this, PlayState* play) {
|
||||||
if (Actor_TextboxIsClosing(&this->actor, play)) {
|
if (Actor_TextboxIsClosing(&this->actor, play)) {
|
||||||
if (!IS_RANDO) {
|
play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gHyruleFieldZeldaSongOfTimeCs);
|
||||||
play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gHyruleFieldZeldaSongOfTimeCs);
|
gSaveContext.cutsceneTrigger = 1;
|
||||||
gSaveContext.cutsceneTrigger = 1;
|
|
||||||
} else {
|
|
||||||
play->transitionTrigger = TRANS_TRIGGER_START;
|
|
||||||
play->transitionType = TRANS_TYPE_FADE_WHITE;
|
|
||||||
gSaveContext.nextTransitionType = TRANS_TYPE_FADE_WHITE;
|
|
||||||
play->nextEntranceIndex = ENTR_HYRULE_FIELD_16;
|
|
||||||
gSaveContext.nextCutsceneIndex = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemOcarina_WaitInWater(ItemOcarina* this, PlayState* play) {
|
void ItemOcarina_WaitInWater(ItemOcarina* this, PlayState* play) {
|
||||||
if (Actor_HasParent(&this->actor, play)) {
|
if (
|
||||||
|
Actor_HasParent(&this->actor, play) ||
|
||||||
|
(
|
||||||
|
!GameInteractor_Should(GI_VB_GIVE_ITEM_OCARINA_OF_TIME, true, NULL) &&
|
||||||
|
(this->actor.xzDistToPlayer < 20.0f) && (fabsf(this->actor.yDistToPlayer) < 10.0f) &&
|
||||||
|
GET_PLAYER(play)->stateFlags2 & PLAYER_STATE2_DIVING
|
||||||
|
)
|
||||||
|
) {
|
||||||
Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_OCARINA_OF_TIME);
|
Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_OCARINA_OF_TIME);
|
||||||
Flags_SetSwitch(play, 3);
|
Flags_SetSwitch(play, 3);
|
||||||
this->actionFunc = ItemOcarina_StartSoTCutscene;
|
this->actionFunc = ItemOcarina_StartSoTCutscene;
|
||||||
this->actor.draw = NULL;
|
this->actor.draw = NULL;
|
||||||
} else {
|
} else {
|
||||||
if (!IS_RANDO) {
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_OCARINA_OF_TIME, true, NULL)) {
|
||||||
func_8002F434(&this->actor, play, GI_OCARINA_OOT, 30.0f, 50.0f);
|
func_8002F434(&this->actor, play, GI_OCARINA_OOT, 30.0f, 50.0f);
|
||||||
} else {
|
|
||||||
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_HF_OCARINA_OF_TIME_ITEM, GI_OCARINA_OOT);
|
|
||||||
GiveItemEntryFromActor(&this->actor, play, getItemEntry, 30.0f, 50.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((play->gameplayFrames & 13) == 0) {
|
if ((play->gameplayFrames & 13) == 0) {
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "z_obj_switch.h"
|
#include "z_obj_switch.h"
|
||||||
#include "objects/gameplay_dangeon_keep/gameplay_dangeon_keep.h"
|
#include "objects/gameplay_dangeon_keep/gameplay_dangeon_keep.h"
|
||||||
#include "vt.h"
|
#include "vt.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
|
#define FLAGS ACTOR_FLAG_UPDATE_WHILE_CULLED
|
||||||
|
|
||||||
@ -249,10 +250,12 @@ void ObjSwitch_SetOn(ObjSwitch* this, PlayState* play) {
|
|||||||
subType = (this->dyna.actor.params >> 4 & 7);
|
subType = (this->dyna.actor.params >> 4 & 7);
|
||||||
Flags_SetSwitch(play, (this->dyna.actor.params >> 8 & 0x3F));
|
Flags_SetSwitch(play, (this->dyna.actor.params >> 8 & 0x3F));
|
||||||
|
|
||||||
if (subType == 0 || subType == 4) {
|
if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) {
|
||||||
OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_CORRECT_CHIME);
|
if (subType == 0 || subType == 4) {
|
||||||
} else {
|
OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_CORRECT_CHIME);
|
||||||
OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR);
|
} else {
|
||||||
|
OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this->cooldownOn = true;
|
this->cooldownOn = true;
|
||||||
@ -266,7 +269,9 @@ void ObjSwitch_SetOff(ObjSwitch* this, PlayState* play) {
|
|||||||
Flags_UnsetSwitch(play, (this->dyna.actor.params >> 8 & 0x3F));
|
Flags_UnsetSwitch(play, (this->dyna.actor.params >> 8 & 0x3F));
|
||||||
|
|
||||||
if ((this->dyna.actor.params >> 4 & 7) == 1) {
|
if ((this->dyna.actor.params >> 4 & 7) == 1) {
|
||||||
OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR);
|
if (GameInteractor_Should(GI_VB_PLAY_ONEPOINT_ACTOR_CS, true, this)) {
|
||||||
|
OnePointCutscene_AttentionSetSfx(play, &this->dyna.actor, NA_SE_SY_TRE_BOX_APPEAR);
|
||||||
|
}
|
||||||
this->cooldownOn = true;
|
this->cooldownOn = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include "soh/Enhancements/randomizer/randomizer_grotto.h"
|
#include "soh/Enhancements/randomizer/randomizer_grotto.h"
|
||||||
#include "soh/Enhancements/randomizer/fishsanity.h"
|
#include "soh/Enhancements/randomizer/fishsanity.h"
|
||||||
#include "soh/frame_interpolation.h"
|
#include "soh/frame_interpolation.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -6658,7 +6659,14 @@ s32 func_8083E5A8(Player* this, PlayState* play) {
|
|||||||
uint8_t showItemCutscene = play->sceneNum == SCENE_BOMBCHU_BOWLING_ALLEY || Item_CheckObtainability(giEntry.itemId) == ITEM_NONE || IS_RANDO;
|
uint8_t showItemCutscene = play->sceneNum == SCENE_BOMBCHU_BOWLING_ALLEY || Item_CheckObtainability(giEntry.itemId) == ITEM_NONE || IS_RANDO;
|
||||||
|
|
||||||
// Only skip cutscenes for drops when they're items/consumables from bushes/rocks/enemies.
|
// Only skip cutscenes for drops when they're items/consumables from bushes/rocks/enemies.
|
||||||
uint8_t isDropToSkip = (interactedActor->id == ACTOR_EN_ITEM00 && interactedActor->params != 6 && interactedActor->params != 17) ||
|
uint8_t isDropToSkip =
|
||||||
|
(
|
||||||
|
interactedActor->id == ACTOR_EN_ITEM00 &&
|
||||||
|
interactedActor->params != ITEM00_HEART_PIECE &&
|
||||||
|
interactedActor->params != ITEM00_SMALL_KEY &&
|
||||||
|
interactedActor->params != ITEM00_SOH_GIVE_ITEM_ENTRY &&
|
||||||
|
interactedActor->params != ITEM00_SOH_GIVE_ITEM_ENTRY_GI
|
||||||
|
) ||
|
||||||
interactedActor->id == ACTOR_EN_KAREBABA ||
|
interactedActor->id == ACTOR_EN_KAREBABA ||
|
||||||
interactedActor->id == ACTOR_EN_DEKUBABA;
|
interactedActor->id == ACTOR_EN_DEKUBABA;
|
||||||
|
|
||||||
@ -6716,8 +6724,10 @@ s32 func_8083E5A8(Player* this, PlayState* play) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func_80836898(play, this, func_8083A434);
|
func_80836898(play, this, func_8083A434);
|
||||||
|
if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_CHEST, true, &giEntry)) {
|
||||||
this->stateFlags1 |= PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_ITEM_OVER_HEAD | PLAYER_STATE1_IN_CUTSCENE;
|
this->stateFlags1 |= PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_ITEM_OVER_HEAD | PLAYER_STATE1_IN_CUTSCENE;
|
||||||
func_8083AE40(this, giEntry.objectId);
|
func_8083AE40(this, giEntry.objectId);
|
||||||
|
}
|
||||||
this->actor.world.pos.x =
|
this->actor.world.pos.x =
|
||||||
chest->dyna.actor.world.pos.x - (Math_SinS(chest->dyna.actor.shape.rot.y) * 29.4343f);
|
chest->dyna.actor.world.pos.x - (Math_SinS(chest->dyna.actor.shape.rot.y) * 29.4343f);
|
||||||
this->actor.world.pos.z =
|
this->actor.world.pos.z =
|
||||||
@ -10087,7 +10097,7 @@ void Player_Init(Actor* thisx, PlayState* play2) {
|
|||||||
|
|
||||||
if ((sp50 == 0) || (sp50 < -1)) {
|
if ((sp50 == 0) || (sp50 < -1)) {
|
||||||
titleFileSize = scene->titleFile.vromEnd - scene->titleFile.vromStart;
|
titleFileSize = scene->titleFile.vromEnd - scene->titleFile.vromStart;
|
||||||
if (gSaveContext.showTitleCard) {
|
if (GameInteractor_Should(GI_VB_SHOW_TITLE_CARD, gSaveContext.showTitleCard, NULL)) {
|
||||||
if ((gSaveContext.sceneSetupIndex < 4) &&
|
if ((gSaveContext.sceneSetupIndex < 4) &&
|
||||||
(gEntranceTable[((void)0, gSaveContext.entranceIndex) + ((void)0, gSaveContext.sceneSetupIndex)].field &
|
(gEntranceTable[((void)0, gSaveContext.entranceIndex) + ((void)0, gSaveContext.sceneSetupIndex)].field &
|
||||||
ENTRANCE_INFO_DISPLAY_TITLE_CARD_FLAG) &&
|
ENTRANCE_INFO_DISPLAY_TITLE_CARD_FLAG) &&
|
||||||
@ -13393,7 +13403,7 @@ s32 func_8084DFF4(PlayState* play, Player* this) {
|
|||||||
play->msgCtx.msgMode = MSGMODE_TEXT_DONE;
|
play->msgCtx.msgMode = MSGMODE_TEXT_DONE;
|
||||||
} else {
|
} else {
|
||||||
if (Message_GetState(&play->msgCtx) == TEXT_STATE_CLOSING) {
|
if (Message_GetState(&play->msgCtx) == TEXT_STATE_CLOSING) {
|
||||||
if (this->getItemId == GI_GAUNTLETS_SILVER && !IS_RANDO) {
|
if (GameInteractor_Should(GI_VB_PLAY_NABOORU_CAPTURED_CS, this->getItemId == GI_GAUNTLETS_SILVER, NULL)) {
|
||||||
play->nextEntranceIndex = ENTR_DESERT_COLOSSUS_0;
|
play->nextEntranceIndex = ENTR_DESERT_COLOSSUS_0;
|
||||||
play->transitionTrigger = TRANS_TRIGGER_START;
|
play->transitionTrigger = TRANS_TRIGGER_START;
|
||||||
gSaveContext.nextCutsceneIndex = 0xFFF1;
|
gSaveContext.nextCutsceneIndex = 0xFFF1;
|
||||||
@ -13409,11 +13419,13 @@ s32 func_8084DFF4(PlayState* play, Player* this) {
|
|||||||
this->unk_862 = 0;
|
this->unk_862 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #region SOH [Randomizer] TODO Better Ice trap handling?
|
||||||
if (this->getItemEntry.itemId == RG_ICE_TRAP && this->getItemEntry.modIndex == MOD_RANDOMIZER) {
|
if (this->getItemEntry.itemId == RG_ICE_TRAP && this->getItemEntry.modIndex == MOD_RANDOMIZER) {
|
||||||
this->unk_862 = 0;
|
this->unk_862 = 0;
|
||||||
gSaveContext.pendingIceTrapCount++;
|
gSaveContext.pendingIceTrapCount++;
|
||||||
Player_SetPendingFlag(this, play);
|
Player_SetPendingFlag(this, play);
|
||||||
}
|
}
|
||||||
|
// #endregion
|
||||||
|
|
||||||
this->getItemId = GI_NONE;
|
this->getItemId = GI_NONE;
|
||||||
this->getItemEntry = (GetItemEntry)GET_ITEM_NONE;
|
this->getItemEntry = (GetItemEntry)GET_ITEM_NONE;
|
||||||
@ -15675,6 +15687,7 @@ void func_8085283C(PlayState* play, Player* this, CsCmdActorAction* arg2) {
|
|||||||
if (LinkAnimation_Update(play, &this->skelAnime)) {
|
if (LinkAnimation_Update(play, &this->skelAnime)) {
|
||||||
func_80852944(play, this, arg2);
|
func_80852944(play, this, arg2);
|
||||||
} else if (this->unk_850 == 0) {
|
} else if (this->unk_850 == 0) {
|
||||||
|
// This is when link picks up the sword in the Ganon fight
|
||||||
Item_Give(play, ITEM_SWORD_MASTER);
|
Item_Give(play, ITEM_SWORD_MASTER);
|
||||||
func_80846720(play, this, 0);
|
func_80846720(play, this, 0);
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user