diff --git a/Set12Simulator/ability.py b/Set12Simulator/ability.py index 1674160..670696e 100755 --- a/Set12Simulator/ability.py +++ b/Set12Simulator/ability.py @@ -57,2838 +57,184 @@ def apply_attack_cooldown(champion, halved=True): champion.add_que('clear_idle', (1 / champion.AS * 1000) / halver) -# Aatrox pulls some of the farthest enemies toward himself, then slams the ground in front of himself, -# dealing magic damage to all enemies hit. -def aatrox(champion): - champion.add_que('change_stat', -1, None, 'ability_active', True) - default_ability_calls(champion) - - champion.add_que('change_stat', stats.ABILITY_LENGTH[champion.name], None, 'ability_active', False) - - enemies = field.find_enemies(champion) - - enemy_amount = len(enemies) - enemies_pulled = stats.ABILITY_TARGETS[champion.name][champion.stars] - - # pull max amount of targets. for example if 3 star aatrox wants to pull 5 but there's 3 alive, pull 2 instead - if enemy_amount < enemies_pulled + 1: - enemies_pulled = enemy_amount - 1 - for i in range(1, enemies_pulled + 1): - - free_hexes = [] - target_neighbors = field.find_neighbors(champion.target.y, champion.target.x) - - for n in target_neighbors: - c = field.coordinates[n[0]][n[1]] - if c is None: - free_hexes.append(n) - - # break if there's no more space around the target unit. this should be implemented better - if len(free_hexes) == 0: - break - - for h in free_hexes: - d = field.distance({'y': enemies[-i][0].y, 'x': enemies[-i][0].x}, {'y': h[0], 'x': h[1]}, False) - h.append(d) - free_hexes.sort(key=lambda x: x[2]) - - enemies[-i][0].move(free_hexes[0][0], free_hexes[0][1], True) - - champion.add_que('execute_function', stats.ABILITY_LENGTH[champion.name], - [aatrox_ability, {'y': champion.target.y, 'x': champion.target.x}]) - - -def aatrox_ability(champion, data): - neighbors = field.find_neighbors(data['y'], data['x']) - neighbors.append([data['y'], data['x']]) - - c = field.coordinates - for n in neighbors: - if c[n[0]][n[1]] and c[n[0]][n[1]].team != champion.team and c[n[0]][n[1]].champion: - champion.spell(c[n[0]][n[1]], stats.ABILITY_DMG[champion.name][champion.stars]) - - apply_attack_cooldown(champion) - def ahri(champion): - champion.idle = False - champion.clear_que_idle() - champion.add_que('clear_idle', stats.ABILITY_LENGTH[champion.name]) - default_ability_calls(champion) - - champion.add_que('execute_function', stats.ABILITY_LENGTH[champion.name], - [ahri_ability, {'y': champion.target.y, 'x': champion.target.x}]) - - -def ahri_ability(champion, data): - radius = stats.ABILITY_RADIUS[champion.name] - # interruption - if champion.stunned or champion.health <= 0: - radius = stats.ABILITY_RADIUS[champion.name] - 1 - - enemies = field.enemies_in_distance(champion, data['y'], data['x'], radius) - for e in enemies: - champion.spell(e, stats.ABILITY_DMG[champion.name][champion.stars]) - - apply_attack_cooldown(champion) - + return def akali(champion): - default_ability_calls(champion) - champion.spell(champion.target, stats.ABILITY_DMG[champion.name][champion.stars]) - - apply_attack_cooldown(champion) - - -# making a cone is not that fun -def annie(champion): - default_ability_calls(champion) - - # 1. find hex that is our neighbor and closest to the target - neighbors = field.find_neighbors(champion.y, champion.x) - if neighbors: - for n in neighbors: - try: - d = field.distance({'y': champion.target.y, 'x': champion.target.x}, {'y': n[0], 'x': n[1]}, False) - n.append(d) - except AttributeError: - print('passing') - pass - # making sure that distance was added - if len(neighbors[0]) == 3: - neighbors = sorted(neighbors, key=lambda x: x[2]) - - # 2. find hex that is 1's neigbor and furthest away from us - # 3 leave the neighbor out of the spell which is in a line's way that's drawn from champion to 'cone_center' - - spell_target = neighbors[0] - - direction_y = spell_target[0] - champion.y + 1 - if champion.y % 2 == 0: - direction_x = spell_target[1] - champion.x + 1 - cone_center_table = [ - [[], [-2, -1], [-2, 1]], - [[0, -2], [], [0, 2]], - [[], [2, -1], [2, 1]] - ] - - leave_out_table = [ - [[], [-3, -1], [-3, 2]], - [[0, -3], [], [0, 2]], - [[], [3, -1], [3, 2]] - ] - - cone_center = [champion.y + cone_center_table[direction_y][direction_x][0], - champion.x + cone_center_table[direction_y][direction_x][1]] - leave_out = [champion.y + leave_out_table[direction_y][direction_x][0], - champion.x + leave_out_table[direction_y][direction_x][1]] - else: - direction_x = spell_target[1] - champion.x + 1 - cone_center_table = [ - [[-2, -1], [-2, 1], []], - [[0, -2], [], [0, 2]], - [[2, -1], [2, 1], []] - ] - - leave_out_table = [ - [[-3, -2], [-3, 1], []], - [[0, -3], [], [0, 3]], - [[3, -2], [3, 1], []] - ] - cone_center = [champion.y + cone_center_table[direction_y][direction_x][0], - champion.x + cone_center_table[direction_y][direction_x][1]] - leave_out = [champion.y + leave_out_table[direction_y][direction_x][0], - champion.x + leave_out_table[direction_y][direction_x][1]] - else: - cone_center = [champion.target.y, champion.target.x] - leave_out = [] - - neighbors = field.find_neighbors(cone_center[0], cone_center[1]) - neighbors.append(cone_center) - for n in neighbors: - if n != leave_out and n[0] >= 0 and n[1] >= 0 and n[0] < 8 and n[1] < 7 and field.coordinates[n[0]][n[1]] \ - and field.coordinates[n[0]][n[1]].team != champion.team and field.coordinates[n[0]][n[1]].champion: - champion.spell(field.coordinates[n[0]][n[1]], stats.ABILITY_DMG[champion.name][champion.stars]) - - apply_attack_cooldown(champion) - shield_amount = stats.SHIELD_AMOUNT[champion.name][champion.stars] * champion.SP - champion.add_que('shield', 0, None, None, - {'amount': shield_amount, 'identifier': champion_functions.MILLIS() * shield_amount, - 'applier': champion, 'original_amount': shield_amount}, - {'increase': True, 'expires': stats.SHIELD_LENGTH[champion.name]}) - - -def aphelios(champion): - default_ability_calls(champion) - - c = None - while c is None: - y = random.randint(0, 7) - x = random.randint(0, 6) - if y == 0 or y == 7 and x == 0 or x == 6 and field.coordinates[y][x] is None: - c = [y, x] - - turret = champion.spawn('aphelios_turret', champion.stars, c[0], c[1], champion.team, False) - champion.underlords.append(turret) - champion.add_que('kill', stats.ABILITY_LENGTH[champion.name][champion.stars] * champion.SP, None, None, turret) - - -# also in champion_functions.py: attack() + return + def ashe(champion): - default_ability_calls(champion) + return - # to ensure the changes to go through before the initial attack, - # we'll just set the change time to be CURRENT TIME - 1 MS - # using ezreal's AS change logic - as_gain = (stats.ABILITY_AS_GAIN[champion.name][champion.stars] - 1) * champion.SP + 1 - champion.add_que('change_stat', -1, None, 'AS', champion.AS * as_gain) - champion.add_que('change_stat', stats.ABILITY_LENGTH[champion.name], None, 'AS', None, {'ezreal': as_gain}) +def bard(champion): + return - champion.add_que('change_stat', -1, None, 'ability_active', True) - champion.add_que('change_stat', stats.ABILITY_LENGTH[champion.name], None, 'ability_active', False) +def blitzcrank(champion): + return +def briar(champion): + return -def ashe_helper(champion, data): - target = data['target'] - items.guinsoos_rageblade(champion) # guinsoos_rageblade - items.statikk_shiv(champion, target) # statikk_shiv - items.runaans_hurricane(champion, target) # runaans_hurricane +def camille(champion): + return - if target.health < 0: - field.find_target(champion) - target = champion.target - for i in range(0, stats.ABILITY_SLICES[champion.name]): - if target: - champion.attack(data['bonus_dmg'], target, False, ' ability', - champion.AD * stats.ABILITY_DAMAGE_MULTIPLIER[champion.name]) - - -def azir(champion): - default_ability_calls(champion) - ability_rectangle_width = 3 - affected_hexes = field.rectangle_from_champion_to_wall_behind_target(champion, ability_rectangle_width, - champion.target.y, champion.target.x) - - longest_line = max([len(affected_hexes[0]), len(affected_hexes[1]), len(affected_hexes[2])]) - - # base_delay = stats.ABILITY_LENGTH[champion.name] / longest_line - already_targeted = [] - - # the whole azir ult executive process - # the line of dudes is three wide - for i in range(0, longest_line): - for j in range(0, ability_rectangle_width): - - # if some line is longer, skip the rest of the iterations regarding this line - if len(affected_hexes[j]) > i: - # current coordinate - c = field.coordinates[affected_hexes[j][i][0]][affected_hexes[j][i][1]] - if c and c.team != champion.team and c.champion and c not in already_targeted: - - # if this coordinate is within the pushing range, find a new coordinate for the minion - if affected_hexes[j][i][2] <= 3: - push_coordinates = None - push_counter = 1 - while not push_coordinates: - if i + push_counter < len(affected_hexes[j]): - if field.coordinates[affected_hexes[j][i + push_counter][0]][ - affected_hexes[j][i + push_counter][1]] is None: - push_coordinates = [affected_hexes[j][i + push_counter][0], - affected_hexes[j][i + push_counter][1]] - else: - push_counter += 1 - else: - break - if push_coordinates: - c.move(push_coordinates[0], push_coordinates[1], True) - already_targeted.append(c) - - # if not, then just stun for 2 seconds - else: - c.add_que('change_stat', -1, None, 'stunned', True) - c.clear_que_stunned_removal() - c.add_que('change_stat', stats.ABILITY_STUN_DURATION[champion.name][champion.stars], None, - 'stunned', False) - already_targeted.append(c) - - champion.spell(c, stats.ABILITY_DMG[champion.name][champion.stars]) - c.add_que('change_stat', 0, None, 'movement_delay', - c.movement_delay * stats.ABILITY_SLOW_AMOUNT[champion.name]) - c.add_que('change_stat', stats.ABILITY_SLOW_DURATION[champion.name], None, 'movement_delay', - champion_functions.reset_stat(c, 'movement_delay')) - - -# forming cones with hexagonal coordinates is absolute aids -# the code is shit but does the job def cassiopeia(champion): - default_ability_calls(champion) - target = champion.target - - # all coords that are 4 tiles away - four_tiles_away = [] - for i in range(-5, 12): - for j in range(-5, 11): - if field.distance({'y': champion.y, 'x': champion.x}, {'y': i, 'x': j}, False) == 4: - four_tiles_away.append([i, j]) - - # get a line from the target to the tiles that are 4 distance away - # then do the same but from the champion itself - # if the target --> tile -line hexes are all in the champion --> - # tile -line, choose that end tile to be the cone end point - line_end_point = [] - for f in four_tiles_away: - - champion_line = (field.line({'y': champion.y, 'x': champion.x}, {'y': f[0], 'x': f[1]})) - target_line = (field.line({'y': target.y, 'x': target.x}, {'y': f[0], 'x': f[1]})) - - includes_all = True - for t in target_line: - if t not in champion_line: - includes_all = False - break - - if includes_all: - line_end_point.append([f[0], f[1]]) - - if not line_end_point: - print("Someone figure out why cassiopeia is dying") - return - line_end_point = line_end_point[0] - # line_end_point = line_end_point[random.randint(0,len(line_end_point) - 1)] - - # find the cone corners. rules: 2 hexes from cone end, 4 hexes from champion - cone_corners = [] - for f in four_tiles_away: - d_from_champion = field.distance({'y': champion.y, 'x': champion.x}, {'y': f[0], 'x': f[1]}, False) - d_from_end_point = field.distance({'y': line_end_point[0], 'x': line_end_point[1]}, {'y': f[0], 'x': f[1]}, - False) - if d_from_champion == 4 and d_from_end_point == 2: - cone_corners.append([f[0], f[1]]) - - # the hexes between the cone end point and the corners - side_points = [] - for f in four_tiles_away: - d_from_first_corner = field.distance({'y': cone_corners[0][0], 'x': cone_corners[0][1]}, {'y': f[0], 'x': f[1]}, - False) - d_from_second_corner = field.distance({'y': cone_corners[1][0], 'x': cone_corners[1][1]}, - {'y': f[0], 'x': f[1]}, False) - d_from_end_point = field.distance({'y': line_end_point[0], 'x': line_end_point[1]}, {'y': f[0], 'x': f[1]}, - False) - if d_from_end_point == 1 and (d_from_first_corner == 1 or d_from_second_corner == 1): - side_points.append([f[0], f[1]]) - - # the middle of the cone: find a certain coord (pic) and choose that and all its neighbors - # the coord should be 2 from end point, 2 from champion and 2-3 from the corners (2 preferred). - mid_hex = None - mid_hex_secondary = None - for i in range(-5, 12): - for j in range(-5, 11): - f = [i, j] - d_from_first_corner = field.distance({'y': cone_corners[0][0], 'x': cone_corners[0][1]}, - {'y': f[0], 'x': f[1]}, False) - d_from_second_corner = field.distance({'y': cone_corners[1][0], 'x': cone_corners[1][1]}, - {'y': f[0], 'x': f[1]}, False) - d_from_end_point = field.distance({'y': line_end_point[0], 'x': line_end_point[1]}, {'y': f[0], 'x': f[1]}, - False) - d_from_champion = field.distance({'y': champion.y, 'x': champion.x}, {'y': f[0], 'x': f[1]}, False) - - if d_from_end_point == 2 and d_from_first_corner == 2 and \ - d_from_second_corner == 2 and d_from_champion == 2: - mid_hex = f - if (d_from_end_point == 2 and d_from_first_corner == 3 and - d_from_second_corner == 3 and d_from_champion == 2): - mid_hex_secondary = f - - # if the hexes align the right way, there's two extra coords that need to be added. one next to each corner - additional_coords = [] - if not mid_hex_secondary and not mid_hex: - mid_hex = [target.y, target.x] - elif not mid_hex: - mid_hex = mid_hex_secondary - for i in range(-5, 12): - for j in range(-5, 11): - f = [i, j] - d_from_first_corner = field.distance({'y': cone_corners[0][0], 'x': cone_corners[0][1]}, - {'y': f[0], 'x': f[1]}, False) - d_from_second_corner = field.distance({'y': cone_corners[1][0], 'x': cone_corners[1][1]}, - {'y': f[0], 'x': f[1]}, False) - d_from_champion = field.distance({'y': champion.y, 'x': champion.x}, {'y': f[0], 'x': f[1]}, False) - - if (d_from_first_corner == 1 or d_from_second_corner == 1) and d_from_champion == 3: - additional_coords.append(f) - - mid_hex_neighbors = [] - if mid_hex: - mid_hex_neighbors = field.find_neighbors(mid_hex[0], mid_hex[1]) - - cone = mid_hex_neighbors - cone.append(mid_hex) - cone.append(side_points[0]) - cone.append(side_points[1]) - cone.append(cone_corners[0]) - cone.append(cone_corners[1]) - cone.append(line_end_point) - if len(additional_coords) == 2: - cone.append(additional_coords[0]) - cone.append(additional_coords[1]) - - # deal the damage and stun the targets etc - already_targeted = [] - for c in cone: - coords = field.coordinates - if 7 >= c[0] >= 0 <= c[1] <= 6: - h = coords[c[0]][c[1]] - if h and h.team != champion.team and h.champion and h not in already_targeted: - # h.add_que('change_stat', -1, None, 'stunned', True) - # adding this when creating 'quicksilver' but seems like we had a reason to stun them here locally - if not ('quicksilver' in h.items and champion_functions.MILLIS() <= - item_stats.item_change_length['quicksilver']): - h.print(' {} {} --> {}'.format('stunned', h.stunned, True)) - h.stunned = True - h.clear_que_stunned_removal() - - h.add_que('change_stat', stats.ABILITY_STUN_DURATION[champion.name][champion.stars], - None, 'stunned', False) - else: - h.print(' not stunned because wears quicksilver') - - dmg_increase = stats.ABILITY_TARGET_INCREASE_DAMAGE_RECEIVING[champion.name] - h.print(' {} {} --> {}'.format('receive_increased_damage', h.receive_increased_damage, - round(dmg_increase * champion.SP, 3))) - h.receive_increased_damage = dmg_increase * champion.SP - - h.add_que('change_stat', stats.ABILITY_STUN_DURATION[champion.name][champion.stars], - None, 'receive_increased_damage', 1) - champion.spell(h, stats.ABILITY_DMG[champion.name][champion.stars]) - - already_targeted.append(h) - - apply_attack_cooldown(champion) - + return def diana(champion): - default_ability_calls(champion) - champion.add_que('change_stat', -1, None, 'ability_active', True) - - shield_identifier = champion_functions.MILLIS() * stats.SHIELD_AMOUNT[champion.name][champion.stars] * champion.SP - shield_amount = stats.SHIELD_AMOUNT[champion.name][champion.stars] * champion.SP - champion.add_que('shield', 0, None, None, {'amount': shield_amount, 'identifier': shield_identifier, - 'applier': champion, 'original_amount': shield_amount}, - {'increase': True, 'expires': stats.SHIELD_LENGTH[champion.name]}) - - neighbors = field.find_neighbors(champion.y, champion.x) - orbs = [] - - neighbor_amount = len(field.find_neighbors(champion.y, champion.x)) - n_a = neighbor_amount - for i in range(0, stats.ABILITY_TARGETS[champion.name][champion.stars]): - orbs.append( - {'y': neighbors[i % n_a][0], 'x': neighbors[i % n_a][1], 'index': i % n_a, 'orbs': orbs, 'identifier': i, - 'shield_identifier': shield_identifier}) - - for o in orbs: - champion.add_que('execute_function', 0, [diana_ability, o]) - - -# spin the orbs -def diana_ability(champion, data): - turn_speed_per_hex = 1500 / 6 - - # hit the enemy if there's someone in the orb's coordinates - c = field.coordinates[data['y']][data['x']] - if c and c.team != champion.team and c.champion: - - if data in data['orbs']: - data['orbs'].remove(data) - - if len(data['orbs']) == 0: - - for s in champion.shields: - if s['identifier'] == data['shield_identifier']: - shield_before = champion.shield_amount() - champion.shields.remove(s) - champion.print( - ' {} {} --> {}'.format('shield', ceil(shield_before), ceil(champion.shield_amount()))) - break - - shield_identifier = champion_functions.MILLIS() * stats.SHIELD_AMOUNT[champion.name][ - champion.stars] * champion.SP - shield_amount = stats.SHIELD_AMOUNT[champion.name][champion.stars] * champion.SP - - champion.add_que('shield', 0, None, None, - {'amount': shield_amount, 'identifier': shield_identifier, 'applier': champion, - 'original_amount': shield_amount}, - {'increase': True, 'expires': stats.SHIELD_LENGTH[champion.name]}) - champion.add_que('change_stat', 0, None, 'ability_active', False) - - # if not, spin the orbs. - else: - neighbors = field.find_neighbors(champion.y, champion.x) - data['index'] += 1 - if data['index'] >= len(neighbors): - data['index'] = 0 - - data['y'] = neighbors[(data['index']) % len(neighbors)][0] - data['x'] = neighbors[(data['index']) % len(neighbors)][1] - for i, d in enumerate(data['orbs']): - if d['identifier'] == data['identifier']: - data['orbs'][i] = data - - champion.add_que('execute_function', turn_speed_per_hex, [diana_ability, data]) - + return def elise(champion): - default_ability_calls(champion) - champion.add_que('change_stat', -1, None, 'ability_active', True) - - # to ensure both, the health change and health per attack -changes to happen BEFORE the auto attack goes through, - # we have to mark these changes as high priority - champion.add_que('change_stat', -2, None, 'health', - champion.health + (stats.HEALTH[champion.name] * config.STARMULTIPLIER ** (champion.stars - 1)) - * (stats.ABILITY_HEALTH_GAIN_PERCENTAGES[champion.name][champion.stars] - 1)) - - champion.add_que('change_stat', -1, None, 'heal_per_attack', - champion.heal_per_attack + stats.ABILITY_HEALTH_PER_ATTACK[champion.name][champion.stars]) - champion.add_que('change_stat', -1, None, 'max_health', - champion.max_health * stats.ABILITY_HEALTH_GAIN_PERCENTAGES[champion.name][champion.stars]) - - -def evelynn(champion): - default_ability_calls(champion) - - r = random.randint(1, 100) / 100 - targets = 1 - if r > stats.ABILITY_TARGET_PROBABILITIES[champion.name][3]: - targets = 3 - elif r > stats.ABILITY_TARGET_PROBABILITIES[champion.name][2]: - targets = 2 - - if champion.target is None: - field.find_target(champion) - target_y = champion.target.y - target_x = champion.target.x - - # find a bunch of close by targets and deal the dmg - enemies_around_target = field.enemies_in_distance(champion, champion.target.y, champion.target.x, 1) - if champion.target in enemies_around_target: - enemies_around_target.remove(champion.target) - enemies_around_target.insert(0, champion.target) - - for i in range(0, targets): - if i > len(enemies_around_target) - 1: - break - - target_dmg = stats.ABILITY_DMG[champion.name][champion.stars] - if (enemies_around_target[i].health / enemies_around_target[i].max_health) < 0.5: - target_dmg *= stats.ABILITY_DAMAGE_MULTIPLIER[champion.name][champion.stars] - - champion.spell(enemies_around_target[i], target_dmg) - - # find a hex that's 3 away from champion and 4 away from the target - teleport_hexes = [] - for i in range(0, 7): - for j in range(0, 6): - d_from_champion = field.distance({'y': champion.y, 'x': champion.x}, {'y': i, 'x': j}, False) - d_from_target = field.distance({'y': target_y, 'x': target_x}, {'y': i, 'x': j}, False) - if d_from_champion == 3 and d_from_target == 4: - teleport_hexes.append([i, j]) - # if there's none, just pick the neighbors - if len(teleport_hexes) == 0: - teleport_hexes = field.find_neighbors(champion.y, champion.x) - - # make sure that we teleport backwards - if champion.y > target_y: - teleport_hexes = list(filter(lambda x: x[0] > target_y, teleport_hexes)) - if champion.y < target_y: - teleport_hexes = list(filter(lambda x: x[0] < target_y, teleport_hexes)) - - if len(teleport_hexes) > 0: - teleport_target = teleport_hexes[random.randint(0, len(teleport_hexes) - 1)] - champion.clear_que_idle() - champion.move(teleport_target[0], teleport_target[1], True) - + return def ezreal(champion): - default_ability_calls(champion) - champion.idle = False - champion.clear_que_idle() - champion.add_que('clear_idle', stats.ABILITY_LENGTH[champion.name]) - - champion.add_que('execute_function', stats.ABILITY_LENGTH[champion.name], - [ezreal_ability, {'y': champion.target.y, 'x': champion.target.x}]) - - -def ezreal_ability(champion, data): - ability_rectangle_width = 5 - - target_y = data['y'] - target_x = data['x'] - - # get the hexes of which the ult passes through - affected_hexes = field.rectangle_from_champion_to_wall_behind_target(champion, ability_rectangle_width, target_y, - target_x) - - longest_line = max([len(affected_hexes[0]), len(affected_hexes[1]), len(affected_hexes[2]), len(affected_hexes[3]), - len(affected_hexes[4])]) - - already_targeted = [] - - for i in range(0, longest_line): - for j in range(0, ability_rectangle_width): - - # if some line is longer, skip the rest of the iterations regarding this line - if len(affected_hexes[j]) > i: - # current coordinate - c = field.coordinates[affected_hexes[j][i][0]][affected_hexes[j][i][1]] - if c and c.team != champion.team and c.champion and c not in already_targeted: - champion.spell(c, stats.ABILITY_DMG[champion.name][champion.stars]) - - c.add_que('change_stat', -1, None, 'AS', - c.AS * stats.ABILITY_AS_DECREASE[champion.name][champion.stars]) - c.add_que('change_stat', stats.ABILITY_AS_CHANGE_LENGTH[champion.name], None, 'AS', None, - {'ezreal': stats.ABILITY_AS_DECREASE[champion.name][champion.stars]}) - - already_targeted.append(c) - - if c and c.team == champion.team and c.champion and c not in already_targeted and c is not champion: - c.add_que('heal', -1, None, None, stats.ABILITY_HEAL[champion.name][champion.stars] * champion.SP) - - c.add_que('change_stat', -1, None, 'AS', - c.AS * stats.ABILITY_AS_GAIN[champion.name][champion.stars]) - c.add_que('change_stat', stats.ABILITY_AS_CHANGE_LENGTH[champion.name], None, 'AS', None, - {'ezreal': stats.ABILITY_AS_GAIN[champion.name][champion.stars]}) - already_targeted.append(c) - - apply_attack_cooldown(champion) - + return def fiora(champion): - default_ability_calls(champion) - champion.idle = False - champion.clear_que_idle() - champion.add_que('clear_idle', stats.ABILITY_LENGTH[champion.name]) - - champion.add_que('change_stat', -1, None, 'immune', True) - champion.add_que('change_stat', stats.ABILITY_LENGTH[champion.name], None, 'immune', False) - - champion.add_que('execute_function', stats.ABILITY_LENGTH[champion.name], [fiora_ability, {}]) - - -def fiora_ability(champion, data): - if not champion.target: - field.find_target(champion) - - if champion.target: - champion.target.add_que('change_stat', -1, None, 'stunned', True) - champion.target.clear_que_stunned_removal() - champion.target.add_que('change_stat', stats.ABILITY_STUN_DURATION[champion.name][champion.stars], None, - 'stunned', False) - - champion.spell(champion.target, stats.ABILITY_DMG[champion.name][champion.stars]) + return - apply_attack_cooldown(champion, False) - - -def garen(champion): - default_ability_calls(champion) - champion.add_que('change_stat', -1, None, 'ability_active', True) - champion.add_que('change_stat', stats.ABILITY_LENGTH[champion.name], None, 'ability_active', False) - - champion.add_que('change_stat', -1, None, 'spell_damage_reduction_percentage', - champion.spell_damage_reduction_percentage * stats.ABILITY_SPELL_DAMAGE_REDUCTION_PERCENTAGE[ - champion.name]) - champion.add_que('change_stat', stats.ABILITY_LENGTH[champion.name], None, 'spell_damage_reduction_percentage', - None, {'garen': stats.ABILITY_SPELL_DAMAGE_REDUCTION_PERCENTAGE[champion.name]}) - - ms = 50 - for i in range(0, stats.ABILITY_SLICES[champion.name]): - champion.add_que('execute_function', - ms + i * (stats.ABILITY_LENGTH[champion.name] / stats.ABILITY_SLICES[champion.name]), - [garen_ability, {}]) - - -def garen_ability(champion, data): - neighbors = field.find_neighbors(champion.y, champion.x) - team = champion.team - enemies_around = [] - for n in neighbors: - c = field.coordinates[n[0]][n[1]] - if c and c.team != team and c.champion: - enemies_around.append(c) - - # if(not champion.stunned): - for e in enemies_around: - champion.spell(e, stats.ABILITY_DMG[champion.name][champion.stars] / stats.ABILITY_SLICES[champion.name]) +def galio(champion): + return +def gwen(champion): + return def hecarim(champion): - champion.add_que('change_stat', -1, None, 'ability_active', True) - default_ability_calls(champion) - champion.add_que('change_stat', stats.ABILITY_LENGTH[champion.name], None, 'ability_active', False) - - for i in range(0, stats.ABILITY_SLICES[champion.name]): - champion.add_que('execute_function', - i * (stats.ABILITY_LENGTH[champion.name] / stats.ABILITY_SLICES[champion.name]), - [hecarim_ability, {}]) - - -def hecarim_ability(champion, data): - neighbors = field.find_neighbors(champion.y, champion.x) - - coords = field.coordinates - for n in neighbors: - c = coords[n[0]][n[1]] - if c and c.team != champion.team and c.champion: - champion.spell(c, stats.ABILITY_DMG[champion.name][champion.stars] / stats.ABILITY_SLICES[champion.name]) - champion.add_que('heal', -1, None, None, ( - stats.ABILITY_HEAL[champion.name][champion.stars] / - stats.ABILITY_SLICES[champion.name]) * champion.SP) - - -def irelia(champion): - default_ability_calls(champion) - ability_rectangle_width = 3 - - # get the hexes of which the ult passes through - affected_hexes = field.rectangle_from_champion_to_wall_behind_target(champion, ability_rectangle_width, - champion.target.y, champion.target.x) - - for i, line in enumerate(affected_hexes): - if len(line) > 3: - affected_hexes[i] = line[:3] - - longest_line = max([len(affected_hexes[0]), len(affected_hexes[1]), len(affected_hexes[2])]) - already_targeted = [] - - for i in range(0, longest_line): - for j in range(0, ability_rectangle_width): - - # if some line is longer, skip the rest of the iterations regarding this line - if len(affected_hexes[j]) > i: - c = field.coordinates[affected_hexes[j][i][0]][affected_hexes[j][i][1]] - if c and c.team != champion.team and c.champion and c not in already_targeted: - champion.spell(c, stats.ABILITY_DMG[champion.name][champion.stars]) - - c.add_que('change_stat', -1, None, 'disarmed', True) - c.add_que('change_stat', stats.ABILITY_DISARM_DURATION[champion.name][champion.stars], None, - 'disarmed', False) - - already_targeted.append(c) - - apply_attack_cooldown(champion) - - -def janna(champion): - default_ability_calls(champion) - ally_units = [] - if champion.team == 'blue': - ally_units = champion.blue_return() - if champion.team == 'red': - ally_units = champion.red_return() - - ally_units = sorted(ally_units, key=lambda x: x.health / x.max_health) - - shielded_units = stats.ABILITY_TARGETS[champion.name][champion.stars] - if len(ally_units) > shielded_units: - ally_units = ally_units[:shielded_units] - - for a in ally_units: - for i in range(0, 3): - for s in a.shields: - if s['applier'] == champion: - shield_before = a.shield_amount() - a.shields.remove(s) - a.print(' {} {} --> {}'.format('shield', ceil(shield_before), ceil(a.shield_amount()))) - break - - identifier = champion_functions.MILLIS() * stats.SHIELD_AMOUNT[champion.name][champion.stars] - shield_amount = stats.SHIELD_AMOUNT[champion.name][champion.stars] * champion.SP - a.add_que('shield', -1, None, None, {'amount': shield_amount, 'identifier': identifier, 'applier': champion, - 'original_amount': shield_amount}, - {'increase': True, 'expires': stats.SHIELD_LENGTH[champion.name]}) - - ad_gain_abs = stats.ABILITY_DMG_GAIN[champion.name][champion.stars] - if a.AD == 0: - percentual_ad_change = 1 - else: - percentual_ad_change = (ad_gain_abs / a.AD) + 1 - a.add_que('change_stat', -1, None, 'AD', a.AD * percentual_ad_change) - a.add_que('change_stat', stats.SHIELD_LENGTH[champion.name], None, 'AD', None, {'ashe': percentual_ad_change}) - - -def jarvaniv(champion): - default_ability_calls(champion) - enemies_plain = champion.enemy_team() - enemies = [] - - for i, e in enumerate(enemies_plain): - d = field.distance(champion, e, True) - enemies.append([e, d]) - - enemies = sorted(enemies, key=lambda x: x[1], reverse=True) - - target = enemies[0][0] - - # find the hex where jarvan moves to (closest free hex to the target) - hexes = [] - coords = field.coordinates - for i in range(0, 8): - for j in range(0, 7): - distance = field.distance({'y': i, 'x': j}, {'y': target.y, 'x': target.x}, False) - hexes.append([coords[i][j], distance, i, j]) - - hexes = sorted(hexes, key=lambda x: x[1]) - target_hex_y = None - target_hex_x = None - while target_hex_y is None: - if not hexes[0][0]: - target_hex_y = hexes[0][2] - target_hex_x = hexes[0][3] - else: - hexes = hexes[1:] - - # now find the path to the target hex and log its surroundings - path = field.line({'y': champion.y, 'x': champion.x}, {'y': target_hex_y, 'x': target_hex_x}) - - target_neighbors = field.find_neighbors(target_hex_y, target_hex_x) - path += target_neighbors - - already_targeted = [] - for p in path: - # print("IN JARVIN ABILITY") - # print(p) - if 0 <= p[0] < 8 and 0 <= p[1] < 7: - c = coords[p[0]][p[1]] - if c and c.team != champion.team and c.champion and c not in already_targeted: - c.add_que('change_stat', -1, None, 'stunned', True) - c.clear_que_stunned_removal() - c.add_que('change_stat', stats.ABILITY_STUN_DURATION[champion.name][champion.stars], None, 'stunned', - False) - - champion.spell(c, stats.ABILITY_DMG[champion.name][champion.stars]) - - already_targeted.append(c) - - champion.clear_que_idle() - champion.move(target_hex_y, target_hex_x, True) + return +def hwei(champion): + return def jax(champion): - default_ability_calls(champion) - - champion.add_que('change_stat', -1, None, 'ability_active', True) - champion.add_que('change_stat', -1, None, 'autoimmune', True) - champion.add_que('change_stat', stats.ABILITY_LENGTH[champion.name], None, 'ability_active', False) - champion.add_que('change_stat', stats.ABILITY_LENGTH[champion.name], None, 'autoimmune', False) - - champion.add_que('execute_function', stats.ABILITY_LENGTH[champion.name], [jax_ability, {}]) - - -def jax_ability(champion, data): - enemy_neighbors = field.enemies_in_distance(champion, champion.y, champion.x, 1) - - for e in enemy_neighbors: - e.add_que('change_stat', -1, None, 'stunned', True) - e.clear_que_stunned_removal() - e.add_que('change_stat', stats.ABILITY_STUN_DURATION[champion.name][champion.stars], None, 'stunned', False) - champion.spell(e, stats.ABILITY_DMG[champion.name][champion.stars]) + return +def jayce(champion): + return def jinx(champion): - default_ability_calls(champion) + return - targets = field.enemies_in_distance(champion, champion.target.y, champion.target.x, 1) - for t in targets: - champion.spell(t, stats.ABILITY_DMG[champion.name][champion.stars]) +def kalista(champion): + return - t.add_que('change_stat', -1, None, 'stunned', True) - t.clear_que_stunned_removal() - t.add_que('change_stat', stats.ABILITY_STUN_DURATION[champion.name][champion.stars], None, 'stunned', False) - - apply_attack_cooldown(champion) +def karma(champion): + return +def kassadin(champion): + return def katarina(champion): - default_ability_calls(champion) - champion.add_que('change_stat', -1, None, 'ability_active', True) - champion.idle = False - champion.clear_que_idle() - champion.add_que('clear_idle', stats.ABILITY_LENGTH[champion.name]) - - champion.add_que('change_stat', stats.ABILITY_LENGTH[champion.name], None, 'ability_active', False) - - for i in range(0, stats.ABILITY_SLICES[champion.name]): - champion.add_que('execute_function', - i * (stats.ABILITY_LENGTH[champion.name] / stats.ABILITY_SLICES[champion.name]), - [katarina_ability, {}]) - - -def katarina_ability(champion, data): - enemies_in_range = field.enemies_in_distance(champion, champion.y, champion.x, 3) - enemies_in_range = enemies_in_range[:3] - - if not champion.stunned: - for e in enemies_in_range: - champion.spell(e, stats.ABILITY_DMG[champion.name][champion.stars] / stats.ABILITY_SLICES[champion.name]) - e.add_que('change_stat', 0, None, 'healing_strength', stats.ABILITY_HEALING_REDUCE[champion.name]) - e.clear_que_healing_reduction() - e.add_que('change_stat', stats.ABILITY_HEALING_REDUCE_LENGTH[champion.name], None, 'healing_strength', 1) - - -def kayn(champion, data={'redash': False}): - if not champion.stunned: - if not champion.target: - field.find_target(champion) - if champion.target: - champion.print( - ' has a new target: ' + '{:<8}'.format(champion.target.team) + '{:<8}'.format(champion.target.name)) - else: - return - - default_ability_calls(champion) - distance = field.distance(champion, champion.target, True) - - r = random.randint(0, 100) - if ((distance > 1 or r > 50) and not data['redash']) or (r > 50 and data['redash']): - target_neighbors = field.find_neighbors(champion.target.y, champion.target.x) - empty_neighbors = [] - coords = field.coordinates - for n in target_neighbors: - if not coords[n[0]][n[1]]: - empty_neighbors.append(n) - if len(empty_neighbors) > 1: - dash_coords = empty_neighbors[random.randint(0, len(empty_neighbors) - 1)] - else: - dash_coords = empty_neighbors[0] - champion.move(dash_coords[0], dash_coords[1], True) - - enemies_in_range = field.enemies_in_distance(champion, champion.y, champion.x, 1) - - for e in enemies_in_range: - ability_dmg = stats.ABILITY_DMG[champion.name][champion.stars] - - if champion.kayn_form == 'shadow_assassin' \ - and champion_functions.MILLIS() < stats.ABILITY_EXTRA_DAMAGE_LENGTH[champion.name]: - ability_dmg *= stats.ABILITY_EXTRA_DAMAGE[champion.name][champion.stars] - - champion.spell(e, ability_dmg) - - # healing if rhaast equipped - if champion.kayn_form == 'rhast': - damage = 0 - if e.MR >= 0: - damage = ability_dmg * (100 / (100 + e.MR)) * champion.SP - else: - damage = ability_dmg * (2 - 100 / (100 - e.MR)) * champion.SP - champion.add_que('heal', -1, None, None, - damage * stats.ABILITY_HEALTH_PER_CAST_DAMAGE_PERCENTAGES[champion.name][ - champion.stars]) - - # increase next spell mana cost by 33% = reduce mana by 33% of maxmana - if not e.mana_cost_increased and e.maxmana > 0: - mana_reduce_amount = e.maxmana * stats.ABILITY_MANA_REQUIREMENT_INCREASEMENT[champion.name] - start_value = e.mana - e.mana -= mana_reduce_amount - e.print(' {} {} --> {}'.format('mana', round(start_value, 1), round(e.mana, 1))) - e.add_que('change_stat', -1, None, 'mana_cost_increased', True) - - # add a 250ms delay after each spin - champion.idle = False - que = champion.que_return() - for q in que: - if q[1] is champion and q[0] == 'clear_idle': - que.remove(q) - champion.que_replace(que) - champion.add_que('clear_idle', 350) - - if len(enemies_in_range) == 1 and len(champion.enemy_team()) > 0: - champion.add_que('execute_function', 350, [kayn, {'redash': True}]) - - -kennen_hits = [] - - -def kennen(champion): - global kennen_hits - kennen_hits = list(filter(lambda x: x[0] != champion, kennen_hits)) - - # for kenny not to ult when there's no targets in range - # brings some extra cpu load - if champion.target and field.distance(champion, champion.target, True) <= stats.ABILITY_RADIUS[champion.name]: - default_ability_calls(champion) - champion.add_que('change_stat', -1, None, 'ability_active', True) - champion.add_que('change_stat', stats.ABILITY_LENGTH[champion.name], None, 'ability_active', False) - - for i in range(0, stats.ABILITY_SLICES[champion.name]): - champion.add_que('execute_function', - i * (stats.ABILITY_LENGTH[champion.name] / stats.ABILITY_SLICES[champion.name]), - [kennen_ability, {}]) - - -def kennen_ability(champion, data): - global kennen_hits - targets = field.enemies_in_distance(champion, champion.y, champion.x, stats.ABILITY_RADIUS[champion.name]) - - if not champion.stunned: - for e in targets: - champion.spell(e, stats.ABILITY_DMG[champion.name][champion.stars] / stats.ABILITY_SLICES[champion.name]) - - found = False - index = -1 - target = e - if len(kennen_hits) > 0: - for i, v in enumerate(kennen_hits): - if v[0] == champion and v[1] == target: - found = True - index = i - break - - if found: - kennen_hits[index][2] += 1 - else: - kennen_hits.append([champion, target, 1]) - index = len(kennen_hits) - 1 - - if kennen_hits[index][2] >= 3: - e.add_que('change_stat', 0, None, 'stunned', True) - e.clear_que_stunned_removal() - e.add_que('change_stat', stats.ABILITY_STUN_DURATION[champion.name][champion.stars], None, 'stunned', - False) - kennen_hits[index][2] = 0 - - -def kindred(champion): - default_ability_calls(champion) - - if not champion.target: - field.find_target(champion) - if champion.target: - champion.print( - ' has a new target: ' + '{:<8}'.format(champion.target.team) + '{:<8}'.format(champion.target.name)) - else: - return - - target = champion.target - target_y = target.y - target_x = target.x - - champion.spell(target, stats.ABILITY_DMG[champion.name][champion.stars]) - - target.add_que('change_stat', 0, None, 'healing_strength', stats.ABILITY_HEALING_REDUCE[champion.name]) - target.clear_que_healing_reduction() - target.add_que('change_stat', stats.ABILITY_HEALING_REDUCE_LENGTH[champion.name], None, 'healing_strength', 1) - - # find all hexes that are within 3 distance of kindred and log the distance from target to all those hexes - potential_hexes = [] - coords = field.coordinates - for i in range(0, 7): - for j in range(0, 6): - distance_to_champion = field.distance({'y': champion.y, 'x': champion.x}, {'y': i, 'x': j}, False) - if distance_to_champion <= 3: - distance_to_target = field.distance({'y': target_y, 'x': target_x}, {'y': i, 'x': j}, False) - potential_hexes.append([i, j, distance_to_target]) - - # find all hexes that are furthest away of the target (still under 4) and choose one random of those - potential_hexes = sorted(potential_hexes, key=lambda x: x[2], reverse=True) - if len(potential_hexes) > 0: - while len(potential_hexes[0]) < 2 and potential_hexes[0][2] > 3: - potential_hexes = potential_hexes[1:] - potential_hexes = list(filter(lambda x: (x[2] == potential_hexes[0][2]), potential_hexes)) - leap_hex = potential_hexes[random.randint(0, len(potential_hexes) - 1)] - - else: - leap_hex = [champion.y, champion.x] - - champion.move(leap_hex[0], leap_hex[1], True) - apply_attack_cooldown(champion, halved=False) - - -def leesin(champion): - default_ability_calls(champion) - # draw a line from lee to target and continue it until it hits an edge - if not champion.target: - field.find_target(champion) - if champion.target is None: - return - if len(champion.enemy_team()) > 0: - line_to_wall_behind_target = field.rectangle_from_champion_to_wall_behind_target(champion, 1, champion.target.y, - champion.target.x) - if line_to_wall_behind_target[0]: - end_point = line_to_wall_behind_target[0][-1] - else: - end_point = [champion.target.y, champion.target.x] - - # find the closest corner to the line's end point - # not perfect - e_y = end_point[0] - e_x = end_point[1] - end_point_original = [e_y, e_x] - if e_x == 6 or e_x == 0: - if e_y > champion.y: - end_point[0] = 7 - if e_y < champion.y: - end_point[0] = 0 - if e_y == champion.y: - if champion.y <= 3: - end_point[0] = 0 - else: - end_point[0] = 7 - - elif e_y == 7 or e_y == 0: - if e_x > champion.x: - end_point[1] = 6 - if e_x < champion.x: - end_point[1] = 0 - if e_x == champion.x: - if champion.y % 2 == 0: - end_point[1] = 0 - else: - end_point[1] = 6 - - coords = field.coordinates - kick_coords = None - kick_out = False - deal = False - - t = champion.target - - # if 3 star, just kill the target and other enemies strictly around it - # Its a fun way of doing things but sure. - if champion.stars == 3: - ttt = field.enemies_in_distance(champion, t.y, t.x, 1) - for tt in ttt: - tt.die() - else: - - # if target is on a side - if t.y == 7 or t.y == 0 or t.x == 6 or t.x == 0: - - corners = [[0, 0], [0, 6], [7, 0], [7, 6]] - - # if they both are on a side lines, remove some corners from the list - if champion.y == 7 or champion.y == 0 or champion.x == 6 or champion.x == 0: - if champion.x > t.x: - corners.remove([0, 6]) - corners.remove([7, 6]) - if champion.x < t.x: - corners.remove([0, 0]) - corners.remove([7, 0]) - if champion.y > t.y: - if champion.x <= t.x: - corners.remove([7, 6]) - if champion.x >= t.x: - corners.remove([7, 0]) - if champion.y < t.y: - if champion.x >= t.x: - corners.remove([0, 0]) - if champion.x <= t.x: - corners.remove([0, 6]) - - # find the closest corner - for i, c in enumerate(corners): - d = field.distance({'y': t.y, 'x': t.x}, {'y': c[0], 'x': c[1]}, False) - corners[i].append(d) - corners = sorted(corners, key=lambda x: x[2]) - closest_corner = corners[0] - - # if we're at the corner (distance == 0) - if closest_corner[2] == 0: - kick_out = True - - # otherwise draw a line from target to the closest corner - # if all hexes on the line are occupied, kick the target out - else: - line = field.line({'y': t.y, 'x': t.x}, {'y': closest_corner[0], 'x': closest_corner[1]}) - all_occupied = True - for l in line: - if coords: - if not 0 <= l[0] <= 7 or 0 <= l[1] <= 6: - all_occupied = False - break - if all_occupied: - kick_out = True - - if not kick_out: - # draw a line from the corner to the (lee to target) -line end point and find the first free spot - - if end_point[:2] != end_point_original: - line = (field.line({'y': end_point[0], 'x': end_point[1]}, - {'y': end_point_original[0], 'x': end_point_original[1]})) - while not kick_coords: - if len(line) == 0: - - # very much just a 'tape on a tap head' -type solution for a rare bug - # if the corner is very full, - # the unit would get kicked out rather than added to the queue of units on the side lane - if not (champion.target.y == 0 or champion.target.y == 7 - or champion.target.x == 0 or champion.target.x == 6): - deal = True - kick_coords = [champion.target.y, champion.target.x] - - else: - kick_out = True - break - if not (line[0][0] == 0 or line[0][0] == 7 or line[0][1] == 0 or line[0][1] == 6)\ - or coords[line[0][0]][line[0][1]]: - line = line[1:] - else: - kick_coords = line[0] - - break - - # if the target is kicked straight to the corner, but it's occupied - # find the closest hex to the corner that's free - else: - # some close hexes - index = 1 - hexes_on_sides = [] - while len(hexes_on_sides) < 1: - hexes_in_distance = field.hexes_in_distance(end_point[0], end_point[1], index) - for n in hexes_in_distance: - # add only if they are on side lanes - if (n[0] == 0 or n[0] == 7 or n[1] == 0 or n[1] == 6) and not coords[n[0]][n[1]]: - hexes_on_sides.append(n) - d = field.distance({'y': n[0], 'x': n[1]}, - {'y': end_point_original[0], 'x': end_point_original[1]}, False) - hexes_on_sides[-1].append(d) - index += 1 - - # sort by distance to the end point and choose the closest one - hexes_on_sides = sorted(hexes_on_sides, key=lambda x: x[2]) - kick_coords = [hexes_on_sides[0][0], hexes_on_sides[0][1]] - - # push, stun, deal damage and dash - if deal or not kick_out: - # enemies which collide with the pushed target - if champion.target.y != kick_coords[0] and champion.target.x != kick_coords[1]: - line = field.line({'y': champion.target.y, 'x': champion.target.x}, - {'y': kick_coords[0], 'x': kick_coords[1]}) - for l in line: - c = coords[l[0]][l[1]] - if c and c.team != champion.team and c.champion and c != champion.target: - c.add_que('change_stat', 0, None, 'stunned', True) - c.clear_que_stunned_removal() - c.add_que('change_stat', - stats.ABILITY_SECONDARY_STUN_DURATION[champion.name][champion.stars], None, - 'stunned', False) - champion.spell(c, stats.ABILITY_DMG[champion.name][champion.stars] / 2) - if champion.target is None: - return - # push to corner - champion.target.move(kick_coords[0], kick_coords[1], True) - target_y = champion.target.y - target_x = champion.target.x - - champion.target.add_que('change_stat', 0, None, 'stunned', True) - champion.target.clear_que_stunned_removal() - champion.target.add_que('change_stat', stats.ABILITY_STUN_DURATION[champion.name][champion.stars], - None, 'stunned', False) - - champion.spell(champion.target, stats.ABILITY_DMG[champion.name][champion.stars]) - - # dash (only if the pushed unit is alive and outside of lee's range) - # find a hex that's a neighbor of the pushed unit and as close as possible to lee - if (champion.target and field.distance({'y': target_y, 'x': target_x}, - {'y': champion.y, 'x': champion.x}, False) > champion.range): - neighbors = field.find_neighbors(target_y, target_x) - for i, n in enumerate(neighbors): - d = field.distance({'y': n[0], 'x': n[1]}, {'y': champion.y, 'x': champion.x}, False) - neighbors[i].append(d) - - neighbors = sorted(neighbors, key=lambda x: x[2]) - for n in neighbors: - if not coords[n[0]][n[1]]: - champion.move(n[0], n[1], True) - apply_attack_cooldown(champion, halved=False) - break - else: - champion.target.die() - - else: - champion.target.die() - - -# this was aids + return +def kogmaw(champion): + return def lillia(champion): - default_ability_calls(champion) - target_amount = stats.ABILITY_TARGETS[champion.name][champion.stars] - enemy_list = champion.enemy_team() - enemies = [] - - for i, e in enumerate(enemy_list): - d = field.distance(champion, e, True) - enemies.append([e, d, e.health]) - - enemies = sorted(enemies, key=lambda x: (x[2]), reverse=True) - if len(enemies) > target_amount: - enemies = enemies[:target_amount] - - for e in enemies: - e[0].add_que('change_stat', 0, None, 'stunned', True) - e[0].clear_que_stunned_removal() - e[0].add_que('change_stat', stats.ABILITY_STUN_DURATION[champion.name][champion.stars], None, 'stunned', False) - - # if two lillia ults by the same unit were casted while the last one's stuns are still active, - # remove the hp checks from the que - """que = champion.que_return() - for q in que: - if(q[1] is champion and q[0] == 'execute_function' and q[3][0] == lillia_ability): - que.remove(q) - champion.que_replace(que) """ - - champion.add_que('execute_function', -1, [lillia_ability, {'enemies': enemies, 'i': 0}]) - - -def lillia_ability(champion, data): - enemies = data['enemies'] - threshold = stats.ABILITY_STUN_STOP_DMG_THRESHOLD[champion.name][champion.stars] - - for e in enemies: - difference = e[2] - e[0].health - if difference > threshold: - e[0].clear_que_stunned_removal() - e[0].add_que('change_stat', 0, None, 'stunned', False) - champion.spell(e[0], stats.ABILITY_DMG[champion.name][champion.stars]) - data['enemies'].remove(e) - - # call the same function every 50 milliseconds until the stuns are over - # these function calls are overwritten in case lillia ults again - if data['i'] * 50 < stats.ABILITY_STUN_DURATION[champion.name][champion.stars]: - # 49ms because the que adds one more ms - champion.add_que('execute_function', 49, [lillia_ability, {'enemies': enemies, 'i': data['i'] + 1}]) - - -# this is a bit shit as well -def lissandra(champion): - default_ability_calls(champion) - enemy_list = champion.enemy_team() - - target = None - for e in enemy_list: - if not target or e.AD > target.AD: - target = e - - dagger_path = field.line({'y': champion.y, 'x': champion.x}, {'y': target.y, 'x': target.x}) - - dagger_target = None - coords = field.coordinates - for d in dagger_path: - if 0 <= d[0] < 8 and 0 <= d[1] < 7: - # print("IN LISSANDRA ABILITY") - # print(d) - c = coords[d[0]][d[1]] - if c and c.team != champion.team and c.champion: - dagger_target = c - break - if not dagger_target: - dagger_target = champion.target - - # find the first three points of the cone (blue in 'lissandra_ult.png') - primary_neighbors = field.find_neighbors(dagger_target.y, dagger_target.x, True) - for i, p in enumerate(primary_neighbors): - distance = field.distance({'y': p[0], 'x': p[1]}, {'y': champion.y, 'x': champion.x}, False) - primary_neighbors[i].append(distance) - primary_neighbors = sorted(primary_neighbors, key=lambda x: (x[2])) - primary_neighbors = primary_neighbors[3:] - for i, p in enumerate(primary_neighbors): - primary_neighbors[i] = [p[0], p[1]] - - # finding the orange circle in 'lissandra_ult.png' - # which of the just found hexes have two of the hexes as neighbors - primary_neighbors_count = [] - for p in primary_neighbors: - primary_neighbors_neighbors = field.find_neighbors(p[0], p[1], True) - primary_neighbors_count.append([p[0], p[1], 0]) - for n in primary_neighbors_neighbors: - if n in primary_neighbors: - primary_neighbors_count[len(primary_neighbors_count) - 1][2] += 1 - - primary_neighbors_count = sorted(primary_neighbors_count, key=lambda x: (x[2]), reverse=True) - middle_hex = [primary_neighbors_count[0][0], primary_neighbors_count[0][1]] - side_primary_neighbors = [[primary_neighbors_count[1][0], primary_neighbors_count[1][1]], - [primary_neighbors_count[2][0], primary_neighbors_count[2][1]]] - - # the dark red circle in 'lissandra_ult.png' - # neighbor of the yellow circle and two distance away from the side primary neighbors - middle_hex_neighbors = field.find_neighbors(middle_hex[0], middle_hex[1], True) - for i, m in enumerate(middle_hex_neighbors): - distance0 = field.distance({'y': m[0], 'x': m[1]}, - {'y': side_primary_neighbors[0][0], 'x': side_primary_neighbors[0][1]}, False) - distance1 = field.distance({'y': m[0], 'x': m[1]}, - {'y': side_primary_neighbors[1][0], 'x': side_primary_neighbors[1][1]}, False) - middle_hex_neighbors[i] = [m[0], m[1], distance0, distance1] - - secondary_middle_hex = list(filter(lambda x: (x[2] == 2 and x[3] == 2), middle_hex_neighbors)) - secondary_middle_hex = [secondary_middle_hex[0][0], secondary_middle_hex[0][1]] - - # now find all the hexes within two distance from the orange circle - # that are also within two distance of the red circle - - middle_hex_two_distance = field.hexes_in_distance(middle_hex[0], middle_hex[1], 2) - secondary_middle_hex_two_distance = field.hexes_in_distance(secondary_middle_hex[0], secondary_middle_hex[1], 2) - - cone = list( - set(map(tuple, middle_hex_two_distance)).intersection(set(map(tuple, secondary_middle_hex_two_distance)))) - - # now add the corners (black) of the cone by finding hexes - # that are of 4 distance from the champion and three distance from the red circle - four_from_champion = field.hexes_distance_away(champion.y, champion.x, 4) - three_from_red = field.hexes_distance_away(secondary_middle_hex[0], secondary_middle_hex[1], 3) - - corners = list(set(map(tuple, four_from_champion)).intersection(set(map(tuple, three_from_red)))) - - for c in corners: - cone.append(c) - - # remove the dagger target since everyone in the cone will be taking secondary damage - cone.remove(tuple((dagger_target.y, dagger_target.x))) - - champion.spell(dagger_target, stats.ABILITY_DMG[champion.name][champion.stars]) - - coords = field.coordinates - for c in cone: - hex_data = coords[c[0]][c[1]] - if hex_data and champion.team != hex_data.team and hex_data.champion: - champion.spell(hex_data, stats.ABILITY_SECONDARY_DMG[champion.name][champion.stars]) - - -lulu_targeted = [] - - -def lulu(champion): - default_ability_calls(champion) - own_team = champion.own_team() - own_team_hp = [] - - for i, o in enumerate(own_team): - own_team_hp.append([o, o.health / o.max_health]) - - own_team_hp = sorted(own_team_hp, key=lambda x: x[1]) - - for o in own_team_hp: - targeted = len(list(filter(lambda x: (x[0] == champion and x[1] == o[0]), lulu_targeted))) - hp_amount = stats.ABILITY_HEALTH_GAIN_TOTAL[champion.name][champion.stars] * champion.SP - if targeted != 0: - o[0].add_que('change_stat', -1, None, 'max_health', o[0].max_health + hp_amount) - o[0].add_que('heal', -1, None, None, hp_amount) - - neighbors = field.enemies_in_distance(o[0], o[0].y, o[0].x, 1) - for n in neighbors: - n.add_que('change_stat', -1, None, 'stunned', True) - n.clear_que_stunned_removal() - n.add_que('change_stat', stats.ABILITY_STUN_DURATION[champion.name][champion.stars], None, 'stunned', False) - lulu_targeted.append([champion, o[0]]) - - break - - -def lux(champion): - default_ability_calls(champion) - if len(champion.enemy_team()) > 0: - enemies = field.enemies_in_distance(champion, champion.y, champion.x, 20) - distances = [] - for e in enemies: - d = field.distance(champion, e, True) - distances.append([e, d]) - distances = sorted(distances, key=lambda x: x[1], reverse=True) - - if len(distances) == 0: - target = [champion.target.y, champion.target.x] - else: - target = distances[0][0] - - if target: - try: - path = field.line({'y': champion.y, 'x': champion.x}, {'y': target.y, 'x': target.x}) - except AttributeError or ValueError: - path = field.line({'y': champion.y, 'x': champion.x}, {'y': 0, 'x': 0}) - coords = field.coordinates - for p in path: - if 0 <= p[0] < 8 and 0 <= p[1] < 7: - # print("IN LUX ABILITY") - # print(p) - c = coords[p[0]][p[1]] - if c and c.team != champion.team and c.champion: - c.add_que('change_stat', -1, None, 'stunned', True) - c.clear_que_stunned_removal() - c.add_que('change_stat', stats.ABILITY_STUN_DURATION[champion.name][champion.stars], - None, 'stunned', False) - champion.spell(c, stats.ABILITY_DMG[champion.name][champion.stars]) - - -def maokai(champion): - default_ability_calls(champion) - - targeted_hexes = [[champion.target.y, champion.target.x]] - - # target all hexes adjacent to target that are 1 away from champion (red dots in 'maokai_ult.png') - target_neighbors = field.find_neighbors(champion.target.y, champion.target.x, True) - for i, t in enumerate(target_neighbors): - d = field.distance({'y': champion.y, 'x': champion.x}, {'y': t[0], 'x': t[1]}, False) - target_neighbors[i] = [t, d] - target_neighbors = sorted(target_neighbors, key=lambda x: x[1]) - target_neighbors = list(filter(lambda x: (x[1] == 1), target_neighbors)) - - # print(target_neighbors) - # Bug happens if there are no neighbors or if it is outside the range of the map. Have yet to test. - if target_neighbors: - targeted_hexes.append(target_neighbors[0][0]) - if len(target_neighbors) > 1: - targeted_hexes.append(target_neighbors[1][0]) - - # also target two hexes behind the unit (red dashes in 'maokai_ult.png') - # the last dashed hex is 3 away from the side neighbors and 3 away from the champion - # NOT THE MOST ELEGANT WAY TO DO THIS: - - three_from_champion = field.hexes_distance_away(champion.y, champion.x, 3) - three_from_n0 = field.hexes_distance_away(target_neighbors[0][0][0], target_neighbors[0][0][1], 3) - three_away = list(set(map(tuple, three_from_champion)).intersection(set(map(tuple, three_from_n0)))) - if len(target_neighbors) > 1: - three_from_n1 = field.hexes_distance_away(target_neighbors[1][0][0], target_neighbors[1][0][1], 3) - three_away = list(set(map(tuple, three_away)).intersection(set(map(tuple, three_from_n1)))) - - # in case the dash hexes are outside the map, let's just find them independently without drawing a line - two_from_champion = field.hexes_distance_away(champion.y, champion.x, 2) - two_from_n0 = field.hexes_distance_away(target_neighbors[0][0][0], target_neighbors[0][0][1], 2) - two_away = list(set(map(tuple, two_from_champion)).intersection(set(map(tuple, two_from_n0)))) - if len(target_neighbors) > 1: - two_from_n1 = field.hexes_distance_away(target_neighbors[1][0][0], target_neighbors[1][0][1], 2) - two_away = list(set(map(tuple, two_away)).intersection(set(map(tuple, two_from_n1)))) - - if len(three_away) > 0: - targeted_hexes.append([three_away[0][0], three_away[0][1]]) - if len(two_away) > 0: - targeted_hexes.append([two_away[0][0], two_away[0][1]]) - - coords = field.coordinates - for t in targeted_hexes: - if 0 <= t[0] <= 7 and 0 <= t[1] <= 6: - c = coords[t[0]][t[1]] - if c and c.team != champion.team and c.champion: - champion.spell(c, stats.ABILITY_DMG[champion.name][champion.stars]) - - c.add_que('change_stat', -1, None, 'AS', - c.AS * stats.ABILITY_AS_DECREASE[champion.name][champion.stars]) - c.add_que('change_stat', stats.ABILITY_AS_CHANGE_LENGTH[champion.name], None, 'AS', None, - {'ezreal': stats.ABILITY_AS_DECREASE[champion.name][champion.stars]}) - - -def morgana(champion): - default_ability_calls(champion) - - champion.add_que('change_stat', -1, None, 'ability_active', True) - champion.add_que('change_stat', stats.ABILITY_LENGTH[champion.name], None, 'ability_active', False) - - # between two random targets cast where it hits the most units - enemies = champion.enemy_team() - random.shuffle(enemies) - - circle0 = field.enemies_in_distance(champion, enemies[0].y, enemies[0].x, stats.ABILITY_RADIUS[champion.name]) - circle1 = [] - if len(enemies) > 1: - circle1 = field.enemies_in_distance(champion, enemies[1].y, enemies[1].x, stats.ABILITY_RADIUS[champion.name]) - target = [enemies[0].y, enemies[0].x] - - if len(circle1) > len(circle0): - target = [enemies[1].y, enemies[1].x] - - for i in range(0, stats.ABILITY_SLICES[champion.name]): - current_ms = i * (stats.ABILITY_LENGTH[champion.name] / stats.ABILITY_SLICES[champion.name]) - champion.add_que('execute_function', current_ms, [morgana_ability, {'coordinates': target, 'ms': current_ms}]) - - -morgana_MR_list = [] - - -def morgana_ability(champion, data): - global morgana_MR_list - targets = field.enemies_in_distance(champion, data['coordinates'][0], data['coordinates'][1], - stats.ABILITY_RADIUS[champion.name]) - - for t in targets: - # if that unit hasn't been targeted by this morgana yet - if len(list(filter(lambda x: (x[0] == champion and x[1] == t), morgana_MR_list))) == 0: - ms_left = stats.ABILITY_LENGTH[champion.name] - data['ms'] + return - t.print(' {} {} --> {}'.format('MR', t.MR, t.MR * stats.ABILITY_MR_DECREASE[champion.name])) - t.MR *= stats.ABILITY_MR_DECREASE[champion.name] - t.add_que('change_stat', ms_left, None, 'MR', None, {'morgana': stats.ABILITY_MR_DECREASE[champion.name]}) +def milio(champion): + return - morgana_MR_list.append([champion, t]) - - champion.spell(t, stats.ABILITY_DMG[champion.name][champion.stars] / stats.ABILITY_SLICES[champion.name]) - - ability_dmg = stats.ABILITY_DMG[champion.name][champion.stars] / stats.ABILITY_SLICES[champion.name] - if t.MR >= 0: - damage = ability_dmg * (100 / (100 + t.MR)) * champion.SP - else: - damage = ability_dmg * (2 - 100 / (100 - t.MR)) * champion.SP - champion.add_que('heal', -1, None, None, damage * stats.ABILITY_HEAL_PER_DAMAGE[champion.name][champion.stars]) - - # clear the list at the end of the last slice - if (data['ms'] == stats.ABILITY_LENGTH[champion.name] - ( - stats.ABILITY_LENGTH[champion.name] / stats.ABILITY_SLICES[champion.name])): - morgana_MR_list = list(filter(lambda x: (x[0] != champion), morgana_MR_list)) +def mordekaiser(champion): + return +def morgana(champion): + return def nami(champion): - default_ability_calls(champion) - - enemy_team = champion.enemy_team() - enemy_team = sorted(enemy_team, key=lambda x: field.distance(champion, x, True)) - target = enemy_team[0] - - target.add_que('change_stat', -1, None, 'stunned', True) - target.clear_que_stunned_removal() - target.add_que('change_stat', stats.ABILITY_STUN_DURATION[champion.name][champion.stars], None, 'stunned', False) - - champion.spell(target, stats.ABILITY_DMG[champion.name][champion.stars]) - - apply_attack_cooldown(champion) - - -def nidalee(champion): - default_ability_calls(champion) + return - enemies = champion.enemy_team() - enemies_distance = [] - for i, e in enumerate(enemies): - d = field.distance(champion, e, True) - enemies_distance.append([e, d]) +def nasus(champion): + return - enemies_distance = (sorted(enemies_distance, key=lambda x: x[1], reverse=True))[0] +def neeko(champion): + return - # don't take the champion's hex into calculations - path = (field.line({'y': champion.y, 'x': champion.x}, {'y': enemies_distance[0].y, 'x': enemies_distance[0].x}))[ - 1:] - dmg = stats.ABILITY_DMG[champion.name][champion.stars] +def nilah(champion): + return - coords = field.coordinates - for p in path: - dmg *= (1 + stats.ABILITY_DAMAGE_ADDITION_PERCENTAGE[champion.name]) - if 0 < p[0] < 8 and 0 < p[1] < 7: - c = coords[p[0]][p[1]] - if c and c.team != champion.team and c.champion: - champion.spell(c, dmg) - break - - apply_attack_cooldown(champion) +def nomsy(champion): + return +def norra_yuumi(champion): + return def nunu(champion): - default_ability_calls(champion) - - if champion.health > champion.target.health: - true_dmg = stats.ABILITY_DMG[champion.name][champion.stars] * ( - 1 + stats.ABILITY_DAMAGE_ADDITION_PERCENTAGE[champion.name]) - champion.spell(champion.target, 0, true_dmg) - else: - champion.spell(champion.target, stats.ABILITY_DMG[champion.name][champion.stars]) - - apply_attack_cooldown(champion) - - -# add to the path any hexes that have three neighbors in the pyke's dashing path (x-marks in 'pyke_ult.png') -def pyke(champion): - default_ability_calls(champion) - champion.add_que('change_stat', -1, None, 'ability_active', True) - champion.add_que('change_stat', stats.ABILITY_LENGTH[champion.name], None, 'ability_active', False) - - # find the enemy that's furthest away - enemies = champion.enemy_team() - enemies_distance = [] - for i, e in enumerate(enemies): - d = field.distance(champion, e, True) - enemies_distance.append([e, d]) - - target = (sorted(enemies_distance, key=lambda x: x[1], reverse=True))[0][0] - - # get that enemy's neighbors to find the dash target - target_neighbors = field.find_neighbors(target.y, target.x) - target_neighbor_distances = [] - for n in target_neighbors: - d = field.distance({'y': champion.y, 'x': champion.x}, {'y': n[0], 'x': n[1]}, False) - target_neighbor_distances.append([n, d]) - target_neighbor_distances = sorted(target_neighbor_distances, key=lambda x: x[1], reverse=True) - - dash_target = None - coords = field.coordinates - for t in target_neighbor_distances: - if not coords[t[0][0]][t[0][1]]: - dash_target = t[0] - break - - # problem: what if the target unit doesn't have free neighbor slots - # kind of a shit solution but find a free hex within two hexes of the original target - # then replace the original target with some enemy next to the new dash target - if not dash_target: - second_degree_neighbors = field.hexes_in_distance(target.y, target.x, 2) - random.shuffle(second_degree_neighbors) - for t in second_degree_neighbors: - if not coords[t[0]][t[1]]: - dash_target = t - break - - if dash_target: - dash_target_neighbors = field.find_neighbors(dash_target[0], dash_target[1]) - random.shuffle(dash_target_neighbors) - for n in dash_target_neighbors: - c = coords[n[0]][n[1]] - if c and c.team != champion.team and c.champion: - target = c - break - - # if we STILL don't have a dash target, give back 90% of pyke's mana and move on - if not dash_target: - champion.add_que('change_stat', -1, None, 'mana', champion.maxmana * 0.9) - - else: - # if the dash_target is further away than the targeted champion, set that hex to be the path's second end - path_target = [target.y, target.x] - distance_to_dash_target = field.distance({'y': champion.y, 'x': champion.x}, - {'y': dash_target[0], 'x': dash_target[1]}, False) - distance_to_target = field.distance(champion, target, True) - if distance_to_dash_target > distance_to_target: - path_target = dash_target - - path = field.line({'y': champion.y, 'x': champion.x}, {'y': path_target[0], 'x': path_target[1]}) - extra_path = [] - - # find all the hexes that have three neighbors which are in the path - all_hexes = field.hexes_in_distance(0, 0, 20) - for a in all_hexes: - a_neighbors = field.find_neighbors(a[0], a[1]) - count = 0 - for n in a_neighbors: - if n in path: - count += 1 - - if count == 3: - extra_path.append(a) - - for e in extra_path: - path.append(e) - - champion.move(dash_target[0], dash_target[1], True) - champion.add_que('execute_function', stats.ABILITY_LENGTH[champion.name], [pyke_ability, {'path': path}]) - - -def pyke_ability(champion, data): - coords = field.coordinates - for p in data['path']: - if 0 <= p[0] <= 7 and 0 <= p[1] <= 6: - c = coords[p[0]][p[1]] - if c and c.team != champion.team and c.champion: - c.add_que('change_stat', -1, None, 'stunned', True) - c.clear_que_stunned_removal() - c.add_que('change_stat', stats.ABILITY_STUN_DURATION[champion.name][champion.stars], None, 'stunned', False) - champion.spell(c, stats.ABILITY_DMG[champion.name][champion.stars]) - - -riven_counter = [] -riven_identifier_list = [] - - -def riven(champion): - if riven_helper(champion, {}): - - global riven_counter - default_ability_calls(champion) - # riven_counter needs to sustain multiple rivens on the field, - # so there's gonna be every riven's data on the same array - found = False - index = -1 - if len(riven_counter) > 0: - for i, v in enumerate(riven_counter): - if v[0] == champion: - found = True - index = i - break - - if found: - riven_counter[index][1] += 1 - else: - riven_counter.append([champion, 1]) - index = len(riven_counter) - 1 - - if len(champion.enemy_team()) > 0: - if not champion.target: - field.find_target(champion) - # target neighbors and their distances to champion - target_neighbors = field.find_neighbors(champion.target.y, champion.target.x, True) - for i, t in enumerate(target_neighbors): - d = field.distance({'y': champion.y, 'x': champion.x}, {'y': t[0], 'x': t[1]}, False) - target_neighbors[i] = [t, d] - - coords = field.coordinates - - # the wave of damage - if riven_counter[index][1] == 3: - - # target_hex = [[champion.target.y, champion.target.x]] - corner_neighbors = [] - - # target all hexes adjacent to target that are 1 away from champion (orange circles in 'riven_ult.png') - target_neighbors = sorted(target_neighbors, key=lambda x: x[1]) - target_neighbors = list(filter(lambda x: (x[1] == 1), target_neighbors)) - - # bugged out once and couldn't repeat. - if len(target_neighbors) > 1: - corner_neighbors.append(target_neighbors[0][0]) - corner_neighbors.append(target_neighbors[1][0]) - - # find the red circle in the pic - two_from_champion = field.hexes_distance_away(champion.y, champion.x, 2, True) - two_from_n0 = field.hexes_distance_away(corner_neighbors[0][0], corner_neighbors[0][1], 2, True) - two_from_n1 = field.hexes_distance_away(corner_neighbors[1][0], corner_neighbors[1][1], 2, True) - two_away = list(set(map(tuple, two_from_champion)).intersection(set(map(tuple, two_from_n0)))) - two_away_list = list(set(map(tuple, two_away)).intersection(set(map(tuple, two_from_n1)))) - slash_hexes = [] - if len(two_away_list) > 0: - two_away = two_away_list[0] - slash_hexes = field.hexes_in_distance(two_away[0], two_away[1], 1) - - slash_hexes.append(corner_neighbors[0]) - slash_hexes.append(corner_neighbors[1]) - - for s in slash_hexes: - if s[0] < 8 and s[1] < 7: - c = coords[s[0]][s[1]] - if c and c.team != champion.team and c.champion: - champion.spell(c, stats.ABILITY_SECONDARY_DMG[champion.name][champion.stars]) - - riven_counter[index][1] = 0 - - # first dash to a furthest free neighboring hex of the target - # then get a shield / reset the shield - # damage ALL neighboring enemies - else: - - random.shuffle(target_neighbors) - target_neighbors = sorted(target_neighbors, key=lambda x: x[1], reverse=True) - - for t in target_neighbors: - t = t[0] - if t[0] >= 0 and t[0] <= 7 and t[1] >= 0 and t[1] <= 6: - c = coords[t[0]][t[1]] - if not c: - champion.move(t[0], t[1], True) - break - - shield_identifier = champion_functions.MILLIS() * stats.SHIELD_AMOUNT[champion.name][ - champion.stars] * champion.SP - shield_amount = stats.SHIELD_AMOUNT[champion.name][champion.stars] * champion.SP - if shield_identifier in riven_identifier_list: - champion.add_que('shield', 0, None, None, - {'amount': shield_amount + 0.001, 'identifier': shield_identifier, - 'applier': champion, 'original_amount': shield_amount + 0.001}, - {'increase': True}) - - riven_identifier_list.append(shield_identifier) - - champion.add_que('shield', 0, None, None, - {'amount': shield_amount, 'identifier': shield_identifier, 'applier': champion, - 'original_amount': shield_amount}, {'increase': True}) - - for t in field.find_neighbors(champion.y, champion.x): - c = coords[t[0]][t[1]] - if c and c.team != champion.team and c.champion: - champion.spell(c, stats.ABILITY_DMG[champion.name][champion.stars]) - - apply_attack_cooldown(champion) - - else: - champion.attack() - - -# check if she has old shields left -def riven_helper(champion, data): - if len(champion.shields) == 0: return True - own_shields = list(filter(lambda x: ( - x['applier'] == champion and x['original_amount'] == - stats.SHIELD_AMOUNT[champion.name][champion.stars] * champion.SP), champion.shields)) - if len(own_shields) == 0: - return True - else: - return False - - -def sejuani(champion): - default_ability_calls(champion) - champion.add_que('change_stat', -1, None, 'ability_active', True) - champion.add_que('change_stat', stats.ABILITY_LENGTH[champion.name], None, 'ability_active', False) - - enemies = champion.enemy_team() - enemies_distance = [] - - for i, e in enumerate(enemies): - d = field.distance(champion, e, True) - enemies_distance.append([e, d]) - enemies_distance = sorted(enemies_distance, key=lambda x: x[1]) - - target = enemies_distance[0][0] - - champion.add_que('execute_function', stats.ABILITY_LENGTH[champion.name], - [sejuani_ability, {'target': [target.y, target.x]}]) - - -def sejuani_ability(champion, data): - target_hexes = field.hexes_in_distance(data['target'][0], data['target'][1], stats.ABILITY_RADIUS[champion.name]) - coords = field.coordinates - for t in target_hexes: - c = coords[t[0]][t[1]] - if (c and c.team != champion.team and c.champion): - c.add_que('change_stat', -1, None, 'stunned', True) - c.clear_que_stunned_removal() - c.add_que('change_stat', stats.ABILITY_STUN_DURATION[champion.name][champion.stars], None, 'stunned', False) - - champion.spell(c, stats.ABILITY_DMG[champion.name][champion.stars]) - - -def sett(champion): - default_ability_calls(champion) - if len(champion.enemy_team()) > 0: - if not champion.target: - field.find_target(champion) - - # add the slamming time (assumed 1000ms) - champion.add_que('change_stat', -1, None, 'ability_active', True) - champion.add_que('change_stat', stats.ABILITY_LENGTH[champion.name], None, 'ability_active', False) - - # slams the target forward ('sett_ult.png') and takes the target's old place. - # if all of the possible hexes are taken, don't move but still slam. - - smash_targets = [] - - target_neighbors = field.find_neighbors(champion.target.y, champion.target.x, False) - for i, t in enumerate(target_neighbors): - d = field.distance({'y': champion.y, 'x': champion.x}, {'y': t[0], 'x': t[1]}, False) - target_neighbors[i] = [t, d] - - # print("IN SETT ABILITY") - # print(target_neighbors) - one_distance_neighbors = list(filter(lambda x: (x[1] == 1), target_neighbors)) - two_distance_neighbors = list(filter(lambda x: (x[1] == 2), target_neighbors)) - - if one_distance_neighbors and two_distance_neighbors: - # finding the preferred smash target hex (two away from the side neighbors [one distance from champion]) - # and two away from the champion itself. - two_from_champion = field.hexes_distance_away(champion.y, champion.x, 2, True) - two_from_n0 = field.hexes_distance_away(one_distance_neighbors[0][0][0], - one_distance_neighbors[0][0][1], 2, True) - if len(one_distance_neighbors) > 1: - two_from_n1 = field.hexes_distance_away(one_distance_neighbors[1][0][0], - one_distance_neighbors[1][0][1], 2, True) - two_away = list(set(map(tuple, two_from_n0)).intersection(set(map(tuple, two_from_n1)))) - else: - two_away = two_from_n0 - two_away = list(set(map(tuple, two_from_champion)).intersection(set(map(tuple, two_away)))) - # add into 'smash_targets' in the next order: first we have the preferred hex (solid red line) - # then the next two will be the secondary smash targets - if two_away: - smash_targets.append([two_away[0][0], two_away[0][1]]) - two_distance_neighbors = list(filter(lambda x: (x[0] != smash_targets[0]), two_distance_neighbors)) - else: - two_distance_neighbors = list(filter(lambda x: (x[0]), two_distance_neighbors)) - smash_targets.append(two_distance_neighbors[0][0]) - if len(two_distance_neighbors) > 1: - smash_targets.append(two_distance_neighbors[1][0]) - - # go through the possibilities and try to find a free hex - free_hex = None - coords = field.coordinates - for s in smash_targets: - if s[0] >= 0 and s[0] <= 7 and s[1] >= 0 and s[1] <= 6: - c = coords[s[0]][s[1]] - if not c: - free_hex = s - break - - # move to the target if there's a fee hex available - if free_hex: - sett_target = [champion.target.y, champion.target.x] - champion.target.move(free_hex[0], free_hex[1], True) - champion.move(sett_target[0], sett_target[1], True) - - # slamming area - damaged_hexes = field.hexes_in_distance(champion.target.y, champion.target.x, 2) - damaged_hexes = list(filter(lambda x: x != [champion.target.y, champion.target.x], damaged_hexes)) - - target_dmg = champion.target.max_health * stats.ABILITY_DMG[champion.name][champion.stars] - secondary_target_dmg = champion.target.max_health * stats.ABILITY_SECONDARY_DMG[champion.name][champion.stars] - champion.spell(champion.target, target_dmg) - coords = field.coordinates - for d in damaged_hexes: - c = coords[d[0]][d[1]] - if c and c.team != champion.team and c.champion: - champion.spell(c, secondary_target_dmg) - - -def shen(champion): - default_ability_calls(champion) - - # target neighbors and their distances to champion - target_neighbors = field.find_neighbors(champion.target.y, champion.target.x) - for i, t in enumerate(target_neighbors): - d = field.distance({'y': champion.y, 'x': champion.x}, {'y': t[0], 'x': t[1]}, False) - target_neighbors[i] = [t, d] - - random.shuffle(target_neighbors) - target_neighbors = sorted(target_neighbors, key=lambda x: x[1], reverse=True) - - # dash to a neighbor of the target that's as far as possible from shen - # if there are no free hexes, stay at the current hex - dash_target = [champion.y, champion.x] - - coords = field.coordinates - for t in target_neighbors: - t = t[0] - c = coords[t[0]][t[1]] - if not c: - dash_target = t - break - - if dash_target != [champion.y, champion.x]: - champion.move(dash_target[0], dash_target[1], True) - - shield_identifier = champion_functions.MILLIS() * stats.SHIELD_AMOUNT[champion.name][champion.stars] * champion.SP - shield_amount = stats.SHIELD_AMOUNT[champion.name][champion.stars] * champion.SP - champion.add_que('shield', 0, None, None, - {'amount': shield_amount, 'identifier': shield_identifier, 'applier': champion, - 'original_amount': shield_amount}, - {'increase': True, 'expires': stats.ABILITY_LENGTH[champion.name][champion.stars]}) - - neighbor_enemies = field.enemies_in_distance(champion, champion.y, champion.x, 1) - - for n in neighbor_enemies: - old_target = n.target - n.add_que('change_target', -1, None, None, champion) - n.add_que('change_target', stats.ABILITY_LENGTH[champion.name][champion.stars], None, None, old_target) - - -def sylas(champion): - default_ability_calls(champion) - - smash_line = [] - - # print("SYLAS ABILITY FIELD LINE") - # print(field.line) - if champion.target: - targetLine = field.line({'y': champion.y, 'x': champion.x}, {'y': champion.target.y, 'x': champion.target.x}) - if len(targetLine) > 1: - first_hex = targetLine[1] - - neighbors = field.find_neighbors(champion.y, champion.x, True) - primary_neighbors = [] - for p in neighbors: - d_champion = field.distance({'y': champion.y, 'x': champion.x}, {'y': p[0], 'x': p[1]}, False) - d_first_hex = field.distance({'y': first_hex[0], 'x': first_hex[1]}, {'y': p[0], 'x': p[1]}, False) - if d_champion == 1 and d_first_hex == 1: - primary_neighbors.append(p) - - smash_line.append(first_hex) - smash_line.append(sylas_ability(champion, {'hexes': primary_neighbors, 'distance': 2})) - smash_line.append(sylas_ability(champion, {'hexes': primary_neighbors, 'distance': 3})) - - # print("SYLAS ABILITY SMASH LINE") - # print(smash_line) - coords = field.coordinates - for s in smash_line: - # print("IN SYLAS ABILITY") - # print(coords) - if coords and s[0] < 8 and s[1] < 7: - c = coords[s[0]][s[1]] - if c and c.team != champion.team and c.champion: - - # increase next spell mana cost of every enemy - # in the line by 33% = reduce mana by 33% of maxmana - if not c.mana_cost_increased and c.maxmana > 0: - mana_reduce_amount = c.maxmana * stats.ABILITY_MANA_REQUIREMENT_INCREASEMENT[champion.name] - start_value = c.mana - c.mana -= mana_reduce_amount - c.print(' {} {} --> {}'.format('mana', round(start_value, 1), round(c.mana, 1))) - c.add_que('change_stat', -1, None, 'mana_cost_increased', True) - - champion.spell(c, stats.ABILITY_DMG[champion.name][champion.stars]) - - -# get the hexes to the smash lane -def sylas_ability(champion, data): - distance = data['distance'] - hexes = data['hexes'] - - x_from_champion = field.hexes_distance_away(champion.y, champion.x, distance, True) - x_from_n0 = field.hexes_distance_away(hexes[0][0], hexes[0][1], distance, True) - x_from_n1 = field.hexes_distance_away(hexes[1][0], hexes[1][1], distance, True) - x_away = list(set(map(tuple, x_from_n0)).intersection(set(map(tuple, x_from_n1)))) - x_away = list(set(map(tuple, x_from_champion)).intersection(set(map(tuple, x_away)))) - - return [x_away[0][0], x_away[0][1]] - - -def talon(champion): - # - # 1. deal spell dmg - # 2. attack with additional damage - # 3. if kills the target - # fill mana - # apply 1000ms ability_active delay - # immune during those 1000ms - # teleport next to an enemy unit which has dealt the most dmg - # change talon's target to that unit - - default_ability_calls(champion) - - if not champion.target: - field.find_target(champion) - original_target = champion.target - - champion.spell(champion.target, stats.ABILITY_DMG[champion.name][champion.stars]) - - # if the target dies to the spell dmg, 'champion.target' will yield 'None' - if champion.target: - bonus_dmg = champion.AD * (stats.ABILITY_DAMAGE_MULTIPLIER[champion.name][champion.stars] - 1) - champion.attack(bonus_dmg) - - if not champion.target or (champion.target != original_target): - next_target = None - - # find an enemy who has the lowest armor - enemy_team = champion.enemy_team() - enemies = [] - for e in enemy_team: - enemies.append([e, e.armor]) - enemies = sorted(enemies, key=lambda x: x[1]) - if len(enemies) > 0: - next_target = enemies[0][0] - champion.add_que('change_stat', -1, None, 'ability_active', True) - # champion.add_que('change_stat', -1, None, 'immune', True) - champion.add_que('change_stat', stats.ABILITY_LENGTH[champion.name], None, 'ability_active', False) - # champion.add_que('change_stat', stats.ABILITY_LENGTH[champion.name], None, 'immune', False) - # champion.add_que('change_stat', stats.ABILITY_LENGTH[champion.name], None, 'mana', champion.maxmana) - - # make sure that talon doesnt try to move while we simulate the jump - champion.idle = False - champion.clear_que_idle() - champion.add_que('clear_idle', stats.ABILITY_LENGTH[champion.name]) - - champion.add_que('execute_function', stats.ABILITY_LENGTH[champion.name], - [talon_ability, {'target': next_target}]) - - -def talon_ability(champion, data): - if data['target'].health > 0: - target_neighbors = field.find_neighbors(data['target'].y, data['target'].x) - random.shuffle(target_neighbors) - jump_target = None - coords = field.coordinates - for t in target_neighbors: - c = coords[t[0]][t[1]] - if not c: - jump_target = t - break - - if jump_target: - champion.print(' leaps') - for e in champion.enemy_team(): - if e.target == champion: - field.find_target(e) - - champion.move(jump_target[0], jump_target[1], True) - champion.clear_que_idle() - champion.add_que('clear_idle', 0) - champion.add_que('change_target', 0, None, None, data['target']) - - -def teemo(champion): - default_ability_calls(champion) - - enemy_team = champion.enemy_team() - enemies = [] - for e in enemy_team: - enemies.append([e, e.AS]) - - enemies = sorted(enemies, key=lambda x: x[1], reverse=True) - target = enemies[0][0] - - targets = field.enemies_in_distance(champion, target.y, target.x, 1) - - # if two teemo ults will be active at the same time, just fill the spell deals back to 6 (teemo's ability slices) - # if teemo is a mage, just let him double cast and deal the full damage - if not ((origin_class.get_origin_class_tier(champion.team, 'mage') > 0 - and origin_class.is_trait(champion, 'mage'))): - for i in range(0, 5): - que = champion.que_return() - for q in que: - for t in targets: - if q[1] is champion and q[0] == 'execute_function' \ - and q[3][0] == teemo_ability and 'target' in q[3][1] and q[3][1]['target'] == t: - que.remove(q) - champion.que_replace(que) - - slice_length = stats.ABILITY_BLIND_DURATION[champion.name][champion.stars] / stats.ABILITY_SLICES[champion.name] - for i in range(1, stats.ABILITY_SLICES[champion.name] + 1): - for t in targets: - champion.add_que('execute_function', i * slice_length, [teemo_ability, {'target': t}]) - - for t in targets: - t.clear_que_blinded_removal() - t.add_que('change_stat', -1, None, 'blinded', True) - t.add_que('change_stat', stats.ABILITY_BLIND_DURATION[champion.name][champion.stars], None, 'blinded', False) - - -def teemo_ability(champion, data): - target = data['target'] - if target and target.health > 0: - dmg = stats.ABILITY_DMG[champion.name][champion.stars] / stats.ABILITY_SLICES[champion.name] - champion.spell(target, dmg) - - -def thresh(champion): - default_ability_calls(champion) - own_team = champion.own_team() - teammates = [] - for o in own_team: - teammates.append([o, o.health / o.max_health]) - - if len(teammates) == 0: - return - teammates = sorted(teammates, key=lambda x: x[1]) - target = teammates[0][0] - - target_neighbors = field.find_neighbors(target.y, target.x) - - shielded_allies = [target] - - coords = field.coordinates - for t in target_neighbors: - c = coords[t[0]][t[1]] - if c and c.team == champion.team and c.champion: - shielded_allies.append(c) - - for a in shielded_allies: - for i in range(0, 3): - for s in a.shields: - if s['applier'] == champion: - shield_before = a.shield_amount() - a.shields.remove(s) - a.print(' {} {} --> {}'.format('shield', ceil(shield_before), ceil(a.shield_amount()))) - break - - identifier = champion_functions.MILLIS() * stats.SHIELD_AMOUNT[champion.name][champion.stars] * champion.SP - shield_amount = stats.SHIELD_AMOUNT[champion.name][champion.stars] * champion.SP - a.add_que('shield', -1, None, None, {'amount': shield_amount, 'identifier': identifier, 'applier': champion, - 'original_amount': shield_amount}, - {'increase': True, 'expires': stats.SHIELD_LENGTH[champion.name]}) - - -# Time to add a few comments because I need to understand what is happening here. -def twistedfate(champion): - default_ability_calls(champion) - - # middle line - # using the rectangle function which kinda sucks for something like this. - # sometimes it misses the target be cause of rng (check 'twistedfate_ult'), - # so fixing it by changing the orange path to the blue one - if champion.target is None: - return - line = field.rectangle_from_champion_to_wall_behind_target(champion, 1, champion.target.y, champion.target.x)[0] - distance = field.distance(champion, champion.target, True) - if int(distance) >= len(line): - distance = len(line) - 1 - # print("Changing distance to {}".format(distance)) - if distance != -1: - line[int(distance)] = [champion.target.y, champion.target.x] - - # find the first hex of the side paths - neighbors = field.find_neighbors(champion.y, champion.x) - for i, n in enumerate(neighbors): - d = field.distance({'y': n[0], 'x': n[1]}, {'y': champion.target.y, 'x': champion.target.x}, False) - neighbors[i] = [n, d] - - neighbors = sorted(neighbors, key=lambda x: x[1]) - neighbors = list(filter(lambda x: x[0] != [champion.target.y, champion.target.x], neighbors)) - - # print("In TF Ability") - # print(neighbors) - if len(neighbors) > 1 and neighbors[0][1] != neighbors[1][1]: - neighbors = neighbors[1:] - - # print("IN TWISTED FATE ABILITY - Neighbors") - # print(neighbors) - if neighbors: - side_line0 = twistedfate_ability(champion, {'c': [neighbors[0][0][0], neighbors[0][0][1]]}) - # Experiencing a bug if tf is on the side of the board and - # one of the lines of cards starts off of the board. - if len(neighbors) > 1: - side_line1 = twistedfate_ability(champion, {'c': [neighbors[1][0][0], neighbors[1][0][1]]}) - - all_hit_hexes = [line] - if neighbors: - all_hit_hexes.append(side_line0) - if len(neighbors) > 1: - all_hit_hexes.append(side_line1) - - already_targeted = [] - coords = field.coordinates - for a in all_hit_hexes: - for h in a: - c = coords[h[0]][h[1]] - if c and c.team != champion.team and c.champion and c not in already_targeted: - already_targeted.append(c) - champion.spell(c, stats.ABILITY_DMG[champion.name][champion.stars]) - - -# get a straight line for the cards to fly -def twistedfate_ability(champion, data): - c = data['c'] - - y_diff = c[0] - champion.y - x_diff = 0 - # find the change in x (always +1 or -1) - if champion.y % 2 == 0: - if y_diff != 0: - if c[1] > champion.x: - x_diff = 1 - if c[1] == champion.x: - x_diff = -1 - else: - x_diff = c[1] - champion.x - - if champion.y % 2 == 1: - if y_diff != 0: - if c[1] == champion.x: - x_diff = 1 - if c[1] < champion.x: - x_diff = -1 - else: - x_diff = c[1] - champion.x - - line = [] - - # flight path - # the x coordinate behaves differently depending on if the y coordinate is odd or even - x = champion.x - if y_diff > 0: - for i in range(champion.y, 8): - if x_diff == 1 and i % 2 == 1 and i != champion.y: - x += x_diff - if x_diff == -1 and i % 2 == 0 and i != champion.y: - x += x_diff - line.append([i, x]) - - if y_diff < 0: - for i in range(champion.y, -1, -1): - if x_diff == -1 and i % 2 == 0 and i != champion.y: - x += x_diff - if x_diff == 1 and i % 2 == 1 and i != champion.y: - x += x_diff - line.append([i, x]) - - if y_diff == 0: - end_x = -1 - if x_diff == 1: - end_x = 7 - for i in range(champion.x, end_x, x_diff): - line.append([champion.y, i]) - - # drop off possible coordinates outside the map - for i in range(0, 5): - for l in line: - if (l[0] < 0 or l[0] > 7 or l[1] < 0 or l[1] > 6): - line.remove(l) - - return (line) - - -def veigar(champion): - default_ability_calls(champion) - - enemy_team = champion.enemy_team() - enemies = [] - for e in enemy_team: - enemies.append([e, e.health]) + return - enemies = sorted(enemies, key=lambda x: x[1]) - target = enemies[0][0] +def olaf(champion): + return - champion.spell(target, stats.ABILITY_DMG[champion.name][champion.stars]) +def poppy(champion): + return - # making the change here so the change goes through before mage's second cast - if target.health <= 0: - start_value = champion.SP - champion.SP += stats.ABILITY_SP_GAIN[champion.name][champion.stars] - champion.print(' {} {} --> {}'.format('SP', round(start_value, 2), round(champion.SP, 2))) +def rakan(champion): + return +def rumble(champion): + return -vi_armor_list = [] +def ryze(champion): + return +def seraphine(champion): + return -def vi(champion): - default_ability_calls(champion) - target = champion.target - distance = field.distance(champion, target, True) +def shen(champion): + return - target_neighbors = field.find_neighbors(target.y, target.x, True) - for i, t in enumerate(target_neighbors): - d = field.distance({'y': champion.y, 'x': champion.x}, {'y': t[0], 'x': t[1]}, False) - target_neighbors[i] = [t, d] +def shyvana(champion): + return - side_primary_neighbors = list(filter(lambda x: x[1] == 1, target_neighbors)) +def smolder(champion): + return - # print("In Vi's Ability") - # print(side_primary_neighbors) - if side_primary_neighbors and len(side_primary_neighbors) > 1 and len(side_primary_neighbors[0]) > 1 \ - and len(side_primary_neighbors[1]) > 1: - x_from_champion = field.hexes_distance_away(champion.y, champion.x, distance + 1, True) - x_from_n0 = field.hexes_distance_away(side_primary_neighbors[0][0][0], side_primary_neighbors[0][0][1], 2, True) - x_from_n1 = field.hexes_distance_away(side_primary_neighbors[1][0][0], side_primary_neighbors[1][0][1], 2, True) - x_away = list(set(map(tuple, x_from_n0)).intersection(set(map(tuple, x_from_n1)))) - x_away = list(set(map(tuple, x_from_champion)).intersection(set(map(tuple, x_away)))) +def soraka(champion): + return - affected_hexes = field.hexes_in_distance(x_away[0][0], x_away[0][1], 1) +def swain(champion): + return - coords = field.coordinates - for a in affected_hexes: - c = coords[a[0]][a[1]] - if c and c.team != champion.team and c.champion: +def syndra(champion): + return - # to make sure there are no double reductions, - # check how long ago the target's armor was reduced last time by this vi - # the armor list elements are of syntax: [reducer, target, milliseconds_when_last_reduced] - # search for target entries - armor_history = (list(filter(lambda x: x[1] == c, vi_armor_list))) - can_be_changed = False - for ar in armor_history: - # there can be multiple vis, so make sure that this entry was done by the current vi - if ar[0] == champion: +def tahm_kench(champion): + return - # amount of ms when reduced last time - diff = champion_functions.MILLIS() - ar[2] - # if more than reduction length, allow new reduction - if diff > stats.ABILITY_LENGTH[champion.name]: - can_be_changed = True +def taric(champion): + return - if len(armor_history) == 0: - can_be_changed = True +def tristana(champion): + return - if can_be_changed: - c.print(' {} {} --> {}'.format('armor', c.armor, - c.armor * stats.ABILITY_ARMOR_DECREASE[champion.name][ - champion.stars])) - c.armor *= stats.ABILITY_ARMOR_DECREASE[champion.name][champion.stars] - c.clear_que_armor_removal() - c.add_que('change_stat', stats.ABILITY_LENGTH[champion.name], None, 'armor', None, - {'vi': stats.ABILITY_ARMOR_DECREASE[champion.name][champion.stars]}) +def twitch(champion): + return - vi_armor_list.append([champion, c, champion_functions.MILLIS()]) +def varus(champion): + return - champion.spell(c, stats.ABILITY_DMG[champion.name][champion.stars]) +def veigar(champion): + return +def vex(champion): + return def warwick(champion): - default_ability_calls(champion) - champion.add_que('change_stat', -1, None, 'ability_active', True) - champion.add_que('change_stat', -1, None, 'lifesteal', - champion.lifesteal + stats.LIFESTEAL[champion.name][champion.stars]) - champion.add_que('change_stat', -1, None, 'movement_delay', stats.MOVEMENTDELAY[champion.name]) - - new_as = champion.AS + ((stats.ABILITY_AS_GAIN[champion.name][champion.stars] - 1) * champion.SP + 1) - champion.add_que('change_stat', -1, None, 'AS', new_as) - + return def wukong(champion): - default_ability_calls(champion) - - target = champion.target - target.add_que('change_stat', -1, None, 'stunned', True) - target.clear_que_stunned_removal() - target.add_que('change_stat', stats.ABILITY_STUN_DURATION[champion.name][champion.stars], None, 'stunned', False) - - bonus_dmg = (champion.AD * (stats.ABILITY_DAMAGE_MULTIPLIER[champion.name][champion.stars] * champion.SP - 1)) - champion.attack(bonus_dmg) - - -def xinzhao(champion): - default_ability_calls(champion) - - enemies = field.enemies_in_distance(champion, champion.y, champion.x, 1) - bonus_dmg = champion.AD * (stats.ABILITY_DAMAGE_MULTIPLIER[champion.name][champion.stars] * champion.SP - 1) - for e in enemies: - champion.attack(bonus_dmg, e) - - champion.add_que('change_stat', -1, None, 'armor', - champion.armor + stats.ABILITY_ARMOR_MR_INCREASE[champion.name][champion.stars]) - champion.add_que('change_stat', -1, None, 'MR', - champion.MR + stats.ABILITY_ARMOR_MR_INCREASE[champion.name][champion.stars]) - - -def yasuo(champion): - default_ability_calls(champion) - - hexes = yasuo_ability(champion, {}) - bonus_dmg = champion.AD * (stats.ABILITY_DAMAGE_MULTIPLIER[champion.name][champion.stars] * champion.SP - 1) - - if (len(hexes) > 0): - target1 = hexes[0][0][1] - target2 = hexes[0][0][2] - if ([champion.y, champion.x] != hexes[0][0][0]): - champion.move(hexes[0][0][0][0], hexes[0][0][0][1], True) - champion.idle = True - champion.clear_que_idle() - champion.attack(bonus_dmg, target1) - champion.attack(bonus_dmg, target2) - - - else: - champion.attack(bonus_dmg, champion.target) - apply_attack_cooldown(champion) - - -# find all the possible hexes where yasuo can strike two enemies -# this is a bit tricky -# go through all free hexes -# find hexes has an enemy neighbor -# then find the commong neighbors of the hex and the enemy -# find the hex that has a distance of two to the original hex and both neighbors -# if this hex is an enemy, we can slash from here -# add to list and sort the list by distances to yasuo -def yasuo_ability(champion, data): - hexes = field.hexes_in_distance(0, 0, 20) - coords = field.coordinates - - possible_hexes = [] - - for h in hexes: - if (h == [champion.y, champion.x] or not coords[h[0]][h[1]]): - neighbors = field.find_neighbors(h[0], h[1]) - for n in neighbors: - c = coords[n[0]][n[1]] - if (c and c.team != champion.team and c.champion): - c_neighbors = field.find_neighbors(c.y, c.x) - one_away = list(set(map(tuple, c_neighbors)).intersection(set(map(tuple, neighbors)))) - - if (len(one_away) == 2): - x_from_champion = field.hexes_distance_away(h[0], h[1], 2, False) - x_from_n0 = field.hexes_distance_away(one_away[0][0], one_away[0][1], 2, False) - x_from_n1 = field.hexes_distance_away(one_away[1][0], one_away[1][1], 2, False) - x_away = list(set(map(tuple, x_from_n0)).intersection(set(map(tuple, x_from_n1)))) - x_away = list(set(map(tuple, x_from_champion)).intersection(set(map(tuple, x_away)))) - if (len(x_away) > 0): - x_away = x_away[0] - c2 = coords[x_away[0]][x_away[1]] - if (c2 and c2.team != champion.team and c2.champion): - possible_hexes.append([h, c, c2]) - - for i, p in enumerate(possible_hexes): - distance = field.distance({'y': champion.y, 'x': champion.x}, {'y': p[0][0], 'x': p[0][1]}, False) - possible_hexes[i] = [p, distance] - possible_hexes = sorted(possible_hexes, key=lambda x: x[1]) - return (possible_hexes) - - -yone_list = [] -yone_checking = False - - -# welcome to the loop city -# the sir lord mayor is named 'for' -# dude's a dick tho -def yone(champion): - global yone_list - global yone_checking - default_ability_calls(champion) - - if (not yone_checking): - champion.add_que('execute_function', 0, [yone_ability, {'loop': True}]) - yone_checking = True - - coords = field.coordinates - - # Seal Fate - if champion.maxmana == stats.MAXMANA[champion.name] and champion.target: - if not champion.target: - field.find_target(champion) - path = field.rectangle_from_champion_to_wall_behind_target(champion, stats.ABILITY_RADIUS[champion.name], - champion.target.y, champion.target.x) - for i, p in enumerate(path): - if (len(p) > 5): path[i] = p[:5] - - middle_line = floor(stats.ABILITY_RADIUS[champion.name] / 2) - if not path[middle_line]: - dash_coordinate = [champion.target.y, champion.target.x] - else: - dash_coordinate = path[middle_line][-1] - - # since the path function kinda sucks (especially when going straight up or down), check if the target is in the path - # if not, change the path a bit to force the target there - distance = field.distance(champion, champion.target, True) - if (len(path[middle_line]) > distance): - found = False - for pp in path: - for p in pp: - if ([p[0], p[1]] == [champion.target.y, champion.target.x]): - found = True - if (not found): - path[middle_line][int(distance)] = [champion.target.y, champion.target.x] - - # if the dash coordinate is taken, find the closest free hex - possible_targets = field.hexes_in_distance(dash_coordinate[0], dash_coordinate[1], 2) - for i, p in enumerate(possible_targets): - d = field.distance({'y': p[0], 'x': p[1]}, {'y': dash_coordinate[0], 'x': dash_coordinate[1]}, False) - possible_targets[i].append(d) - - random.shuffle(possible_targets) - possible_targets = sorted(possible_targets, key=lambda x: x[2]) - - # go through the sorted list of path hexes and find the first one that's free - dash_coordinate = None - for p in possible_targets: - c = coords[p[0]][p[1]] - if (not c): - dash_coordinate = p - break - - # find out how many enemies are there on the path - enemies = 0 - for pp in path: - for p in pp: - c = coords[p[0]][p[1]] - if (c and c.team != champion.team and c.champion): - enemies += 1 - if (enemies > 0): - damage_per_enemy = stats.ABILITY_DMG[champion.name][champion.stars] / enemies - already_targeted = [] - for pp in path: - for p in pp: - c = coords[p[0]][p[1]] - if (c and c.team != champion.team and c.champion and c not in already_targeted): - - c.print( - ' {} {} --> {}'.format('MR', c.MR, c.MR * stats.ABILITY_ARMOR_MR_DECREASE[champion.name])) - c.print(' {} {} --> {}'.format('armor', c.armor, - c.armor * stats.ABILITY_ARMOR_MR_DECREASE[champion.name])) - c.MR *= stats.ABILITY_ARMOR_MR_DECREASE[champion.name] - c.armor *= stats.ABILITY_ARMOR_MR_DECREASE[champion.name] - - # c.add_que('change_stat', -1, None, 'stunned', True) - # c.clear_que_stunned_removal() - # c.add_que('change_stat', stats.ABILITY_STUN_DURATION[champion.name][champion.stars], None, 'stunned', False) - - already_targeted.append(c) - champion.spell(c, damage_per_enemy) - if (c.health > 0): - yone_list.append([champion, c]) - if (yone_helper(champion) > 0): - champion.print( - ' {} {} --> {}'.format('maxmana', champion.maxmana, stats.SECONDARY_MAXMANA[champion.name])) - champion.maxmana = stats.SECONDARY_MAXMANA[champion.name] - champion.print(' list length {} --> {}'.format(0, yone_helper(champion))) - - if (dash_coordinate): - champion.move(dash_coordinate[0], dash_coordinate[1], True) - apply_attack_cooldown(champion) - - # Unforgotten - elif champion.maxmana == stats.SECONDARY_MAXMANA[champion.name] and champion.target: - # sort the marked enemies by hp and check their neighboring hexes - # whichever has the first free hex, is going to be the dash target - marked_enemies = [] - for y in yone_list: - if y[0] == champion: - marked_enemies.append([y[1], y[1].health]) - marked_enemies = sorted(marked_enemies, key=lambda x: x[1]) - - dash_coordinate = None - target = None - - # as we have the list sorted by health, start rolling through it - # go through every unit's every neighbor until we have a free one - for m in marked_enemies: - neighbors = field.find_neighbors(m[0].y, m[0].x) - random.shuffle(neighbors) - for n in neighbors: - c = coords[n[0]][n[1]] - if not c: - target = m[0] - dash_coordinate = n - break - if target: - break - - if target: - damage = (target.max_health - target.health) * stats.ABILITY_MISSING_HEALTH_DAMAGE_PERCENTAGE[champion.name] - damage += stats.ABILITY_SECONDARY_DMG[champion.name][champion.stars] - - distance = field.distance(champion, target, True) - if distance > 1: - champion.print(' dashes') - champion.move(dash_coordinate[0], dash_coordinate[1], True) - champion.spell(target, damage) - champion.add_que('execute_function', 0, [yone_ability, {'loop': False}]) - - -# check if someone on the list has died -def yone_ability(champion, data): - global yone_list - - old_length = yone_helper(champion) - yone_list = list(filter(lambda x: x[1].health > 0, yone_list)) - new_length = yone_helper(champion) - if (new_length != old_length): - champion.print(' list length {} --> {}'.format(old_length, new_length)) - - if (yone_helper(champion) == 0 and champion.maxmana != stats.MAXMANA[champion.name]): - champion.print(' {} {} --> {}'.format('maxmana', champion.maxmana, stats.MAXMANA[champion.name])) - champion.maxmana = stats.MAXMANA[champion.name] - - if (data['loop']): - champion.add_que('execute_function', 50, [yone_ability, {'loop': True}]) - - -def yone_helper(champion): - global yone_list - counter = 0 - for y in yone_list: - if (y[0] == champion): - counter += 1 - return counter - - -def yuumi(champion): - default_ability_calls(champion) - champion.add_que('change_stat', -1, None, 'ability_active', True) - champion.add_que('change_stat', stats.ABILITY_LENGTH[champion.name], None, 'ability_active', False) - - own_team = champion.own_team() - allies = [] - for e in own_team: - allies.append([e, e.health / e.max_health]) - - allies = sorted(allies, key=lambda x: x[1]) - # If the allied already died. Should basically never need to return - if not allies: - print("some dead yummi allies. Should never really see this.") - return - first_target = allies[0][0] - - # heal and change AS for the first target - heal_amount = (first_target.max_health - first_target.health) * \ - stats.ABILITY_HEALTH_GAIN_PERCENTAGES[champion.name][champion.stars] * champion.SP - first_target.add_que('heal', -1, None, None, heal_amount) - as_gain = (stats.ABILITY_AS_GAIN[champion.name][champion.stars] - 1) * champion.SP + 1 - - first_target.add_que('change_stat', -1, None, 'AS', first_target.AS * as_gain) - first_target.add_que('change_stat', stats.ABILITY_AS_CHANGE_LENGTH[champion.name], None, 'AS', None, - {'ezreal': as_gain}) - - second_target = None - dash_target = None - if len(own_team) == 2: - second_target = list(filter(lambda x: x != first_target, own_team))[0] - - # find the ally that's furthest away from the first target - if len(own_team) > 2: - team_distances = [] - for o in own_team: - if o != first_target: - d = field.distance(first_target, o, True) - if o == champion: - d = 0 - team_distances.append([o, d]) - - team_distances = sorted(team_distances, key=lambda x: x[1], reverse=True) - second_target = team_distances[0][0] - - # find the closest free coordinate next to the second target - coords = field.coordinates - possible_targets = field.hexes_in_distance(second_target.y, second_target.x, 2) - for i, p in enumerate(possible_targets): - d = field.distance({'y': p[0], 'x': p[1]}, {'y': second_target.y, 'x': second_target.x}, False) - possible_targets[i].append(d) - - random.shuffle(possible_targets) - possible_targets = sorted(possible_targets, key=lambda x: x[2]) - - # go through the sorted list of path hexes and find the first one that's free - for p in possible_targets: - c = coords[p[0]][p[1]] - if not c: - dash_target = p - break - - if second_target: - pause = 0 - - # fixing a bug which comes from stacking stat changes in the same milliseconds. - # yuumi will instantly heal and buff the second ally if she is a mage - - heal_amount = (second_target.max_health - second_target.health) * \ - stats.ABILITY_HEALTH_GAIN_PERCENTAGES[champion.name][champion.stars] * champion.SP - second_target.add_que('heal', pause, None, None, heal_amount) - - second_target.add_que('change_stat', pause, None, 'AS', second_target.AS * as_gain) - second_target.add_que('change_stat', stats.ABILITY_AS_CHANGE_LENGTH[champion.name] + pause, None, 'AS', None, - {'ezreal': as_gain}) - - if dash_target: - champion.move(dash_target[0], dash_target[1], True) - - -def zilean(champion): - default_ability_calls(champion) - - own_team = champion.own_team() - target_list = [] + return - for o in own_team: - # do not add zilean himself or anyone who is targeted and not dead - if (o != champion and not o.will_revive[0][0]): - target_list.append([o, o.health]) +def xerath(champion): + return - target_list = sorted(target_list, key=lambda x: x[1]) - target_amount = stats.ABILITY_TARGETS[champion.name][champion.stars] - - if (len(target_list) > target_amount): - target_list = target_list[:target_amount] - - # fill the unit's.will_revive's first slot which is reserved for zliean - # the revive itself is handled in "champion_functions.py"'s 'die()' -function - for a in target_list: - champion.print(' placed orb on {} {}'.format(a[0].team, a[0].name)) - old_value = [[a[0].will_revive[0][0]], [a[0].will_revive[1][0]]] - a[0].will_revive[0][0] = champion - new_value = [[a[0].will_revive[0][0].name], [a[0].will_revive[1][0]]] - a[0].print(' {} {} --> {}'.format('will_revive', old_value, new_value)) - - -def galio(champion): - default_ability_calls(champion) - - if (champion.stars >= 2): - new_damage_receiving = champion.receive_decreased_damage * stats.ABILITY_TARGET_DECREASE_DAMAGE_RECEIVING[ - champion.name] - champion.add_que('change_stat', 0, None, 'receive_decreased_damage', new_damage_receiving) - - # taunting - neighbor_enemies = field.enemies_in_distance(champion, champion.y, champion.x, 1) - for n in neighbor_enemies: - old_target = n.target - n.add_que('change_target', -1, None, None, champion) - n.add_que('change_target', stats.ABILITY_LENGTH[champion.name], None, None, old_target) - - # execute the second part of the ult in x seconds - champion.add_que('execute_function', stats.ABILITY_LENGTH[champion.name], [galio_ability, {}]) +def ziggs(champion): + return +def zilean(champion): + return -def galio_ability(champion, data): - end_damage_receiving = champion.receive_decreased_damage / stats.ABILITY_TARGET_DECREASE_DAMAGE_RECEIVING[ - champion.name] - champion.add_que('change_stat', 0, None, 'receive_decreased_damage', end_damage_receiving) +def zoe(champion): + return - radius = stats.ABILITY_RADIUS[champion.name] - targets = field.enemies_in_distance(champion, champion.y, champion.x, radius) - for t in targets: - champion.spell(t, stats.ABILITY_DMG[champion.name][champion.stars]) diff --git a/Set12Simulator/item_stats.py b/Set12Simulator/item_stats.py index f044601..509597a 100755 --- a/Set12Simulator/item_stats.py +++ b/Set12Simulator/item_stats.py @@ -1,65 +1,179 @@ items = { - 'bf_sword': {'AD': 15}, - 'chain_vest': {'armor': 25}, - 'giants_belt': {'health': 200}, - 'needlessly_large_rod': {'SP': 0.15}, - 'negatron_cloak': {'MR': 25}, - 'recurve_bow': {'AS': 1.15}, - 'sparring_gloves': {'crit_chance': 0.10, 'dodge': 0.1}, + 'bf_sword': {'AD': 10}, + 'chain_vest': {'armor': 20}, + 'giants_belt': {'health': 150}, + 'needlessly_large_rod': {'SP': 0.10}, + 'negatron_cloak': {'MR': 20}, + 'recurve_bow': {'AS': 1.10}, + 'sparring_gloves': {'crit_chance': 0.20}, 'spatula': {}, + 'frying_pan': {}, 'tear_of_the_goddess': {'mana': 15}, - 'bloodthirster': {'AD': 15, 'MR': 25, 'lifesteal': 0.40}, - 'blue_buff': {'mana': 30}, + 'bloodthirster': {'AD': 15, 'SP': 0.15, 'MR': 20, 'lifesteal': 0.20}, + 'blue_buff': {'AD': 15, 'SP': 0.15, 'mana': 20}, 'bramble_vest': {'armor': 50}, - 'chalice_of_power': {'mana': 15, 'MR': 25}, - 'deathblade': {'AD': 50}, - 'dragons_claw': {'spell_damage_reduction_percentage': 0.4, 'MR': 50}, - 'duelists_zeal': {'AS': 1.15}, - 'elderwood_heirloom': {'MR': 15}, - 'force_of_nature': {}, - 'frozen_heart': {'armor': 25, 'mana': 15}, - 'gargoyle_stoneplate': {'armor': 25, 'MR': 25}, - 'giant_slayer': {'AD': 15, 'AS': 1.15}, - 'guardian_angel': {'AD': 15, 'armor': 25, 'will_revive': [[None], ['guardian_angel']]}, - 'guinsoos_rageblade': {'AS': 1.15, 'SP': 0.15}, - 'hand_of_justice': {'crit_chance': 0.10, 'dodge': 0.10, 'mana': 15}, - 'hextech_gunblade': {'AD': 15, 'SP': 0.15}, - 'infinity_edge': {'AD': 15, 'crit_chance': 0.2}, - 'ionic_spark': {'SP': 0.15, 'MR': 25}, - 'jeweled_gauntlet': {'SP': 0.15, 'crit_chance': 0.2, 'crit_damage': 0.4}, - 'last_whisper': {'AS': 1.15, 'crit_chance': 0.2}, - 'locket_of_the_iron_solari': {'SP': 0.15, 'armor': 25}, - 'ludens_echo': {'SP': 0.15, 'mana': 15}, - 'mages_cap': {'mana': 15}, - 'mantle_of_dusk': {'SP': 0.15}, - 'morellonomicon': {'SP': 0.15, 'health': 200}, - 'quicksilver': {'MR': 25, 'dodge': 0.20}, - 'rabadons_deathcap': {'SP': 0.80}, - 'rapid_firecannon': {'AS': 1.30}, - 'redemption': {'mana': 15, 'health': 200}, - 'runaans_hurricane': {'AS': 1.15, 'MR': 25}, - 'shroud_of_stillness': {'armor': 25, 'dodge': 0.20}, - 'spear_of_shojin': {'AD': 15, 'mana': 15}, - 'statikk_shiv': {'AS': 1.15, 'mana': 15}, - 'sunfire_cape': {'armor': 25, 'health': 200}, - 'sword_of_the_divine': {'AD': 15}, - 'thieves_gloves': {'crit_chance': 0.2, 'dodge': 0.2}, - 'titans_resolve': {'AS': 1.15, 'armor': 20}, - 'trap_claw': {'health': 200, 'dodge': 0.20}, - 'vanguards_cuirass': {'armor': 25}, - 'warlords_banner': {'health': 200}, - 'warmogs_armor': {'health': 1000}, - 'youmuus_ghostblade': {'crit_chance': 0.10, 'dodge': 0.10}, - 'zekes_herald': {'AD': 15, 'health': 200}, - 'zephyr': {'health': 200, 'MR': 25}, - 'zzrot_portal': {'AS': 1.15, 'health': 200}, - - 'kayn_rhast': {}, - 'kayn_shadowassassin': {}, - + 'adaptive_helm': {'SP': 0.10, 'mana': 15, 'MR': 20}, + 'deathblade': {'AD': 50, 'AMP': 0.08}, + 'dragons_claw': {'MR': 65}, + 'protectors_vow': {'armor': 20, 'mana': 30}, + 'gargoyle_stoneplate': {'armor': 25, 'MR': 25, 'health': 100}, + 'giant_slayer': {'AD': 25, 'SP': 0.25, 'AS': 1.10}, + 'edge_of_night': {'AD': 10, 'armor': 20}, + 'guinsoos_rageblade': {'AS': 1.10, 'SP': 0.10}, + 'hand_of_justice': {'crit_chance': 0.20, 'mana': 15}, + 'hextech_gunblade': {'AD': 15, 'SP': 0.15, 'lifesteal': 0.20}, + 'infinity_edge': {'AD': 35, 'crit_chance': 0.35}, + 'ionic_spark': {'SP': 0.15, 'MR': 25, 'health': 100}, + 'jeweled_gauntlet': {'SP': 0.35, 'crit_chance': 0.35}, + 'last_whisper': {'AD': 15, 'AS': 1.20, 'crit_chance': 0.2}, + 'crownguard': {'SP': 0.10, 'armor': 20, 'health': 100}, + 'archangels_staff': {'SP': 0.20, 'mana': 15}, + 'morellonomicon': {'SP': 0.25, 'AS':1.10, 'health': 150}, + 'quicksilver': {'MR': 20, 'AS': 1.30, 'crit_chance': 0.20}, + 'rabadons_deathcap': {'SP': 0.50, 'AMP': 0.15}, + 'red_buff': {'AS': 1.35, 'AMP': 0.06}, + 'redemption': {'mana': 15, 'health': 150}, + 'runaans_hurricane': {'AD': 25, 'AS': 1.10, 'MR': 20}, + 'steadfast_heart': {'armor': 20, 'crit_chance': 0.20, 'health': 200}, + 'spear_of_shojin': {'AD': 15, 'SP': 0.15, 'mana': 15}, + 'statikk_shiv': {'SP': 0.15, 'AS': 1.15, 'mana': 15}, + 'sunfire_cape': {'armor': 20, 'health': 250}, + 'thieves_gloves': {'crit_chance': 0.2, 'health': 150}, + 'titans_resolve': {'AS': 1.10, 'armor': 20}, + 'guardbreakter': {'SP': 0.10, 'AS': 1.20,'health': 150, 'dodge': 0.20}, + 'warmogs_armor': {'health': 600}, + 'steraks_gage': {'AD': 15, 'health': 150}, + 'evenshroud': {'health': 150, 'MR': 20}, + 'nashors_tooth': {'SP': 0.10, 'AS': 1.10, 'health': 150}, + + 'absolution' : {'health': 400, 'mana': 15}, + 'blessed_bloodthirster': {'AD': 40, 'SP': 0.40, 'MR': 20, 'lifesteal': 0.40}, + 'blue_blessing': {'AD': 50, 'SP': 0.50, 'mana': 20}, + 'brink_of_dawn': {'AD': 30, 'armor': 30}, + 'bulwarks_oath': {'armor': 40, 'mana': 30}, + 'covalent_spark': {'SP': 0.15, 'MR': 40, 'health': 200}, + 'crest_of_cinders': {'AS': 1.60, 'AMP': 0.05}, + 'demonslayer': {'AD': 50, 'SP': 0.50, 'AS': 1.10}, + 'dragons_will': {'MR': 115}, + 'dvarapala_stoneplate': {'armor': 50, 'MR': 50, 'health': 250}, + 'equinox': {'health': 500, 'MR': 30}, + 'eternal_whisper': {'AD': 45, 'AS': 1.25, 'crit_chance': 0.55}, + 'fist_of_fairness': {'crit_chance': 0.40, 'mana': 15}, + 'glamourous_gauntlet': {'SP': 0.55, 'crit_chance': 0.75}, + 'guinsoos_reckoning': {'SP': 0.10, 'AS': 1.20}, + 'hextech_lifeblade': {'AD': 40, 'SP': 0.40, 'lifesteal': 0.30}, + 'jaksho_the_protean': {'SP': 0.25,'MR': 30, 'mana': 15}, + 'legacy_of_the_colossus': {'health': 500, 'armor': 40, 'crit_chance': 0.20}, + 'luminous_deathblade': {'AD': 105, 'AMP': 0.12}, + 'more_more-ellonomicon': {'SP': 0.50, 'AS':1.25, 'health': 150}, + 'quickestsilver': {'MR': 30, 'AS': 1.50, 'crit_chance': 0.40}, + 'rabadons_ascended_deathcap': {'SP': 0.70, 'AMP': 0.33}, + 'rascals_gloves': {'crit_chance': 0.20, 'health': 150}, + 'rosethrorn_vest': {'armor': 100}, + 'royal_crownshield': {'health':200, 'SP': 40, 'armor': 40}, + 'runaans_tempest': {'AD': 35, 'AS': 1.20, 'MR': 20}, + 'spear_of_hirana': {'AD': 35, 'SP': 0.35, 'mana': 20}, + 'statikk_favor': {'SP': 0.50, 'AS': 1.20, 'mana': 15}, + 'steraks_megashield': {'AD': 30, 'health': 400}, + 'sunlight_cape': {'armor': 40, 'health': 450}, + 'the_barons_gift': {'AS': 1.20, 'SP': 0.30, 'health': 200}, + 'titans_vow': {'AS': 1.30, 'armor': 35}, + 'urf-angels-staff': {'SP': 0.50, 'mana': 15}, + 'warmogs_pride': {'health': 1000}, + 'willbreaker': {'AD': 30, 'SP': 0.30, 'AS': 1.30, 'health': 150}, + 'zenith_edge': {'AD': 65, 'crit_chance': 0.75}, + + 'accomplices_glove': {'health': 150, 'crit_chance': 0.20}, + 'aegis_of_the_legion': {'health': 150}, + 'banshees_veil': {'health': 150}, + 'chalice_of_power': {'health': 150}, + 'knights_vow': {'health': 150}, + 'locket_of_the_iron_solari': {'health': 150}, + 'moonstone_renewer': {'health': 150}, + 'needlessly_big_gem': {'health': 150}, + 'obsidian_cleaver': {'health': 150}, + 'randuins_omen': {'health': 150}, + 'shroud_of_stillness': {'health': 150}, + 'spite': {'health': 150}, + 'the_eternal_flame': {'health': 150}, + 'unstable_treasure_chest': {'health': 150}, + 'virtue_of_the_martyr': {'health': 150}, + 'zekes_herald': {'health': 150}, + 'zephyr': {'health': 150}, + 'zzrot_portal': {'health': 150}, + + 'anima_visage': {'health': 450, 'MR': 25}, + 'blacksmiths_gloves': {'crit_chance': 0.30, 'health': 200}, + 'blighting_jewel': {'SP': 0.40}, + 'corrupt_vampiric_scepter': {'AS': 1.60}, + 'deaths_defiance': {'AD': 40, 'armor': 30, 'AS': 1.25, 'lifesteal': 0.25}, + 'deathfire_grasp': {'SP': 0.50, 'mana': 15}, + 'eternal_winter': {'health': 200, 'armor': 20}, + 'fishbones': {'AD': 40, 'AS': 1.40}, + 'forbidden_idol': {'health': 200, 'armor': 25, 'MR': 25}, + 'gamblers_blade': {'SP': 0.10, 'AS': 1.40}, + 'gold_collector': {'AD': 30, 'crit_chance': 0.30}, + 'horizon_focus': {'health': 250, 'mana': 15, 'armor': 20, 'MR': 20}, + 'hullcrusher': {'armor': 35, 'mr': 35, 'AS': 1.30}, + 'infinity_force': {'health': 250, 'AD': 25, 'SP': 0.25, 'armor': 25, 'MR': 25, 'AS': 1.25}, + 'innervating_locket': {'health': 150, 'mana': 15}, + 'lich_bane': {'SP': 0.30, 'mana': 15}, + 'lightshield_crest': {'armor': 50, 'MR': 50}, + 'ludens_tempest': {'AD': 40, 'SP': 0.40}, + 'manazane': {'mana': 15, 'AD': 15, 'SP': 0.10, 'AS': 1.15}, + 'mittens': {'AS': 1.60}, + 'moguls_mail': {'health': 50}, + 'prowlers_claw': {'AD': 50, 'crit_chance': 0.50}, + 'rapid_firecannon': {'AS': 1.75}, + 'seekers_armguard': {'SP': 0.30, 'armor': 30, 'MR': 30}, + 'silvermere_dawn': {'AD': 165, 'armor': 50, 'MR': 50}, + 'snipers_focues': {'AD': 15, 'SP': 15, 'AS': 1.15}, + 'spectral_cutlass': {'AD': 40, 'crit_chance': 0.20}, + 'talisman_of_ascension': {'health': 300, 'AD': 20, 'SP': 0.20}, + 'tricksters_glass': {'armor': 10, 'MR': 10, 'AS': 1.10, 'crit_chance': 0.15}, + 'unending_despair': {'health': 400, 'armor': 40}, + 'wits_end': {'AS': 1.30, 'mana': 30}, + 'zhonyas_paradox': {'SP': 0.45, 'armor': 30, 'MR': 30}, + + 'arcane_emblem': {'health': 150}, + 'bastion_emblem': {'health': 150}, + 'blaster_emblem': {'health': 150}, + 'chrone_emblem': {'health': 150}, + 'eldtrich_emblem': {'health': 150}, + 'faerie_emblem': {'mana': 15}, + 'frostfire_emblem': {'armor': 20}, + 'honeymancey_emblem': {'crit_chance': 0.20}, + 'hunter_emblem': {'health': 150}, + 'incantor_emblem': {'health': 150}, + 'mage_emblem': {'health': 150}, + 'multistriker_emblem': {'health': 150}, + 'portal_emblem': {'SP': 0.10}, + 'preserver_emblem': {'health': 150}, + 'pyro_emblem': {'AS': 1.10}, + 'scholar_emblem': {'health': 150}, + 'shapeshifter_emblem': {'health': 150}, + 'sugarcraft_emblem': {'AD': 10}, + 'vanguard_emblem': {'health': 150}, + 'warrior_emblem': {'health': 150}, + 'witchcraft_emblem': {'MR': 20}, + + 'armor_of_eternal_devotion': {'armor': 60, 'health': 1000}, + 'eternal_monarchs_crown': {'AD': 50, 'SP': 0.50, 'AS': 1.25}, + 'faerie_queens_crown': {'AD': 30, 'SP': 0.30}, + 'queenguards_armor': {'armor': 40, 'health': 250}, + + 'tacticians_crown': {}, + 'tacticians_cape': {}, + 'tacticians_shield': {}, + + 'arcana_signifier': {}, + 'masterwork_upgrade': {}, + + 'lesser_champion_duplicator': {}, 'champion_duplicator': {}, 'magnetic_remover': {}, + 'golden_magnetic_remover': {}, 'reforger': {}, } @@ -73,12 +187,105 @@ 'recurve_bow', 'sparring_gloves', 'spatula', + 'frying_pan', 'tear_of_the_goddess', - 'kayn_rhast', - 'kayn_shadowassassin', + 'lesser_champion_duplicator', 'champion_duplicator', 'magnetic_remover', + 'golden_magnetic_remover', 'reforger', + 'arcana_signifier', + 'masterwork_upgrade' + 'absolution', + 'blessed_bloodthirster', + 'blue_blessing', + 'brink_of_dawn', + 'bulwarks_oath', + 'covalent_spark', + 'crest_of_cinders', + 'demonslayer', + 'dragons_will', + 'dvarapala_stoneplate', + 'equinox', + 'eternal_whisper', + 'fist_of_fairness', + 'glamourous_gauntlet', + 'guinsoos_reckoning', + 'hextech_lifeblade', + 'jaksho_the_protean', + 'legacy_of_the_colossus', + 'luminous_deathblade', + 'more_more-ellonomicon', + 'quickestsilver', + 'rabadons_ascended_deathcap', + 'rascals_gloves', + 'rosethrorn_vest', + 'royal_crownshield', + 'runaans_tempest', + 'spear_of_hirana', + 'statikk_favor', + 'steraks_megashield', + 'sunlight_cape', + 'the_barons_gift', + 'titans_vow', + 'urf-angels-staff', + 'warmogs_pride', + 'willbreaker', + 'zenith_edge', + 'accomplices_glove', + 'aegis_of_the_legion', + 'banshees_veil', + 'chalice_of_power', + 'knights_vow', + 'locket_of_the_iron_solari', + 'moonstone_renewer', + 'needlessly_big_gem', + 'obsidian_cleaver', + 'randuins_omen', + 'shroud_of_stillness', + 'spite', + 'the_eternal_flame', + 'unstable_treasure_chest', + 'virtue_of_the_martyr', + 'zekes_herald', + 'zephyr', + 'zzrot_portal', + 'anima_visage', + 'blacksmiths_gloves', + 'blighting_jewel', + 'corrupt_vampiric_scepter', + 'deaths_defiance', + 'deathfire_grasp', + 'eternal_winter', + 'fishbones', + 'forbidden_idol', + 'gamblers_blade', + 'gold_collector', + 'horizon_focus', + 'hullcrusher', + 'infinity_force', + 'innervating_locket', + 'lich_bane', + 'lightshield_crest', + 'ludens_tempest', + 'manazane', + 'mittens', + 'moguls_mail', + 'prowlers_claw', + 'rapid_firecannon', + 'seekers_armguard', + 'silvermere_dawn', + 'snipers_focues', + 'spectral_cutlass', + 'talisman_of_ascension', + 'tricksters_glass', + 'unending_despair', + 'wits_end', + 'zhonyas_paradox', + 'bastion_emblem', + 'blaster_emblem', + 'incantor_emblem', + 'vanguard_emblem', ] @@ -86,16 +293,13 @@ 'bloodthirster': ['bf_sword', 'negatron_cloak'], 'blue_buff': ['tear_of_the_goddess', 'tear_of_the_goddess'], 'bramble_vest': ['chain_vest', 'chain_vest'], - 'chalice_of_power': ['tear_of_the_goddess', 'negatron_cloak'], + 'adaptive_helm': ['tear_of_the_goddess', 'negatron_cloak'], 'deathblade': ['bf_sword', 'bf_sword'], 'dragons_claw': ['negatron_cloak', 'negatron_cloak'], - 'duelists_zeal': ['recurve_bow', 'spatula'], - 'elderwood_heirloom': ['negatron_cloak', 'spatula'], - 'force_of_nature': ['spatula', 'spatula'], - 'frozen_heart': ['tear_of_the_goddess', 'chain_vest'], + 'protectors_vow': ['tear_of_the_goddess', 'chain_vest'], 'gargoyle_stoneplate': ['chain_vest', 'negatron_cloak'], 'giant_slayer': ['bf_sword', 'recurve_bow'], - 'guardian_angel': ['bf_sword', 'chain_vest'], + 'edge_of_night': ['bf_sword', 'chain_vest'], 'guinsoos_rageblade': ['recurve_bow', 'needlessly_large_rod'], 'hand_of_justice': ['tear_of_the_goddess', 'sparring_gloves'], 'hextech_gunblade': ['bf_sword', 'needlessly_large_rod'], @@ -103,139 +307,315 @@ 'ionic_spark': ['needlessly_large_rod', 'negatron_cloak'], 'jeweled_gauntlet': ['needlessly_large_rod', 'sparring_gloves'], 'last_whisper': ['recurve_bow', 'sparring_gloves'], - 'locket_of_the_iron_solari': ['needlessly_large_rod', 'chain_vest'], - 'ludens_echo': ['needlessly_large_rod', 'tear_of_the_goddess'], - 'mages_cap': ['tear_of_the_goddess', 'spatula'], - 'mantle_of_dusk': ['needlessly_large_rod', 'spatula'], + 'crownguard': ['needlessly_large_rod', 'chain_vest'], + 'archangels_staff': ['needlessly_large_rod', 'tear_of_the_goddess'], 'morellonomicon': ['needlessly_large_rod', 'giants_belt'], 'quicksilver': ['negatron_cloak', 'sparring_gloves'], 'rabadons_deathcap': ['needlessly_large_rod', 'needlessly_large_rod'], - 'rapid_firecannon': ['recurve_bow', 'recurve_bow'], + 'red_buff': ['recurve_bow', 'recurve_bow'], 'redemption': ['tear_of_the_goddess', 'giants_belt'], 'runaans_hurricane': ['recurve_bow', 'negatron_cloak'], - 'shroud_of_stillness': ['chain_vest', 'sparring_gloves'], + 'steadfast_heart': ['chain_vest', 'sparring_gloves'], 'spear_of_shojin': ['bf_sword', 'tear_of_the_goddess'], 'statikk_shiv': ['recurve_bow', 'tear_of_the_goddess'], 'sunfire_cape': ['chain_vest', 'giants_belt'], - 'sword_of_the_divine': ['bf_sword', 'spatula'], 'thieves_gloves': ['sparring_gloves', 'sparring_gloves'], 'titans_resolve': ['chain_vest', 'recurve_bow'], - 'trap_claw': ['giants_belt', 'sparring_gloves'], - 'vanguards_cuirass': ['chain_vest', 'spatula'], - 'warlords_banner': ['giants_belt', 'spatula'], + 'guardbreaker': ['giants_belt', 'sparring_gloves'], 'warmogs_armor': ['giants_belt', 'giants_belt'], - 'youmuus_ghostblade': ['sparring_gloves', 'spatula'], - 'zekes_herald': ['bf_sword', 'giants_belt'], - 'zephyr': ['giants_belt', 'negatron_cloak'], - 'zzrot_portal': ['recurve_bow', 'giants_belt'], + 'steraks_gage': ['bf_sword', 'giants_belt'], + 'evenshroud': ['giants_belt', 'negatron_cloak'], + 'nashors_tooth': ['recurve_bow', 'giants_belt'], + + 'bastion_emblem': ['frying_pan', 'chain_vest'], + 'eldritch_emblem': ['spatuula', 'giant_belt'], + 'faerie_emblem': ['spatula', 'tear_of_the_goddess'], + 'frost_emblem': ['spatula', 'chain_vest'], + 'honeymancer_emblem': ['spatula', 'sparring_gloves'], + 'hunter_emblem': ['frying_pan', 'BF_sword'], + 'mage_emblem': ['frying_pan', 'needlessly_large_rod'], + 'multistriker_emblem': ['frying_pan', 'recurve_bow'], + 'portal_emblem': ['spatula', 'needlessly_large_rod'], + 'preserver_emblem': ['frying_pan', 'negatron_cloak'], + 'pyro_emblem': ['spatula', 'recurve_bow'], + 'scholar_emblem': ['frying_pan', 'tear_of_the_goddess'], + 'shapeshifter_emblem': ['frying_pan', 'giant_belt'], + 'sugarcraft_emblem': ['spatula', 'BF_sword'], + 'warrior_emblem': ['frying_pan', 'sparring_gloves'], + 'witchcraft_emblem': ['spatula', 'negatron_cloak'], + + 'tacticians_crown': ['spatula', 'spatula'], + 'tacticians_cape': ['spatula', 'frying_pan'], + 'tacticians_shield': ['frying_pan', 'frying_pan'], } trait_items = { - 'duelist': 'duelists_zeal', - 'elderwood': 'elderwood_heirloom', - 'mage': 'mages_cap', - 'dusk': 'mantle_of_dusk', - 'divine': 'sword_of_the_divine', - 'vanguard': 'vanguards_cuirass', - 'warlord': 'warlords_banner', - 'assassin': 'youmuus_ghostblade', + 'arcane': 'arcane_emblem', + 'bastion': 'bastion_emblem', + 'blaster': 'blaster_emblem', + 'chrono': 'chrono_emblem', + 'eldritch': 'eldritch_emblem', + 'faerie': 'faerie_emblem', + 'frost': 'frost_emblem', + 'honeymancer': 'honeymancer_emblem', + 'hunter': 'hunter_emblem', + 'mage': 'mage_emblem', + 'multistriker': 'multistriker_emblem', + 'portal': 'portal_emblem', + 'preserver': 'preserver_emblem', + 'pyro': 'pyro_emblem', + 'scholar': 'scholar_emblem', + 'shapeshifter': 'shapeshifter_emblem', + 'sugarcraft': 'sugarcraft_emblem', + 'vanguard': 'vanguard_emblem', + 'warrior': 'warrior_emblem', + 'witchcraft': 'witchcraft_emblem', } SP = { - 'chalice_of_power': 0.35, - 'hand_of_justice': 0.45, + 'crownguard': 0.35, + 'royal_crownshield': 0.50, + 'chalice_of_power': 0.25, + 'hand_of_justice': 0.15, + 'fist_of_fairness': 0.50, + 'obsidian_cleaver': 0.08, + 'spite': 0.20, + 'adaptive_helm': 0.15, + 'jaksho_the_protean': 0.40, + 'archangels_staff': 0.30, + 'urf-angels-staff': 0.40, } AD = { - 'deathblade': 20, + 'steraks_gage': 35, + 'steraks_megashield': 60, + 'hand_of_justice': 15, + 'fist_of_fairness': 50, + 'obisidian_cleaver': 8, + 'spite': 15, +} + +item_as_decrease = { + 'eternal_winter': 0.20, +} + +item_as_increase = { + 'guinsoos_rageblade': 1.05, + 'guinsoos_reckoning': 1.10, + 'nashors_tooth': 1.60, + 'the_barons_gift': 1.20, + 'zekes_herald': 1.35, + 'edge_of_night': 1.15, + 'brink_of_dawn': 1.85, + 'quick_silver': 1.04, + 'quickesilver': 1.09, + 'aeigis_of_the_legion': 1.25, + 'banshees_veil': 1.25, + 'zephyr': 1.08, + 'gamblers_blade': [1.01], #TODO determine how to handle the incremental increase either in the ability or through just a static array with each gold accumulation } -AD_percentage = { - 'hand_of_justice': 1.45, +AMP = { + 'guardbreaker': 0.25, + 'willbreaker': 0.50, + 'giant_slayer': 0.25, + 'demon_slayer': 0.50, + 'needlessly_big_gem': [0.05], #TODO determine how to handle the incremental increase either in the ability or through just a static array with each second accumulation + 'the_eternal_flame': 0.08, + 'deathfire_grasp': [0.25, 0.35], # based on target + 'snipers_focus': 0.09, # stacks by range + 'talisman_of_ascension': 1.20, } crit_chance = { - 'infinity_edge': 0.55 +} + +crit_dmg = { + 'infinity_edge': 1.10, + 'zenith_edge': 1.10, + 'jeweled_gauntlet': 1.10, + 'glamourous_gauntlet': 1.10, + 'prowlers_claw': 1.60, } damage = { - 'bramble_vest': [0, 80, 100, 150], - 'ionic_spark': 2.25, # % of max mana - 'ludens_echo': 180, + 'bramble_vest': 100, + 'rosethorn_vest': 175, + 'ionic_spark': 1.60, # % of max mana + 'coverlent_spark': 2.00, # % of max mana 'statikk_shiv': 80, - 'runaans_hurricane': 0.90 + 'runaans_hurricane': 0.55, # % of AD + 'runaans_tempest': 1.10, # % of AD + 'deathfire_grasp': 0.20, # % of max health + 'horizon_focus': 0.30, # % of max health + 'lich_bane': [200, 480], #TODO determine stage damage + 'ludens_tempest': 100, # + 100% of overkill damage + 'unending_despair': 1.25, # % of shield value + 'wits_end': [42, 100], #TODO determine stage damage } true_damage = {'statikk_shiv': 240} armor = { - 'gargoyle_stoneplate': 15, - 'titans_resolve': 25, + 'gargoyle_stoneplate': 10, # per enemy targeting holder + 'dvapala_stoneplate': 15, # per enemy targeting holder + 'protecters_vow': 20, + 'bulwarks_oath': 60, + 'titans_resolve': 20, + 'titans_vow': 50, + 'adaptive_helm': 40, + 'jaksho_the_protean': 60, + 'evenshroud': 25, + 'eqinox': 70, + 'aeigis_of_the_legion': 15, + 'locket_of_the_iron_solari': 20, + 'randuins_omen': 30, } MR = { - 'gargoyle_stoneplate': 15, - 'titans_resolve': 25, + 'gargoyle_stoneplate': 10, # per enemy targeting holder + 'dvarapala_stoneplate': 15, # per enemy targeting holder + 'protecters_vow': 20, + 'bulwarks_oath': 60, + 'titans_resolve': 20, + 'titan_vow': 50, + 'adaptive_helm': 40, + 'jaksho_the_protean': 60, + 'evenshroud': 25, + 'eqinox': 70, + 'aeigis_of_the_legion': 15, + 'locket_of_the_iron_solari': 20, + 'randuins_omen': 30, } -item_mr_decrease = {'ionic_spark': 0.60} # inverted -item_armor_decrease = {'last_whisper': 0.25} # inverted +durability = { + 'steadfast_heart': [0.08, 0.15], # based on health % + 'legacy_of_the_colossus': [0.16, 0.30], # based on health % + 'redemption': 0.10, + 'absolution': 0.10, +} + +item_mr_decrease = { + 'ionic_spark': 0.70, + 'covlent_spark': 0.70, + 'statikk_shiv': 0.70, +} # inverted + +item_armor_decrease = { + 'last_whisper': 0.70, + 'eternal_whisper': 0.70, + 'even_shroud': 0.70, + 'equinox': 0.70, +} # inverted + +#TODO standardize stack based stats across stats, given the number of items that have them now item_deal_increased_damage_increase = {'titans_resolve': 0.02} heal = { - 'guardian_angel': 400, - 'redemption': 800, } heal_percentage = { - 'hextech_gunblade': 0.33 + 'hextech_gunblade': 0.20, # % of dmg + 'hextech_lifeblade': 0.35, # % of dmg + 'redemption': 0.15, # % of max health + 'absolution': 0.25, # % of max health + 'virtue_of_the_martyr': [0.07, 0.14], # % of max health, depends on holder alive status + 'animas_visage': 0.025, # % of max health + 'corrput_vampiric_scepter': 0.60, # % of extra AD + 'innervating_locket': 0.20, # % of max health, might need to be changed to 6.67% of max health to account for heal over 3 seconds + 'brink_of_dawn': 1.00, # % of missing health + 'covanent_spark': 0.015, # % of max health + 'dragons_will': 0.10, # % of max health + 'wits_end': 0.35, # % of magic damage + 'warmogs_pride': 0.015, # % of max health } shield = { - 'locket_of_the_iron_solari': [0, 300, 375, 500, 800], + 'locket_of_the_iron_solari': 250, + 'bloodthirster': 0.25, # % of max health + 'bleesed_bloodthirster': 0.40, # % of max health + 'crownguard': 0.25, # % of max health + 'royal_crownshield': 0.50, # % of max health + 'protectors_vow': 0.25, # % of max health + 'moonstone_renewer': [55, 325], # TODO need to get each stage shield ammount (55 and 325 are the min and max respectively) + 'lightshield_crest': 0.50, # 50% armor + 50% MR } shield_max = { - 'hextech_gunblade': 400 -} - -item_as_decrease = { - 'frozen_heart': 0.5, } -item_as_increase = { - 'guinsoos_rageblade': 1.06, - 'zekes_herald': 1.35 +max_health = { + 'bramble_vest': 0.05, # % increase + 'rosethorn_vest': 0.15, # % increase + 'steraks_gage': 0.25, # % increase + 'steraks_megashield': 0.40, # % increase + 'dragons_claw': 0.09, # % increase + 'dragons_will': 0.15, # % increase + 'warmogs_armor': 0.12, # % increase + 'knights_vow': 200, + 'shrond_of_stillness': 60, + 'forbidden_idol': 0.50, # % of shield + 'hullcrusher': 600, + 'talisman_of_ascension': 1.00, # % increase + 'warmogs_pride': 0.20, # % increase } lifesteal = { - 'hand_of_justice': 0.45, + 'hand_of_justice': 0.15, } lifesteal_spells = { 'hand_of_justice': 0.45, } -item_mana_cost_increase = {'shroud_of_stillness': 0.33} -mana = {'spear_of_shojin': 5} +item_mana_cost_increase = {'shroud_of_stillness': 0.30} + +mana = { + 'chalice_of_power': 10, + 'spear_of_shojin': 5, + 'spear_of_hirana': 10, + 'adaptive_helm': [1, 10], # depends on start position + 'jaksho_the_protean': [2, 20], # depends on start position + 'innervating_locket': 0.02, # % of max mana + 'mana_zane': 120, # may need to be changed to 24 mana over 5 seconds +} + +mana_reduction = { + 'blue_buff': 10, + 'blue_blessing': 10, +} item_stun_duration = { - 'trap_claw': 4000, 'zephyr': 5000, + 'spite': 2000, + 'eternal_winter': 1500, + 'silvermere_dawn': 800, } item_range = { 'ionic_spark': 2, - 'ludens_echo': 2, - 'sunfire_cape': 2 + 'covlent_spark': 3, + 'sunfire_cape': 2, + 'redemption': 2, + 'absolution': 2, + 'spite': 2, + 'evenshroud': 2, + 'equinox': 3, } item_targets = { - 'ludens_echo': 3, # target + 3 - 'statikk_shiv': [0, 2, 3, 4, 8] # target + x + 'statikk_shiv': 4, + 'statikk_favor': 8, + 'runaans_hurricane': 1, + 'runaans_tempest': 1, + 'ludens_tempest': 3, } -item_max_stacks = {'titans_resolve': 25} +item_max_stacks = { + 'titans_resolve': 25, + 'titan_vow': 25, + 'moguls_mail': 35, +} item_change_length = { 'last_whisper': 3000, @@ -245,25 +625,36 @@ } cooldown = { - 'bramble_vest': 2500, - 'guardian_angel': 2000, + 'bramble_vest': 2000, + 'rosethorn_vest': 2000, 'sunfire_cape': 2000, + 'redemption': 5000, + 'absolution': 5000, + 'eternal_winter': 15000, + 'covalent_spark': 1000, #heal cooldown + 'dragons_will': 2000, #heal cooldown + 'archangels_staff': 5000, + 'urfs_angels_staff': 4000, + 'warmogs_pride': 1500, + 'adaptive_helm': 3000, + 'jaksho_the_protean': 3000, + 'moonstone_renewer': 4000, + 'the_eternal_flame': 5000, + 'virtue_of_the_martyr': 5000, + 'animas_visage': 1000, + 'lightshield_crest': 3000, } -item_activate_every_x_attacks = {'statikk_shiv': 3} +item_activate_every_x_attacks = { + 'statikk_shiv': 3, + 'statikk_favor': 3, +} +#TODO determine what items need this interaction initiative_items = [ 'rapid_firecannon', 'sunfire_cape', 'thieves_gloves', - 'duelists_zeal', - 'elderwood_heirloom', - 'mages_cap', - 'mantle_of_dusk', - 'sword_of_the_divine', - 'vanguards_cuirass', - 'warlords_banner', - 'youmuus_ghostblade' ] # these items will call their items.py -function from items.initiate() thieves_gloves_items = [ @@ -273,10 +664,10 @@ 'chalice_of_power', 'deathblade', 'dragons_claw', - 'frozen_heart', + 'protectors_vow', 'gargoyle_stoneplate', 'giant_slayer', - 'guardian_angel', + 'edge_of_night', 'guinsoos_rageblade', 'hand_of_justice', 'hextech_gunblade', @@ -284,21 +675,80 @@ 'ionic_spark', 'jeweled_gauntlet', 'last_whisper', - 'locket_of_the_iron_solari', - 'ludens_echo', + 'crownguard', + 'archangels_staff', 'morellonomicon', 'quicksilver', 'rabadons_deathcap', - 'rapid_firecannon', + 'red_buff', 'redemption', 'runaans_hurricane', - 'shroud_of_stillness', + 'steadfast_heart', 'spear_of_shojin', 'statikk_shiv', 'sunfire_cape', 'titans_resolve', - 'trap_claw', + 'guardbreaker', 'warmogs_armor', + 'steraks_gage', + 'evenshroud', + 'nashors_tooth', +] + +rascals_gloves_items = [ + 'absolution', + 'blessed_bloodthirster', + 'blue_blessing', + 'brink_of_dawn', + 'bulwarks_oath', + 'covalent_spark', + 'crest_of_cinders', + 'demonslayer', + 'dragons_will', + 'dvarapala_stoneplate', + 'equinox', + 'eternal_whisper', + 'fist_of_fairness', + 'glamourous_gauntlet', + 'guinsoos_reckoning', + 'hextech_lifeblade', + 'jaksho_the_protean', + 'legacy_of_the_colossus', + 'luminous_deathblade', + 'more_more-ellonomicon', + 'quickestsilver', + 'rabadons_ascended_deathcap', + 'rascals_gloves', + 'rosethrorn_vest', + 'royal_crownshield', + 'runaans_tempest', + 'spear_of_hirana', + 'statikk_favor', + 'steraks_megashield', + 'sunlight_cape', + 'the_barons_gift', + 'titans_vow', + 'urf-angels-staff', + 'warmogs_pride', + 'willbreaker', + 'zenith_edge' +] + +accomplishes_gloves_items = [ + 'aegis_of_the_legion', + 'banshees_veil', + 'chalice_of_power', + 'knights_vow', + 'locket_of_the_iron_solari', + 'moonstone_renewer', + 'needlessly_big_gem', + 'obsidian_cleaver', + 'randuins_omen', + 'shroud_of_stillness', + 'spite', + 'the_eternal_flame', + 'unstable_treasure_chest', + 'virtue_of_the_martyr', 'zekes_herald', 'zephyr', 'zzrot_portal', diff --git a/Set12Simulator/items.py b/Set12Simulator/items.py index 63dabb9..a7fb1d2 100755 --- a/Set12Simulator/items.py +++ b/Set12Simulator/items.py @@ -50,7 +50,6 @@ def initiate(champion): # where item functions are based at - def blue_buff(champion): if('blue_buff' in champion.items): change_stat(champion, 'mana', 20) @@ -74,22 +73,8 @@ def bramble_vest(champion): champion.spell(n, item_stats.damage['bramble_vest'][champion.stars], 0, True) -def chalice_of_power(champion): - units = champion.own_team() + champion.enemy_team() - holders = list(filter(lambda x: 'chalice_of_power' in x.items, units)) - - coords = field.coordinates - for holder in holders: - item_amount = len(list(filter(lambda x: x == 'chalice_of_power', holder.items))) - - hexes = [] - if(holder.x >= 1): hexes.append(coords[holder.y][holder.x - 1]) - hexes.append(coords[holder.y][holder.x]) - if(holder.x <= 5): hexes.append(coords[holder.y][holder.x + 1]) - - for h in hexes: - if(h and h.team == champion.team and h.champion): - change_stat(h, 'SP', h.SP + item_stats.SP['chalice_of_power'] * item_amount) +def adaptive_helm(champion): + return #adding stack whenever dealing damage to a target @@ -108,61 +93,11 @@ def deathblade(champion, target): if([champion, target] not in deathblade_list): deathblade_list.append([champion, target]) +def edge_of_night(champion): + return -frozen_heart_list = [] -def frozen_heart(champion): - units = champion.own_team() + champion.enemy_team() - - #if a unit has died and they had some enemies affected, clear those debuffs - for i in range(0, 5): - for u in frozen_heart_list: - if(u[0] not in units): - for c in u[1]: - change_stat(c, 'AS', c.AS / item_stats.item_as_decrease['frozen_heart']) - frozen_heart_list.remove(u) - - has_item = list(filter(lambda x: 'frozen_heart' in x.items, units)) - - #loop through every unit with the item - for c in has_item: - items = 0 - for i in c.items: - if(i == 'frozen_heart'): items += 1 - - c_in_list = list(filter(lambda x: x[0] == c, frozen_heart_list)) - units_in_c_list = [] - new_c_list = [] - - #current affected list by this holder - if(len(c_in_list) > 0): - c_in_list = c_in_list[0] - units_in_c_list = c_in_list[1] - - #if current neighbors are not on the list, debuff - #if they are on the list, keep them on it - current_neighbors = field.enemies_in_distance(c, c.y, c.x, items) - for n in current_neighbors: - if(n not in units_in_c_list): - change_stat(n, 'AS', n.AS * item_stats.item_as_decrease['frozen_heart']) - if(n not in new_c_list): - new_c_list.append(n) - - #if there are some units on the list that aren't neighbors, clear debuff - #otherwise keep the neighbor in the list - for u in units_in_c_list: - if(u not in current_neighbors): - change_stat(u, 'AS', u.AS / item_stats.item_as_decrease['frozen_heart']) - elif(n not in new_c_list): new_c_list.append(u) - - #if there are no entries of this unit's list, append one - if(len(c_in_list) == 0): - frozen_heart_list.append([c, new_c_list]) - #otherwise just replace the list of affected enemy units - else: - for u in frozen_heart_list: - if(u[0] == c): - u[1] = new_c_list - break +def protectors_vow(champion): + return gargoyle_stoneplate_list = [] @@ -351,60 +286,12 @@ def last_whisper(champion, target): target.add_que('change_stat', length, None, 'armor', None, {'vi': item_stats.item_armor_decrease['last_whisper']}) last_whisper_list.append([target, millis]) -def locket_of_the_iron_solari(champion): - units = champion.own_team() + champion.enemy_team() - holders = list(filter(lambda x: 'locket_of_the_iron_solari' in x.items, units)) - - coords = field.coordinates - for holder in holders: - item_amount = len(list(filter(lambda x: x == 'locket_of_the_iron_solari', holder.items))) - - - hexes = [] - if(holder.x >= 2): hexes.append(coords[holder.y][holder.x - 2]) - if(holder.x >= 1): hexes.append(coords[holder.y][holder.x - 1]) - hexes.append(coords[holder.y][holder.x]) - if(holder.x <= 5): hexes.append(coords[holder.y][holder.x + 1]) - if(holder.x <= 4): hexes.append(coords[holder.y][holder.x + 2]) - - for h in hexes: - if(h and h.team == holder.team and h.champion): - shield_size = item_stats.shield['locket_of_the_iron_solari'][holder.stars] * item_amount - - shield_identifier = round(champion_functions.MILLIS() * shield_size + holder.armor) - shield_length = item_stats.item_change_length['locket_of_the_iron_solari'] - h.add_que('shield', -1, None, None, {'amount': shield_size, 'identifier': shield_identifier, 'applier': holder, 'original_amount': shield_size}, {'increase': True, 'expires': shield_length}) +def crownguard(champion): + return -def ludens_echo(champion, target): - - if 'ludens_echo' in champion.items: - item_amount = len(list(filter(lambda x: x == 'ludens_echo', champion.items))) - - # change the flag - champion.spell_has_used_ludens = True - - # find the enemies in range and sort out the proper amount. always include the target - enemies_in_range = field.enemies_in_distance(champion, target.y, target.x, item_stats.item_range['ludens_echo']) - if target in enemies_in_range: - enemies_in_range.remove(target) - - target_amount = item_stats.item_targets['ludens_echo'] - if len(enemies_in_range) > target_amount: - enemies_in_range = enemies_in_range[:target_amount] - - targets = [target] - targets += enemies_in_range - - champion.print(' luden\'s echo hits {} target{}'.format(len(targets), 's' if (len(targets) > 1) else '')) - for t in targets: - damage = item_stats.damage['ludens_echo'] - if (t.stunned or t.disarmed or t.blinded or t.AD_reduction_cc) and not t.name == 'sandguard': - damage *= 2 - - damage *= item_amount - champion.spell(t, damage, 0, True) - +def archangels_staff(champion, target): + return def morellonomicon(champion, target): @@ -412,9 +299,8 @@ def morellonomicon(champion, target): champion.burn(target) -def rapid_firecannon(champion): - change_stat(champion, 'range', champion.range + stats.RANGE[champion.name] * 2) - +def red_buff(champion): + return def redemption(champion): if('redemption' in champion.items): @@ -445,56 +331,8 @@ def runaans_hurricane(champion, target): #hexagonal coordinates are fun and all -def shroud_of_stillness(champion): - units = champion.own_team() + champion.enemy_team() - holders = list(filter(lambda x: 'locket_of_the_iron_solari' in x.items, units)) - - for holder in holders: - affect_odd_x = [] - affect_even_x = [] - - #find which hexes will be affected by the shroud - #depends on champion's position - if(champion.y % 2 == 0): - affect_odd_x.append(champion.x) - if(champion.x <= 5): affect_odd_x.append(champion.x + 1) - - if(champion.x >= 1): affect_even_x.append(champion.x - 1) - affect_even_x.append(champion.x) - if(champion.x <= 5): affect_even_x.append(champion.x + 1) - - if(champion.y % 2 == 1): - affect_even_x.append(champion.x) - if(champion.x >= 1): affect_even_x.append(champion.x - 1) - - if(champion.x >= 1): affect_odd_x.append(champion.x - 1) - affect_odd_x.append(champion.x) - if(champion.x <= 5): affect_odd_x.append(champion.x + 1) - - - affected_hexes = [] - for i in range(0, 8): - if(i % 2 == 0): - for j in affect_even_x: - affected_hexes.append([i, j]) - - if(i % 2 == 1): - for j in affect_odd_x: - affected_hexes.append([i, j]) - - - coords = field.coordinates - for h in affected_hexes: - c = coords[h[0]][h[1]] - if(c and c.team != champion.team and c.champion): - - #increase next spell mana cost of every enemy in the line by x% = reduce mana by x% of maxmana (can go negative) - if(not c.mana_cost_increased and c.maxmana > 0): - mana_reduce_amount = c.maxmana * item_stats.item_mana_cost_increase['shroud_of_stillness'] - start_value = c.mana - c.mana -= mana_reduce_amount - c.print(' {} {} --> {}'.format('mana', round(start_value,1), round(c.mana,1))) - c.add_que('change_stat', -1, None, 'mana_cost_increased', True) +def steadfast_heart(champion): + return @@ -610,146 +448,330 @@ def titans_resolve_helper(unit): # see item notes -def trap_claw(champion, target): +def guardbreaker(champion, target): + return - target.items.remove('trap_claw') - change_stat(champion, 'stunned', True) - champion.add_que('change_stat', item_stats.item_stun_duration['trap_claw'], None, 'stunned', False) +def steraks_gage(champion): + return - if not target.stunned: - target.add_que('change_stat', 1, None, 'stunned', False) - if not target.disarmed: - target.add_que('change_stat', 1, None, 'disarmed', False) - if not target.blinded: - target.add_que('change_stat', 1, None, 'blinded', False) +def evenshroud(champion): + return +def nashors_tooth(champion): + return -def zekes_herald(champion): - units = champion.own_team() + champion.enemy_team() - holders = list(filter(lambda x: 'zekes_herald' in x.items, units)) - - coords = field.coordinates - for holder in holders: - item_amount = len(list(filter(lambda x: x == 'zekes_herald', holder.items))) - - hexes = [] - if holder.x >= 1: - hexes.append(coords[holder.y][holder.x - 1]) - hexes.append(coords[holder.y][holder.x]) - if holder.x <= 5: - hexes.append(coords[holder.y][holder.x + 1]) - - for h in hexes: - if h and h.team == champion.team and h.champion: +def absolution(champion): + return - change_stat(h, 'AS', h.AS * ((item_stats.item_as_increase['zekes_herald'] - 1) * item_amount + 1)) +def blessed_bloodthirster(champion): + return +def blue_blessing(champion): + return -def zephyr(champion): - units = champion.own_team() + champion.enemy_team() - holders = list(filter(lambda x: 'zephyr' in x.items, units)) +def brink_of_dawn(champion): + return + +def bulwarks_oath(champion): + return + +def covalent_spark(champion): + return + +def crest_of_cinders(champion): + return + +def demonslayer(champion): + return + +def dragons_will(champion): + return + +def dvarapala_stoneplate(champion): + return + +def equinox(champion): + return + +def eternal_whisper(champion): + return + +def fist_of_fairness(champion): + return + +def glamourous_gauntlet(champion): + return + +def guinsoos_reckoning(champion): + return + +def hextech_lifeblade(champion): + return + +def jaksho_the_protean(champion): + return + +def legacy_of_the_colossus(champion): + return + +def luminous_deathblade(champion): + return + +def more_more_ellonomicon(champion): + return + +def quickestsilver(champion): + return + +def rabadons_ascended_deathcap(champion): + return - coords = field.coordinates - for holder in holders: - item_amount = len(list(filter(lambda x: x == 'zephyr', holder.items))) +def rascals_gloves(champion): + return - # targeted hex - target_coords = [7 - holder.y, 6 - holder.x] - targets = list(filter(lambda x: x.champion, holder.enemy_team())) - targets = sorted(targets, key=lambda x: field.distance({'y': x.y, 'x': x.x}, {'y': target_coords[0], 'x': target_coords[1]}, False)) - targets = targets[:item_amount] - for t in targets: - c = coords[t.y][t.x] - if c and c.team != holder.team and c.champion: - c.print(' targeted by zephyr') - change_stat(c, 'stunned', True) - change_stat(c, 'champion', False) +def rosethrorn_vest(champion): + return - length = item_stats.item_stun_duration['zephyr'] - c.add_que('change_stat', length, None, 'stunned', False) - c.add_que('change_stat', length, None, 'champion', True) +def royal_crownshield(champion): + return +def runaans_tempest(champion): + return + +def spear_of_hirana(champion): + return + +def statikk_favor(champion): + return + +def steraks_megashield(champion): + return + +def sunlight_cape(champion): + return + +def the_barons_gift(champion): + return + +def titans_vow(champion): + return + +def urf_angels_staff(champion): + return + +def warmogs_pride(champion): + return + +def willbreaker(champion): + return + +def zenith_edge(champion): + return + +def accomplices_glove(champion): + return + +def aegis_of_the_legion(champion): + return + +def banshees_veil(champion): + return + +def chalice_of_power(champion): + return + +def knights_vow(champion): + return + +def locket_of_the_iron_solari(champion): + return + +def moonstone_renewer(champion): + return + +def needlessly_big_gem(champion): + return + +def obsidian_cleaver(champion): + return + +def randuins_omen(champion): + return + +def shroud_of_stillness(champion): + return + +def spite(champion): + return + +def the_eternal_flame(champion): + return + +def unstable_treasure_chest(champion): + return + +def virtue_of_the_martyr(champion): + return + +def zekes_herald(champion): + return + +def zephyr(champion): + return def zzrot_portal(champion): - units = champion.own_team() + champion.enemy_team() - holders = list(filter(lambda x: 'zzrot_portal' in x.items, units)) - for holder in holders: + return + +def anima_visage(champion): + return + +def blacksmiths_gloves(champion): + return + +def blighting_jewel(champion): + return + +def corrupt_vampiric_scepter(champion): + return + +def deaths_defiance(champion): + return + +def deathfire_grasp(champion): + return + +def eternal_winter(champion): + return + +def fishbones(champion): + return + +def forbidden_idol(champion): + return + +def gamblers_blade(champion): + return + +def gold_collector(champion): + return + +def horizon_focus(champion): + return + +def hullcrusher(champion): + return + +def infinity_force(champion): + return + +def innervating_locket(champion): + return + +def lich_bane(champion): + return + +def lightshield_crest(champion): + return + +def ludens_tempest(champion): + return + +def manazane(champion): + return + +def mittens(champion): + return + +def moguls_mail(champion): + return + +def prowlers_claw(champion): + return + +def rapid_firecannon(champion): + return + +def seekers_armguard(champion): + return + +def silvermere_dawn(champion): + return + +def snipers_focues(champion): + return + +def spectral_cutlass(champion): + return - # taunting - neighbor_enemies = field.enemies_in_distance(champion, champion.y, champion.x, 1) - for n in neighbor_enemies: - old_target = n.target - n.add_que('change_target', -1, None, None, champion) - n.add_que('change_target', item_stats.item_change_length['zzrot_portal'], None, None, old_target) +def talisman_of_ascension(champion): + return +def tricksters_glass(champion): + return -# summon the blobs -def zzrot_portal_helper(champion): +def unending_despair(champion): + return - item_amount = len(list(filter(lambda x: x == 'zzrot_portal', champion.items))) - spawn_hexes = field.hexes_in_distance(champion.y, champion.x, 3) +def wits_end(champion): + return - coords = field.coordinates +def zhonyas_paradox(champion): + return - for i, s in enumerate(spawn_hexes): - d = field.distance({'y': s[0], 'x': s[1]}, {'y': champion.y, 'x': champion.x}, False) - spawn_hexes[i].append(d) - random.shuffle(spawn_hexes) - spawn_hexes = sorted(spawn_hexes, key=lambda x: x[2]) +def sugarcraft_emblem(champion): + return - # find us a list of free hexes - spawn_hexes = list(filter(lambda x: not coords[x[0]][x[1]], spawn_hexes)) - spawn_hexes = spawn_hexes[:item_amount] +def frost_emblem(champion): + return - for s in spawn_hexes: - champion.print(' zzrot_portal spawns a construct at {}'.format([s[0], s[1]])) - champion.spawn('construct', champion.stars, s[0], s[1]) +def eldritch_emblem(champion): + return +def portal_emblem(champion): + return -def duelists_zeal(champion): - if champion.team: - origin_class.amounts['duelist'][champion.team] += \ - len(list(filter(lambda x: x == 'duelists_zeal', champion.items))) +def witchcraft_emblem(champion): + return +def pyro_emblem(champion): + return -def elderwood_heirloom(champion): - if champion.team: - origin_class.amounts['elderwood'][champion.team] += \ - len(list(filter(lambda x: x == 'elderwood_heirloom', champion.items))) +def honeymancy_emblem(champion): + return +def faerie_emblem(champion): + return -def mages_cap(champion): - if champion.team: - origin_class.amounts['mage'][champion.team] += \ - len(list(filter(lambda x: x == 'mages_cap', champion.items))) +def hunter_emblem(champion): + return +def bastion_emblem(champion): + return -def mantle_of_dusk(champion): - if champion.team: - origin_class.amounts['dusk'][champion.team] += \ - len(list(filter(lambda x: x == 'mantle_of_dusk', champion.items))) +def shapeshifter_emblem(champion): + return +def mage_emblem(champion): + return -def sword_of_the_divine(champion): - if champion.team: - origin_class.amounts['divine'][champion.team] +=\ - len(list(filter(lambda x: x == 'sword_of_the_divine', champion.items))) +def preserver_emblem(champion): + return +def multistriker_emblem(champion): + return -def vanguards_cuirass(champion): - if champion.team: - origin_class.amounts['vanguard'][champion.team] += \ - len(list(filter(lambda x: x == 'vanguards_cuirass', champion.items))) +def warrior_emblem(champion): + return +def scholar_emblem(champion): + return -def warlords_banner(champion): - if champion.team: - origin_class.amounts['warlord'][champion.team] += \ - len(list(filter(lambda x: x == 'warlords_banner', champion.items))) +def tacticians_crown(champion): + return +def tacticians_cape(champion): + return -def youmuus_ghostblade(champion): - if champion.team: - origin_class.amounts['assassin'][champion.team] += \ - len(list(filter(lambda x: x == 'youmuus_ghostblade', champion.items))) +def tacticians_shield(champion): + return \ No newline at end of file diff --git a/Set12Simulator/stats.py b/Set12Simulator/stats.py index 736ad50..6914cc8 100755 --- a/Set12Simulator/stats.py +++ b/Set12Simulator/stats.py @@ -1,66 +1,64 @@ AD = { - 'aatrox': 60, - 'ahri': 40, + 'ahri': 35, 'akali': 55, - 'annie': 45, - 'aphelios': 50, - 'ashe': 80, - 'azir': 70, - 'cassiopeia': 55, - 'diana': 50, - 'elise': 45, - 'evelynn': 70, - 'ezreal': 80, - 'fiora': 45, - 'garen': 50, - 'hecarim': 55, - 'irelia': 55, - 'janna': 40, - 'jarvaniv': 60, - 'jax': 60, - 'jhin': 100, - 'jinx': 75, - 'kalista': 65, - 'katarina': 65, - 'kayn': 80, - 'kennen': 60, - 'kindred': 70, - 'leesin': 60, - 'lillia': 40, - 'lissandra': 40, - 'lulu': 50, - 'lux': 40, - 'maokai': 55, + 'ashe': 50, + 'bard': 40, + 'blitzcrank': 65, + 'briar': 65, + 'camille': 85, + 'cassiopeia': 35, + 'diana': 60, + 'elise': 50, + 'ezreal': 55, + 'fiora': 75, + 'galio': 55, + 'gwen': 50, + 'hecarim': 60, + 'hwei': 35, + 'jax': 40, + 'jayce': 55, + 'jinx': 50, + 'kalista': 60, + 'karma': 45, + 'kassadin': 45, + 'katarina': 50, + 'kogmaw': 55, + 'lillia': 45, + 'milio': 50, + 'mordekaiser': 60, 'morgana': 50, - 'nami': 40, - 'nidalee': 45, - 'nunu': 65, - 'pyke': 50, - 'riven': 70, - 'sejuani': 45, - 'sett': 60, + 'nami': 45, + 'nasus': 65, + 'neeko': 50, + 'nilah': 50, + 'nomsy': 46, + 'norra_yuumi': 50, + 'nunu': 50, + 'olaf': 75, + 'poppy': 50, + 'rakan': 60, + 'rumble': 50, + 'ryze': 45, + 'seraphine': 25, 'shen': 60, - 'sylas': 70, - 'tahmkench': 85, - 'talon': 90, - 'teemo': 55, - 'thresh': 60, - 'twistedfate': 45, - 'vayne': 40, + 'shyvana': 55, + 'smolder': 80, + 'soraka': 30, + 'swain': 60, + 'syndra': 35, + 'tahm_kench': 70, + 'taric': 60, + 'tristana': 55, + 'twitch': 50, + 'varus': 55, 'veigar': 40, - 'vi': 65, - 'warwick': 85, - 'wukong': 55, - 'xinzhao': 65, - 'yasuo': 50, - 'yone': 80, - 'yuumi': 40, - 'zed': 55, - 'zilean': 45, - - 'construct': 100, - 'galio': [0, 75, 160, 280], - 'sandguard': 0, + 'vex': 50, + 'warwick': 45, + 'wukong': 75, + 'xerath': 50, + 'ziggs': 30, + 'zilean': 35, + 'zoe': 30, 'meleeminion': 20, 'rangedminion': 40, @@ -74,69 +72,66 @@ } AS = { - 'aatrox': 0.65, - 'ahri': 0.75, - 'akali': 0.85, - 'annie': 0.6, - 'aphelios': 0.75, - 'ashe': 0.75, - 'azir': 0.85, - 'cassiopeia': 0.6, - 'diana': 0.65, - 'elise': 0.65, - 'evelynn': 0.7, - 'ezreal': 0.9, - 'fiora': 0.75, - 'garen': 0.6, - 'hecarim': 0.55, - 'irelia': 0.65, - 'janna': 0.6, - 'jarvaniv': 0.6, - 'jax': 0.75, - 'jhin': 0.85, + 'ahri': 0.75, + 'akali': 0.75, + 'ashe': 0.70, + 'bard': 0.75, + 'blitzcrank': 0.55, + 'briar': 0.80, + 'camille': 0.90, + 'cassiopeia': 0.75, + 'diana': 0.85, + 'elise': 0.60, + 'ezreal': 0.75, + 'fiora': 1.00, + 'galio': 0.65, + 'gwen': 0.80, + 'hecarim': 0.75, + 'hwei': 0.75, + 'jax': 0.60, + 'jayce': 0.70, 'jinx': 0.75, - 'kalista': 1.00, - 'katarina': 0.65, - 'kayn': 1.00, - 'kennen': 0.65, - 'kindred': 0.8, - 'leesin': 0.85, - 'lillia': 0.75, - 'lissandra': 0.6, - 'lulu': 0.6, - 'lux': 0.7, - 'maokai': 0.5, - 'morgana': 0.7, - 'nami': 0.65, - 'nidalee': 0.7, - 'nunu': 0.55, - 'pyke': 0.6, - 'riven': 0.75, - 'sejuani': 0.55, - 'sett': 0.75, - 'shen': 0.65, - 'sylas': 0.6, - 'tahmkench': 0.5, - 'talon': 0.8, - 'teemo': 0.7, - 'thresh': 0.55, - 'twistedfate': 0.65, - 'vayne': 0.9, - 'veigar': 0.6, - 'vi': 0.6, - 'warwick': 0.8, - 'wukong': 0.65, - 'xinzhao': 0.8, - 'yasuo': 0.7, - 'yone': 0.95, - 'yuumi': 0.6, - 'zed': 0.75, + 'kalista': 0.75, + 'karma': 0.75, + 'kassadin': 0.75, + 'katarina': 0.75, + 'kogmaw': 0.75, + 'lillia': 0.60, + 'milio': 0.80, + 'mordekaiser': 0.60, + 'morgana': 0.80, + 'nami': 0.80, + 'nasus': 0.65, + 'neeko': 0.65, + 'nilah': 0.80, + 'nomsy': 0.70, + 'norra_yuumi': 0.80, + 'nunu': 0.60, + 'olaf': 0.85, + 'poppy': 0.60, + 'rakan': 0.70, + 'rumble': 0.65, + 'ryze': 0.80, + 'seraphine': 0.70, + 'shen': 0.70, + 'shyvana': 0.65, + 'smolder': 0.85, + 'soraka': 0.70, + 'swain': 0.60, + 'syndra': 0.75, + 'tahm_kench': 0.55, + 'taric': 0.65, + 'tristana': 0.75, + 'twitch': 0.70, + 'varus': 0.75, + 'veigar': 0.75, + 'vex': 0.65, + 'warwick': 0.75, + 'wukong': 0.60, + 'xerath': 0.80, + 'ziggs': 0.70, 'zilean': 0.75, - - 'construct': 0.8, - 'galio': 0.65, - 'aphelios_turret': 0, - 'sandguard': 1, + 'zoe': 0.70, 'meleeminion': 0.8, 'rangedminion': 0.8, @@ -150,68 +145,66 @@ } HEALTH = { - 'aatrox': 800, - 'ahri': 600, - 'akali': 650, - 'annie': 750, - 'aphelios': 500, - 'ashe': 600, - 'azir': 950, - 'cassiopeia': 750, - 'diana': 500, - 'elise': 600, - 'evelynn': 600, - 'ezreal': 750, - 'fiora': 600, - 'garen': 600, - 'hecarim': 750, - 'irelia': 800, - 'janna': 550, - 'jarvaniv': 600, - 'jax': 750, - 'jhin': 600, + 'ahri': 550, + 'akali': 700, + 'ashe': 450, + 'bard': 700, + 'blitzcrank': 650, + 'briar': 1200, + 'camille': 1200, + 'cassiopeia': 600, + 'diana': 1200, + 'elise': 650, + 'ezreal': 700, + 'fiora': 1150, + 'galio': 750, + 'gwen': 1100, + 'hecarim': 850, + 'hwei': 650, + 'jax': 650, + 'jayce': 600, 'jinx': 650, - 'kalista': 550, - 'katarina': 500, - 'kayn': 900, - 'kennen': 650, - 'kindred': 650, - 'leesin': 1000, - 'lillia': 950, - 'lissandra': 550, - 'lulu': 500, - 'lux': 600, - 'maokai': 700, - 'morgana': 750, - 'nami': 550, - 'nidalee': 550, - 'nunu': 750, - 'pyke': 700, - 'riven': 800, - 'sejuani': 850, - 'sett': 1100, - 'shen': 950, - 'sylas': 700, - 'tahmkench': 700, - 'talon': 750, - 'teemo': 500, - 'thresh': 700, - 'twistedfate': 550, - 'vayne': 500, - 'veigar': 600, - 'vi': 700, - 'warwick': 950, - 'wukong': 650, - 'xinzhao': 700, - 'yasuo': 550, - 'yone': 950, - 'yuumi': 600, - 'zed': 650, - 'zilean': 750, - - 'construct': [0, 1500, 2500, 3000, 5000], - 'galio': [0, 800, 1400, 2000], - 'sandguard': 950, + 'kalista': 850, + 'karma': 850, + 'kassadin': 700, + 'katarina': 800, + 'kogmaw': 550, + 'lillia': 650, + 'milio': 900, + 'mordekaiser': 850, + 'morgana': 1100, + 'nami': 850, + 'nasus': 1100, + 'neeko': 900, + 'nilah': 700, + 'nomsy': 500, + 'norra_yuumi': 900, + 'nunu': 800, + 'olaf': 1150, + 'poppy': 650, + 'rakan': 1050, + 'rumble': 800, + 'ryze': 850, + 'seraphine': 500, + 'shen': 850, + 'shyvana': 750, + 'smolder': 1000, + 'soraka': 450, + 'swain': 900, + 'syndra': 550, + 'tahm_kench': 1100, + 'taric': 1100, + 'tristana': 550, + 'twitch': 450, + 'varus': 850, + 'veigar': 650, + 'vex': 850, + 'warwick': 700, + 'wukong': 1000, + 'xerath': 900, + 'ziggs': 450, + 'zilean': 550, + 'zoe': 450, 'meleeminion': 250, 'rangedminion': 150, @@ -225,69 +218,66 @@ } ARMOR = { - 'aatrox': 40, 'ahri': 20, - 'akali': 20, - 'annie': 40, - 'aphelios': 20, - 'ashe': 20, - 'azir': 30, - 'cassiopeia': 30, - 'diana': 30, - 'elise': 30, - 'evelynn': 20, - 'ezreal': 20, - 'fiora': 35, - 'garen':50, - 'hecarim': 45, - 'irelia': 40, - 'janna': 20, - 'jarvaniv': 45, - 'jax': 40, - 'jhin': 20, - 'jinx': 20, - 'kalista': 20, - 'katarina': 20, - 'kayn': 40, - 'kennen': 30, - 'kindred': 20, - 'leesin': 50, - 'lillia': 50, - 'lissandra': 20, - 'lulu': 20, - 'lux': 20, - 'maokai': 35, - 'morgana': 30, - 'nami': 20, - 'nidalee': 30, - 'nunu': 50, - 'pyke': 50, - 'riven': 35, - 'sejuani': 60, - 'sett': 60, - 'shen': 60, - 'sylas': 40, - 'tahmkench': 40, - 'talon': 30, - 'teemo': 20, - 'thresh': 80, - 'twistedfate': 20, - 'vayne': 20, - 'veigar': 20, - 'vi': 40, + 'akali': 45, + 'ashe': 15, + 'bard': 25, + 'blitzcrank': 40, + 'briar': 60, + 'camille': 60, + 'cassiopeia': 20, + 'diana': 60, + 'elise': 40, + 'ezreal': 25, + 'fiora': 55, + 'galio': 45, + 'gwen': 50, + 'hecarim': 50, + 'hwei': 25, + 'jax': 45, + 'jayce': 30, + 'jinx': 25, + 'kalista': 30, + 'karma': 30, + 'kassadin': 45, + 'katarina': 45, + 'kogmaw': 20, + 'lillia': 40, + 'milio': 40, + 'mordekaiser': 50, + 'morgana': 60, + 'nami': 30, + 'nasus': 60, + 'neeko': 45, + 'nilah': 35, + 'nomsy': 15, + 'norra_yuumi': 40, + 'nunu': 45, + 'olaf': 60, + 'poppy': 40, + 'rakan': 60, + 'rumble': 45, + 'ryze': 30, + 'seraphine': 15, + 'shen': 50, + 'shyvana': 45, + 'smolder': 50, + 'soraka': 15, + 'swain': 50, + 'syndra': 20, + 'tahm_kench': 60, + 'taric': 60, + 'tristana': 20, + 'twitch': 15, + 'varus': 30, + 'veigar': 25, + 'vex': 50, 'warwick': 40, - 'wukong': 40, - 'xinzhao': 45, - 'yasuo': 30, - 'yone': 40, - 'yuumi': 20, - 'zed': 20, + 'wukong': 50, + 'xerath': 40, + 'ziggs': 15, 'zilean': 20, - - 'construct': 20, - 'galio': 40, - 'aphelios_turret': 0, - 'sandguard': 50, + 'zoe': 15, 'meleeminion': 0, 'rangedminion': 0, @@ -301,69 +291,66 @@ } MR = { - 'aatrox': 40, 'ahri': 20, - 'akali': 20, - 'annie': 40, - 'aphelios': 20, - 'ashe': 20, - 'azir': 20, + 'akali': 45, + 'ashe': 15, + 'bard': 25, + 'blitzcrank': 40, + 'briar': 60, + 'camille': 60, 'cassiopeia': 20, - 'diana': 20, - 'elise': 20, - 'evelynn': 20, - 'ezreal': 20, - 'fiora': 30, - 'garen':35, - 'hecarim': 30, - 'irelia': 40, - 'janna': 20, - 'jarvaniv': 30, - 'jax': 30, - 'jhin': 20, - 'jinx': 20, - 'kalista': 20, - 'katarina': 20, - 'kayn': 40, - 'kennen': 30, - 'kindred': 20, - 'leesin': 50, - 'lillia': 80, - 'lissandra': 20, - 'lulu': 20, - 'lux': 20, - 'maokai': 20, + 'diana': 60, + 'elise': 40, + 'ezreal': 25, + 'fiora': 55, + 'galio': 45, + 'gwen': 50, + 'hecarim': 50, + 'hwei': 25, + 'jax': 45, + 'jayce': 30, + 'jinx': 25, + 'kalista': 30, + 'karma': 30, + 'kassadin': 45, + 'katarina': 45, + 'kogmaw': 20, + 'lillia': 40, + 'milio': 40, + 'mordekaiser': 50, 'morgana': 60, - 'nami': 20, - 'nidalee': 20, - 'nunu': 30, - 'pyke': 30, - 'riven': 30, - 'sejuani': 40, - 'sett': 30, - 'shen': 40, - 'sylas': 80, - 'tahmkench': 30, - 'talon': 20, - 'teemo': 20, - 'thresh': 20, - 'twistedfate': 20, - 'vayne': 20, - 'veigar': 20, - 'vi': 30, + 'nami': 30, + 'nasus': 60, + 'neeko': 45, + 'nilah': 35, + 'nomsy': 15, + 'norra_yuumi': 40, + 'nunu': 45, + 'olaf': 60, + 'poppy': 40, + 'rakan': 60, + 'rumble': 45, + 'ryze': 30, + 'seraphine': 15, + 'shen': 50, + 'shyvana': 45, + 'smolder': 50, + 'soraka': 15, + 'swain': 50, + 'syndra': 20, + 'tahm_kench': 60, + 'taric': 60, + 'tristana': 20, + 'twitch': 15, + 'varus': 30, + 'veigar': 25, + 'vex': 50, 'warwick': 40, - 'wukong': 30, - 'xinzhao': 30, - 'yasuo': 20, - 'yone': 40, - 'yuumi': 20, - 'zed': 20, + 'wukong': 50, + 'xerath': 40, + 'ziggs': 15, 'zilean': 20, - - 'construct': 20, - 'galio': 40, - 'aphelios_turret': 0, - 'sandguard': 50, + 'zoe': 15, 'meleeminion': 0, 'rangedminion': 0, @@ -377,69 +364,66 @@ } MANA = { - 'aatrox': 75, 'ahri': 0, - 'akali': 0, - 'annie': 0, - 'aphelios': 50, - 'ashe': 0, - 'azir': 75, - 'cassiopeia': 80, - 'diana': 0, - 'elise': 0, - 'evelynn': 0, - 'ezreal': 90, - 'fiora': 0, - 'garen': 0, + 'akali': 10, + 'ashe': 50, + 'bard': 30, + 'blitzcrank': 40, + 'briar': 0, + 'camille': 30, + 'cassiopeia': 0, + 'diana': 40, + 'elise': 30, + 'ezreal': 15, + 'fiora': 70, + 'galio': 30, + 'gwen': 0, 'hecarim': 0, - 'irelia': 50, - 'janna': 30, - 'jarvaniv': 50, - 'jax': 60, - 'jhin': 0, - 'jinx': 70, + 'hwei': 0, + 'jax': 20, + 'jayce': 0, + 'jinx': 0, 'kalista': 0, - 'katarina': 0, - 'kayn': 0, - 'kennen': 65, - 'kindred': 0, - 'leesin': 0, - 'lillia': 80, - 'lissandra': 0, - 'lulu': 60, - 'lux': 40, - 'maokai': 0, - 'morgana': 60, - 'nami': 60, - 'nidalee': 0, - 'nunu': 0, - 'pyke': 75, - 'riven': 0, - 'sejuani': 70, - 'sett': 100, + 'karma': 0, + 'kassadin': 30, + 'katarina': 10, + 'kogmaw': 15, + 'lillia': 40, + 'milio': 0, + 'mordekaiser': 0, + 'morgana': 40, + 'nami': 0, + 'nasus': 0, + 'neeko': 50, + 'nilah': 0, + 'nomsy': 10, + 'norra_yuumi': 30, + 'nunu': 25, + 'olaf': 0, + 'poppy': 30, + 'rakan': 40, + 'rumble': 20, + 'ryze': 15, + 'seraphine': 10, 'shen': 50, - 'sylas': 30, - 'tahmkench': 0, - 'talon': 0, - 'teemo': 0, - 'thresh': 50, - 'twistedfate': 0, - 'vayne': 0, - 'veigar': 0, - 'vi': 0, + 'shyvana': 0, + 'smolder': 0, + 'soraka': 10, + 'swain': 70, + 'syndra': 0, + 'tahm_kench': 80, + 'taric': 50, + 'tristana': 0, + 'twitch': 0, + 'varus': 20, + 'veigar': 40, + 'vex': 50, 'warwick': 0, - 'wukong': 0, - 'xinzhao': 30, - 'yasuo': 0, - 'yone': 0, - 'yuumi': 0, - 'zed': 0, - 'zilean': 100, - - 'construct': 0, - 'galio': 75, - 'aphelios_turret': 0, - 'sandguard': 0, + 'wukong': 20, + 'xerath': 0, + 'ziggs': 0, + 'zilean': 20, + 'zoe': 0, 'meleeminion': 0, 'rangedminion': 0, @@ -453,69 +437,66 @@ } MAXMANA = { - 'aatrox': 150, - 'ahri': 80, - 'akali': 20, - 'annie': 65, - 'aphelios': 80, - 'ashe': 30, - 'azir': 150, - 'cassiopeia': 150, - 'diana': 70, - 'elise': 75, - 'evelynn': 60, - 'ezreal': 150, - 'fiora': 85, - 'garen': 100, - 'hecarim': 120, - 'irelia': 100, - 'janna': 60, - 'jarvaniv': 80, - 'jax': 110, - 'jhin': 0, - 'jinx': 120, - 'kalista': 0, - 'katarina': 90, - 'kayn': 50, - 'kennen': 125, - 'kindred': 35, - 'leesin': 40, - 'lillia': 120, - 'lissandra': 50, - 'lulu': 120, - 'lux': 100, - 'maokai': 75, - 'morgana': 120, - 'nami': 100, - 'nidalee': 80, - 'nunu': 85, - 'pyke': 125, - 'riven': 20, - 'sejuani': 150, - 'sett': 175, - 'shen': 100, - 'sylas': 60, - 'tahmkench': 0, - 'talon': 40, - 'teemo': 60, - 'thresh': 100, - 'twistedfate': 70, - 'vayne': 0, - 'veigar': 45, - 'vi': 60, - 'warwick': 70, - 'wukong': 50, - 'xinzhao': 60, - 'yasuo': 45, - 'yone': 60, - 'yuumi': 40, - 'zed': 0, - 'zilean': 150, - - 'construct': 0, - 'galio': 150, - 'aphelios_turret': 0, - 'sandguard': 0, + 'ahri': 35, + 'akali': 70, + 'ashe': 100, + 'bard': 80, + 'blitzcrank': 90, + 'briar': 80, + 'camille': 100, + 'cassiopeia': 30, + 'diana': 120, + 'elise': 90, + 'ezreal': 75, + 'fiora': 130, + 'galio': 90, + 'gwen': 30, + 'hecarim': 40, + 'hwei': 40, + 'jax': 60, + 'jayce': 60, + 'jinx': 50, + 'kalista': 70, + 'karma': 30, + 'kassadin': 70, + 'katarina': 70, + 'kogmaw': 75, + 'lillia': 100, + 'milio': 90, + 'mordekaiser': 40, + 'morgana': 110, + 'nami': 50, + 'nasus': 80, + 'neeko': 125, + 'nilah': 60, + 'nomsy': 50, + 'norra_yuumi': 80, + 'nunu': 75, + 'olaf': 50, + 'poppy': 80, + 'rakan': 120, + 'rumble': 60, + 'ryze': 90, + 'seraphine': 60, + 'shen': 120, + 'shyvana': 70, + 'smolder': 40, + 'soraka': 50, + 'swain': 70, + 'syndra': 60, + 'tahm_kench': 180, + 'taric': 100, + 'tristana': 60, + 'twitch': 35, + 'varus': 100, + 'veigar': 40, + 'vex': 100, + 'warwick': 0, + 'wukong': 20, + 'xerath': 120, + 'ziggs': 40, + 'zilean': 70, + 'zoe': 30, 'meleeminion': 0, 'rangedminion': 0, @@ -531,69 +512,66 @@ COST = { # including this to get around some bugs. ' ': 0, - 'aatrox': 4, - 'ahri': 4, - 'akali': 3, - 'annie': 2, - 'aphelios': 2, - 'ashe': 4, - 'azir': 5, - 'cassiopeia': 4, - 'diana': 1, + 'ahri': 2, + 'akali': 2, + 'ashe': 1, + 'bard': 3, + 'blitzcrank': 1, + 'briar': 5, + 'camille': 5, + 'cassiopeia': 2, + 'diana': 5, 'elise': 1, - 'evelynn': 3, - 'ezreal': 5, - 'fiora': 1, - 'garen': 1, - 'hecarim': 2, - 'irelia': 3, - 'janna': 2, - 'jarvaniv': 2, - 'jax': 2, - 'jhin': 4, + 'ezreal': 3, + 'fiora': 4, + 'galio': 2, + 'gwen': 4, + 'hecarim': 3, + 'hwei': 3, + 'jax': 1, + 'jayce': 1, 'jinx': 3, - 'kalista': 3, + 'kalista': 4, + 'karma': 4, + 'kassadin': 2, 'katarina': 3, - 'kayn': 5, - 'kennen': 3, - 'kindred': 3, - 'leesin': 5, - 'lillia': 5, - 'lissandra': 1, - 'lulu': 2, - 'lux': 3, - 'maokai': 1, - 'morgana': 4, - 'nami': 1, - 'nidalee': 1, - 'nunu': 3, - 'pyke': 2, - 'riven': 4, - 'sejuani': 4, - 'sett': 5, - 'shen': 4, - 'sylas': 2, - 'tahmkench': 1, - 'talon': 4, - 'teemo': 2, - 'thresh': 2, - 'twistedfate': 1, - 'vayne': 1, + 'kogmaw': 2, + 'lillia': 1, + 'milio': 5, + 'mordekaiser': 3, + 'morgana': 5, + 'nami': 4, + 'nasus': 4, + 'neeko': 3, + 'nilah': 2, + 'nomsy': 1, + 'norra_yuumi': 5, + 'nunu': 2, + 'olaf': 4, + 'poppy': 1, + 'rakan': 4, + 'rumble': 2, + 'ryze': 4, + 'seraphine': 1, + 'shen': 3, + 'shyvana': 2, + 'smolder': 5, + 'soraka': 1, + 'swain': 3, + 'syndra': 2, + 'tahm_kench': 4, + 'taric': 4, + 'tristana': 2, + 'twitch': 1, + 'varus': 4, 'veigar': 3, - 'vi': 2, - 'warwick': 4, - 'wukong': 1, - 'xinzhao': 3, - 'yasuo': 1, - 'yone': 5, - 'yuumi': 3, - 'zed': 2, - 'zilean': 5, - - 'construct': 0, - 'galio': 0, - 'aphelios_turret': 0, - 'sandguard': 0, + 'vex': 3, + 'warwick': 1, + 'wukong': 3, + 'xerath': 5, + 'ziggs': 1, + 'zilean': 2, + 'zoe': 1, 'meleeminion': 0, 'rangedminion': 0, @@ -607,73 +585,70 @@ } SECONDARY_MAXMANA = { - 'yone': 20, + #should not apply to this set? } ABILITY_REQUIRES_TARGET = { - 'aatrox': True, 'ahri': True, - 'akali': True, - 'annie': True, - 'aphelios': False, - 'ashe': True, - 'azir': True, - 'cassiopeia': True, + 'akali': False, + 'ashe': False, + 'bard': True, + 'blitzcrank': False, + 'briar': True, + 'camille': True, + 'cassiopeia': False, 'diana': True, - 'elise': False, - 'evelynn': True, + 'elise': True, 'ezreal': True, 'fiora': True, - 'garen': True, - 'hecarim': True, - 'irelia': True, - 'janna': False, - 'jarvaniv': False, + 'galio': True, + 'gwen': True, + 'hecarim': False, #May need to be true for passive + 'hwei': True, 'jax': False, - 'jhin': False, - 'jinx': True, + 'jayce': True, + 'jinx': False, 'kalista': False, - 'katarina': False, - 'kayn': False, - 'kennen': True, - 'kindred': False, - 'leesin': True, - 'lillia': False, - 'lissandra': True, - 'lulu': False, - 'lux': False, - 'maokai': True, - 'morgana': False, + 'karma': True, + 'kassadin': False, + 'katarina': True, + 'kogmaw': True, + 'lillia': True, + 'milio': True, + 'mordekaiser': True, + 'morgana': True, 'nami': True, - 'nidalee': False, + 'nasus': True, + 'neeko': True, + 'nilah': True, + 'nomsy': True, + 'norra_yuumi': True, 'nunu': True, - 'pyke': False, - 'riven': True, - 'sejuani': False, - 'sett': True, + 'olaf': False, #May need to be true for passive + 'poppy': True, + 'rakan': True, + 'rumble': True, + 'ryze': True, + 'seraphine': True, 'shen': True, - 'sylas': True, - 'tahmkench': False, - 'talon': True, - 'teemo': False, - 'thresh': False, - 'twistedfate': True, - 'vayne': False, - 'veigar': False, - 'vi': True, + 'shyvana': True, + 'smolder': False, + 'soraka': True, + 'swain': False, + 'syndra': True, + 'tahm_kench': True, + 'taric': False, + 'tristana': True, + 'twitch': True, + 'varus': True, + 'veigar': True, + 'vex': False, 'warwick': False, - 'wukong': True, - 'xinzhao': True, - 'yasuo': False, - 'yone': False, - 'yuumi': False, - 'zed': False, - 'zilean': False, - - 'construct': False, - 'galio': False, - 'aphelios_turret': False, - 'sandguard': False, + 'wukong': False, + 'xerath': True, + 'ziggs': True, + 'zilean': True, + 'zoe': True, 'meleeminion': False, 'rangedminion': False, @@ -687,69 +662,66 @@ } ABILITY_WHILE_DISARMED = { - 'aatrox': True, - 'ahri': True, + 'ahri': False, 'akali': False, - 'annie': True, - 'aphelios': True, 'ashe': False, - 'azir': True, - 'cassiopeia': True, - 'diana': True, - 'elise': True, - 'evelynn': True, - 'ezreal': True, + 'bard': False, + 'blitzcrank': False, + 'briar': False, + 'camille': False, + 'cassiopeia': False, + 'diana': False, + 'elise': False, + 'ezreal': False, 'fiora': False, - 'garen': True, - 'hecarim': True, - 'irelia': True, - 'janna': True, - 'jarvaniv': True, - 'jax': True, - 'jhin': False, + 'galio': False, + 'gwen': False, + 'hecarim': False, + 'hwei': False, + 'jax': False, + 'jayce': False, 'jinx': False, 'kalista': False, - 'katarina': True, - 'kayn': False, - 'kennen': True, - 'kindred': False, - 'leesin': False, - 'lillia': True, - 'lissandra': False, - 'lulu': True, - 'lux': True, - 'maokai': False, - 'morgana': True, - 'nami': True, - 'nidalee': False, + 'karma': False, + 'kassadin': False, + 'katarina': False, + 'kogmaw': False, + 'lillia': False, + 'milio': False, + 'mordekaiser': False, + 'morgana': False, + 'nami': False, + 'nasus': False, + 'neeko': False, + 'nilah': False, + 'nomsy': False, + 'norra_yuumi': False, 'nunu': False, - 'pyke': True, - 'riven': False, - 'sejuani': True, - 'sett': True, - 'shen': True, - 'sylas': False, - 'tahmkench': False, - 'talon': False, - 'teemo': False, - 'thresh': True, - 'twistedfate': False, - 'vayne': False, - 'veigar': True, - 'vi': True, - 'warwick': True, + 'olaf': False, + 'poppy': False, + 'rakan': False, + 'rumble': False, + 'ryze': False, + 'seraphine': False, + 'shen': False, + 'shyvana': False, + 'smolder': False, + 'soraka': False, + 'swain': False, + 'syndra': False, + 'tahm_kench': False, + 'taric': False, + 'tristana': False, + 'twitch': False, + 'varus': False, + 'veigar': False, + 'vex': False, + 'warwick': False, 'wukong': False, - 'xinzhao': False, - 'yasuo': False, - 'yone': True, - 'yuumi': True, - 'zed': False, - 'zilean': True, - - 'construct': False, - 'galio': True, - 'aphelios_turret': False, - 'sandguard': False, + 'xerath': False, + 'ziggs': False, + 'zilean': False, + 'zoe': False, 'meleeminion': False, 'rangedminion': False, @@ -763,69 +735,66 @@ } RANGE = { - 'aatrox': 1, 'ahri': 4, 'akali': 1, - 'annie': 2, - 'aphelios': 4, 'ashe': 4, - 'azir': 4, - 'cassiopeia': 2, + 'bard': 4, + 'blitzcrank': 1, + 'briar': 1, + 'camille': 1, + 'cassiopeia': 4, 'diana': 1, - 'elise': 2, - 'evelynn': 1, + 'elise': 1, 'ezreal': 4, 'fiora': 1, - 'garen': 1, + 'galio': 1, + 'gwen': 2, 'hecarim': 1, - 'irelia': 1, - 'janna': 4, - 'jarvaniv': 1, + 'hwei': 4, 'jax': 1, - 'jhin': 4, + 'jayce': 4, 'jinx': 4, - 'kalista': 3, + 'kalista': 4, + 'karma': 4, + 'kassadin': 1, 'katarina': 1, - 'kayn': 1, - 'kennen': 2, - 'kindred': 3, - 'leesin': 1, - 'lillia': 2, - 'lissandra': 3, - 'lulu': 3, - 'lux': 4, - 'maokai': 1, - 'morgana': 3, - 'nami': 3, - 'nidalee': 4, + 'kogmaw': 4, + 'lillia': 1, + 'milio': 4, + 'mordekaiser': 1, + 'morgana': 2, + 'nami': 4, + 'nasus': 1, + 'neeko': 1, + 'nilah': 2, + 'nomsy': 4, + 'norra_yuumi': 4, 'nunu': 1, - 'pyke': 1, - 'riven': 1, - 'sejuani': 1, - 'sett': 1, + 'olaf': 1, + 'poppy': 1, + 'rakan': 1, + 'rumble': 1, + 'ryze': 4, + 'seraphine': 4, 'shen': 1, - 'sylas': 1, - 'tahmkench': 1, - 'talon': 1, - 'teemo': 3, - 'thresh': 2, - 'twistedfate': 3, - 'vayne': 4, - 'veigar': 3, - 'vi': 1, + 'shyvana': 1, + 'smolder': 5, + 'soraka': 4, + 'swain': 1, + 'syndra': 4, + 'tahm_kench': 1, + 'taric': 1, + 'tristana': 4, + 'twitch': 4, + 'varus': 4, + 'veigar': 4, + 'vex': 1, 'warwick': 1, 'wukong': 1, - 'xinzhao': 1, - 'yasuo': 1, - 'yone': 1, - 'yuumi': 3, - 'zed': 1, - 'zilean': 3, - - 'construct': 1, - 'galio': 1, - 'aphelios_turret': 99, - 'sandguard': 0, + 'xerath': 4, + 'ziggs': 4, + 'zilean': 4, + 'zoe': 4, 'meleeminion': 1, 'rangedminion': 1, @@ -838,105 +807,100 @@ 'riftherald': 1, } +#Assuming all times are in milliseconds SHIELD_LENGTH = { - 'annie': 8000, - 'diana': 4000, - 'janna': 4000, - 'thresh': 4000, + 'blitzcrank': 6000, + 'dianna': 3000, + 'kasadin': 3000, + 'mordekaiser': 2000, + 'morgrana': 4000, + 'nilah': 3000, + 'poppy': 3000, + 'rakan': 3000, #also applies a shield to allies + 'vex': 4000, + 'wukong': 4000, } ABILITY_LENGTH = { - 'aatrox': 500, - 'ahri': 1500, - 'aphelios': [0, 7000, 8000, 9000, 11000], - 'ashe': 5000, - 'azir': 1500, - 'ezreal': 1500, - 'fiora': 1500, - 'garen': 4000, - 'hecarim': 3000, - 'janna': 4000, - 'jax': 2000, - 'katarina': 2500, - 'kennen': 3000, - 'morgana': 5000, - 'pyke': 1000, - 'sejuani': 2000, - 'sett': 1000, - 'shen': [0, 4000, 4000, 8000], - 'talon': 1300, - 'vi': 8000, - 'warwick': 3000, - 'yuumi': 2000, - 'zilean': [0, 3500, 3000, 1000], - - 'galio': 3000, + 'camille': 3000, + 'diana': 3000, + 'fiora': 500, #Need to figure out exact time of duribilty, this is a tricky one + 'galio': 4000, + 'hecarim': 6000, + 'jax': 6000, + 'jin': 5000, + 'karma': 6000, #base is 6 seconds but 3 star is 4 seconds + 'katarina': 3000, + 'neeko': 2000, + 'norra_yuumi': 5000, #base is 5 seconds but 3 star is 15 seconds + 'olaf': 5000, + 'rumble': 3000, + 'shen': 3000, + 'taric': 4000, } +#likely need in game testing to determine these values MANALOCK = { - 'aatrox': 1000, - 'ahri': 1000 + ABILITY_LENGTH['ahri'], - 'akali': 1250, - 'annie': 1000 + SHIELD_LENGTH['annie'], - 'aphelios': 1000, - 'ashe': 1000 + ABILITY_LENGTH['ashe'], - 'azir': 1000, - 'cassiopeia': 1000, - 'diana': 1000, + 'ahri': 0, + 'akali': 0, + 'ashe': 0, + 'bard': 0, + 'blitzcrank': 0, + 'briar': 0, + 'camille': 0, + 'cassiopeia': 0, + 'diana': 0, 'elise': 0, - 'evelynn': 1000, - 'ezreal': 1000 + ABILITY_LENGTH['ezreal'], - 'fiora': 1000 + ABILITY_LENGTH['fiora'], - 'garen': 1000 + ABILITY_LENGTH['garen'], - 'hecarim': 1000 + ABILITY_LENGTH['hecarim'], - 'irelia': 1000, - 'janna': 1000, - 'jarvaniv': 1000, - 'jax': 1000 + ABILITY_LENGTH['jax'], - 'jhin': 0, - 'jinx': 1000, + 'ezreal': 0, + 'fiora': 0, + 'galio': 0, + 'gwen': 0, + 'hecarim': 0, + 'hwei': 0, + 'jax': 0, + 'jayce': 0, + 'jinx': 0, 'kalista': 0, - 'katarina': 1000 + ABILITY_LENGTH['katarina'], - 'kayn': 1000, - 'kennen': 1000 + ABILITY_LENGTH['kennen'], - 'kindred': 1000, - 'leesin': 1000, - 'lillia': 1000, - 'lissandra': 1000, - 'lulu': 1000, - 'lux': 1000, - 'maokai': 1000, - 'morgana': 1000 + ABILITY_LENGTH['morgana'], - 'nami': 1000, - 'nidalee': 1000, - 'nunu': 1000, - 'pyke': 1000 + ABILITY_LENGTH['pyke'], - 'riven': 1000, - 'sejuani': 1000 + ABILITY_LENGTH['sejuani'], - 'sett': 1000 + ABILITY_LENGTH['sett'], - 'shen': 1000, # a bit tricky since this scales by stars. handled in the champion class object creation - 'sylas': 1000, - 'tahmkench': 0, - 'talon': 1000 + ABILITY_LENGTH['talon'], - 'teemo': 1000, - 'thresh': 1000, - 'twistedfate': 1000, - 'vayne': 0, - 'veigar': 1000, - 'vi': 1000, + 'karma': 0, + 'kassadin': 0, + 'katarina': 0, + 'kogmaw': 0, + 'lillia': 0, + 'milio': 0, + 'mordekaiser': 0, + 'morgana': 0, + 'nami': 0, + 'nasus': 0, + 'neeko': 0, + 'nilah': 0, + 'nomsy': 0, + 'norra_yuumi': 0, + 'nunu': 0, + 'olaf': 0, + 'poppy': 0, + 'rakan': 0, + 'rumble': 0, + 'ryze': 0, + 'seraphine': 0, + 'shen': 0, + 'shyvana': 0, + 'smolder': 0, + 'soraka': 0, + 'swain': 0, + 'syndra': 0, + 'tahm_kench': 0, + 'taric': 0, + 'tristana': 0, + 'twitch': 0, + 'varus': 0, + 'veigar': 0, + 'vex': 0, 'warwick': 0, - 'wukong': 1000, - 'xinzhao': 1000, - 'yasuo': 1000, - 'yone': 1000, - 'yuumi': 1000 + ABILITY_LENGTH['yuumi'], - 'zed': 0, - 'zilean': 1000, - - 'construct': 0, - 'galio': 1000 + ABILITY_LENGTH['galio'], - 'aphelios_turret': 0, - 'sandguard': 0, + 'wukong': 0, + 'xerath': 0, + 'ziggs': 0, + 'zilean': 0, + 'zoe': 0, 'meleeminion': 0, 'rangedminion': 0, @@ -951,350 +915,220 @@ ATTACK_WHILE_ABILITY_ACTIVE = { - 'aatrox': False, - 'ashe': True, + 'camille': True, 'diana': True, - 'elise': True, - 'garen': False, + 'fiora': False, + 'galio': True, 'hecarim': True, 'jax': True, + 'jin': True, + 'karma': True, 'katarina': False, - 'kennen': True, - 'morgana': True, - 'pyke': True, - 'sejuani': True, - 'sett': False, - 'talon': False, - 'warwick': True, - 'yuumi': False, + 'neeko': False, + 'norra_yuumi': True, + 'olaf': True, + 'rumble': False, + 'shen': True, + 'taric': False, } - +#TODO AP and AD scalings have changed since this set, this will likely need a overhaul +#These will need to filled out with each new champ ability added ABILITY_DMG = { - 'aatrox': [0,250,450,1250], - 'ahri': [0,500,700,3000], - 'akali': [0,175,250,400], - 'annie': [0,250,350,450], - 'azir': [0,200,350,8888], - 'cassiopeia': [0,275,400,2000], - 'diana': [0,70,80,90,100], - 'evelynn': [0,350,500,1400], - 'ezreal': [0,250,450,9999], - 'fiora': [0, 200, 300, 450], - 'garen': [0,450,675,1125], - 'hecarim': [0, 250, 400, 600], - 'irelia': [0, 200, 300, 600], - 'jarvaniv': [0, 175, 250, 750], - 'jax': [0, 150, 250, 450], - 'jinx': [0, 150, 250, 450], - 'katarina': [0, 750, 900, 1600], - 'kayn': [0, 400, 600, 6666], - 'kennen': [0, 300, 450, 1200], - 'kindred': [0, 450, 650, 1000], - 'leesin': [0, 250, 450, 1000], - 'lillia': [0, 500, 500, 500], - 'lissandra': [0, 350, 450, 600, 800], - 'lux': [0, 300, 400, 700], - 'maokai': [0, 225, 350, 550], - 'morgana': [0, 250, 400, 2000], - 'nami': [0, 225, 325, 450], - 'nidalee': [0, 225, 350, 600], - 'nunu': [0, 450, 650, 1800], - 'pyke': [0, 125, 200, 375], - 'riven': [0, 175, 250, 750], - 'sejuani': [0, 100, 200, 800], - 'sett': [0, 0.40, 0.60, 4.00], # % of max health - 'sylas': [0, 250, 400, 600, 1000], - 'talon': [0, 85, 135, 400], - 'teemo': [0, 300, 450, 900], - 'twistedfate': [0, 250, 350, 475], - 'veigar': [0, 450, 650, 900], - 'vi': [0, 250, 400, 800], - 'yone': [0, 800, 1300, 9999], - - 'galio': [0, 0, 300, 600] + } ABILITY_SECONDARY_DMG = { - 'lissandra': [0, 175, 225, 300, 450], - 'riven': [0, 300, 450, 1350], - 'sett': [0, 0.20, 0.30, 2.00], # % of max health - 'yone': [0, 250, 400, 1000], - 'galio': [0, 150, 300, 500], } ABILITY_DAMAGE_MULTIPLIER = { - 'ashe': 0.45, - 'evelynn': [0,3,3,3], - 'talon': [0, 2.00, 2.00, 2.50], - 'wukong': [0, 2.25, 2.50, 2.75], - 'xinzhao': [0, 3.00, 3.25, 3.50], - 'yasuo': [0, 1.80, 2.00, 2.25], + } ABILITY_DAMAGE_ADDITION_PERCENTAGE = { - 'nidalee': 0.2, - 'nunu': 0.5, + } ABILITY_MISSING_HEALTH_DAMAGE_PERCENTAGE = { - 'yone': 1.00, + } ABILITY_AS_GAIN = { - 'ashe': [0, 1.45, 1.65, 3.0], - 'ezreal': [0, 1.5, 1.5, 1.5], - 'warwick': [0, 1.35, 1.50, 5.00], - 'yuumi': [0, 1.30, 1.40, 1.60], - 'zilean': [0, 1.50, 1.50, 5.00], + } -ABILITY_AS_SECONDARY_GAIN = {'warwick': [0, 1.60, 1.75, 3.00]} +ABILITY_AS_SECONDARY_GAIN = {} ABILITY_AS_DECREASE = { - 'ezreal': [0, 0.5, 0.5, 0.5], - 'maokai': [0, 0.5, 0.5, 0.5], + } ABILITY_MR_DECREASE = { - 'morgana': 0.60, + } # shredding 40% of their magic resistance ABILITY_ARMOR_DECREASE = { - 'vi': [0, 0.50, 0.25, 0.0001] + } # same as with morgana: values are (1 - reduction). 3 star would bring some troubles if the value was 0.00 ABILITY_ARMOR_MR_DECREASE = { - 'yone': 0.40 + }# 1-reduction ABILITY_SPELL_DAMAGE_REDUCTION_PERCENTAGE = { - 'garen': 0.2 + } ABILITY_ARMOR_MR_INCREASE = { - 'xinzhao': [0, 50, 60, 75], + } #increasing x units ABILITY_AS_CHANGE_LENGTH = { - 'ezreal': 5000, - 'maokai': 3000, - 'yuumi': 5000, + } ABILITY_DMG_GAIN = { - 'janna': [0, 20, 30, 60], + } # percentages and absolutes in the same dict ABILITY_EXTRA_DAMAGE = { - 'kayn': [0, 1.65, 1.65, 1.65] + } -ABILITY_EXTRA_DAMAGE_LENGTH = {'kayn': 10000} +ABILITY_EXTRA_DAMAGE_LENGTH = { +} + ABILITY_DISARM_DURATION = { - 'irelia': [0, 2500, 3000, 3500], + } ABILITY_TARGETS = { - 'aatrox': [0,2,2,5], - 'diana': [0,4,5,6,9], - 'janna': [0, 2, 3, 4], - 'katarina': [0, 4, 6, 8], - 'lillia': [0, 2, 3, 10], - 'zilean': [0, 2, 3, 10], + } ABILITY_TARGET_PROBABILITIES = { - 'evelynn': [0, 0, 0.75, 0.9] # 1 = 75%, 2= 15%, 3 = 10% } ABILITY_RADIUS = { - 'ahri': 2, - 'kennen': 3, - 'morgana': 2, - 'sejuani': 3, - 'sett': 2, - 'yone': 5, - - 'galio': 2, } #how many hexes from the center of the ult. with yone it's just the path length including yone's hex -ABILITY_SECONDARY_RADIUS = {'galio': [0, 1, 2, 4]} +ABILITY_SECONDARY_RADIUS = {} -SHIELD_AMOUNT = { - 'annie': [0,500,700,900], - 'diana': [0,200,300,400,500], - 'janna': [0, 250, 300, 400], - 'riven': [0, 175, 250, 750], - 'shen': [0, 500, 800, 4000], - 'thresh': [0, 250, 450, 750], +SHIELD_AMOUNT = { } ABILITY_HEAL = { - 'ezreal': [0, 250, 450, 9999], - 'hecarim': [0, 250, 400, 600], - 'zilean': [0, 350, 500, 3000], - + } ABILITY_HEAL_PER_DAMAGE = { - 'morgana': [0, 0.20, 0.25, 0.30], + } ABILITY_HEALING_REDUCE = { - 'katarina': 0.5, - 'kindred': 0.5, + } #how much heals will affect the target ABILITY_HEALING_REDUCE_LENGTH = { - 'katarina': 5000, - 'kindred': 5000, + } ABILITY_HEALTH_GAIN_PERCENTAGES = { - 'elise': [0, 1.35, 1.40, 1.45], - 'yuumi': [0, 0.30, 0.45, 0.75], } ABILITY_HEALTH_GAIN_TOTAL = { - 'lulu': [0, 400, 600, 950], } ABILITY_HEALTH_PER_ATTACK = { - 'elise': [0,40,80,160] + } ABILITY_HEALTH_PER_CAST_DAMAGE_PERCENTAGES = { - 'kayn': [0, 0.5, 0.5, 0.5], + } ABILITY_STUN_DURATION = { - 'azir': [0, 2000, 2000, 2000], - 'cassiopeia': [0, 2500, 3000, 5000], - 'fiora': [0, 1500, 2000, 3000], - 'jarvaniv': [0, 1000, 1000, 1000], - 'jax': [0, 1500, 1500, 1500], - 'jinx': [0, 1500, 2000, 2500], - 'kennen': [0, 1500, 1500, 1500], - 'leesin': [0, 2000, 3000, 10000], - 'lillia': [0, 2000, 3000, 8000], - 'lulu': [0, 1000, 1000, 1000], - 'lux': [0, 1500, 2000, 3000], - 'nami': [0, 2500, 3000, 4000], - 'pyke': [0, 2000, 2500, 4000], - 'sejuani': [0, 2500, 3000, 6000], - # 'warwick': [0, 750, 750, 3000], - 'wukong': [0, 1500, 2000, 3000], - # 'yone': [0, 1500, 1500, 1500], - - 'galio': [0, 1500, 2000, 2000], + } ABILITY_BLIND_DURATION = { - 'teemo': [0, 2500, 3000, 4500] } ABILITY_SECONDARY_STUN_DURATION = { - 'leesin': [0, 1000, 1000, 1000], } ABILITY_STUN_STOP_DMG_THRESHOLD = { - 'lillia': [0, 500, 750, 1000] } ABILITY_SLOW_DURATION = { - 'azir': 4000 } ABILITY_SLOW_AMOUNT = { - 'azir': 2 } #how many times slower the unit's movement will be ABILITY_TARGET_INCREASE_DAMAGE_RECEIVING = { - 'cassiopeia': 1.20, } ABILITY_TARGET_DECREASE_DAMAGE_RECEIVING = { - 'galio': 0.50, } ABILITY_MANA_REQUIREMENT_INCREASEMENT = { - 'kayn': 0.33, - 'sylas': 0.33, } ABILITY_SP_GAIN = { - 'veigar': [0, 0.01, 0.01, 0.02] } ABILITY_SLICES = { - 'ashe': 5, - 'garen': 10, - 'hecarim': 10, - 'katarina': 15, - 'kennen': 6, - 'morgana': 10, - 'teemo': 6, + } SECONDARY_ABILITY_COUNTER = { - 'riven': 3 } LIFESTEAL = { - 'warwick': [0, 0.5, 0.5, 2.00], } MOVEMENTDELAY = { - 'warwick': 350 } # absolutely no clue what this should be ACTIVATE_EVERY_X_ATTACKS = { - 'vayne': 3, - 'jhin': 4, - 'zed': 3, + } ACTIVE_STOLEN_AD = { - 'zed': [0, 0.25, 0.30, 0.35] } ACTIVE_DMG = { - 'vayne': [0, 50, 90, 140], - 'zed': [0, 40, 50, 75] } -ACTIVE_DMG_PERCENT = {'jhin': [0, 4.44, 5.00, 12.34]} -ATTACKS_PER_SECOND_FIXED = {'jhin': [0, 0.85, 0.90, 1.2]} -INITIATIVE_ACTIVE = ['jhin', 'tahmkench'] # these champions will execute a function when __init__ing +ACTIVE_DMG_PERCENT = {} +ATTACKS_PER_SECOND_FIXED = {} +INITIATIVE_ACTIVE = [] # these champions will execute a function when __init__ing -ACTIVE_TARGET_HEALT_THRESHOLD = {'kalista': [0, 0.04, 0.06, 0.09]} -ACTIVE_DAMAGE_REDUCTION = {'tahmkench': [0, 15, 25, 75]} +ACTIVE_TARGET_HEALT_THRESHOLD = {} +ACTIVE_DAMAGE_REDUCTION = {} DODGE = 0.0 -DAMAGE_PER_UNIT = [0, 2, 4, 6, 8, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] +#This is now just 1 dmg per unit, this may not be needed anymore in that case +DAMAGE_PER_UNIT = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] -BASE_CHAMPION_LIST = ['diana', 'elise', 'fiora', 'garen', 'lissandra', 'tahmkench', 'maokai', 'nami', 'nidalee', - 'twistedfate', 'vayne', 'wukong', 'yasuo', 'annie', 'aphelios', 'hecarim', 'janna', 'jarvaniv', - 'jax', 'lulu', 'pyke', 'sylas', 'teemo', 'thresh', 'vi', 'zed', 'akali', 'evelynn', 'irelia', - 'jinx', 'kalista', 'katarina', 'kennen', 'kindred', 'lux', 'nunu', 'veigar', 'xinzhao', 'yuumi', - 'aatrox', 'ahri', 'ashe', 'cassiopeia', 'jhin', 'morgana', 'riven', 'sejuani', 'shen', 'talon', - 'warwick', 'azir', 'ezreal', 'kayn', 'leesin', 'lillia', 'sett', 'yone', 'zilean' - ] +BASE_CHAMPION_LIST = ['ahri', 'akali', 'ashe', 'bard', 'blitzcrank', 'briar', 'camille', 'cassiopeia', 'diana', 'elise', 'ezreal', 'fiora', 'galio', 'gwen', 'hecarim', 'hwei', 'jax', 'jayce', 'jinx', 'kalista', 'karma', 'kassadin', 'katarina', 'kogmaw', + 'lillia', 'milio', 'mordekaiser', 'morgana', 'nami', 'nasus', 'neeko', 'nilah', 'nomsy', 'norra_yuumi', 'nunu', 'olaf', 'poppy', 'rakan', 'rumble', 'ryze', 'seraphine', 'shen', 'shyvana', 'smolder', 'soraka', 'swain', 'syndra', + 'tahm_kench', 'taric', 'tristana', 'twitch', 'varus', 'veigar', 'vex', 'warwick', 'wukong', 'xerath', 'ziggs', 'zilean', 'zoe']