Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
42cb7e7
Adding Auto Life 3 and Auto Dog Block objective results (#36)
asilverthorn Dec 18, 2022
c2d1f2b
Stray Flash mod (#33)
asilverthorn Dec 18, 2022
8836319
Adding Osteoclave's bugfix (#29)
asilverthorn Dec 18, 2022
7eb5948
Adding expensive rods and super balls flags (#27)
asilverthorn Dec 18, 2022
32f824a
Bugfix: Fix weapon special abilities with Capture and Multi-steals on…
asilverthorn Dec 18, 2022
45d3c4d
Feature: Flashes: Moving flashes to Graphics; Slowing scrolling backg…
asilverthorn Dec 18, 2022
cb16371
Feature: Adding flags to improve Sketch/Control (#19)
asilverthorn Dec 18, 2022
116a1fe
Feature: Kielbasiago's Adding flag for giving starting Espers (#18)
asilverthorn Dec 18, 2022
bc3b19a
Feature: Kielbasiago's Update ability to shuffle/mix both dragons and…
asilverthorn Dec 18, 2022
995cc33
Feature: Magic MP Randomization (#15)
asilverthorn Dec 18, 2022
f6a6fd4
Adding --starting-level flag (#14)
asilverthorn Dec 18, 2022
ccc66f4
QoL: Adding Rage Move descriptions to rage menu (#13)
asilverthorn Dec 18, 2022
a134980
Feature: Add Remove learnable spells flag + Submenus (#12)
asilverthorn Dec 18, 2022
1f5509d
Removing excluded non-S tier items from tiered or scaled chests (#11)
asilverthorn Dec 18, 2022
72e91b3
Ensuring that Gau can use Magic in FT (#10)
asilverthorn Dec 18, 2022
a277906
Feature: Adding random-encounters-chupon flag (#8)
asilverthorn Dec 18, 2022
0875363
Feature: Kielbasiago's add --start-junk flag (#7)
asilverthorn Dec 18, 2022
55355a7
QoL: Setting default config options to most commonly used values (#6)
asilverthorn Dec 18, 2022
6d76ecf
Making Party warp to Arvis house following K@N (#4)
asilverthorn Dec 18, 2022
2662a91
Feature: Adding -llr flag to randomize L.x lore levels (#3)
asilverthorn Dec 18, 2022
84cc4ba
QoL: Adding clarification of quantity of objective conditions require…
asilverthorn Dec 18, 2022
fda3380
Update version.py
ff6wc Dec 18, 2022
0bfde9d
Update flags.py
ff6wc Dec 19, 2022
5e87370
Update spells.py
ff6wc Dec 19, 2022
a018e84
Feature: Making Top 4 Magitek commands an objective result (#21)
asilverthorn Dec 19, 2022
766f299
Feature: Adding warp-all flag for 0 cost starting Warp (#9)
asilverthorn Dec 19, 2022
a10b2d8
Adding -hf flag to hide flags for fun mystery seeds (#2)
asilverthorn Dec 19, 2022
7996184
Feature: Add movement options, b-dash, sprint shoe options
kielbasiago Feb 26, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions args/arguments.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ def __init__(self):
self.groups = [
"settings",
"objectives",
"starting_party", "characters", "swdtechs", "blitzes", "lores", "rages", "dances", "steal", "commands",
"starting_party", "characters", "swdtechs", "blitzes", "lores", "rages", "dances", "steal", "sketch_control", "commands",
"xpmpgp", "scaling", "bosses", "encounters", "boss_ai",
"espers", "natural_magic",
"espers", "natural_magic", "misc_magic",
"starting_gold_items", "items", "shops", "chests",
"graphics",
"coliseum", "auction_house", "challenges", "bug_fixes", "misc",
Expand All @@ -25,6 +25,7 @@ def __init__(self):

self.parser.add_argument("-nro", dest = "no_rom_output", action = "store_true", help = "Do not output a modified rom file")
self.parser.add_argument("-slog", dest = "stdout_log", action = "store_true", help = "Write log to stdout instead of file")
self.parser.add_argument("-hf", dest = "hide_flags", action = "store_true", help = "Hide Flags (no log, no flags menu)")

for group in self.group_modules.values():
group.parse(self.parser)
Expand Down
47 changes: 42 additions & 5 deletions args/bosses.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
from data.bosses import BossLocations


DEFAULT_DRAGON_PROTOCOL = BossLocations.SHUFFLE
DEFAULT_STATUE_PROTOCOL = BossLocations.MIX
def name():
return "Bosses"

Expand All @@ -9,8 +14,17 @@ def parse(parser):
help = "Boss battles shuffled")
bosses_battles.add_argument("-bbr", "--boss-battles-random", action = "store_true",
help = "Boss battles randomized")
bosses.add_argument("-bmbd", "--mix-bosses-dragons", action = "store_true",

dragons = bosses.add_mutually_exclusive_group()
dragons.add_argument("-drloc", "--dragon-boss-location", default = DEFAULT_DRAGON_PROTOCOL, type = str.lower, choices = BossLocations.ALL,
help = "Decides which locations the eight dragon encounters can be fought")
dragons.add_argument("-bmbd", "--mix-bosses-dragons", action = "store_true",
help = "Shuffle/randomize bosses and dragons together")

statues = bosses.add_mutually_exclusive_group()
statues.add_argument("-stloc", "--statue-boss-location", default = DEFAULT_STATUE_PROTOCOL, type = str.lower, choices = BossLocations.ALL,
help = "Decides which locations the three statue encounters can be fought")

bosses.add_argument("-srp3", "--shuffle-random-phunbaba3", action = "store_true",
help = "Apply Shuffle/Random to Phunbaba 3 (otherwise he will only appear in Mobliz WOR)")
bosses.add_argument("-bnds", "--boss-normalize-distort-stats", action = "store_true",
Expand All @@ -21,7 +35,15 @@ def parse(parser):
help = "Undead status removed from bosses")

def process(args):
pass
if args.mix_bosses_dragons:
args.dragon_boss_location = BossLocations.MIX
args.mix_bosses_dragons = None
# if neither shuffling or randomizing bosses, and we try to mix the dragons/statues, simply shuffle them instead
vanilla_locations = not (args.boss_battles_shuffle or args.boss_battles_random)
if vanilla_locations and args.dragon_boss_location == BossLocations.MIX:
args.dragon_boss_location = BossLocations.SHUFFLE
if vanilla_locations and args.statue_boss_location == BossLocations.MIX:
args.statue_boss_location = BossLocations.SHUFFLE

def flags(args):
flags = ""
Expand All @@ -31,8 +53,14 @@ def flags(args):
elif args.boss_battles_random:
flags += " -bbr"

if args.mix_bosses_dragons:
flags += " -bmbd"
if args.dragon_boss_location:
flags += f" -drloc {args.dragon_boss_location}"
elif args.mix_bosses_dragons:
flags += f" -drloc {BossLocations.MIX}"

if args.statue_boss_location:
flags += f" -stloc {args.statue_boss_location}"

if args.shuffle_random_phunbaba3:
flags += " -srp3"
if args.boss_normalize_distort_stats:
Expand All @@ -51,9 +79,18 @@ def options(args):
elif args.boss_battles_random:
boss_battles = "Random"

dragon_battles = DEFAULT_DRAGON_PROTOCOL
if args.dragon_boss_location:
dragon_battles = args.dragon_boss_location.capitalize()

statue_battles = DEFAULT_DRAGON_PROTOCOL
if args.statue_boss_location:
statue_battles = args.statue_boss_location.capitalize()

return [
("Boss Battles", boss_battles),
("Mix Bosses & Dragons", args.mix_bosses_dragons),
("Dragons", dragon_battles),
("Statues", statue_battles),
("Shuffle/Random Phunbaba 3", args.shuffle_random_phunbaba3),
("Normalize & Distort Stats", args.boss_normalize_distort_stats),
("Boss Experience", args.boss_experience),
Expand Down
5 changes: 5 additions & 0 deletions args/bug_fixes.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ def parse(parser):
help = "Poltergeist and Inferno in Kefka's Tower cannot be skipped")
bug_fixes.add_argument("-fedc", "--fix-enemy-damage-counter", action = "store_true",
help = "Enemy damage counters only trigger if HP is reduced")
bug_fixes.add_argument("-fc", "--fix-capture", action = "store_true",
help = "Fix Capture such that Weapon Special Effects are applied and Multi-Steals work")

def process(args):
pass
Expand All @@ -38,6 +40,8 @@ def flags(args):
flags += " -fbs"
if args.fix_enemy_damage_counter:
flags += " -fedc"
if args.fix_capture:
flags += " -fc"

return flags

Expand All @@ -50,6 +54,7 @@ def options(args):
("Jump", args.fix_jump),
("Boss Skip", args.fix_boss_skip),
("Enemy Damage Counter", args.fix_enemy_damage_counter),
("Capture", args.fix_capture),
]

def menu(args):
Expand Down
86 changes: 82 additions & 4 deletions args/challenges.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,57 @@ def parse(parser):
help = "Exp. Eggs will not appear in coliseum/auction/shops/chests/events")
challenges.add_argument("-nil", "--no-illuminas", action = "store_true",
help = "Illuminas will not appear in coliseum/auction/shops/chests/events")
challenges.add_argument("-nu", "--no-ultima", action = "store_true",
ultima = challenges.add_mutually_exclusive_group()
challenges.add_argument("-noshoes", "--no-sprint-shoes", action = "store_true",
help = "Sprint Shoes will not appear in coliseum/auction/shops/chests")
ultima.add_argument("-nu", "--no-ultima", action = "store_true",
help = "Ultima cannot be learned from espers/items/natural magic")
ultima.add_argument("-u254", "--ultima-254-mp", action = "store_true",
help = "Ultima costs 254 MP")
challenges.add_argument("-nfps", "--no-free-paladin-shields", action = "store_true",
help = "Paladin/Cursed Shields will not appear in coliseum/auction/shops/chests/events (Narshe WOR exclusive)")
challenges.add_argument("-nfce", "--no-free-characters-espers", action = "store_true",
help = "Remove character/esper rewards from: Auction House, Collapsing House, Figaro Castle Throne, Gau's Father's House, Kohlingen Inn, Narshe Weapon Shop, Sealed Gate, South Figaro Basement")
challenges.add_argument("-pd", "--permadeath", action = "store_true",
help = "Life spells cannot be learned. Fenix Downs unavailable (except from starting items). Buckets/inns/tents/events do not revive characters. Phoenix casts Life 3 on party instead of Life")
challenges.add_argument("-rls", "--remove-learnable-spells", type = str,
help = "Remove spells from learnable sources: Items, Espers, Natural Magic, and Objectives")

def process(args):
pass
from constants.spells import black_magic_ids, white_magic_ids, gray_magic_ids, spell_id

# If no_ultima is on, add it to our exclude list for downstream use
# If permadeath is on, add it to our exclude list for downstream use
args.remove_learnable_spell_ids = []
if args.no_ultima:
args.remove_learnable_spell_ids.append(spell_id["Ultima"])
if args.permadeath:
args.remove_learnable_spell_ids.append(spell_id["Life"])
args.remove_learnable_spell_ids.append(spell_id["Life 2"])

if args.remove_learnable_spells:
# Split the comma-separated string
for a_spell_id in args.remove_learnable_spells.split(','):
# look for strings first
a_spell_id = a_spell_id.lower().strip()
if a_spell_id == 'all':
args.remove_learnable_spell_ids.extend(range(len(spell_id)))
elif a_spell_id == 'white':
args.remove_learnable_spell_ids.extend(white_magic_ids)
elif a_spell_id == 'black':
args.remove_learnable_spell_ids.extend(black_magic_ids)
elif a_spell_id == 'gray' or a_spell_id == 'grey':
args.remove_learnable_spell_ids.extend(gray_magic_ids)
else:
spell_ids_lower = {k.lower():v for k,v in spell_id.items()}
if a_spell_id in spell_ids_lower:
args.remove_learnable_spell_ids.append(spell_ids_lower[a_spell_id])
else:
# assuming it's a number... it'll error out if not
args.remove_learnable_spell_ids.append(int(a_spell_id))
# remove duplicates and sort
args.remove_learnable_spell_ids = list(set(args.remove_learnable_spell_ids))
args.remove_learnable_spell_ids.sort()

def flags(args):
flags = ""
Expand All @@ -30,36 +70,64 @@ def flags(args):
flags += " -nee"
if args.no_illuminas:
flags += " -nil"
if args.no_sprint_shoes:
flags += " -noshoes"

if args.no_ultima:
flags += " -nu"
elif args.ultima_254_mp:
flags += " -u254"

if args.no_free_paladin_shields:
flags += " -nfps"
if args.no_free_characters_espers:
flags += " -nfce"
if args.permadeath:
flags += " -pd"
if args.remove_learnable_spells:
flags += f" -rls {args.remove_learnable_spells}"

return flags

def options(args):
ultima = "Original"
if args.no_ultima:
ultima = "No"
elif args.ultima_254_mp:
ultima = "254 MP"

return [
("No Moogle Charms", args.no_moogle_charms),
("No Exp Eggs", args.no_exp_eggs),
("No Illuminas", args.no_illuminas),
("No Ultima", args.no_ultima),
("Ultima", ultima),
("No Sprint Shoes", args.no_sprint_shoes),
("No Free Paladin Shields", args.no_free_paladin_shields),
("No Free Characters/Espers", args.no_free_characters_espers),
("Permadeath", args.permadeath),
("Remove Learnable Spells", args.remove_learnable_spell_ids),
]

def _format_spells_log_entries(spell_ids):
from constants.spells import id_spell
spell_entries = []
for spell_id in spell_ids:
spell_entries.append(("", id_spell[spell_id]))
return spell_entries

def menu(args):
from menus.flags_remove_learnable_spells import FlagsRemoveLearnableSpells

entries = options(args)
for index, entry in enumerate(entries):
key, value = entry
if key == "No Free Paladin Shields":
entries[index] = ("No Free Paladin Shlds", entry[1])
elif key == "No Free Characters/Espers":
entries[index] = ("No Free Chars/Espers", entry[1])
elif key == "Remove Learnable Spells":
entries[index] = ("Remove L. Spells", FlagsRemoveLearnableSpells(value)) # flags sub-menu

return (name(), entries)

def log(args):
Expand All @@ -68,6 +136,16 @@ def log(args):

entries = options(args)
for entry in entries:
log.append(format_option(*entry))
key, value = entry
if key == "Remove Learnable Spells":
if len(value) == 0:
entry = (key, "None")
else:
entry = (key, "") # The entries will show up on subsequent lines
log.append(format_option(*entry))
for spell_entry in _format_spells_log_entries(value):
log.append(format_option(*spell_entry))
else:
log.append(format_option(*entry))

return log
5 changes: 5 additions & 0 deletions args/characters.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ def parse(parser):

characters.add_argument("-sal", "--start-average-level", action = "store_true",
help = "Recruited characters start at the average character level")
characters.add_argument("-stl", "--start-level", default = 3, type = int, choices = range(3, 100), metavar = "COUNT",
help = "Start game at level %(metavar)s.")
characters.add_argument("-sn", "--start-naked", action = "store_true",
help = "Recruited characters start with no equipment")
characters.add_argument("-eu", "--equipable-umaro", action = "store_true",
Expand All @@ -22,6 +24,8 @@ def flags(args):

if args.start_average_level:
flags += " -sal"
if args.start_level != 3:
flags += f" -stl {args.start_level}"
if args.start_naked:
flags += " -sn"
if args.equipable_umaro:
Expand All @@ -36,6 +40,7 @@ def options(args):

return [
("Start Average Level", args.start_average_level),
("Start Level", args.start_level),
("Start Naked", args.start_naked),
("Equipable Umaro", args.equipable_umaro),
("Character Stats", character_stats),
Expand Down
6 changes: 6 additions & 0 deletions args/encounters.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ def parse(parser):
random.add_argument("-rer", "--random-encounters-random",
default = None, type = int, metavar = "PERCENT", choices = range(101),
help = "Random encounters are randomized")
random.add_argument("-rechu", "--random-encounters-chupon", action = "store_true",
help = "All Random Encounters are replaced with Chupon (Coliseum)")

fixed = encounters.add_mutually_exclusive_group()
fixed.add_argument("-fer", "--fixed-encounters-random",
Expand All @@ -33,6 +35,8 @@ def flags(args):
flags += " -res"
elif args.random_encounters_random is not None:
flags += f" -rer {args.random_encounters_random}"
elif args.random_encounters_chupon:
flags += " -rechu"

if args.fixed_encounters_random is not None:
flags += f" -fer {args.fixed_encounters_random}"
Expand All @@ -50,6 +54,8 @@ def options(args):
random_encounters = "Shuffle"
elif args.random_encounters_random is not None:
random_encounters = "Random"
elif args.random_encounters_chupon:
random_encounters = "Chupon"

result.append(("Random Encounters", random_encounters))
if args.random_encounters_random is not None:
Expand Down
22 changes: 21 additions & 1 deletion args/espers.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
from data.espers import Espers
from event.event_reward import CHARACTER_ESPER_ONLY_REWARDS

# If all 27 espers are allocated at start, there will be logic errors when it comes to
# assigning characters to character/esper only checks.
# We would have to ensure that a character is assigned to the {6} char/esper only rewards.
# We could account for this in the logic, but it would gentrify the routing logic a bit much.
MAX_STARTING_ESPERS = Espers.ESPER_COUNT - CHARACTER_ESPER_ONLY_REWARDS

def name():
return "Espers"

Expand All @@ -6,7 +15,13 @@ def parse(parser):
from data.characters import Characters
espers = parser.add_argument_group("Espers")

esper_start = espers.add_mutually_exclusive_group()
esper_start.add_argument("-stesp", "--starting-espers", default = [0, 0], type = int,
nargs = 2, metavar = ("MIN", "MAX"), choices = range(MAX_STARTING_ESPERS + 1),
help = "Party starts with %(metavar) random espers")

esper_spells = espers.add_mutually_exclusive_group()

esper_spells.add_argument("-esrr", "--esper-spells-random-rates", action = "store_true",
help = "Original esper spells with random learn rates")
esper_spells.add_argument("-ess", "--esper-spells-shuffle", action = "store_true",
Expand All @@ -30,7 +45,7 @@ def parse(parser):
esper_mp.add_argument("-emps", "--esper-mp-shuffle", action = "store_true",
help = "Esper MP costs shuffled")
esper_mp.add_argument("-emprv", "--esper-mp-random-value", default = None, type = int,
nargs = 2, metavar = ("MIN", "MAX"), choices = range(129),
nargs = 2, metavar = ("MIN", "MAX"), choices = range(255),
help = "Each esper's MP cost set to random value within given range")
esper_mp.add_argument("-emprp", "--esper-mp-random-percent", default = None, type = int,
nargs = 2, metavar = ("MIN", "MAX"), choices = range(201),
Expand All @@ -50,6 +65,7 @@ def parse(parser):
help = "Espers can be summoned multiple times in battle")

def process(args):
args._process_min_max("starting_espers")
args._process_min_max("esper_spells_random")
args._process_min_max("esper_mp_random_value")
args._process_min_max("esper_mp_random_percent")
Expand All @@ -66,6 +82,9 @@ def process(args):
def flags(args):
flags = ""

if args.starting_espers_min or args.starting_espers_max:
flags += f" -stesp {args.starting_espers_min} {args.starting_espers_max}"

if args.esper_spells_random_rates:
flags += " -esrr"
elif args.esper_spells_shuffle:
Expand Down Expand Up @@ -133,6 +152,7 @@ def options(args):
equipable = f"Balanced Random {args.esper_equipable_balanced_random_value}"

result = []
result.append(("Starting Espers", f"{args.starting_espers_min}-{args.starting_espers_max}"))
result.append(("Spells", spells))
result.append(("Bonuses", bonuses))
if args.esper_bonuses_random:
Expand Down
Loading