RL: Rename Rogue Legacy Folder (#452)

* rename rogue legacy
"`rogue-legacy` is not a valid python module name"

* revert rename of the documentation file
This commit is contained in:
Doug Hoskisson
2022-07-06 14:18:28 -05:00
committed by GitHub
parent ab2b635a77
commit d76b41afe7
11 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,136 @@
import typing
from BaseClasses import Item
from .Names import ItemName
class ItemData(typing.NamedTuple):
code: typing.Optional[int]
progression: bool
quantity: int = 1
event: bool = False
class LegacyItem(Item):
game: str = "Rogue Legacy"
# Separate tables for each type of item.
vendors_table = {
ItemName.blacksmith: ItemData(90000, True),
ItemName.enchantress: ItemData(90001, True),
ItemName.architect: ItemData(90002, False),
}
static_classes_table = {
ItemName.knight: ItemData(90080, False),
ItemName.paladin: ItemData(90081, False),
ItemName.mage: ItemData(90082, False),
ItemName.archmage: ItemData(90083, False),
ItemName.barbarian: ItemData(90084, False),
ItemName.barbarian_king: ItemData(90085, False),
ItemName.knave: ItemData(90086, False),
ItemName.assassin: ItemData(90087, False),
ItemName.shinobi: ItemData(90088, False),
ItemName.hokage: ItemData(90089, False),
ItemName.miner: ItemData(90090, False),
ItemName.spelunker: ItemData(90091, False),
ItemName.lich: ItemData(90092, False),
ItemName.lich_king: ItemData(90093, False),
ItemName.spellthief: ItemData(90094, False),
ItemName.spellsword: ItemData(90095, False),
ItemName.dragon: ItemData(90096, False),
ItemName.traitor: ItemData(90097, False),
}
progressive_classes_table = {
ItemName.progressive_knight: ItemData(90003, False, 2),
ItemName.progressive_mage: ItemData(90004, False, 2),
ItemName.progressive_barbarian: ItemData(90005, False, 2),
ItemName.progressive_knave: ItemData(90006, False, 2),
ItemName.progressive_shinobi: ItemData(90007, False, 2),
ItemName.progressive_miner: ItemData(90008, False, 2),
ItemName.progressive_lich: ItemData(90009, False, 2),
ItemName.progressive_spellthief: ItemData(90010, False, 2),
}
configurable_skill_unlocks_table = {
ItemName.health: ItemData(90013, True, 15),
ItemName.mana: ItemData(90014, True, 15),
ItemName.attack: ItemData(90015, True, 15),
ItemName.magic_damage: ItemData(90016, True, 15),
ItemName.armor: ItemData(90017, True, 10),
ItemName.equip: ItemData(90018, True, 10),
ItemName.crit_chance: ItemData(90019, False, 5),
ItemName.crit_damage: ItemData(90020, False, 5),
}
skill_unlocks_table = {
ItemName.down_strike: ItemData(90021, False),
ItemName.gold_gain: ItemData(90022, False),
ItemName.potion_efficiency: ItemData(90023, False),
ItemName.invulnerability_time: ItemData(90024, False),
ItemName.mana_cost_down: ItemData(90025, False),
ItemName.death_defiance: ItemData(90026, False),
ItemName.haggling: ItemData(90027, False),
ItemName.random_children: ItemData(90028, False),
}
blueprints_table = {
ItemName.squire_blueprints: ItemData(90040, False),
ItemName.silver_blueprints: ItemData(90041, False),
ItemName.guardian_blueprints: ItemData(90042, False),
ItemName.imperial_blueprints: ItemData(90043, False),
ItemName.royal_blueprints: ItemData(90044, False),
ItemName.knight_blueprints: ItemData(90045, False),
ItemName.ranger_blueprints: ItemData(90046, False),
ItemName.sky_blueprints: ItemData(90047, False),
ItemName.dragon_blueprints: ItemData(90048, False),
ItemName.slayer_blueprints: ItemData(90049, False),
ItemName.blood_blueprints: ItemData(90050, False),
ItemName.sage_blueprints: ItemData(90051, False),
ItemName.retribution_blueprints: ItemData(90052, False),
ItemName.holy_blueprints: ItemData(90053, False),
ItemName.dark_blueprints: ItemData(90054, False),
}
progressive_blueprint_table = {
ItemName.progressive_blueprints: ItemData(90055, False),
}
runes_table = {
ItemName.vault_runes: ItemData(90060, False),
ItemName.sprint_runes: ItemData(90061, False),
ItemName.vampire_runes: ItemData(90062, False),
ItemName.sky_runes: ItemData(90063, False),
ItemName.siphon_runes: ItemData(90064, False),
ItemName.retaliation_runes: ItemData(90065, False),
ItemName.bounty_runes: ItemData(90066, False),
ItemName.haste_runes: ItemData(90067, False),
ItemName.curse_runes: ItemData(90068, False),
ItemName.grace_runes: ItemData(90069, False),
ItemName.balance_runes: ItemData(90070, False),
}
misc_items_table = {
ItemName.trip_stat_increase: ItemData(90030, False),
ItemName.gold_1000: ItemData(90031, False),
ItemName.gold_3000: ItemData(90032, False),
ItemName.gold_5000: ItemData(90033, False),
# ItemName.rage_trap: ItemData(90034, False),
}
# Complete item table.
item_table = {
**vendors_table,
**static_classes_table,
**progressive_classes_table,
**configurable_skill_unlocks_table,
**skill_unlocks_table,
**blueprints_table,
**progressive_blueprint_table,
**runes_table,
**misc_items_table,
}
lookup_id_to_name: typing.Dict[int, str] = {data.code: item_name for item_name, data in item_table.items() if data.code}

View File

@@ -0,0 +1,90 @@
import typing
from BaseClasses import Location
from .Names import LocationName
class LegacyLocation(Location):
game: str = "Rogue Legacy"
base_location_table = {
# Manor Renovations
LocationName.manor_ground_base: 91000,
LocationName.manor_main_base: 91001,
LocationName.manor_main_bottom_window: 91002,
LocationName.manor_main_top_window: 91003,
LocationName.manor_main_roof: 91004,
LocationName.manor_left_wing_base: 91005,
LocationName.manor_left_wing_window: 91006,
LocationName.manor_left_wing_roof: 91007,
LocationName.manor_left_big_base: 91008,
LocationName.manor_left_big_upper1: 91009,
LocationName.manor_left_big_upper2: 91010,
LocationName.manor_left_big_windows: 91011,
LocationName.manor_left_big_roof: 91012,
LocationName.manor_left_far_base: 91013,
LocationName.manor_left_far_roof: 91014,
LocationName.manor_left_extension: 91015,
LocationName.manor_left_tree1: 91016,
LocationName.manor_left_tree2: 91017,
LocationName.manor_right_wing_base: 91018,
LocationName.manor_right_wing_window: 91019,
LocationName.manor_right_wing_roof: 91020,
LocationName.manor_right_big_base: 91021,
LocationName.manor_right_big_upper: 91022,
LocationName.manor_right_big_roof: 91023,
LocationName.manor_right_high_base: 91024,
LocationName.manor_right_high_upper: 91025,
LocationName.manor_right_high_tower: 91026,
LocationName.manor_right_extension: 91027,
LocationName.manor_right_tree: 91028,
LocationName.manor_observatory_base: 91029,
LocationName.manor_observatory_scope: 91030,
# Boss Rewards
LocationName.boss_castle: 91100,
LocationName.boss_forest: 91102,
LocationName.boss_tower: 91104,
LocationName.boss_dungeon: 91106,
# Special Rooms
LocationName.special_jukebox: 91200,
LocationName.special_painting: 91201,
LocationName.special_cheapskate: 91202,
LocationName.special_carnival: 91203,
# Special Locations
LocationName.castle: None,
LocationName.garden: None,
LocationName.tower: None,
LocationName.dungeon: None,
LocationName.fountain: None,
}
diary_location_table = {f"{LocationName.diary} {i + 1}": i + 91300 for i in range(0, 25)}
fairy_chest_location_table = {
**{f"{LocationName.castle} - Fairy Chest {i + 1}": i + 91400 for i in range(0, 50)},
**{f"{LocationName.garden} - Fairy Chest {i + 1}": i + 91450 for i in range(0, 50)},
**{f"{LocationName.tower} - Fairy Chest {i + 1}": i + 91500 for i in range(0, 50)},
**{f"{LocationName.dungeon} - Fairy Chest {i + 1}": i + 91550 for i in range(0, 50)},
**{f"Fairy Chest {i + 1}": i + 92200 for i in range(0, 60)},
}
chest_location_table = {
**{f"{LocationName.castle} - Chest {i + 1}": i + 91600 for i in range(0, 100)},
**{f"{LocationName.garden} - Chest {i + 1}": i + 91700 for i in range(0, 100)},
**{f"{LocationName.tower} - Chest {i + 1}": i + 91800 for i in range(0, 100)},
**{f"{LocationName.dungeon} - Chest {i + 1}": i + 91900 for i in range(0, 100)},
**{f"Chest {i + 1}": i + 92000 for i in range(0, 120)},
}
location_table = {
**base_location_table,
**diary_location_table,
**fairy_chest_location_table,
**chest_location_table,
}
lookup_id_to_name: typing.Dict[int, str] = {id: name for name, _ in location_table.items()}

View File

@@ -0,0 +1,97 @@
# Vendor Definitions
blacksmith = "Blacksmith"
enchantress = "Enchantress"
architect = "Architect"
# Progressive Class Definitions
progressive_knight = "Progressive Knights"
progressive_mage = "Progressive Mages"
progressive_barbarian = "Progressive Barbarians"
progressive_knave = "Progressive Knaves"
progressive_shinobi = "Progressive Shinobis"
progressive_miner = "Progressive Miners"
progressive_lich = "Progressive Liches"
progressive_spellthief = "Progressive Spellthieves"
# Static Class Definitions
knight = "Knights"
paladin = "Paladins"
mage = "Mages"
archmage = "Archmages"
barbarian = "Barbarians"
barbarian_king = "Barbarian Kings"
knave = "Knaves"
assassin = "Assassins"
shinobi = "Shinobis"
hokage = "Hokages"
miner = "Miners"
spelunker = "Spelunkers"
lich = "Lichs"
lich_king = "Lich Kings"
spellthief = "Spellthieves"
spellsword = "Spellswords"
dragon = "Dragons"
traitor = "Traitors"
# Skill Unlock Definitions
health = "Health Up"
mana = "Mana Up"
attack = "Attack Up"
magic_damage = "Magic Damage Up"
armor = "Armor Up"
equip = "Equip Up"
crit_chance = "Crit Chance Up"
crit_damage = "Crit Damage Up"
down_strike = "Down Strike Up"
gold_gain = "Gold Gain Up"
potion_efficiency = "Potion Efficiency Up"
invulnerability_time = "Invulnerability Time Up"
mana_cost_down = "Mana Cost Down"
death_defiance = "Death Defiance"
haggling = "Haggling"
random_children = "Randomize Children"
# Misc. Definitions
trip_stat_increase = "Triple Stat Increase"
gold_1000 = "1000 Gold"
gold_3000 = "3000 Gold"
gold_5000 = "5000 Gold"
rage_trap = "Rage Trap"
# Blueprint Definitions
progressive_blueprints = "Progressive Blueprints"
squire_blueprints = "Squire Blueprints"
silver_blueprints = "Silver Blueprints"
guardian_blueprints = "Guardian Blueprints"
imperial_blueprints = "Imperial Blueprints"
royal_blueprints = "Royal Blueprints"
knight_blueprints = "Knight Blueprints"
ranger_blueprints = "Ranger Blueprints"
sky_blueprints = "Sky Blueprints"
dragon_blueprints = "Dragon Blueprints"
slayer_blueprints = "Slayer Blueprints"
blood_blueprints = "Blood Blueprints"
sage_blueprints = "Sage Blueprints"
retribution_blueprints = "Retribution Blueprints"
holy_blueprints = "Holy Blueprints"
dark_blueprints = "Dark Blueprints"
# Rune Definitions
vault_runes = "Vault Runes"
sprint_runes = "Sprint Runes"
vampire_runes = "Vampire Runes"
sky_runes = "Sky Runes"
siphon_runes = "Siphon Runes"
retaliation_runes = "Retaliation Runes"
bounty_runes = "Bounty Runes"
haste_runes = "Haste Runes"
curse_runes = "Curse Runes"
grace_runes = "Grace Runes"
balance_runes = "Balance Runes"
# Event Definitions
boss_castle = "Defeat Castle Hamson Boss"
boss_forest = "Defeat Forest Abkhazia Boss"
boss_tower = "Defeat The Maya Boss"
boss_dungeon = "Defeat The Land of Darkness Boss"
boss_fountain = "Defeat The Fountain"

View File

@@ -0,0 +1,55 @@
# Manor Piece Definitions
manor_ground_base = "Manor Renovation - Ground Road"
manor_main_base = "Manor Renovation - Main Base"
manor_main_bottom_window = "Manor Renovation - Main Bottom Window"
manor_main_top_window = "Manor Renovation - Main Top Window"
manor_main_roof = "Manor Renovation - Main Rooftop"
manor_left_wing_base = "Manor Renovation - Left Wing Base"
manor_left_wing_window = "Manor Renovation - Left Wing Window"
manor_left_wing_roof = "Manor Renovation - Left Wing Rooftop"
manor_left_big_base = "Manor Renovation - Left Big Base"
manor_left_big_upper1 = "Manor Renovation - Left Big Upper 1"
manor_left_big_upper2 = "Manor Renovation - Left Big Upper 2"
manor_left_big_windows = "Manor Renovation - Left Big Windows"
manor_left_big_roof = "Manor Renovation - Left Big Rooftop"
manor_left_far_base = "Manor Renovation - Left Far Base"
manor_left_far_roof = "Manor Renovation - Left Far Roof"
manor_left_extension = "Manor Renovation - Left Extension"
manor_left_tree1 = "Manor Renovation - Left Tree 1"
manor_left_tree2 = "Manor Renovation - Left Tree 2"
manor_right_wing_base = "Manor Renovation - Right Wing Base"
manor_right_wing_window = "Manor Renovation - Right Wing Window"
manor_right_wing_roof = "Manor Renovation - Right Wing Rooftop"
manor_right_big_base = "Manor Renovation - Right Big Base"
manor_right_big_upper = "Manor Renovation - Right Big Upper"
manor_right_big_roof = "Manor Renovation - Right Big Rooftop"
manor_right_high_base = "Manor Renovation - Right High Base"
manor_right_high_upper = "Manor Renovation - Right High Upper"
manor_right_high_tower = "Manor Renovation - Right High Tower"
manor_right_extension = "Manor Renovation - Right Extension"
manor_right_tree = "Manor Renovation - Right Tree"
manor_observatory_base = "Manor Renovation - Observatory Base"
manor_observatory_scope = "Manor Renovation - Observatory Telescope"
# Boss Chest Definitions
boss_castle = "Castle Hamson Boss"
boss_forest = "Forest Abkhazia Boss"
boss_tower = "The Maya Boss"
boss_dungeon = "The Land of Darkness Boss"
# Special Room Definitions
special_jukebox = "Jukebox"
special_painting = "Painting"
special_cheapskate = "Cheapskate Elf's Game"
special_carnival = "Carnival"
# Shorthand Definitions
diary = "Diary"
# Region Definitions
outside = "Outside Castle Hamson"
castle = "Castle Hamson"
garden = "Forest Abkhazia"
tower = "The Maya"
dungeon = "The Land of Darkness"
fountain = "Fountain Room"

View File

@@ -0,0 +1,374 @@
import typing
from Options import Choice, Range, Option, Toggle, DeathLink, DefaultOnToggle, OptionList, OptionSet
class StartingGender(Choice):
"""
Determines the gender of your initial 'Sir Lee' character.
"""
display_name = "Starting Gender"
option_sir = 0
option_lady = 1
alias_male = 0
alias_female = 1
default = "random"
class StartingClass(Choice):
"""
Determines the starting class of your initial 'Sir Lee' character.
"""
display_name = "Starting Class"
option_knight = 0
option_mage = 1
option_barbarian = 2
option_knave = 3
option_shinobi = 4
option_miner = 5
option_spellthief = 6
option_lich = 7
default = 0
class NewGamePlus(Choice):
"""
Puts the castle in new game plus mode which vastly increases enemy level, but increases gold gain by 50%. Not
recommended for those inexperienced to Rogue Legacy!
"""
display_name = "New Game Plus"
option_normal = 0
option_new_game_plus = 1
option_new_game_plus_2 = 2
alias_hard = 1
alias_brutal = 2
default = 0
class LevelScaling(Range):
"""
A percentage modifier for scaling enemy level as you continue throughout the castle. 100 means enemies will have
100% level scaling (normal). Setting this too high will result in enemies with absurdly high levels, you have been
warned.
"""
display_name = "Enemy Level Scaling Percentage"
range_start = 1
range_end = 300
default = 100
class FairyChestsPerZone(Range):
"""
Determines the number of Fairy Chests in a given zone that contain items. After these have been checked, only stat
bonuses can be found in Fairy Chests.
"""
display_name = "Fairy Chests Per Zone"
range_start = 5
range_end = 15
default = 5
class ChestsPerZone(Range):
"""
Determines the number of Non-Fairy Chests in a given zone that contain items. After these have been checked, only
gold or stat bonuses can be found in Chests.
"""
display_name = "Chests Per Zone"
range_start = 15
range_end = 30
default = 15
class UniversalFairyChests(Toggle):
"""
Determines if fairy chests should be combined into one pool instead of per zone, similar to Risk of Rain 2.
"""
display_name = "Universal Fairy Chests"
class UniversalChests(Toggle):
"""
Determines if non-fairy chests should be combined into one pool instead of per zone, similar to Risk of Rain 2.
"""
display_name = "Universal Non-Fairy Chests"
class Vendors(Choice):
"""
Determines where to place the Blacksmith and Enchantress unlocks in logic (or start with them unlocked).
"""
display_name = "Vendors"
option_start_unlocked = 0
option_early = 1
option_normal = 2
option_anywhere = 3
default = 1
class Architect(Choice):
"""
Determines where the Architect sits in the item pool.
"""
display_name = "Architect"
option_start_unlocked = 0
option_normal = 2
option_disabled = 3
default = 2
class ArchitectFee(Range):
"""
Determines how large of a percentage the architect takes from the player when utilizing his services. 100 means he
takes all your gold. 0 means his services are free.
"""
display_name = "Architect Fee Percentage"
range_start = 0
range_end = 100
default = 40
class DisableCharon(Toggle):
"""
Prevents Charon from taking your money when you re-enter the castle. Also removes Haggling from the Item Pool.
"""
display_name = "Disable Charon"
class RequirePurchasing(DefaultOnToggle):
"""
Determines where you will be required to purchase equipment and runes from the Blacksmith and Enchantress before
equipping them. If you disable require purchasing, Manor Renovations are scaled to take this into account.
"""
display_name = "Require Purchasing"
class ProgressiveBlueprints(Toggle):
"""
Instead of shuffling blueprints randomly into the pool, blueprint unlocks are progressively unlocked. You would get
Squire first, then Knight, etc., until finally Dark.
"""
display_name = "Progressive Blueprints"
class GoldGainMultiplier(Choice):
"""
Adjusts the multiplier for gaining gold from all sources.
"""
display_name = "Gold Gain Multiplier"
option_normal = 0
option_quarter = 1
option_half = 2
option_double = 3
option_quadruple = 4
default = 0
class NumberOfChildren(Range):
"""
Determines the number of offspring you can choose from on the lineage screen after a death.
"""
display_name = "Number of Children"
range_start = 1
range_end = 5
default = 3
class AdditionalNames(OptionList):
"""
Set of additional names your potential offspring can have. If Allow Default Names is disabled, this is the only list
of names your children can have. The first value will also be your initial character's name depending on Starting
Gender.
"""
display_name = "Additional Names"
class AllowDefaultNames(DefaultOnToggle):
"""
Determines if the default names defined in the vanilla game are allowed to be used. Warning: Your world will not
generate if the number of Additional Names defined is less than the Number of Children value.
"""
display_name = "Allow Default Names"
class CastleScaling(Range):
"""
Adjusts the scaling factor for how big a castle can be. Larger castles scale enemies quicker and also take longer
to generate. 100 means normal castle size.
"""
display_name = "Castle Size Scaling Percentage"
range_start = 50
range_end = 300
default = 100
class ChallengeBossKhidr(Choice):
"""
Determines if Neo Khidr replaces Khidr in their boss room.
"""
display_name = "Khidr"
option_vanilla = 0
option_challenge = 1
default = 0
class ChallengeBossAlexander(Choice):
"""
Determines if Alexander the IV replaces Alexander in their boss room.
"""
display_name = "Alexander"
option_vanilla = 0
option_challenge = 1
default = 0
class ChallengeBossLeon(Choice):
"""
Determines if Ponce de Freon replaces Ponce de Leon in their boss room.
"""
display_name = "Ponce de Leon"
option_vanilla = 0
option_challenge = 1
default = 0
class ChallengeBossHerodotus(Choice):
"""
Determines if Astrodotus replaces Herodotus in their boss room.
"""
display_name = "Herodotus"
option_vanilla = 0
option_challenge = 1
default = 0
class HealthUpPool(Range):
"""
Determines the number of Health Ups in the item pool.
"""
display_name = "Health Up Pool"
range_start = 0
range_end = 15
default = 15
class ManaUpPool(Range):
"""
Determines the number of Mana Ups in the item pool.
"""
display_name = "Mana Up Pool"
range_start = 0
range_end = 15
default = 15
class AttackUpPool(Range):
"""
Determines the number of Attack Ups in the item pool.
"""
display_name = "Attack Up Pool"
range_start = 0
range_end = 15
default = 15
class MagicDamageUpPool(Range):
"""
Determines the number of Magic Damage Ups in the item pool.
"""
display_name = "Magic Damage Up Pool"
range_start = 0
range_end = 15
default = 15
class ArmorUpPool(Range):
"""
Determines the number of Armor Ups in the item pool.
"""
display_name = "Armor Up Pool"
range_start = 0
range_end = 10
default = 10
class EquipUpPool(Range):
"""
Determines the number of Equip Ups in the item pool.
"""
display_name = "Equip Up Pool"
range_start = 0
range_end = 10
default = 10
class CritChanceUpPool(Range):
"""
Determines the number of Crit Chance Ups in the item pool.
"""
display_name = "Crit Chance Up Pool"
range_start = 0
range_end = 5
default = 5
class CritDamageUpPool(Range):
"""
Determines the number of Crit Damage Ups in the item pool.
"""
display_name = "Crit Damage Up Pool"
range_start = 0
range_end = 5
default = 5
class FreeDiaryOnGeneration(DefaultOnToggle):
"""
Allows the player to get a free diary check every time they regenerate the castle in the starting room.
"""
display_name = "Free Diary On Generation"
class AvailableClasses(OptionSet):
"""
List of classes that will be in the item pool to find. The upgraded form of the class will be added with it.
The upgraded form of your starting class will be available regardless.
"""
display_name = "Available Classes"
default = {"Knight", "Mage", "Barbarian", "Knave", "Shinobi", "Miner", "Spellthief", "Lich", "Dragon", "Traitor"}
valid_keys = {"Knight", "Mage", "Barbarian", "Knave", "Shinobi", "Miner", "Spellthief", "Lich", "Dragon", "Traitor"}
legacy_options: typing.Dict[str, type(Option)] = {
"starting_gender": StartingGender,
"starting_class": StartingClass,
"available_classes": AvailableClasses,
"new_game_plus": NewGamePlus,
"fairy_chests_per_zone": FairyChestsPerZone,
"chests_per_zone": ChestsPerZone,
"universal_fairy_chests": UniversalFairyChests,
"universal_chests": UniversalChests,
"vendors": Vendors,
"architect": Architect,
"architect_fee": ArchitectFee,
"disable_charon": DisableCharon,
"require_purchasing": RequirePurchasing,
"progressive_blueprints": ProgressiveBlueprints,
"gold_gain_multiplier": GoldGainMultiplier,
"number_of_children": NumberOfChildren,
"free_diary_on_generation": FreeDiaryOnGeneration,
"khidr": ChallengeBossKhidr,
"alexander": ChallengeBossAlexander,
"leon": ChallengeBossLeon,
"herodotus": ChallengeBossHerodotus,
"health_pool": HealthUpPool,
"mana_pool": ManaUpPool,
"attack_pool": AttackUpPool,
"magic_damage_pool": MagicDamageUpPool,
"armor_pool": ArmorUpPool,
"equip_pool": EquipUpPool,
"crit_chance_pool": CritChanceUpPool,
"crit_damage_pool": CritDamageUpPool,
"allow_default_names": AllowDefaultNames,
"additional_lady_names": AdditionalNames,
"additional_sir_names": AdditionalNames,
"death_link": DeathLink,
}

View File

@@ -0,0 +1,72 @@
import typing
from BaseClasses import MultiWorld, Region, RegionType, Entrance, ItemClassification
from .Items import LegacyItem
from .Locations import LegacyLocation, diary_location_table, location_table, base_location_table
from .Names import LocationName, ItemName
prog = ItemClassification.progression
def create_regions(world, player: int):
locations: typing.List[str] = []
# Add required locations.
locations += [location for location in base_location_table]
locations += [location for location in diary_location_table]
# Add chests per settings.
if world.universal_fairy_chests[player]:
fairies = int(world.fairy_chests_per_zone[player]) * 4
for i in range(0, fairies):
locations += [f"Fairy Chest {i + 1}"]
else:
fairies = int(world.fairy_chests_per_zone[player])
for i in range(0, fairies):
locations += [f"{LocationName.castle} - Fairy Chest {i + 1}"]
locations += [f"{LocationName.garden} - Fairy Chest {i + 1}"]
locations += [f"{LocationName.tower} - Fairy Chest {i + 1}"]
locations += [f"{LocationName.dungeon} - Fairy Chest {i + 1}"]
if world.universal_chests[player]:
chests = int(world.chests_per_zone[player]) * 4
for i in range(0, chests):
locations += [f"Chest {i + 1}"]
else:
chests = int(world.chests_per_zone[player])
for i in range(0, chests):
locations += [f"{LocationName.castle} - Chest {i + 1}"]
locations += [f"{LocationName.garden} - Chest {i + 1}"]
locations += [f"{LocationName.tower} - Chest {i + 1}"]
locations += [f"{LocationName.dungeon} - Chest {i + 1}"]
# Set up the regions correctly.
world.regions += [
create_region(world, player, "Menu", None, [LocationName.outside]),
create_region(world, player, LocationName.castle, locations),
]
# Connect entrances and set up events.
world.get_entrance(LocationName.outside, player).connect(world.get_region(LocationName.castle, player))
world.get_location(LocationName.castle, player).place_locked_item(LegacyItem(ItemName.boss_castle, prog, None, player))
world.get_location(LocationName.garden, player).place_locked_item(LegacyItem(ItemName.boss_forest, prog, None, player))
world.get_location(LocationName.tower, player).place_locked_item(LegacyItem(ItemName.boss_tower, prog, None, player))
world.get_location(LocationName.dungeon, player).place_locked_item(LegacyItem(ItemName.boss_dungeon, prog, None, player))
world.get_location(LocationName.fountain, player).place_locked_item(LegacyItem(ItemName.boss_fountain, prog, None, player))
def create_region(world: MultiWorld, player: int, name: str, locations=None, exits=None):
# Shamelessly stolen from the ROR2 definition, lol
ret = Region(name, RegionType.Generic, name, player)
ret.world = world
if locations:
for location in locations:
loc_id = location_table.get(location, 0)
location = LegacyLocation(player, location, loc_id, ret)
ret.locations.append(location)
if exits:
for exit in exits:
ret.exits.append(Entrance(player, exit, ret))
return ret

View File

@@ -0,0 +1,177 @@
from BaseClasses import MultiWorld
from .Names import LocationName, ItemName
from ..AutoWorld import LogicMixin
from ..generic.Rules import set_rule
class LegacyLogic(LogicMixin):
def _legacy_has_any_vendors(self, player: int) -> bool:
return self.has_any({ItemName.blacksmith, ItemName.enchantress}, player)
def _legacy_has_all_vendors(self, player: int) -> bool:
return self.has_all({ItemName.blacksmith, ItemName.enchantress}, player)
def _legacy_has_stat_upgrades(self, player: int, amount: int) -> bool:
return self._legacy_stat_upgrade_count(player) >= amount
def _legacy_total_stat_upgrades_count(self, player: int) -> int:
return int(self.world.health_pool[player]) + \
int(self.world.mana_pool[player]) + \
int(self.world.attack_pool[player]) + \
int(self.world.magic_damage_pool[player]) + \
int(self.world.armor_pool[player]) + \
int(self.world.equip_pool[player])
def _legacy_stat_upgrade_count(self, player: int) -> int:
return self.item_count(ItemName.health, player) + self.item_count(ItemName.mana, player) + \
self.item_count(ItemName.attack, player) + self.item_count(ItemName.magic_damage, player) + \
self.item_count(ItemName.armor, player) + self.item_count(ItemName.equip, player)
def set_rules(world: MultiWorld, player: int):
# Check for duplicate names.
if len(set(world.additional_lady_names[player].value)) != len(world.additional_lady_names[player].value):
raise Exception(f"Duplicate values are not allowed in additional_lady_names.")
if len(set(world.additional_sir_names[player].value)) != len(world.additional_sir_names[player].value):
raise Exception(f"Duplicate values are not allowed in additional_sir_names.")
if not world.allow_default_names[player]:
# Check for quantity.
name_count = len(world.additional_lady_names[player].value)
if name_count < int(world.number_of_children[player]):
raise Exception(f"allow_default_names is off, but not enough names are defined in additional_lady_names. Expected {int(world.number_of_children[player])}, Got {name_count}")
name_count = len(world.additional_sir_names[player].value)
if name_count < int(world.number_of_children[player]):
raise Exception(f"allow_default_names is off, but not enough names are defined in additional_sir_names. Expected {int(world.number_of_children[player])}, Got {name_count}")
# Chests
if world.universal_chests[player]:
for i in range(0, world.chests_per_zone[player]):
set_rule(world.get_location(f"Chest {i + 1 + (world.chests_per_zone[player] * 1)}", player),
lambda state: state.has(ItemName.boss_castle, player))
set_rule(world.get_location(f"Chest {i + 1 + (world.chests_per_zone[player] * 2)}", player),
lambda state: state.has(ItemName.boss_forest, player))
set_rule(world.get_location(f"Chest {i + 1 + (world.chests_per_zone[player] * 3)}", player),
lambda state: state.has(ItemName.boss_tower, player))
else:
for i in range(0, world.chests_per_zone[player]):
set_rule(world.get_location(f"{LocationName.garden} - Chest {i + 1}", player),
lambda state: state.has(ItemName.boss_castle, player))
set_rule(world.get_location(f"{LocationName.tower} - Chest {i + 1}", player),
lambda state: state.has(ItemName.boss_forest, player))
set_rule(world.get_location(f"{LocationName.dungeon} - Chest {i + 1}", player),
lambda state: state.has(ItemName.boss_tower, player))
# Fairy Chests
if world.universal_fairy_chests[player]:
for i in range(0, world.fairy_chests_per_zone[player]):
set_rule(world.get_location(f"Fairy Chest {i + 1 + (world.fairy_chests_per_zone[player] * 1)}", player),
lambda state: state.has(ItemName.boss_castle, player))
set_rule(world.get_location(f"Fairy Chest {i + 1 + (world.fairy_chests_per_zone[player] * 2)}", player),
lambda state: state.has(ItemName.boss_forest, player))
set_rule(world.get_location(f"Fairy Chest {i + 1 + (world.fairy_chests_per_zone[player] * 3)}", player),
lambda state: state.has(ItemName.boss_tower, player))
else:
for i in range(0, world.fairy_chests_per_zone[player]):
set_rule(world.get_location(f"{LocationName.garden} - Fairy Chest {i + 1}", player),
lambda state: state.has(ItemName.boss_castle, player))
set_rule(world.get_location(f"{LocationName.tower} - Fairy Chest {i + 1}", player),
lambda state: state.has(ItemName.boss_forest, player))
set_rule(world.get_location(f"{LocationName.dungeon} - Fairy Chest {i + 1}", player),
lambda state: state.has(ItemName.boss_tower, player))
# Vendors
if world.vendors[player] == "early":
set_rule(world.get_location(LocationName.boss_castle, player),
lambda state: state._legacy_has_all_vendors(player))
elif world.vendors[player] == "normal":
set_rule(world.get_location(LocationName.garden, player),
lambda state: state._legacy_has_any_vendors(player))
# Diaries
for i in range(0, 5):
set_rule(world.get_location(f"Diary {i + 6}", player),
lambda state: state.has(ItemName.boss_castle, player))
set_rule(world.get_location(f"Diary {i + 11}", player),
lambda state: state.has(ItemName.boss_forest, player))
set_rule(world.get_location(f"Diary {i + 16}", player),
lambda state: state.has(ItemName.boss_tower, player))
set_rule(world.get_location(f"Diary {i + 21}", player),
lambda state: state.has(ItemName.boss_dungeon, player))
# Scale each manor location.
set_rule(world.get_location(LocationName.manor_left_wing_window, player),
lambda state: state.has(ItemName.boss_castle, player))
set_rule(world.get_location(LocationName.manor_left_wing_roof, player),
lambda state: state.has(ItemName.boss_castle, player))
set_rule(world.get_location(LocationName.manor_right_wing_window, player),
lambda state: state.has(ItemName.boss_castle, player))
set_rule(world.get_location(LocationName.manor_right_wing_roof, player),
lambda state: state.has(ItemName.boss_castle, player))
set_rule(world.get_location(LocationName.manor_left_big_base, player),
lambda state: state.has(ItemName.boss_castle, player))
set_rule(world.get_location(LocationName.manor_right_big_base, player),
lambda state: state.has(ItemName.boss_castle, player))
set_rule(world.get_location(LocationName.manor_left_tree1, player),
lambda state: state.has(ItemName.boss_castle, player))
set_rule(world.get_location(LocationName.manor_left_tree2, player),
lambda state: state.has(ItemName.boss_castle, player))
set_rule(world.get_location(LocationName.manor_right_tree, player),
lambda state: state.has(ItemName.boss_castle, player))
set_rule(world.get_location(LocationName.manor_left_big_upper1, player),
lambda state: state.has(ItemName.boss_forest, player))
set_rule(world.get_location(LocationName.manor_left_big_upper2, player),
lambda state: state.has(ItemName.boss_forest, player))
set_rule(world.get_location(LocationName.manor_left_big_windows, player),
lambda state: state.has(ItemName.boss_forest, player))
set_rule(world.get_location(LocationName.manor_left_big_roof, player),
lambda state: state.has(ItemName.boss_forest, player))
set_rule(world.get_location(LocationName.manor_left_far_base, player),
lambda state: state.has(ItemName.boss_forest, player))
set_rule(world.get_location(LocationName.manor_left_far_roof, player),
lambda state: state.has(ItemName.boss_forest, player))
set_rule(world.get_location(LocationName.manor_left_extension, player),
lambda state: state.has(ItemName.boss_forest, player))
set_rule(world.get_location(LocationName.manor_right_big_upper, player),
lambda state: state.has(ItemName.boss_forest, player))
set_rule(world.get_location(LocationName.manor_right_big_roof, player),
lambda state: state.has(ItemName.boss_forest, player))
set_rule(world.get_location(LocationName.manor_right_extension, player),
lambda state: state.has(ItemName.boss_forest, player))
set_rule(world.get_location(LocationName.manor_right_high_base, player),
lambda state: state.has(ItemName.boss_tower, player))
set_rule(world.get_location(LocationName.manor_right_high_upper, player),
lambda state: state.has(ItemName.boss_tower, player))
set_rule(world.get_location(LocationName.manor_right_high_tower, player),
lambda state: state.has(ItemName.boss_tower, player))
set_rule(world.get_location(LocationName.manor_observatory_base, player),
lambda state: state.has(ItemName.boss_tower, player))
set_rule(world.get_location(LocationName.manor_observatory_scope, player),
lambda state: state.has(ItemName.boss_tower, player))
# Standard Zone Progression
set_rule(world.get_location(LocationName.garden, player),
lambda state: state._legacy_has_stat_upgrades(player, 0.125 * state._legacy_total_stat_upgrades_count(player)) and state.has(ItemName.boss_castle, player))
set_rule(world.get_location(LocationName.tower, player),
lambda state: state._legacy_has_stat_upgrades(player, 0.3125 * state._legacy_total_stat_upgrades_count(player)) and state.has(ItemName.boss_forest, player))
set_rule(world.get_location(LocationName.dungeon, player),
lambda state: state._legacy_has_stat_upgrades(player, 0.5 * state._legacy_total_stat_upgrades_count(player)) and state.has(ItemName.boss_tower, player))
# Bosses
set_rule(world.get_location(LocationName.boss_castle, player),
lambda state: state.has(ItemName.boss_castle, player))
set_rule(world.get_location(LocationName.boss_forest, player),
lambda state: state.has(ItemName.boss_forest, player))
set_rule(world.get_location(LocationName.boss_tower, player),
lambda state: state.has(ItemName.boss_tower, player))
set_rule(world.get_location(LocationName.boss_dungeon, player),
lambda state: state.has(ItemName.boss_dungeon, player))
set_rule(world.get_location(LocationName.fountain, player),
lambda state: state._legacy_has_stat_upgrades(player, 0.625 * state._legacy_total_stat_upgrades_count(player))
and state.has(ItemName.boss_castle, player)
and state.has(ItemName.boss_forest, player)
and state.has(ItemName.boss_tower, player)
and state.has(ItemName.boss_dungeon, player))
world.completion_condition[player] = lambda state: state.has(ItemName.boss_fountain, player)

View File

@@ -0,0 +1,39 @@
traits = [
"Color Blind",
"Gay",
"Near-Sighted",
"Far-Sighted",
"Dyslexia",
"Gigantism",
"Dwarfism",
"Baldness",
"Endomorph",
"Ectomorph",
"Alzheimers",
"Dextrocardia",
"Coprolalia",
"ADHD",
"O.C.D.",
"Hypergonadism",
"Muscle Wk.",
"Stereo Blind",
"I.B.S.",
"Vertigo",
"Tunnel Vision",
"Ambilevous",
"P.A.D.",
"Alektorophobia",
"Hypochondriac",
"Dementia",
"Flexible",
"Eid. Mem.",
"Nostalgic",
"C.I.P.",
"Savant",
"The One",
"Clumsy",
"EHS",
"Glaucoma",
"Adopted",
]

View File

@@ -0,0 +1,176 @@
import typing
from BaseClasses import Item, ItemClassification, Tutorial
from .Items import LegacyItem, ItemData, item_table, vendors_table, static_classes_table, progressive_classes_table, \
skill_unlocks_table, blueprints_table, runes_table, misc_items_table
from .Locations import LegacyLocation, location_table, base_location_table
from .Options import legacy_options
from .Regions import create_regions
from .Rules import set_rules
from .Names import ItemName
from ..AutoWorld import World, WebWorld
class LegacyWeb(WebWorld):
theme = "stone"
tutorials = [Tutorial(
"Multiworld Setup Guide",
"A guide to setting up the Rogue Legacy Randomizer software on your computer. This guide covers single-player, multiworld, and related software.",
"English",
"rogue-legacy_en.md",
"rogue-legacy/en",
["Phar"]
)]
class LegacyWorld(World):
"""
Rogue Legacy is a genealogical rogue-"LITE" where anyone can be a hero. Each time you die, your child will succeed
you. Every child is unique. One child might be colorblind, another might have vertigo-- they could even be a dwarf.
But that's OK, because no one is perfect, and you don't have to be to succeed.
"""
game: str = "Rogue Legacy"
options = legacy_options
topology_present = False
data_version = 3
required_client_version = (0, 2, 3)
web = LegacyWeb()
item_name_to_id = {name: data.code for name, data in item_table.items()}
location_name_to_id = location_table
def _get_slot_data(self):
return {
"starting_gender": self.world.starting_gender[self.player],
"starting_class": self.world.starting_class[self.player],
"new_game_plus": self.world.new_game_plus[self.player],
"fairy_chests_per_zone": self.world.fairy_chests_per_zone[self.player],
"chests_per_zone": self.world.chests_per_zone[self.player],
"universal_fairy_chests": self.world.universal_fairy_chests[self.player],
"universal_chests": self.world.universal_chests[self.player],
"vendors": self.world.vendors[self.player],
"architect_fee": self.world.architect_fee[self.player],
"disable_charon": self.world.disable_charon[self.player],
"require_purchasing": self.world.require_purchasing[self.player],
"gold_gain_multiplier": self.world.gold_gain_multiplier[self.player],
"number_of_children": self.world.number_of_children[self.player],
"khidr": self.world.khidr[self.player],
"alexander": self.world.alexander[self.player],
"leon": self.world.leon[self.player],
"herodotus": self.world.herodotus[self.player],
"allow_default_names": self.world.allow_default_names[self.player],
"additional_sir_names": self.world.additional_sir_names[self.player],
"additional_lady_names": self.world.additional_lady_names[self.player],
"death_link": self.world.death_link[self.player],
}
def _create_items(self, name: str):
data = item_table[name]
return [self.create_item(name)] * data.quantity
def fill_slot_data(self) -> dict:
slot_data = self._get_slot_data()
for option_name in legacy_options:
option = getattr(self.world, option_name)[self.player]
slot_data[option_name] = option.value
return slot_data
def generate_basic(self):
itempool: typing.List[LegacyItem] = []
total_required_locations = 64 + (self.world.chests_per_zone[self.player] * 4) + (self.world.fairy_chests_per_zone[self.player] * 4)
# Fill item pool with all required items
for item in {**skill_unlocks_table, **runes_table}:
# if Haggling, do not add if Disable Charon.
if item == ItemName.haggling and self.world.disable_charon[self.player] == 1:
continue
itempool += self._create_items(item)
# Blueprints
if self.world.progressive_blueprints[self.player]:
itempool += [self.create_item(ItemName.progressive_blueprints)] * 15
else:
for item in blueprints_table:
itempool += self._create_items(item)
# Check Pool settings to add a certain amount of these items.
itempool += [self.create_item(ItemName.health)] * int(self.world.health_pool[self.player])
itempool += [self.create_item(ItemName.mana)] * int(self.world.mana_pool[self.player])
itempool += [self.create_item(ItemName.attack)] * int(self.world.attack_pool[self.player])
itempool += [self.create_item(ItemName.magic_damage)] * int(self.world.magic_damage_pool[self.player])
itempool += [self.create_item(ItemName.armor)] * int(self.world.armor_pool[self.player])
itempool += [self.create_item(ItemName.equip)] * int(self.world.equip_pool[self.player])
itempool += [self.create_item(ItemName.crit_chance)] * int(self.world.crit_chance_pool[self.player])
itempool += [self.create_item(ItemName.crit_damage)] * int(self.world.crit_damage_pool[self.player])
classes = self.world.available_classes[self.player]
if "Dragon" in classes:
itempool.append(self.create_item(ItemName.dragon))
if "Traitor" in classes:
itempool.append(self.create_item(ItemName.traitor))
if self.world.starting_class[self.player] == "knight":
itempool.append(self.create_item(ItemName.progressive_knight))
elif "Knight" in classes:
itempool.extend(self._create_items(ItemName.progressive_knight))
if self.world.starting_class[self.player] == "mage":
itempool.append(self.create_item(ItemName.progressive_mage))
elif "Mage" in classes:
itempool.extend(self._create_items(ItemName.progressive_mage))
if self.world.starting_class[self.player] == "barbarian":
itempool.append(self.create_item(ItemName.progressive_barbarian))
elif "Barbarian" in classes:
itempool.extend(self._create_items(ItemName.progressive_barbarian))
if self.world.starting_class[self.player] == "knave":
itempool.append(self.create_item(ItemName.progressive_knave))
elif "Knave" in classes:
itempool.extend(self._create_items(ItemName.progressive_knave))
if self.world.starting_class[self.player] == "shinobi":
itempool.append(self.create_item(ItemName.progressive_shinobi))
elif "Shinobi" in classes:
itempool.extend(self._create_items(ItemName.progressive_shinobi))
if self.world.starting_class[self.player] == "miner":
itempool.append(self.create_item(ItemName.progressive_miner))
elif "Miner" in classes:
itempool.extend(self._create_items(ItemName.progressive_miner))
if self.world.starting_class[self.player] == "lich":
itempool.append(self.create_item(ItemName.progressive_lich))
elif "Lich" in classes:
itempool.extend(self._create_items(ItemName.progressive_lich))
if self.world.starting_class[self.player] == "spellthief":
itempool.append(self.create_item(ItemName.progressive_spellthief))
elif "Spellthief" in classes:
itempool.extend(self._create_items(ItemName.progressive_spellthief))
# Check if we need to start with these vendors or put them in the pool.
if self.world.vendors[self.player] == "start_unlocked":
self.world.push_precollected(self.world.create_item(ItemName.blacksmith, self.player))
self.world.push_precollected(self.world.create_item(ItemName.enchantress, self.player))
else:
itempool += [self.create_item(ItemName.blacksmith), self.create_item(ItemName.enchantress)]
# Add Architect.
if self.world.architect[self.player] == "start_unlocked":
self.world.push_precollected(self.world.create_item(ItemName.architect, self.player))
elif self.world.architect[self.player] != "disabled":
itempool += [self.create_item(ItemName.architect)]
# Fill item pool with the remaining
for _ in range(len(itempool), total_required_locations):
item = self.world.random.choice(list(misc_items_table.keys()))
itempool += [self.create_item(item)]
self.world.itempool += itempool
def get_filler_item_name(self) -> str:
return self.world.random.choice(list(misc_items_table.keys()))
def create_regions(self):
create_regions(self.world, self.player)
def create_item(self, name: str) -> Item:
data = item_table[name]
return LegacyItem(name, ItemClassification.progression if data.progression else ItemClassification.filler, data.code, self.player)
def set_rules(self):
set_rules(self.world, self.player)

View File

@@ -0,0 +1,27 @@
# Rogue Legacy (PC)
## Where is the settings page?
The [player settings page for this game](../player-settings) is located contains all the options you need to configure
and export a config file.
## What does randomization do to this game?
You are not able to buy skill upgrades in the manor upgrade screen, and instead, need to find them in order to level up
your character to make fighting the 5 bosses easier.
## What items and locations get shuffled?
All the skill upgrades, class upgrades, runes packs, and equipment packs are shuffled in the manor upgrade screen, diary
checks, chests and fairy chests, and boss rewards. Skill upgrades are also grouped in packs of 5 to make the finding of
stats less of a chore. Runes and Equipment are also grouped together.
## Which items can be in another player's world?
Any of the items which can be shuffled may also be placed into another player's world. It is possible to choose to limit
certain items to your own world.
## When the player receives an item, what happens?
When the player receives an item, your character will hold the item above their head and display it to the world. It's
good for business!

View File

@@ -0,0 +1,52 @@
# Rogue Legacy Randomizer Setup Guide
## Required Software
- Rogue Legacy Randomizer from
the [Rogue Legacy Randomizer Releases Page](https://github.com/ThePhar/RogueLegacyRandomizer/releases)
## Configuring your YAML file
### What is a YAML file and why do I need one?
Your YAML file contains a set of configuration options which provide the generator with information about how it should
generate your game. Each player of a multiworld will provide their own YAML file. This setup allows each player to enjoy
an experience customized for their taste, and different players in the same multiworld can all have different options.
### Where do I get a YAML file?
you can customize your settings by visiting the [Rogue Legacy Settings Page](/games/Rogue%20Legacy/player-settings).
### Connect to the MultiServer
Once in game, press the start button and the AP connection screen should appear. You will fill out the hostname, port,
slot name, and password (if applicable). You should only need to fill out hostname, port, and password if the server
provides an alternative one to the default values.
### Play the game
Once you have entered the required values, you go to Connect and then select Confirm on the "Ready to Start" screen. Now
you're off to start your legacy!
## Manual Installation
In order to run Rogue Legacy Randomizer you will need to have Rogue Legacy installed on your local machine. Extract the
Randomizer release into a desired folder **outside** of your Rogue Legacy install. Copy the following files from your
Rogue Legacy install into the main directory of your Rogue Legacy Randomizer install:
- DS2DEngine.dll
- InputSystem.dll
- Nuclex.Input.dll
- SpriteSystem.dll
- Tweener.dll
And copy the directory from your Rogue Legacy install as well into the main directory of your Rogue Legacy Randomizer
install:
- Content/
Then copy the contents of the CustomContent directory in your Rogue Legacy Randomizer into the newly copied Content
directory and overwrite all files.
**BE SURE YOU ARE REPLACING THE COPIED FILES IN YOUR ROGUE LEGACY RANDOMIZER DIRECTORY AND NOT REPLACING YOUR ROGUE
LEGACY FILES!**