Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
332ae91
Test Commit!
SerialBoxes Apr 10, 2025
4e39c55
Initial Setup of Options and World
SerialBoxes Apr 11, 2025
dea6a97
Merge branch 'ArchipelagoMW:main' into main
SerialBoxes Apr 11, 2025
9fc53c1
Added Regions & Rules, and got generation working correctly!
SerialBoxes Apr 12, 2025
693a531
Merge branch 'main' of https://github.com/SerialBoxes/ArchipelagoTrac…
SerialBoxes Apr 12, 2025
91a7531
Refactored Region Generation into its own file, started setting up th…
SerialBoxes Apr 13, 2025
f3106ab
Got a valid websocket connection working with Trackmania!!! Finally!
SerialBoxes Apr 15, 2025
635ff42
Merge branch 'ArchipelagoMW:main' into main
SerialBoxes Apr 15, 2025
d45e473
Small Refactor while testing
SerialBoxes Apr 16, 2025
8ad23fc
Merge remote-tracking branch 'origin/main'
SerialBoxes Apr 16, 2025
1e1a0bd
Add Yaml Options to Slot Data
SerialBoxes Apr 17, 2025
3cc2c85
Added Victory Event, Updated slot data format.
SerialBoxes Apr 19, 2025
37bed62
Added Reroll command, fixed bug with missing icon
SerialBoxes Apr 21, 2025
e7ae027
Added difficulties, TM2 tags, minor edits of docs, and sorted options…
SerialBoxes Apr 23, 2025
7c65e3a
Silly Filler Item names
SerialBoxes Apr 24, 2025
6a8bb4a
conformed to style guidelines, removed unused imports, and fixed rule…
SerialBoxes Apr 24, 2025
14d12af
Merge branch 'ArchipelagoMW:main' into main
SerialBoxes Apr 24, 2025
d6ddb12
Added "target time progressive item chance" option
SerialBoxes Apr 24, 2025
2485104
Merge remote-tracking branch 'origin/main'
SerialBoxes Apr 24, 2025
ddd34c8
Added Generation Tests
SerialBoxes Apr 28, 2025
ac6b4ea
replaced icon
SerialBoxes May 4, 2025
82bf736
Merge branch 'ArchipelagoMW:main' into main
SerialBoxes May 4, 2025
7110c28
No longer hardcoding binding IP, added more filler items
SerialBoxes May 6, 2025
9277fba
Merge branch 'ArchipelagoMW:main' into main
SerialBoxes May 6, 2025
38f9168
Added support for variable length series & different tags per series!
SerialBoxes May 7, 2025
dcb4611
Merge remote-tracking branch 'origin/main'
SerialBoxes May 7, 2025
2105fa5
Handle TMX search criteria generically, support custom series
KScl May 12, 2025
aa3e6ef
Remove a sneaky debug print
KScl May 12, 2025
7588854
Update based on feedback
KScl May 13, 2025
5c3c774
Allow customizing all series search criteria at once
KScl May 13, 2025
3e902ed
Map Tags -> Map Search Settings
KScl May 13, 2025
aa507a9
Merge pull request #1 from KScl/custom-series
SerialBoxes May 13, 2025
f78fe5e
Merge branch 'ArchipelagoMW:main' into main
SerialBoxes May 14, 2025
596c8a3
Default exclude Flagrush and Puzzle, add filler items
SerialBoxes May 14, 2025
2039b29
Add "Has Award" setting
SerialBoxes May 14, 2025
f55a6a1
Add support for "Has Award" option
SerialBoxes May 14, 2025
14ebc62
Forgot to update CustomSeries description
SerialBoxes May 14, 2025
27d197e
Add support for rerolling maps from the menu
SerialBoxes May 14, 2025
76763f2
rename re-roll parameters to be more user friendly
SerialBoxes May 14, 2025
27522d7
Add options to remove specific medal types from the randomizer
SerialBoxes May 14, 2025
4aa17f4
Support disabling medal locations
SerialBoxes May 14, 2025
e1bf971
Add support for disabling medals
SerialBoxes May 14, 2025
ad56ca2
Add support for disabling medals
SerialBoxes May 14, 2025
3e93a1a
Bug Fixes
SerialBoxes May 15, 2025
5378d2a
Merge pull request #2 from SerialBoxes/dev
SerialBoxes May 15, 2025
78942da
Website Fix
SerialBoxes May 15, 2025
8972fe1
Merge pull request #3 from SerialBoxes/dev
SerialBoxes May 15, 2025
b40390b
Fix test failures for series size settings, switch to using World.random
SerialBoxes May 17, 2025
9b29550
Add Target Time Discount Item
SerialBoxes May 19, 2025
6e4027b
Add Discount Item Percentage
SerialBoxes May 19, 2025
b2e8488
Change Theme, Remove PlandoItems references for now
SerialBoxes May 22, 2025
bc126e6
Merge branch 'ArchipelagoMW:main' into main
SerialBoxes May 22, 2025
012e38e
Rework Target Time Discount into PB Discount
SerialBoxes Jun 24, 2025
e037145
Merge branch 'ArchipelagoMW:main' into main
SerialBoxes Jun 24, 2025
7785184
Customize Map Length, Discount Amount, and Medal Items
SerialBoxes Sep 3, 2025
fae6685
Resync Items on Server Reconnect, Fix generating too many items for c…
SerialBoxes Sep 26, 2025
4b13f88
Merge branch 'ArchipelagoMW:main' into main
SerialBoxes Sep 26, 2025
c3184ec
Added Manifest File
SerialBoxes Sep 26, 2025
e8fb6c8
I can't get manifest files to compile :(
SerialBoxes Sep 27, 2025
4179e8b
MultiWorld type checking
SerialBoxes Sep 27, 2025
950dcad
Update Website, add current tags to template file
SerialBoxes Sep 30, 2025
3e03837
Merge branch 'ArchipelagoMW:main' into main
SerialBoxes Sep 30, 2025
a2cd30d
Added manifest file
SerialBoxes Sep 30, 2025
e573041
Add details to manifest
SerialBoxes Sep 30, 2025
391bd1e
Added Kaito to authors, small tidy-ups
SerialBoxes Oct 7, 2025
1d5b5fd
Added custom icon I drew!
SerialBoxes Oct 7, 2025
4db4e9e
Merge branch 'ArchipelagoMW:main' into main
SerialBoxes Oct 7, 2025
2abb7fe
Fix file endings, remove List and Dict imports, and reword PB Discoun…
SerialBoxes Oct 17, 2025
920b5e3
Apply suggestions from code review
SerialBoxes Oct 21, 2025
0c46bbe
Update required software and instructions.
SerialBoxes Oct 22, 2025
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
8 changes: 8 additions & 0 deletions TrackmaniaClient.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from worlds.trackmania.client import launch
import Utils
import ModuleUpdate
ModuleUpdate.update()

if __name__ == "__main__":
Utils.init_logging("TrackmaniaClient", exception_logger="Client")
launch()
Binary file added data/tmicon.ico
Binary file not shown.
Binary file added data/tmicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
142 changes: 142 additions & 0 deletions worlds/trackmania/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import os

from .options import TrackmaniaOptions, create_option_groups
from .items import build_items, trackmania_item_groups, create_itempool, create_item, get_filler_item_name
from .locations import build_locations
from .regions import create_regions
from .rules import set_rules
from worlds.AutoWorld import World, WebWorld
from worlds.LauncherComponents import Component, components, icon_paths, launch_subprocess, Type
from Utils import local_path
from BaseClasses import Item, Tutorial
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from BaseClasses import MultiWorld

def launch_client():
from .client import launch
launch_subprocess(launch, name="TrackmaniaClient")

icon_path : str = local_path('data', 'tmicon.ico')
icon: str = 'icon'

if os.path.exists(icon_path):
icon_paths['tmicon'] = icon_path
icon = 'tmicon'

components.append(Component("Trackmania Client", "TrackmaniaClient", func=launch_client,
component_type=Type.CLIENT, icon=icon))

class Webmania(WebWorld):
theme = "grassFlowers"
option_groups = create_option_groups()
tutorials = [Tutorial(
"Multiworld Setup Guide",
"A guide for setting up Trackmania to be played in Archipelago.",
"English",
"setup_en.md",
"setup/en",
["SerialBoxes"]
)]
rich_text_options_doc = True

class TrackmaniaWorld(World):
"""Trackmania is a mechanically deep arcade racing game that is easy to pick up and addicting to master!
Zoom through hundreds of thousands of user-made tracks as fast as you can!"""
game = "Trackmania" # name of the game/world
options_dataclass = TrackmaniaOptions # options the player can set
options: TrackmaniaOptions # typing hints for option results
web = Webmania()

item_name_to_id = build_items()
location_name_to_id = build_locations()

item_name_groups = trackmania_item_groups

def __init__(self, multiworld: "MultiWorld", player: int):
super().__init__(multiworld, player)
self.series_data: list = []

def create_item(self, name: str) -> Item:
return create_item(self, name)

def create_items(self):
self.multiworld.itempool += create_itempool(self)

#rules are also generated with the regions
def create_regions(self):
create_regions(self)

def set_rules(self):
set_rules(self)

def generate_early(self):
medal_percent: float = float(self.options.medal_requirement.value) / 100.0
base_search_criteria: dict = self.options.custom_series.value.get("all", {})

if self.options.series_minimum_map_number.value > self.options.series_maximum_map_number.value:
temp: int = self.options.series_minimum_map_number.value
self.options.series_minimum_map_number.value = self.options.series_maximum_map_number.value
self.options.series_maximum_map_number.value = temp

if self.options.map_min_length > self.options.map_max_length:
self.options.map_max_length.value = self.options.map_min_length.value + 1

for series in range(1, self.options.series_number.value + 1):
map_count: int = self.random.randint(self.options.series_minimum_map_number.value,
self.options.series_maximum_map_number.value)
if series == 1 and self.options.first_series_size.value > 0:
map_count = self.options.first_series_size.value

medals: int = round(map_count * medal_percent)
medals = max(1, min(medals, map_count)) # clamp between 1 and map_count

search_criteria: dict = base_search_criteria.copy()
search_criteria.update(self.options.custom_series.value.get(series, {}))

# Fill in global defaults and settings
if "map_tags" not in search_criteria:
tags: list = list(self.options.map_tags.value)
if self.options.random_series_tags > 0 and len(tags) > 1:
search_criteria["map_tags"] = [self.random.choice(tags)]
else:
search_criteria["map_tags"] = tags

if "map_etags" not in search_criteria:
search_criteria["map_etags"] = list(self.options.map_etags.value)

if "map_tags_inclusive" not in search_criteria:
search_criteria["map_tags_inclusive"] = self.options.map_tags_inclusive.value

if "difficulties" not in search_criteria:
search_criteria["difficulties"] = list(self.options.difficulties.value)

if "max_length" not in search_criteria:
search_criteria["max_length"] = self.options.map_max_length * 1000

if "min_length" not in search_criteria:
search_criteria["min_length"] = self.options.map_min_length * 1000

if "has_award" not in search_criteria:
search_criteria["has_award"] = self.options.has_award.value

values : dict = {"MedalTotal": medals,
"MapCount": map_count,
"SearchCriteria": search_criteria}
self.series_data.append(values)

def fill_slot_data(self) -> dict:
return {
"TargetTimeSetting": (float(self.options.target_time.value) / 100.0),
"DiscountAmount": (float(self.options.discount_amount) / 1000.0),
"SeriesNumber": self.options.series_number.value,
"DisableBronze": self.options.disable_bronze_locations.value,
"DisableSilver": self.options.disable_silver_locations.value,
"DisableGold": self.options.disable_gold_locations.value,
"DisableAuthor": self.options.disable_author_locations.value,
"SeriesData": self.series_data
}

def get_filler_item_name(self) -> str:
return get_filler_item_name(self)
6 changes: 6 additions & 0 deletions worlds/trackmania/archipelago.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"game": "Trackmania",
"authors": ["SerialBoxes","Kaito Sinclaire"],
"minimum_ap_version": "0.6.0",
"world_version": "1.3.1"
}
Loading