/* * File: z_bg_gjyo_bridge.c * Overlay: ovl_Bg_Gjyo_Bridge * Description: Rainbow Bridge outside Ganon's Castle */ #include "z_bg_gjyo_bridge.h" #include "objects/object_gjyo_objects/object_gjyo_objects.h" #include "scenes/dungeons/ganon_tou/ganon_tou_scene.h" #define FLAGS 0 void BgGjyoBridge_Init(Actor* thisx, GlobalContext* globalCtx); void BgGjyoBridge_Destroy(Actor* thisx, GlobalContext* globalCtx); void BgGjyoBridge_Update(Actor* thisx, GlobalContext* globalCtx); void BgGjyoBridge_Draw(Actor* thisx, GlobalContext* globalCtx); void func_808787A4(BgGjyoBridge* this, GlobalContext* globalCtx); void BgGjyoBridge_TriggerCutscene(BgGjyoBridge* this, GlobalContext* globalCtx); void BgGjyoBridge_SpawnBridge(BgGjyoBridge* this, GlobalContext* globalCtx); const ActorInit Bg_Gjyo_Bridge_InitVars = { ACTOR_BG_GJYO_BRIDGE, ACTORCAT_PROP, FLAGS, OBJECT_GJYO_OBJECTS, sizeof(BgGjyoBridge), (ActorFunc)BgGjyoBridge_Init, (ActorFunc)BgGjyoBridge_Destroy, (ActorFunc)BgGjyoBridge_Update, (ActorFunc)BgGjyoBridge_Draw, NULL, }; static InitChainEntry sInitChain[] = { ICHAIN_F32(uncullZoneScale, 800, ICHAIN_CONTINUE), ICHAIN_VEC3F_DIV1000(scale, 100, ICHAIN_STOP), }; void BgGjyoBridge_Init(Actor* thisx, GlobalContext* globalCtx) { BgGjyoBridge* this = (BgGjyoBridge*)thisx; s32 pad; CollisionHeader* colHeader; colHeader = NULL; Actor_ProcessInitChain(thisx, sInitChain); DynaPolyActor_Init(&this->dyna, DPM_UNK); CollisionHeader_GetVirtual(&gRainbowBridgeCol, &colHeader); this->dyna.bgId = DynaPoly_SetBgActor(globalCtx, &globalCtx->colCtx.dyna, thisx, colHeader); int bridge = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE); if (gSaveContext.eventChkInf[4] & 0x2000 || (gSaveContext.n64ddFlag && bridge == 0)) { this->actionFunc = func_808787A4; } else { this->dyna.actor.draw = NULL; func_8003EBF8(globalCtx, &globalCtx->colCtx.dyna, this->dyna.bgId); this->actionFunc = BgGjyoBridge_TriggerCutscene; } } void BgGjyoBridge_Destroy(Actor* thisx, GlobalContext* globalCtx) { BgGjyoBridge* this = (BgGjyoBridge*)thisx; DynaPoly_DeleteBgActor(globalCtx, &globalCtx->colCtx.dyna, this->dyna.bgId); } void func_808787A4(BgGjyoBridge* this, GlobalContext* globalCtx) { } void LaunchBridgeCutscene(BgGjyoBridge* this, GlobalContext* globalCtx) { globalCtx->csCtx.segment = SEGMENTED_TO_VIRTUAL(gRainbowBridgeCs); gSaveContext.cutsceneTrigger = 1; this->actionFunc = BgGjyoBridge_SpawnBridge; } u8 CheckPlayerPosition(Player* player, GlobalContext* globalCtx) { return (player->actor.world.pos.x > -70.0f) && (player->actor.world.pos.x < 300.0f) && (player->actor.world.pos.y > 1340.0f) && (player->actor.world.pos.z > 1340.0f) && (player->actor.world.pos.z < 1662.0f) && !Gameplay_InCsMode(globalCtx); } u8 CheckStoneCount() { u8 stoneCount = 0; if (CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)) { stoneCount++; } if (CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) { stoneCount++; } if (CHECK_QUEST_ITEM(QUEST_ZORA_SAPPHIRE)) { stoneCount++; } return stoneCount; } u8 CheckMedallionCount() { u8 medallionCount = 0; if (CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST)) { medallionCount++; } if (CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) { medallionCount++; } if (CHECK_QUEST_ITEM(QUEST_MEDALLION_WATER)) { medallionCount++; } if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW)) { medallionCount++; } if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT)) { medallionCount++; } if (CHECK_QUEST_ITEM(QUEST_MEDALLION_LIGHT)) { medallionCount++; } return medallionCount; } u8 CheckDungeonCount() { u8 dungeonCount = 0; if (gSaveContext.dungeonsDone[0] == 1) { dungeonCount++; } if (gSaveContext.dungeonsDone[1] == 1) { dungeonCount++; } if (gSaveContext.dungeonsDone[2] == 1) { dungeonCount++; } if (gSaveContext.dungeonsDone[3] == 1) { dungeonCount++; } if (gSaveContext.dungeonsDone[4] == 1) { dungeonCount++; } if (gSaveContext.dungeonsDone[5] == 1) { dungeonCount++; } if (gSaveContext.dungeonsDone[6] == 1) { dungeonCount++; } if (gSaveContext.dungeonsDone[7] == 1) { dungeonCount++; } return dungeonCount; } void BgGjyoBridge_TriggerCutscene(BgGjyoBridge* this, GlobalContext* globalCtx) { Player* player = GET_PLAYER(globalCtx); if (!gSaveContext.n64ddFlag) { if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) && (INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT) && CheckPlayerPosition(player, globalCtx)) { LaunchBridgeCutscene(this, globalCtx); } } else { int bridge = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE); int bridgeStoneCount = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE_STONE_COUNT); int bridgeMedallionCount = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT); int bridgeRewardCount = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE_REWARD_COUNT); int bridgeDungeonCount = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT); int bridgeTokenCount = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE_TOKEN_COUNT); if (CheckPlayerPosition(player, globalCtx)) { switch (bridge) { case 1: if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) && (INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT)) { LaunchBridgeCutscene(this, globalCtx); } break; case 2: if (CheckStoneCount() >= bridgeStoneCount) { LaunchBridgeCutscene(this, globalCtx); } break; case 3: if (CheckMedallionCount() >= bridgeMedallionCount) { LaunchBridgeCutscene(this, globalCtx); } break; case 4: if ((CheckMedallionCount() + CheckStoneCount()) >= bridgeRewardCount) { LaunchBridgeCutscene(this, globalCtx); } break; case 5: if (CheckDungeonCount() >= bridgeDungeonCount) { LaunchBridgeCutscene(this, globalCtx); } break; case 6: if (gSaveContext.inventory.gsTokens >= bridgeTokenCount) { LaunchBridgeCutscene(this, globalCtx); } break; } } } } void BgGjyoBridge_SpawnBridge(BgGjyoBridge* this, GlobalContext* globalCtx) { if ((globalCtx->csCtx.state != CS_STATE_IDLE) && (globalCtx->csCtx.npcActions[2] != NULL) && (globalCtx->csCtx.npcActions[2]->action == 2)) { this->dyna.actor.draw = BgGjyoBridge_Draw; func_8003EC50(globalCtx, &globalCtx->colCtx.dyna, this->dyna.bgId); gSaveContext.eventChkInf[4] |= 0x2000; } } void BgGjyoBridge_Update(Actor* thisx, GlobalContext* globalCtx) { BgGjyoBridge* this = (BgGjyoBridge*)thisx; this->actionFunc(this, globalCtx); } void BgGjyoBridge_Draw(Actor* thisx, GlobalContext* globalCtx) { BgGjyoBridge* this = (BgGjyoBridge*)thisx; OPEN_DISPS(globalCtx->state.gfxCtx); func_80093D84(globalCtx->state.gfxCtx); gSPSegment(POLY_XLU_DISP++, 8, Gfx_TexScroll(globalCtx->state.gfxCtx, globalCtx->gameplayFrames & 127, globalCtx->gameplayFrames * -3 & 127, 32, 32)); gSPSegment(POLY_XLU_DISP++, 9, Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, 0, -globalCtx->gameplayFrames & 127, 32, 32, 1, 0, globalCtx->gameplayFrames & 127, 32, 32)); gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPDisplayList(POLY_XLU_DISP++, gRainbowBridgeDL); CLOSE_DISPS(globalCtx->state.gfxCtx); }