Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 87 additions & 11 deletions worlds/lol/Connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,19 @@

###SET GLOBAL VARIABLES###
url = "https://127.0.0.1:2999/liveclientdata/allgamedata"
GAME_WIN_LOCATION_CODE = 566900001
unlocked_champion_ids = []
total_lp_gained = 0
in_match = False
tracked_teammates = set()
game_values = {
"required_assists": 0,
"required_cs" : 0,
"required_kills" : 0,
"required_lp" : 0,
"required_vs" : 0,
"current_lp" : 0
"current_lp" : 0,
"starting_champions": 0
}

###SET UP GAME COMMUNICATION PATH###
Expand All @@ -51,10 +54,11 @@ def get_items(game_values):
if file.startswith("AP"):
with open(os.path.join(game_communication_path, file), 'r') as f:
item_id = int(f.readline())
if item_id % 565000000 == 0:
decoded_item = item_id - 565000000
if decoded_item == 0:
game_values["current_lp"] = game_values["current_lp"] + 1
else:
unlocked_champion_ids.append(item_id % 565000000)
elif decoded_item in champions:
unlocked_champion_ids.append(decoded_item)
f.close()

def read_cfg(game_values):
Expand Down Expand Up @@ -84,6 +88,11 @@ def read_cfg(game_values):
game_values["required_vs"] = int(f.readline())
else:
game_values["required_vs"] = 0
if "Starting_Champion_Count.cfg" in files:
with open(os.path.join(game_communication_path, "Starting_Champion_Count.cfg"), 'r') as f:
game_values["starting_champions"] = max(0, int(f.readline()))
else:
game_values["starting_champions"] = 0

def display_champion_list(window):
champion_table_rows = []
Expand All @@ -101,16 +110,27 @@ def display_values(window, game_values):
value_table_rows.append(['Current LP:' , str(game_values["current_lp"])])
window["Values Table"].update(values=value_table_rows)

def send_starting_champion_check():
for i in range(6):
with open(os.path.join(game_communication_path, "send56600000" + str(i)), 'w') as f:
def send_starting_champion_check(game_values):
for i in range(1, game_values["starting_champions"] + 1):
with open(os.path.join(game_communication_path, f"send{566000000 + i}"), 'w') as f:
f.close()

def check_lp_for_victory(game_values):
if game_values["current_lp"] >= game_values["required_lp"] and game_values["required_lp"] != 0:
with open(os.path.join(game_communication_path, "victory"), 'w') as f:
f.close()

def won_game(game_data):
for event in game_data["events"]["Events"]:
if event.get("EventName") == "GameEnd" and event.get("Result") == "Win":
return True
return False

def send_game_win_location(game_data):
if won_game(game_data):
with open(os.path.join(game_communication_path, f"send{GAME_WIN_LOCATION_CODE}"), 'w') as f:
f.close()

def get_player_name(game_data):
return game_data["activePlayer"]["riotIdGameName"]

Expand All @@ -124,6 +144,36 @@ def get_champion_id(champion_name):
if champions[champion_id]["name"] == champion_name:
return champion_id

def get_player_data(game_data, player_name):
for player in game_data["allPlayers"]:
if player["riotIdGameName"] == player_name:
return player
return None

def get_available_teammates(game_data):
player_name = get_player_name(game_data)
player_data = get_player_data(game_data, player_name)
if player_data is None:
return []

player_team = player_data.get("team")
teammate_names = []
for player in game_data["allPlayers"]:
if player.get("team") == player_team and player["riotIdGameName"] != player_name:
teammate_names.append(player["riotIdGameName"])
return sorted(teammate_names)

def update_teammate_selector(window, teammate_names):
valid_teammates = sorted(tracked_teammates.intersection(teammate_names))
set_to_index = [teammate_names.index(teammate_name) for teammate_name in valid_teammates]
window["Tracked Teammates List"].update(values=teammate_names, set_to_index=set_to_index)

def get_tracked_players(game_data):
player_name = get_player_name(game_data)
teammate_names = set(get_available_teammates(game_data))
selected_teammates = sorted(tracked_teammates.intersection(teammate_names))
return [player_name] + selected_teammates

def took_tower(game_data, player_name):
for event in game_data["events"]["Events"]:
if event["EventName"] == "TurretKilled" and event["KillerName"] == player_name:
Expand Down Expand Up @@ -208,11 +258,16 @@ def kills_above(game_data, player_name, score_target):
def assists_above(game_data, player_name, score_target):
return player_assists(game_data, player_name) >= score_target and score_target > 0

def get_objectives_complete(game_data, game_values):
def get_objectives_complete_for_player(game_data, game_values, player_name):
objectives_complete = []
player_name = get_player_name(game_data)
champion_name = get_champion_name(game_data, player_name)
if champion_name is None:
return objectives_complete, None

champion_id = get_champion_id(champion_name)
if champion_id is None:
return objectives_complete, None

if champion_id in unlocked_champion_ids:
if assisted_epic_monster(game_data, player_name, "Dragon"):
objectives_complete.append(1)
Expand All @@ -232,7 +287,13 @@ def get_objectives_complete(game_data, game_values):
objectives_complete.append(8)
if creep_score_above(game_data, player_name, game_values["required_cs"]):
objectives_complete.append(9)
send_locations(objectives_complete, champion_id)
return objectives_complete, champion_id

def get_objectives_complete(game_data, game_values):
for player_name in get_tracked_players(game_data):
objectives_complete, champion_id = get_objectives_complete_for_player(game_data, game_values, player_name)
if champion_id is not None:
send_locations(objectives_complete, champion_id)

def send_locations(objectives_complete, champion_id):
for objective_id in objectives_complete:
Expand All @@ -257,6 +318,16 @@ def send_locations(objectives_complete, champion_id):
[sg.Table(
[
], headings = ["Value Type", "Value Amount"], key = "Values Table")]
]),
sg.Column(
[
[sg.Text("Tracked Teammates")],
[sg.Listbox(
values = [],
select_mode = sg.LISTBOX_SELECT_MODE_MULTIPLE,
size = (24, 6),
enable_events = True,
key = "Tracked Teammates List")]
])
]
]
Expand All @@ -269,19 +340,24 @@ def send_locations(objectives_complete, champion_id):
break
if event == 'Check for Match Button':
in_match = True
if event == "Tracked Teammates List":
tracked_teammates = set(values["Tracked Teammates List"])
check_lp_for_victory(game_values)
get_items(game_values)
read_cfg(game_values)
display_champion_list(window)
display_values(window, game_values)
send_starting_champion_check()
send_starting_champion_check(game_values)
if in_match:
game_data = get_game_data()
if game_data is None:
window["In Match Text"].update("In Match: No Match Found")
update_teammate_selector(window, [])
in_match = False
else:
window["In Match Text"].update("In Match: In Match")
update_teammate_selector(window, get_available_teammates(game_data))
get_objectives_complete(game_data, game_values)
send_game_win_location(game_data)

window.close()
45 changes: 45 additions & 0 deletions worlds/lol/Items.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,51 @@ def get_items_by_category(category: str, disclude: list) -> Dict[str, LOLItemDat
item_table[champions[champion_id]["name"]] = LOLItemData("Champion", code = 565_000000 + int(champion_id), classification = ItemClassification.progression, max_quantity = 1, weight = 1)
item_table["LP"] = LOLItemData("Win Condition", code = 565_000000, classification = ItemClassification.progression, max_quantity = -1, weight = 1)

filler_item_names = [
"Black Spear",
"Cull",
"Dark Seal",
"Doran's Blade",
"Doran's Ring",
"Doran's Shield",
"Guardian's Amulet",
"Guardian's Blade",
"Guardian's Dirk",
"Guardian's Hammer",
"Guardian's Horn",
"Guardian's Orb",
"Guardian's Shroud",
"Gustwalker Hatchling",
"Mosstomper Seedling",
"Scorchclaw Pup",
"Tear of the Goddess",
"World Atlas",
"Amplifying Tome",
"B. F. Sword",
"Blasting Wand",
"Cloak of Agility",
"Cloth Armor",
"Dagger",
"Faerie Charm",
"Glowing Mote",
"Long Sword",
"Needlessly Large Rod",
"Null-Magic Mantle",
"Pickaxe",
"Rejuvenation Bead",
"Ruby Crystal",
"Sapphire Crystal",
]

for index, item_name in enumerate(filler_item_names, start=1):
item_table[item_name] = LOLItemData(
"Filler",
code=565_100000 + index,
classification=ItemClassification.filler,
max_quantity=-1,
weight=1,
)


event_item_table: Dict[str, LOLItemData] = {
}
9 changes: 4 additions & 5 deletions worlds/lol/Locations.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,10 @@ def get_locations_by_category(category: str) -> Dict[str, LOLLocationData]:
location_table[champion_name + " - Get X Kills"] = LOLLocationData("Objective", 566_000000 + (int(champion_id) * 100) + 8)
location_table[champion_name + " - Get X Creep Score"] = LOLLocationData("Objective", 566_000000 + (int(champion_id) * 100) + 9)

location_table["Starting Champion 1"] = LOLLocationData("Starting", 566_000001)
location_table["Starting Champion 2"] = LOLLocationData("Starting", 566_000002)
location_table["Starting Champion 3"] = LOLLocationData("Starting", 566_000003)
location_table["Starting Champion 4"] = LOLLocationData("Starting", 566_000004)
location_table["Starting Champion 5"] = LOLLocationData("Starting", 566_000005)
for index in range(1, 101):
location_table[f"Starting Champion {index}"] = LOLLocationData("Starting", 566_000000 + index)

location_table["Game Win - Enemy Nexus Destroyed"] = LOLLocationData("Objective", 566_900001)

event_location_table: Dict[str, LOLLocationData] = {
}
Expand Down
23 changes: 21 additions & 2 deletions worlds/lol/Options.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ class RequiredLPPercentage(Range):
range_end = 100
display_name = "Required LP Percentage"


class TotalLPCount(Range):
"""
Total LP items to place in the world.
"""
default = 80
range_start = 1
range_end = 500
display_name = "Total LP Count"

class Champions(OptionSet):
"""
Which champions are possibly included in the item pool?
Expand Down Expand Up @@ -65,7 +75,7 @@ class StartingChampions(Range):
"""
default = 3
range_start = 1
range_end = 5
range_end = 100
display_name = "Starting Champions"

class ChampionSubsetCount(Range):
Expand All @@ -77,13 +87,22 @@ class ChampionSubsetCount(Range):
range_end = 200
display_name = "Champion Subset Count"

class ARAMMode(Toggle):
"""
Enable ARAM mode. The only checks enabled are:
Tower, Inhibitor, Assists, and Kills.
"""
display_name = "ARAM Mode"

@dataclass
class LOLOptions(PerGameCommonOptions):
champions: Champions
required_creep_score: RequiredCreepScore
required_vision_score: RequiredVisionScore
required_kills: RequiredKills
required_assists: RequiredAssists
total_lp_count: TotalLPCount
required_lp: RequiredLPPercentage
starting_champions: StartingChampions
champion_subset_count: ChampionSubsetCount
champion_subset_count: ChampionSubsetCount
aram_mode: ARAMMode
14 changes: 9 additions & 5 deletions worlds/lol/Regions.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,26 @@ def create_regions(multiworld: MultiWorld, player: int, options, possible_champi

# Set up locations

aram = bool(options.aram_mode)
for champion_id in champions:
champion_name = champions[champion_id]["name"]
if champion_name in possible_champions:
regions["Match"].locations.append(champion_name + " - Assist Taking Dragon")
regions["Match"].locations.append(champion_name + " - Assist Taking Rift Herald")
regions["Match"].locations.append(champion_name + " - Assist Taking Baron")
if not aram:
regions["Match"].locations.append(champion_name + " - Assist Taking Dragon")
regions["Match"].locations.append(champion_name + " - Assist Taking Rift Herald")
regions["Match"].locations.append(champion_name + " - Assist Taking Baron")
regions["Match"].locations.append(champion_name + " - Assist Taking Tower")
regions["Match"].locations.append(champion_name + " - Assist Taking Inhibitor")
regions["Match"].locations.append(champion_name + " - Get X Assists")
if "Support" in champions[champion_id]["tags"]:
if not aram and "Support" in champions[champion_id]["tags"]:
regions["Match"].locations.append(champion_name + " - Get X Ward Score")
if "Support" not in champions[champion_id]["tags"]:
regions["Match"].locations.append(champion_name + " - Get X Kills")
regions["Match"].locations.append(champion_name + " - Get X Creep Score")
if not aram:
regions["Match"].locations.append(champion_name + " - Get X Creep Score")
for i in range(min(options.starting_champions, len(possible_champions))):
regions["Match"].locations.append("Starting Champion " + str(i+1))
regions["Match"].locations.append("Game Win - Enemy Nexus Destroyed")

# Set up the regions correctly.
for name, data in regions.items():
Expand Down
13 changes: 8 additions & 5 deletions worlds/lol/Rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,23 @@ def has_at_least(state: CollectionState, player: int, item_name, item_qty_requir
return state.count(item_name, player) >= item_qty_required

def set_rules(multiworld: MultiWorld, player: int, options, required_lp, possible_champions):
aram = bool(options.aram_mode)
for champion_id in champions:
champion_name = champions[champion_id]["name"]
if champion_name in possible_champions:
multiworld.get_location(champion_name + " - Assist Taking Dragon" , player).access_rule = lambda state, champion_name = champion_name: has_item(state, player, champion_name)
multiworld.get_location(champion_name + " - Assist Taking Rift Herald", player).access_rule = lambda state, champion_name = champion_name: has_item(state, player, champion_name)
multiworld.get_location(champion_name + " - Assist Taking Baron" , player).access_rule = lambda state, champion_name = champion_name: has_item(state, player, champion_name)
if not aram:
multiworld.get_location(champion_name + " - Assist Taking Dragon" , player).access_rule = lambda state, champion_name = champion_name: has_item(state, player, champion_name)
multiworld.get_location(champion_name + " - Assist Taking Rift Herald", player).access_rule = lambda state, champion_name = champion_name: has_item(state, player, champion_name)
multiworld.get_location(champion_name + " - Assist Taking Baron" , player).access_rule = lambda state, champion_name = champion_name: has_item(state, player, champion_name)
multiworld.get_location(champion_name + " - Assist Taking Tower" , player).access_rule = lambda state, champion_name = champion_name: has_item(state, player, champion_name)
multiworld.get_location(champion_name + " - Assist Taking Inhibitor" , player).access_rule = lambda state, champion_name = champion_name: has_item(state, player, champion_name)
multiworld.get_location(champion_name + " - Get X Assists" , player).access_rule = lambda state, champion_name = champion_name: has_item(state, player, champion_name)
if "Support" in champions[champion_id]["tags"]:
if not aram and "Support" in champions[champion_id]["tags"]:
multiworld.get_location(champion_name + " - Get X Ward Score" , player).access_rule = lambda state, champion_name = champion_name: has_item(state, player, champion_name)
if "Support" not in champions[champion_id]["tags"]:
multiworld.get_location(champion_name + " - Get X Kills" , player).access_rule = lambda state, champion_name = champion_name: has_item(state, player, champion_name)
multiworld.get_location(champion_name + " - Get X Creep Score" , player).access_rule = lambda state, champion_name = champion_name: has_item(state, player, champion_name)
if not aram:
multiworld.get_location(champion_name + " - Get X Creep Score" , player).access_rule = lambda state, champion_name = champion_name: has_item(state, player, champion_name)

# Win condition.
multiworld.completion_condition[player] = lambda state: has_at_least(state, player, "LP", required_lp)
Loading