internal static bool OpenFMInEditor(FanMission fm)
        {
            #region Checks (specific to DromEd)

            // This should never happen because our menu item is supposed to be hidden for Thief 3 FMs.
            if (!GameIsDark(fm.Game))
            {
                Log("FM game type is not a Dark Engine game.\r\n" +
                    "FM: " + (!fm.Archive.IsEmpty() ? fm.Archive : fm.InstalledDir) + "\r\n" +
                    "fm.Game was: " + fm.Game, stackTrace: true);
                Dialogs.ShowError(ErrorText.FMGameTypeIsNotDark);
                return(false);
            }

            GameIndex gameIndex = GameToGameIndex(fm.Game);

            string gamePath = Config.GetGamePath(gameIndex);
            if (gamePath.IsEmpty())
            {
                Log("Game path is empty for " + gameIndex, stackTrace: true);
                Dialogs.ShowError(gameIndex + ":\r\n" + ErrorText.GamePathEmpty);
                return(false);
            }

            string editorExe = Config.GetEditorExe_FromDisk(gameIndex);
            if (editorExe.IsEmpty())
            {
                Log("Editor executable not found.\r\n" +
                    "FM:" + (!fm.Archive.IsEmpty() ? fm.Archive : fm.InstalledDir) + "\r\n" +
                    "Editor executable: " + editorExe);
                Dialogs.ShowError(fm.Game == Game.SS2
                    ? LText.AlertMessages.ShockEd_ExecutableNotFound
                    : LText.AlertMessages.DromEd_ExecutableNotFound);
                return(false);
            }

            #endregion

            // Just in case, and for consistency
            Paths.CreateOrClearTempPath(Paths.StubCommTemp);

            if (gameIndex is GameIndex.Thief1 or GameIndex.Thief2)
            {
                GameConfigFiles.FixCharacterDetailLine(gamePath);
            }
            // We don't need to do this here, right?
            SetUsAsSelector(gameIndex, gamePath, PlaySource.Editor);

            // Since we don't use the stub currently, set this here
            // NOTE: DromEd game mode doesn't even work for me anymore. Black screen no matter what. So I can't test if we need languages.
            GameConfigFiles.SetCamCfgLanguage(gamePath, "");

            // Why not
            GenerateMissFlagFileIfRequired(fm);

            // We don't need the stub for DromEd, cause we don't need to pass anything except the fm folder
            StartExe(editorExe, gamePath, "-fm=\"" + fm.InstalledDir + "\"");

            return(true);
        }
        internal static bool PlayOriginalGame(GameIndex game, bool playMP = false)
        {
            (bool success, string gameExe, string gamePath) =
                CheckAndReturnFinalGameExeAndGamePath(game, playingOriginalGame: true, playMP);
            if (!success)
            {
                return(false);
            }
            Paths.CreateOrClearTempPath(Paths.StubCommTemp);

            if (game is GameIndex.Thief1 or GameIndex.Thief2)
            {
                GameConfigFiles.FixCharacterDetailLine(gamePath);
            }
            SetUsAsSelector(game, gamePath, PlaySource.OriginalGame);

#if !ReleaseBeta && !ReleasePublic
            string args = Config.ForceWindowed ? "+force_windowed" : "";
#else
            string args = "";
#endif
            string workingPath = Config.GetGamePath(game);
            var    sv          = GetSteamValues(game, playMP);
            if (sv.Success)
            {
                (_, gameExe, workingPath, args) = sv;
            }

            WriteStubCommFile(null, gamePath, originalT3: game == GameIndex.Thief3);

            StartExe(gameExe, workingPath, args);

            return(true);
        }
        private static bool PlayFM(FanMission fm, bool playMP = false)
        {
            if (!GameIsKnownAndSupported(fm.Game))
            {
                Log("Game is unknown or unsupported for FM " + (!fm.Archive.IsEmpty() ? fm.Archive : fm.InstalledDir) + "\r\n" +
                    "fm.Game was: " + fm.Game, stackTrace: true);
                Dialogs.ShowError(ErrorText.FMGameTypeUnknownOrUnsupported);
                return(false);
            }

            GameIndex gameIndex = GameToGameIndex(fm.Game);

            (bool success, string gameExe, string gamePath) =
                CheckAndReturnFinalGameExeAndGamePath(gameIndex, playingOriginalGame: false, playMP);
            if (!success)
            {
                return(false);
            }

            // Always do this for robustness, see below
            Paths.CreateOrClearTempPath(Paths.StubCommTemp);

            if (gameIndex is GameIndex.Thief1 or GameIndex.Thief2)
            {
                GameConfigFiles.FixCharacterDetailLine(gamePath);
            }
            SetUsAsSelector(gameIndex, gamePath, PlaySource.FM);

            string steamArgs   = "";
            string workingPath = Config.GetGamePath(gameIndex);
            var    sv          = GetSteamValues(gameIndex, playMP);

            if (sv.Success)
            {
                (_, gameExe, workingPath, steamArgs) = sv;
            }

            // 2019-10-31: Always use the stub now, in prep for matching FMSel's language stuff

            // BUG: Possible stub comm file not being deleted in the following scenario:
            // You launch a game through Steam, but the game doesn't actually launch (because you don't have
            // it in your Steam library or any other situation in which it gets cancelled). Because the game
            // never runs, it never deletes the stub comm file. The next time the game runs, it finds the stub
            // file and loads up whatever FM was specified. This won't happen if you launch an FM or original
            // game from AngelLoader, as we delete or overwrite the stub file ourselves before playing anything,
            // but if you were to run the game manually, it would load whatever FM was specified in the stub
            // once, and then delete it, so if you ran it again it would properly start the original game and
            // everything would be fine again.
            // I could solve it if there was a way to detect if we were being launched through Steam. I don't
            // know if there is, but then I could just specify a Steam=True line in the stub file, and then
            // if we're being launched through steam we read and act on it as usual, but if we're not, then
            // we just delete it and ignore.
            // I'll have to buy the games on Steam to test this. Or just buy one so I can have one game that
            // works and one that doesn't, so I can test both paths.

#if !ReleaseBeta && !ReleasePublic
            string args = !steamArgs.IsEmpty() ? steamArgs : Config.ForceWindowed ? "+force_windowed -fm" : "-fm";
#else
            string args = !steamArgs.IsEmpty() ? steamArgs : "-fm";
#endif

            GenerateMissFlagFileIfRequired(fm);

            WriteStubCommFile(fm, gamePath);

            StartExe(gameExe, workingPath, args);

            // Don't clear the temp folder here, because the stub program will need to read from it. It will
            // delete the temp file itself after it's done with it.

            return(true);
        }