diff --git a/CLI.py b/CLI.py index ada43572..5b8d25f9 100644 --- a/CLI.py +++ b/CLI.py @@ -11,6 +11,7 @@ import sys from Main import main import source.classes.constants as CONST +from source.classes.BabelFish import BabelFish class ArgumentDefaultsHelpFormatter(argparse.RawTextHelpFormatter): @@ -25,271 +26,48 @@ def parse_arguments(argv, no_defaults=False): # get settings settings = get_settings() + fish = BabelFish() + # we need to know how many players we have first parser = argparse.ArgumentParser(add_help=False) parser.add_argument('--multi', default=defval(settings["multi"]), type=lambda value: min(max(int(value), 1), 255)) multiargs, _ = parser.parse_known_args(argv) parser = argparse.ArgumentParser(formatter_class=ArgumentDefaultsHelpFormatter) - parser.add_argument('--create_spoiler', default=defval(settings["create_spoiler"] != 0), help='Output a Spoiler File', action='store_true') - parser.add_argument('--logic', default=defval(settings["logic"]), const='noglitches', nargs='?', choices=['noglitches', 'minorglitches', 'nologic'], - help='''\ - Select Enforcement of Item Requirements. (default: %(default)s) - No Glitches: - Minor Glitches: May require Fake Flippers, Bunny Revival - and Dark Room Navigation. - No Logic: Distribute items without regard for - item requirements. - ''') - parser.add_argument('--mode', default=defval(settings["mode"]), const='open', nargs='?', choices=['standard', 'open', 'inverted'], - help='''\ - Select game mode. (default: %(default)s) - Open: World starts with Zelda rescued. - Standard: Fixes Hyrule Castle Secret Entrance and Front Door - but may lead to weird rain state issues if you exit - through the Hyrule Castle side exits before rescuing - Zelda in a full shuffle. - Inverted: Starting locations are Dark Sanctuary in West Dark - World or at Link's House, which is shuffled freely. - Requires the moon pearl to be Link in the Light World - instead of a bunny. - ''') - parser.add_argument('--swords', default=defval(settings["swords"]), const='random', nargs='?', choices= ['random', 'assured', 'swordless', 'vanilla'], - help='''\ - Select sword placement. (default: %(default)s) - Random: All swords placed randomly. - Assured: Start game with a sword already. - Swordless: No swords. Curtains in Skull Woods and Agahnim\'s - Tower are removed, Agahnim\'s Tower barrier can be - destroyed with hammer. Misery Mire and Turtle Rock - can be opened without a sword. Hammer damages Ganon. - Ether and Bombos Tablet can be activated with Hammer - (and Book). Bombos pads have been added in Ice - Palace, to allow for an alternative to firerod. - Vanilla: Swords are in vanilla locations. - ''') - parser.add_argument('--goal', default=defval(settings["goal"]), const='ganon', nargs='?', choices=['ganon', 'pedestal', 'dungeons', 'triforcehunt', 'crystals'], - help='''\ - Select completion goal. (default: %(default)s) - Ganon: Collect all crystals, beat Agahnim 2 then - defeat Ganon. - Crystals: Collect all crystals then defeat Ganon. - Pedestal: Places the Triforce at the Master Sword Pedestal. - All Dungeons: Collect all crystals, pendants, beat both - Agahnim fights and then defeat Ganon. - Triforce Hunt: Places 30 Triforce Pieces in the world, collect - 20 of them to beat the game. - ''') - parser.add_argument('--difficulty', default=defval(settings["difficulty"]), const='normal', nargs='?', choices=['normal', 'hard', 'expert'], - help='''\ - Select game difficulty. Affects available itempool. (default: %(default)s) - Normal: Normal difficulty. - Hard: A harder setting with less equipment and reduced health. - Expert: A harder yet setting with minimum equipment and health. - ''') - parser.add_argument('--item_functionality', default=defval(settings["item_functionality"]), const='normal', nargs='?', choices=['normal', 'hard', 'expert'], - help='''\ - Select limits on item functionality to increase difficulty. (default: %(default)s) - Normal: Normal functionality. - Hard: Reduced functionality. - Expert: Greatly reduced functionality. - ''') - parser.add_argument('--timer', default=defval(settings["timer"]), const='normal', nargs='?', choices=['none', 'display', 'timed', 'timed-ohko', 'ohko', 'timed-countdown'], - help='''\ - Select game timer setting. Affects available itempool. (default: %(default)s) - None: No timer. - Display: Displays a timer but does not affect - the itempool. - Timed: Starts with clock at zero. Green Clocks - subtract 4 minutes (Total: 20), Blue Clocks - subtract 2 minutes (Total: 10), Red Clocks add - 2 minutes (Total: 10). Winner is player with - lowest time at the end. - Timed OHKO: Starts clock at 10 minutes. Green Clocks add - 5 minutes (Total: 25). As long as clock is at 0, - Link will die in one hit. - OHKO: Like Timed OHKO, but no clock items are present - and the clock is permenantly at zero. - Timed Countdown: Starts with clock at 40 minutes. Same clocks as - Timed mode. If time runs out, you lose (but can - still keep playing). - ''') - parser.add_argument('--progressive', default=defval(settings["progressive"]), const='normal', nargs='?', choices=['on', 'off', 'random'], - help='''\ - Select progressive equipment setting. Affects available itempool. (default: %(default)s) - On: Swords, Shields, Armor, and Gloves will - all be progressive equipment. Each subsequent - item of the same type the player finds will - upgrade that piece of equipment by one stage. - Off: Swords, Shields, Armor, and Gloves will not - be progressive equipment. Higher level items may - be found at any time. Downgrades are not possible. - Random: Swords, Shields, Armor, and Gloves will, per - category, be randomly progressive or not. - Link will die in one hit. - ''') - parser.add_argument('--algorithm', default=defval(settings["algorithm"]), const='balanced', nargs='?', choices=['freshness', 'flood', 'vt21', 'vt22', 'vt25', 'vt26', 'balanced'], - help='''\ - Select item filling algorithm. (default: %(default)s - balanced: vt26 derivative that aims to strike a balance between - the overworld heavy vt25 and the dungeon heavy vt26 - algorithm. - vt26: Shuffle items and place them in a random location - that it is not impossible to be in. This includes - dungeon keys and items. - vt25: Shuffle items and place them in a random location - that it is not impossible to be in. - vt21: Unbiased in its selection, but has tendency to put - Ice Rod in Turtle Rock. - vt22: Drops off stale locations after 1/3 of progress - items were placed to try to circumvent vt21\'s - shortcomings. - Freshness: Keep track of stale locations (ones that cannot be - reached yet) and decrease likeliness of selecting - them the more often they were found unreachable. - Flood: Push out items starting from Link\'s House and - slightly biased to placing progression items with - less restrictions. - ''') - parser.add_argument('--shuffle', default=defval(settings["shuffle"]), const='full', nargs='?', choices=['vanilla', 'simple', 'restricted', 'full', 'crossed', 'insanity', 'restricted_legacy', 'full_legacy', 'madness_legacy', 'insanity_legacy', 'dungeonsfull', 'dungeonssimple'], - help='''\ - Select Entrance Shuffling Algorithm. (default: %(default)s) - Full: Mix cave and dungeon entrances freely while limiting - multi-entrance caves to one world. - Simple: Shuffle Dungeon Entrances/Exits between each other - and keep all 4-entrance dungeons confined to one - location. All caves outside of death mountain are - shuffled in pairs and matched by original type. - Restricted: Use Dungeons shuffling from Simple but freely - connect remaining entrances. - Crossed: Mix cave and dungeon entrances freely while allowing - caves to cross between worlds. - Insanity: Decouple entrances and exits from each other and - shuffle them freely. Caves that used to be single - entrance will still exit to the same location from - which they are entered. - Vanilla: All entrances are in the same locations they were - in the base game. - Legacy shuffles preserve behavior from older versions of the - entrance randomizer including significant technical limitations. - The dungeon variants only mix up dungeons and keep the rest of - the overworld vanilla. - ''') - parser.add_argument('--door_shuffle', default=defval(settings["door_shuffle"]), const='vanilla', nargs='?', choices=['vanilla', 'basic', 'crossed'], - help='''\ - Select Door Shuffling Algorithm. (default: %(default)s) - Basic: Doors are mixed within a single dungeon. - (Not yet implemented) - Crossed: Doors are mixed between all dungeons. - (Not yet implemented) - Vanilla: All doors are connected the same way they were in the - base game. - ''') - parser.add_argument('--experimental', default=defval(settings["experimental"] != 0), help='Enable experimental features', action='store_true') - parser.add_argument('--dungeon_counters', default=defval(settings["dungeon_counters"]), help='Enable dungeon chest counters', const='off', nargs='?', choices=['off', 'on', 'pickup', 'default']) - parser.add_argument('--crystals_ganon', default=defval(settings["crystals_ganon"]), const='7', nargs='?', choices=['random', '0', '1', '2', '3', '4', '5', '6', '7'], - help='''\ - How many crystals are needed to defeat ganon. Any other - requirements for ganon for the selected goal still apply. - This setting does not apply when the all dungeons goal is - selected. (default: %(default)s) - Random: Picks a random value between 0 and 7 (inclusive). - 0-7: Number of crystals needed - ''') - parser.add_argument('--crystals_gt', default=defval(settings["crystals_gt"]), const='7', nargs='?', choices=['random', '0', '1', '2', '3', '4', '5', '6', '7'], - help='''\ - How many crystals are needed to open GT. For inverted mode - this applies to the castle tower door instead. (default: %(default)s) - Random: Picks a random value between 0 and 7 (inclusive). - 0-7: Number of crystals needed - ''') - parser.add_argument('--openpyramid', default=defval(settings["openpyramid"] != 0), help='''\ - Pre-opens the pyramid hole, this removes the Agahnim 2 requirement for it - ''', action='store_true') - parser.add_argument('--rom', default=defval(settings["rom"]), help='Path to an ALttP JAP(1.0) rom to use as a base.') - parser.add_argument('--loglevel', default=defval('info'), const='info', nargs='?', choices=['error', 'info', 'warning', 'debug'], help='Select level of logging for output.') - parser.add_argument('--seed', default=defval(int(settings["seed"]) if settings["seed"] != "" and settings["seed"] is not None else None), help='Define seed number to generate.', type=int) - parser.add_argument('--count', default=defval(int(settings["count"]) if settings["count"] != "" and settings["count"] is not None else None), help='''\ - Use to batch generate multiple seeds with same settings. - If --seed is provided, it will be used for the first seed, then - used to derive the next seed (i.e. generating 10 seeds with - --seed given will produce the same 10 (different) roms each - time). - ''', type=int) - parser.add_argument('--fastmenu', default=defval(settings["fastmenu"]), const='normal', nargs='?', choices=['normal', 'instant', 'double', 'triple', 'quadruple', 'half'], - help='''\ - Select the rate at which the menu opens and closes. - (default: %(default)s) - ''') - parser.add_argument('--quickswap', default=defval(settings["quickswap"] != 0), help='Enable quick item swapping with L and R.', action='store_true') - parser.add_argument('--disablemusic', default=defval(settings["disablemusic"] != 0), help='Disables game music.', action='store_true') - parser.add_argument('--mapshuffle', default=defval(settings["mapshuffle"] != 0), help='Maps are no longer restricted to their dungeons, but can be anywhere', action='store_true') - parser.add_argument('--compassshuffle', default=defval(settings["compassshuffle"] != 0), help='Compasses are no longer restricted to their dungeons, but can be anywhere', action='store_true') - parser.add_argument('--keyshuffle', default=defval(settings["keyshuffle"] != 0), help='Small Keys are no longer restricted to their dungeons, but can be anywhere', action='store_true') - parser.add_argument('--bigkeyshuffle', default=defval(settings["bigkeyshuffle"] != 0), help='Big Keys are no longer restricted to their dungeons, but can be anywhere', action='store_true') - parser.add_argument('--keysanity', default=defval(settings["keysanity"] != 0), help=argparse.SUPPRESS, action='store_true') - parser.add_argument('--retro', default=defval(settings["retro"] != 0), help='''\ - Keys are universal, shooting arrows costs rupees, - and a few other little things make this more like Zelda-1. - ''', action='store_true') - parser.add_argument('--startinventory', default=defval(settings["startinventory"]), help='Specifies a list of items that will be in your starting inventory (separated by commas)') - parser.add_argument('--usestartinventory', default=defval(settings["usestartinventory"] != 0), help='Not supported.') - parser.add_argument('--custom', default=defval(settings["custom"] != 0), help='Not supported.') - parser.add_argument('--customitemarray', default={}, help='Not supported.') - parser.add_argument('--accessibility', default=defval(settings["accessibility"]), const='items', nargs='?', choices=['items', 'locations', 'none'], help='''\ - Select Item/Location Accessibility. (default: %(default)s) - Items: You can reach all unique inventory items. No guarantees about - reaching all locations or all keys. - Locations: You will be able to reach every location in the game. - None: You will be able to reach enough locations to beat the game. - ''') - parser.add_argument('--hints', default=defval(settings["hints"] != 0), help='''\ - Make telepathic tiles and storytellers give helpful hints. - ''', action='store_true') + + # get args + args = [] + with open(os.path.join("resources","app","cli","args.json")) as argsFile: + args = json.load(argsFile) + for arg in args: + argdata = args[arg] + argname = "--" + arg + argatts = {} + argatts["help"] = "(default: %(default)s)" + if "action" in argdata: + argatts["action"] = argdata["action"] + if "choices" in argdata: + argatts["choices"] = argdata["choices"] + argatts["const"] = argdata["choices"][0] + argatts["default"] = argdata["choices"][0] + argatts["nargs"] = "?" + elif arg in settings: + argatts["default"] = defval(settings[arg] != 0) if "type" in argdata and argdata["type"] == "bool" else defval(settings[arg]) + arghelp = fish.translate("cli","help",arg) + if "help" in argdata and argdata["help"] == "suppress": + argatts["help"] = argparse.SUPPRESS + elif not isinstance(arghelp,str): + argatts["help"] = '\n'.join(arghelp).replace("\\'","'") + parser.add_argument(argname,**argatts) + + parser.add_argument('--seed', default=defval(int(settings["seed"]) if settings["seed"] != "" and settings["seed"] is not None else None), help="\n".join(fish.translate("cli","help","seed")), type=int) + parser.add_argument('--count', default=defval(int(settings["count"]) if settings["count"] != "" and settings["count"] is not None else 1), help="\n".join(fish.translate("cli","help","count")), type=int) + parser.add_argument('--customitemarray', default={}, help=argparse.SUPPRESS) + # included for backwards compatibility - parser.add_argument('--shuffleganon', help=argparse.SUPPRESS, action='store_true', default=defval(settings["shuffleganon"] != 0)) - parser.add_argument('--no-shuffleganon', help='''\ - If set, the Pyramid Hole and Ganon's Tower are not - included entrance shuffle pool. - ''', action='store_false', dest='shuffleganon') - parser.add_argument('--heartbeep', default=defval(settings["heartbeep"]), const='normal', nargs='?', choices=['double', 'normal', 'half', 'quarter', 'off'], - help='''\ - Select the rate at which the heart beep sound is played at - low health. (default: %(default)s) - ''') - parser.add_argument('--heartcolor', default=defval(settings["heartcolor"]), const='red', nargs='?', choices=['red', 'blue', 'green', 'yellow', 'random'], - help='Select the color of Link\'s heart meter. (default: %(default)s)') - parser.add_argument('--ow_palettes', default=defval(settings["ow_palettes"]), choices=['default', 'random', 'blackout']) - parser.add_argument('--uw_palettes', default=defval(settings["uw_palettes"]), choices=['default', 'random', 'blackout']) - parser.add_argument('--sprite', default=defval(settings["sprite"]), help='''\ - Path to a sprite sheet to use for Link. Needs to be in - binary format and have a length of 0x7000 (28672) bytes, - or 0x7078 (28792) bytes including palette data. - Alternatively, can be a ALttP Rom patched with a Link - sprite that will be extracted. - ''') - parser.add_argument('--suppress_rom', default=defval(settings["suppress_rom"] != 0), help='Do not create an output rom file.', action='store_true') - parser.add_argument('--gui', help='Launch the GUI', action='store_true') - parser.add_argument('--jsonout', action='store_true', help='''\ - Output .json patch to stdout instead of a patched rom. Used - for VT site integration, do not use otherwise. - ''') - parser.add_argument('--skip_playthrough', action='store_true', default=defval(settings["skip_playthrough"] != 0)) - parser.add_argument('--enemizercli', default=defval(settings["enemizercli"])) - parser.add_argument('--shufflebosses', default=defval(settings["shufflebosses"]), choices=['none', 'basic', 'normal', 'chaos']) - parser.add_argument('--shuffleenemies', default=defval(settings["shuffleenemies"]), choices=['none', 'shuffled', 'chaos']) - parser.add_argument('--enemy_health', default=defval(settings["enemy_health"]), choices=['default', 'easy', 'normal', 'hard', 'expert']) - parser.add_argument('--enemy_damage', default=defval(settings["enemy_damage"]), choices=['default', 'shuffled', 'chaos']) - parser.add_argument('--shufflepots', default=defval(settings["shufflepots"] != 0), action='store_true') parser.add_argument('--beemizer', default=defval(settings["beemizer"]), type=lambda value: min(max(int(value), 0), 4)) - parser.add_argument('--remote_items', default=defval(settings["remote_items"] != 0), action='store_true') parser.add_argument('--multi', default=defval(settings["multi"]), type=lambda value: min(max(int(value), 1), 255)) - parser.add_argument('--names', default=defval(settings["names"])) parser.add_argument('--teams', default=defval(1), type=lambda value: max(int(value), 1)) - parser.add_argument('--outputpath', default=defval(settings["outputpath"])) - parser.add_argument('--race', default=defval(settings["race"] != 0), action='store_true') - parser.add_argument('--saveonexit', default=defval(settings["saveonexit"]), choices=['never', 'ask', 'always']) - parser.add_argument('--outputname') if multiargs.multi: for player in range(1, multiargs.multi + 1): @@ -386,80 +164,81 @@ def get_settings(): "race": False, "customitemarray": { "bow": 0, - "progressivebow": 2, - "boomerang": 1, - "redmerang": 1, - "hookshot": 1, - "mushroom": 1, - "powder": 1, - "firerod": 1, - "icerod": 1, - "bombos": 1, - "ether": 1, - "quake": 1, - "lamp": 1, - "hammer": 1, - "shovel": 1, - "flute": 1, - "bugnet": 1, - "book": 1, - "bottle": 4, - "somaria": 1, - "byrna": 1, - "cape": 1, - "mirror": 1, - "boots": 1, - "powerglove": 0, - "titansmitt": 0, - "progressiveglove": 2, - "flippers": 1, - "pearl": 1, - "heartpiece": 24, - "heartcontainer": 10, - "sancheart": 1, - "sword1": 0, - "sword2": 0, - "sword3": 0, - "sword4": 0, - "progressivesword": 4, - "shield1": 0, - "shield2": 0, - "shield3": 0, - "progressiveshield": 3, - "mail2": 0, - "mail3": 0, - "progressivemail": 2, - "halfmagic": 1, - "quartermagic": 0, - "bombsplus5": 0, - "bombsplus10": 0, - "arrowsplus5": 0, - "arrowsplus10": 0, - "arrow1": 1, - "arrow10": 12, - "bomb1": 0, - "bomb3": 16, - "bomb10": 1, - "rupee1": 2, - "rupee5": 4, - "rupee20": 28, - "rupee50": 7, - "rupee100": 1, - "rupee300": 5, - "blueclock": 0, - "greenclock": 0, - "redclock": 0, - "silversupgrade": 0, - "generickeys": 0, - "triforcepieces": 0, - "triforcepiecesgoal": 0, - "triforce": 0, - "rupoor": 0, - "rupoorcost": 10 - }, + "progressivebow": 2, + "boomerang": 1, + "redmerang": 1, + "hookshot": 1, + "mushroom": 1, + "powder": 1, + "firerod": 1, + "icerod": 1, + "bombos": 1, + "ether": 1, + "quake": 1, + "lamp": 1, + "hammer": 1, + "shovel": 1, + "flute": 1, + "bugnet": 1, + "book": 1, + "bottle": 4, + "somaria": 1, + "byrna": 1, + "cape": 1, + "mirror": 1, + "boots": 1, + "powerglove": 0, + "titansmitt": 0, + "progressiveglove": 2, + "flippers": 1, + "pearl": 1, + "heartpiece": 24, + "heartcontainer": 10, + "sancheart": 1, + "sword1": 0, + "sword2": 0, + "sword3": 0, + "sword4": 0, + "progressivesword": 4, + "shield1": 0, + "shield2": 0, + "shield3": 0, + "progressiveshield": 3, + "mail2": 0, + "mail3": 0, + "progressivemail": 2, + "halfmagic": 1, + "quartermagic": 0, + "bombsplus5": 0, + "bombsplus10": 0, + "arrowsplus5": 0, + "arrowsplus10": 0, + "arrow1": 1, + "arrow10": 12, + "bomb1": 0, + "bomb3": 16, + "bomb10": 1, + "rupee1": 2, + "rupee5": 4, + "rupee20": 28, + "rupee50": 7, + "rupee100": 1, + "rupee300": 5, + "blueclock": 0, + "greenclock": 0, + "redclock": 0, + "silversupgrade": 0, + "generickeys": 0, + "triforcepieces": 0, + "triforcepiecesgoal": 0, + "triforce": 0, + "rupoor": 0, + "rupoorcost": 10 + }, "randomSprite": False, "outputpath": os.path.join("."), "saveonexit": "ask", + "outputname": "", "startinventoryarray": {} } diff --git a/resources/app/cli/args.json b/resources/app/cli/args.json new file mode 100644 index 00000000..aaaff7ae --- /dev/null +++ b/resources/app/cli/args.json @@ -0,0 +1,312 @@ +{ + "create_spoiler": { + "action": "store_true", + "type": "bool" + }, + "logic": { + "choices": [ + "noglitches", + "minorglitches", + "nologic" + ] + }, + "mode": { + "choices": [ + "open", + "standard", + "inverted", + "retro" + ] + }, + "swords": { + "choices": [ + "random", + "assured", + "swordless", + "vanilla" + ] + }, + "goal": { + "choices": [ + "ganon", + "pedestal", + "dungeons", + "triforcehunt", + "crystals" + ] + }, + "difficulty": { + "choices": [ + "normal", + "hard", + "expert" + ] + }, + "item_functionality": { + "choices": [ + "normal", + "hard", + "expert" + ] + }, + "timer": { + "choices": [ + "none", + "display", + "timed", + "timed-ohko", + "ohko", + "timed-countdown" + ] + }, + "progressive": { + "choices": [ + "on", + "off", + "random" + ] + }, + "algorithm": { + "choices": [ + "balanced", + "freshness", + "flood", + "vt21", + "vt22", + "vt25", + "vt26" + ] + }, + "shuffle": { + "choices": [ + "full", + "vanilla", + "simple", + "restricted", + "crossed", + "insanity", + "restricted_legacy", + "full_legacy", + "madness_legacy", + "insanity_legacy", + "dungeonsfull", + "dungeonssimple" + ] + }, + "door_shuffle": { + "choices": [ + "basic", + "crossed", + "vanilla" + ] + }, + "experimental": { + "action": "store_true", + "type": "bool" + }, + "dungeon_counters": { + "choices": [ + "off", + "on", + "pickup", + "default" + ] + }, + "crystals_ganon": { + "choices": [ + 7, 6, 5, 4, 3, 2, 1, 0, "random" + ] + }, + "crystals_gt": { + "choices": [ + 7, 6, 5, 4, 3, 2, 1, 0, "random" + ] + }, + "openpyramid": { + "action": "store_true", + "type": "bool" + }, + "rom": {}, + "loglevel": { + "choices": [ + "info", + "error", + "warning", + "debug" + ] + }, + "fastmenu": { + "choices": [ + "normal", + "instant", + "double", + "triple", + "quadruple", + "half" + ] + }, + "quickswap": { + "action": "store_true", + "type": "bool" + }, + "disablemusic": { + "action": "store_true", + "type": "bool" + }, + "mapshuffle": { + "action": "store_true", + "type": "bool" + }, + "compassshuffle": { + "action": "store_true", + "type": "bool" + }, + "keyshuffle": { + "action": "store_true", + "type": "bool" + }, + "bigkeyshuffle": { + "action": "store_true", + "type": "bool" + }, + "keysanity": { + "action": "store_true", + "type": "bool", + "help": "suppress" + }, + "retro": { + "action": "store_true", + "type": "bool" + }, + "startinventory": {}, + "usestartinventory": { + "type": "bool" + }, + "custom": { + "type": "bool", + "help": "suppress" + }, + "accessibility": { + "choices": [ + "items", + "locations", + "none" + ] + }, + "hints": { + "action": "store_true", + "type": "bool" + }, + "shuffleganon": { + "action": "store_true", + "type": "bool", + "help": "suppress" + }, + "no-shuffleganon": { + "action": "store_false", + "dest": "shuffleganon" + }, + "heartbeep": { + "choices": [ + "normal", + "double", + "half", + "quarter", + "off" + ] + }, + "heartcolor": { + "choices": [ + "red", + "blue", + "green", + "yellow", + "random" + ] + }, + "ow_palettes": { + "choices": [ + "default", + "random", + "blackout" + ] + }, + "uw_palettes": { + "choices": [ + "default", + "random", + "blackout" + ] + }, + "sprite": {}, + "suppress_rom": { + "action": "store_true", + "type": "bool" + }, + "gui": { + "action": "store_true" + }, + "jsonout": { + "action": "store_true" + }, + "skip_playthrough": { + "action": "store_true", + "type": "bool" + }, + "enemizercli": { + "setting": "enemizercli" + }, + "shufflebosses": { + "choices": [ + "none", + "basic", + "normal", + "chaos" + ] + }, + "shuffleenemies": { + "choices": [ + "none", + "shuffled", + "chaos" + ] + }, + "enemy_health": { + "choices": [ + "default", + "easy", + "normal", + "hard", + "expert" + ] + }, + "enemy_damage": { + "choices": [ + "default", + "shuffled", + "chaos" + ] + }, + "shufflepots": { + "action": "store_true", + "type": "bool" + }, + "remote_items": { + "action": "store_true", + "type": "bool" + }, + "names": {}, + "outputpath": {}, + "race": { + "action": "store_true", + "type": "bool" + }, + "saveonexit": { + "choices": [ + "never", + "ask", + "always" + ] + }, + "outputname": {} +} diff --git a/resources/app/cli/lang/en.json b/resources/app/cli/lang/en.json new file mode 100644 index 00000000..2b1df5c9 --- /dev/null +++ b/resources/app/cli/lang/en.json @@ -0,0 +1,224 @@ +{ + "help": { + "create_spoiler": [ "Output a Spoiler File" ], + "logic": [ + "Select Enforcement of Item Requirements. (default: %(default)s)", + "No Glitches: No Glitch knowledge required.", + "Minor Glitches: May require Fake Flippers, Bunny Revival", + " and Dark Room Navigation.", + "No Logic: Distribute items without regard for", + " item requirements." + ], + "mode": [ + "Select game mode. (default: %(default)s)", + "Open: World starts with Zelda rescued.", + "Standard: Fixes Hyrule Castle Secret Entrance and Front Door", + " but may lead to weird rain state issues if you exit", + " through the Hyrule Castle side exits before rescuing", + " Zelda in a full shuffle.", + "Inverted: Starting locations are Dark Sanctuary in West Dark", + " World or at Link's House, which is shuffled freely.", + " Requires the moon pearl to be Link in the Light World", + " instead of a bunny.", + "Retro: Keys are universal, shooting arrows costs rupees,", + " and a few other little things make this more like Zelda-1." + ], + "swords": [ + "Select sword placement. (default: %(default)s)", + "Random: All swords placed randomly.", + "Assured: Start game with a sword already.", + "Swordless: No swords. Curtains in Skull Woods and Agahnim\\'s", + " Tower are removed, Agahnim\\'s Tower barrier can be", + " destroyed with hammer. Misery Mire and Turtle Rock", + " can be opened without a sword. Hammer damages Ganon.", + " Ether and Bombos Tablet can be activated with Hammer", + " (and Book). Bombos pads have been added in Ice", + " Palace, to allow for an alternative to firerod.", + "Vanilla: Swords are in vanilla locations." + ], + "goal": [ + "Select completion goal. (default: %(default)s)", + "Ganon: Collect all crystals, beat Agahnim 2 then", + " defeat Ganon.", + "Crystals: Collect all crystals then defeat Ganon.", + "Pedestal: Places the Triforce at the Master Sword Pedestal.", + "All Dungeons: Collect all crystals, pendants, beat both", + " Agahnim fights and then defeat Ganon.", + "Triforce Hunt: Places 30 Triforce Pieces in the world, collect", + " 20 of them to beat the game." + ], + "difficulty": [ + "Select game difficulty. Affects available itempool. (default: %(default)s)", + "Normal: Normal difficulty.", + "Hard: A harder setting with less equipment and reduced health.", + "Expert: A harder yet setting with minimum equipment and health." + ], + "item_functionality": [ + "Select limits on item functionality to increase difficulty. (default: %(default)s)", + "Normal: Normal functionality.", + "Hard: Reduced functionality.", + "Expert: Greatly reduced functionality." + ], + "timer": [ + "Select game timer setting. Affects available itempool. (default: %(default)s)", + "None: No timer.", + "Display: Displays a timer but does not affect", + " the itempool.", + "Timed: Starts with clock at zero. Green Clocks", + " subtract 4 minutes (Total: 20), Blue Clocks", + " subtract 2 minutes (Total: 10), Red Clocks add", + " 2 minutes (Total: 10). Winner is player with", + " lowest time at the end.", + "Timed OHKO: Starts clock at 10 minutes. Green Clocks add", + " 5 minutes (Total: 25). As long as clock is at 0,", + " Link will die in one hit.", + "OHKO: Like Timed OHKO, but no clock items are present", + " and the clock is permenantly at zero.", + "Timed Countdown:Starts with clock at 40 minutes. Same clocks as", + " Timed mode. If time runs out, you lose (but can", + " still keep playing)." + ], + "progressive": [ + "Select progressive equipment setting. Affects available itempool. (default: %(default)s)", + "On: Swords, Shields, Armor, and Gloves will", + " all be progressive equipment. Each subsequent", + " item of the same type the player finds will", + " upgrade that piece of equipment by one stage.", + "Off: Swords, Shields, Armor, and Gloves will not", + " be progressive equipment. Higher level items may", + " be found at any time. Downgrades are not possible.", + "Random: Swords, Shields, Armor, and Gloves will, per", + " category, be randomly progressive or not.", + " Link will die in one hit." + ], + "algorithm": [ + "Select item filling algorithm. (default: %(default)s)", + "balanced: vt26 derivative that aims to strike a balance between", + " the overworld heavy vt25 and the dungeon heavy vt26", + " algorithm.", + "vt26: Shuffle items and place them in a random location", + " that it is not impossible to be in. This includes", + " dungeon keys and items.", + "vt25: Shuffle items and place them in a random location", + " that it is not impossible to be in.", + "vt21: Unbiased in its selection, but has tendency to put", + " Ice Rod in Turtle Rock.", + "vt22: Drops off stale locations after 1/3 of progress", + " items were placed to try to circumvent vt21\\'s", + " shortcomings.", + "Freshness: Keep track of stale locations (ones that cannot be", + " reached yet) and decrease likeliness of selecting", + " them the more often they were found unreachable.", + "Flood: Push out items starting from Link\\'s House and", + " slightly biased to placing progression items with", + " less restrictions." + ], + "shuffle": [ + "Select Entrance Shuffling Algorithm. (default: %(default)s)", + "Full: Mix cave and dungeon entrances freely while limiting", + " multi-entrance caves to one world.", + "Simple: Shuffle Dungeon Entrances/Exits between each other", + " and keep all 4-entrance dungeons confined to one", + " location. All caves outside of death mountain are", + " shuffled in pairs and matched by original type.", + "Restricted: Use Dungeons shuffling from Simple but freely", + " connect remaining entrances.", + "Crossed: Mix cave and dungeon entrances freely while allowing", + " caves to cross between worlds.", + "Insanity: Decouple entrances and exits from each other and", + " shuffle them freely. Caves that used to be single", + " entrance will still exit to the same location from", + " which they are entered.", + "Vanilla: All entrances are in the same locations they were", + " in the base game.", + "Legacy shuffles preserve behavior from older versions of the", + "entrance randomizer including significant technical limitations.", + "The dungeon variants only mix up dungeons and keep the rest of", + "the overworld vanilla." + ], + "door_shuffle": [ + "Select Door Shuffling Algorithm. (default: %(default)s)", + "Basic: Doors are mixed within a single dungeon.", + "Crossed: Doors are mixed between all dungeons.", + "Vanilla: All doors are connected the same way they were in the", + " base game." + ], + "experimental": [ "Enable experimental features. (default: %(default)s)" ], + "dungeon_counters": [ "Enable dungeon chest counters. (default: %(default)s)" ], + "crystals_ganon": [ + "How many crystals are needed to defeat ganon. Any other", + "requirements for ganon for the selected goal still apply.", + "This setting does not apply when the all dungeons goal is", + "selected. (default: %(default)s)", + "Random: Picks a random value between 0 and 7 (inclusive).", + "0-7: Number of crystals needed" + ], + "crystals_gt": [ + "How many crystals are needed to open GT. For inverted mode", + "this applies to the castle tower door instead. (default: %(default)s)", + "Random: Picks a random value between 0 and 7 (inclusive).", + "0-7: Number of crystals needed" + ], + "openpyramid": [ "Pre-opens the pyramid hole, this removes the Agahnim 2 requirement for it. (default: %(default)s)" ], + "rom": [ + "Path to an ALttP JP (1.0) rom to use as a base." , + "(default: %(default)s)" + ], + "loglevel": [ "Select level of logging for output. (default: %(default)s)" ], + "seed": [ "Define seed number to generate." ], + "count": [ + "Use to batch generate multiple seeds with same settings.", + "If --seed is provided, it will be used for the first seed, then", + "used to derive the next seed (i.e. generating %(default)s seed(s) with", + "--seed given will produce the same %(default)s (different) rom(s) each", + "time)." + ], + "fastmenu": [ + "Select the rate at which the menu opens and closes. (default: %(default)s)" + ], + "quickswap": [ "Enable quick item swapping with L and R. (default: %(default)s)" ], + "disablemusic": [ "Disables game music including MSU-1. (default: %(default)s)" ], + "mapshuffle": [ "Maps are no longer restricted to their dungeons, but can be anywhere. (default: %(default)s)" ], + "compassshuffle": [ "Compasses are no longer restricted to their dungeons, but can be anywhere. (default: %(default)s)" ], + "keyshuffle": [ "Small Keys are no longer restricted to their dungeons, but can be anywhere. (default: %(default)s)" ], + "bigkeyshuffle": [ "Big Keys are no longer restricted to their dungeons, but can be anywhere. (default: %(default)s)" ], + "retro": [ + "Keys are universal, shooting arrows costs rupees,", + "and a few other little things make this more like Zelda-1. (default: %(default)s)" + ], + "startinventory": [ "Specifies a list of items that will be in your starting inventory (separated by commas). (default: %(default)s)" ], + "usestartinventory": [ "Toggle usage of Starting Inventory." ], + "custom": [ "Not supported." ], + "customitemarray": [ "Not supported." ], + "accessibility": [ + "Select Item/Location Accessibility. (default: %(default)s)", + "Items: You can reach all unique inventory items. No guarantees about", + " reaching all locations or all keys.", + "Locations: You will be able to reach every location in the game.", + "None: You will be able to reach enough locations to beat the game." + ], + "hints": [ "Make telepathic tiles and storytellers give helpful hints. (default: %(default)s)" ], + "no-shuffleganon": [ + "If set, the Pyramid Hole and Ganon's Tower are not", + "included entrance shuffle pool. (default: %(default)s)" + ], + "heartbeep": [ + "Select the rate at which the heart beep sound is played at", + "low health. (default: %(default)s)" + ], + "heartcolor": [ "Select the color of Link\\'s heart meter. (default: %(default)s)" ], + "sprite": [ + "Path to a sprite sheet to use for Link. Needs to be in", + "binary format and have a length of 0x7000 (28672) bytes,", + "or 0x7078 (28792) bytes including palette data.", + "Alternatively, can be a ALttP Rom patched with a Link", + "sprite that will be extracted." + ], + "suppress_rom": [ "Do not create an output rom file. (default: %(default)s)" ], + "gui": [ "Launch the GUI. (default: %(default)s)" ], + "jsonout": [ + "Output .json patch to stdout instead of a patched rom. Used", + "for VT site integration, do not use otherwise. (default: %(default)s)" + ] + } +} diff --git a/source/classes/BabelFish.py b/source/classes/BabelFish.py index 972d3eac..d2b52765 100644 --- a/source/classes/BabelFish.py +++ b/source/classes/BabelFish.py @@ -12,6 +12,7 @@ class BabelFish(): self.lang_defns = {} #collect translations self.add_translation_file() #start with default translation file + self.add_translation_file(["resources","app","cli"]) #add help translation file self.add_translation_file(["resources","user","meta"]) #add user translation file def add_translation_file(self,subpath=["resources","app","meta"]):