Repository: vakdev/VakScript Branch: main Commit: 2586ae5aa7ee Files: 26 Total size: 100.8 KB Directory structure: gitextract_s8_au0bo/ ├── .gitignore ├── Auto_Build_VakScript.bat ├── README.md ├── credits.txt ├── requirements.txt └── vakscript/ ├── autoconfig.py ├── autosmite.py ├── data.py ├── drawings.py ├── entities.py ├── gui.py ├── main.py ├── multiprocessing_functions.py ├── offsets.ini ├── orbwalker.py ├── read_manager.py ├── script_class.py ├── scripts/ │ ├── example.py │ └── example_turret_range.py ├── scripts_manager.py ├── settings.json ├── settings.py ├── spaceglider.py ├── stats.py ├── utils.py └── world_to_screen.py ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ .idea/ __pycache__/ ================================================ FILE: Auto_Build_VakScript.bat ================================================ @echo off REM Check if pip is installed pip --version > nul 2>&1 if %errorlevel%==0 ( echo Pip is already installed. echo Installing requirements... pip install -r requirements.txt ) else ( echo Pip is not installed. echo Installing pip... curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py python get-pip.py echo Pip installed successfully. echo Installing requirements... pip install -r requirements.txt ) REM Check if PyInstaller is installed pyinstaller --version >nul 2>&1 if %errorlevel% neq 0 ( echo PyInstaller is not installed. Installing... pip install pyinstaller pyinstaller --version >nul 2>&1 if %errorlevel% neq 0 ( echo Failed to install PyInstaller. echo. echo Press any key to exit... pause >nul exit /b ) ) REM Get the version from data.py for /f "tokens=2 delims=''" %%G in ('findstr "script_version" vakscript\offsets.ini') do ( set "version=%%G" ) REM Set the target folder name using the extracted version set "target_folder=VakScript v%version%" REM Build the Python code using PyInstaller and specify the output folder pyinstaller --onefile --noconsole --hidden-import script_class --distpath "%target_folder%" vakscript\main.py REM Copy required files to the target folder copy vakscript\drawings_font.ttf "%target_folder%" copy vakscript\settings.json "%target_folder%" copy vakscript\offsets.ini "%target_folder%" REM Copy wards folder to the target folder xcopy /E /I /Y vakscript\wards "%target_folder%\wards" REM Copy scripts folder to the target folder xcopy /E /I /Y vakscript\scripts "%target_folder%\scripts" @echo off setlocal EnableDelayedExpansion REM Generate a random alphanumeric string with length 12 set "characters=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" set "random_name=" for /L %%i in (1,1,12) do ( set /a "rand=!random! %% 62" for %%j in (!rand!) do set "random_name=!random_name!!characters:~%%j,1!" ) REM Rename the main.exe file to a random string ren "%target_folder%\main.exe" "!random_name!.exe" REM Remove the build folder if it exists if exist "%cd%\build" ( rmdir /s /q "%cd%\build" ) REM Remove all .spec files for %%i in (*.spec) do ( del "%%i" ) echo Build completed successfully! echo. echo Press any key to exit... pause >nul ================================================ FILE: README.md ================================================ # VakScript - Spaceglider for League of Legends (13.24+) Tool to automate kiting without any attack speed limit, game mode, or entity. The main purpose is help AD Carry players, not limited to any other role. It should be used only for practice, since it creates an huge advantage over a normal player. https://github.com/vakdev/VakScript/assets/93299015/d8412240-c2dc-45fd-a7aa-d93b6670bd67 ![spaceglider](https://github.com/vakdev/VakScript/assets/93299015/ee39794c-fcc0-4bc8-b705-00b56516337b) ## Functions #### 1. Target prio: - Nearest. - Most feed. - Less AA. #### 2. Lasthit: - Auto last hit minions. > If it's manual, you have to use a key. If it's auto, it will lasthit with Orbwalk key while enemies aren't in range. #### 3. Laneclear: - Auto kite minions. #### 4. Drawings: - Show current enemy position. - Show prioritized target. - Show current enemy health. - Show local player range. - Show enemy player range. - Show needed AA. - Show gold. - Show enemy ward/vision. - Limit position. - Limit drawings fps. #### 5. Auto Smite: - Including Blue / Red / Crab. #### 6. External Scripts: - Toggle external scripts ON/OFF. - Limit external scripts drawings fps. ## Usage 1. Download and Install Python 3.10.10 2. Download VakScript zip file. 3. Download and Install pyMeow zip release file. (https://github.com/qb-0/pyMeow) 4. Extract VakScript and install requirements: pip install -r requirements.txt 5. Start main.py ## Usage of Community Add-ons/Scripts 1. Head over to the community scripts channel on our discord. (https://discord.com/channels/977983459626733658/1181850771336212602) 2. Download a add-on of your choice. 3. Move said add-on to your scripts folder you can find it within the folder you got either from compiling Vak yourself, or by downloading a already compiled version through this repository's releases section. 4. Run the script. 5. Hop into a game and enjoy. ## Packaging to .EXE 1. Start Auto_Build_VakScript.bat. 2. Start builded script from VakScript v**.** folder as admin. ## About ### Based on outdated source: https://github.com/hrt/Lmeme ### Is it safe to use? - Yes, it doesn't use any internal game function. All it does is through external memory reading. ### Vakdev: - Discord group: https://discord.gg/esSaFu6kGu - Discord: Vakdev Zet#5964 - YouTube: https://www.youtube.com/@vakdev881 ================================================ FILE: credits.txt ================================================ Contributions Azimov: [https://github.com/AzimovUA] - Added Offsets update using .ini file. - Added Vision tracker. - Added Items reading. - Added Buffs reading. - Added Spells reading. - Added Scripts. - Tester. - Discord mod. almazpyjs: [https://github.com/almazpyjs] - Helped with entities attack range in drawings. PeterParks: [https://github.com/Teemoplays] - Added custom delay in orb. [rem] - Tester. - Discord mod. blackcatxhan: [https://github.com/blackcatxhan] - Added Auto build to .exe. 9quh: - Wrote lasthit code. ================================================ FILE: requirements.txt ================================================ mouse==0.7.1 dearpygui==1.9.0 dearpygui-ext==0.9.5 orjson==3.8.5 keyboard==0.13.5 pywin32==305 pywin32-ctypes==0.2.0 requests==2.28.2 psutil==5.9.4 numpy==1.24.3 ================================================ FILE: vakscript/autoconfig.py ================================================ #ext import os import win32api import fileinput from psutil import process_iter from json import dump #own from data import Info """ TODO: - Check if evtShowCharacterMenu isn't bug. vak code changes: - settings_json updated to latest settings.json file version. """ settings_json = { 'Spaceglider': { 'orbwalk' : 'space', 'laneclear' : 'v', 'lasthit' : 'c', 'attack' : 'a', 'range' : 'o', 'kiting_mode' : 'Normal', 'orbwalk_prio' : 'Less Basic Attacks', 'lasthit_mode' : 'Normal', 'press_range': False, 'ppc' : False }, 'Drawings' : { "show_position": True, "show_focused": True, "show_healths": True, "show_gold": False, "show_spells": False, "show_player_range": True, "show_enemy_range": True, "show_turret_range": True, "show_hits": True, "vision_tracker": True, "screen_track": False, "fps": "60" }, 'AutoSmite' : { 'smite' : 'f', 'randb' : False }, "Scripts" : { } } DEFAULT_CHAMPION_ONLY = '[Button 3]' DEFAULT_PLAYER_ATTACK = '[a]' DEFAULT_WALK_CLICK = '[Button 2]' DEFAULT_RANGE = '[o]' DEFAULT_ORBWALK = '[space]' DEFAULT_LANECLEAR = '[v]' DEFAULT_LASTHIT = '[c]' options = { 'EnableTargetedAttackMove':'1', 'TargetChampionsOnlyAsToggle':'0', 'evtChampionOnly':DEFAULT_CHAMPION_ONLY, 'evtPlayerAttackMoveClick':DEFAULT_PLAYER_ATTACK, 'evtPlayerMoveClick':DEFAULT_WALK_CLICK, 'evtShowCharacterMenu':DEFAULT_RANGE } class Autoconfig: def __init__(self, settings_to_persist, persisted_settings): self.settings_to_persist = settings_to_persist self.persisted_settings = persisted_settings @staticmethod def clear_name(string): return string.strip().removeprefix('"name": "').removesuffix('",') @staticmethod def clear_value(string): return string.strip(" \n").removeprefix('"value": "').removesuffix('"') def remove_duplications(self): #Prevent key bugs. current_values = self.get_persisted_settings() duplications = dict() with open(self.persisted_settings) as persisted_settings: for index, line in enumerate(persisted_settings, 1): line = Autoconfig.clear_value(line) if not line.isdecimal() and '.' not in line: for k, v in current_values.items(): if line == v and index != k: duplications[index] = line if (line.startswith(v) or line.endswith(v)) and index != k: if not line.startswith(('[Alt]', '[Ctrl]')): duplications[index] = line if line == DEFAULT_LASTHIT: duplications[index] = line if line == DEFAULT_LANECLEAR: duplications[index] = line if line == DEFAULT_ORBWALK: duplications[index] = line for line in fileinput.input(self.persisted_settings, inplace=True): current_index = fileinput.lineno() for k, v in duplications.items(): if current_index == k: line = line.replace(v, '[],[]') print(line, end="") def get_persisted_settings(self): current_settings = dict() is_value = False value_pos = None with open(self.persisted_settings, "r+") as persisted_settings: for index, line in enumerate(persisted_settings, 1): line_name = Autoconfig.clear_name(line) if line_name in options.keys(): value_pos = index + 1 is_value = True continue if is_value: current_settings[value_pos] = Autoconfig.clear_value(line) is_value = False return current_settings def set_persisted_settings(self): current_settings = self.get_persisted_settings() for line in fileinput.input(self.persisted_settings, inplace=True): current_index = fileinput.lineno() for (value_pos, current_value), new_value in zip(current_settings.items(), options.values()): if value_pos == current_index: line = line.replace(current_value, new_value) print(line, end="") self.remove_duplications() def toggle_settings_to_persist(self, statment): for line in fileinput.input(self.settings_to_persist, inplace=True): if statment: line = line.replace("false", "true") else: line = line.replace("true", "false") print(line, end="") def set_json_settings(self): with open(Info.settings_file_name, 'w') as json_file: dump(settings_json, json_file, indent=4) def set_config(self): self.toggle_settings_to_persist(False) self.set_persisted_settings() self.toggle_settings_to_persist(True) self.set_json_settings() def start_autoconfig(): league_path = None for process in process_iter(['name', 'cwd']): if process.info['name'] == Info.client_name_executable: os.system('taskkill -f -im "{}"'.format(Info.game_name_executable)) league_path = process.info['cwd'] if league_path is not None and os.path.isdir(league_path): settings_to_persist = os.path.join(league_path, Info.settings_to_persist_path) persisted_settings = os.path.join(league_path, Info.persisted_settings_path) files_list = [settings_to_persist, persisted_settings] for file in files_list: try: win32api.SetFileAttributes(file, 128) except: try: os.chmod(file, 0o777) except: pass Autoconfig(settings_to_persist, persisted_settings).set_config() ================================================ FILE: vakscript/autosmite.py ================================================ #built-in from ctypes import windll from collections import namedtuple from gc import collect as del_mem from time import sleep #ext from pyMeow import open_process, get_module from pyMeow import r_int, r_float, r_uint64 from win32api import GetSystemMetrics, GetCursorPos #own from data import Offsets, Info, VK_CODES from world_to_screen import World from utils import send_key, debug_info from entities import AttributesReader """ TODO: - Fix Username API Request or read in memory instead. """ class Asmite: def __init__(self, settings): self.settings = settings self.obj_health = Offsets.obj_health self.obj_spawn_count = Offsets.obj_spawn_count self.obj_x = Offsets.obj_x self.obj_y = Offsets.obj_y self.obj_z = Offsets.obj_z def get_settings(self): return VK_CODES[self.settings['smite']] def _read_attr(self, process, address, nt): attributes = nt( health = r_float(process, address + self.obj_health), alive = r_int(process, address + self.obj_spawn_count) % 2 == 0, x = r_float(process, address + self.obj_x), y = r_float(process, address + self.obj_y), z = r_float(process, address + self.obj_z) ) return attributes def autosmite(terminate, settings, jungle_pointers, on_window): while not terminate.value: if on_window.value: del_mem() try: process = open_process(process=Info.game_name_executable) base_address = get_module(process, Info.game_name_executable)['base'] local_player = r_uint64(process, base_address + Offsets.local_player) attr_reader = AttributesReader(process, base_address) asmite = Asmite(settings) smite_key = asmite.get_settings() damage = 0 smite_charges = 0 width, height = GetSystemMetrics(0), GetSystemMetrics(1) world = World(process, base_address, width, height) set_cursor_pos = windll.user32.SetCursorPos nt = namedtuple('Attributes', 'health alive x y z') except Exception as asmite_proc_loop: debug_info(asmite_proc_loop, True) sleep(0.1) else: try: while 1 and on_window.value: player = attr_reader.read_player(local_player) for buff in player.buffs: if 'smitedamagetracker' in str(buff.name).lower(): damage = buff.count2 entities = [asmite._read_attr(process, pointer, nt) for pointer in jungle_pointers] target = [entity for entity in entities if entity.health <= damage and entity.alive] spells = attr_reader.read_spells(local_player) if 'smite' in spells[4]['name'].lower(): smite_charges = spells[4]['charges'] elif 'smite' in spells[5]['name'].lower(): smite_charges = spells[5]['charges'] if target and smite_charges > 0: pos = world.world_to_screen(world.get_view_proj_matrix(), target[0].x, target[0].z, target[0].y) mouse_pos = GetCursorPos() if pos: set_cursor_pos(pos[0], pos[1]) send_key(smite_key) sleep(0.01) set_cursor_pos(mouse_pos[0], mouse_pos[1]) sleep(0.03) except Exception as asmite_loop: debug_info(asmite_loop, True) sleep(0.1) ================================================ FILE: vakscript/data.py ================================================ from os import path import configparser """ TODO: - bonus_attack_speed offset in offsets.ini is wrong """ class Offsets: offsets_file = configparser.ConfigParser() offsets_file.read("offsets.ini") local_player = int(offsets_file.get("offsets", "local_player"), 16) game_time = int(offsets_file.get("offsets", "game_time"), 16) view_proj_matrix = int(offsets_file.get("offsets", "view_proj_matrix"), 16) champion_list = int(offsets_file.get("offsets", "champion_list"), 16) minion_list = int(offsets_file.get("offsets", "minion_list"), 16) turret_list = int(offsets_file.get("offsets", "turret_list"), 16) obj_name = int(offsets_file.get("offsets", "obj_name"), 16) obj_lvl = int(offsets_file.get("offsets", "obj_lvl"), 16) obj_team = int(offsets_file.get("offsets", "obj_team"), 16) obj_gold = int(offsets_file.get("offsets", "obj_gold"), 16) obj_health = int(offsets_file.get("offsets", "obj_health"), 16) obj_max_health = int(offsets_file.get("offsets", "obj_max_health"), 16) obj_armor = int(offsets_file.get("offsets", "obj_armor"), 16) obj_magic_resist = int(offsets_file.get("offsets", "obj_magic_resist"), 16) obj_base_attack = int(offsets_file.get("offsets", "obj_base_attack"), 16) obj_bonus_attack = int(offsets_file.get("offsets", "obj_bonus_attack"), 16) obj_bonus_as = int(offsets_file.get("offsets", "obj_bonus_as"), 16) obj_magic_damage = int(offsets_file.get("offsets", "obj_magic_damage"), 16) obj_attack_range = int(offsets_file.get("offsets", "obj_attack_range"), 16) obj_spawn_count = int(offsets_file.get("offsets", "obj_spawn_count"), 16) obj_targetable = int(offsets_file.get("offsets", "obj_targetable"), 16) obj_visible = int(offsets_file.get("offsets", "obj_visible"), 16) obj_x = int(offsets_file.get("offsets", "obj_x"), 16) obj_y = int(offsets_file.get("offsets", "obj_y"), 16) obj_z = int(offsets_file.get("offsets", "obj_z"), 16) obj_spell_book = int(offsets_file.get("offsets", "obj_spell_book"), 16) obj_item_list = int(offsets_file.get("offsets", "obj_item_list"), 16) item_info = int(offsets_file.get("offsets", "item_info"), 16) item_info_id = int(offsets_file.get("offsets", "item_info_id"), 16) spell_info = int(offsets_file.get("offsets", "spell_info"), 16) spell_data = int(offsets_file.get("offsets", "spell_data"), 16) spell_name = int(offsets_file.get("offsets", "spell_name"), 16) spell_level = int(offsets_file.get("offsets", "spell_level"), 16) spell_cooldown = int(offsets_file.get("offsets", "spell_cooldown"), 16) spell_charges = int(offsets_file.get("offsets", "spell_charges"), 16) buff_manager = int(offsets_file.get("offsets", "buff_manager"), 16) buff_count = int(offsets_file.get("offsets", "buff_count"), 16) buff_count2 = int(offsets_file.get("offsets", "buff_count2"), 16) buff_start = int(offsets_file.get("offsets", "buff_start"), 16) buff_end = int(offsets_file.get("offsets", "buff_end"), 16) buff_info = int(offsets_file.get("offsets", "buff_info"), 16) buff_name = int(offsets_file.get("offsets", "buff_name"), 16) class Info: offsets_file = configparser.ConfigParser() offsets_file.read("offsets.ini") script_version = offsets_file.get("version", "script_version") settings_file_name = 'settings.json' settings_file_path = path.abspath(settings_file_name) font_file_name = 'drawings_font.ttf' client_name_executable = 'LeagueClient.exe' game_name_executable = 'League of Legends.exe' game_name_window = 'League of Legends (TM) Client' game_files_path = '\Riot Games\League of Legends' settings_to_persist = 'DATA\CFG\defaults\SettingsToPersist.json' persisted_settings = 'Config\PersistedSettings.json' settings_to_persist_path = path.join(game_files_path, settings_to_persist) persisted_settings_path = path.join(game_files_path, persisted_settings) url_allgamedata = 'https://127.0.0.1:2999/liveclientdata/allgamedata' url_comunitydragon = 'https://raw.communitydragon.org/latest/game/data/characters/{name}/{name}.bin.json' root_key = 'characters/{}/characterrecords/root' VK_CODES = {'backspace':0x08, 'tab':0x09, 'clear':0x0C, 'enter':0x0D, 'shift':0x10, 'ctrl':0x11, 'alt':0x12, 'pause':0x13, 'caps_lock':0x14, 'esc':0x1B, 'spacebar':0x20, 'space':0x20, 'page_up':0x21, 'page_down':0x22, 'end':0x23, 'home':0x24, 'left_arrow':0x25, 'up_arrow':0x26, 'right_arrow':0x27, 'down_arrow':0x28, 'select':0x29, 'print':0x2A, 'execute':0x2B, 'print_screen':0x2C, 'ins':0x2D, 'del':0x2E, 'help':0x2F, '0':0x30, '1':0x31, '2':0x32, '3':0x33, '4':0x34, '5':0x35, '6':0x36, '7':0x37, '8':0x38, '9':0x39, 'a':0x41, 'b':0x42, 'c':0x43, 'd':0x44, 'e':0x45, 'f':0x46, 'g':0x47, 'h':0x48, 'i':0x49, 'j':0x4A, 'k':0x4B, 'l':0x4C, 'm':0x4D, 'n':0x4E, 'o':0x4F, 'p':0x50, 'q':0x51, 'r':0x52, 's':0x53, 't':0x54, 'u':0x55, 'v':0x56, 'w':0x57, 'x':0x58, 'y':0x59, 'z':0x5A, 'numpad_0':0x60, 'numpad_1':0x61, 'numpad_2':0x62, 'numpad_3':0x63, 'numpad_4':0x64, 'numpad_5':0x65, 'numpad_6':0x66, 'numpad_7':0x67, 'numpad_8':0x68, 'numpad_9':0x69, 'multiply_key':0x6A, 'add_key':0x6B, 'separator_key':0x6C, 'subtract_key':0x6D, 'decimal_key':0x6E, 'divide_key':0x6F, 'F1':0x70, 'F2':0x71, 'F3':0x72, 'F4':0x73, 'F5':0x74, 'F6':0x75, 'F7':0x76, 'F8':0x77, 'F9':0x78, 'F10':0x79, 'F11':0x7A, 'F12':0x7B, 'F13':0x7C, 'F14':0x7D, 'F15':0x7E, 'F16':0x7F, 'F17':0x80, 'F18':0x81, 'F19':0x82, 'F20':0x83, 'F21':0x84, 'F22':0x85, 'F23':0x86, 'F24':0x87, 'num_lock':0x90, 'scroll_lock':0x91, 'left_shift':0xA0, 'right_shift ':0xA1, 'left_control':0xA2, 'right_control':0xA3, 'left_menu':0xA4, 'right_menu':0xA5, 'browser_back':0xA6, 'browser_forward':0xA7, 'browser_refresh':0xA8, 'browser_stop':0xA9, 'browser_search':0xAA, 'browser_favorites':0xAB, 'browser_start_and_home':0xAC, 'volume_mute':0xAD, 'volume_Down':0xAE, 'volume_up':0xAF, 'next_track':0xB0, 'previous_track':0xB1, 'stop_media':0xB2, 'play/pause_media':0xB3, 'start_mail':0xB4, 'select_media':0xB5, 'start_application_1':0xB6, 'start_application_2':0xB7, 'attn_key':0xF6, 'crsel_key':0xF7, 'exsel_key':0xF8, 'play_key':0xFA, 'zoom_key':0xFB, 'clear_key':0xFE, '+':0xBB, ',':0xBC, '-':0xBD, '.':0xBE, '/':0xBF, '`':0xC0, ';':0xBA, '[':0xDB, '\\':0xDC, ']':0xDD, "'":0xDE, '`':0xC0} ================================================ FILE: vakscript/drawings.py ================================================ #built-in from gc import collect as del_mem from time import sleep from math import cos, sin, pi #ext from pyMeow import open_process, get_module, load_font, new_color, load_texture, draw_texture from pyMeow import overlay_init, overlay_loop, overlay_close, begin_drawing, end_drawing from pyMeow import draw_line, draw_circle, draw_font, gui_progress_bar, gui_text_box from pyMeow import r_uint64 from win32api import GetSystemMetrics #own from data import Info, Offsets from entities import EntityConditions, TargetSelector, AttributesReader from world_to_screen import World from settings import jsonGetter from utils import safe_title, debug_info """ TODO: - Lower ward tracker thikness. - Add draw_texture funtion to Draw class for future implements or imports. - Remove try-except in ward tracker. (name reading from entities/read_minion will be removed) - Fix black screen. """ class Colors: Lightgray = new_color(200, 200, 200, 255) Gray = new_color(130, 130, 130, 255) Darkgray = new_color(80, 80, 80, 255) Yellow = new_color(253, 249, 0, 255) Gold = new_color(255, 203, 0, 255) Orange = new_color(255, 161, 0, 255) Pink = new_color(255, 109, 194, 255) Red = new_color(230, 41, 55, 255) Maroon = new_color(190, 33, 55, 255) Green = new_color(0, 228, 48, 255) Lime = new_color(0, 158, 47, 255) Darkgreen = new_color(0, 117, 44, 255) Skyblue = new_color(102, 191, 255, 255) Blue = new_color(0, 121, 241, 255) Darkblue = new_color(0, 82, 172, 255) Purple = new_color(200, 122, 255, 255) Violet = new_color(135, 60, 190, 255) Darkpurple = new_color(112, 31, 126, 255) Beige = new_color(211, 176, 131, 255) Brown = new_color(127, 106, 79, 255) Darkbrown = new_color(76, 63, 47, 255) White = new_color(255, 255, 255, 255) Cyan = new_color(0, 255, 167, 255) Black = new_color(0, 0, 0, 255) Blank = new_color(0, 0, 0, 0) Magenta = new_color(255, 0, 255, 255) Raywhite = new_color(245, 245, 245, 255) class Draw: def __init__(self, world, width, height): self.width = width self.height = height self.world_to_screen = world.world_to_screen self.world_to_screen_limited = world.world_to_screen_limited #entity_range self.num_vert = 24 self.angle_increment = 2 * pi / self.num_vert self.cos_values = [cos(i * self.angle_increment) for i in range(self.num_vert)] self.sin_values = [sin(i * self.angle_increment) for i in range(self.num_vert)] @staticmethod def spell_level(pos, spell_levels): x_space = 0 for level in spell_levels: gui_text_box(pos[0] - 60 + x_space, pos[1] - 125, 35, 25, '', 1) draw_font(1, str(level), pos[0] - 50 + x_space, pos[1] - 120, 18, 0, Colors.Gold) x_space += 35 def entity_range(self, view_proj_matrix, game_pos, radius, thickness=1.0, color=Colors.Cyan): for i in range(self.num_vert): vec1 = self.world_to_screen( view_proj_matrix, game_pos[0] + self.cos_values[i] * radius, game_pos[1], game_pos[2] + self.sin_values[i] * radius ) next_index = (i + 1) % self.num_vert vec2 = self.world_to_screen( view_proj_matrix, game_pos[0] + self.cos_values[next_index] * radius, game_pos[1], game_pos[2] + self.sin_values[next_index] * radius ) draw_line(vec1[0], vec1[1], vec2[0], vec2[1], color, thickness) def health(self, entity, own_pos, pos): # Draw healthbars around the screen aiming to enemy position in world. if own_pos: if not (0 <= pos[0] < self.width and 0 <= pos[1] < self.height): dx = pos[0] - own_pos[0] dy = pos[1] - own_pos[1] dx_inv = 1.0 / dx if dx != 0 else float('inf') dy_inv = 1.0 / dy if dy != 0 else float('inf') t_left = -(own_pos[0] - 30) * dx_inv t_right = (self.width - own_pos[0] - 130) * dx_inv t_top = -(own_pos[1] - 30) * dy_inv t_bottom = (self.height - own_pos[1] - 30) * dy_inv valid_t_values = [t for t in [t_left, t_right, t_top, t_bottom] if t >= 0] if valid_t_values: t_min = min(valid_t_values) x_intersect = own_pos[0] + t_min * dx y_intersect = own_pos[1] + t_min * dy draw_font(1, entity.name, x_intersect, y_intersect - 20, 20, 2, Colors.Gold) gui_progress_bar(x_intersect, y_intersect, 100, 15, "", "", entity.health, 0, entity.max_health) def line_to_enemy(self, own_pos, pos, thickness=1.0, color=Colors.Lime): draw_line(own_pos[0], own_pos[1], pos[0], pos[1], color, thickness) draw_circle(pos[0], pos[1], 5.0, color) def drawings(terminate, settings, champion_pointers, ward_pointers, turret_pointers, on_window): """ External drawings process.""" while not terminate.value: if on_window.value: del_mem() try: process = open_process(process=Info.game_name_executable) base_address = get_module(process, Info.game_name_executable)['base'] local_player = r_uint64(process, base_address + Offsets.local_player) attr_reader = AttributesReader(process, base_address) screen_width = GetSystemMetrics(0) screen_height = GetSystemMetrics(1) world = World(process, base_address, screen_width, screen_height) draw = Draw(world, screen_width, screen_height) world_to_screen = world.world_to_screen world_to_screen_limited = world.world_to_screen_limited get_view_proj_matrix = world.get_view_proj_matrix target_selector = TargetSelector(world) show_position = settings['show_position'] show_focused = settings['show_focused'] show_healths = settings['show_healths'] show_spells = settings['show_spells'] show_player_range = settings['show_player_range'] show_enemy_range = settings['show_enemy_range'] show_turret_range = settings['show_turret_range'] show_hits = settings['show_hits'] vision_tracker = settings['vision_tracker'] screen_track = settings['screen_track'] fps = settings['fps'] target_prio = jsonGetter().get_data('orbwalk_prio') target_prio_modes = { 'Less Basic Attacks' : target_selector.select_by_health, 'Most Damage' : target_selector.select_by_damage, 'Nearest Enemy' : target_selector.select_by_distance } select_target = target_prio_modes.get(target_prio, target_selector.select_by_health) if screen_track: world_to_screen = world.world_to_screen_limited except Exception as drawings_proc_loop: debug_info(drawings_proc_loop, True) else: try: if not fps.isdecimal() or fps == '0': fps = 60 overlay_init(title=safe_title(), fps=int(fps)) load_font(Info.font_file_name, 1) wards_texture = { 'yellowtrinket': load_texture('wards/yellowtrinket.png'), 'sightward': load_texture('wards/sightward.png'), 'visionward': load_texture('wards/yellowtrinket.png'), 'bluetrinket': load_texture('wards/bluetrinket.png'), 'jammerdevice': load_texture('wards/pinkward.png'), 'perkszombieward': load_texture('wards/sightward.png') } while overlay_loop(): entities = [attr_reader.read_enemy(pointer) for pointer in champion_pointers] wards = [attr_reader.read_minion(pointer) for pointer in ward_pointers] player = attr_reader.read_player(local_player) view_proj_matrix = get_view_proj_matrix() own_pos = world_to_screen(view_proj_matrix, player.x, player.z, player.y) begin_drawing() if show_player_range: draw.entity_range(view_proj_matrix, (player.x, player.z, player.y), player.attack_range + 65.0, color=Colors.Orange) if show_turret_range: turrets = [attr_reader.read_turret(pointer) for pointer in turret_pointers] for turret in turrets: if EntityConditions.hurtable(turret): draw.entity_range(view_proj_matrix, (turret.x, turret.z, turret.y), 890.0, 1.0, Colors.Red) for entity in entities: if EntityConditions.hurtable(entity): pos = world_to_screen(view_proj_matrix, entity.x, entity.z, entity.y) if pos: if show_enemy_range: draw.entity_range(view_proj_matrix, (entity.x, entity.z, entity.y), entity.attack_range + 65.0, color=Colors.Cyan) if show_position: draw.line_to_enemy(own_pos, pos, color=Colors.Gray) if show_hits: min_attacks = entity.health / EntityConditions.effective_damage(player.basic_attack + player.bonus_attack, entity.armor) draw_font(1, str(round(min_attacks)), pos[0], pos[1] + 50, 20, 2, Colors.Raywhite) if show_healths: draw.health(entity, own_pos, pos) # Removed, because of changes to read_spells() and to the game itself. '''if show_spells: spell_levels = attr_reader.read_spells(entity.pointer) draw.spell_level(pos, spell_levels)''' if vision_tracker: for ward in wards: try: texture = wards_texture[ward.name.lower()] pos = world_to_screen(view_proj_matrix, ward.x, ward.z, ward.y) draw_texture(texture, pos[0], pos[1] + 10, Colors.White, 0, scale=0.5) draw.entity_range(view_proj_matrix, (ward.x, ward.z, ward.y), 900.0, 1.7, Colors.Magenta) draw.entity_range(view_proj_matrix, (ward.x, ward.z, ward.y), 8.0, 2, Colors.Purple) except: pass if show_focused: target = select_target(player, entities) if target: pos = world_to_screen_limited(view_proj_matrix, target.x, target.z, target.y) if pos: draw.line_to_enemy(own_pos, pos, 2.0, Colors.Magenta) end_drawing() if not on_window.value: overlay_close() break except Exception as drawings_loop: debug_info(drawings_loop, True) overlay_close() ================================================ FILE: vakscript/entities.py ================================================ #built-in from collections import namedtuple from math import hypot #ext from pyMeow import r_string, r_float, r_bool, r_int, r_ints64, r_uint64 #own from data import Offsets from stats import Stats """ TODO: - Remove name reading from read_minion. (bugs) - Add read_ward - Optimize buffs and items reading. - Add lasthit function in target selector. """ class AttributesReader(Offsets): def __init__(self, process, base_address): self.process = process self.base_address = base_address self.spell_keys = ['Q', 'W', 'E', 'R', 'D', 'F'] self.PlayerNamedtuple = namedtuple('Player', 'name lvl basic_attack bonus_attack magic_damage x y z attack_range items buffs') self.EnemyNamedtuple = namedtuple('Enemy', 'name health max_health gold armor magic_resist basic_attack bonus_attack magic_damage x y z alive targetable visible attack_range pointer items') self.MinionNamedtuple = namedtuple('Minion', 'name health armor magic_resist x y z alive targetable visible') self.TurretNamedTuple = namedtuple('Turret', 'attack_range x y z alive targetable visible') self.BuffNamedTuple = namedtuple('Buff', 'name count count2 alive') self.zombies = ["Sion", "KogMaw", "Karthus"] def read_items(self, pointer): process = self.process items_ids = [] for i in range(7): try: item = r_uint64(process, pointer + Offsets.obj_item_list + 0x50 + 0x8 * i) item_slot = r_uint64(process, item + 0x10) item_info = r_uint64(process, item_slot + Offsets.item_info) item_info_id = r_int(process, item_info + Offsets.item_info_id) items_ids.append(item_info_id) except: items_ids.append(0) return items_ids def read_buffs(self, pointer): process = self.process buffs = [] for i in range(200): buff_manager = r_uint64(process, pointer + Offsets.buff_manager) try: buff = r_uint64(process, buff_manager + 0x10 + 0x8 * i) buff_count = r_int(process, buff + Offsets.buff_count) buff_count2 = r_int(process, buff + Offsets.buff_count2) except: continue gametime = r_float(process, self.base_address + Offsets.game_time) buff_alive = False try: buff_start = r_float(process, buff + Offsets.buff_start) buff_end = r_float(process, buff + Offsets.buff_end) if buff_start <= gametime <= buff_end: buff_alive = True except: buff_alive = True buff_info = r_uint64(process, buff + Offsets.buff_info) try: buff_name_ptr = r_uint64(process, buff_info + Offsets.buff_name) buff_name = r_string(process, buff_name_ptr, 100) except: continue attributes = self.BuffNamedTuple( name = buff_name, count = buff_count, count2 = buff_count2, alive = buff_alive ) buffs.append(attributes) return buffs def read_player(self, local_player): process = self.process items_ids = self.read_items(local_player) buffs = self.read_buffs(local_player) attributes = self.PlayerNamedtuple( name = r_string(process, local_player + self.obj_name), lvl = r_int(process, local_player + self.obj_lvl), basic_attack = r_float(process, local_player + self.obj_base_attack), bonus_attack = r_float(process, local_player + self.obj_bonus_attack), magic_damage = r_float(process, local_player + self.obj_magic_damage), x = r_float(process, local_player + self.obj_x), y = r_float(process, local_player + self.obj_y), z = r_float(process, local_player + self.obj_z), attack_range = r_float(process, local_player + self.obj_attack_range), items = items_ids, buffs = buffs ) return attributes def read_enemy(self, pointer): process = self.process items_ids = self.read_items(pointer) # Currently cause huge lags, because we read alot of enemies for some reason # buffs = self.read_buffs(pointer) name = r_string(process, pointer + self.obj_name) health = r_float(process, pointer + self.obj_health) attributes = self.EnemyNamedtuple( name = name, health = health, max_health = r_float(process, pointer + self.obj_max_health), gold = r_int(process, pointer + self.obj_gold), armor = r_float(process, pointer + self.obj_armor), magic_resist = r_float(process, pointer + self.obj_magic_resist), basic_attack = r_float(process, pointer + self.obj_base_attack), bonus_attack = r_float(process, pointer + self.obj_bonus_attack), magic_damage = r_float(process, pointer + self.obj_magic_damage), x = r_float(process, pointer + self.obj_x), y = r_float(process, pointer + self.obj_y), z = r_float(process, pointer + self.obj_z), alive = health > 0 if name in self.zombies else r_int(process, pointer + self.obj_spawn_count) % 2 == 0, targetable = r_bool(process, pointer + self.obj_targetable), visible = r_bool(process, pointer + self.obj_visible), attack_range = r_float(process, pointer + self.obj_attack_range), pointer = pointer, items = items_ids, # buffs = buffs ) return attributes def read_minion(self, pointer): process = self.process attributes = self.MinionNamedtuple( name = r_string(process, pointer + self.obj_name), health = r_float(process, pointer + self.obj_health), armor = r_float(process, pointer + self.obj_armor), magic_resist = r_float(process, pointer + self.obj_magic_resist), x = r_float(process, pointer + self.obj_x), y = r_float(process, pointer + self.obj_y), z = r_float(process, pointer + self.obj_z), alive = r_int(process, pointer + self.obj_spawn_count) % 2 == 0, targetable = r_bool(process, pointer + self.obj_targetable), visible = r_bool(process, pointer + self.obj_visible), ) return attributes def read_turret(self, pointer): process = self.process attributes = self.TurretNamedTuple( attack_range = r_float(process, pointer + self.obj_attack_range), x = r_float(process, pointer + self.obj_x), y = r_float(process, pointer + self.obj_y), z = r_float(process, pointer + self.obj_z), alive = r_int(process, pointer + self.obj_spawn_count) % 2 == 0, targetable = r_bool(process, pointer + self.obj_targetable), visible = r_bool(process, pointer + self.obj_visible), ) return attributes def read_spells(self, pointer): spells, process = [], self.process spell_book = r_ints64(process, pointer + self.obj_spell_book, 0x6) for spell_slot in spell_book: spell_info_ptr = r_uint64(process, spell_slot + self.spell_info) spell_data_ptr = r_uint64(process, spell_info_ptr + self.spell_data) spell_name_ptr = r_uint64(process, spell_data_ptr + self.spell_name) name = r_string(process, spell_name_ptr, 50) charges = r_int(process, spell_slot + self.spell_charges) level = r_int(process, spell_slot + self.spell_level) cooldown = r_float(process, spell_slot + self.spell_cooldown) spell = dict(name=name, charges=charges, level=level, cooldown=cooldown) spells.append(spell) # to use spells: spells[0]['level'] or spells[0]['cooldown'] # where 0 is Q, 3 is R, 4 and 5 are summoner spells return spells class EntityConditions: def __init__(self, world=None, stats=None): if stats is not None: self.radius = stats.get_targets_radius() else: self.radius = Stats().get_targets_radius() if world is not None: self.world_to_screen_limited = world.world_to_screen_limited self.get_view_proj_matrix = world.get_view_proj_matrix @staticmethod def hurtable(entity) -> bool: return entity.alive and entity.visible and entity.targetable @staticmethod def effective_damage(damage, armor) -> float: if armor >= 0: return damage * 100. / (100. + armor) return damage * (2. - (100. / (100. - armor))) @staticmethod def max_damage(entity) -> float: return max(entity.basic_attack + entity.bonus_attack, entity.magic_damage) def distance(self, player, target) -> float: return hypot(player.x - target.x, player.y - target.y) def in_distance(self, player, target): return self.distance(player, target) - self.radius.get(target.name, 65.) <= player.attack_range + self.radius.get(player.name, 65.) def in_distance_minion(self, player, target): return self.distance(player, target) - 65.0 <= player.attack_range + self.radius.get(player.name, 65.) def min_attacks(self, player, entity) -> float: return entity.health / self.effective_damage(player.basic_attack + player.bonus_attack, entity.armor) class TargetSelector(EntityConditions): def __init__(self, world=None, stats=None): super().__init__(world, stats) def select_by_health(self, player, targets): # Enemy with less hits to kill him will be focused. target, min_autos = None, None for entity in targets: if self.hurtable(entity) and self.in_distance(player, entity): autos = self.min_attacks(player, entity) if target is None or 0 < autos < min_autos: target, min_autos = entity, autos return target def select_by_damage(self, player, targets): # Enemy with most damage will be focused. target, max_damage = None, None for entity in targets: if self.hurtable(entity) and self.in_distance(player, entity): damage = max(entity.basic_attack + entity.bonus_attack + entity.attack_range, entity.magic_damage) if target is None or damage > max_damage: target, max_damage = entity, damage return target def select_by_distance(self, player, targets): # Nearest enemy will be focused. target, min_distance = None, None for entity in targets: if self.hurtable(entity) and self.in_distance(player, entity): d = self.distance(player, entity) if target is None or d < min_distance: target, min_distance = entity, d return target def select_by_lasthit(self, player, entities): # Select minion to lasthit valid_targets = filter(lambda entity: self.hurtable(entity) and self.in_distance_minion(player, entity) and self.effective_damage(player.basic_attack + player.bonus_attack, entity.armor) > entity.health + entity.armor, entities) return min(valid_targets, key=lambda target: hypot(player.x - target.x, player.y - target.y), default=None) ================================================ FILE: vakscript/gui.py ================================================ #built-in from webbrowser import open_new_tab #ext from dearpygui.dearpygui import create_context, destroy_context, create_viewport, setup_dearpygui, show_viewport, is_dearpygui_running, render_dearpygui_frame, set_primary_window from dearpygui.dearpygui import window, child_window, tab_bar, tab from dearpygui.dearpygui import add_checkbox, add_text, add_combo, add_input_text #own from settings import jsonSetter, jsonGetter from utils import safe_title from autoconfig import start_autoconfig GUI_WIDTH = 340 GUI_HEIGHT = 420 class GUIFunctions: def set_spaceglider_data(key, value): jsonSetter().set_spaceglider_data(key, value) def set_autosmite_data(key, value): jsonSetter().set_autosmite_data(key, value) def set_drawings_data(key, value): jsonSetter().set_drawings_data(key, value) def set_autoconfig(data): if data: start_autoconfig() def show_gui(main_instance, scripts_tabs, loaded_scripts): global GUI_WIDTH create_context() with window(label='', width=GUI_WIDTH, height=GUI_HEIGHT, no_move=True, no_resize=True, no_title_bar=True, tag="Primary Window"): with tab_bar(): with tab(label='Spaceglider'): add_checkbox(label='Use Spaceglider', callback=main_instance.start_spaceglider_process) with child_window(width=GUI_WIDTH * 0.8, height=315): add_combo( label='Kiting mode', width=150, items=['Normal', 'Normal v2', 'In-place'], default_value=jsonGetter().get_data('kiting_mode'), callback=lambda _, data: GUIFunctions.set_spaceglider_data('kiting_mode', data) ) add_combo( label='Target Prio', width=150, items=['Less Basic Attacks','Nearest Enemy','Most Damage'], default_value=jsonGetter().get_data('orbwalk_prio'), callback=lambda _, data: GUIFunctions.set_spaceglider_data('orbwalk_prio', data) ) add_combo( label='Lasthit mode', width=150, items=['Normal'], default_value=jsonGetter().get_data('lasthit_mode'), callback=lambda _, data: GUIFunctions.set_spaceglider_data('lasthit_mode', data) ) add_checkbox( label='In-game Range', default_value=jsonGetter().get_data('press_range'), callback=lambda _, data: GUIFunctions.set_spaceglider_data('press_range', data) ) add_checkbox( label='Potato PC', default_value=jsonGetter().get_data('ppc'), callback=lambda _, data: GUIFunctions.set_spaceglider_data('ppc', data) ) add_checkbox( label='Autoconfig', default_value=False, callback=GUIFunctions.set_autoconfig ) add_text('Keys to use:', color=(128, 0, 128, 255)) add_input_text( label='Spaceglider Key', width=50, no_spaces=True, hint=jsonGetter().get_data('orbwalk').upper(), callback=lambda _, data: GUIFunctions.set_spaceglider_data('orbwalk', data) ) add_input_text( label='Laneclear Key', width=50, no_spaces=True, hint=jsonGetter().get_data('laneclear').upper(), callback=lambda _, data: GUIFunctions.set_spaceglider_data('laneclear', data) ) add_input_text( label='Lasthit Key', width=50, no_spaces=True, hint=jsonGetter().get_data('lasthit').upper(), callback=lambda _, data: GUIFunctions.set_spaceglider_data('lasthit', data) ) add_text('Keys In-game:', color=(0, 100, 0, 255)) add_input_text( label='PlayerAttackMoveClick', width=30, no_spaces=True, hint=jsonGetter().get_data('attack').upper(), callback=lambda _, data: GUIFunctions.set_spaceglider_data('attack', data) ) add_input_text( label='ShowAdvancedPlayerStats', width=30, no_spaces=True, hint=jsonGetter().get_data('range').upper(), callback=lambda _, data: GUIFunctions.set_spaceglider_data('range', data) ) with tab(label='Drawings'): add_checkbox(label='Drawings (borderless)', callback=main_instance.start_drawings_process) with child_window(width=GUI_WIDTH * 0.8, height=265): add_checkbox( label='Position', default_value=jsonGetter().get_data('show_position'), callback=lambda _, data: GUIFunctions.set_drawings_data('show_position', data) ) add_checkbox( label='Prioritized', default_value=jsonGetter().get_data('show_focused'), callback=lambda _, data: GUIFunctions.set_drawings_data('show_focused', data) ) add_checkbox( label='Health', default_value=jsonGetter().get_data('show_healths'), callback=lambda _, data: GUIFunctions.set_drawings_data('show_healths', data) ) add_checkbox( label='Player Range', default_value=jsonGetter().get_data('show_player_range'), callback=lambda _, data: GUIFunctions.set_drawings_data('show_player_range', data) ) add_checkbox( label='Enemy Range', default_value=jsonGetter().get_data('show_enemy_range'), callback=lambda _, data: GUIFunctions.set_drawings_data('show_enemy_range', data) ) add_checkbox( label='Turret Range', default_value=jsonGetter().get_data('show_turret_range'), callback=lambda _, data: GUIFunctions.set_drawings_data('show_turret_range', data) ) add_checkbox( label='Hits', default_value=jsonGetter().get_data('show_hits'), callback=lambda _, data: GUIFunctions.set_drawings_data('show_hits', data) ) add_checkbox( label='Gold', default_value=jsonGetter().get_data('show_gold'), callback=lambda _, data: GUIFunctions.set_drawings_data('show_gold', data) ) ## REMOVED DUE READ ISSUE [v13.21] #add_checkbox( # label='Spell level', # default_value=jsonGetter().get_data('show_spells'), # callback=lambda _, data: GUIFunctions.set_drawings_data('show_spells', data) #) add_checkbox( label='Vision Tracking', default_value=jsonGetter().get_data('vision_tracker'), callback=lambda _, data: GUIFunctions.set_drawings_data('vision_tracker', data) ) add_checkbox( label='Limit position', default_value=jsonGetter().get_data('screen_track'), callback=lambda _, data: GUIFunctions.set_drawings_data('screen_track', data) ) add_input_text( label='Max FPS', width=50, no_spaces=True, hint=jsonGetter().get_data('fps'), callback=lambda _, data: GUIFunctions.set_drawings_data('fps', data) ) with tab(label='AutoSmite'): add_checkbox(label='Use Auto Smite', callback=main_instance.start_autosmite_process) with child_window(width=GUI_WIDTH * 0.8, height=63): add_checkbox( label='Consider Blue / Red / Crab', default_value=jsonGetter().get_data('randb'), callback=lambda _, data: GUIFunctions.set_autosmite_data('randb', data) ) add_input_text( label='Smite Key', width=30, no_spaces=True, hint=jsonGetter().get_data('smite').upper(), callback=lambda _, data: GUIFunctions.set_autosmite_data('smite', data) ) with tab(label='Scripts'): add_checkbox(label='Turn on external scripts', callback=main_instance.start_scripts_process, user_data=loaded_scripts) add_input_text( label='Scripts FPS', width=50, no_spaces=True, hint=jsonGetter().get_data('scripts_fps') if jsonGetter().get_data('scripts_fps') != None else 60, callback=lambda _, data: jsonSetter().set_scripts_data('scripts_fps', data) ) for script_tab in scripts_tabs: script_tab() create_viewport( title=safe_title(), width=GUI_WIDTH, height=GUI_HEIGHT, x_pos=0, y_pos=0, resizable=True ) setup_dearpygui() show_viewport() set_primary_window("Primary Window", True) while is_dearpygui_running(): render_dearpygui_frame() destroy_context() ================================================ FILE: vakscript/main.py ================================================ #built-in import sys from multiprocessing import Process, Manager, freeze_support from ctypes import windll #own from multiprocessing_functions import MultiprocessingFunctions from gui import show_gui from scripts_manager import load_scripts """ TODO: - Optimize scripts loader. """ if __name__ == '__main__': freeze_support() #required for pyinstaller --onefile if not windll.shell32.IsUserAnAdmin(): windll.shell32.ShellExecuteW(None, 'runas', sys.executable, __file__, None, 1) sys.exit() manager = Manager() main_instance = MultiprocessingFunctions(manager) updater_process = Process(target=main_instance.updater) updater_process.start() scripts_tabs = [] print('Loading scripts...') loaded_scripts = load_scripts() for script in loaded_scripts: try: scripts_tabs.append(script.VakScript_draw_menu) except Exception as e: print(f'Error loading {script} tab! Error: {e}') show_gui(main_instance, scripts_tabs, loaded_scripts) main_instance.drawings_terminate.value = 1 main_instance.autosmite_terminate.value = 1 main_instance.updater_terminate.value = 1 main_instance.spaceglider_terminate.value = 1 ================================================ FILE: vakscript/multiprocessing_functions.py ================================================ #built-in import ssl from multiprocessing import Process, Value from time import sleep from json import load from gc import collect as del_mem #ext import requests from pyMeow import open_process, get_module, r_uint64, r_int #own from spaceglider import spaceglider from drawings import drawings from autosmite import autosmite from data import Info, Offsets from read_manager import ListReader from stats import Stats from utils import is_active_window, debug_info from scripts_manager import execute_scripts """ TODO: - Optimize wards reading. """ requests.packages.urllib3.disable_warnings() ssl._create_default_https_context = ssl._create_unverified_context MINION_NAMES = [ 'ha_orderminionsuper', 'ha_orderminionranged', 'ha_chaosminionsuper', 'sru_orderminionsuper', 'ha_orderminionsiege', 'ha_chaosminionmelee', 'sru_chaosminionmelee', 'sru_chaosminionsiege', 'sru_orderminionranged', 'sru_orderminionsiege', 'ha_chaosminionsiege', 'ha_chaosminionranged', 'ha_orderminionmelee', 'sru_chaosminionsuper', 'sru_chaosminionranged', 'sru_orderminionmelee' ] JUNGLE_NAMES = [ 'sru_dragon_air', 'sru_dragon_chemtech', 'sru_dragon_earth', 'sru_dragon_elder', 'sru_dragon_fire', 'sru_dragon_hextech', 'sru_dragon_water', 'sru_riftherald', 'sru_baron', 'sru_riftherald_mercenary_tx_cm', 'sru_red', 'sru_blue', 'sru_crab' ] class MultiprocessingFunctions: def __init__(self, manager): #pointers self.champion_pointers = manager.list() self.minion_pointers = manager.list() self.jungle_pointers = manager.list() self.ward_pointers = manager.list() self.turret_pointers = manager.list() #json settings self.spaceglider_settings = manager.dict() self.autosmite_settings = manager.dict() self.drawings_settings = manager.dict() #terminate self.updater_terminate = Value('i', 0) self.spaceglider_terminate = Value('i', 0) self.autosmite_terminate = Value('i', 0) self.drawings_terminate = Value('i', 0) self.scripts_terminate = Value('i', 0) self.on_window = Value('i', 0) #entities names self.minion_names = MINION_NAMES self.jungle_names = JUNGLE_NAMES def updater(self) -> None: """ This function will continuosly update and share all the pointers and settings that each process needs. """ while not self.updater_terminate.value: del_mem() try: name_exec = Info.game_name_executable process = open_process(process=name_exec) base_address = get_module(process, name_exec)['base'] local_player = r_uint64(process, base_address + Offsets.local_player) local_team = r_int(process, local_player + Offsets.obj_team) read_pointers = ListReader(process, base_address, local_team) stats = Stats() except Exception as updater_proc_loop: debug_info(updater_proc_loop, True) sleep(0.1) else: try: while True: if is_active_window(): self.on_window.value = 1 self.update_settings() if not self.spaceglider_terminate.value or not self.drawings_terminate.value: self.champion_pointers[:] = read_pointers.get_pointers(Offsets.champion_list, stats.names, size=128, search_mode=0) self.minion_pointers[:] = read_pointers.get_pointers(Offsets.minion_list, size=512, search_mode=1) self.ward_pointers[:] = read_pointers.get_pointers(Offsets.minion_list, size=512, search_mode=3) self.turret_pointers[:] = read_pointers.get_pointers(Offsets.turret_list, size=64, search_mode=2) if not self.autosmite_terminate.value: if not self.autosmite_settings['randb']: jg_names = self.jungle_names[:-3] else: jg_names = self.jungle_names self.jungle_pointers[:] = read_pointers.get_pointers(Offsets.minion_list, jg_names, size=512, search_mode=0) else: self.on_window.value = 0 sleep(0.1) except Exception as updater_loop: debug_info(updater_loop, True) self.on_window.value = 0 def update_settings(self) -> None: with open(Info.settings_file_name, 'r+') as json_file: settings = load(json_file) if not self.spaceglider_terminate.value: for k, v in settings['Spaceglider'].items(): self.spaceglider_settings[k] = v if not self.drawings_terminate.value: for k, v in settings['Drawings'].items(): self.drawings_settings[k] = v if not self.autosmite_terminate.value: for k, v in settings['AutoSmite'].items(): self.autosmite_settings[k] = v def start_spaceglider_process(self, _, state) -> None: if state: self.spaceglider_terminate.value = 0 process = Process(target=spaceglider, args=( self.spaceglider_terminate, self.spaceglider_settings, self.champion_pointers, self.minion_pointers, self.on_window )) process.start() else: self.spaceglider_terminate.value = 1 def start_autosmite_process(self, _, state) -> None: if state: self.autosmite_terminate.value = 0 process = Process(target=autosmite, args=( self.autosmite_terminate, self.autosmite_settings, self.jungle_pointers, self.on_window )) process.start() else: self.autosmite_terminate.value = 1 def start_drawings_process(self, _, state) -> None: if state: self.drawings_terminate.value = 0 process = Process(target=drawings, args=( self.drawings_terminate, self.drawings_settings, self.champion_pointers, self.ward_pointers, self.turret_pointers, self.on_window )) process.start() else: self.drawings_terminate.value = 1 def start_scripts_process(self, _, state, user_data) -> None: if state: self.scripts_terminate.value = 0 process = Process(target=execute_scripts, args=( self.scripts_terminate, user_data, self.champion_pointers, self.ward_pointers, self.minion_pointers, self.turret_pointers, self.on_window )) process.start() else: self.scripts_terminate.value = 1 ================================================ FILE: vakscript/offsets.ini ================================================ [version] script_version = '14.6' [offsets] game_time: 0x233E7E8 local_player: 0x23524A8 champion_list: 0x232FAC0 minion_list: 0x2334EE0 turret_list: 0x2338490 view_proj_matrix: 0x23A4170 obj_name: 0x43D8 obj_lvl: 0x40A8 obj_team: 0x3C obj_gold: 0x2180 obj_health: 0x11E0 obj_max_health: 0x1208 obj_armor: 0x1954 obj_magic_resist: 0x16E4 obj_base_attack: 0x192C obj_bonus_attack: 0x1628 obj_bonus_as: 0x168C obj_magic_damage: 0x1630 obj_attack_range: 0x1974 obj_spawn_count: 0x360 obj_targetable: 0x1018 obj_visible: 0x348 obj_x: 0x220 obj_y: 0x228 obj_z: 0x224 obj_spell_book: 0x3C58 spell_info: 0x130 spell_data: 0x50 spell_name: 0x80 spell_level: 0x28 spell_cooldown: 0x30 spell_charges: 0x5C obj_item_list: 0x360 item_info: 0x38 item_info_id: 0x9C buff_manager: 0x2818 buff_count: 0x38 buff_count2: 0x8C buff_start: 0x18 buff_end: 0x1C buff_info: 0x10 buff_name: 0x8 ================================================ FILE: vakscript/orbwalker.py ================================================ #built-in from urllib.request import urlopen from time import sleep from ctypes import windll #ext from pyMeow import r_float from orjson import loads from win32api import GetCursorPos from mouse import right_click #own from data import Offsets from utils import send_key """ TODO: - Update windup formula from: https://leagueoflegends.fandom.com/wiki/Basic_attack and use GENERAL FORM for walk.Normal v2 - Fix Kalista disconnect issue. """ class Orbwalk: def __init__(self, process, base_address): self.process = process self.base_address = base_address self.can_attack_time = 0 self.can_move_time = 0 self.game_time_offset = Offsets.game_time def get_game_time(self): return r_float(self.process, self.base_address + self.game_time_offset) @staticmethod def get_attack_time(): stats = loads(urlopen("https://127.0.0.1:2999/liveclientdata/activeplayer").read()) return stats["championStats"]["attackSpeed"] @staticmethod def get_windup_time(base_as, windup, windup_mod, c_attack_speed): if windup_mod: return (1. / base_as) * windup + ((1. / c_attack_speed * windup) - (1. / base_as) * windup) * windup_mod return (1. / base_as) * windup + ((1. / c_attack_speed * windup) - (1. / base_as) * windup) def walk(self, pos, attack_key, base_as, windup, windup_mod): game_time = self.get_game_time() c_attack_speed = self.get_attack_time() mouse_pos = GetCursorPos() if self.can_attack_time < game_time and pos: self.can_attack_time = game_time + 1. / c_attack_speed self.can_move_time = game_time + self.get_windup_time(base_as, windup, windup_mod, c_attack_speed) windll.user32.SetCursorPos(pos[0], pos[1]) send_key(attack_key) sleep(0.01) windll.user32.SetCursorPos(mouse_pos[0], mouse_pos[1]) elif self.can_move_time < game_time: windll.user32.SetCursorPos(mouse_pos[0], mouse_pos[1]) sleep(0.1) right_click() def walk_v2(self, pos, attack_key, base_as, windup, windup_mod): # Will try to fix mouse issue. (moves cursor to target instead of walk.) game_time = self.get_game_time() c_attack_speed = self.get_attack_time() mouse_pos = GetCursorPos() if self.can_attack_time < game_time and pos: self.can_attack_time = game_time + 1. / c_attack_speed self.can_move_time = game_time + self.get_windup_time(base_as, windup, windup_mod, c_attack_speed) windll.user32.SetCursorPos(pos[0], pos[1]) send_key(attack_key) sleep(0.01) windll.user32.SetCursorPos(mouse_pos[0], mouse_pos[1]) elif self.can_move_time < game_time: windll.user32.SetCursorPos(mouse_pos[0], mouse_pos[1]) sleep(0.1) right_click() def walk_inplace(self, pos, attack_key, base_as, windup, windup_mod): game_time = self.get_game_time() c_attack_speed = self.get_attack_time() if self.can_attack_time < game_time and pos: self.can_attack_time = game_time + 1. / c_attack_speed self.can_move_time = game_time + self.get_windup_time(base_as, windup, windup_mod, c_attack_speed) send_key(attack_key) elif self.can_move_time < game_time: sleep(0.1) right_click() def walk_kalista(self, pos, attack_key, *_): if pos: mouse_pos = GetCursorPos() windll.user32.SetCursorPos(pos[0],pos[1]) send_key(attack_key) sleep(0.01) windll.user32.SetCursorPos(mouse_pos[0], mouse_pos[1]) sleep(0.01) right_click() sleep(0.02) elif not pos: right_click() sleep(0.1) ================================================ FILE: vakscript/read_manager.py ================================================ #ext from pyMeow import r_string, r_int, r_int64, r_uint64, r_ints64 #own from data import Offsets """ TODO: - Optimize search_mode 3 """ class ListReader: def __init__(self, process, base_address, local_team): self.process = process self.base_address = base_address self.local_team = local_team self.name_offset = Offsets.obj_name self.team_offset = Offsets.obj_team @staticmethod def _is_valid_name(name, entities_list, search_mode): if isinstance(name, str): name = name.lower() if search_mode == 0: return name in entities_list or name.startswith('practicetool') elif search_mode == 1: return name.startswith(('sru', 'ha')) elif search_mode == 2: return name == 'turret' elif search_mode == 3: wards = ['sightward', 'visionward', 'yellowtrinket', 'yellowtrinketupgrade', 'bluetrinket', 'jammerdevice', 'perkszombieward'] return name in wards return False def is_valid_pointer(self, pointer, entities_list, search_mode): process = self.process try: name = r_string(process, r_int64(process, pointer + self.name_offset), 50) if self._is_valid_name(name, entities_list, search_mode): team = r_int(process, pointer + self.team_offset) if team != self.local_team: return True except: pass try: name = r_string(process, pointer + self.name_offset, 50) if self._is_valid_name(name, entities_list, search_mode): team = r_int(process, pointer + self.team_offset) if team != self.local_team: return True except: pass return False def get_pointers(self, type_list: int, entities_list: list = [], size: int = 512, search_mode: int = 0): process = self.process pointers_mng = r_uint64(process, self.base_address + type_list) pointers = r_ints64(process, r_int64(process, pointers_mng + 0x8), size) return {pointer for pointer in pointers if self.is_valid_pointer(pointer, entities_list, search_mode)} ================================================ FILE: vakscript/script_class.py ================================================ from multiprocessing import Value from dearpygui.dearpygui import add_checkbox, tree_node from settings import jsonSetter, jsonGetter """ TODO: - Check code. """ class UserScript: def __init__(self): self.script_name = __name__ self.script_prefix = 'unnamed' self.script_terminate = Value('i', 1) def hello(self): self.script_terminate = Value('i', 0 if self.VakScript_get_setting('enabled') == True else 1) return True def VakScript_start_process(self, _, state): if state: self.script_terminate.value = 0 self.VakScript_set_setting('enabled', True) else: self.script_terminate.value = 1 self.VakScript_set_setting('enabled', False) def VakScript_draw_menu(self): with tree_node(label=f'{self.script_name}', default_open=True): add_checkbox( label=f'Enable {self.script_name}', default_value=True if self.script_terminate.value == 0 else False, callback=self.VakScript_start_process ) def VakScript_set_setting(self, key, value): jsonSetter().set_scripts_data(f'{self.script_prefix}_{key}', value) def VakScript_get_setting(self, key): return jsonGetter().get_data(f'{self.script_prefix}_{key}') if jsonGetter().get_data(f'{self.script_prefix}_{key}') != None else False ================================================ FILE: vakscript/scripts/example.py ================================================ from pyMeow import draw_font, new_color from script_class import UserScript class Script(UserScript): def __init__(self): super().__init__() # script_name is used in VakScript GUI self.script_name = 'Example Script' # script_prefix is used in settings.json where all script settins is stored self.script_prefix = 'example' def main(self, attr_reader, draw, world, local_player, champions, wards, minions, turrets, game_time): # recieving view proj matrix view_proj_matrix = world.get_view_proj_matrix() # recieving world to screen function world_to_screen = world.world_to_screen # reading player attributes (name, coords, health, mana etc.) player = attr_reader.read_player(local_player) # if reading was successful if player: # converting player game coords to screen coords # it's needed to tell the script where to draw own_pos = world_to_screen(view_proj_matrix, player.x, player.z, player.y) # drawing text on player champion position, own_pos[0] is x, own_pos[1] is y # draw_font(fontId: int, text: string, posX, posY, fontSize, spacing: float, tint: Color) # fontId is font id from scripts_manager.py draw_font(1, f'{self.script_name}', own_pos[0] + 30, own_pos[1] + 20, 20, 2, new_color(255, 203, 0, 255)) ================================================ FILE: vakscript/scripts/example_turret_range.py ================================================ from script_class import UserScript from entities import EntityConditions from scripts_manager import Colors from dearpygui.dearpygui import add_checkbox, tree_node class Script(UserScript): def __init__(self): super().__init__() self.script_name = 'Example Turret Script' self.script_prefix = 'example_turret' self.limited = False # rewriting VakScript_draw_menu function from UserScript class def VakScript_draw_menu(self): with tree_node(label=f'{self.script_name}', default_open=True): add_checkbox( label=f'Enable {self.script_name}', default_value=self.VakScript_get_setting('enabled'), callback=self.VakScript_start_process ) add_checkbox( label='Limit position on screen', default_value=self.VakScript_get_setting('limited'), callback=self.set_limit_position ) def set_limit_position(self, _, state): self.VakScript_set_setting('limited', state) def main(self, attr_reader, draw, world, local_player, champions, wards, minions, turrets, game_time): self.limited = self.VakScript_get_setting('limited') view_proj_matrix = world.get_view_proj_matrix() for turret in turrets: if EntityConditions.hurtable(turret): draw.entity_range(view_proj_matrix, (turret.x, turret.z, turret.y), 890.0, 1.0, Colors.Red, limited=self.limited) ================================================ FILE: vakscript/scripts_manager.py ================================================ #built-in from gc import collect as del_mem from math import cos, sin, pi from glob import glob import os import sys from time import sleep #ext from pyMeow import open_process, get_module, load_font, new_color from pyMeow import overlay_init, overlay_loop, overlay_close, begin_drawing, end_drawing from pyMeow import draw_line, draw_circle from pyMeow import r_uint64, r_float from win32api import GetSystemMetrics #own from data import Info, Offsets from entities import AttributesReader from world_to_screen import World from utils import safe_title from settings import jsonGetter, jsonSetter """ TODO: - Remove re-writting of Colors and Drawings class. Import from drawings.py instead. - Check code. """ class Colors: Lightgray = new_color(200, 200, 200, 255) Gray = new_color(130, 130, 130, 255) Darkgray = new_color(80, 80, 80, 255) Yellow = new_color(253, 249, 0, 255) Gold = new_color(255, 203, 0, 255) Orange = new_color(255, 161, 0, 255) Pink = new_color(255, 109, 194, 255) Red = new_color(230, 41, 55, 255) Maroon = new_color(190, 33, 55, 255) Green = new_color(0, 228, 48, 255) Lime = new_color(0, 158, 47, 255) Darkgreen = new_color(0, 117, 44, 255) Skyblue = new_color(102, 191, 255, 255) Blue = new_color(0, 121, 241, 255) Darkblue = new_color(0, 82, 172, 255) Purple = new_color(200, 122, 255, 255) Violet = new_color(135, 60, 190, 255) Darkpurple = new_color(112, 31, 126, 255) Beige = new_color(211, 176, 131, 255) Brown = new_color(127, 106, 79, 255) Darkbrown = new_color(76, 63, 47, 255) White = new_color(255, 255, 255, 255) Cyan = new_color(0, 255, 167, 255) Black = new_color(0, 0, 0, 255) Blank = new_color(0, 0, 0, 0) Magenta = new_color(255, 0, 255, 255) Raywhite = new_color(245, 245, 245, 255) class Draw: def __init__(self, world, width, height): self.width = width self.height = height self.world_to_screen = world.world_to_screen self.world_to_screen_limited = world.world_to_screen_limited #entity_range self.num_vert = 24 self.angle_increment = 2 * pi / self.num_vert self.cos_values = [cos(i * self.angle_increment) for i in range(self.num_vert)] self.sin_values = [sin(i * self.angle_increment) for i in range(self.num_vert)] def entity_range(self, view_proj_matrix, game_pos, radius, thickness=1.0, color=Colors.Cyan, limited=False): world_to_screen = self.world_to_screen_limited if limited else self.world_to_screen for i in range(self.num_vert): vec1 = world_to_screen( view_proj_matrix, game_pos[0] + self.cos_values[i] * radius, game_pos[1], game_pos[2] + self.sin_values[i] * radius ) next_index = (i + 1) % self.num_vert vec2 = world_to_screen( view_proj_matrix, game_pos[0] + self.cos_values[next_index] * radius, game_pos[1], game_pos[2] + self.sin_values[next_index] * radius ) if vec1 and vec2: draw_line(vec1[0], vec1[1], vec2[0], vec2[1], color, thickness) def line_to_enemy(self, own_pos, pos, thickness=1.0, color=Colors.Lime): draw_line(own_pos[0], own_pos[1], pos[0], pos[1], color, thickness) draw_circle(pos[0], pos[1], 5.0, color) def load_scripts(): sys.path.insert(0, './scripts') if getattr(sys, 'frozen', False): application_path = os.path.dirname(sys.executable) elif __file__: application_path = os.path.dirname(__file__) scripts_folder = os.path.join(application_path, 'scripts') python_files = glob(os.path.join(scripts_folder, '*.py')) loaded_scripts = [] for file in python_files: module_name = os.path.splitext(os.path.basename(file))[0] try: module = __import__(module_name) module_class = module.Script() if module_class.hello(): print(f'Loaded successfully: {module_name}') loaded_scripts.append(module_class) else: print(f'Error loading {module_name}') except Exception as e: print(f'Error loading {module_name}: {e}') return loaded_scripts def execute_scripts(terminate, user_data, champion_pointers, ward_pointers, minion_pointers, turret_pointers, on_window): while not terminate.value: if jsonGetter().get_data('scripts_fps'): fps = int(jsonGetter().get_data('scripts_fps')) else: fps = 60 jsonSetter().set_scripts_data('scripts_fps', fps) if on_window.value: del_mem() process = open_process(process=Info.game_name_executable) base_address = get_module(process, Info.game_name_executable)['base'] local_player = r_uint64(process, base_address + Offsets.local_player) attr_reader = AttributesReader(process, base_address) screen_width = GetSystemMetrics(0) screen_height = GetSystemMetrics(1) world = World(process, base_address, screen_width, screen_height) draw = Draw(world, screen_width, screen_height) loaded_scripts = user_data overlay_init(title=safe_title(), fps=fps) load_font(Info.font_file_name, 1) while overlay_loop(): champions = [attr_reader.read_enemy(pointer) for pointer in champion_pointers] wards = [attr_reader.read_minion(pointer) for pointer in ward_pointers] minions = [attr_reader.read_minion(pointer) for pointer in minion_pointers] turrets = [attr_reader.read_turret(pointer) for pointer in turret_pointers] game_time = r_float(process, base_address + Offsets.game_time) begin_drawing() for script in loaded_scripts: if script.script_terminate.value: continue script.main(attr_reader, draw, world, local_player, champions, wards, minions, turrets, game_time) end_drawing() if not on_window.value: overlay_close() break sleep(0.1) ================================================ FILE: vakscript/settings.json ================================================ { "Spaceglider": { "orbwalk": "space", "laneclear": "v", "lasthit": "c", "attack": "a", "range": "o", "kiting_mode": "Normal", "orbwalk_prio": "Less Basic Attacks", "lasthit_mode": "Normal", "press_range": true, "ppc": false }, "Drawings": { "show_position": true, "show_focused": true, "show_healths": true, "show_gold": true, "show_spells": false, "show_player_range": true, "show_enemy_range": true, "show_turret_range": true, "show_hits": true, "vision_tracker": true, "screen_track": false, "fps": "60" }, "AutoSmite": { "smite": "f", "randb": true }, "Scripts": { } } ================================================ FILE: vakscript/settings.py ================================================ #ext from json import load, dump #own from data import Info, VK_CODES class jsonSetter: def __init__(self): self.file_name = Info.settings_file_name self.file = open(self.file_name, "r+") self.settings = load(self.file) def _json_update(self): self.file.seek(0) dump(self.settings, self.file, indent=4) self.file.truncate() self.file.close() def is_valid_data(self, data): return data.lower() in VK_CODES.keys() def set_spaceglider_data(self, key, data): if isinstance(data, str): if self.is_valid_data(data): self.settings['Spaceglider'][key] = data.lower() elif key.endswith(('mode', 'prio')): self.settings['Spaceglider'][key] = data else: self.settings['Spaceglider'][key] = data self._json_update() def set_drawings_data(self, key, data): self.settings['Drawings'][key] = data self._json_update() def set_autosmite_data(self, key, data): if isinstance(data, str): if self.is_valid_data(data): self.settings['AutoSmite'][key] = data.lower() else: self.settings['AutoSmite'][key] = data self._json_update() def set_scripts_data(self, key, data): self.settings['Scripts'][key] = data self._json_update() class jsonGetter(jsonSetter): def __init__(self): super().__init__() def get_data(self, key): for sk, sv in self.settings.items(): if key in sv: return self.settings[sk][key] ================================================ FILE: vakscript/spaceglider.py ================================================ #built-in from time import sleep from gc import collect as del_mem #ext from pyMeow import open_process, get_module, r_uint64, r_string from win32api import GetSystemMetrics, GetAsyncKeyState, mouse_event from win32con import MOUSEEVENTF_MIDDLEDOWN, MOUSEEVENTF_MIDDLEUP from mouse import right_click #own from data import Info, Offsets, VK_CODES from stats import Stats from orbwalker import Orbwalk from world_to_screen import World from entities import TargetSelector, AttributesReader from utils import press_key, release_key, debug_info """ TODO: - Tests with entities.py and orbwalker.py changes. """ def spaceglider(terminate, settings, champion_pointers, minion_pointers, on_window): """ Auto kite process.""" import ssl import requests requests.packages.urllib3.disable_warnings() ssl._create_default_https_context = ssl._create_unverified_context # Keyboard - mouse functions. # kp= key pres, kr= key release, mp= mouse press, mr= mouse release def ppc(_):pass def kp_mp_function(range_key): press_key(range_key), mouse_event(MOUSEEVENTF_MIDDLEDOWN, 0, 0, 0, 0) def kr_mr_function(range_key): release_key(range_key), mouse_event(MOUSEEVENTF_MIDDLEUP, 0, 0, 0, 0) def kp_function(range_key): press_key(range_key) def mp_function(_): mouse_event(MOUSEEVENTF_MIDDLEDOWN, 0, 0, 0, 0) def mr_function(_): mouse_event(MOUSEEVENTF_MIDDLEUP, 0, 0, 0, 0) while not terminate.value: if on_window.value: del_mem() try: process = open_process(process=Info.game_name_executable) base_address = get_module(process, Info.game_name_executable)['base'] local_player = r_uint64(process, base_address + Offsets.local_player) local_player_name = r_string(process, local_player + Offsets.obj_name) stats = Stats() target_selector = TargetSelector(stats=stats) attr_reader = AttributesReader(process, base_address) orbwalk = Orbwalk(process, base_address) screen_width = GetSystemMetrics(0) screen_height = GetSystemMetrics(1) world = World(process, base_address, screen_width, screen_height) world_to_screen = world.world_to_screen get_view_proj_matrix = world.get_view_proj_matrix base_attack_speed = stats.get_attack_speed(local_player_name) windup, windup_mod = stats.get_windup(local_player_name) orbwalk_key = VK_CODES[settings['orbwalk']] laneclear_key = VK_CODES[settings['laneclear']] lasthit_key = VK_CODES[settings['lasthit']] attack_key = VK_CODES[settings['attack']] range_key = VK_CODES[settings['range']] kiting_mode = settings['kiting_mode'] target_prio = settings['orbwalk_prio'] mode_lasthit = settings['lasthit_mode'] press_range = settings['press_range'] potato_pc = settings['ppc'] target_prio_modes = { 'Less Basic Attacks' : target_selector.select_by_health, 'Most Damage' : target_selector.select_by_damage, 'Nearest Enemy' : target_selector.select_by_distance } select_target = target_prio_modes.get(target_prio, target_selector.select_by_health) select_minion_target = target_selector.select_by_health select_minion_lasthit = target_selector.select_by_lasthit walk_modes = { 'Normal' : orbwalk.walk, 'Normal v2' : orbwalk.walk_v2, 'In-place' : orbwalk.walk_inplace, 'Kalista' : orbwalk.walk_kalista } walk = walk_modes.get(local_player_name, walk_modes[kiting_mode]) walk_min = orbwalk.walk # Script will press all keys it needs. kp_mp, kr_mr, kp, mr = kp_mp_function, kr_mr_function, kp_function, mr_function if not press_range: # Script wont press ShowAdvancedPlayerStats key. kp_mp, kr_mr, kp = mp_function, mr_function, ppc if potato_pc: # Script wont press any key. kp_mp = kr_mr = kp = mr = ppc except Exception as spaceglider_proc_loop: debug_info(spaceglider_proc_loop, True) else: try: while 1: if GetAsyncKeyState(orbwalk_key): kp_mp(range_key) entities = [attr_reader.read_enemy(pointer) for pointer in champion_pointers] target = select_target(attr_reader.read_player(local_player), entities) if target: pos = world_to_screen(get_view_proj_matrix(), target.x, target.z, target.y) walk(pos, attack_key, base_attack_speed, windup, windup_mod) else: sleep(0.1) right_click() continue elif GetAsyncKeyState(lasthit_key): kp_mp(range_key) entities = [attr_reader.read_minion(pointer) for pointer in minion_pointers] target = select_minion_lasthit(attr_reader.read_player(local_player), entities) if target: mr(0) pos = world_to_screen(get_view_proj_matrix(), target.x, target.z, target.y) walk_min(pos, attack_key, base_attack_speed, windup, windup_mod) else: right_click() sleep(0.1) continue elif GetAsyncKeyState(laneclear_key): kp(range_key) entities = [attr_reader.read_minion(pointer) for pointer in minion_pointers] target = select_minion_target(attr_reader.read_player(local_player), entities) if target: pos = world_to_screen(get_view_proj_matrix(), target.x, target.z, target.y) walk_min(pos, attack_key, base_attack_speed, windup, windup_mod) else: right_click() sleep(0.1) continue orbwalk.can_attack_time = 0 kr_mr(range_key) if not on_window.value: break sleep(0.1) except Exception as spaceglider_loop: debug_info(spaceglider_loop, True) kr_mr_function(range_key) ================================================ FILE: vakscript/stats.py ================================================ #built-in from urllib.request import urlopen from functools import lru_cache from time import sleep #ext from orjson import loads from requests import get #own from data import Info from utils import debug_info """ TODO: - Update default windup modifier. - Add stats if its needed. """ class Stats: def __init__(self): while True: try: stats = loads(urlopen(Info.url_allgamedata).read()) self.names = [champion['rawChampionName'].removeprefix('game_character_displayname_').lower() for champion in stats['allPlayers']] self.champion_data = dict() for name in self.names: champion_response = get(Info.url_comunitydragon.format(name=name)).json() self.champion_data[name] = {k.lower(): v for k, v in champion_response.items()} break except Exception as stats_loop: debug_info(stats_loop, True) sleep(0.1) @lru_cache(maxsize=None) def get_attack_speed(self, name): name = name.lower() root_key = 'characters/{}/characterrecords/root'.format(name) base_as = self.champion_data[name][root_key]['attackSpeed'] return base_as @lru_cache(maxsize=None) def get_radius(self, name): name = name.lower() try: root_key = 'characters/{}/characterrecords/root'.format(name) return self.champion_data[name][root_key].get('overrideGameplayCollisionRadius', 65.0) except: return 65.0 @lru_cache(maxsize=None) def get_windup(self, name): name = name.lower() root_key = 'characters/{}/characterrecords/root'.format(name) basic_attack = self.champion_data[name][root_key]['basicAttack'] windup = 0.3 windup_mod = 0. if 'mAttackDelayCastOffsetPercent' in basic_attack: windup = basic_attack['mAttackDelayCastOffsetPercent'] + 0.3 if 'mAttackDelayCastOffsetPercentAttackSpeedRatio' in basic_attack: windup_mod = basic_attack['mAttackDelayCastOffsetPercentAttackSpeedRatio'] return windup, windup_mod def get_targets_radius(self): champions_radius = dict() for name in self.names: radius = self.get_radius(name) champions_radius[name.capitalize()] = radius return champions_radius ================================================ FILE: vakscript/utils.py ================================================ #built-in from ctypes import wintypes, Structure, Union, WinDLL, POINTER, byref, sizeof from random import choice from string import printable from traceback import print_exc from time import sleep #ext from win32gui import GetWindowText, GetForegroundWindow #own from data import Info DEBUG = True # user32 = WinDLL('user32', use_last_error=True) INPUT_KEYBOARD = 1 KEYEVENTF_EXTENDEDKEY = 0x0001 KEYEVENTF_KEYUP = 0x0002 KEYEVENTF_UNICODE = 0x0004 MAPVK_VK_TO_VSC = 0 wintypes.ULONG_PTR = wintypes.WPARAM class MOUSEINPUT(Structure): _fields_ = (("dx", wintypes.LONG), ("dy", wintypes.LONG), ("mouseData", wintypes.DWORD), ("dwFlags", wintypes.DWORD), ("time", wintypes.DWORD), ("dwExtraInfo", wintypes.ULONG_PTR)) class KEYBDINPUT(Structure): _fields_ = (("wVk", wintypes.WORD), ("wScan", wintypes.WORD), ("dwFlags", wintypes.DWORD), ("time", wintypes.DWORD), ("dwExtraInfo", wintypes.ULONG_PTR)) def __init__(self, *args, **kwds): super(KEYBDINPUT, self).__init__(*args, **kwds) if not self.dwFlags & KEYEVENTF_UNICODE: self.wScan = user32.MapVirtualKeyExW(self.wVk, MAPVK_VK_TO_VSC, 0) class HARDWAREINPUT(Structure): _fields_ = (("uMsg", wintypes.DWORD), ("wParamL", wintypes.WORD), ("wParamH", wintypes.WORD)) class INPUT(Structure): class _INPUT(Union): _fields_ = (("ki", KEYBDINPUT), ("mi", MOUSEINPUT), ("hi", HARDWAREINPUT)) _anonymous_ = ("_input",) _fields_ = (("type", wintypes.DWORD), ("_input", _INPUT)) def press_key(hexKeyCode): x = INPUT(type=INPUT_KEYBOARD, ki=KEYBDINPUT(wVk=hexKeyCode)) user32.SendInput(1, byref(x), sizeof(x)) def release_key(hexKeyCode): x = INPUT(type=INPUT_KEYBOARD, ki=KEYBDINPUT(wVk=hexKeyCode, dwFlags=KEYEVENTF_KEYUP)) user32.SendInput(1, byref(x), sizeof(x)) def send_key(hexKeyCode): press_key(hexKeyCode) release_key(hexKeyCode) def is_active_window(): return GetWindowText(GetForegroundWindow()) == Info.game_name_window def safe_title(): return "".join(choice(printable) for i in range(11)) def debug_info(exception=None, ex_info=False, info=None): if DEBUG: if info is not None: print(f'info > {info}') elif exception: print(f's > {exception}') if ex_info: print('d >',end=' ') print_exc() sleep(0.1) ================================================ FILE: vakscript/world_to_screen.py ================================================ #ext from pyMeow import r_bytes from numpy import matmul, array, frombuffer, float32 #own from data import Offsets class World: def __init__(self, process, base_address, width, height): self.process = process self.base_address = base_address self.width = width self.height = height self.view_proj_matrix_offset = Offsets.view_proj_matrix def get_view_proj_matrix(self): data = r_bytes(self.process, self.base_address + self.view_proj_matrix_offset, 0x128) view_matrix = frombuffer(data[:64], dtype=float32).reshape(4, 4) proj_matrix = frombuffer(data[64:128], dtype=float32).reshape(4, 4) view_proj_matrix = matmul(view_matrix, proj_matrix) return view_proj_matrix def world_to_screen(self, view_proj_matrix, x, y, z): clip_coords = matmul(array([x, y, z, 1.0]), view_proj_matrix.reshape(4, 4)) if clip_coords[3] <= 0.: clip_coords[3] = 0.1 clip_coords /= clip_coords[3] return int((self.width / 2.0 * clip_coords[0]) + (clip_coords[0] + self.width / 2.0)), int(-(self.height / 2.0 * clip_coords[1]) + (clip_coords[1] + self.height / 2.0)) def world_to_screen_limited(self, view_proj_matrix, x, y, z): clip_coords = matmul(array([x, y, z, 1.0]), view_proj_matrix.reshape(4, 4)) if clip_coords[3] <= 0.: clip_coords[3] = 0.1 clip_coords /= clip_coords[3] out_x, out_y = int((self.width / 2.0 * clip_coords[0]) + (clip_coords[0] + self.width / 2.0)), int(-(self.height / 2.0 * clip_coords[1]) + (clip_coords[1] + self.height / 2.0)) if 0 <= out_x <= self.width and 0 <= out_y <= self.height: return out_x, out_y