Repository: orkido/LViewLoL Branch: master Commit: 49db3ea7e048 Files: 296 Total size: 19.7 MB Directory structure: gitextract_vav3an8l/ ├── .gitignore ├── GameplayScripts/ │ ├── auto_smite.py │ ├── auto_spell.py │ ├── base_script.py │ ├── champ_tracker.py │ ├── commons/ │ │ ├── __init__.py │ │ ├── damage_calculator.py │ │ ├── items.py │ │ ├── skills.py │ │ └── targeting.py │ ├── drawings.py │ ├── execution_notifier.py │ ├── map_awareness.py │ ├── object_viewer.py │ ├── orb_walker.py │ ├── spell_tracker.py │ ├── tf_card_picker.py │ ├── util_make_heightmap.py____ │ └── vision_tracker.py ├── LView/ │ ├── AntiCrack.cpp │ ├── AntiCrack.h │ ├── Benchmark.h │ ├── ConfigSet.cpp │ ├── ConfigSet.h │ ├── GameData.cpp │ ├── GameData.h │ ├── GameObject.cpp │ ├── GameObject.h │ ├── GameRenderer.cpp │ ├── GameRenderer.h │ ├── Input.cpp │ ├── Input.h │ ├── ItemInfo.h │ ├── ItemSlot.cpp │ ├── ItemSlot.h │ ├── LView.cpp │ ├── LView.vcxproj │ ├── LView.vcxproj.filters │ ├── LView.vcxproj.user │ ├── LeagueMemoryReader.cpp │ ├── LeagueMemoryReader.h │ ├── MapObject.cpp │ ├── MapObject.h │ ├── MemSnapshot.h │ ├── MemoryLoadable.h │ ├── Offsets.cpp │ ├── Offsets.h │ ├── Overlay.cpp │ ├── Overlay.h │ ├── PyGame.h │ ├── PyImguiInterface.h │ ├── PyStructs.h │ ├── Script.cpp │ ├── Script.h │ ├── ScriptManager.cpp │ ├── ScriptManager.h │ ├── Spell.cpp │ ├── Spell.h │ ├── SpellInfo.cpp │ ├── SpellInfo.h │ ├── SpellInterface.h │ ├── Structs.cpp │ ├── Structs.h │ ├── Texture2D.cpp │ ├── Texture2D.h │ ├── UnitInfo.cpp │ ├── UnitInfo.h │ ├── Utils.cpp │ ├── Utils.h │ ├── Vector.h │ ├── boost_container-vc142-mt-gd-x32-1_75.pdb │ ├── boost_json-vc142-mt-gd-x32-1_75.pdb │ ├── boost_python39-vc142-mt-gd-x32-1_75.pdb │ ├── config.ini │ ├── data/ │ │ ├── ItemData.json │ │ ├── SpellData.json │ │ ├── SpellDataCustom.json │ │ └── UnitData.json │ ├── external_includes/ │ │ ├── Python-ast.h │ │ ├── Python.h │ │ ├── abstract.h │ │ ├── asdl.h │ │ ├── ast.h │ │ ├── bitset.h │ │ ├── bltinmodule.h │ │ ├── boolobject.h │ │ ├── bytearrayobject.h │ │ ├── bytesobject.h │ │ ├── cellobject.h │ │ ├── ceval.h │ │ ├── classobject.h │ │ ├── code.h │ │ ├── codecs.h │ │ ├── compile.h │ │ ├── complexobject.h │ │ ├── context.h │ │ ├── cpython/ │ │ │ ├── abstract.h │ │ │ ├── bytearrayobject.h │ │ │ ├── bytesobject.h │ │ │ ├── ceval.h │ │ │ ├── code.h │ │ │ ├── dictobject.h │ │ │ ├── fileobject.h │ │ │ ├── fileutils.h │ │ │ ├── frameobject.h │ │ │ ├── import.h │ │ │ ├── initconfig.h │ │ │ ├── interpreteridobject.h │ │ │ ├── listobject.h │ │ │ ├── methodobject.h │ │ │ ├── object.h │ │ │ ├── objimpl.h │ │ │ ├── pyerrors.h │ │ │ ├── pylifecycle.h │ │ │ ├── pymem.h │ │ │ ├── pystate.h │ │ │ ├── sysmodule.h │ │ │ ├── traceback.h │ │ │ ├── tupleobject.h │ │ │ └── unicodeobject.h │ │ ├── datetime.h │ │ ├── descrobject.h │ │ ├── dictobject.h │ │ ├── dynamic_annotations.h │ │ ├── enumobject.h │ │ ├── errcode.h │ │ ├── eval.h │ │ ├── exports.h │ │ ├── fileobject.h │ │ ├── fileutils.h │ │ ├── floatobject.h │ │ ├── frameobject.h │ │ ├── funcobject.h │ │ ├── genericaliasobject.h │ │ ├── genobject.h │ │ ├── graminit.h │ │ ├── grammar.h │ │ ├── import.h │ │ ├── internal/ │ │ │ ├── pegen_interface.h │ │ │ ├── pycore_abstract.h │ │ │ ├── pycore_accu.h │ │ │ ├── pycore_atomic.h │ │ │ ├── pycore_bytes_methods.h │ │ │ ├── pycore_byteswap.h │ │ │ ├── pycore_call.h │ │ │ ├── pycore_ceval.h │ │ │ ├── pycore_code.h │ │ │ ├── pycore_condvar.h │ │ │ ├── pycore_context.h │ │ │ ├── pycore_dtoa.h │ │ │ ├── pycore_fileutils.h │ │ │ ├── pycore_gc.h │ │ │ ├── pycore_getopt.h │ │ │ ├── pycore_gil.h │ │ │ ├── pycore_hamt.h │ │ │ ├── pycore_hashtable.h │ │ │ ├── pycore_import.h │ │ │ ├── pycore_initconfig.h │ │ │ ├── pycore_interp.h │ │ │ ├── pycore_object.h │ │ │ ├── pycore_pathconfig.h │ │ │ ├── pycore_pyerrors.h │ │ │ ├── pycore_pyhash.h │ │ │ ├── pycore_pylifecycle.h │ │ │ ├── pycore_pymem.h │ │ │ ├── pycore_pystate.h │ │ │ ├── pycore_runtime.h │ │ │ ├── pycore_sysmodule.h │ │ │ ├── pycore_traceback.h │ │ │ ├── pycore_tupleobject.h │ │ │ └── pycore_warnings.h │ │ ├── interpreteridobject.h │ │ ├── intrcheck.h │ │ ├── iterobject.h │ │ ├── listobject.h │ │ ├── longintrepr.h │ │ ├── longobject.h │ │ ├── marshal.h │ │ ├── memoryobject.h │ │ ├── methodobject.h │ │ ├── modsupport.h │ │ ├── moduleobject.h │ │ ├── namespaceobject.h │ │ ├── node.h │ │ ├── object.h │ │ ├── objimpl.h │ │ ├── odictobject.h │ │ ├── opcode.h │ │ ├── osdefs.h │ │ ├── osmodule.h │ │ ├── parsetok.h │ │ ├── patchlevel.h │ │ ├── picklebufobject.h │ │ ├── py_curses.h │ │ ├── pyarena.h │ │ ├── pycapsule.h │ │ ├── pyconfig.h │ │ ├── pyctype.h │ │ ├── pydebug.h │ │ ├── pydtrace.h │ │ ├── pyerrors.h │ │ ├── pyexpat.h │ │ ├── pyfpe.h │ │ ├── pyframe.h │ │ ├── pyhash.h │ │ ├── pylifecycle.h │ │ ├── pymacconfig.h │ │ ├── pymacro.h │ │ ├── pymath.h │ │ ├── pymem.h │ │ ├── pyport.h │ │ ├── pystate.h │ │ ├── pystrcmp.h │ │ ├── pystrhex.h │ │ ├── pystrtod.h │ │ ├── pythonrun.h │ │ ├── pythread.h │ │ ├── pytime.h │ │ ├── rangeobject.h │ │ ├── setobject.h │ │ ├── sliceobject.h │ │ ├── structmember.h │ │ ├── structseq.h │ │ ├── symtable.h │ │ ├── sysmodule.h │ │ ├── token.h │ │ ├── traceback.h │ │ ├── tracemalloc.h │ │ ├── tupleobject.h │ │ ├── typeslots.h │ │ ├── ucnhash.h │ │ ├── unicodeobject.h │ │ ├── warnings.h │ │ └── weakrefobject.h │ ├── external_libs/ │ │ ├── DxErr.lib │ │ ├── DxErr9.lib │ │ ├── X3DAudio.lib │ │ ├── XAPOFX.lib │ │ ├── XInput.lib │ │ ├── _tkinter.lib │ │ ├── boost_python39-vc142-mt-gd-x32-1_75.lib │ │ ├── boost_python39-vc142-mt-x32-1_75.lib │ │ ├── d3d10.lib │ │ ├── d3d10_1.lib │ │ ├── d3d11_beta.lib │ │ ├── d3d9.lib │ │ ├── d3dcompiler.lib │ │ ├── d3dx10.lib │ │ ├── d3dx10d.lib │ │ ├── d3dx11.lib │ │ ├── d3dx9.lib │ │ ├── d3dx9d.lib │ │ ├── d3dxof.lib │ │ ├── ddraw.lib │ │ ├── dinput8.lib │ │ ├── dsetup.lib │ │ ├── dsound.lib │ │ ├── dxgi.lib │ │ ├── dxgi_beta.lib │ │ ├── dxguid.lib │ │ ├── libboost_container-vc142-mt-gd-x32-1_75.lib │ │ ├── libboost_container-vc142-mt-x32-1_75.lib │ │ ├── libboost_json-vc142-mt-gd-x32-1_75.lib │ │ ├── libboost_json-vc142-mt-x32-1_75.lib │ │ ├── python3.lib │ │ ├── python39.lib │ │ ├── python39.pdb │ │ ├── python39_d.lib │ │ ├── python39_d.pdb │ │ ├── python3_d.lib │ │ ├── xapobase.lib │ │ └── xapobased.lib │ ├── imconfig.h │ ├── imgui.cpp │ ├── imgui.h │ ├── imgui.ini │ ├── imgui_demo.cpp │ ├── imgui_draw.cpp │ ├── imgui_impl_dx11.cpp │ ├── imgui_impl_dx11.h │ ├── imgui_impl_win32.cpp │ ├── imgui_impl_win32.h │ ├── imgui_internal.h │ ├── imgui_log.txt │ ├── imgui_tables.cpp │ ├── imgui_widgets.cpp │ ├── imstb_rectpack.h │ ├── imstb_textedit.h │ ├── imstb_truetype.h │ └── stb_image.h ├── LView.sln ├── README.md └── UtilityScripts/ ├── DownloadIcons.py ├── DownloadUnitData.py ├── GenerateItemData.py └── GenerateUnitData.py ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ x64/ Debug/ Release/ LView/boost/ LView/Debug/ LView/Release/ LView/x64/ ================================================ FILE: GameplayScripts/auto_smite.py ================================================ from lview import * enable_key = 0 show_smitable = False enabled_autosmite = False lview_script_info = { "script": "Auto Smite", "author": "leryss", "description": "Auto smites the jungle mob under the cursor" } def lview_load_cfg(cfg): global enable_key, show_smitable enable_key = cfg.get_int("enable_key", 0) show_smitable = cfg.get_bool("show_smitable", True) def lview_save_cfg(cfg): global enable_key, show_smitable cfg.set_int("enable_key", enable_key) cfg.set_bool("show_smitable", show_smitable) def lview_draw_settings(game, ui): global enable_key, show_smitable show_smitable = ui.checkbox("Show when to smite", show_smitable) enable_key = ui.keyselect("Enable auto smite key", enable_key) def lview_update(game, ui): global enable_key, enabled_autosmite, show_smitable smite = game.player.get_summoner_spell(SummonerSpellType.Smite) if smite == None: return if game.was_key_pressed(enable_key): enabled_autosmite = ~enabled_autosmite hovered = game.hovered_obj is_smitable = (hovered and (hovered.has_tags(UnitTag.Unit_Monster_Large) or hovered.has_tags(UnitTag.Unit_Monster_Epic)) and hovered.health - smite.value <= 0) if enabled_autosmite: p = game.world_to_screen(game.player.pos) p.y -= 50 game.draw_button(p, "AutoSmiteOn", Color.BLACK, Color.YELLOW, 10); if is_smitable: smite.trigger() if show_smitable and is_smitable: game.draw_circle_world(hovered.pos, hovered.gameplay_radius, 30, 3, Color.YELLOW) ================================================ FILE: GameplayScripts/auto_spell.py ================================================ from lview import * from commons.targeting import TargetingConfig from commons.skills import * import json, time from pprint import pprint lview_script_info = { "script": "Auto Spell", "author": "leryss", "description": "Automatically casts spells on targets. Skillshots are cast using movement speed prediction. Works great for MOST skills but fails miserably for a few (for example yuumis Q)", } targeting = TargetingConfig() cast_keys = { 'Q': 0, 'W': 0, 'E': 0, 'R': 0 } def lview_load_cfg(cfg): global targeting, cast_keys targeting.load_from_cfg(cfg) cast_keys = json.loads(cfg.get_str('cast_keys', json.dumps(cast_keys))) def lview_save_cfg(cfg): global targeting, cast_keys targeting.save_to_cfg(cfg) cfg.set_str('cast_keys', json.dumps(cast_keys)) def lview_draw_settings(game, ui): global targeting, cast_keys targeting.draw(ui) for slot, key in cast_keys.items(): cast_keys[slot] = ui.keyselect(f'Key to cast {slot}', key) draw_prediction_info(game, ui) def lview_update(game, ui): global targeting, cast_keys for slot, key in cast_keys.items(): if game.was_key_pressed(key): skill = getattr(game.player, slot) b_is_skillshot = is_skillshot(skill.name) skill_range = get_skillshot_range(game, skill.name) if b_is_skillshot else 1500.0 target = targeting.get_target(game, skill_range) if target: if b_is_skillshot: cast_point = castpoint_for_collision(game, skill, game.player, target) else: cast_point = target.pos if cast_point: cast_point = game.world_to_screen(cast_point) old_cpos = game.get_cursor() game.move_cursor(cast_point) skill.trigger() time.sleep(0.01) game.move_cursor(old_cpos) ================================================ FILE: GameplayScripts/base_script.py ================================================ from lview import * lview_script_info = { "script": "", "author": "", "description": "", "target_champ": "none" } def lview_load_cfg(cfg): pass def lview_save_cfg(cfg): pass def lview_draw_settings(game, ui): pass def lview_update(game, ui): pass ================================================ FILE: GameplayScripts/champ_tracker.py ================================================ from lview import * from time import time lview_script_info = { "script": "Champion Tracker", "author": "leryss", "description": "Tracks a enemy throughout the map leaving a trail on the minimap. It will track the enemy jungler by default" } first_iter = True champ_ids = [] tracks = {} tracked_champ_id = 0 seconds_to_track = 3.0 t_last_save_tracks = 0 def lview_load_cfg(cfg): global seconds_to_track seconds_to_track = cfg.get_float("seconds_to_track", 10) def lview_save_cfg(cfg): global seconds_to_track cfg.set_float("seconds_to_track", seconds_to_track) def lview_draw_settings(game, ui): global tracked_champ_id, seconds_to_track, tracks, champ_ids seconds_to_track = ui.dragfloat("Seconds to track", seconds_to_track, 0.1, 3, 20) tracked_champ_id = ui.listbox("Champion to track", [game.get_obj_by_netid(net_id).name for net_id in champ_ids], tracked_champ_id) def lview_update(game, ui): global first_iter, champ_ids global tracks, tracked_champ_id, seconds_to_track, t_last_save_tracks if first_iter: first_iter = False # Populate tracks dict and find jungler to track for champ in game.champs: if champ.is_ally_to(game.player): continue champ_ids.append(champ.net_id) last_idx = len(champ_ids) - 1 tracks[last_idx] = [] if champ.get_summoner_spell(SummonerSpellType.Smite) != None: tracked_champ_id = last_idx # If we didnt find a jungler we just track the first champ by default if tracked_champ_id == 0: tracked_champ_id = 0 if len(tracks) == 0: return now = time() if now - t_last_save_tracks > 0.4: t_last_save_tracks = now for idx, track in tracks.items(): champ = game.get_obj_by_netid(champ_ids[idx]) if champ and champ.is_alive: tracks[idx].append((Vec3(champ.pos.x, champ.pos.y, champ.pos.z), now)) tracks[idx] = list(filter(lambda t: now - t[1] < seconds_to_track, tracks[idx])) for i, (pos, t) in enumerate(tracks[tracked_champ_id]): x = i/len(tracks[tracked_champ_id]) green = (1-2*(x-0.5)/1.0 if x > 0.5 else 1.0); red = (1.0 if x > 0.5 else 2*x/1.0); p = game.world_to_minimap(pos) game.draw_circle_filled(p, 4, 4, Color(red, green, 0.0, 1.0)) ================================================ FILE: GameplayScripts/commons/__init__.py ================================================ ================================================ FILE: GameplayScripts/commons/damage_calculator.py ================================================ import enum from typing import Optional class DamageType(enum.Enum): True_ = 0 Normal = 1 Magic = 2 class DamageSpecification: damage_type: Optional[DamageType] = None base_damage = 0.0 percent_ad = 0.0 percent_ap = 0.0 # Damage is increased by up to missing_health_multiplier based on missing enemy health. Maximum if enemy health is below missing_health_max_multiplier missing_health_scale_multiplier = 0.0 missing_health_max_scale_multiplier = 1.0 # Damage increased by missing_health_multiplier * enemy_missing_health missing_health_multiplier = 0.0 # Damage increased by max_health_multiplier * enemy_max_health max_health_multiplier = 0.0 # damage dealt by source to target def calculate_damage(self, source, target): # Calculate resistance resistance_value = 0.0 penetration_percent = 0.0 penetration_flat = 0.0 penetration_lethality = 0.0 if self.damage_type is None: return 0 elif self.damage_type == DamageType.True_: pass elif self.damage_type == DamageType.Normal: resistance_value = target.armour penetration_percent = 0.0 # TODO penetration_flat = 0.0 # TODO penetration_lethality = 0.0 # TODO elif self.damage_type == DamageType.Magic: resistance_value = target.magic_resist penetration_percent = 0.0 # TODO penetration_flat = 0.0 # TODO penetration_lethality = 0.0 # TODO # Lethality calculation penetration_flat += penetration_lethality * (0.6 + 0.4 * source.lvl / 18.0) # Negative resistance is not affected by penetration if(resistance_value > 0.0): resistance_value = resistance_value * penetration_percent - penetration_flat # Penetration cannot reduce resistance below 0 resistance_value = max(0.0, resistance_value) # Damage multiplier for armor, magic resistance or true damage (resistance_value is zero for true damage) if resistance_value >= 0.0: damage_multiplier = 100.0 / (100.0 + resistance_value) else: damage_multiplier = 2.0 - 100.0 / (100.0 - resistance_value) dealt_damage = ( self.base_damage + self.missing_health_multiplier * (target.max_health - target.health) + self.max_health_multiplier * target.max_health + self.percent_ad * (source.base_atk + source.bonus_atk) + self.percent_ap * source.ap ) percent_current_health = target.health / target.max_health if percent_current_health <= self.missing_health_max_scale_multiplier: dealt_damage = dealt_damage * (1.0 + self.missing_health_scale_multiplier) else: dealt_damage = (dealt_damage * (1.0 + self.missing_health_scale_multiplier - self.missing_health_scale_multiplier * ((percent_current_health - self.missing_health_max_scale_multiplier) / (1.0 - self.missing_health_max_scale_multiplier)))) # Multiplier for armor, magic resist or true damage dealt_damage = damage_multiplier * dealt_damage return dealt_damage def get_damage_specification(champ) -> Optional[DamageSpecification]: spec = DamageSpecification() if champ.name == "darius": # TODO: passive damage multiplier spec.damage_type = DamageType.True_ spec.percent_ad = 0.75 if champ.R.level == 1: spec.base_damage = 100.0 elif champ.R.level == 2: spec.base_damage = 200.0 elif champ.R.level == 3: spec.base_damage = 300.0 elif champ.name == "garen": spec.damage_type = DamageType.True_ if champ.R.level == 1: spec.base_damage = 150.0 spec.missing_health_multiplier = 0.20 elif champ.R.level == 2: spec.base_damage = 300.0 spec.missing_health_multiplier = 0.25 elif champ.R.level == 3: spec.base_damage = 450.0 spec.missing_health_multiplier = 0.30 elif champ.name == "lux": spec.damage_type = DamageType.Magic spec.percent_ap = 1.0 if champ.R.level == 1: spec.base_damage = 300.0 elif champ.R.level == 2: spec.base_damage = 400.0 elif champ.R.level == 3: spec.base_damage = 500.0 elif champ.name == "veigar": spec.damage_type = DamageType.Magic spec.percent_ap = 0.75 spec.missing_health_scale_multiplier = 1.0 spec.missing_health_max_scale_multiplier = 0.33 if champ.R.level == 1: spec.base_damage = 175.0 elif champ.R.level == 2: spec.base_damage = 250.0 elif champ.R.level == 3: spec.base_damage = 325.0 else: return None return spec ================================================ FILE: GameplayScripts/commons/items.py ================================================ from lview import * def crit_from_items(items): crit = 0.0 for item in items: crit += item.crit return crit def onhit_guinsoo(src, target): return crit_from_items(src.items) * 100.0 * 2.0 def onhit_rageknife(src, target): return crit_from_items(src.items) * 100.0 * 1.75 def onhit_noonquiver(src, target): return 0.0 if target.has_tags(UnitTag.Unit_Champion) else 20.0 def onhit_recurve_bow(src, target): return 15.0 def onhit_botrk(src, target): dmg = target.health * (0.06 if src.is_ranged else 0.1) if dmg > 60.0 and not target.has_tags(UnitTag.Unit_Champion): return 60.0 return dmg def onhit_doran_ring(src, target): return 5.0 def onhit_nashors(src, target): return 15.0 + 0.2 * src.ap def onhit_wits_end(src, target): return 11.7 + 3.82 * src.lvl OnHit_Physical = { 3124: onhit_guinsoo, 6677: onhit_rageknife, 6670: onhit_noonquiver, 1043: onhit_recurve_bow, 3153: onhit_botrk, 1056: onhit_doran_ring } OnHit_Magical = { 3115: onhit_nashors, 3091: onhit_wits_end } def get_onhit_physical(source, target): global OnHit_Physical phys = source.base_atk + source.bonus_atk for item in source.items: if item.id in OnHit_Physical: phys += OnHit_Physical[item.id](source, target) return phys def get_onhit_magical(source, target): global OnHit_Magical magical = 0.0 for item in source.items: if item.id in OnHit_Magical: magical += OnHit_Magical[item.id](source, target) return magical ================================================ FILE: GameplayScripts/commons/skills.py ================================================ from lview import * import math, itertools, time from . import items Version = "experimental version" MissileToSpell = {} Spells = {} ChampionSpells = {} class SFlag: Targeted = 1 Line = 2 Cone = 4 Area = 8 CollideWindwall = 16 CollideChampion = 32 CollideMob = 64 CollideGeneric = CollideMob | CollideChampion | CollideWindwall SkillshotLine = CollideGeneric | Line class Spell: def __init__(self, name, missile_names, flags, delay = 0.0): global MissileToSpell, Spells self.flags = flags self.name = name self.missiles = missile_names self.delay = delay Spells[name] = self for missile in missile_names: MissileToSpell[missile] = self delay = 0.0 flags = 0 name = "?" missiles = [] ChampionSpells = { "aatrox": [ Spell("aatroxw", ["aatroxw"], SFlag.CollideGeneric) ], "aurelionsol": [ Spell("aurelionsolq", ["aurelionsolqmissile"], SFlag.SkillshotLine), Spell("aurelionsolr", ["aurelionsolrbeammissile"], SFlag.Line | SFlag.CollideWindwall) ], "ahri": [ Spell("ahriorbofdeception", ["ahriorbmissile"], SFlag.Line | SFlag.CollideWindwall), Spell("ahriseduce", ["ahriseducemissile"], SFlag.CollideGeneric) ], "ashe": [ Spell("volleyattack", ["volleyattack", "volleyattackwithsound"], SFlag.SkillshotLine), Spell("enchantedcrystalarrow", ["enchantedcrystalarrow"], SFlag.Line | SFlag.CollideWindwall | SFlag.CollideChampion) ], "brand": [ Spell("brandq", ["brandqmissile"], SFlag.SkillshotLine), Spell("brandw", [], SFlag.Area) ], "caitlyn": [ Spell("caitlynpiltoverpeacemaker", ["caitlynpiltoverpeacemaker", "caitlynpiltoverpeacemaker2"], SFlag.Line | SFlag.CollideWindwall), Spell("caitlynyordletrap", [], SFlag.Area), Spell("caitlynentrapment", ["caitlynentrapmentmissile"], SFlag.SkillshotLine) ], "chogath": [ Spell("rupture", [], SFlag.Area, delay = 0.627), Spell("feralscream", [], SFlag.Cone | SFlag.CollideWindwall) ], "drmundo": [ Spell("infectedcleavermissilecast", ["infectedcleavermissile"], SFlag.SkillshotLine) ], "diana": [ Spell("dianaq", ["dianaqinnermissile", "dianaqoutermissile"], SFlag.Area) ], "ekko": [ Spell("ekkoq", ["ekkoqmis"], SFlag.Line | SFlag.CollideChampion), Spell("ekkow", ["ekkowmis"], SFlag.Area, delay=3.0) ], "fizz": [ Spell("fizzr", ["fizzrmissile"], SFlag.Line | SFlag.CollideChampion | SFlag.CollideWindwall) ], "irelia": [ Spell("ireliae", ["ireliaemissile"], SFlag.Area), Spell("ireliar", ["ireliar"], SFlag.SkillshotLine) ], "illaoi": [ Spell("illaoiq", [], SFlag.Area), Spell("illaoie", ["illaoiemis"], SFlag.SkillshotLine) ], "jarvaniv": [ Spell("jarvanivdemacianstandard", [], SFlag.Area) ], "khazix": [ Spell("khazixw", ["khazixwmissile"], SFlag.SkillshotLine), Spell("khazixwlong", ["khazixwmissile"], SFlag.SkillshotLine) ], "ezreal": [ Spell("ezrealq", ["ezrealq"], SFlag.SkillshotLine), Spell("ezrealw", ["ezrealw"], SFlag.SkillshotLine), Spell("ezrealr", ["ezrealr"], SFlag.SkillshotLine) ], "evelynn": [ Spell("evelynnq", ["evelynnq"], SFlag.SkillshotLine) ], "graves": [ Spell("gravesqlinespell", ["gravesqlinemis", "gravesqreturn"], SFlag.Line | SFlag.CollideChampion | SFlag.CollideWindwall), Spell("gravessmokegrenade", ["gravessmokegrenadeboom"], SFlag.Area | SFlag.CollideWindwall), Spell("graveschargeshot", ["graveschargeshotshot"], SFlag.Line | SFlag.CollideWindwall) ], "twistedfate": [ Spell("wildcards", ["sealfatemissile"], SFlag.CollideWindwall | SFlag.Line) ], "leesin": [ Spell("blindmonkqone", ["blindmonkqone"], SFlag.SkillshotLine) ], "leona": [ Spell("leonazenithblade", ["leonazenithblademissile"], SFlag.Line | SFlag.CollideChampion | SFlag.CollideWindwall), Spell("leonasolarflare", [], SFlag.Area) ], "leblanc": [ Spell("leblancw", [], SFlag.Area), Spell("leblancrw", [], SFlag.Area), Spell("leblance", ["leblancemissile"], SFlag.SkillshotLine), Spell("leblancre", ["leblancremissile"], SFlag.SkillshotLine) ], "lucian": [ Spell("lucianw", ["lucianwmissile"], SFlag.SkillshotLine), Spell("lucianr", ["lucianrmissile", "lucianrmissileoffhand"], SFlag.SkillshotLine) ], "rengar": [ Spell("rengare", ["rengaremis"], SFlag.SkillshotLine), Spell("rengareemp", ["rengareempmis"], SFlag.SkillshotLine), ], "ryze": [ Spell("ryzeqwrapper", ["ryzeq"], SFlag.SkillshotLine) ], "varus": [ Spell("varusq", ["varusqmissile"], SFlag.Line | SFlag.CollideWindwall), Spell("varuse", ["varusemissile"], SFlag.Area), Spell("varusr", ["varusrmissile"], SFlag.Line | SFlag.CollideChampion | SFlag.CollideWindwall) ], "veigar": [ Spell("veigarbalefulstrike", ["veigarbalefulstrikemis"], SFlag.SkillshotLine), Spell("veigardarkmatter", [], SFlag.Area, delay=1.0), Spell("veigareventhorizon", [], SFlag.Area, delay=0.5) ], "lux": [ Spell("luxlightbinding", ["luxlightbindingmis"], SFlag.SkillshotLine), Spell("luxlightstrikekugel", ["luxlightstrikekugel"], SFlag.Area | SFlag.CollideWindwall), Spell("luxmalicecannon", ["luxmalicecannon"], SFlag.Line) ], "ziggs": [ Spell("ziggsq", ["ziggsqspell", "ziggsqspell2", "ziggsqspell3"], SFlag.Area | SFlag.CollideWindwall), Spell("ziggsw", ["ziggsw"], SFlag.Area | SFlag.CollideWindwall), Spell("ziggse", ["ziggse2"], SFlag.Area | SFlag.CollideWindwall), Spell("ziggsr", ["ziggsrboom", "ziggsrboommedium", "ziggsrboomlong", "ziggsrboomextralong"], SFlag.Area), ], "jhin": [ Spell("jhinw", ["jhinw"], SFlag.Line | SFlag.CollideChampion | SFlag.CollideWindwall, delay=0.5), Spell("jhine", ["jhinetrap"], SFlag.Area | SFlag.CollideWindwall), Spell("jhinrshot", ["jhinrshotmis", "jhinrshotmis4"], SFlag.Line | SFlag.CollideWindwall | SFlag.CollideChampion) ], "nasus": [ Spell("nasuse", [], SFlag.Area) ], "nami": [ Spell("namiq", ["namiqmissile"], SFlag.Area), Spell("namir", ["namirmissile"], SFlag.Line | SFlag.CollideWindwall) ], "nidalee": [ Spell("javelintoss", ["javelintoss"], SFlag.SkillshotLine), Spell("bushwhack", [], SFlag.Area) ], "malphite": [ Spell("ufslash", [], SFlag.Area) ], "thresh": [ Spell("threshq", ["threshqmissile"], SFlag.SkillshotLine), Spell("threshw", ["threshwlanternout"], SFlag.Area | SFlag.CollideWindwall) ], "morgana": [ Spell("morganaq", ["morganaq"], SFlag.SkillshotLine), Spell("morganaw", [], SFlag.Area, delay=0.25) ], "missfortune": [ Spell("missfortunescattershot", [], SFlag.Area, delay=0.25), Spell("missfortunebullettime", ["missfortunebullets"], SFlag.Line | SFlag.CollideWindwall) ], "pantheon": [ Spell("pantheonq", ["pantheonqmissile"], SFlag.Line | SFlag.CollideWindwall), Spell("pantheonr", ["pantheonrmissile"], SFlag.Area) ], "annie": [ Spell("anniew", [], SFlag.Cone | SFlag.CollideWindwall), Spell("annier", [], SFlag.Area) ], "olaf": [ Spell("olafaxethrowcast", ["olafaxethrow"], SFlag.Line | SFlag.CollideWindwall) ], "anivia": [ Spell("flashfrost", ["flashfrostspell"], SFlag.Line | SFlag.CollideWindwall), Spell("crystallize", [], SFlag.Area, delay=0.25), Spell("glacialstorm", [], SFlag.Area) ], "urgot": [ Spell("urgotq", ["urgotqmissile"], SFlag.Area | SFlag.CollideWindwall, delay = 0.2), Spell("urgotr", ["urgotr"], SFlag.Line | SFlag.CollideWindwall | SFlag.CollideChampion) ], "senna": [ Spell("sennaw", ["sennaw"], SFlag.SkillshotLine), Spell("sennar", ["sennar"], SFlag.Line) ], "shyvana": [ Spell("shyvanafireball", ["shyvanafireballmissile"], SFlag.Line | SFlag.CollideChampion | SFlag.CollideWindwall), Spell("shyvanafireballdragon2", ["shyvanafireballdragonmissile"], SFlag.Line | SFlag.Area | SFlag.CollideChampion | SFlag.CollideWindwall) ], "singed": [ Spell("megaadhesive", ["singedwparticlemissile"], SFlag.Area) ], "sivir": [ Spell("sivirq", ["sivirqmissile"], SFlag.Line | SFlag.CollideWindwall) ], "soraka": [ Spell("sorakaq", ["sorakaqmissile"], SFlag.Area), Spell("sorakae", [], SFlag.Area) ], "sona": [ Spell("sonar", ["sonar"], SFlag.Line | SFlag.CollideWindwall) ], "kayle": [ Spell("kayleq", ["kayleqmis"], SFlag.SkillshotLine) ], "zac": [ Spell("zacq", ["zacqmissile"], SFlag.SkillshotLine), Spell("zace", [], SFlag.Area) ], "zyra": [ Spell("zyraq", [], SFlag.Area), Spell("zyraw", [], SFlag.Area), Spell("zyrae", ["zyrae"], SFlag.Line | SFlag.CollideWindwall), Spell("zyrar", [], SFlag.Area) ], "zilean": [ Spell("zileanq", ["zileanqmissile"], SFlag.Area | SFlag.CollideWindwall) ], "orianna": [ Spell("orianaizunacommand", ["orianaizuna"], SFlag.Line | SFlag.Area | SFlag.CollideWindwall) ], "warwick": [ Spell("warwickr", [], SFlag.Area | SFlag.CollideChampion) ] } def draw_prediction_info(game, ui): global ChampionSpells, Version ui.separator() ui.text("Using LPrediction " + Version, Color.PURPLE) if is_champ_supported(game.player): ui.text(game.player.name.upper() + " has skillshot prediction support", Color.GREEN) else: ui.text(game.player.name.upper() + " doesnt have skillshot prediction support", Color.RED) if ui.treenode(f'Supported Champions ({len(ChampionSpells)})'): for champ, spells in sorted(ChampionSpells.items()): ui.text(f"{champ.upper()} {' '*(20 - len(champ))}: {str([spell.name for spell in spells])}") ui.treepop() def get_skillshot_range(game, skill_name): global Spells if skill_name not in Spells: raise Exception("Not a skillshot") # Get the range of the missile if it has a missile skillshot = Spells[skill_name] if len(skillshot.missiles) > 0: return game.get_spell_info(skillshot.missiles[0]).cast_range # If it doesnt have a missile get simply the cast_range from the skill info = game.get_spell_info(skill_name) return info.cast_range*2.0 if is_skillshot_cone(skill_name) else info.cast_range def is_skillshot(skill_name): global Spells, MissileToSpell return skill_name in Spells or skill_name in MissileToSpell def get_missile_parent_spell(missile_name): global MissileToSpell return MissileToSpell.get(missile_name, None) def is_champ_supported(champ): global ChampionSpells return champ.name in ChampionSpells def is_skillshot_cone(skill_name): if skill_name not in Spells: return False return Spells[skill_name].flags & SFlag.Cone def is_last_hitable(game, player, enemy): missile_speed = player.basic_missile_speed + 1 hit_dmg = items.get_onhit_physical(player, enemy) + items.get_onhit_magical(player, enemy) hp = enemy.health atk_speed = player.base_atk_speed * player.atk_speed_multi t_until_basic_hits = game.distance(player, enemy)/missile_speed#(missile_speed*atk_speed/player.base_atk_speed) for missile in game.missiles: if missile.dest_id == enemy.id: src = game.get_obj_by_id(missile.src_id) if src: t_until_missile_hits = game.distance(missile, enemy)/(missile.speed + 1) if t_until_missile_hits < t_until_basic_hits: hp -= src.base_atk return hp - hit_dmg <= 0 # Returns a point where the mouse should click to cast a spells taking into account the targets movement speed def castpoint_for_collision(game, spell, caster, target): global Spells print('predicted') if spell.name not in Spells: return None # Get extra data for spell that isnt provided by lview spell_extra = Spells[spell.name] if len(spell_extra.missiles) > 0: missile = game.get_spell_info(spell_extra.missiles[0]) else: missile = spell t_delay = spell.delay + spell_extra.delay if missile.travel_time > 0.0: t_missile = missile.travel_time else: t_missile = (missile.cast_range / missile.speed) if len(spell_extra.missiles) > 0 and missile.speed > 0.0 else 0.0 # Get direction of target target_dir = target.pos.sub(target.prev_pos).normalize() if math.isnan(target_dir.x): target_dir.x = 0.0 if math.isnan(target_dir.y): target_dir.y = 0.0 if math.isnan(target_dir.z): target_dir.z = 0.0 #print(f'{target_dir.x} {target_dir.y} {target_dir.z}') # If the spell is a line we simulate the main missile to get the collision point if spell_extra.flags & SFlag.Line: iterations = int(missile.cast_range/30.0) step = t_missile/iterations last_dist = 9999999 last_target_pos = None for i in range(iterations): t = i*step target_future_pos = target.pos.add(target_dir.scale((t_delay + t)*target.movement_speed)) spell_dir = target_future_pos.sub(caster.pos).normalize().scale(t*missile.speed) spell_future_pos = caster.pos.add(spell_dir) dist = target_future_pos.distance(spell_future_pos) #print(dist) if dist < missile.width/2.0: return target_future_pos elif dist > last_dist: return last_target_pos else: last_dist = dist last_target_pos = target_future_pos return None # If the spell is an area spell we return the position of the player when the spell procs elif spell_extra.flags & SFlag.Area: return target.pos.add(target_dir.scale((t_delay + t_missile)*target.movement_speed)) else: return target.pos ================================================ FILE: GameplayScripts/commons/targeting.py ================================================ from enum import Enum class Target(Enum): ClosestToPlayer = 0 LowestHealth = 1 MostFed = 2 class TargetingConfig: targets = [ Target.ClosestToPlayer, Target.LowestHealth, Target.MostFed ] targeting_lambdas = { Target.ClosestToPlayer: (lambda player, enemy: player.pos.distance(enemy.pos)), Target.LowestHealth: (lambda player, enemy: enemy.health), Target.MostFed: (lambda player, enemy: -sum([item.cost for item in enemy.items])) } selected = 0 target_minions = False target_jungle = False def draw(self, ui): ui.separator() self.selected = ui.listbox("Target", [str(target)[7:] for target in self.targets], self.selected) self.target_jungle = ui.checkbox("Allow targeting jungle monsters", self.target_jungle) self.target_minions = ui.checkbox("Allow targeting minions", self.target_minions) def get_target(self, game, range): player = game.player target_info = self.targets[self.selected] target = self.find_target(game, game.champs, range, self.targeting_lambdas[target_info]) if not target: others = [] if self.target_jungle: others.extend(game.jungle) if self.target_minions: others.extend(game.minions) if len(others) > 0: target = self.find_target(game, others, range, self.targeting_lambdas[target_info]) return target def find_target(self, game, array, range, value_extractor): target = None min = 99999999 for obj in array: if not obj.is_alive or not obj.is_visible or obj.is_ally_to(game.player) or (game.distance(game.player, obj) - game.player.gameplay_radius - obj.gameplay_radius) > range: continue val = value_extractor(game.player, obj) if val < min: min = val target = obj return target def load_from_cfg(self, cfg): self.selected = cfg.get_int("targeting_target", 0) self.target_jungle = cfg.get_bool("target_jungle", False) self.target_minions = cfg.get_bool("target_minions", False) def save_to_cfg(self, cfg): cfg.set_int("targeting_target", self.selected) cfg.set_bool("target_jungle", self.target_jungle) cfg.set_bool("target_minions", self.target_minions) ================================================ FILE: GameplayScripts/drawings.py ================================================ ### Note: ### Currently the code to draw skillshots is disabled because there are way too many exceptions to make a general renderer. ### Each skill must have flags/ranges defined separately. Maybe in the future ill make a separate python package with skillshot related things if im helped. from lview import * from time import time import itertools, math from commons.skills import * from copy import copy lview_script_info = { "script": "Drawings", "author": "leryss", "description": "Draws indicators for different things" } turret_ranges = False minion_last_hit = False attack_range = False skillshots = False skillshots_predict = False skillshots_min_range = 0 skillshots_max_speed = 0 skillshots_show_ally = False skillshots_show_enemy = False def lview_load_cfg(cfg): global turret_ranges, minion_last_hit, attack_range global skillshots, skillshots_predict, skillshots_min_range, skillshots_max_speed, skillshots_show_ally, skillshots_show_enemy turret_ranges = cfg.get_bool("turret_ranges", True) minion_last_hit = cfg.get_bool("minion_last_hit", True) attack_range = cfg.get_bool("attack_range", True) skillshots = cfg.get_bool("skillshots", True) skillshots_show_ally = cfg.get_bool("skillshots_show_ally", True) skillshots_show_enemy = cfg.get_bool("skillshots_show_enemy", True) #skillshots_predict = cfg.get_bool("skillshots_predict", True) skillshots_min_range = cfg.get_float("skillshots_min_range", 500) skillshots_max_speed = cfg.get_float("skillshots_max_speed", 2500) def lview_save_cfg(cfg): global turret_ranges, minion_last_hit, attack_range global skillshots, skillshots_predict, skillshots_min_range, skillshots_max_speed, skillshots_show_ally, skillshots_show_enemy cfg.set_bool("turret_ranges", turret_ranges) cfg.set_bool("minion_last_hit", minion_last_hit) cfg.set_bool("attack_range", attack_range) cfg.set_bool("skillshots", skillshots) cfg.set_bool("skillshots_show_ally", skillshots_show_ally) cfg.set_bool("skillshots_show_enemy", skillshots_show_enemy) #cfg.set_bool("skillshots_predict", skillshots_predict) cfg.set_float("skillshots_min_range", skillshots_min_range) cfg.set_float("skillshots_max_speed", skillshots_max_speed) def lview_draw_settings(game, ui): global turret_ranges, minion_last_hit, attack_range global skillshots, skillshots_predict, skillshots_min_range, skillshots_max_speed, skillshots_show_ally, skillshots_show_enemy turret_ranges = ui.checkbox("Turret ranges", turret_ranges) minion_last_hit = ui.checkbox("Minion last hit", minion_last_hit) attack_range = ui.checkbox("Champion attack range", attack_range) ui.separator() ui.text("Skillshots (Experimental)") skillshots = ui.checkbox("Draw skillshots", skillshots) skillshots_show_ally = ui.checkbox("Show for allies", skillshots_show_ally) skillshots_show_enemy = ui.checkbox("Show for enemies", skillshots_show_enemy) #skillshots_predict = ui.checkbox("Use skillshot prediction", skillshots_predict) skillshots_min_range = ui.dragfloat("Minimum skillshot range", skillshots_min_range, 100, 0, 3000) skillshots_max_speed = ui.dragfloat("Maximum skillshot speed", skillshots_max_speed, 100, 1000, 5000) draw_prediction_info(game, ui) def draw_rect(game, start_pos, end_pos, radius, color): dir = Vec3(end_pos.x - start_pos.x, 0, end_pos.z - start_pos.z).normalize() left_dir = Vec3(dir.x, dir.y, dir.z).rotate_y(90).scale(radius) right_dir = Vec3(dir.x, dir.y, dir.z).rotate_y(-90).scale(radius) p1 = Vec3(start_pos.x + left_dir.x, start_pos.y + left_dir.y, start_pos.z + left_dir.z) p2 = Vec3(end_pos.x + left_dir.x, end_pos.y + left_dir.y, end_pos.z + left_dir.z) p3 = Vec3(end_pos.x + right_dir.x, end_pos.y + right_dir.y, end_pos.z + right_dir.z) p4 = Vec3(start_pos.x + right_dir.x, start_pos.y + right_dir.y, start_pos.z + right_dir.z) game.draw_rect_world(p1, p2, p3, p4, 3, color) def draw_atk_range(game, player): color = Color.GREEN color.a = 0.5 game.draw_circle_world(player.pos, player.base_atk_range + player.gameplay_radius, 100, 2, color) def draw_turret_ranges(game, player): color = Color.RED color.a = 0.5 for turret in game.turrets: if turret.is_alive and turret.is_enemy_to(player) and game.is_point_on_screen(turret.pos): range = turret.base_atk_range + turret.gameplay_radius game.draw_circle_world(turret.pos, range, 100, 2, color) dist = turret.pos.distance(player.pos) - range if dist <= player.gameplay_radius: game.draw_circle_world(player.pos, player.gameplay_radius*2, 30, 3, Color.RED) def draw_minion_last_hit(game, player): color = Color.CYAN for minion in game.minions: if minion.is_visible and minion.is_alive and minion.is_enemy_to(player) and game.is_point_on_screen(minion.pos): if is_last_hitable(game, player, minion): p = game.hp_bar_pos(minion) game.draw_rect(Vec4(p.x - 34, p.y - 9, p.x + 32, p.y + 1), Color.CYAN, 0, 2) def draw_skillshots(game, player): global skillshots, skillshots_predict, skillshots_min_range, skillshots_max_speed, skillshots_show_ally, skillshots_show_enemy color = Color.WHITE for missile in game.missiles: if not skillshots_show_ally and missile.is_ally_to(game.player): continue if not skillshots_show_enemy and missile.is_enemy_to(game.player): continue if not is_skillshot(missile.name) or missile.speed > skillshots_max_speed or missile.start_pos.distance(missile.end_pos) < skillshots_min_range: continue spell = get_missile_parent_spell(missile.name) if not spell: continue end_pos = missile.end_pos.clone() start_pos = missile.start_pos.clone() curr_pos = missile.pos.clone() impact_pos = None start_pos.y = game.map.height_at(start_pos.x, start_pos.z) + missile.height end_pos.y = start_pos.y curr_pos.y = start_pos.y if spell.flags & SFlag.Line: draw_rect(game, curr_pos, end_pos, missile.width, color) game.draw_circle_world_filled(curr_pos, missile.width, 20, Color.RED) elif spell.flags & SFlag.Area: r = game.get_spell_info(spell.name).cast_radius end_pos.y = game.map.height_at(end_pos.x, end_pos.z) percent_done = missile.start_pos.distance(curr_pos)/missile.start_pos.distance(end_pos) color = Color(1, 1.0 - percent_done, 0, 0.5) game.draw_circle_world(end_pos, r, 40, 3, color) game.draw_circle_world_filled(end_pos, r*percent_done, 40, color) def lview_update(game, ui): global turret_ranges, minion_last_hit, attack_range, skillshots player = game.player if attack_range and game.is_point_on_screen(player.pos): draw_atk_range(game, player) if turret_ranges: draw_turret_ranges(game, player) if minion_last_hit: draw_minion_last_hit(game, player) if skillshots: draw_skillshots(game, player) ================================================ FILE: GameplayScripts/execution_notifier.py ================================================ from lview import * import commons.damage_calculator as damage_calculator lview_script_info = { "script": "Execution notifier", "author": "orkido", "description": "Shows message if a enemy champion can be executed with an ability" } def lview_load_cfg(cfg): pass def lview_save_cfg(cfg): pass def lview_draw_settings(game, ui): pass def lview_update(game, ui): damage_spec = damage_calculator.get_damage_specification(game.player) if damage_spec is None: # Current champion is not supported return for champ in game.champs: if champ.is_enemy_to(game.player): dmg = damage_spec.calculate_damage(game.player, champ) if champ.health <= dmg: game.draw_circle_filled(game.world_to_screen(champ.pos), 100.0, 100, Color.RED) ================================================ FILE: GameplayScripts/map_awareness.py ================================================ from lview import * lview_script_info = { "script": "Map Awareness", "author": "leryss", "description": "Cheat that improves your map awareness." } bound_max = 0 show_alert_enemy_close = False show_last_enemy_pos = False show_last_enemy_pos_minimap = False def lview_load_cfg(cfg): global bound_max, show_alert_enemy_close, show_last_enemy_pos, show_last_enemy_pos_minimap show_alert_enemy_close = cfg.get_bool("show_alert_enemy_close", True) show_last_enemy_pos = cfg.get_bool("show_last_enemy_pos", True) show_last_enemy_pos_minimap = cfg.get_bool("show_last_enemy_pos_minimap", True) bound_max = cfg.get_float("bound_max", 4000) def lview_save_cfg(cfg): global bound_max, show_alert_enemy_close, show_last_enemy_pos, show_last_enemy_pos_minimap cfg.set_float("bound_max", bound_max) cfg.set_bool("show_alert_enemy_close", show_alert_enemy_close) cfg.set_bool("show_last_enemy_pos", show_last_enemy_pos) cfg.set_bool("show_last_enemy_pos_minimap", show_last_enemy_pos_minimap) def lview_draw_settings(game, ui): global bound_max, show_alert_enemy_close, show_last_enemy_pos, show_last_enemy_pos_minimap show_last_enemy_pos = ui.checkbox("Show last position of champions", show_last_enemy_pos) show_last_enemy_pos_minimap = ui.checkbox("Show last position of champions on minimap", show_last_enemy_pos_minimap) ui.separator() show_alert_enemy_close = ui.checkbox("Show champions that are getting close", show_alert_enemy_close) bound_max = ui.dragfloat("Alert when distance less than", bound_max, 100.0, 500.0, 10000.0) def draw_champ_world_icon(game, champ, pos, size, draw_distance = False, draw_hp_bar = False, draw_invisible_duration = False): size_hp_bar = size/10.0 percent_hp = champ.health/champ.max_health # Draw champ icon pos.x -= size/2.0 pos.y -= size/2.0 game.draw_image(champ.name.lower() + "_square", pos, pos.add(Vec2(size, size)), Color.WHITE if champ.is_visible else Color.GRAY, 100.0) # Draw hp bar if draw_hp_bar: pos.y += size game.draw_rect_filled(Vec4(pos.x, pos.y, pos.x + size, pos.y + size_hp_bar), Color.BLACK) game.draw_rect_filled(Vec4(pos.x + 1, pos.y + 1, pos.x + 1 + (size - 1)*percent_hp, pos.y + size_hp_bar - 1), Color.GREEN) # Draw distance if draw_distance: pos.x += size_hp_bar pos.y += size_hp_bar game.draw_text(pos, '{:.0f}m'.format(game.distance(champ, game.player)), Color.WHITE) if not champ.is_visible and draw_invisible_duration: pos.x += 2*size_hp_bar pos.y += size_hp_bar game.draw_text(pos, '{:.0f}'.format(game.time - champ.last_visible_at), Color.WHITE) def show_alert(game, champ): if game.is_point_on_screen(champ.pos) or not champ.is_alive or not champ.is_visible or champ.is_ally_to(game.player): return dist = champ.pos.distance(game.player.pos) if dist > bound_max: return pos = game.world_to_screen(champ.pos.sub(game.player.pos).normalize().scale(500).add(game.player.pos)) draw_champ_world_icon(game, champ, pos, 48.0, True, True, False) def show_last_pos_world(game, champ): if champ.is_visible or not champ.is_alive or not game.is_point_on_screen(champ.pos): return draw_champ_world_icon(game, champ, game.world_to_screen(champ.pos), 48.0, False, True, True) def show_last_pos_minimap(game, champ): if champ.is_visible or not champ.is_alive: return draw_champ_world_icon(game, champ, game.world_to_minimap(champ.pos), 24.0, False, False, False) def lview_update(game, ui): global bound_max, show_alert_enemy_close, show_last_enemy_pos, show_last_enemy_pos_minimap for champ in game.champs: if show_alert_enemy_close: show_alert(game, champ) if show_last_enemy_pos: show_last_pos_world(game, champ) if show_last_enemy_pos_minimap: show_last_pos_minimap(game, champ) ================================================ FILE: GameplayScripts/object_viewer.py ================================================ from lview import * from pprint import pprint lview_script_info = { "script": "Object Explorer", "author": "leryss", "description": "This is not a cheat. This just provides a way to explore ingame objects" } def draw_spell(spell, ui): if ui.treenode(str(spell.slot)): ui.labeltext("name", spell.name) ui.labeltext("summmoner_spell_type", str(spell.summoner_spell_type)) ui.dragint("level", spell.level) ui.dragfloat("ready_at", spell.ready_at) ui.dragfloat("value", spell.value) ui.separator() ui.dragfloat("speed", spell.speed) ui.dragfloat("cast_range", spell.cast_range) ui.dragfloat("width", spell.width) ui.dragfloat("cast_radius", spell.cast_radius) ui.dragfloat("height", spell.height) ui.dragfloat("delay", spell.delay) ui.treepop() def draw_items(items, ui): for item in items: if ui.treenode(str(item.id)): ui.dragint("slot", item.slot) if item.movement_speed > 0: ui.dragfloat("movement_speed", item.movement_speed) if item.health > 0: ui.dragfloat("health", item.health) if item.crit > 0: ui.dragfloat("crit", item.crit) if item.ability_power > 0: ui.dragfloat("ability_power", item.ability_power) if item.mana > 0: ui.dragfloat("mana", item.mana) if item.armour > 0: ui.dragfloat("armour", item.armour) if item.magic_resist > 0: ui.dragfloat("magic_resist", item.magic_resist) if item.physical_damage > 0: ui.dragfloat("physical_damage", item.physical_damage) if item.attack_speed > 0: ui.dragfloat("attack_speed", item.attack_speed) if item.life_steal > 0: ui.dragfloat("life_steal", item.life_steal) if item.hp_regen > 0: ui.dragfloat("hp_regen", item.hp_regen) if item.movement_speed_percent > 0: ui.dragfloat("movement_speed_percent", item.movement_speed_percent) ui.treepop() def draw_missile(obj, ui): if ui.treenode("{}_({}->{}) ({})".format(obj.name, obj.src_id, obj.dest_id, hex(obj.address))): ui.dragint("id", obj.id) ui.labeltext("net_id", hex(obj.net_id)) ui.dragint("team", obj.team) ui.labeltext("start_pos", f"x={obj.start_pos.x:.2f}, y={obj.start_pos.y:.2f}, z={obj.start_pos.z:.2f}") ui.labeltext("end_pos", f"x={obj.end_pos.x:.2f}, y={obj.end_pos.y:.2f}, z={obj.end_pos.z:.2f}") ui.labeltext("pos", f"x={obj.pos.x:.2f}, y={obj.pos.y:.2f}, z={obj.pos.z:.2f}") ui.dragint("src_id", obj.src_id) ui.dragint("dest_id", obj.dest_id) ui.separator() ui.dragfloat("speed", obj.speed) ui.dragfloat("cast_range", obj.cast_range) ui.dragfloat("width", obj.width) ui.dragfloat("cast_radius", obj.cast_radius) ui.dragfloat("height", obj.height) ui.dragfloat("delay", obj.delay) ui.treepop() def draw_game_object(obj, ui, additional_draw = None, set_open=False): if(obj == None): ui.text("null", Color.RED) return if(set_open): ui.opennext() if ui.treenode("{}_{} ({})".format(obj.name, obj.id, hex(obj.address))): ui.labeltext("address", hex(obj.address)) ui.labeltext("net_id", hex(obj.net_id)) ui.labeltext("name", obj.name, Color.ORANGE) ui.labeltext("pos", f"x={obj.pos.x:.2f}, y={obj.pos.y:.2f}, z={obj.pos.z:.2f}") ui.dragint("id", obj.id) ui.separator() ui.dragfloat("health", obj.health) ui.checkbox("is_alive", obj.is_alive) ui.separator() ui.dragfloat("base_atk", obj.base_atk) ui.dragfloat("bonus_atk", obj.bonus_atk) ui.dragfloat("armour", obj.armour) ui.dragfloat("magic_resist", obj.magic_resist) ui.dragfloat("ap", obj.ap) ui.dragfloat("crit", obj.crit) ui.dragfloat("crit_multi", obj.crit_multi) ui.separator() ui.dragfloat("atk_range", obj.atk_range) ui.dragfloat("base_atk_range", obj.base_atk_range) ui.dragfloat("base_atk_speed", obj.base_atk_speed) ui.dragfloat("atk_speed_multi", obj.atk_speed_multi) ui.dragfloat("atk_speed_ratio", obj.atk_speed_ratio) ui.dragfloat("basic_missile_speed", obj.basic_missile_speed) ui.dragfloat("base_ms", obj.base_ms) ui.dragfloat("movement_speed", obj.movement_speed) ui.separator() ui.dragfloat("selection_radius", obj.selection_radius) ui.dragfloat("gameplay_radius", obj.gameplay_radius) ui.dragfloat("pathing_radius", obj.pathing_radius) ui.dragfloat("acquisition_radius", obj.acquisition_radius) ui.separator() ui.dragfloat("duration", obj.duration) ui.dragfloat("last_visible_at", obj.last_visible_at) ui.checkbox("is_visible", obj.is_visible) if additional_draw != None: additional_draw() ui.treepop() def draw_champion(obj, ui): def draw_spells(): ui.dragint("Level", obj.lvl) ui.text("Items") draw_items(obj.items, ui) ui.text("Skills") draw_spell(obj.Q, ui) draw_spell(obj.W, ui) draw_spell(obj.E, ui) draw_spell(obj.R, ui) draw_spell(obj.D, ui) draw_spell(obj.F, ui) draw_game_object(obj, ui, additional_draw = draw_spells) def draw_list(label, objs, ui, draw_func): if ui.treenode(label): for obj in objs: draw_func(obj, ui) ui.treepop() def lview_load_cfg(cfg): pass def lview_save_cfg(cfg): pass def lview_draw_settings(objs, ui): pass def lview_update(game, ui): ui.begin("Object Viewer") ui.dragfloat("time", game.time) if game.hovered_obj: ui.labeltext("hovered_obj", f"{game.hovered_obj.name} ({hex(game.hovered_obj.address)})") else: ui.labeltext("hovered_obj", "none") ui.text("Local Champion") draw_champion(game.player, ui) ui.text("Lists") draw_list("Champions", game.champs, ui, draw_champion) draw_list("Minions", game.minions, ui, draw_game_object) draw_list("Jungle", game.jungle, ui, draw_game_object) draw_list("Turrets", game.turrets, ui, draw_game_object) draw_list("Missiles", game.missiles, ui, draw_missile) draw_list("Others", game.others, ui, draw_game_object) ui.end() ================================================ FILE: GameplayScripts/orb_walker.py ================================================ from lview import * from commons import skills from commons.targeting import TargetingConfig import time, json lview_script_info = { "script": "Orbwalker", "author": "leryss", "description": "Automatically kites enemies. Also has last hit built in" } last_attacked = 0 last_moved = 0 key_attack_move = 0 key_orbwalk = 0 auto_last_hit = False max_atk_speed = 0 toggle_mode = False toggled = False targeting = TargetingConfig() def lview_load_cfg(cfg): global key_attack_move, key_orbwalk, max_atk_speed, auto_last_hit, toggle_mode global targeting key_attack_move = cfg.get_int("key_attack_move", 0) key_orbwalk = cfg.get_int("key_orbwalk", 0) max_atk_speed = cfg.get_float("max_atk_speed", 2.0) auto_last_hit = cfg.get_bool("auto_last_hit", True) toggle_mode = cfg.get_bool("toggle_mode", False) targeting.load_from_cfg(cfg) def lview_save_cfg(cfg): global key_attack_move, key_orbwalk, max_atk_speed, auto_last_hit, toggle_mode global targeting cfg.set_int("key_attack_move", key_attack_move) cfg.set_int("key_orbwalk", key_orbwalk) cfg.set_float("max_atk_speed", max_atk_speed) cfg.set_bool("auto_last_hit", auto_last_hit) cfg.set_bool("toggle_mode", toggle_mode) targeting.save_to_cfg(cfg) def lview_draw_settings(game, ui): global key_attack_move, key_orbwalk, max_atk_speed, auto_last_hit, toggle_mode global targeting champ_name = game.player.name max_atk_speed = ui.sliderfloat("Max attack speed", max_atk_speed, 1.5, 3.0) key_attack_move = ui.keyselect("Attack move key", key_attack_move) key_orbwalk = ui.keyselect("Orbwalk activate key", key_orbwalk) auto_last_hit = ui.checkbox("Last hit minions when no targets", auto_last_hit) toggle_mode = ui.checkbox("Toggle mode", toggle_mode) targeting.draw(ui) def find_minion_target(game): atk_range = game.player.base_atk_range + game.player.gameplay_radius min_health = 9999999999 target = None for minion in game.minions: if minion.is_enemy_to(game.player) and minion.is_alive and minion.health < min_health and game.distance(game.player, minion) < atk_range and skills.is_last_hitable(game, game.player, minion): target = minion min_health = minion.health return target def get_target(game): global auto_last_hit target = targeting.get_target(game, game.player.base_atk_range + game.player.gameplay_radius) if not target and auto_last_hit: return find_minion_target(game) return target def lview_update(game, ui): global last_attacked, alternate, last_moved global key_attack_move, key_orbwalk, max_atk_speed global toggle_mode, toggled if toggle_mode: if game.was_key_pressed(key_orbwalk): toggled = not toggled if not toggled: return elif not game.is_key_down(key_orbwalk): return game.draw_button(game.world_to_screen(game.player.pos), "OrbWalking", Color.BLACK, Color.WHITE) # Handle basic attacks self = game.player atk_speed = self.base_atk_speed * self.atk_speed_multi b_windup_time = (1.0/self.base_atk_speed)*game.player.basic_atk_windup c_atk_time = 1.0/atk_speed max_atk_time = 1.0/max_atk_speed target = get_target(game) t = time.time() if t - last_attacked > max(c_atk_time, max_atk_time) and target: last_attacked = t game.press_key(key_attack_move) game.click_at(True, game.world_to_screen(target.pos)) else: dt = t - last_attacked if dt > b_windup_time and t - last_moved > 0.15: last_moved = t game.press_right_click() ================================================ FILE: GameplayScripts/spell_tracker.py ================================================ from lview import * show_local_champ = False show_allies = False show_enemies = False lview_script_info = { "script": "Spell Tracker", "author": "leryss", "description": "Tracks spell cooldowns and levels" } def get_color_for_cooldown(cooldown): if cooldown > 0.0: return Color.DARK_RED else: return Color(1, 1, 1, 1) def draw_spell(game, spell, pos, size, show_lvl = True, show_cd = True): cooldown = spell.get_current_cooldown(game.time) color = get_color_for_cooldown(cooldown) if spell.level > 0 else Color.GRAY game.draw_image(spell.icon, pos, pos.add(Vec2(size, size)), color, 10.0) if show_cd and cooldown > 0.0: game.draw_text(pos.add(Vec2(4, 5)), str(int(cooldown)), Color.WHITE) if show_lvl: for i in range(spell.level): offset = i*4 game.draw_rect_filled(Vec4(pos.x + offset, pos.y + 24, pos.x + offset + 3, pos.y + 26), Color.YELLOW) def draw_overlay_on_champ(game, champ): p = game.hp_bar_pos(champ) p.x -= 70 if not game.is_point_on_screen(p): return p.x += 25 draw_spell(game, champ.Q, p, 24) p.x += 25 draw_spell(game, champ.W, p, 24) p.x += 25 draw_spell(game, champ.E, p, 24) p.x += 25 draw_spell(game, champ.R, p, 24) p.x += 37 p.y -= 32 draw_spell(game, champ.D, p, 15, False, False) p.y += 16 draw_spell(game, champ.F, p, 15, False, False) def lview_update(game, ui): global show_allies, show_enemies, show_local_champ for champ in game.champs: if not champ.is_visible or not champ.is_alive: continue if champ == game.player and show_local_champ: draw_overlay_on_champ(game, champ) elif champ != game.player: if champ.is_ally_to(game.player) and show_allies: draw_overlay_on_champ(game, champ) elif champ.is_enemy_to(game.player) and show_enemies: draw_overlay_on_champ(game, champ) def lview_load_cfg(cfg): global show_allies, show_enemies, show_local_champ show_allies = cfg.get_bool("show_allies", False) show_enemies = cfg.get_bool("show_enemies", True) show_local_champ = cfg.get_bool("show_local_champ", False) def lview_save_cfg(cfg): global show_allies, show_enemies, show_local_champ cfg.set_bool("show_allies", show_allies) cfg.set_bool("show_enemies", show_enemies) cfg.set_bool("show_local_champ", show_local_champ) def lview_draw_settings(game, ui): global show_allies, show_enemies, show_local_champ show_allies = ui.checkbox("Show overlay on allies", show_allies) show_enemies = ui.checkbox("Show overlay on enemies", show_enemies) show_local_champ = ui.checkbox("Show overlay on self", show_local_champ) ================================================ FILE: GameplayScripts/tf_card_picker.py ================================================ from lview import * lview_script_info = { "script": "Twisted Fate Card Picker", "author": "leryss", "description": "Picks specific cards for twisted fate", "target_champ": "twistedfate" } key_blue, key_red, key_yellow = 0, 0, 0 card_to_lock = None key_w = 17 def lview_load_cfg(cfg): global key_blue, key_red, key_yellow key_blue = cfg.get_int("key_blue", 0) key_red = cfg.get_int("key_red", 0) key_yellow = cfg.get_int("key_yellow", 0) def lview_save_cfg(cfg): global key_blue, key_red, key_yellow cfg.set_int("key_blue", key_blue) cfg.set_int("key_red", key_red) cfg.set_int("key_yellow", key_yellow) def lview_draw_settings(game, ui): global key_blue, key_red, key_yellow key_blue = ui.keyselect("Key blue card", key_blue) key_red = ui.keyselect("Key red card", key_red) key_yellow = ui.keyselect("Key yellow card", key_yellow) def lview_update(game, ui): global key_blue, key_red, key_yellow, key_w global card_to_lock if card_to_lock is not None: if card_to_lock == game.player.W.name: game.press_key(key_w) card_to_lock = None elif game.player.W.name == 'pickacard' and game.player.W.get_current_cooldown(game.time) == 0.0: key_to_press = None if game.was_key_pressed(key_blue): card_to_lock = "bluecardlock" key_to_press = key_blue elif game.was_key_pressed(key_red): card_to_lock = "redcardlock" key_to_press = key_red elif game.was_key_pressed(key_yellow): card_to_lock = "goldcardlock" key_to_press = key_yellow if key_to_press: game.press_key(key_w) ================================================ FILE: GameplayScripts/util_make_heightmap.py____ ================================================ from lview import * import json, time, os from pprint import pformat lview_script_info = { "script": "Util Make Height Map", "author": "", "description": "" } def lview_load_cfg(cfg): pass def lview_save_cfg(cfg): pass def lview_draw_settings(game, ui): global enable_draw if ui.button("Extrapolate"): extrapolate() enable_draw = ui.checkbox("Draw map", enable_draw) enable_draw = False size = 512 m = [[0 for i in range(size)] for i in range(size)] file_name = "" time_last_save = 0 first_iter = True def get_neighbours(m, i, j): neighbours = [] if m[i - 1][j - 1] != 0: neighbours.append(m[i - 1][j - 1]) if m[i - 1][j] != 0: neighbours.append(m[i - 1][j]) if m[i - 1][j + 1] != 0: neighbours.append(m[i - 1][j + 1]) if m[i][j - 1] != 0: neighbours.append(m[i][j - 1]) if m[i][j + 1] != 0: neighbours.append(m[i][j + 1]) if m[i + 1][j - 1] != 0: neighbours.append(m[i + 1][j - 1]) if m[i + 1][j] != 0: neighbours.append(m[i + 1][j]) if m[i + 1][j + 1] != 0: neighbours.append(m[i + 1][j + 1]) return neighbours def extrapolate(): global m, size to_modify = [] for i in range(1, size - 1): for j in range(1, size - 1): if m[i][j] != 0: continue neighbours = get_neighbours(m, i, j) if len(neighbours) > 0: to_modify.append((i, j, sum(neighbours)/len(neighbours))) print(f'Extrapolated {len(to_modify)} points') for (i, j, h) in to_modify: m[i][j] = h def save(s): global m with open(s, 'w') as f: f.write(json.dumps(m)) def load(s): global m if os.path.exists(s): with open(s, 'r') as f: m = json.loads(f.read()) def draw(game): global m, size c = game.player.pos.clone() c.scale(size/15000) window = 50 cx = int(c.x) cz = int(c.z) startx = 0 if cx - window < 0 else cx - window endx = size if cx + window > size else cx + window startz = 0 if cz - window < 0 else cz - window endz = size if cz + window > size else cz + window for i in range(startx, endx): for j in range(startz, endz): color = Color(0, 0, 0, 0) if m[i][j] != 0: color = Color(0, (m[i][j] + 300)/400, 0, 0.8) p = Vec3(i/size*15000, 0, j/size*15000) p2 = Vec3(i/size*15000, 100 + m[i][j], j/size*15000) #game.draw_line(game.world_to_screen(p), game.world_to_screen(p2), 2, color) #game.draw_circle_world_filled(p2, 10, 5, color) game.draw_text(game.world_to_screen(p), f'{m[i][j]:.0f}', Color.GREEN) last_launched_t = 0 last_moved_t = 0 def lview_update(game, ui): global m, size, enable_draw, time_last_save, first_iter global file_name global last_launched_t, last_moved_t if first_iter: first_iter = False file_name = "HeightMap_" + str(game.map.type) + ".json" load(file_name) if game.is_key_down(2): if time.time() - last_launched_t > 0.01: game.player.R.trigger() last_launched_t = time.time() p = game.player.pos.clone() p.scale(size/15000) #game.draw_button(game.world_to_screen(game.player.pos), f'{abs(game.player.pos.y - m[int(p.x)][int(p.z)])}', Color.WHITE, Color.BLACK) game.draw_button(game.world_to_screen(game.player.pos), f'{abs(game.player.pos.y - game.map.height_at(game.player.pos.x, game.player.pos.z))}', Color.WHITE, Color.BLACK) ''' for champ in game.champs: p = champ.pos.clone() p.scale(size/15000) if m[int(p.x)][int(p.z)] == 0: m[int(p.x)][int(p.z)] = champ.pos.y else: m[int(p.x)][int(p.z)] = min(champ.pos.y, m[int(p.x)][int(p.z)]) ''' for missile in game.missiles: if missile.dest_id != 0: continue p = missile.pos.clone() p.scale(size/15000) px, pz = int(p.x), int(p.z) if px < size and px > 0 and pz < size and pz > 0: if m[px][pz] == 0: m[px][pz] = missile.pos.y - 100 else: m[px][pz] = min(missile.pos.y - 100, m[px][pz]) if time.time() - time_last_save > 10: save(file_name) time_last_save = time.time() if enable_draw: draw(game) ================================================ FILE: GameplayScripts/vision_tracker.py ================================================ from lview import * import json lview_script_info = { "script": "Vision Tracker", "author": "leryss", "description": "Tracks enemy invisible objects and clones" } show_clones, show_wards, show_traps = None, None, None traps = { #Name -> (radius, show_radius_circle, show_radius_circle_minimap, icon) 'caitlyntrap' : [50, True, False, "caitlyn_yordlesnaptrap"], 'jhintrap' : [140, True, False, "jhin_e"], 'jinxmine' : [50, True, False, "jinx_e"], 'maokaisproutling' : [50, False, False, "maokai_e"], 'nidaleespear' : [50, True, False, "nidalee_w1"], 'shacobox' : [300, True, False, "jester_deathward"], 'teemomushroom' : [75, True, True, "teemo_r"] } wards = { 'bluetrinket' : [900, True, True, "bluetrinket"], 'jammerdevice' : [900, True, True, "pinkward"], 'perkszombieward' : [900, True, True, "bluetrinket"], 'sightward' : [900, True, True, "sightward"], 'visionward' : [900, True, True, "sightward"], 'yellowtrinket' : [900, True, True, "yellowtrinket"], 'yellowtrinketupgrade' : [900, True, True, "yellowtrinket"], 'ward' : [900, True, True, "sightward"], } clones = { 'shaco' : [0, False, False, "shaco_square"], 'leblanc' : [0, False, False, "leblanc_square"], 'monkeyking' : [0, False, False, "monkeyking_square"], 'neeko' : [0, False, False, "neeko_square"], 'fiddlesticks' : [0, False, False, "fiddlesticks_square"], } def lview_load_cfg(cfg): global show_clones, show_wards, show_traps, traps, wards show_clones = cfg.get_bool("show_clones", True) show_wards = cfg.get_bool("show_wards", True) show_traps = cfg.get_bool("show_traps", True) traps = json.loads(cfg.get_str("traps", json.dumps(traps))) wards = json.loads(cfg.get_str("wards", json.dumps(wards))) def lview_save_cfg(cfg): global show_clones, show_wards, show_traps, traps, wards cfg.set_bool("show_clones", show_clones) cfg.set_bool("show_wards", show_wards) cfg.set_bool("show_traps", show_traps) cfg.set_str("traps", json.dumps(traps)) cfg.set_str("wards", json.dumps(wards)) def lview_draw_settings(game, ui): global traps, wards global show_clones, show_wards, show_traps show_clones = ui.checkbox("Show clones", show_clones) show_wards = ui.checkbox("Show wards", show_wards) show_traps = ui.checkbox("Show clones", show_traps) ui.text("Traps") for x in traps.keys(): if ui.treenode(x): traps[x][1] = ui.checkbox("Show range circles", traps[x][1]) traps[x][2] = ui.checkbox("Show on minimap", traps[x][2]) ui.treepop() ui.text("Wards") for x in wards.keys(): if ui.treenode(x): wards[x][1] = ui.checkbox("Show range circles", wards[x][1]) wards[x][2] = ui.checkbox("Show on minimap", wards[x][2]) ui.treepop() def draw(game, obj, radius, show_circle_world, show_circle_map, icon): sp = game.world_to_screen(obj.pos) if game.is_point_on_screen(sp): duration = obj.duration + obj.last_visible_at - game.time if duration > 0: game.draw_text(sp.add(Vec2(5, 30)), f'{duration:.0f}', Color.WHITE) game.draw_image(icon, sp, sp.add(Vec2(30, 30)), Color.WHITE, 10) if show_circle_world: game.draw_circle_world(obj.pos, radius, 30, 3, Color.RED) if show_circle_map: p = game.world_to_minimap(obj.pos) game.draw_circle(game.world_to_minimap(obj.pos), game.distance_to_minimap(radius), 15, 2, Color.RED) def lview_update(game, ui): global show_clones, show_wards, show_traps global traps, wards, clones for obj in game.others: if obj.is_ally_to(game.player) or not obj.is_alive: continue if show_wards and obj.has_tags(UnitTag.Unit_Ward) and obj.name in wards: draw(game, obj, *(wards[obj.name])) elif show_traps and obj.has_tags(UnitTag.Unit_Special_Trap) and obj.name in traps: draw(game, obj, *(traps[obj.name])) if show_clones: for champ in game.champs: if champ.is_ally_to(game.player) or not champ.is_alive: continue if champ.name in clones and champ.R.name == champ.D.name: draw(game, champ, *(clones[champ.name])) ================================================ FILE: LView/AntiCrack.cpp ================================================ #include "AntiCrack.h" #include "Windows.h" #include #include #include std::string exec(const char* cmd) { std::array buffer; std::string result; std::unique_ptr pipe(_popen(cmd, "r"), _pclose); if (!pipe) { throw std::runtime_error("popen() failed!"); } while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { result += buffer.data(); } return result; } std::string HashHardwareComponents(std::string components) { std::stringstream in(components); std::stringstream out; std::string buff; std::hash hasher; while (std::getline(in, buff, '\n')) { size_t hash = hasher(buff); out << std::hex << hash; } return out.str(); } std::string AntiCrack::GetHardwareID() { std::string hwComponents = exec( "wmic PATH Win32_VideoController GET PNPDeviceID | more +1 | findstr /R \"[^\\n]\" &" "wmic PATH Win32_PhysicalMemory GET SerialNumber | more +1 | findstr /R \"[^\\n]\" &" "wmic PATH Win32_LogicalDisk GET VolumeSerialNumber | more +1 | findstr /R \"[^\\n]\" &" "wmic PATH Win32_Processor GET ProcessorId | more +1 | findstr /R \"[^\\n]\" &" "wmic PATH win32_computersystem GET name | more +1 | findstr /R \"[^\\n]\""); return HashHardwareComponents(hwComponents); } ================================================ FILE: LView/AntiCrack.h ================================================ #pragma once #include /// Utilities to prevent people from craking the cheat in 1 hour namespace AntiCrack { std::string GetHardwareID(); }; ================================================ FILE: LView/Benchmark.h ================================================ #pragma once struct UIBenchmark { float renderTimeMs; float processTimeMs; }; struct ReadBenchmark { float readObjectsMs; float readRendererMs; }; struct ViewBenchmark { float drawSettingsMs; float drawPanelMs; float drawOverlayMs; }; ================================================ FILE: LView/ConfigSet.cpp ================================================ #include "ConfigSet.h" #include ConfigSet* ConfigSet::instance = nullptr; void ConfigSet::LoadFromFile() { std::string line; size_t delimiterIdx; std::ifstream file("config.ini"); if (file.is_open()) { while (std::getline(file, line)) { delimiterIdx = line.find("="); if (delimiterIdx == std::string::npos) throw std::runtime_error(std::string("Config file line does not contain delimiter `=`: ").append(line)); rawValues[line.substr(0, delimiterIdx)] = line.substr(delimiterIdx + 1, line.length()); } file.close(); } } void ConfigSet::SetPrefixKey(std::string prefix) { prefixKey = prefix; } std::string ConfigSet::GetPrefixKey() { return prefixKey; } void ConfigSet::SaveToFile() { std::ofstream file("config.ini"); if (!file.is_open()) throw std::runtime_error("Couldn't open file to save config set"); for (auto it = rawValues.begin(); it != rawValues.end(); ++it) { file << it->first << "=" << it->second << "\n"; } file.close(); } int ConfigSet::GetInt(const char* key, int defaultVal) { auto it = rawValues.find(prefixKey + "::" + key); if (it == rawValues.end()) return defaultVal; std::string& val = it->second; if (val.substr(0, 2).compare("0x") == 0) return std::stoi(val, nullptr, 16); return std::stoi(val); } float ConfigSet::GetFloat(const char* key, float defaultVal) { auto it = rawValues.find(prefixKey + "::" + key); if (it == rawValues.end()) return defaultVal; std::string& val = it->second; return std::stof(val); } bool ConfigSet::GetBool(const char* key, bool defaultVal) { auto it = rawValues.find(prefixKey + "::" + key); if (it == rawValues.end()) return defaultVal; std::string& val = it->second; return std::stod(val); } std::string ConfigSet::GetStr(const char* key, const char* defaultVal) { auto it = rawValues.find(prefixKey + "::" + key); if (it == rawValues.end()) return defaultVal; return it->second; } void ConfigSet::SetInt(const char* key, int value) { rawValues[(prefixKey + "::" + key)] = std::to_string(value); } void ConfigSet::SetFloat(const char* key, float value) { rawValues[(prefixKey + "::" + key)] = std::to_string(value); } void ConfigSet::SetBool(const char* key, bool value) { rawValues[(prefixKey + "::" + key)] = std::to_string(value); } void ConfigSet::SetStr(const char* key, const char* value) { rawValues[(prefixKey + "::" + key)] = value; } ================================================ FILE: LView/ConfigSet.h ================================================ #pragma once #include #include /// Class used to save and load configs class ConfigSet { public: /// Only made public for C++ to python bindings. Use ConfigSet::Get() to retrieve the singleton instance ConfigSet() {}; int GetInt(const char* key, int defaultVal); bool GetBool(const char* key, bool defaultVal); float GetFloat(const char* key, float defaultVal); std::string GetStr(const char*, const char* defaultVal); void SetInt(const char*, int val); void SetBool(const char*, bool val); void SetFloat(const char*, float val); void SetStr(const char*, const char* val); void LoadFromFile(); void SaveToFile(); /// Sets a prefix to all the keys provided in all the Get/Set calls. void SetPrefixKey(std::string prefixKey); std::string GetPrefixKey(); /// Gets singleton instance static ConfigSet* Get() { if (instance == nullptr) { instance = new ConfigSet(); instance->LoadFromFile(); } return instance; } private: static ConfigSet* instance; std::string prefixKey; std::map rawValues; }; ================================================ FILE: LView/GameData.cpp ================================================ #include "GameData.h" #include #include #include #include "Utils.h" #include "Overlay.h" using namespace std; UnitInfo* GameData::UnknownUnit = new UnitInfo(); SpellInfo* GameData::UnknownSpell = new SpellInfo(); ItemInfo* GameData::UnknownItem = new ItemInfo(); std::map GameData::Units = {}; std::map GameData::Spells = {}; std::map GameData::Images = {}; std::map GameData::Items = {}; void GameData::Load(std::string& dataFolder) { std::string unitData = dataFolder + "/UnitData.json"; std::string spellData = dataFolder + "/SpellData.json"; std::string spellDataCustom = dataFolder + "/SpellDataCustom.json"; std::string itemData = dataFolder + "/ItemData.json"; std::string spellIcons = dataFolder + "/icons_spells"; std::string champIcons = dataFolder + "/icons_champs"; std::string extraIcons = dataFolder + "/icons_extra"; printf("\r Loading item data \n"); LoadItemData(itemData); printf("\r Loading unit data \n"); LoadUnitData(unitData); printf("\r Loading spell data \n"); LoadSpellData(spellData); LoadSpellData(spellDataCustom); printf("\r Loading images \n"); LoadIcons(spellIcons); LoadIcons(champIcons); LoadIcons(extraIcons); printf("\r Loading complete \n"); } UnitInfo * GameData::GetUnitInfoByName(std::string& name) { auto it = Units.find(name); if (it != Units.end()) return it->second; return UnknownUnit; } SpellInfo * GameData::GetSpellInfoByName(std::string& name) { auto it = Spells.find(name); if (it != Spells.end()) return it->second; return UnknownSpell; } ItemInfo * GameData::GetItemInfoById(int id) { auto it = Items.find(id); if (it != Items.end()) return it->second; return UnknownItem; } boost::json::value parse_json_file(std::string& path) { std::ifstream inputData; inputData.open(path); if (!inputData.is_open()) throw std::runtime_error("Can't open unit data file"); boost::json::stream_parser p; boost::json::error_code ec; do { char buf[4096]; inputData.read(buf, sizeof(buf)); p.write(buf, inputData.gcount(), ec); } while (!inputData.eof()); if (ec) throw std::runtime_error("Failed to parse JSON file"); p.finish(ec); if (ec) throw std::runtime_error("Failed to parse JSON file"); boost::json::value jv = p.release(); return jv; } double json_to_double(boost::json::value val) { if (val.is_int64()) return val.as_int64(); else return val.as_double(); } void GameData::LoadUnitData(std::string& path) { boost::json::value jv = parse_json_file(path); auto& units = jv.get_array(); for (auto& unit : units) { auto& unitObj = unit.get_object(); UnitInfo* unit = new UnitInfo(); unit->acquisitionRange = (float)json_to_double(unitObj["acquisitionRange"]); unit->attackSpeedRatio = (float)json_to_double(unitObj["attackSpeedRatio"]); unit->baseAttackRange = (float)json_to_double(unitObj["attackRange"]); unit->baseAttackSpeed = (float)json_to_double(unitObj["attackSpeed"]); unit->baseMovementSpeed = (float)json_to_double(unitObj["baseMoveSpeed"]); unit->basicAttackMissileSpeed = (float)json_to_double(unitObj["basicAtkMissileSpeed"]); unit->basicAttackWindup = (float)json_to_double(unitObj["basicAtkWindup"]); unit->gameplayRadius = (float)json_to_double(unitObj["gameplayRadius"]); unit->healthBarHeight = (float)json_to_double(unitObj["healthBarHeight"]); unit->name = Character::ToLower(std::string(unitObj["name"].as_string().c_str())); unit->pathRadius = (float)json_to_double(unitObj["pathingRadius"]); unit->selectionRadius = (float)json_to_double(unitObj["selectionRadius"]); auto& tags = unitObj["tags"].as_array(); for (auto& tag : tags) unit->SetTag(tag.as_string().c_str()); Units[unit->name] = unit; } } void GameData::LoadSpellData(std::string& path) { boost::json::value jv = parse_json_file(path); auto& spells = jv.as_array(); for (auto& spell : spells) { auto& spellObj = spell.as_object(); SpellInfo* info = new SpellInfo(); info->flags = (SpellFlags)spellObj["flags"].as_int64(); info->delay = (float)json_to_double(spellObj["delay"]); info->height = (float)json_to_double(spellObj["height"]); info->icon = Character::ToLower(std::string(spellObj["icon"].as_string().c_str())); info->name = Character::ToLower(std::string(spellObj["name"].as_string().c_str())); info->width = (float)json_to_double(spellObj["width"]); info->castRange = (float)json_to_double(spellObj["castRange"]); info->castRadius = (float)json_to_double(spellObj["castRadius"]); info->speed = (float)json_to_double(spellObj["speed"]); info->travelTime = (float)json_to_double(spellObj["travelTime"]); info->flags = (SpellFlags) (info->flags | (spellObj["projectDestination"].as_bool() ? ProjectedDestination : 0)); Spells[info->name] = info; } } void GameData::LoadIcons(std::string& path) { std::string folder(path); WIN32_FIND_DATAA findData; HANDLE hFind; int nrFiles = std::distance(filesystem::directory_iterator(path), filesystem::directory_iterator()); int nrFile = 0; hFind = FindFirstFileA((folder + "\\*.png").c_str(), &findData); do { if (hFind != INVALID_HANDLE_VALUE) { if(nrFile % 100 == 0) printf("\r Loading %d/%d ", nrFile, nrFiles); std::string filePath = folder + "/" + findData.cFileName; Texture2D* image = Texture2D::LoadFromFile(Overlay::GetDxDevice(), filePath); if (image == nullptr) printf("Failed to load: %s\n", filePath.c_str()); else { std::string fileName(findData.cFileName); fileName.erase(fileName.find(".png"), 4); Images[Character::ToLower(fileName)] = image; } } nrFile++; } while (FindNextFileA(hFind, &findData)); } void GameData::LoadItemData(std::string & path) { boost::json::value jv = parse_json_file(path); auto& items = jv.as_array(); for (auto& itemObj : items) { auto& item = itemObj.as_object(); ItemInfo* info = new ItemInfo(); info->movementSpeed = (float)json_to_double(item["movementSpeed"]); info->health = (float)json_to_double(item["health"]); info->crit = (float)json_to_double(item["crit"]); info->abilityPower = (float)json_to_double(item["abilityPower"]); info->mana = (float)json_to_double(item["mana"]); info->armour = (float)json_to_double(item["armour"]); info->magicResist = (float)json_to_double(item["magicResist"]); info->physicalDamage = (float)json_to_double(item["physicalDamage"]); info->attackSpeed = (float)json_to_double(item["attackSpeed"]); info->lifeSteal = (float)json_to_double(item["lifeSteal"]); info->hpRegen = (float)json_to_double(item["hpRegen"]); info->movementSpeedPercent = (float)json_to_double(item["movementSpeedPercent"]); info->cost = (float)json_to_double(item["cost"]); info->id = item["id"].as_int64(); Items[info->id] = info; } } ================================================ FILE: LView/GameData.h ================================================ #pragma once #include #include "UnitInfo.h" #include "SpellInfo.h" #include "Texture2D.h" #include "ItemInfo.h" /// Data that cant be read from memory or it is too inefficient to do so can be accessed with this class. class GameData { public: static void Load(std::string& dataFolder); static UnitInfo* GetUnitInfoByName(std::string& name); static SpellInfo* GetSpellInfoByName(std::string& name); static ItemInfo* GetItemInfoById(int id); private: static void LoadUnitData(std::string& path); static void LoadSpellData(std::string& path); static void LoadIcons(std::string& path); static void LoadItemData(std::string& path); public: static UnitInfo* UnknownUnit; static SpellInfo* UnknownSpell; static ItemInfo* UnknownItem; static std::map Units; static std::map Spells; static std::map Images; static std::map Items; }; ================================================ FILE: LView/GameObject.cpp ================================================ #include "GameObject.h" #include "Utils.h" #include "Offsets.h" #include "Spell.h" #include "GameData.h" BYTE GameObject::buff[GameObject::sizeBuff] = {}; BYTE GameObject::buffDeep[GameObject::sizeBuffDeep] = {}; bool GameObject::HasUnitTags(const UnitTag& type1) const { return unitInfo->tags.test(type1); } bool GameObject::IsEqualTo(const GameObject& other) const { return this->objectIndex == other.objectIndex; } bool GameObject::IsNotEqualTo(const GameObject& other) const { return this->objectIndex != other.objectIndex; } float GameObject::GetAcquisitionRadius() const { return unitInfo->acquisitionRange; } float GameObject::GetSelectionRadius() const { return unitInfo->selectionRadius; } float GameObject::GetPathingRadius() const { return unitInfo->pathRadius; } float GameObject::GetGameplayRadius() const { return unitInfo->gameplayRadius; } float GameObject::GetBasicAttackMissileSpeed() const { return unitInfo->basicAttackMissileSpeed; } float GameObject::GetBasicAttackWindup() const { return unitInfo->basicAttackWindup; } float GameObject::GetAttackSpeedRatio() const { return unitInfo->attackSpeedRatio; } float GameObject::GetBaseMovementSpeed() const { return unitInfo->baseMovementSpeed; } float GameObject::GetBaseAttackSpeed() const { return unitInfo->baseAttackSpeed; } float GameObject::GetBaseAttackRange() const { return unitInfo->baseAttackRange; } float GameObject::GetAttackRange() const { return GetBaseAttackRange() + GetGameplayRadius(); } float GameObject::GetHpBarHeight() const { return unitInfo->healthBarHeight; } bool GameObject::IsEnemyTo(const GameObject& other) const { return this->team != other.team; } bool GameObject::IsAllyTo(const GameObject& other) const { return this->team == other.team; } void GameObject::LoadFromMem(DWORD base, HANDLE hProcess, bool deepLoad) { address = base; Mem::Read(hProcess, base, buff, sizeBuff); // Store previous position once N milliseconds to avoid the case when position == previousPosition but the object is moving std::chrono::duration timeDuration = high_resolution_clock::now() - timeSinceLastPreviousPosition; if (timeDuration.count() > 20) { previousPosition = position.clone(); timeSinceLastPreviousPosition = high_resolution_clock::now(); } memcpy(&team, &buff[Offsets::ObjTeam], sizeof(short)); memcpy(&position, &buff[Offsets::ObjPos], sizeof(Vector3)); memcpy(&health, &buff[Offsets::ObjHealth], sizeof(float)); memcpy(&maxHealth, &buff[Offsets::ObjMaxHealth], sizeof(float)); memcpy(&baseAttack, &buff[Offsets::ObjBaseAtk], sizeof(float)); memcpy(&bonusAttack, &buff[Offsets::ObjBonusAtk], sizeof(float)); memcpy(&armour, &buff[Offsets::ObjArmor], sizeof(float)); memcpy(&magicResist, &buff[Offsets::ObjMagicRes], sizeof(float)); memcpy(&duration, &buff[Offsets::ObjExpiry], sizeof(float)); memcpy(&isVisible, &buff[Offsets::ObjVisibility], sizeof(bool)); memcpy(&objectIndex, &buff[Offsets::ObjIndex], sizeof(short)); memcpy(&crit, &buff[Offsets::ObjCrit], sizeof(float)); memcpy(&critMulti, &buff[Offsets::ObjCritMulti], sizeof(float)); memcpy(&abilityPower, &buff[Offsets::ObjAbilityPower], sizeof(float)); memcpy(&atkSpeedMulti, &buff[Offsets::ObjAtkSpeedMulti], sizeof(float)); memcpy(&movementSpeed, &buff[Offsets::ObjMoveSpeed], sizeof(float)); memcpy(&networkId, &buff[Offsets::ObjNetworkID], sizeof(DWORD)); // Check if alive DWORD spawnCount; memcpy(&spawnCount, &buff[Offsets::ObjSpawnCount], sizeof(int)); isAlive = (spawnCount % 2 == 0); if (deepLoad) { char nameBuff[50]; Mem::Read(hProcess, Mem::ReadDWORDFromBuffer(buff, Offsets::ObjName), nameBuff, 50); if (Character::ContainsOnlyASCII(nameBuff, 50)) name = Character::ToLower(std::string(nameBuff)); else name = std::string(""); unitInfo = GameData::GetUnitInfoByName(name); } // Read extension of object if (HasUnitTags(Unit_Champion)) { LoadChampionFromMem(base, hProcess, deepLoad); } else if(unitInfo == GameData::UnknownUnit) { // Try reading missile extension LoadMissileFromMem(base, hProcess, deepLoad); } } // Champion stuff DWORD GameObject::spellSlotPointerBuffer[6] = {}; BYTE GameObject::itemListBuffer[0x100] = {}; void GameObject::LoadChampionFromMem(DWORD base, HANDLE hProcess, bool deepLoad) { // Read spells memcpy(&spellSlotPointerBuffer, &buff[Offsets::ObjSpellBook], sizeof(DWORD) * 6); Q.LoadFromMem(spellSlotPointerBuffer[0], hProcess); W.LoadFromMem(spellSlotPointerBuffer[1], hProcess); E.LoadFromMem(spellSlotPointerBuffer[2], hProcess); R.LoadFromMem(spellSlotPointerBuffer[3], hProcess); D.LoadFromMem(spellSlotPointerBuffer[4], hProcess); F.LoadFromMem(spellSlotPointerBuffer[5], hProcess); // Read items DWORD ptrList = Mem::ReadDWORD(hProcess, address + Offsets::ObjItemList); Mem::Read(hProcess, ptrList, itemListBuffer, 0x100); for (int i = 0; i < 6; ++i) { itemSlots[i].isEmpty = true; itemSlots[i].slot = i; DWORD itemPtr = 0, itemInfoPtr = 0; memcpy(&itemPtr, itemListBuffer + i * 0x10 + Offsets::ItemListItem, sizeof(DWORD)); if (itemPtr == 0) continue; itemInfoPtr = Mem::ReadDWORD(hProcess, itemPtr + Offsets::ItemInfo); if (itemInfoPtr == 0) continue; int id = Mem::ReadDWORD(hProcess, itemInfoPtr + Offsets::ItemInfoId); itemSlots[i].isEmpty = false; itemSlots[i].stats = GameData::GetItemInfoById(id); } // Read level level = Mem::ReadDWORD(hProcess, base + Offsets::ObjLvl); } float GameObject::GetBasicAttackDamage() { return baseAttack + bonusAttack; } Spell* GameObject::GetSummonerSpell(SummonerSpellType type) { if (D.summonerSpellType == type) return &D; if (F.summonerSpellType == type) return &F; return nullptr; } bool GameObject::IsRanged() { return GetBaseAttackRange() >= 300.f; } list GameObject::ItemsToPyList() { list l; for (int i = 0; i < 6; ++i){ if (!itemSlots[i].isEmpty) l.append(boost::ref(itemSlots[i])); } return l; } // Missile stuff void GameObject::LoadMissileFromMem(DWORD base, HANDLE hProcess, bool deepLoad) { if (!deepLoad) return; DWORD spellInfoPtr = Mem::ReadDWORDFromBuffer(buff, Offsets::MissileSpellInfo); if (spellInfoPtr == 0) return; DWORD spellDataPtr = Mem::ReadDWORD(hProcess, spellInfoPtr + Offsets::SpellInfoSpellData); if (spellDataPtr == 0) return; memcpy(&srcIndex, buff + Offsets::MissileSrcIdx, sizeof(short)); memcpy(&destIndex, buff + Offsets::MissileDestIdx, sizeof(short)); memcpy(&startPos, buff + Offsets::MissileStartPos, sizeof(Vector3)); memcpy(&endPos, buff + Offsets::MissileEndPos, sizeof(Vector3)); Mem::Read(hProcess, spellDataPtr, buff, 0x500); // Read name char nameBuff[50]; Mem::Read(hProcess, Mem::ReadDWORD(hProcess, spellDataPtr + Offsets::SpellDataMissileName), nameBuff, 50); if (Character::ContainsOnlyASCII(nameBuff, 50)) name = Character::ToLower(std::string(nameBuff)); else name = std::string(""); // Find static data spellInfo = GameData::GetSpellInfoByName(name); // Some spells require their end position to be projected using the range of the spell if (spellInfo != GameData::UnknownSpell && HasSpellFlags(ProjectedDestination)) { startPos.y += spellInfo->height; // Calculate direction vector and normalize endPos = Vector3(endPos.x - startPos.x, 0, endPos.z - startPos.z); endPos = endPos.normalize(); // Update endposition using the height of the current position endPos.x = endPos.x*spellInfo->castRange + startPos.x; endPos.y = startPos.y; endPos.z = endPos.z*spellInfo->castRange + startPos.z; } } bool GameObject::EqualSpellFlags(SpellFlags flags) const { return spellInfo->flags == flags; } bool GameObject::HasSpellFlags(SpellFlags flags) const { return (spellInfo->flags & flags) == flags; } float GameObject::GetSpeed() const { return spellInfo->speed; } float GameObject::GetCastRange() const { return spellInfo->castRange; } float GameObject::GetWidth() const { return spellInfo->width; } float GameObject::GetCastRadius() const { return spellInfo->castRadius; } float GameObject::GetDelay() const { return spellInfo->delay; } float GameObject::GetHeight() const { return spellInfo->height; } float GameObject::GetTravelTime() const { return spellInfo->travelTime; } std::string GameObject::GetIcon() const { return spellInfo->icon; } ================================================ FILE: LView/GameObject.h ================================================ #pragma once #include #include #include #include "Vector.h" #include "windows.h" #include "MemoryLoadable.h" #include "UnitInfo.h" #include "GameData.h" #include "Spell.h" #include "SpellInterface.h" #include "ItemSlot.h" #include #include using namespace boost::python; using namespace std::chrono; /// Base game object /// /// Due to how league's game objects are implemented and to achieve good performance reading game objects /// this class doesnt use inheritance instead it packs all the types together in this class class GameObject: MemoryLoadable, SpellInterface { public: // Base void LoadFromMem(DWORD base, HANDLE hProcess, bool deepLoad = true); bool HasUnitTags(const UnitTag& type1) const; float GetAcquisitionRadius() const; float GetSelectionRadius() const; float GetPathingRadius() const; float GetGameplayRadius() const; float GetBasicAttackMissileSpeed() const; float GetBasicAttackWindup() const; float GetAttackSpeedRatio() const; float GetBaseMovementSpeed() const; float GetBaseAttackSpeed() const; float GetBaseAttackRange() const; float GetAttackRange() const; float GetHpBarHeight() const; bool IsEnemyTo(const GameObject& other) const; bool IsAllyTo(const GameObject& other) const; bool IsEqualTo(const GameObject& other) const; bool IsNotEqualTo(const GameObject& other) const; public: float health; float maxHealth; float baseAttack; float bonusAttack; float armour; float magicResist; float crit; float critMulti; float abilityPower; float atkSpeedMulti; float movementSpeed; float duration; short objectIndex; short team; bool isVisible; bool isAlive; float lastVisibleAt; std::string name; Vector3 position; high_resolution_clock::time_point timeSinceLastPreviousPosition; Vector3 previousPosition; DWORD networkId; DWORD address; UnitInfo* unitInfo = GameData::UnknownUnit; protected: static const SIZE_T sizeBuff = 0x4000; static const SIZE_T sizeBuffDeep = 0x1000; static BYTE buff[sizeBuff]; static BYTE buffDeep[sizeBuffDeep]; // Champion related stuff public: void LoadChampionFromMem(DWORD base, HANDLE hProcess, bool deepLoad = true); float GetBasicAttackDamage(); Spell* GetSummonerSpell(SummonerSpellType type); bool IsRanged(); list ItemsToPyList(); Spell Q = Spell(SpellSlot::Q); Spell W = Spell(SpellSlot::W); Spell E = Spell(SpellSlot::E); Spell R = Spell(SpellSlot::R); Spell D = Spell(SpellSlot::D); Spell F = Spell(SpellSlot::F); DWORD level; ItemSlot itemSlots[6]; private: static DWORD spellSlotPointerBuffer[6]; static BYTE itemListBuffer[0x100]; // Spell related stuff public: void LoadMissileFromMem(DWORD base, HANDLE hProcess, bool deepLoad = true); bool HasSpellFlags(SpellFlags flags) const override; bool EqualSpellFlags(SpellFlags flags) const override; float GetSpeed() const override; float GetCastRange() const override; float GetWidth() const override; float GetCastRadius() const override; float GetDelay() const override; float GetHeight() const override; float GetTravelTime() const override; std::string GetIcon() const override; short srcIndex; short destIndex; Vector3 startPos; Vector3 endPos; SpellInfo* spellInfo = GameData::UnknownSpell; }; ================================================ FILE: LView/GameRenderer.cpp ================================================ #include "GameRenderer.h" #include "Offsets.h" #include "Utils.h" #include "MapObject.h" #include void GameRenderer::LoadFromMem(DWORD_PTR renderBase, DWORD_PTR moduleBase, HANDLE hProcess) { char buff[128]; Mem::Read(hProcess, renderBase, buff, 128); memcpy(&width, &buff[Offsets::RendererWidth], sizeof(int)); memcpy(&height, &buff[Offsets::RendererHeight], sizeof(int)); Mem::Read(hProcess, moduleBase + Offsets::ViewProjMatrices, buff, 128); memcpy(viewMatrix, buff, 16 * sizeof(float)); memcpy(projMatrix, &buff[16 * sizeof(float)], 16 * sizeof(float)); MultiplyMatrices(viewProjMatrix, viewMatrix, 4, 4, projMatrix, 4, 4); } /* Multiply two matrices */ void GameRenderer::MultiplyMatrices(float *out, float *a, int row1, int col1, float *b, int row2, int col2) { int size = row1 * col2; for (int i = 0; i < row1; i++) { for (int j = 0; j < col2; j++) { float sum = 0.f; for (int k = 0; k < col1; k++) sum = sum + a[i * col1 + k] * b[k * col2 + j]; out[i * col2 + j] = sum; } } } Vector2 GameRenderer::WorldToScreen(const Vector3& pos) const { Vector2 out = { 0.f, 0.f }; Vector2 screen = { (float)width, (float)height }; static Vector4 clipCoords; clipCoords.x = pos.x * viewProjMatrix[0] + pos.y * viewProjMatrix[4] + pos.z * viewProjMatrix[8] + viewProjMatrix[12]; clipCoords.y = pos.x * viewProjMatrix[1] + pos.y * viewProjMatrix[5] + pos.z * viewProjMatrix[9] + viewProjMatrix[13]; clipCoords.z = pos.x * viewProjMatrix[2] + pos.y * viewProjMatrix[6] + pos.z * viewProjMatrix[10] + viewProjMatrix[14]; clipCoords.w = pos.x * viewProjMatrix[3] + pos.y * viewProjMatrix[7] + pos.z * viewProjMatrix[11] + viewProjMatrix[15]; if (clipCoords.w < 1.0f) clipCoords.w = 1.f; Vector3 M; M.x = clipCoords.x / clipCoords.w; M.y = clipCoords.y / clipCoords.w; M.z = clipCoords.z / clipCoords.w; out.x = (screen.x / 2.f * M.x) + (M.x + screen.x / 2.f); out.y = -(screen.y / 2.f * M.y) + (M.y + screen.y / 2.f); return out; } Vector2 GameRenderer::WorldToMinimap(const Vector3& pos, const Vector2& wPos, const Vector2& wSize) const { Vector2 result = { pos.x / 15000.f, pos.z / 15000.f }; result.x = wPos.x + result.x * wSize.x; result.y = wPos.y + wSize.y - (result.y * wSize.y); return result; } float GameRenderer::DistanceToMinimap(float dist, const Vector2& wSize) const { // This assumes that the minimap is a square ! return (dist / 15000.f) * wSize.x; } bool GameRenderer::IsScreenPointOnScreen(const Vector2& point, float offsetX, float offsetY) const { return point.x > -offsetX && point.x < (width + offsetX) && point.y > -offsetY && point.y < (height + offsetY); } bool GameRenderer::IsWorldPointOnScreen(const Vector3& point, float offsetX, float offsetY) const { return IsScreenPointOnScreen(WorldToScreen(point), offsetX, offsetY); } void GameRenderer::DrawCircleAt(ImDrawList* canvas, const Vector3& worldPos, float radius, bool filled, int numPoints, ImColor color, float thickness) const { if (numPoints >= 200) return; static ImVec2 points[200]; float step = 6.2831f / numPoints; float theta = 0.f; for (int i = 0; i < numPoints; i++, theta += step) { Vector3 worldSpace = { worldPos.x + radius * cos(theta), worldPos.y, worldPos.z - radius * sin(theta) }; Vector2 screenSpace = WorldToScreen(worldSpace); points[i].x = screenSpace.x; points[i].y = screenSpace.y; } if (filled) canvas->AddConvexPolyFilled(points, numPoints, color); else canvas->AddPolyline(points, numPoints, color, true, thickness); } ================================================ FILE: LView/GameRenderer.h ================================================ #pragma once #include "Vector.h" #include "windows.h" #include "imgui.h" /// Represents the state of the games renderer class GameRenderer { public: int width, height; float viewMatrix[16]; float projMatrix[16]; float viewProjMatrix[16]; void LoadFromMem(DWORD_PTR renderBase, DWORD_PTR moduleBase, HANDLE hProcess); /// Converts world coordinates to screen coordinates Vector2 WorldToScreen(const Vector3& pos) const; /// Converts world coordinates to minimap coordinates Vector2 WorldToMinimap(const Vector3& pos, const Vector2& wPos, const Vector2& wSize) const; /// Converts distances in world space to minimap space float DistanceToMinimap(float dist, const Vector2& wSize) const; /// Draws a circle at the given coordinate. Coordinates and radius must be in world space void DrawCircleAt(ImDrawList* canvas, const Vector3& worldPos, float radius, bool filled, int numPoints, ImColor color, float thickness = 3.f) const; /// Used to determine if a screen space point is on screen bool IsScreenPointOnScreen(const Vector2& point, float offsetX = 0.f, float offsetY = 0.f) const; /// Used to determine if a world space point is on screen bool IsWorldPointOnScreen(const Vector3& point, float offsetX = 0.f, float offsetY = 0.f) const; private: void MultiplyMatrices(float *out, float *a, int row1, int col1, float *b, int row2, int col2); }; ================================================ FILE: LView/Input.cpp ================================================ #include "Input.h" #include "windows.h" #include #include "Vector.h" using namespace std::chrono; void Input::PressKey(HKey key) { INPUT input; input.type = INPUT_KEYBOARD; input.ki.wScan = key; input.ki.time = 0; input.ki.dwExtraInfo = 0; input.ki.wVk = 0; input.ki.dwFlags = KEYEVENTF_SCANCODE; SendInput(1, &input, sizeof(INPUT)); Sleep(8); input.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP; SendInput(1, &input, sizeof(INPUT)); } bool Input::WasKeyPressed(HKey key) { static high_resolution_clock::time_point nowTime; static high_resolution_clock::time_point lastTimePressed[300] = {high_resolution_clock::now()}; static bool pressed[300] = { 0 }; static duration timeDiff; int virtualKey = MapVirtualKeyA(key, MAPVK_VSC_TO_VK); if (virtualKey == 0) return false; nowTime = high_resolution_clock::now(); timeDiff = nowTime - lastTimePressed[virtualKey]; if (pressed[virtualKey]) { if (timeDiff.count() > 200) pressed[virtualKey] = false; return false; } bool keyDown = GetAsyncKeyState(virtualKey) & 0x8000; if (keyDown) { lastTimePressed[virtualKey] = high_resolution_clock::now(); pressed[virtualKey] = true; return true; } return false; } bool Input::IsKeyDown(HKey key) { int virtualKey = MapVirtualKeyA(key, MAPVK_VSC_TO_VK); if (virtualKey == 0) return false; return GetAsyncKeyState(virtualKey); } Vector2 Input::GetCursorPosition() { POINT pos; GetCursorPos(&pos); return { (float)pos.x, (float)pos.y }; } void Input::PressLeftClick() { INPUT input = {0}; input.type = INPUT_MOUSE; input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN; SendInput(1, &input, sizeof(INPUT)); Sleep(8); input.mi.dwFlags = MOUSEEVENTF_LEFTUP; SendInput(1, &input, sizeof(INPUT)); } void Input::PressRightClick() { INPUT input = { 0 }; input.type = INPUT_MOUSE; input.mi.dwFlags = MOUSEEVENTF_RIGHTDOWN; SendInput(1, &input, sizeof(INPUT)); Sleep(8); input.mi.dwFlags = MOUSEEVENTF_RIGHTUP; SendInput(1, &input, sizeof(INPUT)); } void Input::ClickAt(bool leftClick, float x, float y) { static float fScreenWidth = (float)::GetSystemMetrics(SM_CXSCREEN) - 1; static float fScreenHeight = (float)::GetSystemMetrics(SM_CYSCREEN) - 1; POINT oldPos; GetCursorPos(&oldPos); INPUT input = { 0 }; input.type = INPUT_MOUSE; input.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE; input.mi.dx = (LONG)(x * (65535.0f / fScreenWidth)); input.mi.dy = (LONG)(y * (65535.0f / fScreenHeight)); SendInput(1, &input, sizeof(INPUT)); input.mi.dwFlags = (leftClick ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_RIGHTDOWN); SendInput(1, &input, sizeof(INPUT)); Sleep(8); input.mi.dwFlags = (leftClick ? MOUSEEVENTF_LEFTUP: MOUSEEVENTF_RIGHTUP); SendInput(1, &input, sizeof(INPUT)); input.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE; input.mi.dx = (LONG)(oldPos.x * (65535.0f / fScreenWidth)); input.mi.dy = (LONG)(oldPos.y * (65535.0f / fScreenHeight)); SendInput(1, &input, sizeof(INPUT)); SendInput(1, &input, sizeof(INPUT)); } void Input::MoveCursorTo(float x, float y) { static float fScreenWidth = (float)::GetSystemMetrics(SM_CXSCREEN) - 1; static float fScreenHeight = (float)::GetSystemMetrics(SM_CYSCREEN) - 1; INPUT input = { 0 }; input.type = INPUT_MOUSE; input.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE; input.mi.dx = (LONG)(x * (65535.0f / fScreenWidth)); input.mi.dy = (LONG)(y * (65535.0f / fScreenHeight)); // Sometimes this fails idk why the fuck but calling the function two times seems to solve it SendInput(1, &input, sizeof(INPUT)); SendInput(1, &input, sizeof(INPUT)); } ================================================ FILE: LView/Input.h ================================================ #pragma once #include "Vector.h" /* Took from https://www.millisecond.com/support/docs/v6/html/language/scancodes.htm */ enum HKey { NO_KEY = 0, ESC, N_1, N_2, N_3, N_4, N_5, N_6, N_7, N_8, N_9, N_0, MINUS, EQUAL, BS, Tab, Q, W, E, R, T, Y, U, I, O, P, LBRACKET, RBRACKET, ENTER, CTRL, A, S, D, F, G, H, J, K, L, SEMICOLON, SINGLE_QUOTE, TILDE, LSHIFT, BACKSLASH, Z, X, C, V, B, N, M, COMMA, DOT, FRONTSLASH, RSHIFT, PRINT_SCREEN, ALT, SPACE, CAPS, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, NUM, SCROLL, HOME, UP, PAGE_UP, NUM_MINUS, LEFT, CENTER, RIGHT, PLUS, END, DOWN, PAGE_DOWN, INSERT, DEL }; static const char* HKeyNames[] = { "None", "Esc", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "=", "Backspace", "Tab", "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", "[", "]", "Enter", "Ctrl", "A", "S", "D", "F", "G", "H", "J", "K", "L", ";", "'", "`", "LShift", "\\", "Z", "X", "C", "V", "B", "N", "M", ",", ".", "/", "RShift", "PrtScrn", "Alt", "Space", "Caps", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "Num", "Scrl", "Home", "Num8", "PgUp", "NumMinus", "Num4", "Num5", "Num6", "NumPlus", "End", "NumDown", "PgDown", "Insert", "Del" }; /// Keyboard/Mouse input related utilities. For keyboards the hardware key codes are used instead of the virtual ones. namespace Input { /// Presses the specified hardware key void PressKey(HKey key); /// Checks if a key was pressed recently. Only one caller can use this function for a given key. bool WasKeyPressed(HKey key); /// Checks if the key is held down. bool IsKeyDown(HKey key); /// Gets the cursor position in window coordinates Vector2 GetCursorPosition(); /// Sends a left click input void PressLeftClick(); /// Sends a right click input void PressRightClick(); /// Moves the cursor at the specified location, clicks and then moves the cursor back at the initial location void ClickAt(bool leftClick, float x, float y); /// Moves the cursor to the specified window coordinates. void MoveCursorTo(float x, float y); } ================================================ FILE: LView/ItemInfo.h ================================================ #pragma once #include struct ItemInfo { public: int id; float cost; float movementSpeed; float health; float crit; float abilityPower; float mana; float armour; float magicResist; float physicalDamage; float attackSpeed; float lifeSteal; float hpRegen; float movementSpeedPercent; }; ================================================ FILE: LView/ItemSlot.cpp ================================================ #include "ItemSlot.h" int ItemSlot::GetId() { return stats->id; } float ItemSlot::GetCost() { return stats->cost; } float ItemSlot::GetMovementSpeed() { return stats->movementSpeed; } float ItemSlot::GetHealth() { return stats->health; } float ItemSlot::GetCrit() { return stats->crit; } float ItemSlot::GetAbilityPower() { return stats->abilityPower; } float ItemSlot::GetMana() { return stats->mana; } float ItemSlot::GetArmour() { return stats->armour; } float ItemSlot::GetMagicResist() { return stats->magicResist; } float ItemSlot::GetPhysicalDamage() { return stats->physicalDamage; } float ItemSlot::GetAttackSpeed() { return stats->attackSpeed; } float ItemSlot::GetLifeSteal() { return stats->lifeSteal; } float ItemSlot::GetHpRegen() { return stats->hpRegen; } float ItemSlot::GetMovementSpeedPercent() { return stats->movementSpeed; } ================================================ FILE: LView/ItemSlot.h ================================================ #pragma once #include "ItemInfo.h" class ItemSlot { public: int GetId(); float GetCost(); float GetMovementSpeed(); float GetHealth(); float GetCrit(); float GetAbilityPower(); float GetMana(); float GetArmour(); float GetMagicResist(); float GetPhysicalDamage(); float GetAttackSpeed(); float GetLifeSteal(); float GetHpRegen(); float GetMovementSpeedPercent(); public: bool isEmpty = true; int slot = 0; ItemInfo* stats = nullptr; }; ================================================ FILE: LView/LView.cpp ================================================ #define BOOST_DEBUG_PYTHON #define USE_IMPORT_EXPORT #define USE_WINDOWS_DLL_SEMANTICS #define STB_IMAGE_IMPLEMENTATION #include "PyStructs.h" #include #include "windows.h" #include "Utils.h" #include "Structs.h" #include "LeagueMemoryReader.h" #include "Offsets.h" #include "AntiCrack.h" #include "MapObject.h" #include "GameData.h" #include #include "Overlay.h" #include #include #include using namespace std::chrono; /* bool Authenticate(); */ void MainLoop(Overlay& overlay, LeagueMemoryReader& reader); int main() { printf( " ::: ::: ::: ::::::::::: :::::::::: ::: ::: \n" " :+: :+: :+: :+: :+: :+: :+: \n" " +:+ +:+ +:+ +:+ +:+ +:+ +:+ \n" " +#+ +#+ +:+ +#+ +#++:++# +#+ +:+ +#+ \n" " +#+ +#+ +#+ +#+ +#+ +#+ +#+#+ +#+ \n" " #+# #+#+#+# #+# #+# #+#+# #+#+# \n" " ########## ### ########### ########## ### ### \n\n" ); Overlay overlay = Overlay(); LeagueMemoryReader reader = LeagueMemoryReader(); try { printf("[+] Initializing PyModule\n"); PyImport_AppendInittab("lview", &PyInit_lview); Py_Initialize(); printf("[+] Initialising imgui and directx UI\n"); overlay.Init(); printf("[+] Loading static map data\n\n"); MapObject::Get(MapType::SUMMONERS_RIFT)->Load("data/height_map_sru.bin"); MapObject::Get(MapType::HOWLING_ABYSS)->Load("data/height_map_ha.bin"); printf("[+] Loading unit data\n"); std::string dataPath("data"); GameData::Load(dataPath); MainLoop(overlay, reader); Py_Finalize(); } catch (std::runtime_error exception) { std::cout << exception.what() << std::endl; } printf("Press any key to exit..."); getch(); } void MainLoop(Overlay& overlay, LeagueMemoryReader& reader) { MemSnapshot memSnapshot; bool rehook = true; bool firstIter = true; printf("[i] Waiting for league process...\n"); while (true) { bool isLeagueWindowActive = reader.IsLeagueWindowActive(); if (overlay.IsVisible()) { // One some systems the ingame cursor is replaced with the default Windows cursor // With the WS_EX_TRANSPARENT window flag enabled the cursor is as expected but the user cannot control the overlay if (Input::WasKeyPressed(HKey::F8)) { overlay.ToggleTransparent(); } if (!isLeagueWindowActive) { overlay.Hide(); } } else if (isLeagueWindowActive) { overlay.Show(); } try { overlay.StartFrame(); // Try to find the league process and get its information necessary for reading if (rehook) { reader.HookToProcess(); rehook = false; firstIter = true; memSnapshot = MemSnapshot(); printf("[i] Found league process. The UI will appear when the game stars.\n"); } else { if (!reader.IsHookedToProcess()) { rehook = true; printf("[i] League process is dead.\n"); printf("[i] Waiting for league process...\n"); } reader.MakeSnapshot(memSnapshot); // If the game started if (memSnapshot.gameTime > 2.f) { // Tell the UI that a new game has started if (firstIter) { overlay.GameStart(memSnapshot); firstIter = false; } overlay.Update(memSnapshot); } } } catch (WinApiException exception) { // This should trigger only when we don't find the league process. rehook = true; } catch (std::runtime_error exception) { printf("[!] Unexpected error occured: \n [!] %s \n", exception.what()); break; } overlay.RenderFrame(); } } /* #include #include #include #include #include /// Authentication using AWS. Calls a lambda from AWS that will do the authentication. bool Authenticate() { Aws::SDKOptions options; Aws::InitAPI(options); ConfigSet* cfg = ConfigSet::Get(); cfg->SetPrefixKey("auth"); std::string name = cfg->GetStr("user", ""); std::string region = cfg->GetStr("region", ""); std::string accessKey = cfg->GetStr("access_key", ""); std::string secretKey = cfg->GetStr("secret_key", ""); cfg->SetPrefixKey(""); if (region.empty() || name.empty() || accessKey.empty() || secretKey.empty()) { printf("[!] auth:: config fields are missing"); return false; } Aws::Auth::AWSCredentials credentials; credentials.SetAWSAccessKeyId(accessKey.c_str()); credentials.SetAWSSecretKey(secretKey.c_str()); Aws::Client::ClientConfiguration config; config.region = Aws::String(region.c_str()); std::string hwid = AntiCrack::GetHardwareID(); std::shared_ptr payload = Aws::MakeShared("FunctionTest"); Aws::Utils::Json::JsonValue json; json.WithString("operation", "auth"); json.WithString("name", name.c_str()); json.WithString("secret_key", secretKey.c_str()); json.WithString("access_key", accessKey.c_str()); json.WithString("hwid", hwid.c_str()); *payload << json.View().WriteReadable(); auto client = Aws::MakeShared("alloc_tag", credentials, config); Aws::Lambda::Model::InvokeRequest invokeRequest; invokeRequest.SetFunctionName("lview-auth"); invokeRequest.SetInvocationType(Aws::Lambda::Model::InvocationType::RequestResponse); invokeRequest.SetLogType(Aws::Lambda::Model::LogType::Tail); invokeRequest.SetBody(payload); invokeRequest.SetContentType("application/javascript"); auto outcome = client->Invoke(invokeRequest); if (!outcome.IsSuccess()) { printf("[!] Access denied.\n"); auto err = outcome.GetError(); printf(err.GetExceptionName().c_str()); return false; } auto& result = outcome.GetResult(); Aws::Utils::Json::JsonValue resultJson(result.GetPayload()); int statusCode = resultJson.View().GetInteger("status"); Aws::String msg = resultJson.View().GetString("msg"); if (statusCode != 200) { printf("[!] Server authentication failed: %s\n", msg.c_str()); return false; } printf("[+] Server authentication succeeded: %s\n", msg.c_str()); return true; } */ ================================================ FILE: LView/LView.vcxproj ================================================ Debug Win32 Release Win32 Debug x64 Release x64 15.0 {B1847FC4-24EC-448C-8478-1AF955EF2C28} Win32Proj LView 10.0.19041.0 Application true v142 Unicode Application false v142 true Unicode Application true v142 Unicode Application false v142 true Unicode true ConsoleApplication true false ConsoleApplication $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); false Level3 Disabled true _SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpp17 $(SolutionDir)\LView\boost;$(SolutionDir)\LView\external_includes;%(AdditionalIncludeDirectories) Console true $(SolutionDir)\LView\external_libs;%(AdditionalLibraryDirectories) python39.lib;d3d11.lib;dxgi.lib;dcomp.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) Level3 Disabled true _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true F:\Github\LViewLoL\LView\external_includes;%(AdditionalIncludeDirectories) Console true F:\Github\LViewLoL\LView\external_libs;%(AdditionalLibraryDirectories) python39_d.lib;python39.lib;d3d9.lib;d3dx9.lib;%(AdditionalDependencies) Level3 MaxSpeed true true true _SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpp17 $(SolutionDir)\LView\boost;$(SolutionDir)\LView\external_includes;%(AdditionalIncludeDirectories) Console true true true $(SolutionDir)\LView\external_libs;%(AdditionalLibraryDirectories) python39.lib;d3d11.lib;dxgi.lib;dcomp.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) Level3 MaxSpeed true true true NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true F:\Github\LViewLoL\LView\external_includes;%(AdditionalIncludeDirectories) Console true true true F:\Github\LViewLoL\LView\external_libs;%(AdditionalLibraryDirectories) python39_d.lib;python39.lib;d3d9.lib;d3dx9.lib;%(AdditionalDependencies) ================================================ FILE: LView/LView.vcxproj.filters ================================================  {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hh;hpp;hxx;hm;inl;inc;ipp;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms {32136a6d-8cd7-4799-985c-41045dbdfc59} {c41e4a3e-5831-4f46-b805-716fdeccd807} {896ec100-64c0-4b57-aba6-5b62f361dff3} {3f16e38a-ff17-45e9-9c82-26e29044bd89} {277024ac-8f44-404e-aec4-a058949713dd} {d28b0c84-0437-4186-bf25-e02b6db8c8c7} {a2f140b9-3045-40da-be66-60eabf10af5d} {f24696f8-27e0-4883-9478-56065f8048e4} {0ffb7377-39cd-40f3-8539-0eba6297aefe} {c139ef89-3486-4f32-bff6-8e82d5fe5a24} {7ab4a644-702d-449c-b876-0ddde6ddd978} {462e78dd-f859-45e0-8411-dd4643618c9a} {890199b9-57ab-45fd-bd47-9b8cd568f133} Source Files\External\imgui Source Files\External\imgui Source Files\External\imgui Source Files\External\imgui Source Files\External\imgui Source Files\External\imgui Source Files\Utils Source Files\Utils Source Files\Utils Source Files\Python Source Files\Utils Source Files\Core Source Files\Core Source Files\Core Source Files\External\imgui Source Files\GUI Source Files\Structs\GameRelated\Spells Source Files\Structs\GameRelated\Units Source Files\Python Source Files\Structs\GameRelated\Data Source Files\Structs\GameRelated\Spells Source Files\Structs\GameRelated\Spells Source Files\Structs\GameRelated\Units Source Files\Structs\GameRelated\Data Source Files\Structs\GameRelated\Others Source Files\Utils Source Files\Structs\GameRelated\Others Source Files\External\imgui Source Files\External\imgui Source Files\External\imgui Source Files\External\imgui Source Files\External\imgui Source Files\External\imgui Source Files\External\imgui Source Files\Utils Source Files\Utils Source Files\Utils Source Files\Utils Source Files\Python Source Files\Python Source Files\Python Source Files\Python Source Files\Python Source Files\Utils Source Files\Core Source Files\External\imgui Source Files\GUI Source Files\Structs\GameRelated\Spells Source Files\Structs\GameRelated\Units Source Files\Utils Source Files\Utils Source Files\Structs\GameRelated\Data Source Files\Structs\GameRelated\Spells Source Files\Structs\GameRelated\Units Source Files\Structs\GameRelated\Data Source Files\Structs\GameRelated\Others Source Files\Structs\GameRelated\Others Source Files\External\stb_image Source Files\Utils Source Files\Structs\GameRelated\Others Source Files\Structs\GameRelated\Others Source Files\Core ================================================ FILE: LView/LView.vcxproj.user ================================================  ================================================ FILE: LView/LeagueMemoryReader.cpp ================================================ #include "LeagueMemoryReader.h" #include "windows.h" #include "Utils.h" #include "Structs.h" #include "psapi.h" #include #include LeagueMemoryReader::LeagueMemoryReader() { // Some trash object not worth reading blacklistedObjectNames.insert("testcube"); blacklistedObjectNames.insert("testcuberender"); blacklistedObjectNames.insert("testcuberender10vision"); blacklistedObjectNames.insert("s5test_wardcorpse"); blacklistedObjectNames.insert("sru_camprespawnmarker"); blacklistedObjectNames.insert("sru_plantrespawnmarker"); blacklistedObjectNames.insert("preseason_turret_shield"); } bool LeagueMemoryReader::IsLeagueWindowActive() { HWND handle = GetForegroundWindow(); DWORD h; GetWindowThreadProcessId(handle, &h); return pid == h; } bool LeagueMemoryReader::IsHookedToProcess() { return Process::IsProcessRunning(pid); } void LeagueMemoryReader::HookToProcess() { // Find the window hWindow = FindWindowA("RiotWindowClass", NULL); if (hWindow == NULL) { throw WinApiException("League window not found"); } // Get the process ID GetWindowThreadProcessId(hWindow, &pid); if (pid == NULL) { throw WinApiException("Couldn't retrieve league process id"); } // Open the process hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); if (hProcess == NULL) { throw WinApiException("Couldn't open league process"); } // Check architecture if (0 == IsWow64Process(hProcess, &is64Bit)) { throw WinApiException("Failed to identify if process has 32 or 64 bit architecture"); } HMODULE hMods[1024]; DWORD cbNeeded; if (EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded)) { moduleBaseAddr = (DWORD_PTR)hMods[0]; } else { throw WinApiException("Couldn't retrieve league base address"); } blacklistedObjects.clear(); } void LeagueMemoryReader::ReadRenderer(MemSnapshot& ms) { high_resolution_clock::time_point readTimeBegin; duration readDuration; readTimeBegin = high_resolution_clock::now(); DWORD rendererAddr = Mem::ReadDWORD(hProcess, moduleBaseAddr + Offsets::Renderer); ms.renderer->LoadFromMem(rendererAddr, moduleBaseAddr, hProcess); readDuration = high_resolution_clock::now() - readTimeBegin; ms.benchmark->readRendererMs = readDuration.count(); } void LeagueMemoryReader::FindHoveredObject(MemSnapshot& ms) { int addrObj = Mem::ReadDWORD(hProcess, moduleBaseAddr + Offsets::UnderMouseObject); int netId = Mem::ReadDWORD(hProcess, addrObj + Offsets::ObjNetworkID); auto it = ms.objectMap.find(netId); if (it != ms.objectMap.end()) ms.hoveredObject = it->second; else ms.hoveredObject = nullptr; } /// This method reads the game objects from memory. It reads the tree structure of a std::map /// in this std::map reside Champions, Minions, Turrets, Missiles, Jungle mobs etc. Basically non static objects. void LeagueMemoryReader::ReadObjects(MemSnapshot& ms) { static const int maxObjects = 500; static int pointerArray[maxObjects]; high_resolution_clock::time_point readTimeBegin; duration readDuration; readTimeBegin = high_resolution_clock::now(); ms.champions.clear(); ms.minions.clear(); ms.jungle.clear(); ms.missiles.clear(); ms.turrets.clear(); ms.others.clear(); int objectManager = Mem::ReadDWORD(hProcess, moduleBaseAddr + Offsets::ObjectManager); static char buff[0x500]; Mem::Read(hProcess, objectManager, buff, 0x100); int numMissiles, rootNode; memcpy(&numMissiles, buff + Offsets::ObjectMapCount, sizeof(int)); memcpy(&rootNode, buff + Offsets::ObjectMapRoot, sizeof(int)); std::queue nodesToVisit; std::set visitedNodes; nodesToVisit.push(rootNode); // Read object pointers from tree int nrObj = 0; int reads = 0; int childNode1, childNode2, childNode3, node; while (reads < maxObjects && nodesToVisit.size() > 0) { node = nodesToVisit.front(); nodesToVisit.pop(); if (visitedNodes.find(node) != visitedNodes.end()) continue; reads++; visitedNodes.insert(node); Mem::Read(hProcess, node, buff, 0x30); memcpy(&childNode1, buff, sizeof(int)); memcpy(&childNode2, buff + 4, sizeof(int)); memcpy(&childNode3, buff + 8, sizeof(int)); nodesToVisit.push(childNode1); nodesToVisit.push(childNode2); nodesToVisit.push(childNode3); unsigned int netId = 0; memcpy(&netId, buff + Offsets::ObjectMapNodeNetId, sizeof(int)); // Network ids of the objects we are interested in start from 0x40000000. We do this check for performance reasons. if (netId - (unsigned int)0x40000000 > 0x100000) continue; int addr; memcpy(&addr, buff + Offsets::ObjectMapNodeObject, sizeof(int)); if (addr == 0) continue; pointerArray[nrObj] = addr; nrObj++; } // Read objects from the pointers we just read for (int i = 0; i < nrObj; ++i) { int netId; Mem::Read(hProcess, pointerArray[i] + Offsets::ObjNetworkID, &netId, sizeof(int)); if (blacklistedObjects.find(netId) != blacklistedObjects.end()) continue; std::shared_ptr obj; auto it = ms.objectMap.find(netId); if (it == ms.objectMap.end()) { obj = std::shared_ptr(new GameObject()); obj->LoadFromMem(pointerArray[i], hProcess, true); ms.objectMap[obj->networkId] = obj; } else { obj = it->second; obj->LoadFromMem(pointerArray[i], hProcess, false); // If the object changed its id for whatever the fuck reason then we update the map with the new index if (netId != obj->networkId) { ms.objectMap[obj->networkId] = obj; } } if (obj->isVisible) { obj->lastVisibleAt = ms.gameTime; } if (obj->networkId != 0) { ms.indexToNetId[obj->objectIndex] = obj->networkId; ms.updatedThisFrame.insert(obj->networkId); if (obj->name.size() <= 2 || blacklistedObjectNames.find(obj->name) != blacklistedObjectNames.end()) blacklistedObjects.insert(obj->networkId); else if (obj->HasUnitTags(Unit_Champion)) ms.champions.push_back(obj); else if (obj->HasUnitTags(Unit_Minion_Lane)) ms.minions.push_back(obj); else if (obj->HasUnitTags(Unit_Monster)) ms.jungle.push_back(obj); else if (obj->HasUnitTags(Unit_Structure_Turret)) ms.turrets.push_back(obj); else if (obj->spellInfo != GameData::UnknownSpell) ms.missiles.push_back(obj); else ms.others.push_back(obj); } } readDuration = high_resolution_clock::now() - readTimeBegin; ms.benchmark->readObjectsMs = readDuration.count(); } void LeagueMemoryReader::ReadMinimap(MemSnapshot & snapshot) { int minimapObj = Mem::ReadDWORD(hProcess, moduleBaseAddr + Offsets::MinimapObject); int minimapHud = Mem::ReadDWORD(hProcess, minimapObj + Offsets::MinimapObjectHud); static char buff[0x80]; Mem::Read(hProcess, minimapHud, buff, 0x80); memcpy(&snapshot.minimapPos, buff + Offsets::MinimapHudPos, sizeof(Vector2)); memcpy(&snapshot.minimapSize, buff + Offsets::MinimapHudSize, sizeof(Vector2)); } void LeagueMemoryReader::FindPlayerChampion(MemSnapshot & snapshot) { int netId = 0; Mem::Read(hProcess, Mem::ReadDWORD(hProcess, moduleBaseAddr + Offsets::LocalPlayer) + Offsets::ObjNetworkID, &netId, sizeof(int)); auto it = snapshot.objectMap.find(netId); if (it != snapshot.objectMap.end()) snapshot.player = it->second; else // If we can't find the local player either the offset is wrong or we are watching a replay snapshot.player = (snapshot.champions.size() > 0 ? snapshot.champions[0] : nullptr); } void LeagueMemoryReader::ClearMissingObjects(MemSnapshot & ms) { auto it = ms.objectMap.begin(); while (it != ms.objectMap.end()) { if (ms.updatedThisFrame.find(it->first) == ms.updatedThisFrame.end()) { it = ms.objectMap.erase(it); } else ++it; } } void LeagueMemoryReader::MakeSnapshot(MemSnapshot& ms) { Mem::Read(hProcess, moduleBaseAddr + Offsets::GameTime, &ms.gameTime, sizeof(float)); if (ms.gameTime > 2) { ms.updatedThisFrame.clear(); ReadRenderer(ms); ReadMinimap(ms); ReadObjects(ms); ClearMissingObjects(ms); FindPlayerChampion(ms); FindHoveredObject(ms); ms.map = std::shared_ptr(MapObject::Get(ms.turrets.size() > 10 ? SUMMONERS_RIFT : HOWLING_ABYSS)); } } ================================================ FILE: LView/LeagueMemoryReader.h ================================================ #pragma once #include "windows.h" #include "GameObject.h" #include "GameRenderer.h" #include "Offsets.h" #include "MemSnapshot.h" #include #include #include #include #include using namespace std::chrono; /// Class used to read from leagues process memory class LeagueMemoryReader { public: LeagueMemoryReader(); /// Checks if leagues window is still active bool IsLeagueWindowActive(); /// Checks to see if we have a league window stored bool IsHookedToProcess(); /// Finds leagues window and stores it void HookToProcess(); /// Creates an object with everything of iterest from the game void MakeSnapshot(MemSnapshot& ms); private: // Process related HANDLE hProcess = NULL; DWORD pid = 0; HWND hWindow = NULL; // Memory related DWORD_PTR moduleBaseAddr = 0; DWORD moduleSize = 0; BOOL is64Bit = FALSE; private: float minDistanceToCursor; /// Blacklisted objects that we don't need to read for performance reasons. Set key is the object's network id std::set blacklistedObjects; std::set blacklistedObjectNames; void ReadRenderer(MemSnapshot& snapshot); void ReadObjects(MemSnapshot& snapshot); void ReadMinimap(MemSnapshot& snapshot); void FindPlayerChampion(MemSnapshot& snapshot); void ClearMissingObjects(MemSnapshot& snapshot); void FindHoveredObject(MemSnapshot& ms); }; ================================================ FILE: LView/MapObject.cpp ================================================ #include "MapObject.h" #include #include "Utils.h" std::array, 2> MapObject::maps = std::array, 2>({ nullptr, nullptr }); const float MapObject::HEIGHT_MAP_SIZE_RATIO = SIZE_HEIGHT_MAP / 15000.f; void MapObject::Load(const char* heightMapFile) { std::ifstream input(heightMapFile, std::ios::binary); if (!input.is_open()) throw std::runtime_error("No height_map.bin file"); for (int i = 0; i < SIZE_HEIGHT_MAP; ++i) { input.read((char*)heightMap[i].data(), SIZE_HEIGHT_MAP * sizeof(float)); } } float MapObject::GetHeightAt(float x, float z) { int ix = Clamp( (int)(HEIGHT_MAP_SIZE_RATIO*x), 0, SIZE_HEIGHT_MAP - 1); int iz = Clamp( (int)(HEIGHT_MAP_SIZE_RATIO*z), 0, SIZE_HEIGHT_MAP - 1); return heightMap[ix][iz]; } std::shared_ptr& MapObject::Get(MapType type) { if (maps[type] == nullptr) { maps[type] = std::shared_ptr(new MapObject()); maps[type]->type = type; } return maps[type]; } ================================================ FILE: LView/MapObject.h ================================================ #pragma once #include #include enum MapType { SUMMONERS_RIFT = 0, HOWLING_ABYSS = 1 }; class MapObject { public: /// Loads map data from disk void Load(const char* heightMapFile); /// Returns the ground Y coordinate. Uses a preloaded height map. float GetHeightAt(float x, float z); public: MapType type; static const int SIZE_HEIGHT_MAP = 512; static const float HEIGHT_MAP_SIZE_RATIO; std::array, SIZE_HEIGHT_MAP> heightMap; static std::shared_ptr& Get(MapType type); private: static std::array, 2> maps; }; ================================================ FILE: LView/MemSnapshot.h ================================================ #pragma once #include #include #include #include "Benchmark.h" #include "GameRenderer.h" #include "GameObject.h" #include "MapObject.h" /// Object encapsulating league's game state struct MemSnapshot { /* Lists of objects by category */ std::vector> champions; std::vector> minions; std::vector> jungle; std::vector> turrets; std::vector> missiles; std::vector> others; /* A map between the network id of the object and the object itself */ std::map> objectMap; std::map indexToNetId; /* Used to clear objectMap for objects that are no longer in game */ std::set updatedThisFrame; /* The champion of the player running the app */ std::shared_ptr player = nullptr; /* The object below the mouse */ std::shared_ptr hoveredObject = nullptr; /* Game renderer info */ std::unique_ptr renderer = std::unique_ptr(new GameRenderer()); /* How many seconds have elapsed since the game started */ float gameTime = 0.f; /* Stuff about the map the players are currently on */ std::shared_ptr map; /* Minimap related stuff */ Vector2 minimapPos; Vector2 minimapSize; /* Memory reading benchmarks */ std::unique_ptr benchmark = std::unique_ptr(new ReadBenchmark()); }; ================================================ FILE: LView/MemoryLoadable.h ================================================ #pragma once #include "windows.h" /// Interface to be implemented by game objects that are read from memory class MemoryLoadable { virtual void LoadFromMem(DWORD base, HANDLE hProcess, bool deepLoad = true) = 0; }; ================================================ FILE: LView/Offsets.cpp ================================================ #include "Offsets.h" Offsets::Offsets() {}; int Offsets::GameTime = 0x30d2c58; int Offsets::ObjIndex = 0x20; int Offsets::ObjTeam = 0x4C; int Offsets::ObjNetworkID = 0xCC; int Offsets::ObjPos = 0x1d8; int Offsets::ObjVisibility = 0x0270; int Offsets::ObjSpawnCount = 0x218; int Offsets::ObjSrcIndex = 0x290; int Offsets::ObjMana = 0x0298; int Offsets::ObjHealth = 0xd98; int Offsets::ObjMaxHealth = 0xDA8; int Offsets::ObjArmor = 0x1890; int Offsets::ObjMagicRes = 0x12D4; int Offsets::ObjBaseAtk = 0x12A4; int Offsets::ObjBonusAtk = 0x121C; int Offsets::ObjMoveSpeed = 0x12E4; int Offsets::ObjSpellBook = 0x27C8; int Offsets::ObjName = 0x2bb4; int Offsets::ObjLvl = 0x3354; int Offsets::ObjExpiry = 0x298; int Offsets::ObjCrit = 0x12C8; int Offsets::ObjCritMulti = 0x12BC; int Offsets::ObjAbilityPower = 0x122C; int Offsets::ObjAtkSpeedMulti = 0x12A0; int Offsets::ObjItemList = 0x33A0; int Offsets::ItemListItem = 0xC; int Offsets::ItemInfo = 0x20; int Offsets::ItemInfoId = 0x68; int Offsets::ViewProjMatrices = 0x030ff708; int Offsets::Renderer = 0x0310257c; int Offsets::RendererWidth = 0xC; int Offsets::RendererHeight = 0x10; int Offsets::SpellSlotLevel = 0x20; int Offsets::SpellSlotTime = 0x28; int Offsets::SpellSlotDamage = 0x94; int Offsets::SpellSlotSpellInfo = 0x13C; int Offsets::SpellInfoSpellData = 0x44; int Offsets::SpellDataSpellName = 0x6C; int Offsets::SpellDataMissileName = 0x6C; int Offsets::ObjectManager = 0x0183e1a0; int Offsets::LocalPlayer = 0x030da914; int Offsets::UnderMouseObject = 0x180f208; int Offsets::ObjectMapCount = 0x2C; int Offsets::ObjectMapRoot = 0x28; int Offsets::ObjectMapNodeNetId = 0x10; int Offsets::ObjectMapNodeObject = 0x14; int Offsets::MissileSpellInfo = 0x258; int Offsets::MissileSrcIdx = 0x2B8; int Offsets::MissileDestIdx = 0x310; int Offsets::MissileStartPos = 0x2D4; int Offsets::MissileEndPos = 0x2E0; int Offsets::MinimapObject = 0000000000; int Offsets::MinimapObjectHud = 0x88; int Offsets::MinimapHudPos = 0x60; int Offsets::MinimapHudSize = 0x68; ================================================ FILE: LView/Offsets.h ================================================ #pragma once #include "ConfigSet.h" /// Defines offsets for reading structs from league of legends memory class Offsets { public: Offsets(); static int GameTime; static int ObjIndex; static int ObjTeam; static int ObjNetworkID; static int ObjPos; static int ObjVisibility; static int ObjSpawnCount; static int ObjHealth; static int ObjMaxHealth; static int ObjMana; static int ObjArmor; static int ObjMagicRes; static int ObjBaseAtk; static int ObjBonusAtk; static int ObjMoveSpeed; static int ObjSpellBook; static int ObjName; static int ObjLvl; static int ObjExpiry; static int ObjCrit; static int ObjCritMulti; static int ObjAbilityPower; static int ObjAtkSpeedMulti; static int ObjItemList; static int ObjSrcIndex; static int ItemListItem; static int ItemInfo; static int ItemInfoId; static int ViewProjMatrices; static int Renderer; static int RendererWidth; static int RendererHeight; static int SpellSlotLevel; static int SpellSlotTime; static int SpellSlotDamage; static int SpellSlotSpellInfo; static int SpellInfoSpellData; static int SpellDataSpellName; static int SpellDataMissileName; static int ObjectManager; static int LocalPlayer; static int UnderMouseObject; static int ObjectMapCount; static int ObjectMapRoot; static int ObjectMapNodeNetId; static int ObjectMapNodeObject; static int MissileSpellInfo; static int MissileSrcIdx; static int MissileDestIdx; static int MissileStartPos; static int MissileEndPos; static int MinimapObject; static int MinimapObjectHud; static int MinimapHudPos; static int MinimapHudSize; }; ================================================ FILE: LView/Overlay.cpp ================================================ #include "Overlay.h" #include "Utils.h" #include "Structs.h" #include "LeagueMemoryReader.h" #include "Benchmark.h" #include #include #define HCheck(x, m) if(x != S_OK) { throw std::runtime_error(Character::Format("DirectX: Failed at %s. Error code: %d\n", m, MAKE_HRESULT(1, _FACDXGI, X))); } ID3D11Device* Overlay::dxDevice = NULL; ID3D11DeviceContext* Overlay::dxDeviceContext = NULL; IDXGISwapChain1* Overlay::dxSwapChain = NULL; ID3D11RenderTargetView* Overlay::dxRenderTarget = NULL; Overlay::Overlay(): configs(*(ConfigSet::Get())){ } void Overlay::Init() { // Create transparent window std::string windowClassName = Character::RandomString(10); std::string windowName = Character::RandomString(10); SetConsoleTitleA(windowName.c_str()); // Create window with random name & class name WNDCLASSEXA wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, windowClassName.c_str(), NULL }; RegisterClassExA(&wc); hWindow = CreateWindowExA( WS_EX_TOPMOST | WS_EX_NOACTIVATE | WS_EX_LAYERED, windowClassName.c_str(), windowName.c_str(), WS_POPUP, 1, 1, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), nullptr, nullptr, GetModuleHandle(0), nullptr); if (hWindow == NULL) { throw WinApiException("Failed to create overlay window"); } ShowWindow(hWindow, SW_SHOW); // Initialize Direct3D if (!CreateDeviceD3D(hWindow)) { CleanupDeviceD3D(); throw std::runtime_error("Failed to create D3D device"); } // Setup imgui context IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; io.ConfigWindowsMoveFromTitleBarOnly = true; // Setup Dear ImGui style ImGui::StyleColorsDark(); // Setup Platform/Renderer backends ImGui_ImplWin32_Init(hWindow); ImGui_ImplDX11_Init(dxDevice, dxDeviceContext); ImGui::GetStyle().Alpha = 1.f; } void Overlay::GameStart(MemSnapshot& memSnapshot) { scriptManager.LoadAll(configs.GetStr("scriptsFolder", "."), memSnapshot.player->name); } void Overlay::StartFrame() { MSG msg; ZeroMemory(&msg, sizeof(MSG)); if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } ImGui_ImplDX11_NewFrame(); ImGui_ImplWin32_NewFrame(); ImGui::NewFrame(); } void Overlay::Update(MemSnapshot& memSnapshot) { // Simple check to see if game ended if (memSnapshot.champions.size() == 0 || !isWindowVisible) return; auto timeBefore = high_resolution_clock::now(); PyGame state = PyGame::ConstructFromMemSnapshot(memSnapshot); DrawOverlayWindows(state); ExecScripts(state); DrawUI(state, memSnapshot); duration timeDuration = high_resolution_clock::now() - timeBefore; processTimeMs = timeDuration.count(); } void Overlay::RenderFrame() { static ImVec4 clear_color = ImVec4(0.f, 0.f, 0.f, 0.f); // Render auto timeBefore = high_resolution_clock::now(); ImGui::EndFrame(); ImGui::Render(); dxDeviceContext->OMSetRenderTargets(1, &dxRenderTarget, NULL); dxDeviceContext->ClearRenderTargetView(dxRenderTarget, (float*)&clear_color); ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); dxSwapChain->Present(0, 0); duration timeDuration = high_resolution_clock::now() - timeBefore; renderTimeMs = timeDuration.count(); } void Overlay::ExecScripts(PyGame & state) { for (auto& script : scriptManager.activeScripts) { if (script->enabled && script->loadError.empty() && script->execError.empty()) script->ExecUpdate(state, imguiInterface); } } void Overlay::DrawUI(PyGame& state, MemSnapshot& memSnapshot) { high_resolution_clock::time_point timeBefore; ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); ImGui::SetNextWindowSize(ImVec2(550, 680), ImGuiCond_FirstUseEver); if (!ImGui::Begin("LVIEW by leryss")) { ImGui::End(); return; } if (ImGui::BeginTabBar("LViewTabBar", ImGuiTabBarFlags_None)) { if (ImGui::BeginTabItem("Scripts##ScriptsId")) { DrawScriptSettings(state, memSnapshot); ImGui::EndTabItem(); } if (ImGui::BeginTabItem("Benchmarks##BenchmarksId")) { DrawBenchmarks(memSnapshot); ImGui::EndTabItem(); } ImGui::EndTabBar(); } ImGui::End(); } void Overlay::DrawOverlayWindows(PyGame& state) { // Draw game overlay (used for primitive rendering) auto io = ImGui::GetIO(); ImGui::SetNextWindowSize(io.DisplaySize); ImGui::SetNextWindowPos(ImVec2(0, 0)); ImGui::Begin("##Overlay", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoBackground ); state.overlay = ImGui::GetWindowDrawList(); ImGui::End(); } void Overlay::DrawScriptSettings(PyGame& state, MemSnapshot& memSnapshot) { ImGui::Text("Script Settings"); if (ImGui::Button("Save all script settings")) { scriptManager.SaveAllScriptsConfigs(); configs.SaveToFile(); } ImGui::SameLine(); if (ImGui::Button("Reload all scripts")) { GameStart(memSnapshot); } int idNode = 10000; for (std::shared_ptr