Files
dockipelago/worlds/trackmania/items.py
Jonathan Tinney 7971961166
Some checks failed
Analyze modified files / flake8 (push) Failing after 2m28s
Build / build-win (push) Has been cancelled
Build / build-ubuntu2204 (push) Has been cancelled
ctest / Test C++ ubuntu-latest (push) Has been cancelled
ctest / Test C++ windows-latest (push) Has been cancelled
Analyze modified files / mypy (push) Has been cancelled
Build and Publish Docker Images / Push Docker image to Docker Hub (push) Successful in 5m4s
Native Code Static Analysis / scan-build (push) Failing after 5m2s
type check / pyright (push) Successful in 1m7s
unittests / Test Python 3.11.2 ubuntu-latest (push) Failing after 16m23s
unittests / Test Python 3.12 ubuntu-latest (push) Failing after 28m19s
unittests / Test Python 3.13 ubuntu-latest (push) Failing after 14m49s
unittests / Test hosting with 3.13 on ubuntu-latest (push) Successful in 5m0s
unittests / Test Python 3.13 macos-latest (push) Has been cancelled
unittests / Test Python 3.11 windows-latest (push) Has been cancelled
unittests / Test Python 3.13 windows-latest (push) Has been cancelled
add schedule I, sonic 1/frontiers/heroes, spirit island
2026-04-02 23:46:36 -07:00

161 lines
6.0 KiB
Python

from BaseClasses import Item, ItemClassification
from .data import base_id, base_filler_id, filler_item_names
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from . import TrackmaniaWorld
class TrackmaniaItem(Item):
game = "Trackmania"
trackmania_items: dict[str,int] = {
"Bronze Medal" : base_id,
"Silver Medal" : base_id + 1,
"Gold Medal" : base_id + 2,
"Author Medal" : base_id + 3,
"Map Skip" : base_id + 4,
"PB Discount" : base_id + 5,
}
trackmania_item_groups = {
"Medals": {"Bronze Medal", "Silver Medal", "Gold Medal", "Author Medal"},
"Useful Items": {"Map Skip", "PB Discount"},
"Filler Items": set(filler_item_names)
}
#Item classification for most of our items is dependent on the target_time setting, so it cannot be hardcoded.
def determine_item_classification(world:"TrackmaniaWorld", name: str) -> ItemClassification:
target_time = world.options.target_time
match name:
case "Bronze Medal":
return ItemClassification.progression if target_time < 100 else ItemClassification.filler
case "Silver Medal":
return ItemClassification.progression if 100 <= target_time < 200 else ItemClassification.filler
case "Gold Medal":
return ItemClassification.progression if 200 <= target_time < 300 else ItemClassification.filler
case "Author Medal":
return ItemClassification.progression if 300 <= target_time else ItemClassification.filler
case "Map Skip":
return ItemClassification.useful
case "PB Discount":
return ItemClassification.useful
case _:
return ItemClassification.filler
def get_progression_medal(world: "TrackmaniaWorld") -> str:
match world.options.target_time:
case x if x < 100:
return "Bronze Medal"
case x if 100 <= x < 200:
return "Silver Medal"
case x if 200 <= x < 300:
return "Gold Medal"
case x if 300 <= x:
return "Author Medal"
case _:
return ""
def create_itempool(world: "TrackmaniaWorld") -> list[Item]:
itempool: list[Item] = []
total_map_count: int = 0
for series in world.series_data:
total_map_count += series["MapCount"]
total_item_slots: int = (total_map_count * get_locations_per_map(world))
spots_remaining: int = total_item_slots
#create medals for each map
if spots_remaining >= total_map_count:
itempool += create_medals(world, "Author Medal", 300, total_map_count)
spots_remaining = total_item_slots - len(itempool)
if spots_remaining >= total_map_count:
itempool += create_medals(world, "Gold Medal", 200, total_map_count)
spots_remaining = total_item_slots - len(itempool)
if spots_remaining >= total_map_count:
itempool += create_medals(world, "Silver Medal", 100, total_map_count)
spots_remaining = total_item_slots - len(itempool)
if spots_remaining >= total_map_count:
itempool += create_medals(world, "Bronze Medal", 0, total_map_count)
spots_remaining = total_item_slots - len(itempool)
if spots_remaining < 0:
spots_remaining = 0 # just in case
skip_count = min(round(float(spots_remaining) * (world.options.skip_percentage / 100.0)),spots_remaining)
itempool += create_items(world, "Map Skip", skip_count)
discount_count = min(round(float(spots_remaining) * (world.options.discount_percentage / 100.0)),spots_remaining-skip_count)
itempool += create_items(world, "PB Discount", discount_count)
filler_count = spots_remaining - skip_count - discount_count
for x in range(filler_count):
filler_name = get_filler_item_name(world)
itempool += create_items(world,filler_name, 1)
return itempool
def create_medals(world: "TrackmaniaWorld", medal: str, minimum_target_time:int, map_count: int) -> list[Item]:
if get_progression_medal(world) != medal and not get_medal_enabled(world, medal):
return []
if world.options.target_time >= minimum_target_time:
return create_items(world, medal, map_count)
return []
def create_item(world: "TrackmaniaWorld", name: str) -> Item:
item_id = world.item_name_to_id[name]
return TrackmaniaItem(name, determine_item_classification(world,name), item_id, world.player)
def create_items(world: "TrackmaniaWorld", name: str, count: int) -> list[Item]:
item_id = world.item_name_to_id[name]
itemlist: list[Item] = []
for i in range(count):
itemlist += [TrackmaniaItem(name, determine_item_classification(world,name), item_id, world.player)]
return itemlist
def get_filler_item_name(world: "TrackmaniaWorld") -> str:
return filler_item_names[world.random.randint(0, len(filler_item_names)-1)]
def get_medal_enabled(world: "TrackmaniaWorld", medal: str) -> bool:
match medal:
case "Bronze Medal":
return world.options.disable_bronze_medals <= 0
case "Silver Medal":
return world.options.disable_silver_medals <= 0
case "Gold Medal":
return world.options.disable_gold_medals <= 0
case "Author Medal":
return True
case _:
return True
def get_locations_per_map(world: "TrackmaniaWorld") -> int:
checks: int = 1
if world.options.target_time < 100 or world.options.disable_bronze_locations <= 0:
checks += 1
if world.options.target_time >=100 and world.options.disable_silver_locations <= 0:
checks += 1
if world.options.target_time >=200 and world.options.disable_gold_locations <= 0:
checks += 1
if world.options.target_time >=300 and world.options.disable_author_locations <= 0:
checks += 1
return checks
def build_items() -> dict[str,int]:
# hardcoded items
items: dict[str, int] = trackmania_items
# filler items
filler_id:int = base_filler_id
for x in range(len(filler_item_names)):
items[filler_item_names[x]] = filler_id
filler_id += 1
return items