Help:Using mods and Quest flag overrides: Difference between pages

From ZeldaMods (Breath of the Wild)
(Difference between pages)
Jump to navigation Jump to search
imported>Leoetlino
m (clarify telemetry patch location)
 
imported>Leoetlino
m (Reverted edits by Susko3 (talk) to last revision by Leoetlino)
 
Line 1: Line 1:
Welcome, players! This article will walk you through setting up BotW to play with mods. There are three different platforms you can play on:
To ensure that [[quest]]s do not become uncompletable if the player leaves an area when they have only been partially solved, some GameData flags are '''always''' manually overwritten by the [[GameDataMgr]] when a [[stage]] is loaded.


* Wii U console
GameDataMgr is also responsible for always resetting the "get flag" for the Bow of Light to ensure it spawns and for making Kass spawn in Rito Village (see [[#Kass quests]]).
* Cemu, the Wii U emulator, on your computer
* Switch console


Almost all Wii U mods should work on both the console and Cemu, but most Switch mods aren't cross-compatible. In addition, many mods are only compatible with version 1.5.0 of BotW.
== Kass quests ==
Sometime ''after'' the release of 1.0.0, completion checks for Kass' quests were added to the same GameDataMgr function. These are exactly the same as the ones that can be found in the BloodyMoonRelief<Musician_Check> [[event flow]] but implemented in the executable instead. The reason why Nintendo has decided to duplicate the checks is unknown, but it might be a workaround for some kind of event bug: Kass not spawning in Rito Village even after all of his quests have been completed used to be a widespread issue.


Note that any mods which edit any of the same files as each other will probably be incompatible and cause issues. Sometimes, mods that edit different files can also be unexpectedly incompatible. If you are using multiple mods and you find glitches, please figure out which mod / combination of mods is causing the issue before reporting it to the mod creator(s).
In 1.5.0, Npc_Musician_Come (the flag that causes Kass to spawn in Rito Village) is set iff the following flags are set:
* Animal_Forest_Finish
* HateeluMini_Treasure_Finish
* Thunder_Sword_Finish
* Relief_Landing_Finish
* TwoWheels_Finish
* Shadow_Sign_Finish
* MouthofDragon_Finish
* BloodyMoonRelief_Finish
* Rito_BrosRock_Finish


== Wii U Console ==
== Implementation in 1.5.0 ==
<source lang="c++">
// utility functions (inlined in the actual executable)
void GameDataMgr::setFlag(const sead::SafeString& flagName, bool value)
{
  if (this->paramB.changeOnlyOnce)
    return;
  if (!TriggerParam::setBoolByKey(*this->paramB.param1, value, flag_name, this->paramB.x, 1LL, 1))
    return;
  if (!this->paramB.propagateParam1Changes)
    return;
  TriggerParam::setBoolByKey(*this->paramB.param, value, flag_name, this->paramB.x, 1LL, 1);
}


=== Setting up homebrew ===
bool GameDataMgr::flagIsSet(const sead::SafeString& flagName)
Follow [https://wiiu.hacks.guide/ this guide] to set up your Wii U console to use homebrew software.
{
  bool value;
  return TriggerParam::getFlagByKey(*this->param.param1, &value, flagName, this->param.x) && value;
}


=== Setting up SDCafiine ===
// 0x7100DD0A88
SDCafiine is a Wii U homebrew program that will load modded game files from your SD card.
// called from GameScene
void GameDataMgr::getAndSetShrineQuestAndKassFlags()
{
  if (flagIsSet("DarkWoods_Giant_Clear") && !flagIsSet("DarkWoods_Finish"))
    setFlag("DarkWoods_Giant_Clear", false);


# Download the latest stable release of SDCafiine (not a "nightly" version) from [https://github.com/Maschell/SDCafiine/releases here].
  if ( TriggerParam::getFlagByKey(*this->param.param1, &giant_ball1, "giant_ball1", this->param.x)
# Extract the contents of the .zip into the root of your SD card.
    && TriggerParam::getFlagByKey(*this->param.param1, &giant_ball2, "giant_ball2", this->param.x)
# Create a new folder in the root of your SD Card, named <code>sdcafiine</code>.
    && TriggerParam::getFlagByKey(*this->param.param1, &giant_ball3, "giant_ball3", this->param.x)
# Within that folder, create a new folder with the name of your game's Title ID. On Wii U, the JP version of BotW uses <code>00050000101C9300</code>, the US version uses <code>00050000101C9400</code>, and the EU version uses <code>00050000101C9500</code>.
    && TriggerParam::getFlagByKey(*this->param.param1, &giant_dungeon, "giant_dungeon", this->param.x)
# Within that folder, you can create any number of folders named after the mods you want to use. When you boot the game, a menu will appear allowing you to select one to use.
    && TriggerParam::getFlagByKey(*this->param.param1, &lithograph1, "MainField_DgnObj_RemainsLithogragh_A_02_789666109", this->param.x)
# Inside each of those folders, create a folder named <code>content</code>. Your mod files will go in here. (Mods will often include a <code>content</code> folder already to make things clear.)
    && TriggerParam::getFlagByKey(*this->param.param1, &lithograph2, "MainField_DgnObj_RemainsLithogragh_A_02_2456751716", this->param.x)
    && TriggerParam::getFlagByKey(*this->param.param1, &lithograph3, "MainField_DgnObj_RemainsLithogragh_A_02_1822262999", this->param.x) )
  {
    if (giant_ball1 && !lithograph1 && !(this->flags & 0x40000))
      setFlag("MainField_DgnObj_RemainsLithogragh_A_02_789666109", true);
    if (giant_ball2 && !lithograph2 && !(this->flags & 0x40000))
      setFlag("MainField_DgnObj_RemainsLithogragh_A_02_2456751716", true);
    if (giant_ball3 && !lithograph3 && !(this->flags & 0x40000))
      setFlag("MainField_DgnObj_RemainsLithogragh_A_02_1822262999", true);
    if (!giant_dungeon && giant_ball1 && giant_ball2 && giant_ball3)
      setFlag("giant_dungeon", true);
  }


To use mods, you just need to select the SDCafiine option from the Homebrew Launcher, then boot your game immediately afterwards.
  if (flagIsSet("MainField_Weapon_Bow_071_2178255681"))
    setFlag("MainField_Weapon_Bow_071_2178255681", false);


== Cemu Emulator ==
  if (flagIsSet("BalladOfHeroes_Step02") && !flagIsSet("BalladOfHeroes_Step03"))
  {
    int defeatedCount =
      flagIsSet("Defeat_OneHitDungeon001") +
      flagIsSet("Defeat_OneHitDungeon002") +
      flagIsSet("Defeat_OneHitDungeon003") +
      flagIsSet("Defeat_OneHitDungeon004");


=== Download Cemu Emulator ===
    bool defeatedNonLockedOneHitDungeon = !Lock_OneHitDungeon001 && Defeat_OneHitDungeon001;
You can find the latest version of Cemu Emulator on the [http://cemu.info/ Official Cemu Website]
    defeatedNonLockedOneHitDungeon |= !Lock_OneHitDungeon002 && Defeat_OneHitDungeon002;
    defeatedNonLockedOneHitDungeon |= !Lock_OneHitDungeon003 && Defeat_OneHitDungeon003;
    defeatedNonLockedOneHitDungeon |= !Lock_OneHitDungeon004 && Defeat_OneHitDungeon004;


=== Setting up homebrew ===
    if ( defeatedNonLockedOneHitDungeon && defeatedCount >= 1 )
Follow [https://wiiu.hacks.guide/ this guide] to set up your Wii U console to use homebrew software, in order to allow you to dump the game files from your console to your PC.
    {
      if (!flagIsSet("BalladOfHeroes_Step02_Dungeon01"))
        setFlag("BalladOfHeroes_Step02_Dungeon01", true);
      if ( defeatedCount >= 2 )
      {
        if (!flagIsSet("BalladOfHeroes_Step02_Dungeon02"))
          setFlag("BalladOfHeroes_Step02_Dungeon02", true);
        if ( defeatedCount >= 3 )
        {
          if (!flagIsSet("BalladOfHeroes_Step02_Dungeon03"))
            setFlag("BalladOfHeroes_Step02_Dungeon03", true);
          if (defeatedCount >= 4 && !flagIsSet("BalladOfHeroes_Step2_Dungeon4"))
            setFlag("BalladOfHeroes_Step2_Dungeon4", true);
        }
      }
    }
  }


=== Dumping the game files ===
  if (flagIsSet("IsGet_Armor_005_Head") &&
To play BotW on Cemu, you'll need to [[Help:Dumping games|dump the game files]] from the console to your computer. Then run the <code>U-King.rpx</code> file from Cemu to boot the game.
      flagIsSet("IsGet_Armor_005_Upper") &&
      flagIsSet("IsGet_Armor_005_Lower") &&
      !(this->flags & 0x40000))
  {
    setFlag("CompleteDungeon_Finish", true);
  }


=== Installing the DLC ===
  if (flagIsSet("NightStoneBreak") && !flagIsSet("NightStoneDungeonAppear"))
If you dumped the game's add-on content (aoc) files, follow [http://compat.cemu.info/wiki/Tutorial:How_to_install_a_DLC this guide] to install them in Cemu.
    setFlag("NightStoneBreak", false);


=== Setting up and Maximising Performance ===
  if (flagIsSet("Animal_Forest_Finish") &&
Now that you have Cemu and your games files, it is recommended you use [http://compat.cemu.info/wiki/Serfrosts_Cemu_Setup_Guide Serfrosts Cemu Setup Guide] to maximise performance on your hardware before installing mods.
      flagIsSet("HateeluMini_Treasure_Finish") &&
      flagIsSet("Thunder_Sword_Finish") &&
      flagIsSet("Relief_Landing_Finish") &&
      flagIsSet("TwoWheels_Finish") &&
      flagIsSet("Shadow_Sign_Finish") &&
      flagIsSet("MouthofDragon_Finish") &&
      flagIsSet("BloodyMoonRelief_Finish") &&
      flagIsSet("Rito_BrosRock_Finish"))
  {
    setFlag("Npc_Musician_Come", true);
  }
}
</source>


=== Installing mods with the graphic pack menu ===
[[Category:Internals]]
Cemu uses "graphic packs" to install mods without overwriting any of the base files, allowing you to easily install or uninstall mods without leaving any trace.
[[Category:Game mechanics]]
 
Graphic packs are installed by placing the unzipped folder in <code>Cemu/graphicPacks/</code>. Note that most newer mods will come packaged as a graphic pack, or have a graphic pack option.
 
To check that the mod is a graphic pack, open the mod folder within <code>Cemu/graphicPacks/</code>. A graphic pack will have a file called <code>rules.txt</code> next to the <code>content</code> and/or <code>aoc</code> folder.
 
 
If a mod is not packaged as a graphic pack you will have to package it yourself, otherwise skip to the end of this section. This method works for versions of Cemu 1.15.1+
 
# Create a new folder inside <code>Cemu/graphicPacks/</code> named after the mod you want to use.
# Inside that folder, create a folder named <code>content</code>. Your mod files will go in here. (Mods will often include a <code>content</code> folder already to make things clear.)
# Create a file named <code>rules.txt</code> next to the <code>content</code> folder (if the downloaded mod doesn't already include one). Use this example as a template:
 
[Definition]
titleIds = 00050000101C9300,00050000101C9400,00050000101C9500
name = <Mod Name>
path = "The Legend of Zelda: Breath of the Wild/Mods/<Mod Name>"
description = <Mod description here>
version = 3
fsPriority = 100
<code>version</code> must be set to 3 to work correctly. <code>fsPriority</code> determines the order in which mods are prioritized - higher numbers prioritize that mod's files over other mods. Mods without an <code>fsPriority</code> entry specified will default to 100.
 
 
Once a mod has been added, simply enable it from Cemu's graphic pack menu to use it. You can find this menu in <code>Options > Graphic Packs</code> or by right-clicking a game and selecting <code>Edit Graphic Packs</code>.
Note that most mods should not be enabled or disabled while the game is running.
 
=== Installing mods using BCML ===
Mods that are already packaged as a graphic pack can also be installed using [[Help:Tools/BCML|BCML]], a mod loading tool. In addition to being simpler than manually extracting and enabling the mod, BCML is designed to resolve certain kinds of conflicts between different mods. Mods that modify the [[RSTB]], the same [[SARC]] files, or [[Message archives]] will not function properly together unless the changes are merged. BCML does this automatically. To install mods with BCML:
 
# Install BCML using the instructions [[Help:Tools/BCML#Setup|here]].
# '''Command line version''': Install a mod by running <code>bcml install path\to\mod.zip</code>.  {{CLI help}} BCML will ask you to specify the directory where Cemu is installed first.
# '''Graphical version''': Open the GUI by running <code>bcml-gui</code>. {{CLI help}} Select the directory where Cemu is intalled. Then click "Install" and select the mod you want to install.
 
BCML should automatically enable installed mods in Cemu, but check to make sure by opening the Cemu graphic pack menu and looking in the "BCML Mods" category.
 
== Switch ==
 
=== Setting up homebrew ===
Follow [https://guide.sdsetup.com this guide] to set up your Switch console to use homebrew software.
 
This tutorial uses Atmosphère Custom Firmware (CFW). It is strongly recommended '''not''' to use other CFWs as they tend to be outdated, unsafe and/or use stolen code from Atmosphère.
{{warning|text=Running homebrew on your console may lead to it getting banned from Nintendo's online services (including eShop and game updates). Enabling Airplane Mode will not help, as telemetry reports are saved and sent to Nintendo the next time you connect to the internet.
 
However, this risk is very minimal as long as you are sensible and only use a safe, sane CFW (Atmosphère) and mods on offline games (don't install NSPs or pirate games!) as Atmosphère does not leave any trace on the system and disables some system telemetry.
 
If you are paranoid, turn on Airplane Mode ''before running homebrew for the first time'', then make a full system backup, and always stay offline until you restore that clean backup.}}
 
=== Disabling telemetry reports ===
The Switch version of ''Breath of the Wild'' sends many [[telemetry]] reports so when you are using mods that modify gameplay in a detectable way or add new content in any way, it is strongly recommended to disable telemetry reports because they are used by Zelda developers to understand how people play BotW and also to help them fix bugs.
 
Mods that modify actors are especially dangerous as they might cause the game to use the ActorSystem emergency heap and trigger many memory-related play reports.
 
To disable problematic telemetry reports:
 
* For 1.5.0, download this [http://static.zeldamods.org/patch_switch150_no_telemetry.ips patch], put it in <code>/atmosphere/exefs_patches/botw_no_telemetry/</code> (create new folders if required) and rename the file to <code>16A91992BBA71201E98756F3BC8F5D2F.ips</code>. This patch works for the Switch 1.5.0 [[executable]] only (build ID: 16A91992BBA71201E98756F3BC8F5D2F).
 
* For 1.6.0, download this [http://static.zeldamods.org/patch_switch160_no_telemetry.ips patch], put it at <code>/atmosphere/exefs_patches/botw_no_telemetry/</code> (create new folders if required) and rename the file to <code>8E9978D50BDD20B4C8395A106C27FFDE.ips</code>. This patch works for the Switch 1.6.0 [[executable]] only (build ID: 8E9978D50BDD20B4C8395A106C27FFDE).
 
=== Installing mods ===
 
# In the root of your MicroSD card, there should be a folder named <code>atmosphere</code>.
# Within that folder, there should be a folder named <code>contents</code>. Inside that, create a folder with the name of your game's Title ID. For BotW on Switch, the Title ID is <code>01007EF00011E000</code>. (In versions of Atmosphere prior to v0.10.0, the <code>contents</code> folder was instead called <code>titles</code>.)
# Inside that, make a folder called <code>romfs</code>. Your mod files will go in here. (Mods will often include all or part of this folder structure already, to make things easy.)
 
To use the mod, simply boot the console into CFW, then boot the game, and the mod will be active.
 
Note that mods are not permanently installed on the console. To remove all installed mods, simply delete <code>/atmosphere/contents/01007EF00011E000</code>.
[[Category:Guides]]

Revision as of 06:37, 10 January 2020

To ensure that quests do not become uncompletable if the player leaves an area when they have only been partially solved, some GameData flags are always manually overwritten by the GameDataMgr when a stage is loaded.

GameDataMgr is also responsible for always resetting the "get flag" for the Bow of Light to ensure it spawns and for making Kass spawn in Rito Village (see #Kass quests).

Kass quests

Sometime after the release of 1.0.0, completion checks for Kass' quests were added to the same GameDataMgr function. These are exactly the same as the ones that can be found in the BloodyMoonRelief<Musician_Check> event flow but implemented in the executable instead. The reason why Nintendo has decided to duplicate the checks is unknown, but it might be a workaround for some kind of event bug: Kass not spawning in Rito Village even after all of his quests have been completed used to be a widespread issue.

In 1.5.0, Npc_Musician_Come (the flag that causes Kass to spawn in Rito Village) is set iff the following flags are set:

  • Animal_Forest_Finish
  • HateeluMini_Treasure_Finish
  • Thunder_Sword_Finish
  • Relief_Landing_Finish
  • TwoWheels_Finish
  • Shadow_Sign_Finish
  • MouthofDragon_Finish
  • BloodyMoonRelief_Finish
  • Rito_BrosRock_Finish

Implementation in 1.5.0

// utility functions (inlined in the actual executable)
void GameDataMgr::setFlag(const sead::SafeString& flagName, bool value)
{
  if (this->paramB.changeOnlyOnce)
    return;
  if (!TriggerParam::setBoolByKey(*this->paramB.param1, value, flag_name, this->paramB.x, 1LL, 1))
    return;
  if (!this->paramB.propagateParam1Changes)
    return;
  TriggerParam::setBoolByKey(*this->paramB.param, value, flag_name, this->paramB.x, 1LL, 1);
}

bool GameDataMgr::flagIsSet(const sead::SafeString& flagName)
{
  bool value;
  return TriggerParam::getFlagByKey(*this->param.param1, &value, flagName, this->param.x) && value;
}

// 0x7100DD0A88
// called from GameScene
void GameDataMgr::getAndSetShrineQuestAndKassFlags()
{
  if (flagIsSet("DarkWoods_Giant_Clear") && !flagIsSet("DarkWoods_Finish"))
    setFlag("DarkWoods_Giant_Clear", false);

  if ( TriggerParam::getFlagByKey(*this->param.param1, &giant_ball1, "giant_ball1", this->param.x)
    && TriggerParam::getFlagByKey(*this->param.param1, &giant_ball2, "giant_ball2", this->param.x)
    && TriggerParam::getFlagByKey(*this->param.param1, &giant_ball3, "giant_ball3", this->param.x)
    && TriggerParam::getFlagByKey(*this->param.param1, &giant_dungeon, "giant_dungeon", this->param.x)
    && TriggerParam::getFlagByKey(*this->param.param1, &lithograph1, "MainField_DgnObj_RemainsLithogragh_A_02_789666109", this->param.x)
    && TriggerParam::getFlagByKey(*this->param.param1, &lithograph2, "MainField_DgnObj_RemainsLithogragh_A_02_2456751716", this->param.x)
    && TriggerParam::getFlagByKey(*this->param.param1, &lithograph3, "MainField_DgnObj_RemainsLithogragh_A_02_1822262999", this->param.x) )
  {
    if (giant_ball1 && !lithograph1 && !(this->flags & 0x40000))
      setFlag("MainField_DgnObj_RemainsLithogragh_A_02_789666109", true);
    if (giant_ball2 && !lithograph2 && !(this->flags & 0x40000))
      setFlag("MainField_DgnObj_RemainsLithogragh_A_02_2456751716", true);
    if (giant_ball3 && !lithograph3 && !(this->flags & 0x40000))
      setFlag("MainField_DgnObj_RemainsLithogragh_A_02_1822262999", true);
    if (!giant_dungeon && giant_ball1 && giant_ball2 && giant_ball3)
      setFlag("giant_dungeon", true);
  }

  if (flagIsSet("MainField_Weapon_Bow_071_2178255681"))
    setFlag("MainField_Weapon_Bow_071_2178255681", false);

  if (flagIsSet("BalladOfHeroes_Step02") && !flagIsSet("BalladOfHeroes_Step03"))
  {
    int defeatedCount =
      flagIsSet("Defeat_OneHitDungeon001") +
      flagIsSet("Defeat_OneHitDungeon002") +
      flagIsSet("Defeat_OneHitDungeon003") +
      flagIsSet("Defeat_OneHitDungeon004");

    bool defeatedNonLockedOneHitDungeon = !Lock_OneHitDungeon001 && Defeat_OneHitDungeon001;
    defeatedNonLockedOneHitDungeon |= !Lock_OneHitDungeon002 && Defeat_OneHitDungeon002;
    defeatedNonLockedOneHitDungeon |= !Lock_OneHitDungeon003 && Defeat_OneHitDungeon003;
    defeatedNonLockedOneHitDungeon |= !Lock_OneHitDungeon004 && Defeat_OneHitDungeon004;

    if ( defeatedNonLockedOneHitDungeon && defeatedCount >= 1 )
    {
      if (!flagIsSet("BalladOfHeroes_Step02_Dungeon01"))
        setFlag("BalladOfHeroes_Step02_Dungeon01", true);
      if ( defeatedCount >= 2 )
      {
        if (!flagIsSet("BalladOfHeroes_Step02_Dungeon02"))
          setFlag("BalladOfHeroes_Step02_Dungeon02", true);
        if ( defeatedCount >= 3 )
        {
          if (!flagIsSet("BalladOfHeroes_Step02_Dungeon03"))
            setFlag("BalladOfHeroes_Step02_Dungeon03", true);
          if (defeatedCount >= 4 && !flagIsSet("BalladOfHeroes_Step2_Dungeon4"))
            setFlag("BalladOfHeroes_Step2_Dungeon4", true);
        }
      }
    }
  }

  if (flagIsSet("IsGet_Armor_005_Head") &&
      flagIsSet("IsGet_Armor_005_Upper") &&
      flagIsSet("IsGet_Armor_005_Lower") &&
      !(this->flags & 0x40000))
  {
    setFlag("CompleteDungeon_Finish", true);
  }

  if (flagIsSet("NightStoneBreak") && !flagIsSet("NightStoneDungeonAppear"))
    setFlag("NightStoneBreak", false);

  if (flagIsSet("Animal_Forest_Finish") &&
      flagIsSet("HateeluMini_Treasure_Finish") &&
      flagIsSet("Thunder_Sword_Finish") &&
      flagIsSet("Relief_Landing_Finish") &&
      flagIsSet("TwoWheels_Finish") &&
      flagIsSet("Shadow_Sign_Finish") &&
      flagIsSet("MouthofDragon_Finish") &&
      flagIsSet("BloodyMoonRelief_Finish") &&
      flagIsSet("Rito_BrosRock_Finish"))
  {
    setFlag("Npc_Musician_Come", true);
  }
}