GameScene
GameScene is a critical subsystem that is responsible for core functionality such as initialising other components, creating stages (world, title screen, etc.) and handling the game's main loop.
Subsystem | |
---|---|
Official name | Yes |
Description | Handles the main loop and stages |
Init function |
Switch 1.5.0: 0x71007D1DD8 Wii U 1.5.0: ??? |
Debug only | No |
Unlike most other subsystems, GameScene is not a singleton: it is a member of the uking::frm::System structure[1].
Definitions
Stages
Also called scenes in XLink code.
Type | Description | Map types |
---|---|---|
0 | Invalid ("None") | - |
1 | Open world stage (except GameTestField) ("オープンワールド") | MainField, AocField |
2 | Indoor stage ("Cダンジョン") | CDungeon, MainFieldSpot, GameTestDungeon |
3 | Open world stage (GameTestField) ("GameTset") | GameTestField |
4 | MainFieldDungeon ("四大遺物") | MainFieldDungeon |
5 | Indoor stage or viewer stage ("ビューワー") | ActorViewer |
Maps that have the same stage type typically use the same subsystems and share most characteristics. For example, all open world stages use the Tera height map terrain system and load map units in the same way.
StageBinders
Type | Description |
---|---|
0 | OpenWorldStage |
1 | IndoorStage (CDungeon, ...) |
2 | MainFieldDungeonStage |
3 | TitleStage |
4 | StartupSaveCheckStage |
5 | Viewer |
Fade types
Type | Description |
---|---|
0 | |
1 | |
2 | Show logo[3] |
GameScene state strings
Name | Description |
---|---|
1st | Demo mode [check] |
2nd | Demo mode |
初回シーケンス | Initial sequence - New save |
TitleMenu | Title menu |
Presentation | Demo mode |
E3_2016/Presentation | Demo mode |
StartupSaveCheckStage | |
Viewer | |
CDungeon | |
MainFieldDungeonStage | |
MainField | |
GameTestField | |
GameTestField2 | |
AocField | |
GameTestDungeon | |
MonolithTestDungeon | |
SrdTestDungeon | |
MarioClubTestDungeon | |
TestField | |
研修用 | |
MonolithTest100enemy | |
MinimumField | |
ActorViewer |
Init
- GameScene::initialize (0x71007A8014)
- Load the environment graphics archive (Env.sgenvb)
- Create the GameScene heap
- Create the StageBinder heap
- Start the GameScene TaskMgr (thread)
- InitializeSubSystem (note: some of the below names are unofficial, see Subsystems for more details)
- AutoPlacementFlowMgr
- FadeProgress
- DungeonPackMgr
- PlayerInfo
- PlayerResetPosMgr
- GameSceneSubsys3
- GameSceneSubsys4
- GameSceneSubsys5
- ActorHeapUtil
- E3Mgr
- aoc2
- aoc3
- DamageInfoMgr
- CookingMgr
- GameSceneSubsys7
- ActorLimiter
- GameSceneSubsys9
- GameSceneSubsys10
- IceBlockMgr
- AmiiboMgr
- GameSceneSubsys11
- GameSceneSubsys12
- GameSceneSubsys13
- GameSceneSubsys14
- GameSceneSubsys15
- ResidentActorMgr
- Create UI heap
- uiManager
- Load the Fade screen
- OnUiActorMgr
- CreatePlayerEquipActorMgr
- CreatePlayerTrashActorMgr
- TipsMgr
- nxargs
- GameScene::initializeGraphicsLayer_
- ErrorViewerTask init
- Set Get Demo handler
- Set Check Weapon Free Slot handler (1, 2)
- ...
- SaveSystem init
- Set initial state
- nn::err::ShowUnacceptableAddOnContentVersionError if needed
-
- [Debug] StarterPackMgr: Load Title pack
- GlobalParameter
- GlobalParameter: Load actorpack
- E3Mgr: Load System/BuildTime.txt (stubbed in release versions)
- TipsMgr: Load tips
- ResidentActorMgr: Load configuration (ResidentActors.byml)
- AutoPlacementFlowMgr: Load auto placement event flows
- KingEditor: Stubbed
- E3Mgr: init
Initial state
The initial state the game launches into is determined by GameScene[5].
const bool isFirstLaunch = SaveSystem::sInstance->isFirstLaunch();
State* state = isFirstLaunch ? &state_NewSave : &state_LunchTitle;
if ( aocManager::sInstance && aocManager::sInstance->flags & 2 )
nn::err::ShowUnacceptableAddOnContentVersionError();
const bool isDemo = E3Mgr::sInstance && E3Mgr::sInstance->isDemoMode();
if (isDemo)
state = &state_LunchTitle;
if (!isDemo && isFirstLaunch)
sIsFirstNonDemoLaunch = 1;
StateMachine::changeState(&this->stateMachine, state);
States
Note: when the Indoor stage binder is initialised and if the map name changes, a "dungeon" telemetry report is emitted with "leave" or "enter" as the event name and the old/new map name as additional data[6].
StageMgr
This section is empty. You can help by adding to it. |
StageSelect
This section is empty. You can help by adding to it. |
StageTransition
Entered before stage generation starts and after Fade (loading screen) has been initialised and made visible. This state machine state is a noop.
LunchTitle
LunchTitle (sic) is entered when the game is launched. The internal state string is "TitleMenu" or (in demo mode) "2nd".
The run function is extremely simple: it simply creates the TitleStage binder (with doNotShowLogo=true[7]) when the "common run" status (see below) is 0xa, then calls the "common run" function (with isNewSave=false[8]).
NewSave
This section needs expansion. You can help by adding to it. |
Entered on the first boot or when the new game option is selected. The associated state string is "初回シーケンス" ("initial sequence").
PatchError
This section is empty. You can help by adding to it. |
Main loop
Three GameScene functions are called in a row from RootTask (see Executable) after initialisation has completed, i.e. in the game's main loop. (Note: these 3 names are unofficial.)
precalc
- FadeProgress: Update the progress gauge on the Fade screen (animated).
- Update current map name based on player position (when Link is not in a dungeon).
- Run StageMgr and StageSelect code.
- If a flag is set, run the final step of stage generation. (Unused?)
- If stage status is "NeedsGeneration":
- Call some MCMgr function at 0x71007A9198.
- Run save upload subsystem if needed.
- Call GameScene::genStage with second argument being
!EventMgr::sInstance->hasActiveEvent() || EventMgr::sInstance->getActiveEvent()->name != "Demo169_0"
.
- If stage status is "NeedsUnload":
- Call some MCMgr function at 0x71007A9198.
- Run save upload subsystem if needed.
- Call GameScene::unloadStage.
- If no stage is being unloaded, call
this->activeStageBinder->getStage()->preCalc
. - ??? (something involving GameScene Subsystem #12)
- Call some MCMgr function at 0x71007A9198, again.
- If the current state is StageMgr:
- Reset the current stage binder by setting a flag for StageMgr if needed (after a Blood Moon[check])
- If a forced blood moon is ready
- If panic blood moons can be triggered (see Blood moon), call the Blood Moon demo (Demo011_0).
- Report the panic blood moon via the telemetry system.
- If any panic condition is true, and if panic blood moons are enabled[9], request a panic blood moon by setting a SkyMgr flag. SkyMgr will start a 90 frame timer (3 seconds) and set a ready flag once it has expired. The timer is reset every time the panic blood moon is temporarily inhibited.
calc
This section is empty. You can help by adding to it. |
postcalc
This section is empty. You can help by adding to it. |
Common state run function
Called from StageSelectRun, LunchTitleRun and NewSaveRun.
- Status 0:
- Start loading
- Finish startup logo (Switch)[10]
- If the state string is set to 初回シーケンス, clear the Resource system cache ("ClearAllCaches")[11].
- Debug stuff[12].
- E3 Demo stuff[13].
- Show the Fade screen (loading screen) if the state string does not[14] end with "Viewer" or is not any of the following strings: 1st, 2nd, Presentation, TitleMenu, 初回シーケンス, StartupSaveCheckStage
- StageSelect stuff[18].
- Stop "resource compaction" and wait for it to be stopped[19].
- If the stage string starts with CDungeon[20] or MainFieldDungeonStage[21], start loading the associated DungeonPack[22].
- BaseProcMgr: start ActorCreate initializer thread[23][check].
- FadeProgress: reset internal state[24], set progress to 0%[25] and mark loading as active[26].
- Start loading
- Status 2:
- If the GameScene state machine's current state is StageSelect or NewSave, do something involving LayerMgrTask and the Renderer.[check]
- Status 0xa:
- TipsMgr: update tips if the loading screen is visible (not just opened). TipsMgr will load tips depending on the stage that is being loaded.
- Status 0xb:
Stage generation
- Terrain::sInstance->flags |= 0x180u
- Step 0
- Step 1
- If a pack was loaded by DungeonPackMgr, wait for DungeonPack loading to finish[31] and switch active pack to the dungeon pack.
- Step 2
- If the stage to load is TitleStage, wait for TitlePack loading to finish[32] and switch active pack to the title pack.
- Step 3: start stage generation[33]
- PlacementMgr
- ActorSystem::sInstance->field_13A = 0
- Update current map flags (e.g. sIsDungeon)
- Clear BaseProcMgr ActorCreate queue[check]
- Create uking::Stage::ForBaseProcDual heap (if not already done), which will be used for actors, ActorCreator and BaseProcMgr
- ActorSystem::sInstance->field_139 = 0
- If the state string starts with 初回シーケンス, MainField, GameTestField, GameTestField2, AocField, CDungeon, MainFieldDungeonStage, GameTestDungeon, MonolithTestDungeon, SrdTestDungeon, MarioClubTestDungeon, TestField, 研修用, MonolithTest100enemy, MinimumField, or ActorViewer, call GameScene::startBgProcessing (0x71007B2054)
- If "new save" was selected, initialize PauseMenuDataMgr data
- If the stage to load is TitleStage, load Layout/Title.blarc for ui::LayoutResourceMgr.
- If "new save" was selected and the awakening demo hasn't been played since the game was launched[34], ask EventMgr to call Demo169_0.
- Some PhysicsMemSys stuff (0x71007ADBE0).
- Step 4
- Wait for completion of Title BG processing (20% of the loading bar)
- uiManager (0x71007ACD04)
- Initialize StatisticsMgr paths depending on current map type.
- Update aoc2's mapType and mapName fields.
- Step 5
- Step 6
- Load env.genvb binary (gsys::ModelSceneEnv::clearImpl + loadBinaryImpl)
- If the stage binder type is 0, 1 or 2 (OpenWorldStage, IndoorStage or MainFieldDungeonStage):
- Set loading progress to 40%.
- Graphics stuff, again
- OnUiActorMgr
- GameScene::loadTera (on a separate thread)
- Step 7
- If the stage binder type is 0, 1 or 2 (OpenWorldStage, IndoorStage or MainFieldDungeonStage):
- Wait for Tera to load[36]
- If the stage binder type is 0, 1 or 2 (OpenWorldStage, IndoorStage or MainFieldDungeonStage):
- Step 8
- Step 9
- Initialize QuestMgr.
- Set loading progress to 60%.
- Step 10
- Load stage specific resources[37]: if the binder type is StageBinderType::Title (3), the Title layout archive is loaded by LayoutResourceMgr. Otherwise, nothing happens.
- Step 11
- #Stage generation step 11
- Update player saved position, map type, map name, ...
- Change GameScene state to StageSelect or StageMgr (step 11-6 sets the state pointer to StageMgr).
- Terrain stuff[check]
- DungeonPackMgr: clean up state (destroy arena and heap) and unregister entry factory.
- Set flag 0xa25 (genStageStep12Reached?[check]) on the Fade screen instance.
- Stop resource compaction and set some flags on the TextureHandleMgr.
- Step 12
- Set aoc2 flag 0x4 if
isNewSave || !isShrine || isStageDebug
and clear it otherwise. - #Stage generation step 12
- Terrain stuff again[check]
- Set aoc2 flag 0x4 if
- Step 13 (final)
- #Stage generation final step
- Various flags are set upon completion, for example GameScene stage status is set to 0, isInitializingStage is set to false, etc.
- FadeProgress is reset.
- Stage generation debug timer is stopped.
- aoc2: IsLastPlayHardMode is updated.
- GameScene::sNeedsOptionLoad is set to true.
Stage generation step 11
- Step 0: init before stage gen (ステージ生成前の初期化処理)[38]
- Various flags are set (GameScene, BaseProcMgr, Awareness, EventMgr), in particular field 0x1d12a is set to true if
!isNewSave
. - Set initial position based on the stage binder. This may be overridden with a saved position or an event position later on.
- GameSceneSubsys2, ActorSystem: set some flags
- GameSceneSubsys14: Update current location name (game data flag: SaveLocationName). The flag is written to if the player is in a shrine or a Divine Beast. Otherwise, it's read.
- PhysicsMemSys: set indoor flag if the stage binder type is Indoor (1)
- aoc2: Set flag 0x1 (IsLastPlayHardMode) if the corresponding game data flag is set. This is what the rest of the game uses to determine if Master Mode is enabled.
- Effect, Reaction, PhysicsMemSys, EventMgr
- PlacementMgr, LODMgr, EventMgr, WorldMgr, Awareness, Effect, XLink, VFR
- aocManager: set latest version played and HasAocVer{1,2,3} flags.
- Terrain
- Initialize the sound system and the UI manager
- If the stage binder type is OpenWorld (0) or the map name is ActorViewer or the current stage is a debug map:
- Create the HorseMgr instance, initialize it and create the horse actor.
- Create the WolfLinkMgr instance and initialize it.
- Create the MotorcycleMgr instance and initialize it.
- GameSceneSubsys5, GameSceneSubsys4: ? [check]
- If a flag is set (GameScene @ 0x6e5), SaveSystem::startLoad is called.
- TipsMgr: Initialize the TipsSystemActor.
- Various flags are set (GameScene, BaseProcMgr, Awareness, EventMgr), in particular field 0x1d12a is set to true if
- Step 1: wait for horse generation (馬の生成待ち)
- Step 2: if the stage binder type is not Title and not Viewer and not StartupSaveCheck, initialize PauseMenuDataMgr (PauseMenuDataMgr::fromSaveData).
- Step 3: wait for player equipment actor generation to complete (プレイヤーの装備アクターの生成完了待ち): CreatePlayerEquipActorMgr
- Step 4
- aocManager: parse MainField static map unit (if aocManager exists)
- Something involving vectors and calculations[check]
- Step 5
- Update FadeProgress based on the queue size of the BaseProcMgr actor create initializer[check] and PlacementMgr load progress[check]. This step represents the last 40% of the progress bar.
- Start #Stage generation step 11-5b as an async task[39] and wait for it to complete.
- Stop the Fade screen "color animator".
- Call this->stage->initForStageGen (vtable @ 0x60). For most stages, this calls WorldMgr's SkyMgr::update.
- Graphics, uiManager, agl::lyr::Renderer: ?[check]
- Set this->activeStageBinder (@ 0x2a0) to this->stageBinder (@ 0x2a8)[40].
- Step 6
- Set next GameScene state to StageMgr.
- qword_71025D16C0: ?[check]
- If the binder type is Title (3):
- If the ROM type is "RID_Demo": reset some internal state in SaveMgr and SaveSystem.
- If aoc3 is initialized, set Blight rematch counters to 0 for all four blights.
- PauseMenuDataMgr: Update IsOpenItemCategory flags if necessary.
- Step 7: wait for save data upload to finish (if an upload is in progress).
- Step 8: BaseProcMgr: wait for some actor create initializer event and reset it[check]
Stage generation step 11-5b
- ProductReporter: reset scene work time (the amount of time since the last scene generation) and reset the blood moon reporter.
- Destroy the previous stage binder (this->activeStageBinder) if it's different from the current binder (this->stageBinder), and also set this->stage to nullptr.
- Set the scene change event flow and entry point names:
- If the binder type is Title: Demo025_2<Demo025_2>
- If aocManager::sInstance->version >= 0x200 and !100enemy_Activated and IsGet_Weapon_Sword_070 and !IsPlayed_Demo146_0:
- If the current map area is 14 (Korok Forest):
- If AIDef:Query/CheckBalladOfHeroActiveTiming is 1: Aoc2Resident<InForrest>
- If AIDef:Query/CheckBalladOfHeroActiveTiming is 0: Demo201_0<Demo201_0>
- Otherwise:
- If AIDef:Query/CheckBalladOfHeroActiveTiming is 2: Aoc2Resident<InShrineOfResurrection>
- If AIDef:Query/CheckBalladOfHeroActiveTiming is 1: Aoc2Resident<InOtherArea>
- If AIDef:Query/CheckBalladOfHeroActiveTiming is 0: Demo200_0<Demo200_0>
- If the current map area is 14 (Korok Forest):
- Otherwise, if the map type is MainField:
- If AIDef:Query/CheckBalladOfHeroActiveTiming is 2: Demo600_1<Demo600_1>
- If AIDef:Query/CheckBalladOfHeroActiveTiming is 1: Demo600_1<Demo600_0>
- Otherwise: Demo025_0<Demo025_0>
- If the map type is CDungeon or MarioClubTestDungeon: Demo008_2<Demo008_2>
- WorldMgr ShootingStarMgr: Update the isMainField flag.
- AmiiboMgr: Set flag 0x40 if the map name is MainField, otherwise clear it.
- Create the stage[41].
- The stage class is automatically selected based on the stage binder type.
- stage->init and stage->postInit are called here[42].
Stage generation step 12
Stage generation final step
References
- ↑ uking::frm::System::gameScene @ 0x10 (Switch)
- ↑ As returned by the first virtual function in the StageBinderBase interface
- ↑ See 0x71007B8CD0 and AIDef:Action/ExitGame
- ↑ The state string is a sead::FixedSafeString<0x100> stored in GameScene @ 0x720.
- ↑ GameScene::initialize, 0x71007A86CC
- ↑ StageBinder::initAndReportDungeonLeaveEnter[unofficial name] at 0x71007B79A8
- ↑ 0x71007B47D8
- ↑ 0x71007B47F4
- ↑ GameConfig::sInstance->disablePanicBloodMoons (@ 0x3da on Switch 1.5.0) must be false.
- ↑ 0x71007AF6F8
- ↑ 0x71007AFBDC
- ↑ 0x71007AFDE4
- ↑ 0x71007AFEF4
- ↑ 0x71007AFF08
- ↑ 0x71007AFFC4
- ↑ 0x71007AFFCC
- ↑ See function at 0x71007B0C60
- ↑ 0x71007B0000
- ↑ 0x71007B00B4 (stop compaction) to 0x71007B010C (end of the busy loop)
- ↑ 0x71007B0124
- ↑ 0x71007B0160
- ↑ 0x71007B0190
- ↑ 0x71011BF1C4
- ↑ 0x71007B01D4
- ↑ 0x71007B01E0
- ↑ 0x71007B01E8
- ↑ 0x71007B1058
- ↑ 0x71007B105C
- ↑ 0x71007AC8A0
- ↑ 0x71007AD3AC
- ↑ DungeonPack読み込み待ち
- ↑ TitlePack読み込み待ち
- ↑ ステージ生成開始
- ↑ 0x71007ADB3C
- ↑ 0x71007ACDE4
- ↑ tera読み込み待ち
- ↑ ステージ固有リソースの読み込み待ち
- ↑ The function can be found at 0x71007B15A8 in Switch 1.5.0.
- ↑ 0x71007B2C78
- ↑ 0x71007B1A88
- ↑ 0x71007B3C5C
- ↑ 0x71007CC024