New Game: Faxanadu (#3059)
This commit is contained in:
parent
c97e4866dd
commit
6e5adc7abd
|
@ -76,6 +76,7 @@ Currently, the following games are supported:
|
|||
* Kingdom Hearts 1
|
||||
* Mega Man 2
|
||||
* Yacht Dice
|
||||
* Faxanadu
|
||||
|
||||
For setup and instructions check out our [tutorials page](https://archipelago.gg/tutorial/).
|
||||
Downloads can be found at [Releases](https://github.com/ArchipelagoMW/Archipelago/releases), including compiled
|
||||
|
|
|
@ -63,6 +63,9 @@
|
|||
# Factorio
|
||||
/worlds/factorio/ @Berserker66
|
||||
|
||||
# Faxanadu
|
||||
/worlds/faxanadu/ @Daivuk
|
||||
|
||||
# Final Fantasy Mystic Quest
|
||||
/worlds/ffmq/ @Alchav @wildham0
|
||||
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
from BaseClasses import ItemClassification
|
||||
from typing import List, Optional
|
||||
|
||||
|
||||
class ItemDef:
|
||||
def __init__(self,
|
||||
id: Optional[int],
|
||||
name: str,
|
||||
classification: ItemClassification,
|
||||
count: int,
|
||||
progression_count: int,
|
||||
prefill_location: Optional[str]):
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.classification = classification
|
||||
self.count = count
|
||||
self.progression_count = progression_count
|
||||
self.prefill_location = prefill_location
|
||||
|
||||
|
||||
items: List[ItemDef] = [
|
||||
ItemDef(400000, 'Progressive Sword', ItemClassification.progression, 4, 0, None),
|
||||
ItemDef(400001, 'Progressive Armor', ItemClassification.progression, 3, 0, None),
|
||||
ItemDef(400002, 'Progressive Shield', ItemClassification.useful, 4, 0, None),
|
||||
ItemDef(400003, 'Spring Elixir', ItemClassification.progression, 1, 0, None),
|
||||
ItemDef(400004, 'Mattock', ItemClassification.progression, 1, 0, None),
|
||||
ItemDef(400005, 'Unlock Wingboots', ItemClassification.progression, 1, 0, None),
|
||||
ItemDef(400006, 'Key Jack', ItemClassification.progression, 1, 0, None),
|
||||
ItemDef(400007, 'Key Queen', ItemClassification.progression, 1, 0, None),
|
||||
ItemDef(400008, 'Key King', ItemClassification.progression, 1, 0, None),
|
||||
ItemDef(400009, 'Key Joker', ItemClassification.progression, 1, 0, None),
|
||||
ItemDef(400010, 'Key Ace', ItemClassification.progression, 1, 0, None),
|
||||
ItemDef(400011, 'Ring of Ruby', ItemClassification.progression, 1, 0, None),
|
||||
ItemDef(400012, 'Ring of Dworf', ItemClassification.progression, 1, 0, None),
|
||||
ItemDef(400013, 'Demons Ring', ItemClassification.progression, 1, 0, None),
|
||||
ItemDef(400014, 'Black Onyx', ItemClassification.progression, 1, 0, None),
|
||||
ItemDef(None, 'Sky Spring Flow', ItemClassification.progression, 1, 0, 'Sky Spring'),
|
||||
ItemDef(None, 'Tower of Fortress Spring Flow', ItemClassification.progression, 1, 0, 'Tower of Fortress Spring'),
|
||||
ItemDef(None, 'Joker Spring Flow', ItemClassification.progression, 1, 0, 'Joker Spring'),
|
||||
ItemDef(400015, 'Deluge', ItemClassification.progression, 1, 0, None),
|
||||
ItemDef(400016, 'Thunder', ItemClassification.useful, 1, 0, None),
|
||||
ItemDef(400017, 'Fire', ItemClassification.useful, 1, 0, None),
|
||||
ItemDef(400018, 'Death', ItemClassification.useful, 1, 0, None),
|
||||
ItemDef(400019, 'Tilte', ItemClassification.useful, 1, 0, None),
|
||||
ItemDef(400020, 'Ring of Elf', ItemClassification.useful, 1, 0, None),
|
||||
ItemDef(400021, 'Magical Rod', ItemClassification.useful, 1, 0, None),
|
||||
ItemDef(400022, 'Pendant', ItemClassification.useful, 1, 0, None),
|
||||
ItemDef(400023, 'Hourglass', ItemClassification.filler, 6, 0, None),
|
||||
# We need at least 4 red potions for the Tower of Red Potion. Up to the player to save them up!
|
||||
ItemDef(400024, 'Red Potion', ItemClassification.filler, 15, 4, None),
|
||||
ItemDef(400025, 'Elixir', ItemClassification.filler, 4, 0, None),
|
||||
ItemDef(400026, 'Glove', ItemClassification.filler, 5, 0, None),
|
||||
ItemDef(400027, 'Ointment', ItemClassification.filler, 8, 0, None),
|
||||
ItemDef(400028, 'Poison', ItemClassification.trap, 13, 0, None),
|
||||
ItemDef(None, 'Killed Evil One', ItemClassification.progression, 1, 0, 'Evil One'),
|
||||
# Placeholder item so the game knows which shop slot to prefill wingboots
|
||||
ItemDef(400029, 'Wingboots', ItemClassification.useful, 0, 0, None),
|
||||
]
|
|
@ -0,0 +1,199 @@
|
|||
from typing import List, Optional
|
||||
|
||||
|
||||
class LocationType():
|
||||
world = 1 # Just standing there in the world
|
||||
hidden = 2 # Kill all monsters in the room to reveal, each "item room" counter tick.
|
||||
boss_reward = 3 # Kill a boss to reveal the item
|
||||
shop = 4 # Buy at a shop
|
||||
give = 5 # Given by an NPC
|
||||
spring = 6 # Activatable spring
|
||||
boss = 7 # Entity to kill to trigger the check
|
||||
|
||||
|
||||
class ItemType():
|
||||
unknown = 0 # Or don't care
|
||||
red_potion = 1
|
||||
|
||||
|
||||
class LocationDef:
|
||||
def __init__(self, id: Optional[int], name: str, region: str, type: int, original_item: int):
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.region = region
|
||||
self.type = type
|
||||
self.original_item = original_item
|
||||
|
||||
|
||||
locations: List[LocationDef] = [
|
||||
# Eolis
|
||||
LocationDef(400100, 'Eolis Guru', 'Eolis', LocationType.give, ItemType.unknown),
|
||||
LocationDef(400101, 'Eolis Key Jack', 'Eolis', LocationType.shop, ItemType.unknown),
|
||||
LocationDef(400102, 'Eolis Hand Dagger', 'Eolis', LocationType.shop, ItemType.unknown),
|
||||
LocationDef(400103, 'Eolis Red Potion', 'Eolis', LocationType.shop, ItemType.red_potion),
|
||||
LocationDef(400104, 'Eolis Elixir', 'Eolis', LocationType.shop, ItemType.unknown),
|
||||
LocationDef(400105, 'Eolis Deluge', 'Eolis', LocationType.shop, ItemType.unknown),
|
||||
|
||||
# Path to Apolune
|
||||
LocationDef(400106, 'Path to Apolune Magic Shield', 'Path to Apolune', LocationType.shop, ItemType.unknown),
|
||||
LocationDef(400107, 'Path to Apolune Death', 'Path to Apolune', LocationType.shop, ItemType.unknown),
|
||||
|
||||
# Apolune
|
||||
LocationDef(400108, 'Apolune Small Shield', 'Apolune', LocationType.shop, ItemType.unknown),
|
||||
LocationDef(400109, 'Apolune Hand Dagger', 'Apolune', LocationType.shop, ItemType.unknown),
|
||||
LocationDef(400110, 'Apolune Deluge', 'Apolune', LocationType.shop, ItemType.unknown),
|
||||
LocationDef(400111, 'Apolune Red Potion', 'Apolune', LocationType.shop, ItemType.red_potion),
|
||||
LocationDef(400112, 'Apolune Key Jack', 'Apolune', LocationType.shop, ItemType.unknown),
|
||||
|
||||
# Tower of Trunk
|
||||
LocationDef(400113, 'Tower of Trunk Hidden Mattock', 'Tower of Trunk', LocationType.hidden, ItemType.unknown),
|
||||
LocationDef(400114, 'Tower of Trunk Hidden Hourglass', 'Tower of Trunk', LocationType.hidden, ItemType.unknown),
|
||||
LocationDef(400115, 'Tower of Trunk Boss Mattock', 'Tower of Trunk', LocationType.boss_reward, ItemType.unknown),
|
||||
|
||||
# Path to Forepaw
|
||||
LocationDef(400116, 'Path to Forepaw Hidden Red Potion', 'Path to Forepaw', LocationType.hidden, ItemType.red_potion),
|
||||
LocationDef(400117, 'Path to Forepaw Glove', 'Path to Forepaw', LocationType.world, ItemType.unknown),
|
||||
|
||||
# Forepaw
|
||||
LocationDef(400118, 'Forepaw Long Sword', 'Forepaw', LocationType.shop, ItemType.unknown),
|
||||
LocationDef(400119, 'Forepaw Studded Mail', 'Forepaw', LocationType.shop, ItemType.unknown),
|
||||
LocationDef(400120, 'Forepaw Small Shield', 'Forepaw', LocationType.shop, ItemType.unknown),
|
||||
LocationDef(400121, 'Forepaw Red Potion', 'Forepaw', LocationType.shop, ItemType.red_potion),
|
||||
LocationDef(400122, 'Forepaw Wingboots', 'Forepaw', LocationType.shop, ItemType.unknown),
|
||||
LocationDef(400123, 'Forepaw Key Jack', 'Forepaw', LocationType.shop, ItemType.unknown),
|
||||
LocationDef(400124, 'Forepaw Key Queen', 'Forepaw', LocationType.shop, ItemType.unknown),
|
||||
|
||||
# Trunk
|
||||
LocationDef(400125, 'Trunk Hidden Ointment', 'Trunk', LocationType.hidden, ItemType.unknown),
|
||||
LocationDef(400126, 'Trunk Hidden Red Potion', 'Trunk', LocationType.hidden, ItemType.red_potion),
|
||||
LocationDef(400127, 'Trunk Red Potion', 'Trunk', LocationType.world, ItemType.red_potion),
|
||||
LocationDef(None, 'Sky Spring', 'Trunk', LocationType.spring, ItemType.unknown),
|
||||
|
||||
# Joker Spring
|
||||
LocationDef(400128, 'Joker Spring Ruby Ring', 'Joker Spring', LocationType.give, ItemType.unknown),
|
||||
LocationDef(None, 'Joker Spring', 'Joker Spring', LocationType.spring, ItemType.unknown),
|
||||
|
||||
# Tower of Fortress
|
||||
LocationDef(400129, 'Tower of Fortress Poison 1', 'Tower of Fortress', LocationType.world, ItemType.unknown),
|
||||
LocationDef(400130, 'Tower of Fortress Poison 2', 'Tower of Fortress', LocationType.world, ItemType.unknown),
|
||||
LocationDef(400131, 'Tower of Fortress Hidden Wingboots', 'Tower of Fortress', LocationType.world, ItemType.unknown),
|
||||
LocationDef(400132, 'Tower of Fortress Ointment', 'Tower of Fortress', LocationType.world, ItemType.unknown),
|
||||
LocationDef(400133, 'Tower of Fortress Boss Wingboots', 'Tower of Fortress', LocationType.boss_reward, ItemType.unknown),
|
||||
LocationDef(400134, 'Tower of Fortress Elixir', 'Tower of Fortress', LocationType.world, ItemType.unknown),
|
||||
LocationDef(400135, 'Tower of Fortress Guru', 'Tower of Fortress', LocationType.give, ItemType.unknown),
|
||||
LocationDef(None, 'Tower of Fortress Spring', 'Tower of Fortress', LocationType.spring, ItemType.unknown),
|
||||
|
||||
# Path to Mascon
|
||||
LocationDef(400136, 'Path to Mascon Hidden Wingboots', 'Path to Mascon', LocationType.hidden, ItemType.unknown),
|
||||
|
||||
# Tower of Red Potion
|
||||
LocationDef(400137, 'Tower of Red Potion', 'Tower of Red Potion', LocationType.world, ItemType.red_potion),
|
||||
|
||||
# Mascon
|
||||
LocationDef(400138, 'Mascon Large Shield', 'Mascon', LocationType.shop, ItemType.unknown),
|
||||
LocationDef(400139, 'Mascon Thunder', 'Mascon', LocationType.shop, ItemType.unknown),
|
||||
LocationDef(400140, 'Mascon Mattock', 'Mascon', LocationType.shop, ItemType.unknown),
|
||||
LocationDef(400141, 'Mascon Red Potion', 'Mascon', LocationType.shop, ItemType.red_potion),
|
||||
LocationDef(400142, 'Mascon Key Jack', 'Mascon', LocationType.shop, ItemType.unknown),
|
||||
LocationDef(400143, 'Mascon Key Queen', 'Mascon', LocationType.shop, ItemType.unknown),
|
||||
|
||||
# Path to Victim
|
||||
LocationDef(400144, 'Misty Shop Death', 'Path to Victim', LocationType.shop, ItemType.unknown),
|
||||
LocationDef(400145, 'Misty Shop Hourglass', 'Path to Victim', LocationType.shop, ItemType.unknown),
|
||||
LocationDef(400146, 'Misty Shop Elixir', 'Path to Victim', LocationType.shop, ItemType.unknown),
|
||||
LocationDef(400147, 'Misty Shop Red Potion', 'Path to Victim', LocationType.shop, ItemType.red_potion),
|
||||
LocationDef(400148, 'Misty Doctor Office', 'Path to Victim', LocationType.hidden, ItemType.unknown),
|
||||
|
||||
# Tower of Suffer
|
||||
LocationDef(400149, 'Tower of Suffer Hidden Wingboots', 'Tower of Suffer', LocationType.hidden, ItemType.unknown),
|
||||
LocationDef(400150, 'Tower of Suffer Hidden Hourglass', 'Tower of Suffer', LocationType.hidden, ItemType.unknown),
|
||||
LocationDef(400151, 'Tower of Suffer Pendant', 'Tower of Suffer', LocationType.boss_reward, ItemType.unknown),
|
||||
|
||||
# Victim
|
||||
LocationDef(400152, 'Victim Full Plate', 'Victim', LocationType.shop, ItemType.unknown),
|
||||
LocationDef(400153, 'Victim Mattock', 'Victim', LocationType.shop, ItemType.unknown),
|
||||
LocationDef(400154, 'Victim Red Potion', 'Victim', LocationType.shop, ItemType.red_potion),
|
||||
LocationDef(400155, 'Victim Key King', 'Victim', LocationType.shop, ItemType.unknown),
|
||||
LocationDef(400156, 'Victim Key Queen', 'Victim', LocationType.shop, ItemType.unknown),
|
||||
LocationDef(400157, 'Victim Tavern', 'Mist', LocationType.give, ItemType.unknown),
|
||||
|
||||
# Mist
|
||||
LocationDef(400158, 'Mist Hidden Poison 1', 'Mist', LocationType.hidden, ItemType.unknown),
|
||||
LocationDef(400159, 'Mist Hidden Poison 2', 'Mist', LocationType.hidden, ItemType.unknown),
|
||||
LocationDef(400160, 'Mist Hidden Wingboots', 'Mist', LocationType.hidden, ItemType.unknown),
|
||||
LocationDef(400161, 'Misty Magic Hall', 'Mist', LocationType.give, ItemType.unknown),
|
||||
LocationDef(400162, 'Misty House', 'Mist', LocationType.give, ItemType.unknown),
|
||||
|
||||
# Useless Tower
|
||||
LocationDef(400163, 'Useless Tower', 'Useless Tower', LocationType.hidden, ItemType.unknown),
|
||||
|
||||
# Tower of Mist
|
||||
LocationDef(400164, 'Tower of Mist Hidden Ointment', 'Tower of Mist', LocationType.hidden, ItemType.unknown),
|
||||
LocationDef(400165, 'Tower of Mist Elixir', 'Tower of Mist', LocationType.world, ItemType.unknown),
|
||||
LocationDef(400166, 'Tower of Mist Black Onyx', 'Tower of Mist', LocationType.boss_reward, ItemType.unknown),
|
||||
|
||||
# Path to Conflate
|
||||
LocationDef(400167, 'Path to Conflate Hidden Ointment', 'Path to Conflate', LocationType.hidden, ItemType.unknown),
|
||||
LocationDef(400168, 'Path to Conflate Poison', 'Path to Conflate', LocationType.hidden, ItemType.unknown),
|
||||
|
||||
# Helm Branch
|
||||
LocationDef(400169, 'Helm Branch Hidden Glove', 'Helm Branch', LocationType.hidden, ItemType.unknown),
|
||||
LocationDef(400170, 'Helm Branch Battle Helmet', 'Helm Branch', LocationType.boss_reward, ItemType.unknown),
|
||||
|
||||
# Conflate
|
||||
LocationDef(400171, 'Conflate Giant Blade', 'Conflate', LocationType.shop, ItemType.unknown),
|
||||
LocationDef(400172, 'Conflate Magic Shield', 'Conflate', LocationType.shop, ItemType.unknown),
|
||||
LocationDef(400173, 'Conflate Wingboots', 'Conflate', LocationType.shop, ItemType.unknown),
|
||||
LocationDef(400174, 'Conflate Red Potion', 'Conflate', LocationType.shop, ItemType.red_potion),
|
||||
LocationDef(400175, 'Conflate Guru', 'Conflate', LocationType.give, ItemType.unknown),
|
||||
|
||||
# Branches
|
||||
LocationDef(400176, 'Branches Hidden Ointment', 'Branches', LocationType.hidden, ItemType.unknown),
|
||||
LocationDef(400177, 'Branches Poison', 'Branches', LocationType.world, ItemType.unknown),
|
||||
LocationDef(400178, 'Branches Hidden Mattock', 'Branches', LocationType.hidden, ItemType.unknown),
|
||||
LocationDef(400179, 'Branches Hidden Hourglass', 'Branches', LocationType.hidden, ItemType.unknown),
|
||||
|
||||
# Path to Daybreak
|
||||
LocationDef(400180, 'Path to Daybreak Hidden Wingboots 1', 'Path to Daybreak', LocationType.hidden, ItemType.unknown),
|
||||
LocationDef(400181, 'Path to Daybreak Magical Rod', 'Path to Daybreak', LocationType.world, ItemType.unknown),
|
||||
LocationDef(400182, 'Path to Daybreak Hidden Wingboots 2', 'Path to Daybreak', LocationType.hidden, ItemType.unknown),
|
||||
LocationDef(400183, 'Path to Daybreak Poison', 'Path to Daybreak', LocationType.world, ItemType.unknown),
|
||||
LocationDef(400184, 'Path to Daybreak Glove', 'Path to Daybreak', LocationType.world, ItemType.unknown),
|
||||
LocationDef(400185, 'Path to Daybreak Battle Suit', 'Path to Daybreak', LocationType.boss_reward, ItemType.unknown),
|
||||
|
||||
# Daybreak
|
||||
LocationDef(400186, 'Daybreak Tilte', 'Daybreak', LocationType.shop, ItemType.unknown),
|
||||
LocationDef(400187, 'Daybreak Giant Blade', 'Daybreak', LocationType.shop, ItemType.unknown),
|
||||
LocationDef(400188, 'Daybreak Red Potion', 'Daybreak', LocationType.shop, ItemType.red_potion),
|
||||
LocationDef(400189, 'Daybreak Key King', 'Daybreak', LocationType.shop, ItemType.unknown),
|
||||
LocationDef(400190, 'Daybreak Key Queen', 'Daybreak', LocationType.shop, ItemType.unknown),
|
||||
|
||||
# Dartmoor Castle
|
||||
LocationDef(400191, 'Dartmoor Castle Hidden Hourglass', 'Dartmoor Castle', LocationType.hidden, ItemType.unknown),
|
||||
LocationDef(400192, 'Dartmoor Castle Hidden Red Potion', 'Dartmoor Castle', LocationType.hidden, ItemType.red_potion),
|
||||
|
||||
# Dartmoor
|
||||
LocationDef(400193, 'Dartmoor Giant Blade', 'Dartmoor', LocationType.shop, ItemType.unknown),
|
||||
LocationDef(400194, 'Dartmoor Red Potion', 'Dartmoor', LocationType.shop, ItemType.red_potion),
|
||||
LocationDef(400195, 'Dartmoor Key King', 'Dartmoor', LocationType.shop, ItemType.unknown),
|
||||
|
||||
# Fraternal Castle
|
||||
LocationDef(400196, 'Fraternal Castle Hidden Ointment', 'Fraternal Castle', LocationType.hidden, ItemType.unknown),
|
||||
LocationDef(400197, 'Fraternal Castle Shop Hidden Ointment', 'Fraternal Castle', LocationType.hidden, ItemType.unknown),
|
||||
LocationDef(400198, 'Fraternal Castle Poison 1', 'Fraternal Castle', LocationType.world, ItemType.unknown),
|
||||
LocationDef(400199, 'Fraternal Castle Poison 2', 'Fraternal Castle', LocationType.world, ItemType.unknown),
|
||||
LocationDef(400200, 'Fraternal Castle Poison 3', 'Fraternal Castle', LocationType.world, ItemType.unknown),
|
||||
# LocationDef(400201, 'Fraternal Castle Red Potion', 'Fraternal Castle', LocationType.world, ItemType.red_potion), # This location is inaccessible. Keeping commented for context.
|
||||
LocationDef(400202, 'Fraternal Castle Hidden Hourglass', 'Fraternal Castle', LocationType.hidden, ItemType.unknown),
|
||||
LocationDef(400203, 'Fraternal Castle Dragon Slayer', 'Fraternal Castle', LocationType.boss_reward, ItemType.unknown),
|
||||
LocationDef(400204, 'Fraternal Castle Guru', 'Fraternal Castle', LocationType.give, ItemType.unknown),
|
||||
|
||||
# Evil Fortress
|
||||
LocationDef(400205, 'Evil Fortress Ointment', 'Evil Fortress', LocationType.world, ItemType.unknown),
|
||||
LocationDef(400206, 'Evil Fortress Poison 1', 'Evil Fortress', LocationType.world, ItemType.unknown),
|
||||
LocationDef(400207, 'Evil Fortress Glove', 'Evil Fortress', LocationType.world, ItemType.unknown),
|
||||
LocationDef(400208, 'Evil Fortress Poison 2', 'Evil Fortress', LocationType.world, ItemType.unknown),
|
||||
LocationDef(400209, 'Evil Fortress Poison 3', 'Evil Fortress', LocationType.world, ItemType.unknown),
|
||||
LocationDef(400210, 'Evil Fortress Hidden Glove', 'Evil Fortress', LocationType.hidden, ItemType.unknown),
|
||||
LocationDef(None, 'Evil One', 'Evil Fortress', LocationType.boss, ItemType.unknown),
|
||||
]
|
|
@ -0,0 +1,107 @@
|
|||
from Options import PerGameCommonOptions, Toggle, DefaultOnToggle, StartInventoryPool, Choice
|
||||
from dataclasses import dataclass
|
||||
|
||||
|
||||
class KeepShopRedPotions(Toggle):
|
||||
"""
|
||||
Prevents the Shop's Red Potions from being shuffled. Those locations
|
||||
will have purchasable Red Potion as usual for their usual price.
|
||||
"""
|
||||
display_name = "Keep Shop Red Potions"
|
||||
|
||||
|
||||
class IncludePendant(Toggle):
|
||||
"""
|
||||
Pendant is an item that boosts your attack power permanently when picked up.
|
||||
However, due to a programming error in the original game, it has the reverse
|
||||
effect. You start with the Pendant power, and lose it when picking
|
||||
it up. So this item is essentially a trap.
|
||||
There is a setting in the client to reverse the effect back to its original intend.
|
||||
This could be used in conjunction with this option to increase or lower difficulty.
|
||||
"""
|
||||
display_name = "Include Pendant"
|
||||
|
||||
|
||||
class IncludePoisons(DefaultOnToggle):
|
||||
"""
|
||||
Whether or not to include Poison Potions in the pool of items. Including them
|
||||
effectively turn them into traps in multiplayer.
|
||||
"""
|
||||
display_name = "Include Poisons"
|
||||
|
||||
|
||||
class RequireDragonSlayer(Toggle):
|
||||
"""
|
||||
Requires the Dragon Slayer to be available before fighting the final boss is required.
|
||||
Turning this on will turn Progressive Shields into progression items.
|
||||
|
||||
This setting does not force you to use Dragon Slayer to kill the final boss.
|
||||
Instead, it ensures that you will have the Dragon Slayer and be able to equip
|
||||
it before you are expected to beat the final boss.
|
||||
"""
|
||||
display_name = "Require Dragon Slayer"
|
||||
|
||||
|
||||
class RandomMusic(Toggle):
|
||||
"""
|
||||
All levels' music is shuffled. Except the title screen because it's finite.
|
||||
This is an aesthetic option and doesn't affect gameplay.
|
||||
"""
|
||||
display_name = "Random Musics"
|
||||
|
||||
|
||||
class RandomSound(Toggle):
|
||||
"""
|
||||
All sounds are shuffled.
|
||||
This is an aesthetic option and doesn't affect gameplay.
|
||||
"""
|
||||
display_name = "Random Sounds"
|
||||
|
||||
|
||||
class RandomNPC(Toggle):
|
||||
"""
|
||||
NPCs and their portraits are shuffled.
|
||||
This is an aesthetic option and doesn't affect gameplay.
|
||||
"""
|
||||
display_name = "Random NPCs"
|
||||
|
||||
|
||||
class RandomMonsters(Choice):
|
||||
"""
|
||||
Choose how monsters are randomized.
|
||||
"Vanilla": No randomization
|
||||
"Level Shuffle": Monsters are shuffled within a level
|
||||
"Level Random": Monsters are picked randomly, balanced based on the ratio of the current level
|
||||
"World Shuffle": Monsters are shuffled across the entire world
|
||||
"World Random": Monsters are picked randomly, balanced based on the ratio of the entire world
|
||||
"Chaotic": Completely random, except big vs small ratio is kept. Big are mini-bosses.
|
||||
"""
|
||||
display_name = "Random Monsters"
|
||||
option_vanilla = 0
|
||||
option_level_shuffle = 1
|
||||
option_level_random = 2
|
||||
option_world_shuffle = 3
|
||||
option_world_random = 4
|
||||
option_chaotic = 5
|
||||
default = 0
|
||||
|
||||
|
||||
class RandomRewards(Toggle):
|
||||
"""
|
||||
Monsters drops are shuffled.
|
||||
"""
|
||||
display_name = "Random Rewards"
|
||||
|
||||
|
||||
@dataclass
|
||||
class FaxanaduOptions(PerGameCommonOptions):
|
||||
start_inventory_from_pool: StartInventoryPool
|
||||
keep_shop_red_potions: KeepShopRedPotions
|
||||
include_pendant: IncludePendant
|
||||
include_poisons: IncludePoisons
|
||||
require_dragon_slayer: RequireDragonSlayer
|
||||
random_musics: RandomMusic
|
||||
random_sounds: RandomSound
|
||||
random_npcs: RandomNPC
|
||||
random_monsters: RandomMonsters
|
||||
random_rewards: RandomRewards
|
|
@ -0,0 +1,66 @@
|
|||
from BaseClasses import Region
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from . import FaxanaduWorld
|
||||
|
||||
|
||||
def create_region(name, player, multiworld):
|
||||
region = Region(name, player, multiworld)
|
||||
multiworld.regions.append(region)
|
||||
return region
|
||||
|
||||
|
||||
def create_regions(faxanadu_world: "FaxanaduWorld"):
|
||||
player = faxanadu_world.player
|
||||
multiworld = faxanadu_world.multiworld
|
||||
|
||||
# Create regions
|
||||
menu = create_region("Menu", player, multiworld)
|
||||
eolis = create_region("Eolis", player, multiworld)
|
||||
path_to_apolune = create_region("Path to Apolune", player, multiworld)
|
||||
apolune = create_region("Apolune", player, multiworld)
|
||||
create_region("Tower of Trunk", player, multiworld)
|
||||
path_to_forepaw = create_region("Path to Forepaw", player, multiworld)
|
||||
forepaw = create_region("Forepaw", player, multiworld)
|
||||
trunk = create_region("Trunk", player, multiworld)
|
||||
create_region("Joker Spring", player, multiworld)
|
||||
create_region("Tower of Fortress", player, multiworld)
|
||||
path_to_mascon = create_region("Path to Mascon", player, multiworld)
|
||||
create_region("Tower of Red Potion", player, multiworld)
|
||||
mascon = create_region("Mascon", player, multiworld)
|
||||
path_to_victim = create_region("Path to Victim", player, multiworld)
|
||||
create_region("Tower of Suffer", player, multiworld)
|
||||
victim = create_region("Victim", player, multiworld)
|
||||
mist = create_region("Mist", player, multiworld)
|
||||
create_region("Useless Tower", player, multiworld)
|
||||
create_region("Tower of Mist", player, multiworld)
|
||||
path_to_conflate = create_region("Path to Conflate", player, multiworld)
|
||||
create_region("Helm Branch", player, multiworld)
|
||||
create_region("Conflate", player, multiworld)
|
||||
branches = create_region("Branches", player, multiworld)
|
||||
path_to_daybreak = create_region("Path to Daybreak", player, multiworld)
|
||||
daybreak = create_region("Daybreak", player, multiworld)
|
||||
dartmoor_castle = create_region("Dartmoor Castle", player, multiworld)
|
||||
create_region("Dartmoor", player, multiworld)
|
||||
create_region("Fraternal Castle", player, multiworld)
|
||||
create_region("Evil Fortress", player, multiworld)
|
||||
|
||||
# Create connections
|
||||
menu.add_exits(["Eolis"])
|
||||
eolis.add_exits(["Path to Apolune"])
|
||||
path_to_apolune.add_exits(["Apolune"])
|
||||
apolune.add_exits(["Tower of Trunk", "Path to Forepaw"])
|
||||
path_to_forepaw.add_exits(["Forepaw"])
|
||||
forepaw.add_exits(["Trunk"])
|
||||
trunk.add_exits(["Joker Spring", "Tower of Fortress", "Path to Mascon"])
|
||||
path_to_mascon.add_exits(["Tower of Red Potion", "Mascon"])
|
||||
mascon.add_exits(["Path to Victim"])
|
||||
path_to_victim.add_exits(["Tower of Suffer", "Victim"])
|
||||
victim.add_exits(["Mist"])
|
||||
mist.add_exits(["Useless Tower", "Tower of Mist", "Path to Conflate"])
|
||||
path_to_conflate.add_exits(["Helm Branch", "Conflate", "Branches"])
|
||||
branches.add_exits(["Path to Daybreak"])
|
||||
path_to_daybreak.add_exits(["Daybreak"])
|
||||
daybreak.add_exits(["Dartmoor Castle"])
|
||||
dartmoor_castle.add_exits(["Dartmoor", "Fraternal Castle", "Evil Fortress"])
|
|
@ -0,0 +1,79 @@
|
|||
from typing import TYPE_CHECKING
|
||||
from worlds.generic.Rules import set_rule
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from . import FaxanaduWorld
|
||||
|
||||
|
||||
def can_buy_in_eolis(state, player):
|
||||
# Sword or Deluge so we can farm for gold.
|
||||
# Ring of Elf so we can get 1500 from the King.
|
||||
return state.has_any(["Progressive Sword", "Deluge", "Ring of Elf"], player)
|
||||
|
||||
|
||||
def has_any_magic(state, player):
|
||||
return state.has_any(["Deluge", "Thunder", "Fire", "Death", "Tilte"], player)
|
||||
|
||||
|
||||
def set_rules(faxanadu_world: "FaxanaduWorld"):
|
||||
player = faxanadu_world.player
|
||||
multiworld = faxanadu_world.multiworld
|
||||
|
||||
# Region rules
|
||||
set_rule(multiworld.get_entrance("Eolis -> Path to Apolune", player), lambda state:
|
||||
state.has_all(["Key Jack", "Progressive Sword"], player)) # You can't go far with magic only
|
||||
set_rule(multiworld.get_entrance("Apolune -> Tower of Trunk", player), lambda state: state.has("Key Jack", player))
|
||||
set_rule(multiworld.get_entrance("Apolune -> Path to Forepaw", player), lambda state: state.has("Mattock", player))
|
||||
set_rule(multiworld.get_entrance("Trunk -> Joker Spring", player), lambda state: state.has("Key Joker", player))
|
||||
set_rule(multiworld.get_entrance("Trunk -> Tower of Fortress", player), lambda state: state.has("Key Jack", player))
|
||||
set_rule(multiworld.get_entrance("Trunk -> Path to Mascon", player), lambda state:
|
||||
state.has_all(["Key Queen", "Ring of Ruby", "Sky Spring Flow", "Tower of Fortress Spring Flow", "Joker Spring Flow"], player) and
|
||||
state.has("Progressive Sword", player, 2))
|
||||
set_rule(multiworld.get_entrance("Path to Mascon -> Tower of Red Potion", player), lambda state:
|
||||
state.has("Key Queen", player) and
|
||||
state.has("Red Potion", player, 4)) # It's impossible to go through the tower of Red Potion without at least 1-2 potions. Give them 4 for good measure.
|
||||
set_rule(multiworld.get_entrance("Path to Victim -> Tower of Suffer", player), lambda state: state.has("Key Queen", player))
|
||||
set_rule(multiworld.get_entrance("Path to Victim -> Victim", player), lambda state: state.has("Unlock Wingboots", player))
|
||||
set_rule(multiworld.get_entrance("Mist -> Useless Tower", player), lambda state:
|
||||
state.has_all(["Key King", "Unlock Wingboots"], player))
|
||||
set_rule(multiworld.get_entrance("Mist -> Tower of Mist", player), lambda state: state.has("Key King", player))
|
||||
set_rule(multiworld.get_entrance("Mist -> Path to Conflate", player), lambda state: state.has("Key Ace", player))
|
||||
set_rule(multiworld.get_entrance("Path to Conflate -> Helm Branch", player), lambda state: state.has("Key King", player))
|
||||
set_rule(multiworld.get_entrance("Path to Conflate -> Branches", player), lambda state: state.has("Key King", player))
|
||||
set_rule(multiworld.get_entrance("Daybreak -> Dartmoor Castle", player), lambda state: state.has("Ring of Dworf", player))
|
||||
set_rule(multiworld.get_entrance("Dartmoor Castle -> Evil Fortress", player), lambda state: state.has("Demons Ring", player))
|
||||
|
||||
# Location rules
|
||||
set_rule(multiworld.get_location("Eolis Key Jack", player), lambda state: can_buy_in_eolis(state, player))
|
||||
set_rule(multiworld.get_location("Eolis Hand Dagger", player), lambda state: can_buy_in_eolis(state, player))
|
||||
set_rule(multiworld.get_location("Eolis Elixir", player), lambda state: can_buy_in_eolis(state, player))
|
||||
set_rule(multiworld.get_location("Eolis Deluge", player), lambda state: can_buy_in_eolis(state, player))
|
||||
set_rule(multiworld.get_location("Eolis Red Potion", player), lambda state: can_buy_in_eolis(state, player))
|
||||
set_rule(multiworld.get_location("Path to Apolune Magic Shield", player), lambda state: state.has("Key King", player)) # Mid-late cost, make sure we've progressed
|
||||
set_rule(multiworld.get_location("Path to Apolune Death", player), lambda state: state.has("Key Ace", player)) # Mid-late cost, make sure we've progressed
|
||||
set_rule(multiworld.get_location("Tower of Trunk Hidden Mattock", player), lambda state:
|
||||
# This is actually possible if the monster drop into the stairs and kill it with dagger. But it's a "pro move"
|
||||
state.has("Deluge", player, 1) or
|
||||
state.has("Progressive Sword", player, 2))
|
||||
set_rule(multiworld.get_location("Path to Forepaw Glove", player), lambda state:
|
||||
state.has_all(["Deluge", "Unlock Wingboots"], player))
|
||||
set_rule(multiworld.get_location("Trunk Red Potion", player), lambda state: state.has("Unlock Wingboots", player))
|
||||
set_rule(multiworld.get_location("Sky Spring", player), lambda state: state.has("Unlock Wingboots", player))
|
||||
set_rule(multiworld.get_location("Tower of Fortress Spring", player), lambda state: state.has("Spring Elixir", player))
|
||||
set_rule(multiworld.get_location("Tower of Fortress Guru", player), lambda state: state.has("Sky Spring Flow", player))
|
||||
set_rule(multiworld.get_location("Tower of Suffer Hidden Wingboots", player), lambda state:
|
||||
state.has("Deluge", player) or
|
||||
state.has("Progressive Sword", player, 2))
|
||||
set_rule(multiworld.get_location("Misty House", player), lambda state: state.has("Black Onyx", player))
|
||||
set_rule(multiworld.get_location("Misty Doctor Office", player), lambda state: has_any_magic(state, player))
|
||||
set_rule(multiworld.get_location("Conflate Guru", player), lambda state: state.has("Progressive Armor", player, 3))
|
||||
set_rule(multiworld.get_location("Branches Hidden Mattock", player), lambda state: state.has("Unlock Wingboots", player))
|
||||
set_rule(multiworld.get_location("Path to Daybreak Glove", player), lambda state: state.has("Unlock Wingboots", player))
|
||||
set_rule(multiworld.get_location("Dartmoor Castle Hidden Hourglass", player), lambda state: state.has("Unlock Wingboots", player))
|
||||
set_rule(multiworld.get_location("Dartmoor Castle Hidden Red Potion", player), lambda state: has_any_magic(state, player))
|
||||
set_rule(multiworld.get_location("Fraternal Castle Guru", player), lambda state: state.has("Progressive Sword", player, 4))
|
||||
set_rule(multiworld.get_location("Fraternal Castle Shop Hidden Ointment", player), lambda state: has_any_magic(state, player))
|
||||
|
||||
if faxanadu_world.options.require_dragon_slayer.value:
|
||||
set_rule(multiworld.get_location("Evil One", player), lambda state:
|
||||
state.has_all_counts({"Progressive Sword": 4, "Progressive Armor": 3, "Progressive Shield": 4}, player))
|
|
@ -0,0 +1,190 @@
|
|||
from typing import Any, Dict, List
|
||||
|
||||
from BaseClasses import Item, Location, Tutorial, ItemClassification, MultiWorld
|
||||
from worlds.AutoWorld import WebWorld, World
|
||||
from . import Items, Locations, Regions, Rules
|
||||
from .Options import FaxanaduOptions
|
||||
from worlds.generic.Rules import set_rule
|
||||
|
||||
|
||||
DAXANADU_VERSION = "0.3.0"
|
||||
|
||||
|
||||
class FaxanaduLocation(Location):
|
||||
game: str = "Faxanadu"
|
||||
|
||||
|
||||
class FaxanaduItem(Item):
|
||||
game: str = "Faxanadu"
|
||||
|
||||
|
||||
class FaxanaduWeb(WebWorld):
|
||||
tutorials = [Tutorial(
|
||||
"Multiworld Setup Guide",
|
||||
"A guide to setting up the Faxanadu randomizer connected to an Archipelago Multiworld",
|
||||
"English",
|
||||
"setup_en.md",
|
||||
"setup/en",
|
||||
["Daivuk"]
|
||||
)]
|
||||
theme = "dirt"
|
||||
|
||||
|
||||
class FaxanaduWorld(World):
|
||||
"""
|
||||
Faxanadu is an action role-playing platform video game developed by Hudson Soft for the Nintendo Entertainment System
|
||||
"""
|
||||
options_dataclass = FaxanaduOptions
|
||||
options: FaxanaduOptions
|
||||
game = "Faxanadu"
|
||||
web = FaxanaduWeb()
|
||||
|
||||
item_name_to_id = {item.name: item.id for item in Items.items if item.id is not None}
|
||||
item_name_to_item = {item.name: item for item in Items.items}
|
||||
location_name_to_id = {loc.name: loc.id for loc in Locations.locations if loc.id is not None}
|
||||
|
||||
def __init__(self, world: MultiWorld, player: int):
|
||||
self.filler_ratios: Dict[str, int] = {}
|
||||
|
||||
super().__init__(world, player)
|
||||
|
||||
def create_regions(self):
|
||||
Regions.create_regions(self)
|
||||
|
||||
# Add locations into regions
|
||||
for region in self.multiworld.get_regions(self.player):
|
||||
for loc in [location for location in Locations.locations if location.region == region.name]:
|
||||
location = FaxanaduLocation(self.player, loc.name, loc.id, region)
|
||||
|
||||
# In Faxanadu, Poison hurts you when picked up. It makes no sense to sell them in shops
|
||||
if loc.type == Locations.LocationType.shop:
|
||||
location.item_rule = lambda item, player=self.player: not (player == item.player and item.name == "Poison")
|
||||
|
||||
region.locations.append(location)
|
||||
|
||||
def set_rules(self):
|
||||
Rules.set_rules(self)
|
||||
self.multiworld.completion_condition[self.player] = lambda state: state.has("Killed Evil One", self.player)
|
||||
|
||||
def create_item(self, name: str) -> FaxanaduItem:
|
||||
item: Items.ItemDef = self.item_name_to_item[name]
|
||||
return FaxanaduItem(name, item.classification, item.id, self.player)
|
||||
|
||||
# Returns how many red potions were prefilled into shops
|
||||
def prefill_shop_red_potions(self) -> int:
|
||||
red_potion_in_shop_count = 0
|
||||
if self.options.keep_shop_red_potions:
|
||||
red_potion_item = self.item_name_to_item["Red Potion"]
|
||||
red_potion_shop_locations = [
|
||||
loc
|
||||
for loc in Locations.locations
|
||||
if loc.type == Locations.LocationType.shop and loc.original_item == Locations.ItemType.red_potion
|
||||
]
|
||||
for loc in red_potion_shop_locations:
|
||||
location = self.get_location(loc.name)
|
||||
location.place_locked_item(FaxanaduItem(red_potion_item.name, red_potion_item.classification, red_potion_item.id, self.player))
|
||||
red_potion_in_shop_count += 1
|
||||
return red_potion_in_shop_count
|
||||
|
||||
def put_wingboot_in_shop(self, shops, region_name):
|
||||
item = self.item_name_to_item["Wingboots"]
|
||||
shop = shops.pop(region_name)
|
||||
slot = self.random.randint(0, len(shop) - 1)
|
||||
loc = shop[slot]
|
||||
location = self.get_location(loc.name)
|
||||
location.place_locked_item(FaxanaduItem(item.name, item.classification, item.id, self.player))
|
||||
|
||||
# Put a rule right away that we need to have to unlocked.
|
||||
set_rule(location, lambda state: state.has("Unlock Wingboots", self.player))
|
||||
|
||||
# Returns how many wingboots were prefilled into shops
|
||||
def prefill_shop_wingboots(self) -> int:
|
||||
# Collect shops
|
||||
shops: Dict[str, List[Locations.LocationDef]] = {}
|
||||
for loc in Locations.locations:
|
||||
if loc.type == Locations.LocationType.shop:
|
||||
if self.options.keep_shop_red_potions and loc.original_item == Locations.ItemType.red_potion:
|
||||
continue # Don't override our red potions
|
||||
shops.setdefault(loc.region, []).append(loc)
|
||||
|
||||
shop_count = len(shops)
|
||||
wingboots_count = round(shop_count / 2.5) # On 10 shops, we should have about 4 shops with wingboots
|
||||
|
||||
# At least one should be in the first 4 shops. Because we require wingboots to progress past that point.
|
||||
must_have_regions = [region for i, region in enumerate(shops) if i < 4]
|
||||
self.put_wingboot_in_shop(shops, self.random.choice(must_have_regions))
|
||||
|
||||
# Fill in the rest randomly in remaining shops
|
||||
for i in range(wingboots_count - 1): # -1 because we added one already
|
||||
region = self.random.choice(list(shops.keys()))
|
||||
self.put_wingboot_in_shop(shops, region)
|
||||
|
||||
return wingboots_count
|
||||
|
||||
def create_items(self) -> None:
|
||||
itempool: List[FaxanaduItem] = []
|
||||
|
||||
# Prefill red potions in shops if option is set
|
||||
red_potion_in_shop_count = self.prefill_shop_red_potions()
|
||||
|
||||
# Prefill wingboots in shops
|
||||
wingboots_in_shop_count = self.prefill_shop_wingboots()
|
||||
|
||||
# Create the item pool, excluding fillers.
|
||||
prefilled_count = red_potion_in_shop_count + wingboots_in_shop_count
|
||||
for item in Items.items:
|
||||
# Ignore pendant if turned off
|
||||
if item.name == "Pendant" and not self.options.include_pendant:
|
||||
continue
|
||||
|
||||
# ignore fillers for now, we will fill them later
|
||||
if item.classification in [ItemClassification.filler, ItemClassification.trap] and \
|
||||
item.progression_count == 0:
|
||||
continue
|
||||
|
||||
prefill_loc = None
|
||||
if item.prefill_location:
|
||||
prefill_loc = self.get_location(item.prefill_location)
|
||||
|
||||
# if require dragon slayer is turned on, we need progressive shields to be progression
|
||||
item_classification = item.classification
|
||||
if self.options.require_dragon_slayer and item.name == "Progressive Shield":
|
||||
item_classification = ItemClassification.progression
|
||||
|
||||
if prefill_loc:
|
||||
prefill_loc.place_locked_item(FaxanaduItem(item.name, item_classification, item.id, self.player))
|
||||
prefilled_count += 1
|
||||
else:
|
||||
for i in range(item.count - item.progression_count):
|
||||
itempool.append(FaxanaduItem(item.name, item_classification, item.id, self.player))
|
||||
for i in range(item.progression_count):
|
||||
itempool.append(FaxanaduItem(item.name, ItemClassification.progression, item.id, self.player))
|
||||
|
||||
# Set up filler ratios
|
||||
self.filler_ratios = {
|
||||
item.name: item.count
|
||||
for item in Items.items
|
||||
if item.classification in [ItemClassification.filler, ItemClassification.trap]
|
||||
}
|
||||
|
||||
# If red potions are locked in shops, remove the count from the ratio.
|
||||
self.filler_ratios["Red Potion"] -= red_potion_in_shop_count
|
||||
|
||||
# Remove poisons if not desired
|
||||
if not self.options.include_poisons:
|
||||
self.filler_ratios["Poison"] = 0
|
||||
|
||||
# Randomly add fillers to the pool with ratios based on og game occurrence counts.
|
||||
filler_count = len(Locations.locations) - len(itempool) - prefilled_count
|
||||
for i in range(filler_count):
|
||||
itempool.append(self.create_item(self.get_filler_item_name()))
|
||||
|
||||
self.multiworld.itempool += itempool
|
||||
|
||||
def get_filler_item_name(self) -> str:
|
||||
return self.random.choices(list(self.filler_ratios.keys()), weights=list(self.filler_ratios.values()))[0]
|
||||
|
||||
def fill_slot_data(self) -> Dict[str, Any]:
|
||||
slot_data = self.options.as_dict("keep_shop_red_potions", "random_musics", "random_sounds", "random_npcs", "random_monsters", "random_rewards")
|
||||
slot_data["daxanadu_version"] = DAXANADU_VERSION
|
||||
return slot_data
|
|
@ -0,0 +1,27 @@
|
|||
# Faxanadu
|
||||
|
||||
## Where is the settings page?
|
||||
|
||||
The [player options page](../player-options) contains the options needed to configure your game session.
|
||||
|
||||
## What does randomization do to this game?
|
||||
|
||||
All game items collected in the map, shops, and boss drops are randomized.
|
||||
|
||||
Keys are unique. Once you get the Jack Key, you can open all Jack doors; the key stays in your inventory.
|
||||
|
||||
Wingboots are randomized across shops only. They are LOCKED and cannot be bought until you get the item that unlocks them.
|
||||
|
||||
Normal Elixirs don't revive the tower spring. A new item, Spring Elixir, is necessary. This new item is unique.
|
||||
|
||||
## What is the goal?
|
||||
|
||||
The goal is to kill the Evil One.
|
||||
|
||||
## What is a "check" in The Faxanadu?
|
||||
|
||||
Shop items, item locations in the world, boss drops, and secret items.
|
||||
|
||||
## What "items" can you unlock in Faxanadu?
|
||||
|
||||
Keys, Armors, Weapons, Potions, Shields, Magics, Poisons, Gloves, etc.
|
|
@ -0,0 +1,32 @@
|
|||
# Faxanadu Randomizer Setup
|
||||
|
||||
## Required Software
|
||||
|
||||
- [Daxanadu](https://github.com/Daivuk/Daxanadu/releases/)
|
||||
- Faxanadu ROM, English version
|
||||
|
||||
## Optional Software
|
||||
|
||||
- [ArchipelagoTextClient](https://github.com/ArchipelagoMW/Archipelago/releases)
|
||||
|
||||
## Installing Daxanadu
|
||||
1. Download [Daxanadu.zip](https://github.com/Daivuk/Daxanadu/releases/) and extract it.
|
||||
2. Copy your rom `Faxanadu (U).nes` into the newly extracted folder.
|
||||
|
||||
## Joining a MultiWorld Game
|
||||
|
||||
1. Launch Daxanadu.exe
|
||||
2. From the Main menu, go to the `ARCHIPELAGO` menu. Enter the server's address, slot name, and password. Then select `PLAY`.
|
||||
3. Enjoy!
|
||||
|
||||
To continue a game, follow the same connection steps.
|
||||
Connecting with a different seed won't erase your progress in other seeds.
|
||||
|
||||
## Archipelago Text Client
|
||||
|
||||
We recommend having Archipelago's Text Client open on the side to keep track of what items you receive and send.
|
||||
Daxanadu doesn't display messages. You'll only get popups when picking them up.
|
||||
|
||||
## Auto-Tracking
|
||||
|
||||
Daxanadu has an integrated tracker that can be toggled in the options.
|
Loading…
Reference in New Issue