From 60ece5b489025f04a63185f726b7a0a91f67c199 Mon Sep 17 00:00:00 2001
From: Storm Dragon <stormdragon2976@gmail.com>
Date: Mon, 24 Mar 2025 21:39:02 -0400
Subject: [PATCH] Attempt to standardize controls for all mods.

---
 Toby Doom Launcher.py | 186 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 186 insertions(+)

diff --git a/Toby Doom Launcher.py b/Toby Doom Launcher.py
index b8d0fcc..49ad7f6 100755
--- a/Toby Doom Launcher.py	
+++ b/Toby Doom Launcher.py	
@@ -853,11 +853,197 @@ class DoomLauncher(QMainWindow):
             self.gamePath = Path.home() / ".local/games/doom"
             self.configFile = Path(os.getenv('XDG_CONFIG_HOME', Path.home() / '.config')) / 'gzdoom/gzdoom.ini'
 
+        # Make sure controls are set
+        self.checkAndFixControls()
+
         self.tobyVersion = TOBY_VERSION
         self.speechHandler = SpeechHandler(self.configFile)
         self.iwadSelector = IWADSelector()  # Add IWAD selector
         self.init_launcher_ui()
 
+    def checkAndFixControls(self):
+        """Check and fix control bindings in GZDoom configuration for all game types."""
+        if not self.configFile.exists():
+            print("Config file not found")
+            return False
+    
+        try:
+            # Read config file
+            with open(self.configFile, 'r') as f:
+                configLines = f.readlines()
+        
+            changesNeeded = False
+        
+            standardControls = {
+                'attack': 'Ctrl',
+                'altattack': 'Alt',
+                'use': 'Space',
+                'turn180': 'X'
+            }
+        
+            tobyAccessibilityControls = {
+                'E': 'pukename TurnCompass 1',  # Turn compass right
+                'R': 'pukename TurnCompass 0',  # Turn compass left
+                'Q': 'pukename CompassScript',  # Compass script
+                ';': 'netevent Toby_CheckLevelStats',  # Check level stats
+                "'": 'toby_proximity_toggle_keybind'   # Toggle proximity detector
+            }
+        
+            # Map section prefixes to their control sections
+            controlSections = {}
+        
+            currentSection = None
+            for i, line in enumerate(configLines):
+                line = line.strip()
+            
+                # Detect section headers
+                if line.startswith('[') and line.endswith(']'):
+                    currentSection = line[1:-1]
+                    
+                    # If this is a bindings section, extract the game prefix
+                    if '.Bindings' in currentSection:
+                        prefix = currentSection.split('.')[0]  # e.g., 'Doom', 'Heretic'
+                        controlSections[prefix] = controlSections.get(prefix, []) + [currentSection]
+                    
+                    continue
+                
+                # Check if we're in any Bindings section
+                if currentSection and '.Bindings' in currentSection and '=' in line:
+                    key, binding = line.split('=', 1)
+                    key = key.strip()
+                    binding = binding.strip()
+                    
+                    # Check if this line defines a binding we want to change
+                    for control, standardKey in standardControls.items():
+                        if binding == f"+{control}" and key != standardKey:
+                            # This is a binding we want to fix
+                            configLines[i] = f"{standardKey}=+{control}\n"
+                            changesNeeded = True
+                            print(f"Fixed {control} binding in {currentSection} from {key} to {standardKey}")
+            
+            # Check for the Toby accessibility controls across all game types
+            # For each game prefix, check if it has the correct CompassMod.Bindings, etc.
+            for prefix, sections in controlSections.items():
+                mainBindingSection = f"{prefix}.Bindings"
+                compassModSection = f"{prefix}.CompassMod.Bindings"
+                proximitySection = f"{prefix}.ProximityDetector.Bindings"
+                checkModSection = f"{prefix}.CheckMod.Bindings"
+                
+                # Check if the accessibility sections exist, create them if not
+                if compassModSection not in sections:
+                    # Add this section after the main Bindings section
+                    for i, line in enumerate(configLines):
+                        if line.strip() == f"[{mainBindingSection}]":
+                            # Find the next section
+                            nextSectionIdx = next((j for j in range(i+1, len(configLines)) if configLines[j].strip().startswith('[')), len(configLines))
+                            # Insert the new section
+                            configLines.insert(nextSectionIdx, f"\n[{compassModSection}]\n")
+                            configLines.insert(nextSectionIdx+1, "Q=pukename CompassScript\n")
+                            configLines.insert(nextSectionIdx+2, "F=pukename FaceNorth\n")
+                            configLines.insert(nextSectionIdx+3, "E=pukename TurnCompass 1\n")
+                            configLines.insert(nextSectionIdx+4, "R=pukename TurnCompass 0\n\n")
+                            changesNeeded = True
+                            print(f"Added {compassModSection} section")
+                            break
+                
+                if proximitySection not in sections:
+                    # Need to add this section
+                    for i, line in enumerate(configLines):
+                        if line.strip() == f"[{mainBindingSection}]":
+                            # Find the next section
+                            nextSectionIdx = next((j for j in range(i+1, len(configLines)) if configLines[j].strip().startswith('[')), len(configLines))
+                            # Insert the new section before the next section
+                            configLines.insert(nextSectionIdx, f"\n[{proximitySection}]\n")
+                            configLines.insert(nextSectionIdx+1, "'=toby_proximity_toggle_keybind\n\n")
+                            changesNeeded = True
+                            print(f"Added {proximitySection} section")
+                            break
+                
+                if checkModSection not in sections:
+                    # Need to add this section
+                    for i, line in enumerate(configLines):
+                        if line.strip() == f"[{mainBindingSection}]":
+                            # Find the next section
+                            nextSectionIdx = next((j for j in range(i+1, len(configLines)) if configLines[j].strip().startswith('[')), len(configLines))
+                            # Insert the new section before the next section
+                            configLines.insert(nextSectionIdx, f"\n[{checkModSection}]\n")
+                            configLines.insert(nextSectionIdx+1, "U=netevent Toby_CheckCoordinates\n")
+                            configLines.insert(nextSectionIdx+2, "H=netevent Toby_CheckHealth\n")
+                            configLines.insert(nextSectionIdx+3, "N=netevent Toby_CheckArmor\n")
+                            configLines.insert(nextSectionIdx+4, "B=netevent Toby_CheckAmmo\n")
+                            configLines.insert(nextSectionIdx+5, "K=netevent Toby_CheckKeys\n")
+                            configLines.insert(nextSectionIdx+6, "I=netevent Toby_CheckCurrentItem\n")
+                            configLines.insert(nextSectionIdx+7, ";=netevent Toby_CheckLevelStats\n\n")
+                            changesNeeded = True
+                            print(f"Added {checkModSection} section")
+                            break
+                
+                # Check if accessibility keys are correctly set in existing sections
+                currentSection = None
+                for i, line in enumerate(configLines):
+                    line = line.strip()
+                    
+                    # Detect section headers
+                    if line.startswith('[') and line.endswith(']'):
+                        currentSection = line[1:-1]
+                        continue
+                    
+                    # Process compass mod bindings
+                    if currentSection == compassModSection and '=' in line:
+                        key, binding = line.split('=', 1)
+                        key = key.strip()
+                        binding = binding.strip()
+                        
+                        # Check E and R keys for compass functions
+                        if key == 'E' and binding != 'pukename TurnCompass 1':
+                            configLines[i] = "E=pukename TurnCompass 1\n"
+                            changesNeeded = True
+                            print(f"Fixed E key in {compassModSection}")
+                        elif key == 'R' and binding != 'pukename TurnCompass 0':
+                            configLines[i] = "R=pukename TurnCompass 0\n"
+                            changesNeeded = True
+                            print(f"Fixed R key in {compassModSection}")
+                        elif key == 'Q' and binding != 'pukename CompassScript':
+                            configLines[i] = "Q=pukename CompassScript\n"
+                            changesNeeded = True
+                            print(f"Fixed Q key in {compassModSection}")
+                    
+                    # Process proximity detector bindings
+                    if currentSection == proximitySection and '=' in line:
+                        key, binding = line.split('=', 1)
+                        key = key.strip()
+                        binding = binding.strip()
+                        
+                        # Check apostrophe key for proximity toggle
+                        if key == "'" and binding != 'toby_proximity_toggle_keybind':
+                            configLines[i] = "'=toby_proximity_toggle_keybind\n"
+                            changesNeeded = True
+                            print(f"Fixed ' key in {proximitySection}")
+                    
+                    # Process check mod bindings
+                    if currentSection == checkModSection and '=' in line:
+                        key, binding = line.split('=', 1)
+                        key = key.strip()
+                        binding = binding.strip()
+                        
+                        # Check semicolon key for level stats
+                        if key == ";" and binding != 'netevent Toby_CheckLevelStats':
+                            configLines[i] = ";=netevent Toby_CheckLevelStats\n"
+                            changesNeeded = True
+                            print(f"Fixed ; key in {checkModSection}")
+            
+            # Write the config if needed
+            if changesNeeded:
+                with open(self.configFile, 'w') as f:
+                    f.writelines(configLines)
+                print("Updated GZDoom configuration with standard key bindings")
+                
+            return changesNeeded
+            
+        except Exception as e:
+            print(f"Error checking/fixing controls: {e}", file=sys.stderr)
+            return False
+    
     def generate_single_player_script(self):
         """Generate script for single player game"""
         selectedGame = self.gameCombo.currentText()