diff --git a/Toby Doom Launcher.py b/Toby Doom Launcher.py index 56da56d..ed7f2dc 100755 --- a/Toby Doom Launcher.py +++ b/Toby Doom Launcher.py @@ -941,8 +941,20 @@ class DoomLauncher(QMainWindow): self.tobyVersion = TOBY_VERSION self.speechHandler = SpeechHandler(self.configFile) self.iwadSelector = IWADSelector() # Add IWAD selector + self.gameProcess = None # Track running game process self.init_launcher_ui() + def closeEvent(self, event): + """Handle application close event""" + # Terminate any running game process + if self.gameProcess and self.gameProcess.poll() is None: + try: + self.gameProcess.terminate() + self.gameProcess.wait(timeout=2) + except: + self.gameProcess.kill() + event.accept() + def check_and_fix_controls(self): """Check and fix control bindings in GZDoom configuration for all game types.""" if not self.configFile.exists(): @@ -1462,14 +1474,16 @@ class DoomLauncher(QMainWindow): return gameFiles.append(str(tobyMod)) - # Handle map selection right after TobyAccMod if specified + selectedMapPath = None # Store map selection for later if needed + + # Handle map selection - either now or store for later if config.get('use_map_menu', False) and 'submenu' not in config: mapFiles = ["None"] # Start with None option mapsDir = self.gamePath / "Addons/MAPS" if mapsDir.exists(): # Include both .wad and .pk3 files for maps for extension in ["*.wad", "*.pk3"]: - mapFiles.extend([p.name for p in mapsDir.glob(extension) + mapFiles.extend([p.name for p in mapsDir.glob(extension) if p.name not in ["TobyDeathArena_V2-0.wad"]]) # Add Operation MDK as special case @@ -1504,12 +1518,21 @@ class DoomLauncher(QMainWindow): else: mapPath = str(self.gamePath / "Addons/MAPS" / selectedMap) if Path(mapPath).exists(): - gameFiles.append(mapPath) + # Check if map should be added after files + if config.get('map_after_files', False): + selectedMapPath = mapPath # Store for later + else: + gameFiles.append(mapPath) # Add now (current behavior) if selectedMap == "TobyDoomLevels.pk3": musicRenamer = self.gamePath / "Toby-Doom-Level-Music-Renamer.pk3" if musicRenamer.exists(): - gameFiles.append(str(musicRenamer)) + if config.get('map_after_files', False): + # Store renamer path along with map + if selectedMapPath: + selectedMapPath = [selectedMapPath, str(musicRenamer)] + else: + gameFiles.append(str(musicRenamer)) # Handle submenu if present if 'submenu' in config: @@ -1564,6 +1587,13 @@ class DoomLauncher(QMainWindow): gameFiles.append(str(optPath)) break # Only add the first optional file found + # Add map after files if specified (overrides earlier map packs) + if selectedMapPath: + if isinstance(selectedMapPath, list): + gameFiles.extend(selectedMapPath) + else: + gameFiles.append(selectedMapPath) + # Get any custom flags gameFlags = config.get('flags', []) @@ -2561,15 +2591,16 @@ class DoomLauncher(QMainWindow): # Add script generation option to map selection dialog generateScript = False + selectedMapPath = None # Store map selection for later if needed - # Handle map selection right after TobyAccMod if specified + # Handle map selection - either now or store for later if config.get('use_map_menu', False) and 'submenu' not in config: mapFiles = ["None"] # Start with None option mapsDir = self.gamePath / "Addons/MAPS" if mapsDir.exists(): # Include both .wad and .pk3 files for maps for extension in ["*.wad", "*.pk3"]: - mapFiles.extend([p.name for p in mapsDir.glob(extension) + mapFiles.extend([p.name for p in mapsDir.glob(extension) if p.name not in ["TobyDeathArena_V2-0.wad"]]) # Add Operation MDK as special case @@ -2618,12 +2649,21 @@ class DoomLauncher(QMainWindow): else: mapPath = str(self.gamePath / "Addons/MAPS" / selectedMap) if Path(mapPath).exists(): - gameFiles.append(mapPath) + # Check if map should be added after files + if config.get('map_after_files', False): + selectedMapPath = mapPath # Store for later + else: + gameFiles.append(mapPath) # Add now (current behavior) if selectedMap == "TobyDoomLevels.pk3": musicRenamer = self.gamePath / "Toby-Doom-Level-Music-Renamer.pk3" if musicRenamer.exists(): - gameFiles.append(str(musicRenamer)) + if config.get('map_after_files', False): + # Store renamer path along with map + if selectedMapPath: + selectedMapPath = [selectedMapPath, str(musicRenamer)] + else: + gameFiles.append(str(musicRenamer)) # Handle submenu if present if 'submenu' in config: @@ -2680,6 +2720,13 @@ class DoomLauncher(QMainWindow): gameFiles.append(str(optPath)) break # Only add the first optional file found + # Add map after files if specified (overrides earlier map packs) + if selectedMapPath: + if isinstance(selectedMapPath, list): + gameFiles.extend(selectedMapPath) + else: + gameFiles.append(selectedMapPath) + # Get any custom flags gameFlags = config.get('flags', []) @@ -3180,6 +3227,9 @@ class DoomLauncher(QMainWindow): env=dict(os.environ, PYTHONUNBUFFERED="1") ) + # Track the process for cleanup + self.gameProcess = process + # Start speech processing thread speechThread = threading.Thread( target=self.speechHandler.speak_thread, @@ -3207,6 +3257,14 @@ if __name__ == "__main__": # Converts version number to required format (e.g., 8.0 -> "8-0") TOBY_VERSION: Final[str] = f"{int(TOBY_VERSION_NUMBER)}-{int(TOBY_VERSION_NUMBER * 10 % 10)}" setproctitle("Toby Doom Launcher") + + # Set up signal handling for clean shutdown + import signal + def signal_handler(sig, frame): + QApplication.quit() + signal.signal(signal.SIGINT, signal_handler) + signal.signal(signal.SIGTERM, signal_handler) + app = QApplication(sys.argv) window = DoomLauncher() window.show()