class TekkenGameReader: def __init__(self): self.pid = -1 self.needReaquireGameState = True self.needReacquireModule = True self.module_address = 0 self.original_facing = None self.config_reader = ConfigReader('memory_address') self.player_data_pointer_offset = self.config_reader.get_property( 'player_data_pointer_offset', MemoryAddressOffsets.player_data_pointer_offset.value, lambda x: int(x, 16)) def GetValueFromAddress(self, processHandle, address, isFloat=False, is64bit=False): data = c.c_ulonglong() bytesRead = c.c_ulonglong() successful = ReadProcessMemory(processHandle, address, c.byref(data), c.sizeof(data), c.byref(bytesRead)) if not successful: e = GetLastError() print("ReadProcessMemory Error: Code " + str(e)) self.needReacquireModule = True self.needReaquireGameState = True self.pid = -1 if not is64bit: value = int(data.value) % pow(2, 32) else: value = int(data.value) if not isFloat: return (value) else: return struct.unpack("<f", struct.pack("<I", (value)))[0] def IsForegroundPID(self): pid = c.wintypes.DWORD() active = c.windll.user32.GetForegroundWindow() active_window = c.windll.user32.GetWindowThreadProcessId( active, c.byref(pid)) return pid.value == self.pid def GetWindowRect(self): if self.IsForegroundPID(): rect = c.wintypes.RECT() c.windll.user32.GetWindowRect( c.windll.user32.GetForegroundWindow(), c.byref(rect)) return rect else: return None def HasWorkingPID(self): return self.pid > -1 def GetUpdatedState(self): gameSnapshot = None if not self.HasWorkingPID(): self.pid = PIDSearcher.GetPIDByName( b'TekkenGame-Win64-Shipping.exe') if self.HasWorkingPID(): print("Tekken pid acquired: " + str(self.pid)) else: print("Tekken pid not acquired. Trying to acquire...") return gameSnapshot if (self.needReacquireModule): print("Trying to acquire Tekken library in pid: " + str(self.pid)) self.module_address = ModuleEnumerator.GetModuleAddressByPIDandName( self.pid, 'TekkenGame-Win64-Shipping.exe') if self.module_address == None: print( "TekkenGame-Win64-Shipping.exe not found. Likely wrong process id." ) elif (self.module_address != 0x140000000): print( "Unrecognized location for TekkenGame-Win64-Shipping.exe module. Tekken.exe Patch? Wrong process id?" ) else: print("Found TekkenGame-Win64-Shipping.exe") self.needReacquireModule = False if self.module_address != None: processHandle = OpenProcess(0x10, False, self.pid) try: player_data_base_address = self.GetValueFromAddress( processHandle, self.module_address + self.player_data_pointer_offset, is64bit=True) if player_data_base_address == 0: print("No fight detected. Gamestate not updated.") self.needReaquireGameState = True else: player_data_second_address = 0 best_frame_count = -1 second_address_base = self.GetValueFromAddress( processHandle, player_data_base_address, is64bit=True) for i in range( 8 ): # for rollback purposes, there are 8 copies of the game state, each one updatating once every 8 frames potential_second_address = second_address_base + ( i * MemoryAddressOffsets.rollback_frame_offset.value) potential_frame_count = self.GetValueFromAddress( processHandle, potential_second_address + GameDataAddress.frame_count.value) if potential_frame_count > best_frame_count: player_data_second_address = potential_second_address best_frame_count = potential_frame_count p1_bot = BotSnapshot() p2_bot = BotSnapshot() for data in PlayerDataAddress: p1_value = self.GetValueFromAddress( processHandle, player_data_second_address + data.value, IsDataAFloat(data)) p2_value = self.GetValueFromAddress( processHandle, player_data_second_address + MemoryAddressOffsets.p2_data_offset.value + data.value, IsDataAFloat(data)) p1_bot.player_data_dict[data] = p1_value p2_bot.player_data_dict[data] = p2_value bot_facing = self.GetValueFromAddress( processHandle, player_data_second_address + GameDataAddress.facing.value, IsDataAFloat(data)) #positionArrays = {} #for startingAddress in valuesOfPositionArrays: # positionArrays[startingAddress[0]] = [] # for i in range(16): # positionOffset = 32 #our xyz coordinate is 32 bytes, a 4 byte x, y, and z value followed by five 4 byte values that don't change # positionArrays[startingAddress[0]].append(TekkenGameReader.GetValueFromAddress(processHandle, player_data_second_address + startingAddress[1] + (i * positionOffset), startingAddress[2])) #for key in positionArrays: # positionArray = positionArrays[key] # gameData[key] = sum(positionArray)/float(len(positionArray)) if self.original_facing == None and best_frame_count > 0: self.original_facing = bot_facing > 0 self.needReaquireGameState = False p1_bot.Bake() p2_bot.Bake() gameSnapshot = GameSnapshot(p1_bot, p2_bot, best_frame_count, bot_facing) finally: CloseHandle(processHandle) return gameSnapshot def GetNeedReacquireState(self): return self.needReaquireGameState
class Overlay: def __init__(self, master, xy_size, window_name): print("Launching {}".format(window_name)) config_filename = "frame_data_overlay" self.tekken_config = ConfigReader(config_filename) is_windows_7 = 'Windows-7' in platform.platform() self.is_draggable_window = self.tekken_config.get_property(DisplaySettings.config_name(), DisplaySettings.overlay_as_draggable_window.name, False) self.is_minimize_on_lost_focus = self.tekken_config.get_property(DisplaySettings.config_name(), DisplaySettings.only_appears_when_Tekken_7_has_focus.name, True) self.is_transparency = self.tekken_config.get_property(DisplaySettings.config_name(), DisplaySettings.transparent_background.name, not is_windows_7) self.is_overlay_on_top = not self.tekken_config.get_property(DisplaySettings.config_name(), DisplaySettings.overlay_on_bottom.name, False) self.overlay_visible = False if master == None: self.toplevel = Tk() else: self.toplevel = Toplevel() self.toplevel.wm_title(window_name) self.toplevel.attributes("-topmost", True) self.background_color = CurrentColorScheme.dict[ColorSchemeEnum.background] if self.is_transparency: self.tranparency_color = CurrentColorScheme.dict[ColorSchemeEnum.transparent] self.toplevel.wm_attributes("-transparentcolor", self.tranparency_color) self.toplevel.attributes("-alpha", "0.75") else: if is_windows_7: print("Windows 7 detected. Disabling transparency.") self.tranparency_color = self.background_color self.toplevel.configure(background=self.tranparency_color) self.toplevel.iconbitmap('TekkenData/tekken_bot_close.ico') if not self.is_draggable_window: self.toplevel.overrideredirect(True) self.w = xy_size[0] self.h = xy_size[1] self.toplevel.geometry(str(self.w) + 'x' + str(self.h)) def update_location(self): if not self.is_draggable_window: tekken_rect = self.launcher.gameState.gameReader.GetWindowRect() if tekken_rect != None: x = (tekken_rect.right + tekken_rect.left) / 2 - self.w / 2 if self.is_overlay_on_top: y = tekken_rect.top else: y = tekken_rect.bottom - self.h - 10 self.toplevel.geometry('%dx%d+%d+%d' % (self.w, self.h, x, y)) if not self.overlay_visible: self.show() else: if self.overlay_visible: self.hide() def update_state(self): pass def hide(self): if self.is_minimize_on_lost_focus and not self.is_draggable_window: self.toplevel.withdraw() self.overlay_visible = False def show(self): self.toplevel.deiconify() self.overlay_visible = True def write_config_file(self): self.tekken_config.write()
class GUI_FrameDataOverlay(): def __init__(self, master): print("Tekken Bot Starting...") is_windows_7 = 'Windows-7' in platform.platform() self.tekken_config = ConfigReader("frame_data_overlay") self.is_draggable_window = self.tekken_config.get_property( DisplaySettings.config_name(), DisplaySettings.overlay_as_draggable_window.name, False) self.is_minimize_on_lost_focus = self.tekken_config.get_property( DisplaySettings.config_name(), DisplaySettings.only_appears_when_Tekken_7_has_focus.name, True) self.is_transparency = self.tekken_config.get_property( DisplaySettings.config_name(), DisplaySettings.transparent_background.name, not is_windows_7) self.is_overlay_on_top = not self.tekken_config.get_property( DisplaySettings.config_name(), DisplaySettings.overlay_on_bottom.name, False) self.enable_nerd_data = self.tekken_config.get_property( DisplaySettings.config_name(), "data_for_nerds", False) self.show_live_framedata = self.tekken_config.get_property( DisplaySettings.config_name(), DisplaySettings.tiny_live_frame_data_numbers.name, True) self.mode = OverlayMode.FrameData self.launcher = FrameDataLauncher(self.enable_nerd_data) self.overlay_visible = False if master == None: self.toplevel = Tk() else: self.toplevel = Toplevel() self.toplevel.wm_title("Tekken Bot: Frame Data Overlay") self.toplevel.attributes("-topmost", True) self.background_color = CurrentColorScheme.dict[ ColorSchemeEnum.background] if self.is_transparency: self.tranparency_color = CurrentColorScheme.dict[ ColorSchemeEnum.transparent] self.toplevel.wm_attributes("-transparentcolor", self.tranparency_color) self.toplevel.attributes("-alpha", "0.75") else: if is_windows_7: print("Windows 7 detected. Disabling transparency.") self.tranparency_color = self.background_color self.toplevel.configure(background=self.tranparency_color) self.w = 1000 self.h = 86 if self.enable_nerd_data: self.w += 400 self.toplevel.geometry(str(self.w) + 'x' + str(self.h)) self.toplevel.iconbitmap('TekkenData/tekken_bot_close.ico') if not self.is_draggable_window: self.toplevel.overrideredirect(True) self.s = Style() self.s.theme_use('alt') self.s.configure('.', background=self.background_color) self.s.configure( '.', foreground=CurrentColorScheme.dict[ColorSchemeEnum.advantage_text]) Grid.columnconfigure(self.toplevel, 0, weight=0) Grid.columnconfigure(self.toplevel, 1, weight=0) Grid.columnconfigure(self.toplevel, 2, weight=0) Grid.columnconfigure(self.toplevel, 3, weight=1) Grid.columnconfigure(self.toplevel, 4, weight=0) Grid.columnconfigure(self.toplevel, 5, weight=0) Grid.columnconfigure(self.toplevel, 6, weight=0) Grid.rowconfigure(self.toplevel, 0, weight=1) Grid.rowconfigure(self.toplevel, 1, weight=0) self.s.configure('TFrame', background=self.tranparency_color) self.fa_p1_var, fa_p1_label = self.create_frame_advantage_label(1) self.fa_p2_var, fa_p2_label = self.create_frame_advantage_label(5) self.l_margin = self.create_padding_frame(0) self.r_margin = self.create_padding_frame(6) self.l_seperator = self.create_padding_frame(2) self.r_seperator = self.create_padding_frame(4) if self.show_live_framedata: self.l_live_recovery = self.create_live_recovery(fa_p1_label, 0) self.r_live_recovery = self.create_live_recovery(fa_p2_label, 0) self.text = self.create_textbox(3) self.stdout = sys.stdout self.redirector = TextRedirector(self.stdout, self.text, self.s, self.fa_p1_var, self.fa_p2_var) self.text.configure(state="normal") self.text.delete("1.0", "end") #self.text.insert("1.0", "{:^5}|{:^8}|{:^9}|{:^7}|{:^5}|{:^5}|{:^8}|{:^5}|{:^5}|{:^7}|{:^5}|{}\n".format(" input ", "type", "startup", "block", "hit", "CH", "active", "track", "tot", "rec", "stun", "notes")) #self.redirector.populate_column_names(self.get_data_columns()) self.redirector.set_columns_to_print(self.get_data_columns()) self.text.configure(state="disabled") def get_data_columns(self): booleans_for_columns = [] for enum in DataColumns: bool = self.tekken_config.get_property(DataColumns.config_name(), enum.name, True) booleans_for_columns.append(bool) return booleans_for_columns def redirect_stdout(self): sys.stdout = self.redirector def restore_stdout(self): sys.stdout = self.stdout def create_padding_frame(self, col): padding = Frame(self.toplevel, width=10) padding.grid(row=0, column=col, rowspan=2, sticky=N + S + W + E) return padding def create_live_recovery(self, parent, col): live_recovery_var = StringVar() live_recovery_var.set('??') live_recovery_label = Label(parent, textvariable=live_recovery_var, font=("Segoe UI", 12), width=5, anchor='c') #live_recovery_label.grid(row=0, column=col, sticky =S+W) live_recovery_label.place(rely=0.0, relx=0.0, x=4, y=4, anchor=NW) return live_recovery_var def create_frame_advantage_label(self, col): frame_advantage_var = StringVar() frame_advantage_var.set('?') frame_advantage_label = Label(self.toplevel, textvariable=frame_advantage_var, font=("Consolas", 44), width=4, anchor='c', borderwidth=4, relief='ridge') frame_advantage_label.grid(row=0, column=col) return frame_advantage_var, frame_advantage_label def create_attack_type_label(self, col): attack_type_var = StringVar() attack_type_var.set('?') attack_type_label = Label(self.toplevel, textvariable=attack_type_var, font=("Verdana", 12), width=10, anchor='c', borderwidth=4, relief='ridge') attack_type_label.grid(row=1, column=col) return attack_type_var def create_textbox(self, col): textbox = Text(self.toplevel, font=("Consolas, 14"), wrap=NONE, highlightthickness=0, pady=0, relief='flat') # self.text.pack(side="top", fill="both", expand=True) textbox.grid(row=0, column=col, rowspan=2, sticky=N + S + W + E) #textbox.configure(background='black') #textbox.configure(background='white') textbox.configure(background=self.background_color) textbox.configure( foreground=CurrentColorScheme.dict[ColorSchemeEnum.system_text]) #textbox.configure(foreground='dark khaki') #textbox.configure(foreground='#839496') #textbox.configure(foreground='#657B83') return textbox def update_launcher(self): time1 = time.time() self.launcher.Update() if self.show_live_framedata: if len(self.launcher.gameState.stateLog) > 1: l_recovery = str( self.launcher.gameState.GetOppFramesTillNextMove() - self.launcher.gameState.GetBotFramesTillNextMove()) r_recovery = str( self.launcher.gameState.GetBotFramesTillNextMove() - self.launcher.gameState.GetOppFramesTillNextMove()) if not '-' in l_recovery: l_recovery = '+' + l_recovery if not '-' in r_recovery: r_recovery = '+' + r_recovery self.l_live_recovery.set(l_recovery) self.r_live_recovery.set(r_recovery) if not self.is_draggable_window: tekken_rect = self.launcher.gameState.gameReader.GetWindowRect() if tekken_rect != None: x = (tekken_rect.right + tekken_rect.left) / 2 - self.w / 2 if self.is_overlay_on_top: y = tekken_rect.top else: y = tekken_rect.bottom - self.h - 10 self.toplevel.geometry('%dx%d+%d+%d' % (self.w, self.h, x, y)) if not self.overlay_visible: self.show() else: if self.overlay_visible: self.hide() if self.launcher.gameState.gameReader.GetNeedReacquireState(): self.restore_stdout() else: self.redirect_stdout() time2 = time.time() elapsed_time = 1000 * (time2 - time1) self.toplevel.after(max(2, 8 - int(round(elapsed_time))), self.update_launcher) def hide(self): if self.is_minimize_on_lost_focus and not self.is_draggable_window: self.toplevel.withdraw() self.overlay_visible = False def show(self): self.toplevel.deiconify() self.overlay_visible = True def set_columns_to_print(self, columns_to_print): self.redirector.set_columns_to_print(columns_to_print) def update_column_to_print(self, enum, value): self.tekken_config.set_property(DataColumns.config_name(), enum.name, value) self.write_config_file() def write_config_file(self): self.tekken_config.write()
class GUI_FrameDataOverlay(Tk): def __init__(self): print("Tekken Bot Starting...") is_windows_7 = 'Windows-7' in platform.platform() self.tekken_config = ConfigReader("frame_data_overlay") self.is_draggable_window = self.tekken_config.get_property("independent_window_mode", True, lambda x: not "0" in str(x)) self.is_minimize_on_lost_focus = self.tekken_config.get_property("minimize_on_lost_focus", True, lambda x: not "0" in str(x)) self.is_transparency = self.tekken_config.get_property("transparency", not is_windows_7, lambda x: not "0" in str(x)) self.enable_nerd_data = self.tekken_config.get_property("data_for_nerds", False, lambda x: not "0" in str(x)) self.launcher = FrameDataLauncher(self.enable_nerd_data) self.overlay_visible = False Tk.__init__(self) self.wm_title("Tekken Bot: Frame Data Overlay") self.attributes("-topmost", True) #self.background_color = '#002B36' self.background_color = 'gray10' if self.is_transparency: self.wm_attributes("-transparentcolor", "white") self.attributes("-alpha", "0.75") self.tranparency_color = 'white' else: if is_windows_7: print("Windows 7 detected. Disabling transparency.") self.tranparency_color = self.background_color self.configure(background=self.tranparency_color) self.w = 820 self.h = 96 if self.enable_nerd_data: self.w += 400 self.geometry( str(self.w) + 'x' + str(self.h)) self.iconbitmap('TekkenData/tekken_bot_close.ico') if not self.is_draggable_window: self.overrideredirect(True) self.s = Style() self.s.theme_use('alt') self.s.configure('.', background=self.background_color) self.s.configure('.', foreground='black') Grid.columnconfigure(self, 0, weight=0) Grid.columnconfigure(self, 1, weight=0) Grid.columnconfigure(self, 2, weight=0) Grid.columnconfigure(self, 3, weight=1) Grid.columnconfigure(self, 4, weight=0) Grid.columnconfigure(self, 5, weight=0) Grid.columnconfigure(self, 6, weight=0) Grid.rowconfigure(self, 0, weight=1) Grid.rowconfigure(self, 1, weight=0) self.s.configure('TFrame', background=self.tranparency_color) self.fa_p1_var = self.create_frame_advantage_label(1) self.fa_p2_var = self.create_frame_advantage_label(5) self.l_margin = self.create_padding_frame(0) self.r_margin = self.create_padding_frame(2) self.l_seperator = self.create_padding_frame(4) self.r_seperator = self.create_padding_frame(6) self.text = self.create_textbox(3) self.stdout = sys.stdout self.redirector = TextRedirector(self.stdout, self.text, self.s, self.fa_p1_var, self.fa_p2_var) self.text.configure(state="normal") self.text.delete("1.0", "end") self.text.insert("1.0", "{:^5}|{:^8}|{:^9}|{:^8}|{:^5}|{:^5}|{:^5}|{}\n".format(" input ", "type", "startup", "block", "hit", "CH", "active", "notes")) self.text.configure(state="disabled") def redirect_stdout(self): sys.stdout = self.redirector def restore_stdout(self): sys.stdout = self.stdout def create_padding_frame(self, col): padding = Frame(width=10) padding.grid(row=0, column=col, rowspan=2, sticky=N + S + W + E) return padding def create_frame_advantage_label(self, col): frame_advantage_var = StringVar() frame_advantage_var.set('??') frame_advantage_label = Label(self, textvariable=frame_advantage_var, font=("Consolas", 44), width=4, anchor='c', borderwidth=4, relief='ridge') frame_advantage_label.grid(row=0, column=col) return frame_advantage_var def create_attack_type_label(self, col): attack_type_var = StringVar() attack_type_var.set('??') attack_type_label = Label(self, textvariable=attack_type_var, font=("Verdana", 12), width=10, anchor='c', borderwidth=4, relief='ridge') attack_type_label.grid(row=1, column=col) return attack_type_var def create_textbox(self, col): textbox = Text(self, font=("Consolas, 14"), wrap=NONE, highlightthickness=0, relief='flat') # self.text.pack(side="top", fill="both", expand=True) textbox.grid(row=0, column=col, rowspan=2, sticky=N + S + W + E) #textbox.configure(background='black') #textbox.configure(background='white') textbox.configure(background=self.background_color) textbox.configure(foreground='lawn green') #textbox.configure(foreground='dark khaki') #textbox.configure(foreground='#839496') #textbox.configure(foreground='#657B83') return textbox def update_launcher(self): time1 = time.time() self.launcher.Update() time2 = time.time() elapsed_time = 1000 * (time2 - time1) if not self.is_draggable_window: tekken_rect = self.launcher.gameState.gameReader.GetWindowRect() if tekken_rect != None: x = (tekken_rect.right + tekken_rect.left)/2 - self.w/2 y = tekken_rect.top self.geometry('%dx%d+%d+%d' % (self.w, self.h, x, y)) if not self.overlay_visible: self.show() else: if self.overlay_visible: self.hide() if self.launcher.gameState.gameReader.GetNeedReacquireState(): self.restore_stdout() else: self.redirect_stdout() #print(10 - int(round(elapsed_time))) self.after(max(2, 8 - int(round(elapsed_time))), self.update_launcher) def hide(self): if self.is_minimize_on_lost_focus and not self.is_draggable_window: self.withdraw() self.overlay_visible = False def show(self): self.deiconify() self.overlay_visible = True
class GUI_FrameDataOverlay(Tk): def __init__(self): print("Tekken Bot Starting...") self.tekken_config = ConfigReader("frame_data_overlay") self.launcher = FrameDataLauncher() self.overlay_visible = False Tk.__init__(self) self.wm_title("Tekken Bot: Frame Data Overlay") self.wm_attributes("-transparentcolor", "white") self.attributes("-topmost", True) self.attributes("-alpha", "0.75") self.iconbitmap('TekkenData/tekken_bot_close.ico') self.overrideredirect(True) self.configure(background='white') self.s = Style() self.s.theme_use('alt') self.s.configure('.', background='black') self.s.configure('.', foreground='black') Grid.columnconfigure(self, 0, weight=0) Grid.columnconfigure(self, 1, weight=1) Grid.columnconfigure(self, 2, weight=0) Grid.rowconfigure(self, 0, weight=1) Grid.rowconfigure(self, 1, weight=0) self.fa_p1_var = self.create_frame_advantage_label(0) self.fa_p2_var = self.create_frame_advantage_label(2) self.at_p1_var = self.create_attack_type_label(0) self.at_p2_var = self.create_attack_type_label(2) self.text = self.create_textbox() self.stdout = sys.stdout self.redirector = TextRedirector(self.stdout, self.text, self.s, self.fa_p1_var, self.fa_p2_var, self.at_p1_var, self.at_p2_var) self.redirect_stdout() print("move | type | startup | damage | block | hit | active") self.restore_stdout() def redirect_stdout(self): sys.stdout = self.redirector def restore_stdout(self): sys.stdout = self.stdout def create_frame_advantage_label(self, col): frame_advantage_var = StringVar() frame_advantage_var.set('??') frame_advantage_label = Label(self, textvariable=frame_advantage_var, font=("Consolas", 44), width=4, anchor='c', borderwidth=4, relief='ridge') frame_advantage_label.grid(row=0, column=col, sticky=E + W + N) return frame_advantage_var def create_attack_type_label(self, col): attack_type_var = StringVar() attack_type_var.set('??') attack_type_label = Label(self, textvariable=attack_type_var, font=("Verdana", 14), width=9, anchor='c', borderwidth=4, relief='ridge') attack_type_label.grid(row=1, column=col) return attack_type_var def create_textbox(self): textbox = Text(self, font=("Consolas, 13"), wrap="word", highlightthickness=2, relief='ridge') # self.text.pack(side="top", fill="both", expand=True) textbox.grid(row=0, column=1, rowspan=2, sticky=N + S + W + E) textbox.configure(background='black') textbox.configure(foreground='green') return textbox def update_launcher(self): self.launcher.Update() tekken_rect = self.launcher.gameState.gameReader.GetWindowRect() if tekken_rect != None: w = 720 h = 120 x = (tekken_rect.right + tekken_rect.left)/2 - w/2 y = tekken_rect.top self.geometry('%dx%d+%d+%d' % (w, h, x, y)) if not self.overlay_visible: self.show() else: if self.overlay_visible: self.hide() if self.launcher.gameState.gameReader.GetNeedReacquireState(): self.restore_stdout() else: self.redirect_stdout() self.after(7, self.update_launcher) def hide(self): if self.tekken_config.get_property("minimize_on_lost_focus", True, lambda x: not "0" in str(x) ): self.withdraw() self.overlay_visible = False def show(self): self.deiconify() self.overlay_visible = True
class TekkenGameReader: def __init__(self): self.pid = -1 self.needReaquireGameState = True self.needReacquireModule = True self.module_address = 0 self.original_facing = None self.config_reader = ConfigReader('memory_address') self.player_data_pointer_offset = self.config_reader.get_property( 'player_data_pointer_offset', MemoryAddressOffsets.player_data_pointer_offset.value, lambda x: int(x, 16)) def ReacquireEverything(self): self.needReacquireModule = True self.needReaquireGameState = True self.pid = -1 def GetValueFromAddress(self, processHandle, address, isFloat=False, is64bit=False): data = c.c_ulonglong() bytesRead = c.c_ulonglong() successful = ReadProcessMemory(processHandle, address, c.byref(data), c.sizeof(data), c.byref(bytesRead)) if not successful: e = GetLastError() print("ReadProcessMemory Error: Code " + str(e)) self.ReacquireEverything() if not is64bit: value = int(data.value) % pow(2, 32) else: value = int(data.value) if not isFloat: return (value) else: return struct.unpack("<f", struct.pack("<I", (value)))[0] def GetPlayerDataFrame(self, processHandle, address): data = c.create_string_buffer( MemoryAddressOffsets.rollback_frame_offset.value) bytesRead = c.c_ulonglong( MemoryAddressOffsets.rollback_frame_offset.value) successful = ReadProcessMemory(processHandle, address, c.byref(data), c.sizeof(data), c.byref(bytesRead)) if not successful: e = GetLastError() print("Getting Player Data Error: Code " + str(e)) #print('{} : {}'.format(address, self.GetValueFromFrame(data, PlayerDataAddress.simple_move_state))) return data def GetValueFromFrame(self, frame, offset, is_player_2, is_float=False): address = offset if is_player_2: address += MemoryAddressOffsets.p2_data_offset.value bytes = frame[address:address + 4] if not is_float: return struct.unpack("<I", bytes)[0] else: return struct.unpack("<f", bytes)[0] def IsForegroundPID(self): pid = c.wintypes.DWORD() active = c.windll.user32.GetForegroundWindow() active_window = c.windll.user32.GetWindowThreadProcessId( active, c.byref(pid)) return pid.value == self.pid def GetWindowRect(self): if self.IsForegroundPID(): rect = c.wintypes.RECT() c.windll.user32.GetWindowRect( c.windll.user32.GetForegroundWindow(), c.byref(rect)) return rect else: return None def HasWorkingPID(self): return self.pid > -1 def GetUpdatedState(self, rollback_frame=0): gameSnapshot = None if not self.HasWorkingPID(): self.pid = PIDSearcher.GetPIDByName( b'TekkenGame-Win64-Shipping.exe') if self.HasWorkingPID(): print("Tekken pid acquired: " + str(self.pid)) else: print("Tekken pid not acquired. Trying to acquire...") return gameSnapshot if (self.needReacquireModule): print("Trying to acquire Tekken library in pid: " + str(self.pid)) self.module_address = ModuleEnumerator.GetModuleAddressByPIDandName( self.pid, 'TekkenGame-Win64-Shipping.exe') if self.module_address == None: print( "TekkenGame-Win64-Shipping.exe not found. Likely wrong process id. Reacquiring pid." ) self.ReacquireEverything() elif (self.module_address != 0x140000000): print( "Unrecognized location for TekkenGame-Win64-Shipping.exe module. Tekken.exe Patch? Wrong process id?" ) else: print("Found TekkenGame-Win64-Shipping.exe") self.needReacquireModule = False if self.module_address != None: processHandle = OpenProcess(0x10, False, self.pid) try: player_data_base_address = self.GetValueFromAddress( processHandle, self.module_address + self.player_data_pointer_offset, is64bit=True) if player_data_base_address == 0: if not self.needReaquireGameState: print("No fight detected. Gamestate not updated.") self.needReaquireGameState = True else: last_eight_frames = [] second_address_base = self.GetValueFromAddress( processHandle, player_data_base_address, is64bit=True) for i in range( 8 ): # for rollback purposes, there are 8 copies of the game state, each one updatating once every 8 frames potential_second_address = second_address_base + ( i * MemoryAddressOffsets.rollback_frame_offset.value) potential_frame_count = self.GetValueFromAddress( processHandle, potential_second_address + GameDataAddress.frame_count.value) last_eight_frames.append( (potential_frame_count, potential_second_address)) if rollback_frame >= len(last_eight_frames): print( "ERROR: requesting {} frame of {} long rollback frame" .format(rollback_frame, len(last_eight_frames))) rollback_frame = len(last_eight_frames) - 1 best_frame_count, player_data_second_address = sorted( last_eight_frames, key=lambda x: -x[0])[rollback_frame] p1_bot = BotSnapshot() p2_bot = BotSnapshot() player_data_frame = self.GetPlayerDataFrame( processHandle, player_data_second_address) for offset_enum in PlayerDataAddress: #p1_value = self.GetValueFromAddress(processHandle, player_data_second_address + data.value, IsDataAFloat(data)) #p2_value = self.GetValueFromAddress(processHandle, player_data_second_address + MemoryAddressOffsets.p2_data_offset.value + data.value, IsDataAFloat(data)) p1_value = self.GetValueFromFrame( player_data_frame, offset_enum.value, False) p2_value = self.GetValueFromFrame( player_data_frame, offset_enum.value, True) p1_bot.player_data_dict[offset_enum] = p1_value p2_bot.player_data_dict[offset_enum] = p2_value #bot_facing = self.GetValueFromAddress(processHandle, player_data_second_address + GameDataAddress.facing.value, IsDataAFloat(offset_enum)) bot_facing = self.GetValueFromFrame( player_data_frame, GameDataAddress.facing.value, False) #for startingAddress in (PlayerDataAddress.x, PlayerDataAddress.y, PlayerDataAddress.z): # positionOffset = 32 # our xyz coordinate is 32 bytes, a 4 byte x, y, and z value followed by five 4 byte values that don't change # p1_coord_array = [] # p2_coord_array = [] # for i in range(16): # #p1_coord_array.append(self.GetValueFromAddress(processHandle, player_data_second_address + startingAddress.value + (i * positionOffset), True)) # #p2_coord_array.append(self.GetValueFromAddress(processHandle, player_data_second_address + startingAddress.value + (i * positionOffset) + MemoryAddressOffsets.p2_data_offset.value, True)) # p1_coord_array.append(self.GetValueFromFrame(player_data_frame, startingAddress.value + (i * positionOffset), False, True)) # p2_coord_array.append(self.GetValueFromFrame(player_data_frame, startingAddress.value + (i * positionOffset), True, True)) # p1_bot.player_data_dict[startingAddress] = p1_coord_array # p2_bot.player_data_dict[startingAddress] = p2_coord_array # #print("numpy.array([" + xyz_coord + "])") ##print("--------------------") if self.original_facing == None and best_frame_count > 0: self.original_facing = bot_facing > 0 if self.needReaquireGameState: print("Fight detected. Updating gamestate.") self.needReaquireGameState = False p1_bot.Bake() p2_bot.Bake() gameSnapshot = GameSnapshot(p1_bot, p2_bot, best_frame_count, bot_facing) finally: CloseHandle(processHandle) return gameSnapshot def GetNeedReacquireState(self): return self.needReaquireGameState