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