Problemstellung:
Bei der Belegung der Eingabegeräte hält sich Star Citizen nicht an Windows-Vorgaben sondern würfelt sich seine IDs selbst zusammen, so dass alle Tastenzuordnungen nicht mehr stimmen, wenn sich aus irgendeinem Grund die Reihenfolge der Eingabegeräte ändert. CIG selbst bietet zwar mit "pp_resortdevices" einen Konsolenbefehl an, mit dem man Joystick-IDs ändern kann - nur hat das zumindest bei mir noch nie funktioniert. Mary Lene Drake hat hier Wechselnde Joystick-IDs verhindern - Reihenfolge festlegen - Fragen rund um Crash & Star Citizen, technische Probleme etc. - C.R.A.S.H CORPS (crashcorps.space) eine Lösung vorgestellt, die durch EAC (EasyAntiCheat) allerdings nicht mehr verwendet werden kann. Tools wie HidHide, vJoy und Joystick Gremlin funktionieren bei mir zwar, sind aber recht aufwendig zu konfigurieren und zu pflegen.
Die meisten Lösungen, von denen ich bisher diesbezüglich weiß, sind in der Regel hardwarebasiert: Die Joysticks sind z.B. an einen Hub mit einzeln schaltbaren Ports angeschlossen und müssen in einer bestimmten Reihenfolge wieder aktiviert werden, nachdem die jeweiligen Treiber deinstalliert worden sind.
Ich wollte eine Software-Lösung haben, damit ich nicht unter meinem Tisch herumkriechen muss. Bisher hatte ich die Datei mit der Joystickbelegung manuell editiert, aber das ist mir im Lauf der Zeit auf die Nerven gegangen... Ich wollte auch mit Windows-Bordmitteln arbeiten, ohne zusätzliche Toos und dergleichen, daher habe ich versucht über die Powershell eine Lösung zu finden. Ausserdem bin ich programmiertechnisch ein Lauch und wollte mir einfach ein paar Powershell-Kenntnisse aneignen, das funktioniert bei mir immer besser anhand eines konkreten Problems statt durch irgendwelche synthetischen Aufgabestellungen in einer Laborumgebung.
Disclaimer 1: Ich bin KEIN Programmierer, sondern hab nur etwas mit der Powershell herumgespielt hat. Ich bin mir sicher, dass ich teilweise sehr "seltsam" vorgegangen bin: Falls sich jemand damit beschäftigen will, bin ich gerne bereit dazuzulernen und bin für entsprechende Hinweise dankbar. Falls es nicht funktioniert, schickt mir bitte Eure Original-Datei wie im Lösungsansatz, Schritt 1 beschrieben und ich sehe mir das mal an...
Disclaimer 2: Das folgende Script funktioniert NICHT bei HOSAS-Konfigurationen mit zwei oder mehreren identischen Devices: Ich frage die IDs der Geräte ab und wenn jemand z.B. zwei Thrustmaster T.16000 verwendet, dann sind die IDs identisch. Ich habe keine Lösung dafür gefunden die nicht ausgeufert wäre und vor allem: Ich kann das nicht testen, weil ich selbst nicht so ein Setup verwende...
Disclaimer 3: Es funktioniert NUR, wenn sich an der Anzahl und den verwendeten Joysticks inzwischen nichts geändert hat!
Disclaimer 4: Ich habe das folgende so gründlich wie möglich getestet - seid trotzdem vorsichtig, wenn Ihr es testet und erstellt Euch auf jeden Fall ein Backup der Konfigurationsdatei wie in Schritt 1 meines Lösungsansatzes beschrieben!
Disclaimer 5: Das ganze ist erstmal nur für den "internen Dienstgebrauch" - ich habe mal vor, das auf Spectrum zu veröffentlichen, aber dazu muss es vorher noch etwas poliert werden. Wenn es Probleme gibt, bin ich hier einfach im TS zu erreichen und Ihr kennt mich - in Spectrum muss ich mich unter Umständen mit Leuten herumschlagen, die das ganze ernst nehmen - und dies hier ist nur ein Hobby-Projekt ....
Mein Lösungsansatz:
1. Nachdem man einmal die gewünschte Joystickbelegung gefunden hat, erstellt man sich gemäß https://support.robertsspacein…nd-import-custom-profiles eine "Originaldatei" indem indem man im Spiel unter "Options" im Reiter "Keybindings" auf "Advanced Controls Customization" klickt und dann im Menü "Control Profiles" den Punkt "Save Controls Settings" auswählt. Im anschliessenden Fenster vergibt mal als Dateinamen "original" und speichert mit "Save".
Bilderquellen: ALLE (auch die nachfolgenden) Bilder sind eigene Screeshots!
Dies erstellt im Star Citizen-Verzeichnes des Users (bei mir z.B. "D:\Roberts Space Industries\StarCitizen\LIVE\USER\Client\0\Controls\Mappings") eine Datei
"layout_original_exported.xml"
Diese Datei fasst man nun nicht mehr an - es sei denn man stellt fest, dass einem eine andere Belegung der Joysticktasten besser behagt. Dann erstellt man wie beschrieben eine neue Originaldatei (die alte Datei sicherheitshalber vorher löschen oder umbenennen!).
2. Stellt man fest, das Star Citizen die Joysticks durcheinandergewürfelt hat, erstellt man eine Delta-Datei mit den Änderungen und nennt sie "changed".
Man erhält im Verzeichnis eine Datei
"layout_changed_exported.xml"
3. Nun öffnet man eine Powershell (Windows-Startbutton und "Powershell" eintippen)...
...und kopiert dort die folgenden Zeilen hinein:
## EingabeVariablen deklarieren
$SCPath = Read-Host -Prompt 'Input Location to Star Citizen-Mappings'
$OriginalFile = "$SCPath"+'\layout_original_exported.xml'
$ChangedFile = "$SCPath"+'\layout_changed_exported.xml'
$ResultFile = "$SCPath"+'\RESULT.xml'
## Arrays für Joystickbezeichnungen deklarieren
[System.Collections.ArrayList]$ProductOriginalArray = @()
[System.Collections.ArrayList]$ProductChangedArray = @()
[System.Collections.ArrayList]$ProductResultArray = @()
## Arrays für Joystick-IDs deklarieren
[System.Collections.ArrayList]$InstancesOriginalArray = @()
[System.Collections.ArrayList]$InstancesChangedArray = @()
[System.Collections.ArrayList]$InstancesResultArray = @()
## Arrays für Joystick-Identifier aus Typ, ID und Bezeichnung
[System.Collections.ArrayList]$OptionTypesOriginalArray = @()
[System.Collections.ArrayList]$OptionTypesChangedArray = @()
[System.Collections.ArrayList]$OptionTypesResultArray = @()
## Originaldatei einlesen
[xml]$xmlElm = Get-Content -Path $OriginalFile
[xml]$xmlAttr = Get-Content -Path $OriginalFile
## Ursprüngliche Joystickbelegungen umbenennen um Probleme beim späteren ändern zu vermeiden
$OriginaljsRenamed = Get-Content $OriginalFile -RAW | ForEach-Object {
$_ -replace 'js(\d{1})_', 'jsORIGINAL$1_'
}
## Ursprüngliche Joystickbezeichnungen einlesen (Tastatur wird ignoriert)
$ProductOriginalArray = $xmlAttr.ActionMaps.options | Where type -EQ 'joystick' | Select-Object -ExpandProperty 'product'
## Den ursprüngliche Joystickbezeichnungen zugeordnete IDs identifizieren
foreach ($i in $ProductOriginalArray){
$InstancesOriginalArray += $xmlAttr.ActionMaps.options |
Where product -eq $i |
Select-Object -ExpandProperty instance
}
## Datei mit den Änderungen einlesen
[xml]$xmlElm = Get-Content -Path $ChangedFile
[xml]$xmlAttr = Get-Content -Path $ChangedFile
## geänderte Joystickbezeichnungen einlesen (wird nicht verwendet: Joystick-Anzahl und Typ müssen identisch sein)
$ProductChangedArray = $xmlAttr.ActionMaps.options | Where type -EQ 'joystick' | Select-Object -ExpandProperty 'product'
## Die geänderten IDs werden gesucht
foreach ($i in $ProductOriginalArray){
$InstancesChangedArray += $xmlAttr.ActionMaps.options |
Where product -eq $i |
Select-Object -ExpandProperty instance
}
## Die Joystick-Identifier der Orginaldatei werden nachgebaut
for($i=0;$i-lt $ProductOriginalArray.count;$i++){
$OptionTypesOriginalArray += -join("<options type=`"joystick`" instance=`"",$InstancesOriginalArray[$i],"`" Product=`"",$ProductOriginalArray[$i],"")
}
## Die Joystick-Identifier der geänderten Datei werden nachgebaut
for($i=0;$i-lt $ProductOriginalArray.count;$i++){
$OptionTypesChangedArray += -join("<options type=`"joystick`" instance=`"",$InstancesChangedArray[$i],"`" Product=`"",$ProductOriginalArray[$i],"")
}
## Das Ergebnis der umbenannten ursprüngliche Joystickbelegungen wird in ein Array geschrieben
$InstancesResultArray = @($OriginaljsRenamed)
## Entsprechend der Anzahl der Joysticks werden die umbenannten Joystickbelegungen in die neuen Belegungen geändert
for($i=0;$i-lt $ProductOriginalArray.count;$i++){
$InstancesResultArray += ForEach-Object {
$InstancesResultArray[$i] -replace -join("jsORIGINAL",$InstancesOriginalArray[$i]), -join("js",$InstancesChangedArray[$i])
}
}
## Der letzte Durchlauf der Joystickbelegungen wird in ein Array geschrieben
$ProductResultArray = @($InstancesResultArray[$i])
## Die originalen Joystick-Identifier mit der alten ID werden durch die Identifier mit der neuen ID ersetzt
for($i=0;$i-lt $ProductOriginalArray.count;$i++){
$ProductResultArray += ForEach-Object {
$ProductResultArray[$i] -replace [Regex]::Escape($OptionTypesOriginalArray[$i]),$OptionTypesChangedArray[$i]
}
}
## Die Ausgabedatei wird erstellt
$ProductResultArray[$i] > $ResultFile
Nach dem Ausführen wird man zunächst nach dem Pfad der Mapping-Datei im Starcitizen-Verzeichnisses gefragt (also z.B. bei mir "D:\Roberts Space Industries\StarCitizen\LIVE\USER\Client\0\Controls\Mappings") - es wird davon ausgegangen, dass dort sowohl eine Datei "layout_original_exported.xml" als auch eine Datei "layout_changed_exported.xml" vorhanden sind.
Anschliessend findet man in diesem Pfad eine Datei "RESULT.xml" vor.
Die Powershell kann geschlossen werden, nachdem man sich vergewissert hat, dass eine Datei "RESULT.xml" im Star Citizen Mappings-Verzeichnis erstellt wurde.
4. Die erstellte Datei liest man in Star Citizen in der Konsole ein, indem innerhalb des Spiels die Konsole geöffnet wird (auf Deutschen Tastaturen ist das defaultmäßig das Caret "^", auf der Taste links neben der "1") und dann folgendes eingibt:
pp_RebindKeys
sowie
pp_RebindKeys RESULT.xml
Es ist nicht nötig, Star Citizen oder gar den PC neu zu starten.
5. Enjoy!
Nachsatz: Mir ist völlig klar, dass man noch verschiedene Mechanismen für die Fehlerbehandlung einbauen und dass man es für Anwender noch etwas freundlicher gestalten kann, mir kam es jetzt aber primär darauf an, den eigentlichen Algorithmus vorzustellen und weniger darauf, ein fertig poliertes Produkt zu präsentieren (Hey, wir spielen Star Citizen, wir sind Alpha-Builds gewohnt!)...