- Have python installed
- Download remap.py and put it next to the config file
inputUserMappings.xml
(Should be in ...\Cyberpunk 2077\r6\config) - Open a terminal,
cd
into the directory with the script, and runpython remap.py
- It should create a new file called
inputUserMappings2.xml
- Now rename
inputUserMappings.xml
to something else, and renameinputUserMappings2.xml
toinputUserMappings.xml
Last active
May 23, 2024 02:36
-
-
Save Gordin/6fd87fa7ba3b9f50fce4e614cd7c00c6 to your computer and use it in GitHub Desktop.
Script that remaps Keys in Cyberpunk 2077 from qwertz to dvorak and shifts everything one key to the right (to play with ESDF)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[tool.pyright] | |
include = ["."] | |
reportMissingImports = true | |
pythonVersion = "3.10" | |
pythonPlatform = "Windows" | |
executionEnvironments = [ | |
{ root = "." } | |
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
from lxml import objectify, etree | |
dvorak_mapping = { | |
# key on (german) keyboard: letter in dvorak | |
'IK_A': 'IK_A', | |
'IK_B': 'IK_X', | |
'IK_C': 'IK_I', | |
'IK_D': 'IK_E', | |
'IK_E': 'IK_Period', | |
'IK_F': 'IK_U', | |
'IK_G': 'IK_I', | |
'IK_H': 'IK_D', | |
'IK_I': 'IK_C', | |
'IK_J': 'IK_H', | |
'IK_K': 'IK_T', | |
'IK_L': 'IK_N', | |
'IK_M': 'IK_M', | |
'IK_N': 'IK_B', | |
'IK_O': 'IK_R', | |
'IK_P': 'IK_L', | |
'IK_Q': 'IK_SingleQuote', | |
'IK_R': 'IK_P', | |
'IK_S': 'IK_O', | |
'IK_T': 'IK_Y', | |
'IK_U': 'IK_G', | |
'IK_V': 'IK_K', | |
'IK_W': 'IK_Comma', | |
'IK_X': 'IK_Q', | |
'IK_Y': 'IK_Semicolon', | |
'IK_Z': 'IK_F', | |
} | |
personal_mapping = { | |
'IK_SingleQuote': 'IK_Comma', | |
'IK_Comma': 'IK_Period', | |
'IK_Period': 'IK_P', | |
'IK_P': 'IK_Y', | |
'IK_Y': 'IK_F', | |
'IK_F': 'IK_G', | |
'IK_G': 'IK_C', | |
'IK_C': 'IK_R', | |
'IK_R': 'IK_L', | |
'IK_L': 'IK_Slash', | |
'IK_A': 'IK_O', | |
'IK_O': 'IK_E', | |
'IK_E': 'IK_U', | |
'IK_U': 'IK_I', | |
'IK_I': 'IK_D', | |
'IK_D': 'IK_H', | |
'IK_H': 'IK_T', | |
'IK_T': 'IK_N', | |
'IK_N': 'IK_S', | |
'IK_Semicolon': 'IK_Q', | |
'IK_Q': 'IK_J', | |
'IK_J': 'IK_K', | |
'IK_K': 'IK_X', | |
'IK_X': 'IK_B', | |
'IK_B': 'IK_M', | |
'IK_M': 'IK_V', | |
'IK_LShift': 'IK_A', | |
'IK_Shift': 'IK_A', | |
'IK_LControl': 'IK_Semicolon', | |
'IK_Ctrl': 'IK_Semicolon', | |
'IK_Left': 'ignore', | |
'IK_Right': 'ignore', | |
'IK_Up': 'ignore', | |
'IK_Down': 'ignore', | |
'IK_Enter': 'ignore', | |
'IK_Backspace': 'ignore', | |
'IK_Space': 'ignore', | |
'IK_Escape': 'ignore', | |
'IK_Tab': 'ignore', | |
'IK_Alt': 'ignore', | |
'ReportIssue_ButtonGroup': 'ignore', | |
'IK_1': 'ignore', | |
'IK_2': 'ignore', | |
'IK_3': 'ignore', | |
'IK_4': 'ignore', | |
'IK_5': 'ignore', | |
'IK_6': 'ignore', | |
'IK_7': 'ignore', | |
'IK_8': 'ignore', | |
'IK_9': 'ignore', | |
'IK_0': 'ignore', | |
'IK_Home': 'ignore', | |
'IK_RControl': 'ignore', | |
'IK_RShift': 'ignore', | |
'IK_1_LShift': 'ignore', | |
'IK_2_LShift': 'ignore', | |
'IK_3_LShift': 'ignore', | |
'IK_CapsLock': 'ignore', | |
} | |
def loadXML(): | |
f = open("inputUserMappings.xml", "r", encoding="utf8") | |
text = f.read() | |
return objectify.fromstring(text) | |
def ignoreButton(name: str): | |
if name.startswith('IK_Pad'): | |
return True | |
if name.startswith('IK_PAD'): | |
return True | |
if name.startswith('IK_Mouse'): | |
return True | |
if name.startswith('IK_NumPad'): | |
return True | |
if name.startswith('IK_PS4'): | |
return True | |
if name.startswith('IK_F') and name != 'IK_F': | |
return True | |
if 'Mouse' in name: | |
return True | |
if 'Thumb' in name: | |
return True | |
return False | |
def remapButton(button): | |
old_id = button.attrib['id'] | |
if ignoreButton(old_id): | |
return | |
new_id = dvorak_mapping.get(old_id) | |
if (new_id): | |
button.attrib['id'] = new_id | |
print('remapped {} to {}'.format(old_id, new_id)) | |
old_id = button.attrib['id'] | |
new_id = personal_mapping.get(old_id) | |
if new_id == 'ignore': | |
pass | |
elif new_id: | |
button.attrib['id'] = new_id | |
print('shift {} over to {}'.format(old_id, new_id)) | |
else: | |
print('missing mapping for {}'.format(old_id)) | |
def main(): | |
tree = loadXML() | |
children = tree.getchildren() | |
for mapping in list(filter(lambda x: x != '', children)): | |
buttons = mapping.getchildren() | |
for button in list(filter(lambda x: x.tag == 'button', buttons)): | |
# print(button.attrib) | |
remapButton(button) | |
return tree | |
if __name__ == "__main__": | |
tree = main() | |
xmlString = etree.tostring(tree, pretty_print=True, encoding='unicode') | |
print(xmlString) | |
with open('inputUserMappings2.xml', 'w', encoding='utf8') as f: | |
f.write('<?xml version="1.0"?>\n') | |
f.write(xmlString) |
thanks for your reply! it does work for some keybinds but not all, some the game doesn't like, I am however running the game via proton on linux so maybe that is messing with it... i will figure something out eventually, for now, I have just been playing with a controller. anyhow thanks! ^^
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@micr0-dev It worked fine when I wrote it 2 years ago... Haven't played Cyberpunk since then.
I'd be surprised if this could crash the game though since it just shuffles existing keys in a config file around. Maybe the game had added more keybinds in the last years and now some keys are bound two multiple things and it doesn't like that. I'm just randomly guessing though, since I haven't played in a long time. Maybe you can even do all the rebinds in the game now ^^ (I'm guessing not though, otherwise why would anyone look at this script...)