From bfc1a8d9c515c33c753a9957fd45b54d1c19be59 Mon Sep 17 00:00:00 2001 From: Billybishop <30381194+Billybishop@users.noreply.github.com> Date: Thu, 25 Mar 2021 03:52:12 -0400 Subject: [PATCH 01/19] Added Azir to orb walker and added Azir utility script Azir soldier management, soldier drawing, and champ + minions targeting logic for active soldiers. Azir autohotkey utility script to prevent orbwalker from interrupting manual spellcasts. --- GameplayScripts/commons/targeting.py | 16 +++++++- GameplayScripts/orb_walker.py | 55 ++++++++++++++++++++++++++-- UtilityScripts/azir.ahk | 39 ++++++++++++++++++++ 3 files changed, 104 insertions(+), 6 deletions(-) create mode 100644 UtilityScripts/azir.ahk diff --git a/GameplayScripts/commons/targeting.py b/GameplayScripts/commons/targeting.py index 15382db7..73298182 100644 --- a/GameplayScripts/commons/targeting.py +++ b/GameplayScripts/commons/targeting.py @@ -1,3 +1,4 @@ +from lview import * from enum import Enum class Target(Enum): @@ -43,8 +44,19 @@ 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: + range_calc = (game.distance(game.player, obj) - game.player.gameplay_radius - obj.gameplay_radius) + soldier_radius = 315 + for soldier_obj in game.others: + if not soldier_obj.is_alive or soldier_obj.is_enemy_to(game.player): + continue + + if soldier_obj.has_tags(UnitTag.Unit_Special_AzirW): + if game.distance(game.player, obj) > (range + soldier_radius): + continue + + range_calc = (game.distance(soldier_obj, obj) - soldier_obj.gameplay_radius - obj.gameplay_radius) + + if not obj.is_alive or not obj.is_visible or obj.is_ally_to(game.player) or range_calc > (range + soldier_radius): continue val = value_extractor(game.player, obj) diff --git a/GameplayScripts/orb_walker.py b/GameplayScripts/orb_walker.py index bda2c6f7..ae6ad7cc 100644 --- a/GameplayScripts/orb_walker.py +++ b/GameplayScripts/orb_walker.py @@ -22,6 +22,12 @@ targeting = TargetingConfig() +soldiers = { + #Name -> (radius, show_radius_circle, show_radius_circle_minimap, icon) + 'azirsoldier' : [315, True, False, "azir_w"] +} + + def lview_load_cfg(cfg): global key_attack_move, key_orbwalk, max_atk_speed, auto_last_hit, toggle_mode global targeting @@ -67,15 +73,52 @@ def find_minion_target(game): return target +def find_soldier_minion_target(game, soldier_obj): + atk_range = game.player.base_atk_range + game.player.gameplay_radius + soldier_atk_range = soldier_obj.base_atk_range + soldier_obj.gameplay_radius + min_health = 9999999999 + soldier_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 + soldier_atk_range and game.distance(soldier_obj, minion) < soldier_atk_range and skills.is_last_hitable(game, game.player, minion): + soldier_target = minion + min_health = minion.health + + return soldier_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: + for obj in game.others: + if not obj.is_alive or obj.is_enemy_to(game.player): + continue + + if obj.has_tags(UnitTag.Unit_Special_AzirW): + return find_soldier_minion_target(game, obj) + return find_minion_target(game) return target +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 last_attacked, alternate, last_moved global key_attack_move, key_orbwalk, max_atk_speed @@ -90,7 +133,7 @@ def lview_update(game, ui): elif not game.is_key_down(key_orbwalk): return - game.draw_button(game.world_to_screen(game.player.pos), "OrbWalking", Color.BLACK, Color.WHITE) + # game.draw_button(game.world_to_screen(game.player.pos), "OrbWalking", Color.BLACK, Color.WHITE) # Handle basic attacks self = game.player @@ -112,7 +155,11 @@ def lview_update(game, ui): if dt > b_windup_time and t - last_moved > 0.15: last_moved = t game.press_right_click() + + for obj in game.others: + if not obj.is_alive or obj.is_enemy_to(game.player): + continue - - - \ No newline at end of file + if obj.has_tags(UnitTag.Unit_Special_AzirW): + draw(game, obj, *(soldiers[obj.name])) + \ No newline at end of file diff --git a/UtilityScripts/azir.ahk b/UtilityScripts/azir.ahk new file mode 100644 index 00000000..6080178e --- /dev/null +++ b/UtilityScripts/azir.ahk @@ -0,0 +1,39 @@ +#NoEnv +#MaxHotkeysPerInterval 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 +#Persistent +#InstallKeybdHook +#InstallMouseHook + +#If leagueClientActive() + $q:: + While(GetKeyState("q","P")) { + Send, q + Sleep, 004 + } + Return + + $w:: + While(GetKeyState("w","P")) { + Send, w + Sleep, 004 + } + Return + + $e:: + While(GetKeyState("e","P")) { + Send, e + Sleep, 004 + } + Return + + $r:: + While(GetKeyState("r","P")) { + Send, r + Sleep, 004 + } + Return +#If + +leagueClientActive() { + return WinActive("ahk_class RiotWindowClass") +} From 64a59fcc4bc788dcc87353269e09350655dd6d66 Mon Sep 17 00:00:00 2001 From: Billybishop <30381194+Billybishop@users.noreply.github.com> Date: Sat, 27 Mar 2021 03:05:30 -0400 Subject: [PATCH 02/19] Update README.md updated readme with vs2019 notes --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index f664f7b0..5c4acaba 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ +# Fork Details +!!! IMPORTANT !!! This uses VS2019 and the mvc142 toolkit, please be sure your environment matches this configuration before attempting to build, and ofcourse you will still need to follow the steps outlined for the original project. Orkido on UC has documented much of what you need to do in order to get the project building from VS2019 so if you have trouble please search the LView thread for his comments on the matter. + # LViewLoL !!! IMPORTANT !!! I've noticed riot already has taken notice of this project and they have implemented a few signatures for detecting this. Don't use this as it is, if you know what you are doing you will have a clue what to modify to avoid detection. Also careful if you want to copy paste code from here to an internal it seems riot has taken an extra step in making some code signatures. From bbd5861da951ec187690dbb305519784794f8271 Mon Sep 17 00:00:00 2001 From: Billybishop <30381194+Billybishop@users.noreply.github.com> Date: Sat, 27 Mar 2021 07:25:09 -0400 Subject: [PATCH 03/19] Workaround for orb walker and small fix for range checks when azir soldiers up Merged bckd00r and pureSadness changes (evade and buffmanager). Also integrated damage_calculator into skills module. Then added really dumb workaround to lower the damage multiplier in damage_calculator.calculate_damage because last hits are always too early unless this is implemented - at least on Azir. I might be losing my mind. Updated azir range values to better match League data. --- GameplayScripts/commons/damage_calculator.py | 5 +- GameplayScripts/commons/skills.py | 12 +- GameplayScripts/commons/targeting.py | 15 ++- GameplayScripts/evade.py | 122 +++++++++++++++++++ GameplayScripts/orb_walker.py | 4 +- LView/BuffInstance.cpp | 1 + LView/BuffInstance.h | 13 ++ LView/GameObject.cpp | 43 +++++++ LView/GameObject.h | 7 ++ LView/LView.vcxproj | 6 +- LView/LView.vcxproj.filters | 6 + LView/Offsets.cpp | 29 +++-- LView/Offsets.h | 7 ++ LView/PyStructs.h | 7 ++ LView/config.ini | 13 +- LView/imgui.ini | 10 +- 16 files changed, 274 insertions(+), 26 deletions(-) create mode 100644 GameplayScripts/evade.py create mode 100644 LView/BuffInstance.cpp create mode 100644 LView/BuffInstance.h diff --git a/GameplayScripts/commons/damage_calculator.py b/GameplayScripts/commons/damage_calculator.py index 7e6bfca7..137d9e27 100644 --- a/GameplayScripts/commons/damage_calculator.py +++ b/GameplayScripts/commons/damage_calculator.py @@ -60,6 +60,9 @@ def calculate_damage(self, source, target): damage_multiplier = 100.0 / (100.0 + resistance_value) else: damage_multiplier = 2.0 - 100.0 / (100.0 - resistance_value) + + # BB: Temp workaround until we figure out wtf is wrong with last hitting - works well on Azir + damage_multiplier = 100/(100+(resistance_value*0.70)) dealt_damage = ( self.base_damage @@ -71,7 +74,7 @@ def calculate_damage(self, source, target): 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) + dealt_damage = dealt_damage * (1.1 + self.missing_health_scale_multiplier) else: dealt_damage = (dealt_damage * (1.0 + self.missing_health_scale_multiplier - self.missing_health_scale_multiplier diff --git a/GameplayScripts/commons/skills.py b/GameplayScripts/commons/skills.py index f4173701..674ec7f5 100644 --- a/GameplayScripts/commons/skills.py +++ b/GameplayScripts/commons/skills.py @@ -1,12 +1,17 @@ from lview import * import math, itertools, time from . import items +from commons.damage_calculator import DamageSpecification +from commons.damage_calculator import DamageType Version = "experimental version" MissileToSpell = {} Spells = {} ChampionSpells = {} +damageCalc = DamageSpecification() +damageType = DamageType(2); + class SFlag: Targeted = 1 Line = 2 @@ -298,11 +303,14 @@ 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 + + damageCalc.damage_type = damageType + damageCalc.base_damage = 0 - hit_dmg = items.get_onhit_physical(player, enemy) + items.get_onhit_magical(player, enemy) + hit_dmg = damageCalc.calculate_damage(player, enemy) + 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 diff --git a/GameplayScripts/commons/targeting.py b/GameplayScripts/commons/targeting.py index 73298182..4769d6ff 100644 --- a/GameplayScripts/commons/targeting.py +++ b/GameplayScripts/commons/targeting.py @@ -44,8 +44,10 @@ def find_target(self, game, array, range, value_extractor): target = None min = 99999999 for obj in array: + is_soldier_targeting = False range_calc = (game.distance(game.player, obj) - game.player.gameplay_radius - obj.gameplay_radius) - soldier_radius = 315 + soldier_radius = 310 + soldier_affect_range = 690 for soldier_obj in game.others: if not soldier_obj.is_alive or soldier_obj.is_enemy_to(game.player): continue @@ -55,10 +57,21 @@ def find_target(self, game, array, range, value_extractor): continue range_calc = (game.distance(soldier_obj, obj) - soldier_obj.gameplay_radius - obj.gameplay_radius) + is_soldier_targeting = True + + if not obj.is_alive or not obj.is_visible or obj.is_ally_to(game.player) or range_calc > (range + soldier_radius): continue + if is_soldier_targeting == True: + if not obj.is_alive or not obj.is_visible or obj.is_ally_to(game.player) or range_calc > soldier_radius: + continue + + if is_soldier_targeting == False: + if not obj.is_alive or not obj.is_visible or obj.is_ally_to(game.player) or range_calc > range: + continue + val = value_extractor(game.player, obj) if val < min: min = val diff --git a/GameplayScripts/evade.py b/GameplayScripts/evade.py new file mode 100644 index 00000000..35082e72 --- /dev/null +++ b/GameplayScripts/evade.py @@ -0,0 +1,122 @@ +from lview import * +from commons.targeting import TargetingConfig +from time import time +import itertools, math +from commons.skills import * +from copy import copy +from math import * + +lview_script_info = { + "script": "Evader", + "author": "https://github.com/bckd00r / bckd00r", + "description": "Evade module with LViewLoL" +} + +bound_max = 0 + +evades = False +evade_min_range = 0 + +targeting = TargetingConfig() + +def clamp_norm_2d(v, n_max): + vx = v.x + vy = v.y + vz = v.z + n = sqrt(pow(vx, float(2)) + pow(vz, float(2))) + f = min(n, n_max) / n + return Vec3(f * vx, vy,f * vz) + + +def PointOnLineSegment(pt1, pt2, pt, epsilon = 0.001): + if (pt.x - max(pt1.x, pt2.x) > epsilon or + min(pt1.x, pt2.x) - pt.x > epsilon or + pt.y - max(pt1.y, pt2.y) > epsilon or + min(pt1.y, pt2.y) - pt.y > epsilon): + return False + if abs(pt2.x - pt1.x) < epsilon: + return abs(pt1.x - pt.x) < epsilon or abs(pt2.x - pt.x) < epsilon + if abs(pt2.y - pt1.y) < epsilon: + return abs(pt1.y - pt.y) < epsilon or abs(pt2.y - pt.y) < epsilon + + x = pt1.x + (pt.y - pt1.y) * (pt2.x - pt1.x) / (pt2.y - pt1.y) + y = pt1.y + (pt.x - pt1.x) * (pt2.y - pt1.y) / (pt2.x - pt1.x) + + return abs(pt.x - x) < epsilon or abs(pt.y - y) < epsilon + +def isLeft(a, b, c): + return ((b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)) > 0 + +def lview_load_cfg(cfg): + global evades, evade_min_range + evades = cfg.get_bool("evades", True) + evade_min_range = cfg.get_float("evade_min_range", 500) + +def lview_save_cfg(cfg): + global evades, evade_min_range + cfg.set_bool("evades", evades) + cfg.set_float("evade_min_range", evade_min_range) + +def lview_draw_settings(game, ui): + global evades, evade_min_range + ui.separator() + ui.text("Evader (Experimental)") + evades = ui.checkbox("Evade skills", evades) + evade_min_range = ui.dragfloat("Minimum evade range", evade_min_range, 100, 0, 3000) + draw_prediction_info(game, ui) + + +def evade_skills(game, player): + global targeting, evades, evade_min_range + color = Color.WHITE + for missile in game.missiles: + if missile.is_ally_to(game.player): + 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() + dodge_pos = game.player.pos + 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 + p = game.world_to_screen(game.player.pos) + br = game.player.gameplay_radius + direction = Vec3(end_pos.x - start_pos.x, end_pos.y - start_pos.y, end_pos.z - start_pos.y) + pos3 = Vec3(end_pos.x + direction.x * float(1.0), end_pos.y + direction.y, end_pos.z + direction.z * -float(1.0)) + pos4 = Vec3(end_pos.x + direction.x * -float(1.0), end_pos.y + direction.y, end_pos.z + direction.z * float(1.0)) + direction2 = Vec3(pos3.x - pos4.x, pos3.y - pos4.y, pos3.z - pos4.z) + direction2 = clamp_norm_2d(direction2, br) + direction3 = Vec3(0, 0, 0) + direction3.x = -direction2.x + direction3.y = -direction2.y + direction3.z = -direction2.z + if spell.flags & SFlag.Area: + end_pos.y = game.map.height_at(end_pos.x, end_pos.z) + + if PointOnLineSegment(game.world_to_screen(start_pos), game.world_to_screen(end_pos), game.world_to_screen(dodge_pos), br): + r = game.get_spell_info(spell.name).cast_radius + percent_done = missile.start_pos.distance(curr_pos)/missile.start_pos.distance(end_pos) + p.y -= 50 + game.draw_button(p, "Evade: ON", Color.GRAY, Color.YELLOW, 100) + if isLeft(game.world_to_screen(start_pos), game.world_to_screen(end_pos), game.world_to_screen(dodge_pos)): + direction4 = direction3 + else: + direction4 = direction2 + evadePos = Vec3(dodge_pos.x + direction4.x, dodge_pos.y + direction4.y, dodge_pos.z + direction4.z) + old_cpos = game.get_cursor() + game.move_cursor(game.world_to_screen(evadePos)) + game.press_right_click() + +def lview_update(game, ui): + global evades + + player = game.player + + if evades: + evade_skills(game, player) + + \ No newline at end of file diff --git a/GameplayScripts/orb_walker.py b/GameplayScripts/orb_walker.py index ae6ad7cc..55aa33ac 100644 --- a/GameplayScripts/orb_walker.py +++ b/GameplayScripts/orb_walker.py @@ -15,6 +15,7 @@ key_attack_move = 0 key_orbwalk = 0 auto_last_hit = False +soldier_target = None max_atk_speed = 0 toggle_mode = False @@ -24,7 +25,7 @@ soldiers = { #Name -> (radius, show_radius_circle, show_radius_circle_minimap, icon) - 'azirsoldier' : [315, True, False, "azir_w"] + 'azirsoldier' : [310, True, False, "azir_w"] } @@ -87,6 +88,7 @@ def find_soldier_minion_target(game, soldier_obj): def get_target(game): global auto_last_hit + global soldier_target target = targeting.get_target(game, game.player.base_atk_range + game.player.gameplay_radius) diff --git a/LView/BuffInstance.cpp b/LView/BuffInstance.cpp new file mode 100644 index 00000000..84265549 --- /dev/null +++ b/LView/BuffInstance.cpp @@ -0,0 +1 @@ +#include "BuffInstance.h" \ No newline at end of file diff --git a/LView/BuffInstance.h b/LView/BuffInstance.h new file mode 100644 index 00000000..a9547df2 --- /dev/null +++ b/LView/BuffInstance.h @@ -0,0 +1,13 @@ +#pragma once +#include + +class BuffInstance +{ +public: + + BuffInstance(std::string buffname, float starttime, float endtime) : name(buffname), startTime(starttime), endTime(endtime) {} + + std::string name; + float startTime; + float endTime; +}; \ No newline at end of file diff --git a/LView/GameObject.cpp b/LView/GameObject.cpp index c0f29220..845767ca 100644 --- a/LView/GameObject.cpp +++ b/LView/GameObject.cpp @@ -183,6 +183,40 @@ void GameObject::LoadChampionFromMem(DWORD base, HANDLE hProcess, bool deepLoad) itemSlots[i].stats = GameData::GetItemInfoById(id); } + // Read Buffs + DWORD buffArrayBgn = Mem::ReadDWORD(hProcess, address + Offsets::ObjBuffManager + Offsets::BuffManagerEntriesArray); + if (buffArrayBgn != 0) //reads 0 sometimes + { + buffVector.clear(); + + for (int i = 0; i < 50; i++) //idk what size is good + { + DWORD buffInstancePtr = buffArrayBgn + i * 4; + DWORD buffInstance = Mem::ReadDWORD(hProcess, buffInstancePtr); + + Mem::Read(hProcess, buffInstance, buff, sizeBuff); + + if (buffInstance == 0) + continue; + + DWORD buffInfo = Mem::ReadDWORDFromBuffer(buff, 0x8); + + if (buffInfo < 10) + continue; + + char buffnamebuffer[240]; + Mem::Read(hProcess, buffInfo + Offsets::BuffName, buffnamebuffer, 240); + + float buffStartTime; + float buffEndTime; + + memcpy(&buffStartTime, &buff[Offsets::BuffEntryBuffStartTime], sizeof(float)); + memcpy(&buffEndTime, &buff[Offsets::BuffEntryBuffEndTime], sizeof(float)); + + buffVector.push_back(BuffInstance(buffnamebuffer, buffStartTime, buffEndTime)); + } + } + // Read level level = Mem::ReadDWORD(hProcess, base + Offsets::ObjLvl); } @@ -212,6 +246,15 @@ list GameObject::ItemsToPyList() { return l; } +list GameObject::BuffsToPyList() { + list buffList; + for (auto &buffs : buffVector) + { + buffList.append(boost::ref(buffs)); + } + return buffList; +} + // Missile stuff void GameObject::LoadMissileFromMem(DWORD base, HANDLE hProcess, bool deepLoad) { diff --git a/LView/GameObject.h b/LView/GameObject.h index e2fd94ed..9027c506 100644 --- a/LView/GameObject.h +++ b/LView/GameObject.h @@ -11,6 +11,7 @@ #include "Spell.h" #include "SpellInterface.h" #include "ItemSlot.h" +#include "BuffInstance.h" #include #include @@ -98,6 +99,7 @@ class GameObject: MemoryLoadable, SpellInterface { bool IsRanged(); list ItemsToPyList(); + list BuffsToPyList(); Spell Q = Spell(SpellSlot::Q); Spell W = Spell(SpellSlot::W); @@ -108,6 +110,11 @@ class GameObject: MemoryLoadable, SpellInterface { DWORD level; ItemSlot itemSlots[6]; + + std::vector buffVector; + + + private: static DWORD spellSlotPointerBuffer[6]; static BYTE itemListBuffer[0x100]; diff --git a/LView/LView.vcxproj b/LView/LView.vcxproj index f391006d..4569269e 100644 --- a/LView/LView.vcxproj +++ b/LView/LView.vcxproj @@ -114,7 +114,7 @@ true _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - F:\Github\LViewLoL\LView\external_includes;%(AdditionalIncludeDirectories) + $(SolutionDir)\LView\boost;$(SolutionDir)\LView\external_includes;%(AdditionalIncludeDirectories) Console @@ -158,7 +158,7 @@ true NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true - F:\Github\LViewLoL\LView\external_includes;%(AdditionalIncludeDirectories) + $(SolutionDir)\LView\boost;$(SolutionDir)\LView\external_includes;%(AdditionalIncludeDirectories) Console @@ -171,6 +171,7 @@ + @@ -201,6 +202,7 @@ + diff --git a/LView/LView.vcxproj.filters b/LView/LView.vcxproj.filters index 3c502e25..d0c498ae 100644 --- a/LView/LView.vcxproj.filters +++ b/LView/LView.vcxproj.filters @@ -135,6 +135,9 @@ Source Files\Structs\GameRelated\Others + + Source Files\Structs\GameRelated\Others + @@ -242,5 +245,8 @@ Source Files\Core + + Source Files\Structs\GameRelated\Others + \ No newline at end of file diff --git a/LView/Offsets.cpp b/LView/Offsets.cpp index 225ef3b7..e7e93ee0 100644 --- a/LView/Offsets.cpp +++ b/LView/Offsets.cpp @@ -3,6 +3,12 @@ Offsets::Offsets() {}; int Offsets::GameTime = 0x02f8d1dc; +int Offsets::ViewProjMatrices = 0x2FB7998; +int Offsets::Renderer = 0x02fba770; +int Offsets::ObjectManager = 0x016f8678; +int Offsets::LocalPlayer = 0x02f9512c; +int Offsets::UnderMouseObject = 0x2346840; +int Offsets::MinimapObject = 0x02f94b0c; int Offsets::ObjIndex = 0x20; int Offsets::ObjTeam = 0x4C; @@ -33,8 +39,6 @@ int Offsets::ItemListItem = 0xC; int Offsets::ItemInfo = 0x20; int Offsets::ItemInfoId = 0x68; -int Offsets::ViewProjMatrices = 0x2fb7998; -int Offsets::Renderer = 0x02fba770; int Offsets::RendererWidth = 0x10; int Offsets::RendererHeight = 0x14; @@ -46,23 +50,24 @@ int Offsets::SpellInfoSpellData = 0x44; int Offsets::SpellDataSpellName = 0x64; int Offsets::SpellDataMissileName = 0x64; -int Offsets::ObjectManager = 0x016f8678; -int Offsets::LocalPlayer = 0x02f9512c; -int Offsets::UnderMouseObject = 0x2346840; - -int Offsets::ObjectMapCount = 0x2C; -int Offsets::ObjectMapRoot = 0x28; -int Offsets::ObjectMapNodeNetId = 0x10; -int Offsets::ObjectMapNodeObject = 0x14; - int Offsets::MissileSpellInfo = 0x230; int Offsets::MissileSrcIdx = 0x290; int Offsets::MissileDestIdx = 0x2E8; int Offsets::MissileStartPos = 0x2A8; int Offsets::MissileEndPos = 0x2B4; -int Offsets::MinimapObject = 0x02f94b0c; +int Offsets::ObjectMapCount = 0x2C; +int Offsets::ObjectMapRoot = 0x28; +int Offsets::ObjectMapNodeNetId = 0x10; +int Offsets::ObjectMapNodeObject = 0x14; int Offsets::MinimapObjectHud = 0x88; int Offsets::MinimapHudPos = 0x60; int Offsets::MinimapHudSize = 0x68; + +int Offsets::ObjBuffManager = 0x2178; +int Offsets::BuffManagerEntriesArray = 0x10; +int Offsets::BuffEntryBuff = 0x8; +int Offsets::BuffEntryBuffStartTime = 0xC; +int Offsets::BuffEntryBuffEndTime = 0x10; +int Offsets::BuffName = 0x8; \ No newline at end of file diff --git a/LView/Offsets.h b/LView/Offsets.h index 42bf7a8b..b923157a 100644 --- a/LView/Offsets.h +++ b/LView/Offsets.h @@ -70,4 +70,11 @@ class Offsets { static int MinimapObjectHud; static int MinimapHudPos; static int MinimapHudSize; + + static int ObjBuffManager; + static int BuffManagerEntriesArray; + static int BuffEntryBuff; + static int BuffEntryBuffStartTime; + static int BuffEntryBuffEndTime; + static int BuffName; }; \ No newline at end of file diff --git a/LView/PyStructs.h b/LView/PyStructs.h index a9f2c7a4..79ee030a 100644 --- a/LView/PyStructs.h +++ b/LView/PyStructs.h @@ -46,6 +46,12 @@ BOOST_PYTHON_MODULE(lview) { .def_readonly("movement_speed_percent", &ItemSlot::GetMovementSpeedPercent) ; + class_("Buff", init()) + .def_readonly("name", &BuffInstance::name) + .def_readonly("start_time", &BuffInstance::startTime) + .def_readonly("end_time", &BuffInstance::endTime) + ; + class_("Spell", init()) .def_readonly("name", &Spell::name) .def_readonly("slot", &Spell::slot) @@ -122,6 +128,7 @@ BOOST_PYTHON_MODULE(lview) { .def_readonly("D", &GameObject::D) .def_readonly("F", &GameObject::F) .def_readonly("items", &GameObject::ItemsToPyList) + .def_readonly("buffs", &GameObject::BuffsToPyList) .def_readonly("lvl", &GameObject::level) .def("get_summoner_spell", &GameObject::GetSummonerSpell, return_value_policy()) diff --git a/LView/config.ini b/LView/config.ini index 26ed51e8..8c037d50 100644 --- a/LView/config.ini +++ b/LView/config.ini @@ -1,4 +1,4 @@ -::scriptsFolder=F:\Github\LViewLoL\GameplayScripts +::scriptsFolder=C:\Users\Default.DESKTOP-EELLM56\Documents\GitHub\LViewLoL-base\GameplayScripts Auto Smite::enable_key=41 Auto Smite::enabled=1 Auto Smite::show_smitable=1 @@ -19,14 +19,23 @@ Drawings::skillshots_predict=0 Drawings::skillshots_show_ally=1 Drawings::skillshots_show_enemy=1 Drawings::turret_ranges=1 +Evader::enabled=1 +Evader::evade_min_range=500.000000 +Evader::evades=1 +Execution notifier::enabled=1 Map Awareness::bound_max=4000.000000 Map Awareness::enabled=1 +Map Awareness::show_alert_enemy_close=1 +Map Awareness::show_last_enemy_pos=1 +Map Awareness::show_last_enemy_pos_minimap=1 Object Explorer::enabled=1 Orbwalker::auto_last_hit=1 Orbwalker::enabled=1 Orbwalker::key_attack_move=30 Orbwalker::key_orbwalk=57 Orbwalker::max_atk_speed=2.322000 +Orbwalker::target_jungle=1 +Orbwalker::target_minions=0 Orbwalker::targeting_target=1 Orbwalker::toggle_mode=0 Spell Tracker::enabled=1 @@ -42,4 +51,4 @@ Vision Tracker::show_clones=1 Vision Tracker::show_traps=1 Vision Tracker::show_wards=1 Vision Tracker::traps={"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"]} -Vision Tracker::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"]} \ No newline at end of file +Vision Tracker::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"]} diff --git a/LView/imgui.ini b/LView/imgui.ini index 28fcc59d..6f82e161 100644 --- a/LView/imgui.ini +++ b/LView/imgui.ini @@ -74,9 +74,9 @@ Size=502,659 Collapsed=0 [Window][Object Viewer] -Pos=129,25 +Pos=1840,252 Size=664,844 -Collapsed=0 +Collapsed=1 [Window][Champion to track] Pos=60,60 @@ -109,9 +109,9 @@ Size=569,442 Collapsed=0 [Window][LVIEW by leryss] -Pos=1138,21 -Size=690,889 -Collapsed=0 +Pos=1686,442 +Size=690,885 +Collapsed=1 [Table][0xBF3CBA1D,3] Column 0 Weight=1.0000 From 9a886efee660c952d5afd9d433163bae541ccd2f Mon Sep 17 00:00:00 2001 From: Billybishop <30381194+Billybishop@users.noreply.github.com> Date: Sat, 27 Mar 2021 09:01:24 -0400 Subject: [PATCH 04/19] Added orbwalking fixes Added a couple fixes to orb walker, targeting, and damage calculator - used Azir as reference. Note: set DamageType(2) in skills.py for AP if you plan on playing Azir, otherwise leave it on DamageType(1) which is AD. --- GameplayScripts/commons/damage_calculator.py | 2 +- GameplayScripts/commons/skills.py | 2 +- GameplayScripts/commons/targeting.py | 11 ++++------- GameplayScripts/orb_walker.py | 10 +++++----- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/GameplayScripts/commons/damage_calculator.py b/GameplayScripts/commons/damage_calculator.py index 137d9e27..faa63e72 100644 --- a/GameplayScripts/commons/damage_calculator.py +++ b/GameplayScripts/commons/damage_calculator.py @@ -62,7 +62,7 @@ def calculate_damage(self, source, target): damage_multiplier = 2.0 - 100.0 / (100.0 - resistance_value) # BB: Temp workaround until we figure out wtf is wrong with last hitting - works well on Azir - damage_multiplier = 100/(100+(resistance_value*0.70)) + damage_multiplier = 100/(100+(resistance_value*0.82)) dealt_damage = ( self.base_damage diff --git a/GameplayScripts/commons/skills.py b/GameplayScripts/commons/skills.py index 674ec7f5..b88050ba 100644 --- a/GameplayScripts/commons/skills.py +++ b/GameplayScripts/commons/skills.py @@ -10,7 +10,7 @@ ChampionSpells = {} damageCalc = DamageSpecification() -damageType = DamageType(2); +damageType = DamageType(1); class SFlag: Targeted = 1 diff --git a/GameplayScripts/commons/targeting.py b/GameplayScripts/commons/targeting.py index 4769d6ff..f0e3d0dc 100644 --- a/GameplayScripts/commons/targeting.py +++ b/GameplayScripts/commons/targeting.py @@ -44,10 +44,12 @@ def find_target(self, game, array, range, value_extractor): target = None min = 99999999 for obj in array: + is_soldier_targeting = False range_calc = (game.distance(game.player, obj) - game.player.gameplay_radius - obj.gameplay_radius) - soldier_radius = 310 - soldier_affect_range = 690 + soldier_affect_range = 700 + soldier_radius = 345 + for soldier_obj in game.others: if not soldier_obj.is_alive or soldier_obj.is_enemy_to(game.player): continue @@ -59,11 +61,6 @@ def find_target(self, game, array, range, value_extractor): range_calc = (game.distance(soldier_obj, obj) - soldier_obj.gameplay_radius - obj.gameplay_radius) is_soldier_targeting = True - - - if not obj.is_alive or not obj.is_visible or obj.is_ally_to(game.player) or range_calc > (range + soldier_radius): - continue - if is_soldier_targeting == True: if not obj.is_alive or not obj.is_visible or obj.is_ally_to(game.player) or range_calc > soldier_radius: continue diff --git a/GameplayScripts/orb_walker.py b/GameplayScripts/orb_walker.py index 55aa33ac..70d7e428 100644 --- a/GameplayScripts/orb_walker.py +++ b/GameplayScripts/orb_walker.py @@ -25,7 +25,7 @@ soldiers = { #Name -> (radius, show_radius_circle, show_radius_circle_minimap, icon) - 'azirsoldier' : [310, True, False, "azir_w"] + 'azirsoldier' : [345, True, False, "azir_w"] } @@ -68,19 +68,19 @@ def find_minion_target(game): 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): + if minion.is_visible and 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 find_soldier_minion_target(game, soldier_obj): - atk_range = game.player.base_atk_range + game.player.gameplay_radius - soldier_atk_range = soldier_obj.base_atk_range + soldier_obj.gameplay_radius + soldier_affect_range = 700 + soldier_radius = 345 min_health = 9999999999 soldier_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 + soldier_atk_range and game.distance(soldier_obj, minion) < soldier_atk_range and skills.is_last_hitable(game, game.player, minion): + if minion.is_visible and minion.is_enemy_to(game.player) and minion.is_alive and minion.health < min_health and game.distance(game.player, minion) < soldier_affect_range + soldier_radius and game.distance(soldier_obj, minion) < soldier_radius and skills.is_last_hitable(game, game.player, minion): soldier_target = minion min_health = minion.health From 37a6f7c2607953421cedf9a6f13e13c0070ac310 Mon Sep 17 00:00:00 2001 From: Billybishop <30381194+Billybishop@users.noreply.github.com> Date: Sat, 27 Mar 2021 09:05:49 -0400 Subject: [PATCH 05/19] Update README.md updated readme for python setup pitfall --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 5c4acaba..3b339e0b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # Fork Details !!! IMPORTANT !!! This uses VS2019 and the mvc142 toolkit, please be sure your environment matches this configuration before attempting to build, and ofcourse you will still need to follow the steps outlined for the original project. Orkido on UC has documented much of what you need to do in order to get the project building from VS2019 so if you have trouble please search the LView thread for his comments on the matter. +Note: In some few cases depending on your Windows installation or whether you had Python installed beforehand your Python might not have properly set the system environment variables. If you run into the case where you are able to successfully compile the app but it instantly closes after running it (be sure to have followed the steps properly), then you may need to set the Python path in your environment variables manually; to be safe, add the path to the User's 'Path', System's 'Path' variables, and then add a PYTHONHOME variable if you don't have it and point it to your root Python directory. + # LViewLoL !!! IMPORTANT !!! I've noticed riot already has taken notice of this project and they have implemented a few signatures for detecting this. Don't use this as it is, if you know what you are doing you will have a clue what to modify to avoid detection. Also careful if you want to copy paste code from here to an internal it seems riot has taken an extra step in making some code signatures. From 7e8c3e7bf923d72d63d5038f10c05fca588283a4 Mon Sep 17 00:00:00 2001 From: Billybishop <30381194+Billybishop@users.noreply.github.com> Date: Sat, 27 Mar 2021 09:07:08 -0400 Subject: [PATCH 06/19] Update README.md ... --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3b339e0b..ebd7ca4a 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Fork Details !!! IMPORTANT !!! This uses VS2019 and the mvc142 toolkit, please be sure your environment matches this configuration before attempting to build, and ofcourse you will still need to follow the steps outlined for the original project. Orkido on UC has documented much of what you need to do in order to get the project building from VS2019 so if you have trouble please search the LView thread for his comments on the matter. -Note: In some few cases depending on your Windows installation or whether you had Python installed beforehand your Python might not have properly set the system environment variables. If you run into the case where you are able to successfully compile the app but it instantly closes after running it (be sure to have followed the steps properly), then you may need to set the Python path in your environment variables manually; to be safe, add the path to the User's 'Path', System's 'Path' variables, and then add a PYTHONHOME variable if you don't have it and point it to your root Python directory. +Note: In some few cases depending on your Windows installation or whether you had Python installed beforehand your Python might not have properly set the system environment variables. If you run into the case where you are able to successfully compile the app but it instantly closes after running it (be sure to have followed the steps properly), then you may need to set the Python path in your environment variables manually; to be safe, add the root python path and the root python /scripts directory to the User's 'Path', System's 'Path' variables, and then add a PYTHONHOME variable if you don't have it in your User variables and point it to your root Python directory. # LViewLoL !!! IMPORTANT !!! I've noticed riot already has taken notice of this project and they have implemented a few signatures for detecting this. Don't use this as it is, if you know what you are doing you will have a clue what to modify to avoid detection. Also careful if you want to copy paste code from here to an internal it seems riot has taken an extra step in making some code signatures. From 081d990ff7b701eceacc7e0887f0719664e6dbe3 Mon Sep 17 00:00:00 2001 From: Billybishop <30381194+Billybishop@users.noreply.github.com> Date: Sat, 27 Mar 2021 11:06:29 -0400 Subject: [PATCH 07/19] Attempt to fix last hitting and targeting This is a patch that is trying to fix targeting and orbwalking issues seen in last version, should also slightly improve azir soldier behavior due to updated data. --- GameplayScripts/commons/damage_calculator.py | 4 ++-- GameplayScripts/commons/targeting.py | 19 ++++++++++++------- GameplayScripts/orb_walker.py | 6 +++--- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/GameplayScripts/commons/damage_calculator.py b/GameplayScripts/commons/damage_calculator.py index faa63e72..ab11996d 100644 --- a/GameplayScripts/commons/damage_calculator.py +++ b/GameplayScripts/commons/damage_calculator.py @@ -16,7 +16,7 @@ class DamageSpecification: # 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 + missing_health_max_scale_multiplier = 0.33 # Damage increased by missing_health_multiplier * enemy_missing_health missing_health_multiplier = 0.0 @@ -74,7 +74,7 @@ def calculate_damage(self, source, target): percent_current_health = target.health / target.max_health if percent_current_health <= self.missing_health_max_scale_multiplier: - dealt_damage = dealt_damage * (1.1 + self.missing_health_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 diff --git a/GameplayScripts/commons/targeting.py b/GameplayScripts/commons/targeting.py index f0e3d0dc..4e4c595f 100644 --- a/GameplayScripts/commons/targeting.py +++ b/GameplayScripts/commons/targeting.py @@ -43,33 +43,38 @@ def get_target(self, game, range): def find_target(self, game, array, range, value_extractor): target = None min = 99999999 + val = 0 for obj in array: + soldier = None is_soldier_targeting = False range_calc = (game.distance(game.player, obj) - game.player.gameplay_radius - obj.gameplay_radius) - soldier_affect_range = 700 - soldier_radius = 345 + soldier_affect_range = 660 + soldier_radius = 440 for soldier_obj in game.others: if not soldier_obj.is_alive or soldier_obj.is_enemy_to(game.player): continue if soldier_obj.has_tags(UnitTag.Unit_Special_AzirW): - if game.distance(game.player, obj) > (range + soldier_radius): + if game.distance(game.player, obj) > (soldier_affect_range + soldier_radius): continue - range_calc = (game.distance(soldier_obj, obj) - soldier_obj.gameplay_radius - obj.gameplay_radius) + soldier = soldier_obj + range_calc = (game.distance(soldier_obj, obj))# - soldier_obj.gameplay_radius - obj.gameplay_radius) is_soldier_targeting = True if is_soldier_targeting == True: if not obj.is_alive or not obj.is_visible or obj.is_ally_to(game.player) or range_calc > soldier_radius: continue - - if is_soldier_targeting == False: + + val = value_extractor(soldier, obj) + else: if not obj.is_alive or not obj.is_visible or obj.is_ally_to(game.player) or range_calc > range: continue + + val = value_extractor(game.player, obj) - val = value_extractor(game.player, obj) if val < min: min = val target = obj diff --git a/GameplayScripts/orb_walker.py b/GameplayScripts/orb_walker.py index 70d7e428..7c8d0286 100644 --- a/GameplayScripts/orb_walker.py +++ b/GameplayScripts/orb_walker.py @@ -75,7 +75,7 @@ def find_minion_target(game): return target def find_soldier_minion_target(game, soldier_obj): - soldier_affect_range = 700 + soldier_affect_range = 660 soldier_radius = 345 min_health = 9999999999 soldier_target = None @@ -94,7 +94,7 @@ def get_target(game): if not target and auto_last_hit: for obj in game.others: - if not obj.is_alive or obj.is_enemy_to(game.player): + if not obj.is_alive or obj.is_ally_to(game.player): continue if obj.has_tags(UnitTag.Unit_Special_AzirW): @@ -142,7 +142,7 @@ def lview_update(game, ui): 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 + c_atk_time = (1.0/atk_speed)+0.10 max_atk_time = 1.0/max_atk_speed target = get_target(game) From f8768a1c1544e2ad5bb4c133ca2f0c1f1f20b554 Mon Sep 17 00:00:00 2001 From: Billybishop <30381194+Billybishop@users.noreply.github.com> Date: Sat, 27 Mar 2021 11:12:04 -0400 Subject: [PATCH 08/19] Update Azir data updated azir soldier radius and effective range data --- GameplayScripts/commons/targeting.py | 2 +- GameplayScripts/orb_walker.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/GameplayScripts/commons/targeting.py b/GameplayScripts/commons/targeting.py index 4e4c595f..d2346838 100644 --- a/GameplayScripts/commons/targeting.py +++ b/GameplayScripts/commons/targeting.py @@ -50,7 +50,7 @@ def find_target(self, game, array, range, value_extractor): is_soldier_targeting = False range_calc = (game.distance(game.player, obj) - game.player.gameplay_radius - obj.gameplay_radius) soldier_affect_range = 660 - soldier_radius = 440 + soldier_radius = 375 for soldier_obj in game.others: if not soldier_obj.is_alive or soldier_obj.is_enemy_to(game.player): diff --git a/GameplayScripts/orb_walker.py b/GameplayScripts/orb_walker.py index 7c8d0286..581b0f19 100644 --- a/GameplayScripts/orb_walker.py +++ b/GameplayScripts/orb_walker.py @@ -25,7 +25,7 @@ soldiers = { #Name -> (radius, show_radius_circle, show_radius_circle_minimap, icon) - 'azirsoldier' : [345, True, False, "azir_w"] + 'azirsoldier' : [375, True, False, "azir_w"] } @@ -76,7 +76,7 @@ def find_minion_target(game): def find_soldier_minion_target(game, soldier_obj): soldier_affect_range = 660 - soldier_radius = 345 + soldier_radius = 375 min_health = 9999999999 soldier_target = None for minion in game.minions: From 77311fa1b931cb32106c3a1891fe7bffa6b8c093 Mon Sep 17 00:00:00 2001 From: Billybishop <30381194+Billybishop@users.noreply.github.com> Date: Sat, 27 Mar 2021 12:48:44 -0400 Subject: [PATCH 09/19] QoL Azir stuff QoL azir soldier stuff to assist orbwalker --- GameplayScripts/commons/targeting.py | 10 ++++------ GameplayScripts/orb_walker.py | 8 ++++---- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/GameplayScripts/commons/targeting.py b/GameplayScripts/commons/targeting.py index d2346838..7bdfeb1b 100644 --- a/GameplayScripts/commons/targeting.py +++ b/GameplayScripts/commons/targeting.py @@ -50,7 +50,7 @@ def find_target(self, game, array, range, value_extractor): is_soldier_targeting = False range_calc = (game.distance(game.player, obj) - game.player.gameplay_radius - obj.gameplay_radius) soldier_affect_range = 660 - soldier_radius = 375 + soldier_radius = 310 for soldier_obj in game.others: if not soldier_obj.is_alive or soldier_obj.is_enemy_to(game.player): @@ -61,19 +61,17 @@ def find_target(self, game, array, range, value_extractor): continue soldier = soldier_obj - range_calc = (game.distance(soldier_obj, obj))# - soldier_obj.gameplay_radius - obj.gameplay_radius) + range_calc = (game.distance(soldier_obj, obj) - obj.gameplay_radius) is_soldier_targeting = True if is_soldier_targeting == True: if not obj.is_alive or not obj.is_visible or obj.is_ally_to(game.player) or range_calc > soldier_radius: continue - - val = value_extractor(soldier, obj) else: if not obj.is_alive or not obj.is_visible or obj.is_ally_to(game.player) or range_calc > range: continue - - val = value_extractor(game.player, obj) + + val = value_extractor(game.player, obj) if val < min: min = val diff --git a/GameplayScripts/orb_walker.py b/GameplayScripts/orb_walker.py index 581b0f19..0811d5b1 100644 --- a/GameplayScripts/orb_walker.py +++ b/GameplayScripts/orb_walker.py @@ -25,7 +25,7 @@ soldiers = { #Name -> (radius, show_radius_circle, show_radius_circle_minimap, icon) - 'azirsoldier' : [375, True, False, "azir_w"] + 'azirsoldier' : [310, True, False, "azir_w"] } @@ -76,11 +76,11 @@ def find_minion_target(game): def find_soldier_minion_target(game, soldier_obj): soldier_affect_range = 660 - soldier_radius = 375 + soldier_radius = 310 min_health = 9999999999 soldier_target = None for minion in game.minions: - if minion.is_visible and minion.is_enemy_to(game.player) and minion.is_alive and minion.health < min_health and game.distance(game.player, minion) < soldier_affect_range + soldier_radius and game.distance(soldier_obj, minion) < soldier_radius and skills.is_last_hitable(game, game.player, minion): + if minion.is_visible and minion.is_enemy_to(game.player) and minion.is_alive and minion.health < min_health and game.distance(game.player, minion) < soldier_affect_range + soldier_radius and skills.is_last_hitable(game, game.player, minion): soldier_target = minion min_health = minion.health @@ -94,7 +94,7 @@ def get_target(game): if not target and auto_last_hit: for obj in game.others: - if not obj.is_alive or obj.is_ally_to(game.player): + if not obj.is_alive or obj.is_enemy_to(game.player): continue if obj.has_tags(UnitTag.Unit_Special_AzirW): From 6edf4bf024f432bb744de207d1409872262d9642 Mon Sep 17 00:00:00 2001 From: Billybishop <30381194+Billybishop@users.noreply.github.com> Date: Sat, 27 Mar 2021 14:04:35 -0400 Subject: [PATCH 10/19] More Azir QoL fixes Resolved last hitting for azir and fixed damage calculation not setting damage type properly. --- GameplayScripts/commons/damage_calculator.py | 4 ++-- GameplayScripts/commons/skills.py | 7 +++++-- GameplayScripts/orb_walker.py | 11 ++++++----- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/GameplayScripts/commons/damage_calculator.py b/GameplayScripts/commons/damage_calculator.py index ab11996d..69d94929 100644 --- a/GameplayScripts/commons/damage_calculator.py +++ b/GameplayScripts/commons/damage_calculator.py @@ -16,7 +16,7 @@ class DamageSpecification: # 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 = 0.33 + missing_health_max_scale_multiplier = 1.0 # Damage increased by missing_health_multiplier * enemy_missing_health missing_health_multiplier = 0.0 @@ -62,7 +62,7 @@ def calculate_damage(self, source, target): damage_multiplier = 2.0 - 100.0 / (100.0 - resistance_value) # BB: Temp workaround until we figure out wtf is wrong with last hitting - works well on Azir - damage_multiplier = 100/(100+(resistance_value*0.82)) + #damage_multiplier = 100/(100+((0.01+resistance_value)*330)) dealt_damage = ( self.base_damage diff --git a/GameplayScripts/commons/skills.py b/GameplayScripts/commons/skills.py index b88050ba..80ba71c5 100644 --- a/GameplayScripts/commons/skills.py +++ b/GameplayScripts/commons/skills.py @@ -10,7 +10,7 @@ ChampionSpells = {} damageCalc = DamageSpecification() -damageType = DamageType(1); +damageType = DamageType.Normal; class SFlag: Targeted = 1 @@ -307,10 +307,13 @@ def is_skillshot_cone(skill_name): def is_last_hitable(game, player, enemy): missile_speed = player.basic_missile_speed + 1 + #percent_ad/ap doesn't help for last hitting, makes it last hit way too early + #damageCalc.percent_ad = 1.0 + #damageCalc.percent_ap = 1.0 damageCalc.damage_type = damageType damageCalc.base_damage = 0 - hit_dmg = damageCalc.calculate_damage(player, enemy) + items.get_onhit_physical(player, enemy) + items.get_onhit_magical(player, enemy) + hit_dmg = (damageCalc.calculate_damage(player, enemy) + items.get_onhit_physical(player, enemy) + items.get_onhit_magical(player, enemy))-2 hp = enemy.health atk_speed = player.base_atk_speed * player.atk_speed_multi diff --git a/GameplayScripts/orb_walker.py b/GameplayScripts/orb_walker.py index 0811d5b1..ae204033 100644 --- a/GameplayScripts/orb_walker.py +++ b/GameplayScripts/orb_walker.py @@ -80,7 +80,7 @@ def find_soldier_minion_target(game, soldier_obj): min_health = 9999999999 soldier_target = None for minion in game.minions: - if minion.is_visible and minion.is_enemy_to(game.player) and minion.is_alive and minion.health < min_health and game.distance(game.player, minion) < soldier_affect_range + soldier_radius and skills.is_last_hitable(game, game.player, minion): + if minion.is_visible and minion.is_enemy_to(game.player) and minion.is_alive and minion.health < min_health and game.distance(game.player, minion) < soldier_affect_range + soldier_radius and game.distance(soldier_obj, minion) < soldier_radius and skills.is_last_hitable(game, game.player, minion): soldier_target = minion min_health = minion.health @@ -98,9 +98,10 @@ def get_target(game): continue if obj.has_tags(UnitTag.Unit_Special_AzirW): - return find_soldier_minion_target(game, obj) + target = find_soldier_minion_target(game, obj) - return find_minion_target(game) + if not target: + target = find_minion_target(game) return target @@ -141,8 +142,8 @@ def lview_update(game, ui): 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)+0.10 + 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) From 626bd94f96419d7834ba5d14045ff9be2ce3bdd8 Mon Sep 17 00:00:00 2001 From: Billybishop <30381194+Billybishop@users.noreply.github.com> Date: Tue, 30 Mar 2021 19:05:23 -0400 Subject: [PATCH 11/19] Orbwalking and Azir updates Lots of changes to orbwalker and last hit calculation - now much more accurate. Azir part of orbwalk updated with more accurate values and rewritten to support multiple soldiers. --- GameplayScripts/commons/skills.py | 108 ++++++++++++++++-- GameplayScripts/commons/targeting.py | 32 ++---- GameplayScripts/orb_walker.py | 159 +++++++++++++++++++++------ 3 files changed, 238 insertions(+), 61 deletions(-) diff --git a/GameplayScripts/commons/skills.py b/GameplayScripts/commons/skills.py index 80ba71c5..2b6cc0a0 100644 --- a/GameplayScripts/commons/skills.py +++ b/GameplayScripts/commons/skills.py @@ -10,7 +10,7 @@ ChampionSpells = {} damageCalc = DamageSpecification() -damageType = DamageType.Normal; +damageType = DamageType.Normal class SFlag: Targeted = 1 @@ -43,6 +43,28 @@ def __init__(self, name, missile_names, flags, delay = 0.0): name = "?" missiles = [] +#Based on level, not sure exact formula so hardcoded it +AzirSoldierDamage = { + 1: 50, + 2: 52, + 3: 54, + 4: 56, + 5: 58, + 6: 60, + 7: 62, + 8: 65, + 9: 70, + 10: 75, + 11: 80, + 12: 90, + 13: 100, + 14: 110, + 15: 120, + 16: 130, + 17: 140, + 18: 150 +} + ChampionSpells = { "aatrox": [ Spell("aatroxw", ["aatroxw"], SFlag.CollideGeneric) @@ -304,27 +326,99 @@ def is_skillshot_cone(skill_name): return False return Spells[skill_name].flags & SFlag.Cone +def is_soldier_alive(game): + if game.player.name == "azir": + for obj in game.others: + if not obj.is_alive or obj.is_enemy_to(game.player): + continue + + if obj.has_tags(UnitTag.Unit_Special_AzirW): + return obj + + return None + +def soldier_near_obj(game, enemy): + if game.player.name == "azir": + soldier_affect_range = 650.0 + soldier_radius = 325.0 + + for obj in game.others: + if not obj.is_alive or obj.is_enemy_to(game.player) or game.distance(game.player, obj) > soldier_affect_range + soldier_radius: + continue + + if obj.has_tags(UnitTag.Unit_Special_AzirW): + if (game.distance(obj, enemy) < soldier_radius): + return obj + + return None + +def count_soldiers_near_obj(game, enemy): + num_soldiers = 0 + if game.player.name == "azir": + soldier_affect_range = 650.0 + soldier_radius = 325.0 + + for obj in game.others: + if not obj.is_alive or obj.is_enemy_to(game.player) or game.distance(game.player, obj) > soldier_affect_range + soldier_radius: + continue + + if obj.has_tags(UnitTag.Unit_Special_AzirW): + if (game.distance(obj, enemy) < soldier_radius): + num_soldiers += 1 + + return num_soldiers + def is_last_hitable(game, player, enemy): missile_speed = player.basic_missile_speed + 1 + atk_speed = player.base_atk_speed * player.atk_speed_multi - #percent_ad/ap doesn't help for last hitting, makes it last hit way too early + #percent_ad/ap will be situationally helpful for last hitting #damageCalc.percent_ad = 1.0 #damageCalc.percent_ap = 1.0 damageCalc.damage_type = damageType - damageCalc.base_damage = 0 + damageCalc.base_damage = (player.base_atk + player.bonus_atk) - 0.50 + + #soldier_near_obj returns None if you're not playing Azir + #1 soldier = 0% additional onhit soldier dmg, 2 soldiers = 25% addtional onhit soldier dmg, 3 = 50%, etc.. + #one soldier can deal max 150 + 0.60 percent_ap, two soldiers is (150 + 0.60 percent_ap) * 1.25, three is *1.5, etc... + soldier = soldier_near_obj(game, enemy) + + if soldier is not None: + num_soldiers = count_soldiers_near_obj(game, enemy) + #Azir dmg formula + damageCalc.base_damage = AzirSoldierDamage[player.lvl] + (player.ap * 0.60) + #Addtional 25% dmg for each additional soldier (num_soldiers-1) + damageCalc.base_damage = damageCalc.base_damage + (damageCalc.base_damage*((num_soldiers-1) * 0.25)) - 0.50 + damageCalc.damage_type = DamageType.Magic + #Missile speed for soldier autos is weird- it isnt a missile but the soldier spears do have a travel time before dmg is registered, it can be interrupted by issuing another command much like a traditional auto windup. + #Couldn't find a basic_atk_windup for azirsoldier so missile speed is partially based on magic number + atk_speed = player.base_atk_speed * player.atk_speed_multi #or is it * soldier.atk_speed_multi? + missile_speed = (3866.0 * atk_speed/player.base_atk_speed) + #t_until_basic_hits = (4.0/atk_speed) + #windup_time = ((1.0/player.base_atk_speed)*soldier.basic_atk_windup) + #game.draw_button(game.world_to_screen(game.player.pos), str(damageCalc.base_damage), Color.BLACK, Color.WHITE) + + #game.draw_button(game.world_to_screen(game.player.pos), str(damageCalc.damage_type) + ": " + str(damageCalc.base_damage), Color.BLACK, Color.WHITE) - hit_dmg = (damageCalc.calculate_damage(player, enemy) + items.get_onhit_physical(player, enemy) + items.get_onhit_magical(player, enemy))-2 + hit_dmg = (damageCalc.calculate_damage(player, enemy))# + items.get_onhit_physical(player, enemy) + items.get_onhit_magical(player, enemy))#-12 + + #game.draw_button(game.world_to_screen(game.player.pos), str(damageCalc.damage_type) + ": " + str(hit_dmg), Color.BLACK, Color.WHITE) 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) + #where should we be applying client-server latency to the formula- in orbwalker or here? for missile in game.missiles: if missile.dest_id == enemy.id: + #minion_missilespeed = 0 #0 means it's a melee minion, can't find basic_atk_windup for minions or soldiers + src = game.get_obj_by_id(missile.src_id) if src: - t_until_missile_hits = game.distance(missile, enemy)/(missile.speed + 1) - + #t_until_missile_hits = game.distance(missile, enemy)/((0.001+missile.speed)-50)#(missile.speed + 1) + t_until_missile_hits = game.distance(missile, enemy)/(src.basic_missile_speed + 1) #Using src's basic missile speed is most reliable because different minion types have different missile speeds + + #game.draw_button(game.world_to_screen(src.pos), str(src.name) + " Missile Speed: " + str(src.basic_missile_speed), Color.BLACK, Color.WHITE) + if t_until_missile_hits < t_until_basic_hits: hp -= src.base_atk diff --git a/GameplayScripts/commons/targeting.py b/GameplayScripts/commons/targeting.py index 7bdfeb1b..6eeef1a1 100644 --- a/GameplayScripts/commons/targeting.py +++ b/GameplayScripts/commons/targeting.py @@ -1,5 +1,6 @@ from lview import * from enum import Enum +from commons import skills class Target(Enum): ClosestToPlayer = 0 @@ -45,30 +46,19 @@ def find_target(self, game, array, range, value_extractor): min = 99999999 val = 0 for obj in array: - - soldier = None - is_soldier_targeting = False + if not obj.is_alive or not obj.is_visible or obj.is_ally_to(game.player): + continue + range_calc = (game.distance(game.player, obj) - game.player.gameplay_radius - obj.gameplay_radius) - soldier_affect_range = 660 - soldier_radius = 310 - - for soldier_obj in game.others: - if not soldier_obj.is_alive or soldier_obj.is_enemy_to(game.player): - continue - - if soldier_obj.has_tags(UnitTag.Unit_Special_AzirW): - if game.distance(game.player, obj) > (soldier_affect_range + soldier_radius): - continue - - soldier = soldier_obj - range_calc = (game.distance(soldier_obj, obj) - obj.gameplay_radius) - is_soldier_targeting = True - - if is_soldier_targeting == True: - if not obj.is_alive or not obj.is_visible or obj.is_ally_to(game.player) or range_calc > soldier_radius: + soldier_radius = 325.0 + soldier = skills.soldier_near_obj(game, obj) + + if soldier is not None: + range_calc = (game.distance(soldier, obj)) + if range_calc > soldier_radius: continue else: - if not obj.is_alive or not obj.is_visible or obj.is_ally_to(game.player) or range_calc > range: + if range_calc > range: continue val = value_extractor(game.player, obj) diff --git a/GameplayScripts/orb_walker.py b/GameplayScripts/orb_walker.py index ae204033..73ae15ba 100644 --- a/GameplayScripts/orb_walker.py +++ b/GameplayScripts/orb_walker.py @@ -1,6 +1,7 @@ from lview import * from commons import skills from commons.targeting import TargetingConfig +from datetime import datetime import time, json lview_script_info = { @@ -14,8 +15,25 @@ key_attack_move = 0 key_orbwalk = 0 + +key_whitelist = { + "key_1": 2, + "key_2": 3, + "key_3": 4, + "key_4": 5, + "key_5": 6, + "key_6": 7, + "key_7": 8, + "key_q": 16, + "key_w": 17, + "key_e": 18, + "key_r": 19, + "key_d": 32, + "key_f": 33 +} + auto_last_hit = False -soldier_target = None +target = None max_atk_speed = 0 toggle_mode = False @@ -25,7 +43,7 @@ soldiers = { #Name -> (radius, show_radius_circle, show_radius_circle_minimap, icon) - 'azirsoldier' : [310, True, False, "azir_w"] + 'azirsoldier' : [325.0, True, False, "azir_w"] } @@ -66,45 +84,72 @@ def lview_draw_settings(game, ui): def find_minion_target(game): atk_range = game.player.base_atk_range + game.player.gameplay_radius min_health = 9999999999 - target = None + player_target = None for minion in game.minions: - if minion.is_visible and 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 + if minion.is_visible and minion.is_enemy_to(game.player) and minion.is_alive and minion.health < min_health and game.distance(game.player, minion) < atk_range: + #game.draw_circle_world(minion.pos, 24, 16, 3, Color.BLUE) + + if skills.is_last_hitable(game, game.player, minion): + player_target = minion + min_health = minion.health - return target + return player_target -def find_soldier_minion_target(game, soldier_obj): - soldier_affect_range = 660 - soldier_radius = 310 +def find_soldier_minion_target(game): + soldier_affect_range = 650.0 + soldier_radius = 325.0 min_health = 9999999999 soldier_target = None for minion in game.minions: - if minion.is_visible and minion.is_enemy_to(game.player) and minion.is_alive and minion.health < min_health and game.distance(game.player, minion) < soldier_affect_range + soldier_radius and game.distance(soldier_obj, minion) < soldier_radius and skills.is_last_hitable(game, game.player, minion): - soldier_target = minion - min_health = minion.health + soldier = skills.soldier_near_obj(game, minion) + if minion.is_visible and minion.is_enemy_to(game.player) and minion.is_alive and minion.health < min_health and soldier is not None: + #game.draw_circle_world(minion.pos, 48.0, 16, 3, Color.BLUE) + + if skills.is_last_hitable(game, game.player, minion): + soldier_target = minion + min_health = minion.health return soldier_target def get_target(game): global auto_last_hit - global soldier_target - - target = targeting.get_target(game, game.player.base_atk_range + game.player.gameplay_radius) - + global target + + atk_range = game.player.base_atk_range + game.player.gameplay_radius + + if target is not None and (not target.is_visible or not target.is_alive or (skills.soldier_near_obj(game, target) is None and game.distance(game.player, target) > atk_range)): + #game.draw_circle_world(game.player.pos, 24.0, 16, 3, Color.BLACK) + target = None + + if target is None: + target = targeting.get_target(game, atk_range) + if not target and auto_last_hit: - for obj in game.others: - if not obj.is_alive or obj.is_enemy_to(game.player): - continue - - if obj.has_tags(UnitTag.Unit_Special_AzirW): - target = find_soldier_minion_target(game, obj) + soldier = skills.is_soldier_alive(game) + + #only need to know if > 0 soldiers are up + if soldier is not None: + target = find_soldier_minion_target(game) if not target: target = find_minion_target(game) return target +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(game, obj, radius, show_circle_world, show_circle_map, icon): sp = game.world_to_screen(obj.pos) @@ -122,11 +167,23 @@ def draw(game, obj, radius, show_circle_world, show_circle_map, icon): 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 last_attacked, alternate, last_moved global key_attack_move, key_orbwalk, max_atk_speed global toggle_mode, toggled + global target + #game.draw_button(game.world_to_screen(game.player.pos), "Buffs: azirwprocbuff" + str(game.player.buffs[0].name) + " - Duration: " + str(game.player.buffs[0].end_time), Color.BLACK, Color.WHITE) + + #if game.player.name == "azir": + # for obj in game.others: + # if not obj.is_alive or obj.is_enemy_to(game.player): + # continue + + # if obj.has_tags(UnitTag.Unit_Special_AzirW): + # draw(game, obj, *(soldiers[obj.name])) + if toggle_mode: if game.was_key_pressed(key_orbwalk): toggled = not toggled @@ -135,34 +192,70 @@ def lview_update(game, ui): elif not game.is_key_down(key_orbwalk): return - + + # for key in key_whitelist.items(): + # if game.was_key_pressed(key): + # last_attacked = time.time() + + # if game.player.name == "azir": + # if game.was_key_pressed(key_q): + # last_attacked = time.time() + # if game.was_key_pressed(key_w): + # last_attacked = time.time() + # if game.was_key_pressed(key_e): + # last_attacked = time.time() + # if game.was_key_pressed(key_r): + # last_attacked = time.time() + # 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 + if target is not None: + game.draw_circle_world(target.pos, 24.0, 16, 3, Color.WHITE) + + # if game.player.name == "azir" and game.player.W.level > 0: + # #Check if azir arise buff is active (it's named azirwprocbuff) + # azir_w_atk_speeds = { + # 1:20, + # 2:30, + # 3:40, + # 4:50, + # 5:60 + # } + # azir_w_atk_speed_multiplier = azir_w_atk_speeds[game.player.W.level] + + # w_time = time.time() + # for buff in game.player.buffs: + # if buff.name == "azirwprocbuff": + # if time.time() < buff.end_time: + # #our attack speed buff is active + # #need to check spell level of w and get the attack speed multiplier + # atk_speed = (self.base_atk_speed) + + + # soldier = soldier_near_obj(game, target) + # if soldier is not None: + + # num_soldiers = count_soldiers_near_obj(game, target) + # if num_soldiers == 3: + + 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.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() - - for obj in game.others: - if not obj.is_alive or obj.is_enemy_to(game.player): - continue - - if obj.has_tags(UnitTag.Unit_Special_AzirW): - draw(game, obj, *(soldiers[obj.name])) \ No newline at end of file From 2de666eb9b0867432eaab09c14a0bf57b6d1ec15 Mon Sep 17 00:00:00 2001 From: Billybishop <30381194+Billybishop@users.noreply.github.com> Date: Tue, 30 Mar 2021 20:31:03 -0400 Subject: [PATCH 12/19] Added last hit priority orbwalking mode Global target now can be overwritten outside of the usual validation case by holding the V key instead of Spacebar. Spacebar will still last hit, but it will always prioritize champions if they're in range. Holding V will still harass, but it will always prioritize low health minions if they're in range. --- GameplayScripts/commons/damage_calculator.py | 3 - GameplayScripts/commons/skills.py | 23 +---- GameplayScripts/orb_walker.py | 101 +++++++------------ LView/config.ini | 5 +- 4 files changed, 45 insertions(+), 87 deletions(-) diff --git a/GameplayScripts/commons/damage_calculator.py b/GameplayScripts/commons/damage_calculator.py index 69d94929..7e6bfca7 100644 --- a/GameplayScripts/commons/damage_calculator.py +++ b/GameplayScripts/commons/damage_calculator.py @@ -60,9 +60,6 @@ def calculate_damage(self, source, target): damage_multiplier = 100.0 / (100.0 + resistance_value) else: damage_multiplier = 2.0 - 100.0 / (100.0 - resistance_value) - - # BB: Temp workaround until we figure out wtf is wrong with last hitting - works well on Azir - #damage_multiplier = 100/(100+((0.01+resistance_value)*330)) dealt_damage = ( self.base_damage diff --git a/GameplayScripts/commons/skills.py b/GameplayScripts/commons/skills.py index 2b6cc0a0..c55c5bc6 100644 --- a/GameplayScripts/commons/skills.py +++ b/GameplayScripts/commons/skills.py @@ -392,33 +392,21 @@ def is_last_hitable(game, player, enemy): damageCalc.damage_type = DamageType.Magic #Missile speed for soldier autos is weird- it isnt a missile but the soldier spears do have a travel time before dmg is registered, it can be interrupted by issuing another command much like a traditional auto windup. #Couldn't find a basic_atk_windup for azirsoldier so missile speed is partially based on magic number - atk_speed = player.base_atk_speed * player.atk_speed_multi #or is it * soldier.atk_speed_multi? + atk_speed = player.base_atk_speed * player.atk_speed_multi missile_speed = (3866.0 * atk_speed/player.base_atk_speed) - #t_until_basic_hits = (4.0/atk_speed) - #windup_time = ((1.0/player.base_atk_speed)*soldier.basic_atk_windup) - #game.draw_button(game.world_to_screen(game.player.pos), str(damageCalc.base_damage), Color.BLACK, Color.WHITE) - #game.draw_button(game.world_to_screen(game.player.pos), str(damageCalc.damage_type) + ": " + str(damageCalc.base_damage), Color.BLACK, Color.WHITE) - - hit_dmg = (damageCalc.calculate_damage(player, enemy))# + items.get_onhit_physical(player, enemy) + items.get_onhit_magical(player, enemy))#-12 - - #game.draw_button(game.world_to_screen(game.player.pos), str(damageCalc.damage_type) + ": " + str(hit_dmg), Color.BLACK, Color.WHITE) - + #TODO: integrate item onhit calculation based on damagetype + hit_dmg = (damageCalc.calculate_damage(player, enemy)) hp = enemy.health - t_until_basic_hits = game.distance(player, enemy)/missile_speed#(missile_speed*atk_speed/player.base_atk_speed) + t_until_basic_hits = game.distance(player, enemy)/missile_speed - #where should we be applying client-server latency to the formula- in orbwalker or here? + #where should we be applying client-server latency to the formula - in orbwalker or here? for missile in game.missiles: if missile.dest_id == enemy.id: - #minion_missilespeed = 0 #0 means it's a melee minion, can't find basic_atk_windup for minions or soldiers - src = game.get_obj_by_id(missile.src_id) if src: - #t_until_missile_hits = game.distance(missile, enemy)/((0.001+missile.speed)-50)#(missile.speed + 1) t_until_missile_hits = game.distance(missile, enemy)/(src.basic_missile_speed + 1) #Using src's basic missile speed is most reliable because different minion types have different missile speeds - #game.draw_button(game.world_to_screen(src.pos), str(src.name) + " Missile Speed: " + str(src.basic_missile_speed), Color.BLACK, Color.WHITE) - if t_until_missile_hits < t_until_basic_hits: hp -= src.base_atk @@ -453,7 +441,6 @@ def castpoint_for_collision(game, spell, caster, target): 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: diff --git a/GameplayScripts/orb_walker.py b/GameplayScripts/orb_walker.py index 73ae15ba..fd4fcc4d 100644 --- a/GameplayScripts/orb_walker.py +++ b/GameplayScripts/orb_walker.py @@ -15,6 +15,7 @@ key_attack_move = 0 key_orbwalk = 0 +key_lasthit = 0 key_whitelist = { "key_1": 2, @@ -48,35 +49,38 @@ def lview_load_cfg(cfg): - global key_attack_move, key_orbwalk, max_atk_speed, auto_last_hit, toggle_mode + global key_attack_move, key_orbwalk, key_lasthit, 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) + key_lasthit = cfg.get_int("key_lasthit", 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 key_attack_move, key_orbwalk, key_lasthit, 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_int("key_lasthit", key_lasthit) 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 key_attack_move, key_orbwalk, key_lasthit, 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) + key_orbwalk = ui.keyselect("Orbwalk and focus harass key", key_orbwalk) + key_lasthit = ui.keyselect("Orbwalk and focus lasthit key", key_lasthit) 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) @@ -87,8 +91,6 @@ def find_minion_target(game): player_target = None for minion in game.minions: if minion.is_visible and minion.is_enemy_to(game.player) and minion.is_alive and minion.health < min_health and game.distance(game.player, minion) < atk_range: - #game.draw_circle_world(minion.pos, 24, 16, 3, Color.BLUE) - if skills.is_last_hitable(game, game.player, minion): player_target = minion min_health = minion.health @@ -103,25 +105,38 @@ def find_soldier_minion_target(game): for minion in game.minions: soldier = skills.soldier_near_obj(game, minion) if minion.is_visible and minion.is_enemy_to(game.player) and minion.is_alive and minion.health < min_health and soldier is not None: - #game.draw_circle_world(minion.pos, 48.0, 16, 3, Color.BLUE) - if skills.is_last_hitable(game, game.player, minion): soldier_target = minion min_health = minion.health return soldier_target -def get_target(game): +def champ_near_obj(game, champ): + soldier_target = skills.soldier_near_obj(game, champ) + atk_range = game.player.base_atk_range + game.player.gameplay_radius + if soldier_target is not None: + return True + else: + return game.distance(game.player, champ) < atk_range + + return False + +def get_target(game, last_hit_prio): global auto_last_hit global target atk_range = game.player.base_atk_range + game.player.gameplay_radius if target is not None and (not target.is_visible or not target.is_alive or (skills.soldier_near_obj(game, target) is None and game.distance(game.player, target) > atk_range)): - #game.draw_circle_world(game.player.pos, 24.0, 16, 3, Color.BLACK) target = None - if target is None: + if target is not None: + if not last_hit_prio and not target.has_tags(UnitTag.Unit_Champion): + #since last target is valid but it isn't a champion and we're focusing on harass then we're allowed to overwrite target only if we can find a champion in range + for champ in game.champs: + if champ_near_obj(game, champ): + target = targeting.get_target(game, atk_range) + else: target = targeting.get_target(game, atk_range) if not target and auto_last_hit: @@ -170,87 +185,45 @@ def draw(game, obj, radius, show_circle_world, show_circle_map, icon): def lview_update(game, ui): global last_attacked, alternate, last_moved - global key_attack_move, key_orbwalk, max_atk_speed + global key_attack_move, key_orbwalk, key_lasthit, max_atk_speed global toggle_mode, toggled global target - #game.draw_button(game.world_to_screen(game.player.pos), "Buffs: azirwprocbuff" + str(game.player.buffs[0].name) + " - Duration: " + str(game.player.buffs[0].end_time), Color.BLACK, Color.WHITE) - - #if game.player.name == "azir": - # for obj in game.others: - # if not obj.is_alive or obj.is_enemy_to(game.player): - # continue - - # if obj.has_tags(UnitTag.Unit_Special_AzirW): - # draw(game, obj, *(soldiers[obj.name])) - 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): + elif not game.is_key_down(key_orbwalk) and not game.is_key_down(key_lasthit): return + last_hit_priority = False + if game.is_key_down(key_lasthit): + last_hit_priority = True + + #Use if you need to prevent orbwalker from interrupting your key presses: # for key in key_whitelist.items(): # if game.was_key_pressed(key): # last_attacked = time.time() - # if game.player.name == "azir": - # if game.was_key_pressed(key_q): - # last_attacked = time.time() - # if game.was_key_pressed(key_w): - # last_attacked = time.time() - # if game.was_key_pressed(key_e): - # last_attacked = time.time() - # if game.was_key_pressed(key_r): - # last_attacked = time.time() - - # game.draw_button(game.world_to_screen(game.player.pos), "OrbWalking", Color.BLACK, Color.WHITE) - - # Handle basic attacks + #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 + #Show orbwalk target if target is not None: game.draw_circle_world(target.pos, 24.0, 16, 3, Color.WHITE) - # if game.player.name == "azir" and game.player.W.level > 0: - # #Check if azir arise buff is active (it's named azirwprocbuff) - # azir_w_atk_speeds = { - # 1:20, - # 2:30, - # 3:40, - # 4:50, - # 5:60 - # } - # azir_w_atk_speed_multiplier = azir_w_atk_speeds[game.player.W.level] - - # w_time = time.time() - # for buff in game.player.buffs: - # if buff.name == "azirwprocbuff": - # if time.time() < buff.end_time: - # #our attack speed buff is active - # #need to check spell level of w and get the attack speed multiplier - # atk_speed = (self.base_atk_speed) - - - # soldier = soldier_near_obj(game, target) - # if soldier is not None: - - # num_soldiers = count_soldiers_near_obj(game, target) - # if num_soldiers == 3: - - - target = get_target(game) + target = get_target(game, last_hit_priority) t = time.time() if t - last_attacked > max(c_atk_time, max_atk_time) and target: last_attacked = t + #Don't use press_key if you can avoid it, configure your ingame settings to support attack move on left click #game.press_key(key_attack_move) game.click_at(True, game.world_to_screen(target.pos)) else: diff --git a/LView/config.ini b/LView/config.ini index 8c037d50..aecffa1b 100644 --- a/LView/config.ini +++ b/LView/config.ini @@ -19,9 +19,9 @@ Drawings::skillshots_predict=0 Drawings::skillshots_show_ally=1 Drawings::skillshots_show_enemy=1 Drawings::turret_ranges=1 -Evader::enabled=1 +Evader::enabled=0 Evader::evade_min_range=500.000000 -Evader::evades=1 +Evader::evades=0 Execution notifier::enabled=1 Map Awareness::bound_max=4000.000000 Map Awareness::enabled=1 @@ -32,6 +32,7 @@ Object Explorer::enabled=1 Orbwalker::auto_last_hit=1 Orbwalker::enabled=1 Orbwalker::key_attack_move=30 +Orbwalker::key_lasthit=46 Orbwalker::key_orbwalk=57 Orbwalker::max_atk_speed=2.322000 Orbwalker::target_jungle=1 From 8b020cb8c5faff529ce9ebe8452ba0841643c0f0 Mon Sep 17 00:00:00 2001 From: Billybishop <30381194+Billybishop@users.noreply.github.com> Date: Tue, 30 Mar 2021 21:17:21 -0400 Subject: [PATCH 13/19] Update config.ini Config push --- LView/config.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LView/config.ini b/LView/config.ini index aecffa1b..4dc88e63 100644 --- a/LView/config.ini +++ b/LView/config.ini @@ -32,7 +32,7 @@ Object Explorer::enabled=1 Orbwalker::auto_last_hit=1 Orbwalker::enabled=1 Orbwalker::key_attack_move=30 -Orbwalker::key_lasthit=46 +Orbwalker::key_lasthit=47 Orbwalker::key_orbwalk=57 Orbwalker::max_atk_speed=2.322000 Orbwalker::target_jungle=1 From 10b0a2738c15277ccd44c7ed2185b7ee54a50851 Mon Sep 17 00:00:00 2001 From: Billybishop <30381194+Billybishop@users.noreply.github.com> Date: Tue, 30 Mar 2021 23:26:29 -0400 Subject: [PATCH 14/19] Tweaking Orbwalker last hit mode and Azir last hits Orbwalker now better prioritizes targets during last hit mode. Trying to find best values for Azir last hits for consistently maintaining 9/10+ cs. This appears best so far. --- GameplayScripts/commons/skills.py | 10 +++++----- GameplayScripts/orb_walker.py | 19 +++++++++++++------ 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/GameplayScripts/commons/skills.py b/GameplayScripts/commons/skills.py index c55c5bc6..641ed46f 100644 --- a/GameplayScripts/commons/skills.py +++ b/GameplayScripts/commons/skills.py @@ -369,14 +369,14 @@ def count_soldiers_near_obj(game, enemy): return num_soldiers def is_last_hitable(game, player, enemy): - missile_speed = player.basic_missile_speed + 1 + missile_speed = player.basic_missile_speed + 1.0 atk_speed = player.base_atk_speed * player.atk_speed_multi #percent_ad/ap will be situationally helpful for last hitting #damageCalc.percent_ad = 1.0 #damageCalc.percent_ap = 1.0 damageCalc.damage_type = damageType - damageCalc.base_damage = (player.base_atk + player.bonus_atk) - 0.50 + damageCalc.base_damage = (player.base_atk + player.bonus_atk) - 0.33 #soldier_near_obj returns None if you're not playing Azir #1 soldier = 0% additional onhit soldier dmg, 2 soldiers = 25% addtional onhit soldier dmg, 3 = 50%, etc.. @@ -388,12 +388,12 @@ def is_last_hitable(game, player, enemy): #Azir dmg formula damageCalc.base_damage = AzirSoldierDamage[player.lvl] + (player.ap * 0.60) #Addtional 25% dmg for each additional soldier (num_soldiers-1) - damageCalc.base_damage = damageCalc.base_damage + (damageCalc.base_damage*((num_soldiers-1) * 0.25)) - 0.50 + damageCalc.base_damage = (damageCalc.base_damage + (damageCalc.base_damage*((num_soldiers-1) * 0.25))) - 0.25 damageCalc.damage_type = DamageType.Magic #Missile speed for soldier autos is weird- it isnt a missile but the soldier spears do have a travel time before dmg is registered, it can be interrupted by issuing another command much like a traditional auto windup. #Couldn't find a basic_atk_windup for azirsoldier so missile speed is partially based on magic number atk_speed = player.base_atk_speed * player.atk_speed_multi - missile_speed = (3866.0 * atk_speed/player.base_atk_speed) + missile_speed = (3882.0 * atk_speed/player.base_atk_speed) #TODO: integrate item onhit calculation based on damagetype hit_dmg = (damageCalc.calculate_damage(player, enemy)) @@ -405,7 +405,7 @@ def is_last_hitable(game, player, enemy): 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)/(src.basic_missile_speed + 1) #Using src's basic missile speed is most reliable because different minion types have different missile speeds + t_until_missile_hits = game.distance(missile, enemy)/((src.basic_missile_speed + 1.0) - 0.4)#- 1.1 #Using src's basic missile speed is most reliable because different minion types have different missile speeds if t_until_missile_hits < t_until_basic_hits: hp -= src.base_atk diff --git a/GameplayScripts/orb_walker.py b/GameplayScripts/orb_walker.py index fd4fcc4d..6c150121 100644 --- a/GameplayScripts/orb_walker.py +++ b/GameplayScripts/orb_walker.py @@ -131,12 +131,16 @@ def get_target(game, last_hit_prio): target = None if target is not None: - if not last_hit_prio and not target.has_tags(UnitTag.Unit_Champion): - #since last target is valid but it isn't a champion and we're focusing on harass then we're allowed to overwrite target only if we can find a champion in range - for champ in game.champs: - if champ_near_obj(game, champ): - target = targeting.get_target(game, atk_range) - else: + if not last_hit_prio: + if not target.has_tags(UnitTag.Unit_Champion): + #since last target is valid but it isn't a champion and we're focusing on harass then we're allowed to overwrite target only if we can find a champion in range + for champ in game.champs: + if champ_near_obj(game, champ): + target = targeting.get_target(game, atk_range) + else: + target = None + + elif not last_hit_prio: target = targeting.get_target(game, atk_range) if not target and auto_last_hit: @@ -148,6 +152,9 @@ def get_target(game, last_hit_prio): if not target: target = find_minion_target(game) + + if not target and last_hit_prio: + target = targeting.get_target(game, atk_range) return target From 6af09140afb716349d5537be7800644f753df61a Mon Sep 17 00:00:00 2001 From: Billybishop <30381194+Billybishop@users.noreply.github.com> Date: Wed, 31 Mar 2021 15:46:14 -0400 Subject: [PATCH 15/19] Merged 11.7 Offsets Updated offsets to support 11.7 and added 4 new offsets, GameVersion, ObjExperience, SpellSlotSmiteTimer, and SpellSlotSmiteCharges. --- LView/Offsets.cpp | 59 +++++++++++++++++++++++++---------------------- LView/Offsets.h | 4 ++++ 2 files changed, 36 insertions(+), 27 deletions(-) diff --git a/LView/Offsets.cpp b/LView/Offsets.cpp index e7e93ee0..fcb847c7 100644 --- a/LView/Offsets.cpp +++ b/LView/Offsets.cpp @@ -2,13 +2,17 @@ Offsets::Offsets() {}; -int Offsets::GameTime = 0x02f8d1dc; -int Offsets::ViewProjMatrices = 0x2FB7998; -int Offsets::Renderer = 0x02fba770; -int Offsets::ObjectManager = 0x016f8678; -int Offsets::LocalPlayer = 0x02f9512c; -int Offsets::UnderMouseObject = 0x2346840; -int Offsets::MinimapObject = 0x02f94b0c; +int Offsets::GameTime = 0x02F6D134; // 11.6 ==> 11.7 +int Offsets::GameVersion = 0x2F872D8; // 11.6 ==> 11.7 + +int Offsets::ViewProjMatrices = 0x2F97FF0; // 11.6 ==> 11.7 +int Offsets::Renderer = 0x2F9ADD0; // 11.6 ==> 11.7 +int Offsets::RendererWidth = 0x0C; // 11.6 ==> 11.7 +int Offsets::RendererHeight = 0x10; // 11.6 ==> 11.7 + +int Offsets::ObjectManager = 0x16D85B8; // 11.6 ==> 11.7 +int Offsets::LocalPlayer = 0x2F7513C; // 11.6 ==> 11.7 +int Offsets::UnderMouseObject = 0x2326780; // 11.6 ==> 11.7 int Offsets::ObjIndex = 0x20; int Offsets::ObjTeam = 0x4C; @@ -20,28 +24,26 @@ int Offsets::ObjSrcIndex = 0x290; int Offsets::ObjMana = 0x298; int Offsets::ObjHealth = 0xD98; int Offsets::ObjMaxHealth = 0xDA8; -int Offsets::ObjArmor = 0x129C; -int Offsets::ObjMagicRes = 0x12A4; -int Offsets::ObjBaseAtk = 0x1274; -int Offsets::ObjBonusAtk = 0x11F0; -int Offsets::ObjMoveSpeed = 0x12B4; -int Offsets::ObjSpellBook = 0x2B98; -int Offsets::ObjName = 0x2F84; -int Offsets::ObjLvl = 0x36D4; +int Offsets::ObjArmor = 0x12C4; // 11.6 ==> 11.7 +int Offsets::ObjMagicRes = 0x12CC; // 11.6 ==> 11.7 +int Offsets::ObjBaseAtk = 0x129C; // 11.6 ==> 11.7 +int Offsets::ObjBonusAtk = 0x1218; // 11.6 ==> 11.7 +int Offsets::ObjMoveSpeed = 0x12DC; // 11.6 ==> 11.7 +int Offsets::ObjSpellBook = 0x2BA0; // 11.6 ==> 11.7 +int Offsets::ObjName = 0x2F8C; // 11.6 ==> 11.7 +int Offsets::ObjLvl = 0x36DC; // 11.6 ==> 11.7 int Offsets::ObjExpiry = 0x298; -int Offsets::ObjCrit = 0x1298; -int Offsets::ObjCritMulti = 0x1288; -int Offsets::ObjAbilityPower = 0x1200; +int Offsets::ObjCrit = 0x12C0; // 11.6 ==> 11.7 +int Offsets::ObjCritMulti = 0x12B0; // 11.6 ==> 11.7 +int Offsets::ObjAbilityPower = 0x1228; // 11.6 ==> 11.7 int Offsets::ObjAtkSpeedMulti = 0x1270; -int Offsets::ObjItemList = 0x3708; +int Offsets::ObjItemList = 0x3714; // 11.6 ==> 11.7 +int Offsets::ObjExperience = 0x36CC; // 11.6 ==> 11.7 int Offsets::ItemListItem = 0xC; int Offsets::ItemInfo = 0x20; int Offsets::ItemInfoId = 0x68; -int Offsets::RendererWidth = 0x10; -int Offsets::RendererHeight = 0x14; - int Offsets::SpellSlotLevel = 0x20; int Offsets::SpellSlotTime = 0x28; int Offsets::SpellSlotDamage = 0x94; @@ -49,18 +51,21 @@ int Offsets::SpellSlotSpellInfo = 0x13C; int Offsets::SpellInfoSpellData = 0x44; int Offsets::SpellDataSpellName = 0x64; int Offsets::SpellDataMissileName = 0x64; +int Offsets::SpellSlotSmiteTimer = 0x64; +int Offsets::SpellSlotSmiteCharges = 0x58; -int Offsets::MissileSpellInfo = 0x230; -int Offsets::MissileSrcIdx = 0x290; -int Offsets::MissileDestIdx = 0x2E8; -int Offsets::MissileStartPos = 0x2A8; -int Offsets::MissileEndPos = 0x2B4; +int Offsets::MissileSpellInfo = 0x258; // 11.6 ==> 11.7 +int Offsets::MissileSrcIdx = 0x2B8; // 11.6 ==> 11.7 +int Offsets::MissileDestIdx = 0x310; // 11.6 ==> 11.7 +int Offsets::MissileStartPos = 0x2D0; // 11.6 ==> 11.7 +int Offsets::MissileEndPos = 0x2DC; // 11.6 ==> 11.7 int Offsets::ObjectMapCount = 0x2C; int Offsets::ObjectMapRoot = 0x28; int Offsets::ObjectMapNodeNetId = 0x10; int Offsets::ObjectMapNodeObject = 0x14; +int Offsets::MinimapObject = 0x2F74B38; // 11.6 ==> 11.7 int Offsets::MinimapObjectHud = 0x88; int Offsets::MinimapHudPos = 0x60; int Offsets::MinimapHudSize = 0x68; diff --git a/LView/Offsets.h b/LView/Offsets.h index b923157a..11a99a47 100644 --- a/LView/Offsets.h +++ b/LView/Offsets.h @@ -8,6 +8,7 @@ class Offsets { Offsets(); static int GameTime; + static int GameVersion; static int ObjIndex; static int ObjTeam; @@ -33,6 +34,7 @@ class Offsets { static int ObjAtkSpeedMulti; static int ObjItemList; static int ObjSrcIndex; + static int ObjExperience; static int ItemListItem; static int ItemInfo; @@ -50,6 +52,8 @@ class Offsets { static int SpellInfoSpellData; static int SpellDataSpellName; static int SpellDataMissileName; + static int SpellSlotSmiteTimer; + static int SpellSlotSmiteCharges; static int ObjectManager; static int LocalPlayer; From d9fb0ebf70f5b3bb4a88a45b6eac7af48845a031 Mon Sep 17 00:00:00 2001 From: Billybishop <30381194+Billybishop@users.noreply.github.com> Date: Wed, 31 Mar 2021 15:54:49 -0400 Subject: [PATCH 16/19] Update README.md Added usage details --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index ebd7ca4a..3fc6c13a 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,10 @@ +# Usage Details +These are the settings I find help LView operate the most accurately. If you're having issues with LView misclicking or orbwalker missing last hits, please make sure you've done the following first: +- Set attack move to on cursor in game settings +- Set auto attack off in game settings +- Checkbox the option to bind autoattack to left click in game settings +- Bind target champions only to space bar and V key for primary and secondary keybind (for both orbwalk modes) and make sure it's not set to toggle in game settings + # Fork Details !!! IMPORTANT !!! This uses VS2019 and the mvc142 toolkit, please be sure your environment matches this configuration before attempting to build, and ofcourse you will still need to follow the steps outlined for the original project. Orkido on UC has documented much of what you need to do in order to get the project building from VS2019 so if you have trouble please search the LView thread for his comments on the matter. From 18c866460cb0db3112220d4537047219bfbaab86 Mon Sep 17 00:00:00 2001 From: Billybishop <30381194+Billybishop@users.noreply.github.com> Date: Wed, 31 Mar 2021 18:31:07 -0400 Subject: [PATCH 17/19] Leryss - 11.7 Fixed and added offsets Fixed offsets that weren't working and added several new offsets. Author: Leryss --- GameplayScripts/commons/skills.py | 2 +- LView/Offsets.cpp | 56 ++++++++++++++++++++++++------- LView/Offsets.h | 48 +++++++++++++++++++++----- 3 files changed, 83 insertions(+), 23 deletions(-) diff --git a/GameplayScripts/commons/skills.py b/GameplayScripts/commons/skills.py index 641ed46f..9094fa00 100644 --- a/GameplayScripts/commons/skills.py +++ b/GameplayScripts/commons/skills.py @@ -393,7 +393,7 @@ def is_last_hitable(game, player, enemy): #Missile speed for soldier autos is weird- it isnt a missile but the soldier spears do have a travel time before dmg is registered, it can be interrupted by issuing another command much like a traditional auto windup. #Couldn't find a basic_atk_windup for azirsoldier so missile speed is partially based on magic number atk_speed = player.base_atk_speed * player.atk_speed_multi - missile_speed = (3882.0 * atk_speed/player.base_atk_speed) + missile_speed = (3895.0 * atk_speed/player.base_atk_speed) #TODO: integrate item onhit calculation based on damagetype hit_dmg = (damageCalc.calculate_damage(player, enemy)) diff --git a/LView/Offsets.cpp b/LView/Offsets.cpp index fcb847c7..1793a32c 100644 --- a/LView/Offsets.cpp +++ b/LView/Offsets.cpp @@ -2,50 +2,73 @@ Offsets::Offsets() {}; -int Offsets::GameTime = 0x02F6D134; // 11.6 ==> 11.7 +int Offsets::GameTime = 0x02f6d134; // 11.6 ==> 11.7 int Offsets::GameVersion = 0x2F872D8; // 11.6 ==> 11.7 -int Offsets::ViewProjMatrices = 0x2F97FF0; // 11.6 ==> 11.7 -int Offsets::Renderer = 0x2F9ADD0; // 11.6 ==> 11.7 +int Offsets::ViewProjMatrices = 0x02f97ff0; // 11.6 ==> 11.7 +int Offsets::Renderer = 0x02f9add0; // 11.6 ==> 11.7 int Offsets::RendererWidth = 0x0C; // 11.6 ==> 11.7 int Offsets::RendererHeight = 0x10; // 11.6 ==> 11.7 -int Offsets::ObjectManager = 0x16D85B8; // 11.6 ==> 11.7 -int Offsets::LocalPlayer = 0x2F7513C; // 11.6 ==> 11.7 -int Offsets::UnderMouseObject = 0x2326780; // 11.6 ==> 11.7 +int Offsets::ObjectManager = 0x016d85b8; // 11.6 ==> 11.7 +int Offsets::LocalPlayer = 0x02f7513c; // 11.6 ==> 11.7 +int Offsets::UnderMouseObject = 0x2346840; // 11.6 ==> 11.7 + +int Offsets::Chat = 0x02f75208; +int Offsets::ChatIsOpen = 0x650; +int Offsets::FnCharacterDataStackUpdate = 0x000ee560; int Offsets::ObjIndex = 0x20; int Offsets::ObjTeam = 0x4C; int Offsets::ObjNetworkID = 0xCC; int Offsets::ObjPos = 0x1d8; +int Offsets::ObjName = 0x2F8C; // 11.6 ==> 11.7 +int Offsets::ObjLvl = 0x36DC; // 11.6 ==> 11.7 +int Offsets::ObjTransformation = 0x2f80; +int Offsets::ObjMissileSpellCast = 0x250; int Offsets::ObjVisibility = 0x270; int Offsets::ObjSpawnCount = 0x284; int Offsets::ObjSrcIndex = 0x290; int Offsets::ObjMana = 0x298; +int Offsets::ObjInvulnerable = 0x3D0; +int Offsets::ObjTargetable = 0xD00; +int Offsets::ObjRecallState = 0xD8C; int Offsets::ObjHealth = 0xD98; int Offsets::ObjMaxHealth = 0xDA8; +int Offsets::ObjAbilityHaste = 0x10F4; +int Offsets::ObjLethality = 0x11DC; int Offsets::ObjArmor = 0x12C4; // 11.6 ==> 11.7 +int Offsets::ObjBonusArmor = 0x12C8; int Offsets::ObjMagicRes = 0x12CC; // 11.6 ==> 11.7 +int Offsets::ObjBonusMagicRes = 0x12D0; int Offsets::ObjBaseAtk = 0x129C; // 11.6 ==> 11.7 int Offsets::ObjBonusAtk = 0x1218; // 11.6 ==> 11.7 int Offsets::ObjMoveSpeed = 0x12DC; // 11.6 ==> 11.7 int Offsets::ObjSpellBook = 0x2BA0; // 11.6 ==> 11.7 -int Offsets::ObjName = 0x2F8C; // 11.6 ==> 11.7 -int Offsets::ObjLvl = 0x36DC; // 11.6 ==> 11.7 int Offsets::ObjExpiry = 0x298; int Offsets::ObjCrit = 0x12C0; // 11.6 ==> 11.7 int Offsets::ObjCritMulti = 0x12B0; // 11.6 ==> 11.7 int Offsets::ObjAbilityPower = 0x1228; // 11.6 ==> 11.7 -int Offsets::ObjAtkSpeedMulti = 0x1270; -int Offsets::ObjItemList = 0x3714; // 11.6 ==> 11.7 +int Offsets::ObjAtkSpeedMulti = 0x1298; +int Offsets::ObjAtkRange = 0x12E4; +int Offsets::ObjMagicPen = 0x11C0; +int Offsets::ObjMagicPenMulti = 0x11C8; // 1.0 when no percent magic pen is applied otherwise its below 1.0 depending on the percent applied +int Offsets::ObjAdditionalApMulti = 0x122C; // I use this for rabadon, its 0.35 when rabadon is in inventory int Offsets::ObjExperience = 0x36CC; // 11.6 ==> 11.7 +int Offsets::ObjDirection = 0x1B88; +int Offsets::ObjItemList = 0x3728; // 11.6 ==> 11.7 int Offsets::ItemListItem = 0xC; +int Offsets::ItemActiveName = 0x10; +int Offsets::ItemCharges = 0x24; int Offsets::ItemInfo = 0x20; int Offsets::ItemInfoId = 0x68; int Offsets::SpellSlotLevel = 0x20; int Offsets::SpellSlotTime = 0x28; +int Offsets::SpellSlotCharges = 0x58; +int Offsets::SpellSlotTimeCharge = 0x64; +int Offsets::SpellSlotValue = 0x94; int Offsets::SpellSlotDamage = 0x94; int Offsets::SpellSlotSpellInfo = 0x13C; int Offsets::SpellInfoSpellData = 0x44; @@ -53,6 +76,7 @@ int Offsets::SpellDataSpellName = 0x64; int Offsets::SpellDataMissileName = 0x64; int Offsets::SpellSlotSmiteTimer = 0x64; int Offsets::SpellSlotSmiteCharges = 0x58; +int Offsets::SpellDataManaArray = 0x524; int Offsets::MissileSpellInfo = 0x258; // 11.6 ==> 11.7 int Offsets::MissileSrcIdx = 0x2B8; // 11.6 ==> 11.7 @@ -65,14 +89,20 @@ int Offsets::ObjectMapRoot = 0x28; int Offsets::ObjectMapNodeNetId = 0x10; int Offsets::ObjectMapNodeObject = 0x14; -int Offsets::MinimapObject = 0x2F74B38; // 11.6 ==> 11.7 +int Offsets::MinimapObject = 0x02f74b38; // 11.6 ==> 11.7 int Offsets::MinimapObjectHud = 0x88; int Offsets::MinimapHudPos = 0x60; int Offsets::MinimapHudSize = 0x68; -int Offsets::ObjBuffManager = 0x2178; +int Offsets::CharacterDataStack = 0x2F80; +int Offsets::CharacterDataStackSkinId = 0x18; + +int Offsets::ObjBuffManager = 0x217C; int Offsets::BuffManagerEntriesArray = 0x10; int Offsets::BuffEntryBuff = 0x8; int Offsets::BuffEntryBuffStartTime = 0xC; int Offsets::BuffEntryBuffEndTime = 0x10; -int Offsets::BuffName = 0x8; \ No newline at end of file +int Offsets::BuffEntryBuffCount = 0x74; +int Offsets::BuffName = 0x8; +int Offsets::BuffEntryBuffNodeStart = 0x20; +int Offsets::BuffEntryBuffNodeCurrent = 0x24; \ No newline at end of file diff --git a/LView/Offsets.h b/LView/Offsets.h index 11a99a47..ca380715 100644 --- a/LView/Offsets.h +++ b/LView/Offsets.h @@ -10,6 +10,19 @@ class Offsets { static int GameTime; static int GameVersion; + static int ViewProjMatrices; + static int Renderer; + static int RendererWidth; + static int RendererHeight; + + static int ObjectManager; + static int LocalPlayer; + static int UnderMouseObject; + + static int Chat; + static int ChatIsOpen; + static int FnCharacterDataStackUpdate; + static int ObjIndex; static int ObjTeam; static int ObjNetworkID; @@ -18,32 +31,43 @@ class Offsets { static int ObjSpawnCount; static int ObjHealth; static int ObjMaxHealth; + static int ObjAbilityHaste; + static int ObjLethality; static int ObjMana; + static int ObjInvulnerable; + static int ObjTargetable; + static int ObjRecallState; static int ObjArmor; + static int ObjBonusArmor; static int ObjMagicRes; + static int ObjBonusMagicRes; static int ObjBaseAtk; static int ObjBonusAtk; static int ObjMoveSpeed; static int ObjSpellBook; static int ObjName; static int ObjLvl; + static int ObjTransformation; + static int ObjMissileSpellCast; static int ObjExpiry; static int ObjCrit; static int ObjCritMulti; static int ObjAbilityPower; static int ObjAtkSpeedMulti; + static int ObjAtkRange; + static int ObjMagicPen; + static int ObjMagicPenMulti; + static int ObjAdditionalApMulti; static int ObjItemList; static int ObjSrcIndex; static int ObjExperience; + static int ObjDirection; static int ItemListItem; static int ItemInfo; static int ItemInfoId; - - static int ViewProjMatrices; - static int Renderer; - static int RendererWidth; - static int RendererHeight; + static int ItemActiveName; + static int ItemCharges; static int SpellSlotLevel; static int SpellSlotTime; @@ -54,10 +78,10 @@ class Offsets { static int SpellDataMissileName; static int SpellSlotSmiteTimer; static int SpellSlotSmiteCharges; - - static int ObjectManager; - static int LocalPlayer; - static int UnderMouseObject; + static int SpellSlotCharges; + static int SpellSlotTimeCharge; + static int SpellSlotValue; + static int SpellDataManaArray; static int ObjectMapCount; static int ObjectMapRoot; @@ -75,10 +99,16 @@ class Offsets { static int MinimapHudPos; static int MinimapHudSize; + static int CharacterDataStack; + static int CharacterDataStackSkinId; + static int ObjBuffManager; static int BuffManagerEntriesArray; static int BuffEntryBuff; static int BuffEntryBuffStartTime; static int BuffEntryBuffEndTime; static int BuffName; + static int BuffEntryBuffCount; + static int BuffEntryBuffNodeStart; + static int BuffEntryBuffNodeCurrent; }; \ No newline at end of file From 4f73d58c775199feb99be10c09b7f74bf69f803d Mon Sep 17 00:00:00 2001 From: Billybishop <30381194+Billybishop@users.noreply.github.com> Date: Sat, 3 Apr 2021 19:55:13 -0400 Subject: [PATCH 18/19] Core changes and offsets, orbwalking, cass/azir Orbwalking now has a way to handle special champs that affect the orbwalker (like cass E and azir's soldiers). Cass has been added to orbwalker with integrated Q (uses prediction) and E for lasthitting and attacking champs. Core now reads ability haste and mana from memory. Offsets have been updated with many additions and fixed some broken 11.7 offsets. You no longer need to use 'bind auto attack to left mouse' in game settings, and you should unbind the 'target champion only' key to make sure it's not on space or V. --- GameplayScripts/commons/skills.py | 58 +++++++++--- GameplayScripts/commons/targeting.py | 38 ++++++-- GameplayScripts/object_viewer.py | 2 + GameplayScripts/orb_walker.py | 135 +++++++++++++++++++-------- LView/GameObject.cpp | 2 + LView/GameObject.h | 2 + LView/Offsets.cpp | 12 +-- LView/PyStructs.h | 2 + LView/config.ini | 2 +- UtilityScripts/cass.ahk | 34 +++++++ 10 files changed, 218 insertions(+), 69 deletions(-) create mode 100644 UtilityScripts/cass.ahk diff --git a/GameplayScripts/commons/skills.py b/GameplayScripts/commons/skills.py index 9094fa00..dde495cd 100644 --- a/GameplayScripts/commons/skills.py +++ b/GameplayScripts/commons/skills.py @@ -65,6 +65,28 @@ def __init__(self, name, missile_names, flags, delay = 0.0): 18: 150 } +#Based on level, not sure exact formula so hardcoded it +CassiopeiaEDamage = { + 1: 52, + 2: 56, + 3: 60, + 4: 64, + 5: 68, + 6: 72, + 7: 76, + 8: 80, + 9: 84, + 10: 88, + 11: 92, + 12: 96, + 13: 100, + 14: 104, + 15: 108, + 16: 112, + 17: 116, + 18: 120 +} + ChampionSpells = { "aatrox": [ Spell("aatroxw", ["aatroxw"], SFlag.CollideGeneric) @@ -90,6 +112,9 @@ def __init__(self, name, missile_names, flags, delay = 0.0): Spell("caitlynyordletrap", [], SFlag.Area), Spell("caitlynentrapment", ["caitlynentrapmentmissile"], SFlag.SkillshotLine) ], + "cassiopeia": [ + Spell("cassiopeiaq", [], SFlag.Area, delay = 0.250) + ], "chogath": [ Spell("rupture", [], SFlag.Area, delay = 0.627), Spell("feralscream", [], SFlag.Cone | SFlag.CollideWindwall) @@ -381,19 +406,28 @@ def is_last_hitable(game, player, enemy): #soldier_near_obj returns None if you're not playing Azir #1 soldier = 0% additional onhit soldier dmg, 2 soldiers = 25% addtional onhit soldier dmg, 3 = 50%, etc.. #one soldier can deal max 150 + 0.60 percent_ap, two soldiers is (150 + 0.60 percent_ap) * 1.25, three is *1.5, etc... - soldier = soldier_near_obj(game, enemy) + if game.player.name == "azir": + soldier = soldier_near_obj(game, enemy) + + if soldier is not None: + num_soldiers = count_soldiers_near_obj(game, enemy) + #Azir dmg formula + damageCalc.base_damage = AzirSoldierDamage[player.lvl] + (player.ap * 0.60) + #Addtional 25% dmg for each additional soldier (num_soldiers-1) + damageCalc.base_damage = (damageCalc.base_damage + (damageCalc.base_damage*((num_soldiers-1) * 0.25))) - 0.25 + damageCalc.damage_type = DamageType.Magic + #Missile speed for soldier autos is weird- it isnt a missile but the soldier spears do have a travel time before dmg is registered, it can be interrupted by issuing another command much like a traditional auto windup. + #Couldn't find a basic_atk_windup for azirsoldier so missile speed is partially based on magic number + atk_speed = player.base_atk_speed * player.atk_speed_multi + missile_speed = (3895.0 * atk_speed/player.base_atk_speed) + elif game.player.name == "cassiopeia": + skillE = getattr(game.player, 'E') - if soldier is not None: - num_soldiers = count_soldiers_near_obj(game, enemy) - #Azir dmg formula - damageCalc.base_damage = AzirSoldierDamage[player.lvl] + (player.ap * 0.60) - #Addtional 25% dmg for each additional soldier (num_soldiers-1) - damageCalc.base_damage = (damageCalc.base_damage + (damageCalc.base_damage*((num_soldiers-1) * 0.25))) - 0.25 - damageCalc.damage_type = DamageType.Magic - #Missile speed for soldier autos is weird- it isnt a missile but the soldier spears do have a travel time before dmg is registered, it can be interrupted by issuing another command much like a traditional auto windup. - #Couldn't find a basic_atk_windup for azirsoldier so missile speed is partially based on magic number - atk_speed = player.base_atk_speed * player.atk_speed_multi - missile_speed = (3895.0 * atk_speed/player.base_atk_speed) + if game.player.mana > 50.0: + damageCalc.base_damage = CassiopeiaEDamage[player.lvl] + (player.ap * 0.10) + damageCalc.damage_type = DamageType.Magic + atk_speed = 0.125 + missile_speed = 2500 #TODO: integrate item onhit calculation based on damagetype hit_dmg = (damageCalc.calculate_damage(player, enemy)) diff --git a/GameplayScripts/commons/targeting.py b/GameplayScripts/commons/targeting.py index 6eeef1a1..c44bde60 100644 --- a/GameplayScripts/commons/targeting.py +++ b/GameplayScripts/commons/targeting.py @@ -14,6 +14,11 @@ class TargetingConfig: Target.LowestHealth: (lambda player, enemy: enemy.health), Target.MostFed: (lambda player, enemy: -sum([item.cost for item in enemy.items])) } + #Necessary to properly determine orbwalking last hits - Azir uses soldiers to harass and last hit. Cass uses E to harass and last hit. + special_targeting_champs = { + "azir": 325.0, #Azir soldier radius + "cassiopeia": 711.0 #Cass E range + } selected = 0 target_minions = False target_jungle = False @@ -50,17 +55,30 @@ def find_target(self, game, array, range, value_extractor): continue range_calc = (game.distance(game.player, obj) - game.player.gameplay_radius - obj.gameplay_radius) - soldier_radius = 325.0 - soldier = skills.soldier_near_obj(game, obj) - if soldier is not None: - range_calc = (game.distance(soldier, obj)) - if range_calc > soldier_radius: - continue - else: - if range_calc > range: - continue - + #check if our champ is one of special_orbwalk_champs + if game.player.name in self.special_targeting_champs: + if game.player.name == "azir": + soldier = skills.soldier_near_obj(game, obj) + + if soldier is not None: + range_calc = (game.distance(soldier, obj)) + if range_calc > self.special_targeting_champs[game.player.name]: + continue + else: + if range_calc > range: + continue + elif game.player.name == "cassiopeia": + skillQ = getattr(game.player, 'Q') + skillE = getattr(game.player, 'E') + useQ = False + #TODO: Move Cass Q range value into a data structure + if skillQ.get_current_cooldown(game.time) == 0.0 and range_calc < 850.0: + useQ = True + pass + if not useQ and (skillE.get_current_cooldown(game.time) > 0 or range_calc > self.special_targeting_champs[game.player.name]): + continue + val = value_extractor(game.player, obj) if val < min: diff --git a/GameplayScripts/object_viewer.py b/GameplayScripts/object_viewer.py index 202b3e18..da0f2c24 100644 --- a/GameplayScripts/object_viewer.py +++ b/GameplayScripts/object_viewer.py @@ -83,6 +83,7 @@ def draw_game_object(obj, ui, additional_draw = None, set_open=False): ui.separator() ui.dragfloat("health", obj.health) + ui.dragfloat("mana", obj.mana) ui.checkbox("is_alive", obj.is_alive) ui.separator() @@ -91,6 +92,7 @@ def draw_game_object(obj, ui, additional_draw = None, set_open=False): ui.dragfloat("armour", obj.armour) ui.dragfloat("magic_resist", obj.magic_resist) ui.dragfloat("ap", obj.ap) + ui.dragfloat("ability_haste", obj.ability_haste) ui.dragfloat("crit", obj.crit) ui.dragfloat("crit_multi", obj.crit_multi) diff --git a/GameplayScripts/orb_walker.py b/GameplayScripts/orb_walker.py index 6c150121..18901771 100644 --- a/GameplayScripts/orb_walker.py +++ b/GameplayScripts/orb_walker.py @@ -11,6 +11,7 @@ } last_attacked = 0 +last_cass_q = 0 last_moved = 0 key_attack_move = 0 @@ -42,12 +43,12 @@ targeting = TargetingConfig() -soldiers = { - #Name -> (radius, show_radius_circle, show_radius_circle_minimap, icon) - 'azirsoldier' : [325.0, True, False, "azir_w"] +#Used to branch orbwalking logic if Player is using one of these champs +special_orbwalk_champs = { + "azir": 0.0, + "cassiopeia": 0.0 } - def lview_load_cfg(cfg): global key_attack_move, key_orbwalk, key_lasthit, max_atk_speed, auto_last_hit, toggle_mode global targeting @@ -85,21 +86,21 @@ def lview_draw_settings(game, ui): 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 +#Added range parameter so we can specify custom minion targeting range based on champ ability range (like cass E for example) +def find_minion_target(game, range): + #atk_range = game.player.base_atk_range + game.player.gameplay_radius min_health = 9999999999 player_target = None for minion in game.minions: - if minion.is_visible and minion.is_enemy_to(game.player) and minion.is_alive and minion.health < min_health and game.distance(game.player, minion) < atk_range: + if minion.is_visible and minion.is_enemy_to(game.player) and minion.is_alive and minion.health < min_health and game.distance(game.player, minion) < range: if skills.is_last_hitable(game, game.player, minion): player_target = minion min_health = minion.health return player_target +#We rely on skills.soldier_near_obj to calculate the range and retrieve the soldier data for soldier's minion target def find_soldier_minion_target(game): - soldier_affect_range = 650.0 - soldier_radius = 325.0 min_health = 9999999999 soldier_target = None for minion in game.minions: @@ -124,6 +125,7 @@ def champ_near_obj(game, champ): def get_target(game, last_hit_prio): global auto_last_hit global target + global special_orbwalk_champs atk_range = game.player.base_atk_range + game.player.gameplay_radius @@ -138,26 +140,30 @@ def get_target(game, last_hit_prio): if champ_near_obj(game, champ): target = targeting.get_target(game, atk_range) else: - target = None - + target = None elif not last_hit_prio: target = targeting.get_target(game, atk_range) if not target and auto_last_hit: - soldier = skills.is_soldier_alive(game) + if game.player.name in special_orbwalk_champs: + if game.player.name == "azir": + soldier = skills.is_soldier_alive(game) + + #only need to know if > 0 soldiers are up + if soldier is not None: + target = find_soldier_minion_target(game) + elif game.player.name == "cassiopeia": + target = find_minion_target(game, 711.0) - #only need to know if > 0 soldiers are up - if soldier is not None: - target = find_soldier_minion_target(game) - if not target: - target = find_minion_target(game) + target = find_minion_target(game, game.player.base_atk_range + game.player.gameplay_radius) - if not target and last_hit_prio: - target = targeting.get_target(game, atk_range) + #Unused for now, only use V for last hitting, don't expect V to harass champs + # if not target and last_hit_prio: + # target = targeting.get_target(game, atk_range) return target - + 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() @@ -189,13 +195,41 @@ def draw(game, obj, radius, show_circle_world, show_circle_map, icon): 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 cassQ(game, target): + global last_attacked + + skill = getattr(game.player, 'Q') + + cast_point = skills.castpoint_for_collision(game, skill, game.player, target) + if cast_point and game.distance(game.player, target) < 850.0: + cast_point = game.world_to_screen(cast_point) + cursor_pos = game.get_cursor() + game.move_cursor(cast_point) + skill.trigger() + time.sleep(0.01) + game.move_cursor(cursor_pos) + +def cassE(game, target): + global last_attacked + + skill = getattr(game.player, 'E') + + if game.distance(game.player, target) < 711.0: + cast_point = game.world_to_screen(target.pos) + cursor_pos = game.get_cursor() + game.move_cursor(cast_point) + skill.trigger() + time.sleep(0.01) + game.move_cursor(cursor_pos) + def lview_update(game, ui): - global last_attacked, alternate, last_moved + global last_attacked, last_cass_q, alternate, last_moved global key_attack_move, key_orbwalk, key_lasthit, max_atk_speed global toggle_mode, toggled global target - + global special_orbwalk_champs + if toggle_mode: if game.was_key_pressed(key_orbwalk): toggled = not toggled @@ -209,33 +243,54 @@ def lview_update(game, ui): if game.is_key_down(key_lasthit): last_hit_priority = True + #Show orbwalk target + if target is not None: + game.draw_circle_world(target.pos, 24.0, 16, 3, Color.WHITE) + #Use if you need to prevent orbwalker from interrupting your key presses: # for key in key_whitelist.items(): # if game.was_key_pressed(key): - # last_attacked = time.time() + # last_attacked = time.time() - #Handle basic attacks self = game.player + #Handle basic attacks 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 + t = time.time() + soldier_hitting = False - #Show orbwalk target - if target is not None: - game.draw_circle_world(target.pos, 24.0, 16, 3, Color.WHITE) - + #NEWWY DEWWY target = get_target(game, last_hit_priority) - t = time.time() - if t - last_attacked > max(c_atk_time, max_atk_time) and target: - last_attacked = t + + if game.player.name in special_orbwalk_champs: + if game.player.name == "azir": + if target: + soldier = skills.soldier_near_obj(game, target) + if soldier is not None: + soldier_hitting = True + elif game.player.name == "cassiopeia": + if target: + skillQ = getattr(game.player, 'Q') + skillE = getattr(game.player, 'E') + abilityHastePercent = (100 - 100/((1/100)*game.player.ability_haste + 1))/100 + + if t - last_cass_q >= (3.50 - (3.50 * abilityHastePercent)) and skillQ.get_current_cooldown(game.time) == 0 and game.player.mana > (50.0 + (10 * (skillQ.level-1))) and target and target.has_tags(UnitTag.Unit_Champion) and game.distance(game.player, target) < 850.0: + last_cass_q = t + cassQ(game, target) + if t - last_attacked >= (0.75 - (0.75 * abilityHastePercent)) and skillE.get_current_cooldown(game.time) == 0 and game.player.mana > 50.0 and target and game.distance(game.player, target) < 711.0: + last_attacked = t + cassE(game, target) - #Don't use press_key if you can avoid it, configure your ingame settings to support attack move on left click - #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() - \ No newline at end of file + if t - last_attacked >= max(c_atk_time, max_atk_time) and target and ((game.distance(game.player, target) < self.base_atk_range + self.gameplay_radius - target.gameplay_radius) or soldier_hitting): + last_attacked = t + cast_point = game.world_to_screen(target.pos) + cursor_pos = game.get_cursor() + game.move_cursor(cast_point) + game.press_right_click() + time.sleep(0.01) + game.move_cursor(cursor_pos) + elif t - last_attacked >= b_windup_time and t - last_moved > 0.08: + last_moved = t + game.press_right_click() \ No newline at end of file diff --git a/LView/GameObject.cpp b/LView/GameObject.cpp index 845767ca..21c1253f 100644 --- a/LView/GameObject.cpp +++ b/LView/GameObject.cpp @@ -101,6 +101,7 @@ void GameObject::LoadFromMem(DWORD base, HANDLE hProcess, bool deepLoad) { memcpy(&team, &buff[Offsets::ObjTeam], sizeof(short)); memcpy(&position, &buff[Offsets::ObjPos], sizeof(Vector3)); memcpy(&health, &buff[Offsets::ObjHealth], sizeof(float)); + memcpy(&mana, &buff[Offsets::ObjMana], sizeof(float)); memcpy(&maxHealth, &buff[Offsets::ObjMaxHealth], sizeof(float)); memcpy(&baseAttack, &buff[Offsets::ObjBaseAtk], sizeof(float)); memcpy(&bonusAttack, &buff[Offsets::ObjBonusAtk], sizeof(float)); @@ -112,6 +113,7 @@ void GameObject::LoadFromMem(DWORD base, HANDLE hProcess, bool deepLoad) { memcpy(&crit, &buff[Offsets::ObjCrit], sizeof(float)); memcpy(&critMulti, &buff[Offsets::ObjCritMulti], sizeof(float)); memcpy(&abilityPower, &buff[Offsets::ObjAbilityPower], sizeof(float)); + memcpy(&abilityHaste, &buff[Offsets::ObjAbilityHaste], sizeof(float)); memcpy(&atkSpeedMulti, &buff[Offsets::ObjAtkSpeedMulti], sizeof(float)); memcpy(&movementSpeed, &buff[Offsets::ObjMoveSpeed], sizeof(float)); memcpy(&networkId, &buff[Offsets::ObjNetworkID], sizeof(DWORD)); diff --git a/LView/GameObject.h b/LView/GameObject.h index 9027c506..c908f06d 100644 --- a/LView/GameObject.h +++ b/LView/GameObject.h @@ -53,6 +53,7 @@ class GameObject: MemoryLoadable, SpellInterface { public: float health; + float mana; float maxHealth; float baseAttack; float bonusAttack; @@ -61,6 +62,7 @@ class GameObject: MemoryLoadable, SpellInterface { float crit; float critMulti; float abilityPower; + float abilityHaste; float atkSpeedMulti; float movementSpeed; float duration; diff --git a/LView/Offsets.cpp b/LView/Offsets.cpp index 1793a32c..079c8220 100644 --- a/LView/Offsets.cpp +++ b/LView/Offsets.cpp @@ -5,14 +5,14 @@ Offsets::Offsets() {}; int Offsets::GameTime = 0x02f6d134; // 11.6 ==> 11.7 int Offsets::GameVersion = 0x2F872D8; // 11.6 ==> 11.7 -int Offsets::ViewProjMatrices = 0x02f97ff0; // 11.6 ==> 11.7 -int Offsets::Renderer = 0x02f9add0; // 11.6 ==> 11.7 +int Offsets::ViewProjMatrices = 0x2f97ff0; // 11.6 ==> 11.7 +int Offsets::Renderer = 0x2f9add0; // 11.6 ==> 11.7 int Offsets::RendererWidth = 0x0C; // 11.6 ==> 11.7 int Offsets::RendererHeight = 0x10; // 11.6 ==> 11.7 -int Offsets::ObjectManager = 0x016d85b8; // 11.6 ==> 11.7 -int Offsets::LocalPlayer = 0x02f7513c; // 11.6 ==> 11.7 -int Offsets::UnderMouseObject = 0x2346840; // 11.6 ==> 11.7 +int Offsets::ObjectManager = 0x16d85b8; // 11.6 ==> 11.7 +int Offsets::LocalPlayer = 0x2f7513c; // 11.6 ==> 11.7 +int Offsets::UnderMouseObject = 0x2326780; // 11.6 ==> 11.7 int Offsets::Chat = 0x02f75208; int Offsets::ChatIsOpen = 0x650; @@ -89,7 +89,7 @@ int Offsets::ObjectMapRoot = 0x28; int Offsets::ObjectMapNodeNetId = 0x10; int Offsets::ObjectMapNodeObject = 0x14; -int Offsets::MinimapObject = 0x02f74b38; // 11.6 ==> 11.7 +int Offsets::MinimapObject = 0x2f74b38; // 11.6 ==> 11.7 int Offsets::MinimapObjectHud = 0x88; int Offsets::MinimapHudPos = 0x60; int Offsets::MinimapHudSize = 0x68; diff --git a/LView/PyStructs.h b/LView/PyStructs.h index 79ee030a..bacf1359 100644 --- a/LView/PyStructs.h +++ b/LView/PyStructs.h @@ -78,6 +78,7 @@ BOOST_PYTHON_MODULE(lview) { class_("Obj") .def_readonly("address", &GameObject::address) .def_readonly("health", &GameObject::health) + .def_readonly("mana", &GameObject::mana) .def_readonly("max_health", &GameObject::maxHealth) .def_readonly("base_atk", &GameObject::baseAttack) .def_readonly("bonus_atk", &GameObject::bonusAttack) @@ -96,6 +97,7 @@ BOOST_PYTHON_MODULE(lview) { .def_readonly("crit", &GameObject::crit) .def_readonly("crit_multi", &GameObject::critMulti) .def_readonly("ap", &GameObject::abilityPower) + .def_readonly("ability_haste", &GameObject::abilityHaste) .def_readonly("atk_speed_multi", &GameObject::atkSpeedMulti) .def_readonly("team", &GameObject::team) diff --git a/LView/config.ini b/LView/config.ini index 4dc88e63..02cc11e7 100644 --- a/LView/config.ini +++ b/LView/config.ini @@ -2,7 +2,7 @@ Auto Smite::enable_key=41 Auto Smite::enabled=1 Auto Smite::show_smitable=1 -Auto Spell::cast_keys={"Q": 2, "W": 3, "E": 4, "R": 5} +Auto Spell::cast_keys={"Q": 0, "W": 0, "E": 0, "R": 0} Auto Spell::enabled=1 Auto Spell::target_jungle=1 Auto Spell::target_minions=1 diff --git a/UtilityScripts/cass.ahk b/UtilityScripts/cass.ahk new file mode 100644 index 00000000..a813ddb8 --- /dev/null +++ b/UtilityScripts/cass.ahk @@ -0,0 +1,34 @@ +#NoEnv +#MaxHotkeysPerInterval 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 +#Persistent +#InstallKeybdHook +#InstallMouseHook + +#If leagueClientActive() +/* $e:: + * While(GetKeyState("e","P")) { + * Send, e + * Sleep, 004 + * } + * Return + */ + $w:: + While(GetKeyState("w","P")) { + Send, w + Sleep, 004 + } + Return + + $r:: + While(GetKeyState("r","P")) { + Send, r + Sleep, 004 + } + Return + + +#If + +leagueClientActive() { + return WinActive("ahk_class RiotWindowClass") +} From ebef85e872e2e596d95eb952a20387302bf59141 Mon Sep 17 00:00:00 2001 From: Billybishop <30381194+Billybishop@users.noreply.github.com> Date: Sat, 3 Apr 2021 19:57:18 -0400 Subject: [PATCH 19/19] Update README.md Updated readme to cross out some usage details --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3fc6c13a..710c4e9c 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ These are the settings I find help LView operate the most accurately. If you're having issues with LView misclicking or orbwalker missing last hits, please make sure you've done the following first: - Set attack move to on cursor in game settings - Set auto attack off in game settings -- Checkbox the option to bind autoattack to left click in game settings -- Bind target champions only to space bar and V key for primary and secondary keybind (for both orbwalk modes) and make sure it's not set to toggle in game settings +- ~~Checkbox the option to bind autoattack to left click in game settings~~ +- ~~Bind target champions only to space bar and V key for primary and secondary keybind (for both orbwalk modes) and make sure it's not set to toggle in game settings~~ # Fork Details !!! IMPORTANT !!! This uses VS2019 and the mvc142 toolkit, please be sure your environment matches this configuration before attempting to build, and ofcourse you will still need to follow the steps outlined for the original project. Orkido on UC has documented much of what you need to do in order to get the project building from VS2019 so if you have trouble please search the LView thread for his comments on the matter.