From e16fac95489fef9d1d709bc436bf840eab6d375a Mon Sep 17 00:00:00 2001 From: mhn65536 <53567009+mhn65536@users.noreply.github.com> Date: Tue, 26 Nov 2024 17:31:13 +0100 Subject: [PATCH] i shall be squashed anyway (#1097) --- FF1Blazorizer/Tabs/AdjustmentsTab.razor | 1 + FF1Blazorizer/wwwroot/tooltips/tooltips.json | 6 + FF1Lib/Flags/Flags.cs | 1460 +++++++++--------- FF1Lib/Hacks.cs | 10 + FF1Lib/Randomize.cs | 891 +++++------ 5 files changed, 1194 insertions(+), 1174 deletions(-) diff --git a/FF1Blazorizer/Tabs/AdjustmentsTab.razor b/FF1Blazorizer/Tabs/AdjustmentsTab.razor index d9290d28a..ddce798a3 100644 --- a/FF1Blazorizer/Tabs/AdjustmentsTab.razor +++ b/FF1Blazorizer/Tabs/AdjustmentsTab.razor @@ -60,6 +60,7 @@

Other Tweaks

TRANCE is Status Element Increase Dark Penalty + Increase Enemy Regeneration Disable Minimap In-Battle Poison Damage: Damage: diff --git a/FF1Blazorizer/wwwroot/tooltips/tooltips.json b/FF1Blazorizer/wwwroot/tooltips/tooltips.json index 0f6de6287..19c0359e8 100644 --- a/FF1Blazorizer/wwwroot/tooltips/tooltips.json +++ b/FF1Blazorizer/wwwroot/tooltips/tooltips.json @@ -2349,6 +2349,12 @@ "screenshot": "increaseDarkPenaltyCheckBox.png", "description": "If enabled, \"Dark\" status severely decreases an attacker's chance to hit or crit an enemy: their crit chance is set to 0%, and they lose all of their base hit chance (this effectively makes the penalty -168 instead of the normal -40), leaving them with only their Hit% vs the defender's Evasion.\nAffects both players and enemies inflicted with \"Dark\" status." }, + { + "Id": "increaseRegenerationCheckBox", + "title": "Increase Enemy Regeneration", + "screenshot": null, + "description": "If enabled, \"Regeneration\" category enemies heal 57HP per turn instead of 3HP." + }, { "Id": "poisonModeDropDown", "title": "In-Battle Poison Damage", diff --git a/FF1Lib/Flags/Flags.cs b/FF1Lib/Flags/Flags.cs index dce1227f0..13e6427b6 100644 --- a/FF1Lib/Flags/Flags.cs +++ b/FF1Lib/Flags/Flags.cs @@ -1,729 +1,731 @@ -using System.Numerics; -using System.Reflection; -using Newtonsoft.Json; -using System.IO.Compression; -using static FF1Lib.FF1Rom; -using FF1Lib.Sanity; -using System.ComponentModel; - -namespace FF1Lib -{ - public partial class Flags : IIncentiveFlags, IScaleFlags, IVictoryConditionFlags, IFloorShuffleFlags, IItemPlacementFlags - { - #region StartingEquipment - - public bool? StartingEquipmentMasamune { get; set; } = false; - - public bool? StartingEquipmentKatana { get; set; } = false; - - public bool? StartingEquipmentHealStaff { get; set; } = false; - - public bool? StartingEquipmentZeusGauntlet { get; set; } = false; - - public bool? StartingEquipmentWhiteShirt { get; set; } = false; - - public bool? StartingEquipmentRibbon { get; set; } = false; - - public bool? StartingEquipmentDragonslayer { get; set; } = false; - - public bool? StartingEquipmentLegendKit { get; set; } = false; - - public bool? StartingEquipmentRandomEndgameWeapon { get; set; } = false; - - public bool? StartingEquipmentRandomAoe { get; set; } = false; - - public bool? StartingEquipmentRandomCasterItem { get; set; } = false; - - public bool? StartingEquipmentGrandpasSecretStash { get; set; } = false; - - public bool? StartingEquipmentOneItem { get; set; } = false; - - public bool? StartingEquipmentRandomCrap { get; set; } = false; - - public bool? StartingEquipmentStarterPack { get; set; } = false; - - public bool? StartingEquipmentRandomTypeWeapon { get; set; } = false; - - public bool StartingEquipmentRemoveFromPool { get; set; } = false; - - public bool StartingEquipmentNoDuplicates { get; set; } = false; - - #endregion - - public bool? ReversedFloors { get; set; } = false; - public bool BuffTier1DamageSpells { get; set; } = false; - public bool NoEmptyScripts { get; set; } = false; - public bool LaterLoose { get; set; } = false; - public bool? MermaidPrison { get; set; } = false; - - public GuaranteedDefenseItem GuaranteedDefenseItem { get; set; } = GuaranteedDefenseItem.None; - - public GuaranteedPowerItem GuaranteedPowerItem { get; set; } = GuaranteedPowerItem.None; - - public ScriptTouchMultiplier ScriptMultiplier { get; set; } = ScriptTouchMultiplier.Vanilla; - public ScriptTouchMultiplier TouchMultiplier { get; set; } = ScriptTouchMultiplier.Vanilla; - public TouchPool TouchPool { get; set; } = TouchPool.All; - public TouchMode TouchMode { get; set; } = TouchMode.Standard; - public RibbonMode RibbonMode { get; set; } = RibbonMode.Vanilla; - - public bool Archipelago { get; set; } = false; - public bool ArchipelagoGold { get; set; } = false; - public bool ArchipelagoConsumables { get; set; } = false; - public bool ArchipelagoShards { get; set; } = false; - public ArchipelagoEquipment ArchipelagoEquipment { get; set; } = ArchipelagoEquipment.None; - - public ItemMagicMode ItemMagicMode { get; set; } = ItemMagicMode.Vanilla; - public ItemMagicPool ItemMagicPool { get; set; } = ItemMagicPool.All; - public bool? MagisizeWeapons { get; set; } = false; - - public bool DisableMinimap { get; set; } = false; - - public bool LooseItemsForwardPlacement { get; set; } = false; - - public bool LooseItemsSpreadPlacement { get; set; } = false; - - public bool LooseItemsNpcBalance { get; set; } = false; - public bool AllowUnsafePlacement { get; set; } = false; - public bool ShipCanalBeforeFloater { get; set; } = false; - - [IntegerFlag(0, 100, 10)] - public int ExpChestConversionMin { get; set; } = 0; - - [IntegerFlag(0, 100, 10)] - public int ExpChestConversionMax { get; set; } = 0; - - [IntegerFlag(0, 20000, 500)] - public int ExpChestMinReward { get; set; } = 2000; - - [IntegerFlag(0, 20000, 500)] - public int ExpChestMaxReward { get; set; } = 8000; - - public SpellNameMadness SpellNameMadness { get; set; } = SpellNameMadness.None; - - public ExtConsumableSet ExtConsumableSet { get; set; } = ExtConsumableSet.None; - - public bool EnableSoftInBattle { get; set; } = false; - public LifeInBattleSetting EnableLifeInBattle { get; set; } = LifeInBattleSetting.LifeInBattleAll; - - public bool? NormalShopsHaveExtConsumables { get; set; } = false; - - public bool? LegendaryShopHasExtConsumables { get; set; } = false; - - public TreasureStackSize ExtConsumableTreasureStackSize { get; set; } = TreasureStackSize.Default; - - public ExtStartingItemSet ExtStartingItemSet { get; set; } = ExtStartingItemSet.None; - - public ExtConsumableChestSet ExtConsumableChests { get; set; } = ExtConsumableChestSet.None; - - public OwMapExchanges OwMapExchange { get; set; } = OwMapExchanges.None; - public bool OwShuffledAccess { get; set; } = false; - public bool OwUnsafeStart { get; set; } = false; - public bool OwRandomPregen { get; set; } = false; - - public bool? RelocateChests { get; set; } = false; - public bool RelocateChestsTrapIndicator { get; set; } = false; - - public bool? ShuffleChimeAccess { get; set; } = false; - public bool? ShuffleChimeIncludeTowns { get; set; } = false; - - public GameModes GameMode { get; set; } = GameModes.Standard; - - [IntegerFlag(0, Int32.MaxValue-1)] - public int MapGenSeed { get; set; } = 0; - - public OwMapExchangeData ReplacementMap { get; set; } = null; - - public string ResourcePack { get; set; } = null; - - #region ShopKiller - - public ShopKillMode ShopKillMode_Weapons { get; set; } = ShopKillMode.None; - public ShopKillMode ShopKillMode_Armor { get; set; } = ShopKillMode.None; - public ShopKillMode ShopKillMode_Item { get; set; } = ShopKillMode.None; - public ShopKillMode ShopKillMode_Black { get; set; } = ShopKillMode.None; - public ShopKillMode ShopKillMode_White { get; set; } = ShopKillMode.None; - - public ShopKillFactor ShopKillFactor_Weapons { get; set; } = ShopKillFactor.Kill20Percent; - public ShopKillFactor ShopKillFactor_Armor { get; set; } = ShopKillFactor.Kill20Percent; - public ShopKillFactor ShopKillFactor_Item { get; set; } = ShopKillFactor.Kill20Percent; - public ShopKillFactor ShopKillFactor_Black { get; set; } = ShopKillFactor.Kill20Percent; - public ShopKillFactor ShopKillFactor_White { get; set; } = ShopKillFactor.Kill20Percent; - - public bool ShopKillExcludeConeria_Weapons { get; set; } = false; - public bool ShopKillExcludeConeria_Armor { get; set; } = false; - public bool ShopKillExcludeConeria_Item { get; set; } = false; - public bool ShopKillExcludeConeria_Black { get; set; } = false; - public bool ShopKillExcludeConeria_White { get; set; } = false; - - #endregion - - public bool? ExcludeGoldFromScaling { get; set; } = false; - public bool CheapVendorItem { get; set; } = false; - - public StartingLevel StartingLevel { get; set; } - public TransmooglifierVariance TransmooglifierVariance { get; set; } - - [IntegerFlag(1, 50)] - public int MaxLevelLow { get; set; } = 50; - [IntegerFlag(1, 50)] - public int MaxLevelHigh { get; set; } = 50; - - public bool Spoilers { get; set; } = false; - public bool TournamentSafe { get; set; } = false; - public bool BlindSeed { get; set; } = false; - public bool? Shops { get; set; } = false; - public bool? Treasures { get; set; } = false; - public bool? ChestsKeyItems { get; set; } = false; - public bool? NPCItems { get; set; } = false; - public bool? NPCFetchItems { get; set; } = false; - public bool? RandomWares { get; set; } = false; - public bool? RandomWaresIncludesSpecialGear { get; set; } = false; - public bool? RandomLoot { get; set; } = false; - - public bool ShardHunt { get; set; } = false; - public ShardCount ShardCount { get; set; } = ShardCount.Count16; - - [IntegerFlag(0, 5)] - public int OrbsRequiredCount { get; set; } = 4; - public OrbsRequiredMode OrbsRequiredMode { get; set; } = OrbsRequiredMode.Any; - public bool? OrbsRequiredSpoilers { get; set; } = false; - public FinalFormation TransformFinalFormation { get; set; } = FinalFormation.None; - public bool? ChaosRush { get; set; } = false; - public ToFRMode ToFRMode { get; set; } = ToFRMode.Long; - public FiendsRefights FiendsRefights { get; set; } = FiendsRefights.All; - public bool? ExitToFR { get; set; } = false; - public bool? ChaosFloorEncounters { get; set; } = false; - public bool? MagicShops { get; set; } = false; - public bool? MagicShopLocs { get; set; } = false; - public bool? MagicShopLocationPairs { get; set; } = false; - public bool? MagicLevels { get; set; } = false; - public bool? MagicPermissions { get; set; } = false; - public bool? Weaponizer { get; set; } = false; - public bool? WeaponizerNamesUseQualityOnly { get; set; } = false; - public bool? WeaponizerCommonWeaponsHavePowers { get; set; } = false; - public bool? ArmorCrafter { get; set; } = false; - public bool? MagicLevelsTiered { get; set; } = false; - public bool? MagicLevelsMixed { get; set; } = false; - - public AutohitThreshold MagicAutohitThreshold { get; set; } = AutohitThreshold.Vanilla; - - public bool? Rng { get; set; } = false; - public bool FixMissingBattleRngEntry { get; set; } = false; - - public bool? EncounterPrng { get; set; } = false; - - public bool? UnrunnableShuffle { get; set; } = true; - [IntegerFlag(0, 100, 4)] - public int UnrunnablesLow { get; set; } = 0; - [IntegerFlag(0, 100, 4)] - public int UnrunnablesHigh { get; set; } = 0; - public bool? EnemyFormationsSurprise { get; set; } = false; - public bool? UnrunnablesStrikeFirstAndSurprise { get; set; } = false; - - public TrapTileMode EnemyTrapTiles { get; set; } = TrapTileMode.Vanilla; - public FormationPool TCFormations { get; set; } = FormationPool.AltFormationDist; - public TCOptions TCBetterTreasure { get; set; } = TCOptions.None; - public TCOptions TCKeyItems { get; set; } = TCOptions.None; - public TCOptions TCShards { get; set; } = TCOptions.None; - public bool TCExcludeCommons { get; set; } = false; - - [IntegerFlag(0, 260, 20)] - public int TCChestCount { get; set; } = 0; - public bool TCProtectIncentives { get; set; } = false; - public bool? TCMasaGuardian { get; set; } = false; - public bool? TrappedChaos { get; set; } = false; - public bool? TCIndicator { get; set; } = false; - public bool? SwolePirates { get; set; } = false; - public bool? ShuffleScriptsEnemies { get; set; } = false; - public bool? RemoveBossScripts { get; set; } = false; - public bool? ShuffleScriptsBosses { get; set; } = false; - public bool? ShuffleSkillsSpellsEnemies { get; set; } = false; - public bool? ShuffleSkillsSpellsBosses { get; set; } = false; - public bool? NoConsecutiveNukes { get; set; } = false; - public bool TranceHasStatusElement { get; set; } = false; - public bool? EnemySkillsSpellsTiered { get; set; } = false; - public bool? AllowUnsafePirates { get; set; } = false; - public bool? AllowUnsafeMelmond { get; set; } = false; - - public WarMECHMode WarMECHMode { get; set; } = WarMECHMode.Vanilla; - public bool? OrdealsPillars { get; set; } = false; - public bool? ShuffleLavaTiles { get; set; } = false; - public SkyCastle4FMazeMode SkyCastle4FMazeMode { get; set; } = SkyCastle4FMazeMode.Vanilla; - public bool? TitansTrove { get; set; } = false; - public bool? LefeinSuperStore { get; set; } = false; - public bool? LefeinShops { get; set; } = false; - public bool? RandomVampAttack { get; set; } = false; - public bool? RandomVampAttackIncludesConeria { get; set; } = false; - public bool? FightBahamut { get; set; } = false; - public bool? SwoleBahamut { get; set; } = false; - public bool? SwoleAstos { get; set; } = false; - public bool? ConfusedOldMen { get; set; } = false; - public bool? GaiaShortcut { get; set; } = false; - - [IntegerFlag(0, 10, 1)] - public int DamageTileLow { get; set; } = 1; - [IntegerFlag(0, 10, 1)] - public int DamageTileHigh { get; set; } = 1; - public bool? OWDamageTiles { get; set; } = false; - public bool? DamageTilesKill { get; set; } = false; - public bool? ArmorResistsDamageTileDamage { get; set; } = false; - - public bool? MoveGaiaItemShop { get; set; } = false; - public bool? ShufflePravokaShops { get; set; } = false; - public bool? FlipDungeons { get; set; } = false; - public bool? VerticallyFlipDungeons { get; set; } = false; - public bool SpookyFlag { get; set; } = false; - public bool DraculasFlag { get; set; } = false; - public bool? MapOpenProgression { get; set; } = false; - public bool? MapOpenProgressionDocks { get; set; } = false; - public bool? Entrances { get; set; } = false; - public bool? Towns { get; set; } = false; - public bool? IncludeConeria { get; set; } = false; - public bool? Floors { get; set; } = false; - public bool? AllowDeepCastles { get; set; } = false; - public bool? AllowDeepTowns { get; set; } = false; - public bool? MapOpenProgressionExtended { get; set; } = false; - public bool? MapAirshipDock { get; set; } = false; - public bool? MapBahamutCardiaDock { get; set; } = false; - public bool? MapLefeinRiver { get; set; } = false; - public bool? MapBridgeLefein { get; set; } = false; - public bool? MapRiverToMelmond { get; set; } = false; - public bool? MapGaiaMountainPass { get; set; } = false; - public bool? MapHighwayToOrdeals { get; set; } = false; - public bool? MapDragonsHoard { get; set; } = false; - public bool? MapHallOfDragons { get; set; } = false; - public bool? EntrancesIncludesDeadEnds { get; set; } = false; - public bool? EntrancesMixedWithTowns { get; set; } = false; - - public bool? IncentivizeFreeNPCs { get; set; } = false; - public bool? IncentivizeFetchNPCs { get; set; } = false; - public bool? IncentivizeTail { get; set; } = false; - public bool? IncentivizeMainItems { get; set; } = false; - public bool? IncentivizeFetchItems { get; set; } = false; - public bool? IncentivizeCanoeItem { get; set; } = false; - public bool? IncentivizeAirship { get; set; } = false; - public bool? IncentivizeShipAndCanal { get; set; } = false; - public bool? IncentivizeBridgeItem { get; set; } = false; - - public bool? IncentivizeMarsh { get; set; } = false; - public bool? IncentivizeEarth { get; set; } = false; - public bool? IncentivizeVolcano { get; set; } = false; - public bool? IncentivizeIceCave { get; set; } = false; - public bool? IncentivizeOrdeals { get; set; } = false; - public bool? IncentivizeSeaShrine { get; set; } = false; - public bool? IncentivizeConeria { get; set; } = false; - public bool? IncentivizeMarshKeyLocked { get; set; } = false; - public bool? IncentivizeSkyPalace { get; set; } = false; - public bool? IncentivizeTitansTrove { get; set; } = false; - public bool? IncentivizeCardia { get; set; } = false; - - public IncentivePlacementType IceCaveIncentivePlacementType { get; set; } = IncentivePlacementType.Vanilla; - public IncentivePlacementType OrdealsIncentivePlacementType { get; set; } = IncentivePlacementType.Vanilla; - public IncentivePlacementType MarshIncentivePlacementType { get; set; } = IncentivePlacementType.Vanilla; - public IncentivePlacementType TitansIncentivePlacementType { get; set; } = IncentivePlacementType.Vanilla; - public IncentivePlacementTypeEarth EarthIncentivePlacementType { get; set; } = IncentivePlacementTypeEarth.Vanilla; - public IncentivePlacementTypeVolcano VolcanoIncentivePlacementType { get; set; } = IncentivePlacementTypeVolcano.Vanilla; - public IncentivePlacementTypeSea SeaShrineIncentivePlacementType { get; set; } = IncentivePlacementTypeSea.Vanilla; - public IncentivePlacementTypeSky SkyPalaceIncentivePlacementType { get; set; } = IncentivePlacementTypeSky.Vanilla; - public IncentivePlacementType CorneriaIncentivePlacementType { get; set; } = IncentivePlacementType.Vanilla; - public IncentivePlacementType MarshLockedIncentivePlacementType { get; set; } = IncentivePlacementType.Vanilla; - public IncentivePlacementType CardiaIncentivePlacementType { get; set; } = IncentivePlacementType.Vanilla; - - public bool? BetterTrapChests { get; set; } = false; - public bool? IncentivizeMasamune { get; set; } = false; - public bool? IncentivizeKatana { get; set; } = false; - public bool? IncentivizeXcalber { get; set; } = false; - public bool? IncentivizeVorpal { get; set; } = false; - public bool? IncentivizeOpal { get; set; } = false; - public bool? IncentivizeRibbon { get; set; } = false; - public bool? IncentivizeDefCastArmor { get; set; } = false; - public bool? IncentivizeOffCastArmor { get; set; } = false; - public bool? IncentivizeOtherCastArmor { get; set; } = false; - public bool? IncentivizePowerRod { get; set; } = false; - public bool? IncentivizeDefCastWeapon { get; set; } = false; - public bool? IncentivizeOffCastWeapon { get; set; } = false; - public bool IncentivizeOtherCastWeapon { get; set; } = false; - public bool? LooseExcludePlacedDungeons { get; set; } = false; - public bool? EarlyKing { get; set; } = false; - public bool? EarlySarda { get; set; } = false; - public bool? EarlySage { get; set; } = false; - public bool? EarlyOrdeals { get; set; } = false; - public bool? ShuffleObjectiveNPCs { get; set; } = false; - public bool OnlyRequireGameIsBeatable { get; set; } = true; - public bool? FreeBridge { get; set; } = false; - public bool? FreeShip { get; set; } = false; - public bool? FreeAirship { get; set; } = false; - public bool? FreeLute { get; set; } = false; - public bool? FreeRod { get; set; } = false; - public bool EnableCritNumberDisplay { get; set; } = false; - public bool? FreeCanal { get; set; } = false; - public bool? FreeCanoe { get; set; } = false; - public bool EasyMode { get; set; } = false; - - public bool HousesFillHp { get; set; } = false; - - public bool SpeedHacks { get; set; } = false; - public bool NoPartyShuffle { get; set; } = false; - public bool Dash { get; set; } = false; - public bool SpeedBoat { get; set; } = false; - public bool? AirBoat { get; set; } = false; - public bool BuyTen { get; set; } = false; - public bool IdentifyTreasures { get; set; } = false; - public bool ShopInfo { get; set; } = false; - public bool ChestInfo { get; set; } = false; - public bool IncentiveChestItemsFanfare { get; set; } = false; - public bool WaitWhenUnrunnable { get; set; } = false; - public bool ImprovedClinic { get; set; } = false; - public bool Etherizer { get; set; } = false; - // Done - public bool HouseMPRestoration { get; set; } = false; - public bool WeaponStats { get; set; } = false; - public bool BBCritRate { get; set; } = false; - public bool WeaponCritRate { get; set; } = false; - public bool WeaponBonuses { get; set; } = false; - public ThiefAGI ThiefAgilityBuff { get; set; } = ThiefAGI.Vanilla; - public SpoilerBatHints SkyWarriorSpoilerBats { get; set; } = SpoilerBatHints.Vanilla; - public bool? SpoilerBatsDontCheckOrbs { get; set; } = false; - public bool? MoveToFBats { get; set; } = false; - - [IntegerFlag(0, 50)] - public int WeaponTypeBonusValue { get; set; } = 10; - - public ChanceToRunMode ChanceToRun { get; set; } = ChanceToRunMode.Vanilla; - - public bool SpellBugs { get; set; } = false; - public bool BlackBeltAbsorb { get; set; } = false; - public bool NPCSwatter { get; set; } = false; - public bool BattleMagicMenuWrapAround { get; set; } = false; - public bool MagicMenuSpellReordering { get; set; } = false; - public bool InventoryAutosort { get; set; } = false; - public bool RepeatedHealPotionUse { get; set; } = false; - public bool AutoRetargeting { get; set; } = false; - public bool EnemyStatusAttackBug { get; set; } = false; - public bool ImproveTurnOrderRandomization { get; set; } = false; - public bool FixHitChanceCap { get; set; } = false; - - public bool? MelmondClinic { get; set; } = false; - public bool DDProgressiveTilesets { get; set; } = false; - public bool DDFiendOrbs { get; set; } = false; - public TailBahamutMode TailBahamutMode { get; set; } = TailBahamutMode.Random; - public StartingGold StartingGold { get; set; } = StartingGold.Gp400; - public bool IncludeMorale { get; set; } = false; - public bool DeadsGainXP { get; set; } = false; - public bool NonesGainXP { get; set; } = false; - public bool? NoTail { get; set; } = false; - public bool? NoFloater { get; set; } = false; - public bool? GuaranteedMasamune { get; set; } = false; - public bool? SendMasamuneHome { get; set; } = false; - - public ConsumableChestSet MoreConsumableChests { get; set; } = ConsumableChestSet.Vanilla; - - public bool? NoMasamune { get; set; } = false; - public bool? NoXcalber { get; set; } = false; - public bool? ClassAsNpcFiends { get; set; } = false; - public bool? ClassAsNpcKeyNPC { get; set; } = false; - - [IntegerFlag(0, 13)] - public int ClassAsNpcCount { get; set; } = 6; - public bool? ClassAsNpcDuplicate { get; set; } = false; - public bool? ClassAsNpcForcedFiends { get; set; } = false; - public bool? ClassAsNpcPromotion { get; set; } = false; - - [IntegerFlag(0, 500, 10)] - public int BossScaleStatsLow { get; set; } = 50; - - [IntegerFlag(0, 500, 10)] - public int BossScaleStatsHigh { get; set; } = 200; - - [IntegerFlag(0, 500, 10)] - public int BossScaleHpLow { get; set; } = 50; - - [IntegerFlag(0, 500, 10)] - public int BossScaleHpHigh { get; set; } = 200; - - [IntegerFlag(0, 500, 10)] - public int EnemyScaleStatsLow { get; set; } = 50; - - [IntegerFlag(0, 500, 10)] - public int EnemyScaleStatsHigh { get; set; } = 200; - - [IntegerFlag(0, 500, 10)] - public int EnemyScaleHpLow { get; set; } = 50; - - [IntegerFlag(0, 500, 10)] - public int EnemyScaleHpHigh { get; set; } = 200; - - [IntegerFlag(0, 500, 10)] - public int PriceScaleFactorLow { get; set; } = 50; - - [IntegerFlag(0, 500, 10)] - public int PriceScaleFactorHigh { get; set; } = 200; - - [DoubleFlag(1.0, 5.0, 0.1)] - public double ExpMultiplier { get; set; } = 0; - - [IntegerFlag(0, 250, 25)] - public int ExpBonus { get; set; } = 0; - - [DoubleFlag(0.5, 3.0, 0.1)] - public double ExpMultiplierFighter { get; set; } = 1.0; - - [DoubleFlag(0.5, 3.0, 0.1)] - public double ExpMultiplierThief { get; set; } = 1.0; - - [DoubleFlag(0.5, 3.0, 0.1)] - public double ExpMultiplierBlackBelt { get; set; } = 1.0; - - [DoubleFlag(0.5, 3.0, 0.1)] - public double ExpMultiplierRedMage { get; set; } = 1.0; - - [DoubleFlag(0.5, 3.0, 0.1)] - public double ExpMultiplierWhiteMage { get; set; } = 1.0; - - [DoubleFlag(0.5, 3.0, 0.1)] - public double ExpMultiplierBlackMage { get; set; } = 1.0; - - [DoubleFlag(0, 45)] - public double EncounterRate { get; set; } = 0; - - [DoubleFlag(0, 45)] - public double DungeonEncounterRate { get; set; } = 0; - public ProgressiveScaleMode ProgressiveScaleMode { get; set; } = ProgressiveScaleMode.Disabled; - - public StartingItemSet StartingItemSet { get; set; } = StartingItemSet.None; - - public TreasureStackSize ConsumableTreasureStackSize { get; set; } = TreasureStackSize.Default; - - public bool? FIGHTER1 { get; set; } = false; - public bool? THIEF1 { get; set; } = false; - public bool? BLACK_BELT1 { get; set; } = false; - public bool? RED_MAGE1 { get; set; } = false; - public bool? WHITE_MAGE1 { get; set; } = false; - public bool? BLACK_MAGE1 { get; set; } = false; - - public bool? FIGHTER2 { get; set; } = false; - public bool? THIEF2 { get; set; } = false; - public bool? BLACK_BELT2 { get; set; } = false; - public bool? RED_MAGE2 { get; set; } = false; - public bool? WHITE_MAGE2 { get; set; } = false; - public bool? BLACK_MAGE2 { get; set; } = false; - - public bool? FIGHTER3 { get; set; } = false; - public bool? THIEF3 { get; set; } = false; - public bool? BLACK_BELT3 { get; set; } = false; - public bool? RED_MAGE3 { get; set; } = false; - public bool? WHITE_MAGE3 { get; set; } = false; - public bool? BLACK_MAGE3 { get; set; } = false; - - public bool? FIGHTER4 { get; set; } = false; - public bool? THIEF4 { get; set; } = false; - public bool? BLACK_BELT4 { get; set; } = false; - public bool? RED_MAGE4 { get; set; } = false; - public bool? WHITE_MAGE4 { get; set; } = false; - public bool? BLACK_MAGE4 { get; set; } = false; - - public bool? KNIGHT1 { get; set; } = false; - public bool? KNIGHT2 { get; set; } = false; - public bool? KNIGHT3 { get; set; } = false; - public bool? KNIGHT4 { get; set; } = false; - public bool? NINJA1 { get; set; } = false; - public bool? NINJA2 { get; set; } = false; - public bool? NINJA3 { get; set; } = false; - public bool? NINJA4 { get; set; } = false; - public bool? MASTER1 { get; set; } = false; - public bool? MASTER2 { get; set; } = false; - public bool? MASTER3 { get; set; } = false; - public bool? MASTER4 { get; set; } = false; - public bool? RED_WIZ1 { get; set; } = false; - public bool? RED_WIZ2 { get; set; } = false; - public bool? RED_WIZ3 { get; set; } = false; - public bool? RED_WIZ4 { get; set; } = false; - public bool? WHITE_WIZ1 { get; set; } = false; - public bool? WHITE_WIZ2 { get; set; } = false; - public bool? WHITE_WIZ3 { get; set; } = false; - public bool? WHITE_WIZ4 { get; set; } = false; - public bool? BLACK_WIZ1 { get; set; } = false; - public bool? BLACK_WIZ2 { get; set; } = false; - public bool? BLACK_WIZ3 { get; set; } = false; - public bool? BLACK_WIZ4 { get; set; } = false; - public bool? NONE_CLASS2 { get; set; } = false; - public bool? NONE_CLASS3 { get; set; } = false; - public bool? NONE_CLASS4 { get; set; } = false; - public bool? FORCED1 { get; set; } = false; - public bool? FORCED2 { get; set; } = false; - public bool? FORCED3 { get; set; } = false; - public bool? FORCED4 { get; set; } = false; - public bool? DraftFighter { get; set; } = false; - public bool? DraftThief { get; set; } = false; - public bool? DraftBlackBelt { get; set; } = false; - public bool? DraftRedMage { get; set; } = false; - public bool? DraftWhiteMage { get; set; } = false; - public bool? DraftBlackMage { get; set; } = false; - public bool? DraftKnight { get; set; } = false; - public bool? DraftNinja { get; set; } = false; - public bool? DraftMaster { get; set; } = false; - public bool? DraftRedWiz { get; set; } = false; - public bool? DraftWhiteWiz { get; set; } = false; - public bool? DraftBlackWiz { get; set; } = false; - public bool? TAVERN1 { get; set; } = false; - public bool? TAVERN2 { get; set; } = false; - public bool? TAVERN3 { get; set; } = false; - public bool? TAVERN4 { get; set; } = false; - public bool? TAVERN5 { get; set; } = false; - public bool? TAVERN6 { get; set; } = false; - - public bool WeaponPermissions { get; set; } = false; - public bool ArmorPermissions { get; set; } = false; - public bool? RecruitmentMode { get; set; } = false; - public bool? RecruitmentModeHireOnly { get; set; } = false; - public bool? RecruitmentModeReplaceOnlyNone { get; set; } = false; - public bool? ClampMinimumStatScale { get; set; } = false; - public bool? ClampMinimumBossStatScale { get; set; } = false; - public bool? ClampMinimumPriceScale { get; set; } = false; - public bool EFGWaterfall { get; set; } = false; - public bool? FiendShuffle { get; set; } = false; - public bool DisableTentSaving { get; set; } = false; - public bool DisableInnSaving { get; set; } = false; - public bool SaveGameWhenGameOver { get; set; } = false; - public bool SaveGameDWMode { get; set; } = false; - public bool? ShuffleAstos { get; set; } = false; - public bool UnsafeAstos { get; set; } = false; - public bool? RandomizeEnemizer { get; set; } = false; - public bool? RandomizeFormationEnemizer { get; set; } = false; - public bool? GenerateNewSpellbook { get; set; } = false; - public bool? SpellcrafterMixSpells { get; set; } = false; - public bool ThiefHitRate { get; set; } = false; - public bool AllSpellLevelsForKnightNinja { get; set; } = false; - public bool BuffHealingSpells { get; set; } = false; - public bool IntAffectsSpells { get; set; } = false; - public bool? AddDamageTiles { get; set; } = false; - public bool? DamageTilesCastles { get; set; } = false; - public bool? DamageTilesDungeons { get; set; } = false; - public bool? DamageTilesCaves { get; set; } = false; - public bool? DamageTilesTowns { get; set; } = false; - public bool? DamageTilesTof { get; set; } = false; - public DamageTilesQuantity DamageTilesQuantity { get; set; } = DamageTilesQuantity.Normal; - public bool? FreeTail { get; set; } = false; - public bool? HintsVillage { get; set; } = false; - public bool? SpellcrafterRetainPermissions { get; set; } = false; - public bool? RandomWeaponBonus { get; set; } = false; - public bool? RandomArmorBonus { get; set; } = false; - public bool? RandomWeaponBonusExcludeMasa { get; set; } = false; - - [IntegerFlag(-9, 9)] - public int RandomWeaponBonusLow { get; set; } = -5; - - [IntegerFlag(-9, 9)] - public int RandomWeaponBonusHigh { get; set; } = 5; - - [IntegerFlag(-9, 9)] - public int RandomArmorBonusLow { get; set; } = -5; - - [IntegerFlag(-9, 9)] - public int RandomArmorBonusHigh { get; set; } = 5; - public bool? SeparateBossHPScaling { get; set; } = false; - public bool? SeparateEnemyHPScaling { get; set; } = false; - public bool? ClampBossHPScaling { get; set; } = false; - public bool? ClampEnemyHpScaling { get; set; } = false; - public PoolSize PoolSize { get; set; } = PoolSize.Size6; - public bool? EnablePoolParty { get; set; } = false; - public bool SafePoolParty { get; set; } = false; - public bool? IncludePromClasses { get; set; } = false; - public bool? EnableRandomPromotions { get; set; } = false; - public bool? IncludeBaseClasses { get; set; } = false; - public bool? RandomPromotionsSpoilers { get; set; } = false; - public bool? RandomizeClassCasting { get; set; } = false; - public bool? RandomizeClassKeyItems { get; set; } = false; - public bool? RandomizeClassIncludeXpBonus { get; set; } = false; - public bool? AlternateFiends { get; set; } = false; - public bool? FinalFantasy2Fiends { get; set; } = false; - public bool? FinalFantasy3Fiends { get; set; } = false; - public bool? FinalFantasy4Fiends { get; set; } = false; - public bool? FinalFantasy5Fiends { get; set; } = false; - public bool? FinalFantasy6Fiends { get; set; } = false; - public bool? FinalFantasy1BonusFiends { get; set; } = false; - public bool? BlackOrbFiends { get; set; } = false; - public bool? NoBossSkillScriptShuffle { get; set; } = false; - - public bool? MooglieWeaponBalance { get; set; } = false; - public bool? GuaranteeCustomClassComposition { get; set; } = false; - - public bool? LegendaryWeaponShop { get; set; } = false; - public bool? LegendaryArmorShop { get; set; } = false; - public bool? LegendaryBlackShop { get; set; } = false; - public bool? LegendaryWhiteShop { get; set; } = false; - public bool? LegendaryItemShop { get; set; } = false; - - public bool ExclusiveLegendaryWeaponShop { get; set; } = false; - public bool ExclusiveLegendaryArmorShop { get; set; } = false; - public bool ExclusiveLegendaryBlackShop { get; set; } = false; - public bool ExclusiveLegendaryWhiteShop { get; set; } = false; - public bool ExclusiveLegendaryItemShop { get; set; } = false; - public ClassRandomizationMode RandomizeClassMode { get; set; } = ClassRandomizationMode.None; - - [IntegerFlag(0, 3)] - public int RandomizeClassMaxBonus { get; set; } = 2; - - [IntegerFlag(0, 3)] - public int RandomizeClassMaxMalus { get; set; } = 1; - public bool? EarlierHighTierMagic { get; set; } = false; - public bool? ChangeMaxMP { get; set; } = false; - - [IntegerFlag(0, 9)] - public int RedMageMaxMP { get; set; } = 9; - - [IntegerFlag(0, 9)] - public int WhiteMageMaxMP { get; set; } = 9; - - [IntegerFlag(0, 9)] - public int BlackMageMaxMP { get; set; } = 9; - - [IntegerFlag(0, 9)] - public int KnightMaxMP { get; set; } = 4; - - [IntegerFlag(0, 9)] - public int NinjaMaxMP { get; set; } = 4; - - public bool? Knightlvl4 { get; set; } = false; - public bool? PinkMage { get; set; } = false; - public bool? BlackKnight { get; set; } = false; - public bool? BlackKnightKeep { get; set; } = false; - public bool? WhiteNinja { get; set; } = false; - public bool? WhiteNinjaKeep { get; set; } = false; - - public MpGainOnMaxGain MpGainOnMaxGainMode { get; set; } = MpGainOnMaxGain.None; - - public LockHitMode LockMode { get; set; } = LockHitMode.Vanilla; - // Done - public MDEFGrowthMode MDefMode { get; set; } = MDEFGrowthMode.None; - - public FormationShuffleMode FormationShuffleMode { get; set; } = FormationShuffleMode.None; - - public RandomizeTreasureMode RandomizeTreasure { get; set; } = RandomizeTreasureMode.None; - public bool OpenChestsInOrder { get; set; } = false; - public bool SetRNG { get; set; } = false; - public WorldWealthMode WorldWealth { get; set; } = WorldWealthMode.Standard; - public DeepDungeonGeneratorMode DeepDungeonGenerator { get; set; } = DeepDungeonGeneratorMode.Progressive; - public EvadeCapValues EvadeCap { get; set; } = EvadeCapValues.medium; - - public bool? AllowUnsafeStartArea { get; set; } = false; - - public bool? IncreaseDarkPenalty { get; set; } = false; - public PoisonModeOptions PoisonMode { get; set; } = PoisonModeOptions.Constant; - [IntegerFlag(1,500)] - public int PoisonSetDamageValue { get; set; } = 3; - - public bool? TouchIncludeBosses { get; set; } = false; - - public bool? Lockpicking { get; set; } = false; - // Done - public bool? ReducedLuck { get; set; } = false; - - [IntegerFlag(1, 50)] - public int LockpickingLevelRequirement { get; set; } = 10; - - public bool WhiteMageHarmEveryone { get; set; } = false; - - public bool? ProcgenEarth { get; set; } = false; - } -} +using System.Numerics; +using System.Reflection; +using Newtonsoft.Json; +using System.IO.Compression; +using static FF1Lib.FF1Rom; +using FF1Lib.Sanity; +using System.ComponentModel; + +namespace FF1Lib +{ + public partial class Flags : IIncentiveFlags, IScaleFlags, IVictoryConditionFlags, IFloorShuffleFlags, IItemPlacementFlags + { + #region StartingEquipment + + public bool? StartingEquipmentMasamune { get; set; } = false; + + public bool? StartingEquipmentKatana { get; set; } = false; + + public bool? StartingEquipmentHealStaff { get; set; } = false; + + public bool? StartingEquipmentZeusGauntlet { get; set; } = false; + + public bool? StartingEquipmentWhiteShirt { get; set; } = false; + + public bool? StartingEquipmentRibbon { get; set; } = false; + + public bool? StartingEquipmentDragonslayer { get; set; } = false; + + public bool? StartingEquipmentLegendKit { get; set; } = false; + + public bool? StartingEquipmentRandomEndgameWeapon { get; set; } = false; + + public bool? StartingEquipmentRandomAoe { get; set; } = false; + + public bool? StartingEquipmentRandomCasterItem { get; set; } = false; + + public bool? StartingEquipmentGrandpasSecretStash { get; set; } = false; + + public bool? StartingEquipmentOneItem { get; set; } = false; + + public bool? StartingEquipmentRandomCrap { get; set; } = false; + + public bool? StartingEquipmentStarterPack { get; set; } = false; + + public bool? StartingEquipmentRandomTypeWeapon { get; set; } = false; + + public bool StartingEquipmentRemoveFromPool { get; set; } = false; + + public bool StartingEquipmentNoDuplicates { get; set; } = false; + + #endregion + + public bool? ReversedFloors { get; set; } = false; + public bool BuffTier1DamageSpells { get; set; } = false; + public bool NoEmptyScripts { get; set; } = false; + public bool LaterLoose { get; set; } = false; + public bool? MermaidPrison { get; set; } = false; + + public GuaranteedDefenseItem GuaranteedDefenseItem { get; set; } = GuaranteedDefenseItem.None; + + public GuaranteedPowerItem GuaranteedPowerItem { get; set; } = GuaranteedPowerItem.None; + + public ScriptTouchMultiplier ScriptMultiplier { get; set; } = ScriptTouchMultiplier.Vanilla; + public ScriptTouchMultiplier TouchMultiplier { get; set; } = ScriptTouchMultiplier.Vanilla; + public TouchPool TouchPool { get; set; } = TouchPool.All; + public TouchMode TouchMode { get; set; } = TouchMode.Standard; + public RibbonMode RibbonMode { get; set; } = RibbonMode.Vanilla; + + public bool Archipelago { get; set; } = false; + public bool ArchipelagoGold { get; set; } = false; + public bool ArchipelagoConsumables { get; set; } = false; + public bool ArchipelagoShards { get; set; } = false; + public ArchipelagoEquipment ArchipelagoEquipment { get; set; } = ArchipelagoEquipment.None; + + public ItemMagicMode ItemMagicMode { get; set; } = ItemMagicMode.Vanilla; + public ItemMagicPool ItemMagicPool { get; set; } = ItemMagicPool.All; + public bool? MagisizeWeapons { get; set; } = false; + + public bool DisableMinimap { get; set; } = false; + + public bool LooseItemsForwardPlacement { get; set; } = false; + + public bool LooseItemsSpreadPlacement { get; set; } = false; + + public bool LooseItemsNpcBalance { get; set; } = false; + public bool AllowUnsafePlacement { get; set; } = false; + public bool ShipCanalBeforeFloater { get; set; } = false; + + [IntegerFlag(0, 100, 10)] + public int ExpChestConversionMin { get; set; } = 0; + + [IntegerFlag(0, 100, 10)] + public int ExpChestConversionMax { get; set; } = 0; + + [IntegerFlag(0, 20000, 500)] + public int ExpChestMinReward { get; set; } = 2000; + + [IntegerFlag(0, 20000, 500)] + public int ExpChestMaxReward { get; set; } = 8000; + + public SpellNameMadness SpellNameMadness { get; set; } = SpellNameMadness.None; + + public ExtConsumableSet ExtConsumableSet { get; set; } = ExtConsumableSet.None; + + public bool EnableSoftInBattle { get; set; } = false; + public LifeInBattleSetting EnableLifeInBattle { get; set; } = LifeInBattleSetting.LifeInBattleAll; + + public bool? NormalShopsHaveExtConsumables { get; set; } = false; + + public bool? LegendaryShopHasExtConsumables { get; set; } = false; + + public TreasureStackSize ExtConsumableTreasureStackSize { get; set; } = TreasureStackSize.Default; + + public ExtStartingItemSet ExtStartingItemSet { get; set; } = ExtStartingItemSet.None; + + public ExtConsumableChestSet ExtConsumableChests { get; set; } = ExtConsumableChestSet.None; + + public OwMapExchanges OwMapExchange { get; set; } = OwMapExchanges.None; + public bool OwShuffledAccess { get; set; } = false; + public bool OwUnsafeStart { get; set; } = false; + public bool OwRandomPregen { get; set; } = false; + + public bool? RelocateChests { get; set; } = false; + public bool RelocateChestsTrapIndicator { get; set; } = false; + + public bool? ShuffleChimeAccess { get; set; } = false; + public bool? ShuffleChimeIncludeTowns { get; set; } = false; + + public GameModes GameMode { get; set; } = GameModes.Standard; + + [IntegerFlag(0, Int32.MaxValue-1)] + public int MapGenSeed { get; set; } = 0; + + public OwMapExchangeData ReplacementMap { get; set; } = null; + + public string ResourcePack { get; set; } = null; + + #region ShopKiller + + public ShopKillMode ShopKillMode_Weapons { get; set; } = ShopKillMode.None; + public ShopKillMode ShopKillMode_Armor { get; set; } = ShopKillMode.None; + public ShopKillMode ShopKillMode_Item { get; set; } = ShopKillMode.None; + public ShopKillMode ShopKillMode_Black { get; set; } = ShopKillMode.None; + public ShopKillMode ShopKillMode_White { get; set; } = ShopKillMode.None; + + public ShopKillFactor ShopKillFactor_Weapons { get; set; } = ShopKillFactor.Kill20Percent; + public ShopKillFactor ShopKillFactor_Armor { get; set; } = ShopKillFactor.Kill20Percent; + public ShopKillFactor ShopKillFactor_Item { get; set; } = ShopKillFactor.Kill20Percent; + public ShopKillFactor ShopKillFactor_Black { get; set; } = ShopKillFactor.Kill20Percent; + public ShopKillFactor ShopKillFactor_White { get; set; } = ShopKillFactor.Kill20Percent; + + public bool ShopKillExcludeConeria_Weapons { get; set; } = false; + public bool ShopKillExcludeConeria_Armor { get; set; } = false; + public bool ShopKillExcludeConeria_Item { get; set; } = false; + public bool ShopKillExcludeConeria_Black { get; set; } = false; + public bool ShopKillExcludeConeria_White { get; set; } = false; + + #endregion + + public bool? ExcludeGoldFromScaling { get; set; } = false; + public bool CheapVendorItem { get; set; } = false; + + public StartingLevel StartingLevel { get; set; } + public TransmooglifierVariance TransmooglifierVariance { get; set; } + + [IntegerFlag(1, 50)] + public int MaxLevelLow { get; set; } = 50; + [IntegerFlag(1, 50)] + public int MaxLevelHigh { get; set; } = 50; + + public bool Spoilers { get; set; } = false; + public bool TournamentSafe { get; set; } = false; + public bool BlindSeed { get; set; } = false; + public bool? Shops { get; set; } = false; + public bool? Treasures { get; set; } = false; + public bool? ChestsKeyItems { get; set; } = false; + public bool? NPCItems { get; set; } = false; + public bool? NPCFetchItems { get; set; } = false; + public bool? RandomWares { get; set; } = false; + public bool? RandomWaresIncludesSpecialGear { get; set; } = false; + public bool? RandomLoot { get; set; } = false; + + public bool ShardHunt { get; set; } = false; + public ShardCount ShardCount { get; set; } = ShardCount.Count16; + + [IntegerFlag(0, 5)] + public int OrbsRequiredCount { get; set; } = 4; + public OrbsRequiredMode OrbsRequiredMode { get; set; } = OrbsRequiredMode.Any; + public bool? OrbsRequiredSpoilers { get; set; } = false; + public FinalFormation TransformFinalFormation { get; set; } = FinalFormation.None; + public bool? ChaosRush { get; set; } = false; + public ToFRMode ToFRMode { get; set; } = ToFRMode.Long; + public FiendsRefights FiendsRefights { get; set; } = FiendsRefights.All; + public bool? ExitToFR { get; set; } = false; + public bool? ChaosFloorEncounters { get; set; } = false; + public bool? MagicShops { get; set; } = false; + public bool? MagicShopLocs { get; set; } = false; + public bool? MagicShopLocationPairs { get; set; } = false; + public bool? MagicLevels { get; set; } = false; + public bool? MagicPermissions { get; set; } = false; + public bool? Weaponizer { get; set; } = false; + public bool? WeaponizerNamesUseQualityOnly { get; set; } = false; + public bool? WeaponizerCommonWeaponsHavePowers { get; set; } = false; + public bool? ArmorCrafter { get; set; } = false; + public bool? MagicLevelsTiered { get; set; } = false; + public bool? MagicLevelsMixed { get; set; } = false; + + public AutohitThreshold MagicAutohitThreshold { get; set; } = AutohitThreshold.Vanilla; + + public bool? Rng { get; set; } = false; + public bool FixMissingBattleRngEntry { get; set; } = false; + + public bool? EncounterPrng { get; set; } = false; + + public bool? UnrunnableShuffle { get; set; } = true; + [IntegerFlag(0, 100, 4)] + public int UnrunnablesLow { get; set; } = 0; + [IntegerFlag(0, 100, 4)] + public int UnrunnablesHigh { get; set; } = 0; + public bool? EnemyFormationsSurprise { get; set; } = false; + public bool? UnrunnablesStrikeFirstAndSurprise { get; set; } = false; + + public TrapTileMode EnemyTrapTiles { get; set; } = TrapTileMode.Vanilla; + public FormationPool TCFormations { get; set; } = FormationPool.AltFormationDist; + public TCOptions TCBetterTreasure { get; set; } = TCOptions.None; + public TCOptions TCKeyItems { get; set; } = TCOptions.None; + public TCOptions TCShards { get; set; } = TCOptions.None; + public bool TCExcludeCommons { get; set; } = false; + + [IntegerFlag(0, 260, 20)] + public int TCChestCount { get; set; } = 0; + public bool TCProtectIncentives { get; set; } = false; + public bool? TCMasaGuardian { get; set; } = false; + public bool? TrappedChaos { get; set; } = false; + public bool? TCIndicator { get; set; } = false; + public bool? SwolePirates { get; set; } = false; + public bool? ShuffleScriptsEnemies { get; set; } = false; + public bool? RemoveBossScripts { get; set; } = false; + public bool? ShuffleScriptsBosses { get; set; } = false; + public bool? ShuffleSkillsSpellsEnemies { get; set; } = false; + public bool? ShuffleSkillsSpellsBosses { get; set; } = false; + public bool? NoConsecutiveNukes { get; set; } = false; + public bool TranceHasStatusElement { get; set; } = false; + public bool? EnemySkillsSpellsTiered { get; set; } = false; + public bool? AllowUnsafePirates { get; set; } = false; + public bool? AllowUnsafeMelmond { get; set; } = false; + + public WarMECHMode WarMECHMode { get; set; } = WarMECHMode.Vanilla; + public bool? OrdealsPillars { get; set; } = false; + public bool? ShuffleLavaTiles { get; set; } = false; + public SkyCastle4FMazeMode SkyCastle4FMazeMode { get; set; } = SkyCastle4FMazeMode.Vanilla; + public bool? TitansTrove { get; set; } = false; + public bool? LefeinSuperStore { get; set; } = false; + public bool? LefeinShops { get; set; } = false; + public bool? RandomVampAttack { get; set; } = false; + public bool? RandomVampAttackIncludesConeria { get; set; } = false; + public bool? FightBahamut { get; set; } = false; + public bool? SwoleBahamut { get; set; } = false; + public bool? SwoleAstos { get; set; } = false; + public bool? ConfusedOldMen { get; set; } = false; + public bool? GaiaShortcut { get; set; } = false; + + [IntegerFlag(0, 10, 1)] + public int DamageTileLow { get; set; } = 1; + [IntegerFlag(0, 10, 1)] + public int DamageTileHigh { get; set; } = 1; + public bool? OWDamageTiles { get; set; } = false; + public bool? DamageTilesKill { get; set; } = false; + public bool? ArmorResistsDamageTileDamage { get; set; } = false; + + public bool? MoveGaiaItemShop { get; set; } = false; + public bool? ShufflePravokaShops { get; set; } = false; + public bool? FlipDungeons { get; set; } = false; + public bool? VerticallyFlipDungeons { get; set; } = false; + public bool SpookyFlag { get; set; } = false; + public bool DraculasFlag { get; set; } = false; + public bool? MapOpenProgression { get; set; } = false; + public bool? MapOpenProgressionDocks { get; set; } = false; + public bool? Entrances { get; set; } = false; + public bool? Towns { get; set; } = false; + public bool? IncludeConeria { get; set; } = false; + public bool? Floors { get; set; } = false; + public bool? AllowDeepCastles { get; set; } = false; + public bool? AllowDeepTowns { get; set; } = false; + public bool? MapOpenProgressionExtended { get; set; } = false; + public bool? MapAirshipDock { get; set; } = false; + public bool? MapBahamutCardiaDock { get; set; } = false; + public bool? MapLefeinRiver { get; set; } = false; + public bool? MapBridgeLefein { get; set; } = false; + public bool? MapRiverToMelmond { get; set; } = false; + public bool? MapGaiaMountainPass { get; set; } = false; + public bool? MapHighwayToOrdeals { get; set; } = false; + public bool? MapDragonsHoard { get; set; } = false; + public bool? MapHallOfDragons { get; set; } = false; + public bool? EntrancesIncludesDeadEnds { get; set; } = false; + public bool? EntrancesMixedWithTowns { get; set; } = false; + + public bool? IncentivizeFreeNPCs { get; set; } = false; + public bool? IncentivizeFetchNPCs { get; set; } = false; + public bool? IncentivizeTail { get; set; } = false; + public bool? IncentivizeMainItems { get; set; } = false; + public bool? IncentivizeFetchItems { get; set; } = false; + public bool? IncentivizeCanoeItem { get; set; } = false; + public bool? IncentivizeAirship { get; set; } = false; + public bool? IncentivizeShipAndCanal { get; set; } = false; + public bool? IncentivizeBridgeItem { get; set; } = false; + + public bool? IncentivizeMarsh { get; set; } = false; + public bool? IncentivizeEarth { get; set; } = false; + public bool? IncentivizeVolcano { get; set; } = false; + public bool? IncentivizeIceCave { get; set; } = false; + public bool? IncentivizeOrdeals { get; set; } = false; + public bool? IncentivizeSeaShrine { get; set; } = false; + public bool? IncentivizeConeria { get; set; } = false; + public bool? IncentivizeMarshKeyLocked { get; set; } = false; + public bool? IncentivizeSkyPalace { get; set; } = false; + public bool? IncentivizeTitansTrove { get; set; } = false; + public bool? IncentivizeCardia { get; set; } = false; + + public IncentivePlacementType IceCaveIncentivePlacementType { get; set; } = IncentivePlacementType.Vanilla; + public IncentivePlacementType OrdealsIncentivePlacementType { get; set; } = IncentivePlacementType.Vanilla; + public IncentivePlacementType MarshIncentivePlacementType { get; set; } = IncentivePlacementType.Vanilla; + public IncentivePlacementType TitansIncentivePlacementType { get; set; } = IncentivePlacementType.Vanilla; + public IncentivePlacementTypeEarth EarthIncentivePlacementType { get; set; } = IncentivePlacementTypeEarth.Vanilla; + public IncentivePlacementTypeVolcano VolcanoIncentivePlacementType { get; set; } = IncentivePlacementTypeVolcano.Vanilla; + public IncentivePlacementTypeSea SeaShrineIncentivePlacementType { get; set; } = IncentivePlacementTypeSea.Vanilla; + public IncentivePlacementTypeSky SkyPalaceIncentivePlacementType { get; set; } = IncentivePlacementTypeSky.Vanilla; + public IncentivePlacementType CorneriaIncentivePlacementType { get; set; } = IncentivePlacementType.Vanilla; + public IncentivePlacementType MarshLockedIncentivePlacementType { get; set; } = IncentivePlacementType.Vanilla; + public IncentivePlacementType CardiaIncentivePlacementType { get; set; } = IncentivePlacementType.Vanilla; + + public bool? BetterTrapChests { get; set; } = false; + public bool? IncentivizeMasamune { get; set; } = false; + public bool? IncentivizeKatana { get; set; } = false; + public bool? IncentivizeXcalber { get; set; } = false; + public bool? IncentivizeVorpal { get; set; } = false; + public bool? IncentivizeOpal { get; set; } = false; + public bool? IncentivizeRibbon { get; set; } = false; + public bool? IncentivizeDefCastArmor { get; set; } = false; + public bool? IncentivizeOffCastArmor { get; set; } = false; + public bool? IncentivizeOtherCastArmor { get; set; } = false; + public bool? IncentivizePowerRod { get; set; } = false; + public bool? IncentivizeDefCastWeapon { get; set; } = false; + public bool? IncentivizeOffCastWeapon { get; set; } = false; + public bool IncentivizeOtherCastWeapon { get; set; } = false; + public bool? LooseExcludePlacedDungeons { get; set; } = false; + public bool? EarlyKing { get; set; } = false; + public bool? EarlySarda { get; set; } = false; + public bool? EarlySage { get; set; } = false; + public bool? EarlyOrdeals { get; set; } = false; + public bool? ShuffleObjectiveNPCs { get; set; } = false; + public bool OnlyRequireGameIsBeatable { get; set; } = true; + public bool? FreeBridge { get; set; } = false; + public bool? FreeShip { get; set; } = false; + public bool? FreeAirship { get; set; } = false; + public bool? FreeLute { get; set; } = false; + public bool? FreeRod { get; set; } = false; + public bool EnableCritNumberDisplay { get; set; } = false; + public bool? FreeCanal { get; set; } = false; + public bool? FreeCanoe { get; set; } = false; + public bool EasyMode { get; set; } = false; + + public bool HousesFillHp { get; set; } = false; + + public bool SpeedHacks { get; set; } = false; + public bool NoPartyShuffle { get; set; } = false; + public bool Dash { get; set; } = false; + public bool SpeedBoat { get; set; } = false; + public bool? AirBoat { get; set; } = false; + public bool BuyTen { get; set; } = false; + public bool IdentifyTreasures { get; set; } = false; + public bool ShopInfo { get; set; } = false; + public bool ChestInfo { get; set; } = false; + public bool IncentiveChestItemsFanfare { get; set; } = false; + public bool WaitWhenUnrunnable { get; set; } = false; + public bool ImprovedClinic { get; set; } = false; + public bool Etherizer { get; set; } = false; + // Done + public bool HouseMPRestoration { get; set; } = false; + public bool WeaponStats { get; set; } = false; + public bool BBCritRate { get; set; } = false; + public bool WeaponCritRate { get; set; } = false; + public bool WeaponBonuses { get; set; } = false; + public ThiefAGI ThiefAgilityBuff { get; set; } = ThiefAGI.Vanilla; + public SpoilerBatHints SkyWarriorSpoilerBats { get; set; } = SpoilerBatHints.Vanilla; + public bool? SpoilerBatsDontCheckOrbs { get; set; } = false; + public bool? MoveToFBats { get; set; } = false; + + [IntegerFlag(0, 50)] + public int WeaponTypeBonusValue { get; set; } = 10; + + public ChanceToRunMode ChanceToRun { get; set; } = ChanceToRunMode.Vanilla; + + public bool SpellBugs { get; set; } = false; + public bool BlackBeltAbsorb { get; set; } = false; + public bool NPCSwatter { get; set; } = false; + public bool BattleMagicMenuWrapAround { get; set; } = false; + public bool MagicMenuSpellReordering { get; set; } = false; + public bool InventoryAutosort { get; set; } = false; + public bool RepeatedHealPotionUse { get; set; } = false; + public bool AutoRetargeting { get; set; } = false; + public bool EnemyStatusAttackBug { get; set; } = false; + public bool ImproveTurnOrderRandomization { get; set; } = false; + public bool FixHitChanceCap { get; set; } = false; + + public bool? MelmondClinic { get; set; } = false; + public bool DDProgressiveTilesets { get; set; } = false; + public bool DDFiendOrbs { get; set; } = false; + public TailBahamutMode TailBahamutMode { get; set; } = TailBahamutMode.Random; + public StartingGold StartingGold { get; set; } = StartingGold.Gp400; + public bool IncludeMorale { get; set; } = false; + public bool DeadsGainXP { get; set; } = false; + public bool NonesGainXP { get; set; } = false; + public bool? NoTail { get; set; } = false; + public bool? NoFloater { get; set; } = false; + public bool? GuaranteedMasamune { get; set; } = false; + public bool? SendMasamuneHome { get; set; } = false; + + public ConsumableChestSet MoreConsumableChests { get; set; } = ConsumableChestSet.Vanilla; + + public bool? NoMasamune { get; set; } = false; + public bool? NoXcalber { get; set; } = false; + public bool? ClassAsNpcFiends { get; set; } = false; + public bool? ClassAsNpcKeyNPC { get; set; } = false; + + [IntegerFlag(0, 13)] + public int ClassAsNpcCount { get; set; } = 6; + public bool? ClassAsNpcDuplicate { get; set; } = false; + public bool? ClassAsNpcForcedFiends { get; set; } = false; + public bool? ClassAsNpcPromotion { get; set; } = false; + + [IntegerFlag(0, 500, 10)] + public int BossScaleStatsLow { get; set; } = 50; + + [IntegerFlag(0, 500, 10)] + public int BossScaleStatsHigh { get; set; } = 200; + + [IntegerFlag(0, 500, 10)] + public int BossScaleHpLow { get; set; } = 50; + + [IntegerFlag(0, 500, 10)] + public int BossScaleHpHigh { get; set; } = 200; + + [IntegerFlag(0, 500, 10)] + public int EnemyScaleStatsLow { get; set; } = 50; + + [IntegerFlag(0, 500, 10)] + public int EnemyScaleStatsHigh { get; set; } = 200; + + [IntegerFlag(0, 500, 10)] + public int EnemyScaleHpLow { get; set; } = 50; + + [IntegerFlag(0, 500, 10)] + public int EnemyScaleHpHigh { get; set; } = 200; + + [IntegerFlag(0, 500, 10)] + public int PriceScaleFactorLow { get; set; } = 50; + + [IntegerFlag(0, 500, 10)] + public int PriceScaleFactorHigh { get; set; } = 200; + + [DoubleFlag(1.0, 5.0, 0.1)] + public double ExpMultiplier { get; set; } = 0; + + [IntegerFlag(0, 250, 25)] + public int ExpBonus { get; set; } = 0; + + [DoubleFlag(0.5, 3.0, 0.1)] + public double ExpMultiplierFighter { get; set; } = 1.0; + + [DoubleFlag(0.5, 3.0, 0.1)] + public double ExpMultiplierThief { get; set; } = 1.0; + + [DoubleFlag(0.5, 3.0, 0.1)] + public double ExpMultiplierBlackBelt { get; set; } = 1.0; + + [DoubleFlag(0.5, 3.0, 0.1)] + public double ExpMultiplierRedMage { get; set; } = 1.0; + + [DoubleFlag(0.5, 3.0, 0.1)] + public double ExpMultiplierWhiteMage { get; set; } = 1.0; + + [DoubleFlag(0.5, 3.0, 0.1)] + public double ExpMultiplierBlackMage { get; set; } = 1.0; + + [DoubleFlag(0, 45)] + public double EncounterRate { get; set; } = 0; + + [DoubleFlag(0, 45)] + public double DungeonEncounterRate { get; set; } = 0; + public ProgressiveScaleMode ProgressiveScaleMode { get; set; } = ProgressiveScaleMode.Disabled; + + public StartingItemSet StartingItemSet { get; set; } = StartingItemSet.None; + + public TreasureStackSize ConsumableTreasureStackSize { get; set; } = TreasureStackSize.Default; + + public bool? FIGHTER1 { get; set; } = false; + public bool? THIEF1 { get; set; } = false; + public bool? BLACK_BELT1 { get; set; } = false; + public bool? RED_MAGE1 { get; set; } = false; + public bool? WHITE_MAGE1 { get; set; } = false; + public bool? BLACK_MAGE1 { get; set; } = false; + + public bool? FIGHTER2 { get; set; } = false; + public bool? THIEF2 { get; set; } = false; + public bool? BLACK_BELT2 { get; set; } = false; + public bool? RED_MAGE2 { get; set; } = false; + public bool? WHITE_MAGE2 { get; set; } = false; + public bool? BLACK_MAGE2 { get; set; } = false; + + public bool? FIGHTER3 { get; set; } = false; + public bool? THIEF3 { get; set; } = false; + public bool? BLACK_BELT3 { get; set; } = false; + public bool? RED_MAGE3 { get; set; } = false; + public bool? WHITE_MAGE3 { get; set; } = false; + public bool? BLACK_MAGE3 { get; set; } = false; + + public bool? FIGHTER4 { get; set; } = false; + public bool? THIEF4 { get; set; } = false; + public bool? BLACK_BELT4 { get; set; } = false; + public bool? RED_MAGE4 { get; set; } = false; + public bool? WHITE_MAGE4 { get; set; } = false; + public bool? BLACK_MAGE4 { get; set; } = false; + + public bool? KNIGHT1 { get; set; } = false; + public bool? KNIGHT2 { get; set; } = false; + public bool? KNIGHT3 { get; set; } = false; + public bool? KNIGHT4 { get; set; } = false; + public bool? NINJA1 { get; set; } = false; + public bool? NINJA2 { get; set; } = false; + public bool? NINJA3 { get; set; } = false; + public bool? NINJA4 { get; set; } = false; + public bool? MASTER1 { get; set; } = false; + public bool? MASTER2 { get; set; } = false; + public bool? MASTER3 { get; set; } = false; + public bool? MASTER4 { get; set; } = false; + public bool? RED_WIZ1 { get; set; } = false; + public bool? RED_WIZ2 { get; set; } = false; + public bool? RED_WIZ3 { get; set; } = false; + public bool? RED_WIZ4 { get; set; } = false; + public bool? WHITE_WIZ1 { get; set; } = false; + public bool? WHITE_WIZ2 { get; set; } = false; + public bool? WHITE_WIZ3 { get; set; } = false; + public bool? WHITE_WIZ4 { get; set; } = false; + public bool? BLACK_WIZ1 { get; set; } = false; + public bool? BLACK_WIZ2 { get; set; } = false; + public bool? BLACK_WIZ3 { get; set; } = false; + public bool? BLACK_WIZ4 { get; set; } = false; + public bool? NONE_CLASS2 { get; set; } = false; + public bool? NONE_CLASS3 { get; set; } = false; + public bool? NONE_CLASS4 { get; set; } = false; + public bool? FORCED1 { get; set; } = false; + public bool? FORCED2 { get; set; } = false; + public bool? FORCED3 { get; set; } = false; + public bool? FORCED4 { get; set; } = false; + public bool? DraftFighter { get; set; } = false; + public bool? DraftThief { get; set; } = false; + public bool? DraftBlackBelt { get; set; } = false; + public bool? DraftRedMage { get; set; } = false; + public bool? DraftWhiteMage { get; set; } = false; + public bool? DraftBlackMage { get; set; } = false; + public bool? DraftKnight { get; set; } = false; + public bool? DraftNinja { get; set; } = false; + public bool? DraftMaster { get; set; } = false; + public bool? DraftRedWiz { get; set; } = false; + public bool? DraftWhiteWiz { get; set; } = false; + public bool? DraftBlackWiz { get; set; } = false; + public bool? TAVERN1 { get; set; } = false; + public bool? TAVERN2 { get; set; } = false; + public bool? TAVERN3 { get; set; } = false; + public bool? TAVERN4 { get; set; } = false; + public bool? TAVERN5 { get; set; } = false; + public bool? TAVERN6 { get; set; } = false; + + public bool WeaponPermissions { get; set; } = false; + public bool ArmorPermissions { get; set; } = false; + public bool? RecruitmentMode { get; set; } = false; + public bool? RecruitmentModeHireOnly { get; set; } = false; + public bool? RecruitmentModeReplaceOnlyNone { get; set; } = false; + public bool? ClampMinimumStatScale { get; set; } = false; + public bool? ClampMinimumBossStatScale { get; set; } = false; + public bool? ClampMinimumPriceScale { get; set; } = false; + public bool EFGWaterfall { get; set; } = false; + public bool? FiendShuffle { get; set; } = false; + public bool DisableTentSaving { get; set; } = false; + public bool DisableInnSaving { get; set; } = false; + public bool SaveGameWhenGameOver { get; set; } = false; + public bool SaveGameDWMode { get; set; } = false; + public bool? ShuffleAstos { get; set; } = false; + public bool UnsafeAstos { get; set; } = false; + public bool? RandomizeEnemizer { get; set; } = false; + public bool? RandomizeFormationEnemizer { get; set; } = false; + public bool? GenerateNewSpellbook { get; set; } = false; + public bool? SpellcrafterMixSpells { get; set; } = false; + public bool ThiefHitRate { get; set; } = false; + public bool AllSpellLevelsForKnightNinja { get; set; } = false; + public bool BuffHealingSpells { get; set; } = false; + public bool IntAffectsSpells { get; set; } = false; + public bool? AddDamageTiles { get; set; } = false; + public bool? DamageTilesCastles { get; set; } = false; + public bool? DamageTilesDungeons { get; set; } = false; + public bool? DamageTilesCaves { get; set; } = false; + public bool? DamageTilesTowns { get; set; } = false; + public bool? DamageTilesTof { get; set; } = false; + public DamageTilesQuantity DamageTilesQuantity { get; set; } = DamageTilesQuantity.Normal; + public bool? FreeTail { get; set; } = false; + public bool? HintsVillage { get; set; } = false; + public bool? SpellcrafterRetainPermissions { get; set; } = false; + public bool? RandomWeaponBonus { get; set; } = false; + public bool? RandomArmorBonus { get; set; } = false; + public bool? RandomWeaponBonusExcludeMasa { get; set; } = false; + + [IntegerFlag(-9, 9)] + public int RandomWeaponBonusLow { get; set; } = -5; + + [IntegerFlag(-9, 9)] + public int RandomWeaponBonusHigh { get; set; } = 5; + + [IntegerFlag(-9, 9)] + public int RandomArmorBonusLow { get; set; } = -5; + + [IntegerFlag(-9, 9)] + public int RandomArmorBonusHigh { get; set; } = 5; + public bool? SeparateBossHPScaling { get; set; } = false; + public bool? SeparateEnemyHPScaling { get; set; } = false; + public bool? ClampBossHPScaling { get; set; } = false; + public bool? ClampEnemyHpScaling { get; set; } = false; + public PoolSize PoolSize { get; set; } = PoolSize.Size6; + public bool? EnablePoolParty { get; set; } = false; + public bool SafePoolParty { get; set; } = false; + public bool? IncludePromClasses { get; set; } = false; + public bool? EnableRandomPromotions { get; set; } = false; + public bool? IncludeBaseClasses { get; set; } = false; + public bool? RandomPromotionsSpoilers { get; set; } = false; + public bool? RandomizeClassCasting { get; set; } = false; + public bool? RandomizeClassKeyItems { get; set; } = false; + public bool? RandomizeClassIncludeXpBonus { get; set; } = false; + public bool? AlternateFiends { get; set; } = false; + public bool? FinalFantasy2Fiends { get; set; } = false; + public bool? FinalFantasy3Fiends { get; set; } = false; + public bool? FinalFantasy4Fiends { get; set; } = false; + public bool? FinalFantasy5Fiends { get; set; } = false; + public bool? FinalFantasy6Fiends { get; set; } = false; + public bool? FinalFantasy1BonusFiends { get; set; } = false; + public bool? BlackOrbFiends { get; set; } = false; + public bool? NoBossSkillScriptShuffle { get; set; } = false; + + public bool? MooglieWeaponBalance { get; set; } = false; + public bool? GuaranteeCustomClassComposition { get; set; } = false; + + public bool? LegendaryWeaponShop { get; set; } = false; + public bool? LegendaryArmorShop { get; set; } = false; + public bool? LegendaryBlackShop { get; set; } = false; + public bool? LegendaryWhiteShop { get; set; } = false; + public bool? LegendaryItemShop { get; set; } = false; + + public bool ExclusiveLegendaryWeaponShop { get; set; } = false; + public bool ExclusiveLegendaryArmorShop { get; set; } = false; + public bool ExclusiveLegendaryBlackShop { get; set; } = false; + public bool ExclusiveLegendaryWhiteShop { get; set; } = false; + public bool ExclusiveLegendaryItemShop { get; set; } = false; + public ClassRandomizationMode RandomizeClassMode { get; set; } = ClassRandomizationMode.None; + + [IntegerFlag(0, 3)] + public int RandomizeClassMaxBonus { get; set; } = 2; + + [IntegerFlag(0, 3)] + public int RandomizeClassMaxMalus { get; set; } = 1; + public bool? EarlierHighTierMagic { get; set; } = false; + public bool? ChangeMaxMP { get; set; } = false; + + [IntegerFlag(0, 9)] + public int RedMageMaxMP { get; set; } = 9; + + [IntegerFlag(0, 9)] + public int WhiteMageMaxMP { get; set; } = 9; + + [IntegerFlag(0, 9)] + public int BlackMageMaxMP { get; set; } = 9; + + [IntegerFlag(0, 9)] + public int KnightMaxMP { get; set; } = 4; + + [IntegerFlag(0, 9)] + public int NinjaMaxMP { get; set; } = 4; + + public bool? Knightlvl4 { get; set; } = false; + public bool? PinkMage { get; set; } = false; + public bool? BlackKnight { get; set; } = false; + public bool? BlackKnightKeep { get; set; } = false; + public bool? WhiteNinja { get; set; } = false; + public bool? WhiteNinjaKeep { get; set; } = false; + + public MpGainOnMaxGain MpGainOnMaxGainMode { get; set; } = MpGainOnMaxGain.None; + + public LockHitMode LockMode { get; set; } = LockHitMode.Vanilla; + // Done + public MDEFGrowthMode MDefMode { get; set; } = MDEFGrowthMode.None; + + public FormationShuffleMode FormationShuffleMode { get; set; } = FormationShuffleMode.None; + + public RandomizeTreasureMode RandomizeTreasure { get; set; } = RandomizeTreasureMode.None; + public bool OpenChestsInOrder { get; set; } = false; + public bool SetRNG { get; set; } = false; + public WorldWealthMode WorldWealth { get; set; } = WorldWealthMode.Standard; + public DeepDungeonGeneratorMode DeepDungeonGenerator { get; set; } = DeepDungeonGeneratorMode.Progressive; + public EvadeCapValues EvadeCap { get; set; } = EvadeCapValues.medium; + + public bool? AllowUnsafeStartArea { get; set; } = false; + + public bool? IncreaseDarkPenalty { get; set; } = false; + public bool? IncreaseRegeneration { get; set; } = false; + public PoisonModeOptions PoisonMode { get; set; } = PoisonModeOptions.Constant; + [IntegerFlag(1,500)] + + public int PoisonSetDamageValue { get; set; } = 3; + + public bool? TouchIncludeBosses { get; set; } = false; + + public bool? Lockpicking { get; set; } = false; + // Done + public bool? ReducedLuck { get; set; } = false; + + [IntegerFlag(1, 50)] + public int LockpickingLevelRequirement { get; set; } = 10; + + public bool WhiteMageHarmEveryone { get; set; } = false; + + public bool? ProcgenEarth { get; set; } = false; + } +} diff --git a/FF1Lib/Hacks.cs b/FF1Lib/Hacks.cs index d542fd723..10edfb351 100644 --- a/FF1Lib/Hacks.cs +++ b/FF1Lib/Hacks.cs @@ -325,6 +325,16 @@ public void IncreaseDarkPenalty(bool enable) Put(0x326A7, Blob.FromHex("A9008D56688D62681A")); } + public void IncreaseRegeneration(bool enable) + { + if (!enable) + { + return; + } + + PutInBank(0x0C, 0xA26A, Blob.FromHex("39")); + } + public void SetPoisonMode(PoisonModeOptions poisonMode, int poisonValue) { //see 1C_A670_ImprovedPoison.asm diff --git a/FF1Lib/Randomize.cs b/FF1Lib/Randomize.cs index 71ac4614b..be0359fc1 100644 --- a/FF1Lib/Randomize.cs +++ b/FF1Lib/Randomize.cs @@ -1,445 +1,446 @@ -using FF1Lib.Music; -using FF1Lib.Procgen; -using RomUtilities; -namespace FF1Lib; - -// ReSharper disable once InconsistentNaming -public partial class FF1Rom : NesRom -{ - public const int LevelRequirementsOffset = 0x6CC81; - public const int LevelRequirementsSize = 3; - public const int LevelRequirementsCount = 49; - - public const int GoldItemOffset = 108; // 108 items before gold chests - public const int GoldItemCount = 68; - //public List UnusedGoldItems = new List { 110, 111, 112, 113, 114, 116, 120, 121, 122, 124, 125, 127, 132, 158, 165, 166, 167, 168, 170, 171, 172 }; - - public ItemNames ItemsText; - public GearPermissions ArmorPermissions; - public GearPermissions WeaponPermissions; - public SpellPermissions SpellPermissions; - public GameClasses ClassData; - public RngTables RngTables; - public TileSetsData TileSetsData; - public ZoneFormations ZoneFormations; - public StandardMaps Maps; - public NpcObjectData NpcData; - public DialogueData Dialogues; - public MenuText MenuText; - public TalkRoutines TalkRoutines; - public StartingItems StartingItems; - public EncounterRate EncounterRates; - public EnemyScripts EnemyScripts; - public ShopData ShopData; - public MusicTracks Music; - public NewMusic NewMusic; - public ExtAltFiends ExtAltFiends; - - public DeepDungeon DeepDungeon; - - public OwMapExchange OverworldMapData; - public Teleporters Teleporters; - public Overworld Overworld; - - private SanityCheckerV2 sanityChecker = null; - private PlacementContext PlacementContext = null; - - private Blob SavedHash; - - public void LoadSharedDataTables() - { - ItemsText = new ItemNames(this); - ArmorPermissions = new GearPermissions(0x3BFA0, (int)Item.Cloth, this); - WeaponPermissions = new GearPermissions(0x3BF50, (int)Item.WoodenNunchucks, this); - SpellPermissions = new SpellPermissions(this); - ClassData = new GameClasses(WeaponPermissions, ArmorPermissions, SpellPermissions, this); - } - - public delegate Task ProgressMessage(int step, int max, string message); - - public delegate Task ReportProgress(string message="", int addMax=0); - - int currentStep = 0; - int maxSteps = 0; - public ProgressMessage ProgressCallback; - - public async Task Progress(string message="", int addMax=0) - { - maxSteps += addMax; - currentStep += 1; - if (ProgressCallback != null) { - await ProgressCallback(currentStep, maxSteps, message); - } - } - public async Task Randomize(Blob seed, Flags flags, Preferences preferences) - { - // Confirm ROM integrity - if (flags.TournamentSafe) AssureSafe(); - - // Copy flags for various use - Flags flagsForRng = flags.ShallowCopy(); - Flags unmodifiedFlags = flags.ShallowCopy(); - - // Setup Rng - Blob resourcesPackHash = GenerateRng(flagsForRng, seed); - - // Collapse tristate flags - flags = Flags.ConvertAllTriState(flags, rng); - - await this.Progress("Beginning Randomization", 15); - - // load resource pack data that needs to go into initial ROM before - // data is read - await this.LoadResourcePackPreROM(flags.ResourcePack, preferences); - await this.LoadFunTiles(preferences); - - // Load Initial Data - RngTables = new(this); - TileSetsData = new(this); - ZoneFormations = new(this); - Overworld = new(this, flags, ZoneFormations, rng); - await Overworld.LoadMapExchange(); - ItemsText = new ItemNames(this); - ArmorPermissions = new GearPermissions(0x3BFA0, (int)Item.Cloth, this); - WeaponPermissions = new GearPermissions(0x3BF50, (int)Item.WoodenNunchucks, this); - SpellPermissions = new SpellPermissions(this); - ClassData = new GameClasses(WeaponPermissions, ArmorPermissions, SpellPermissions, this); - Teleporters = new Teleporters(this, Overworld.MapExchangeData); - Maps = new StandardMaps(this, Teleporters, flags); - NpcData = new NpcObjectData(Maps, flags, rng, this); - TalkRoutines = new TalkRoutines(); - Dialogues = new DialogueData(this); - MenuText = new MenuText(this); - ShopData = new ShopData(flags, this); - EncounterRates = new EncounterRate(this); - EnemyScripts = new EnemyScripts(this); - Music = new MusicTracks(); - ExtAltFiends = new ExtAltFiends(flags); - - - await this.Progress(); - - // Expand ROM, move data around - GlobalHacks(); - - // load resource pack data that requires the ROM expansion that just took place - await this.LoadResourcePackPostROM(flags.ResourcePack, Dialogues, EnemyScripts, preferences); - - - TalkRoutines.TransferTalkRoutines(this, flags); - Dialogues.TransferDialogues(); - - // Apply general fixes and hacks - FF1Text.AddNewIcons(this, flags); - Music.ShuffleMusic(this, preferences, new MT19337(funRng.Next())); - NewMusic = new NewMusic(this); - Bugfixes(flags); - GlobalImprovements(flags, Maps, preferences); - MiscHacks(flags, rng); - var oldItemNames = ItemsText.ToList(); - MapIndex warmMechFloor = MapIndex.SkyPalace4F; - - // Load Ressources Packs Maps - LoadResourcePackMaps(flags.ResourcePack, Maps, Teleporters); - - await this.Progress(); - - // Game Modes - DeepDungeon = new DeepDungeon(Maps, Teleporters, NpcData, TileSetsData, flags, this); - if (flags.GameMode == GameModes.DeepDungeon) - { - await this.Progress("Generating Deep Dungeon's Floors...", 2); - - DeepDungeon.Generate(rng, Overworld, EncounterRates, ZoneFormations, Dialogues); - DeepDungeonFloorIndicator(); - warmMechFloor = (MapIndex)DeepDungeon.WarMechFloor; - - await this.Progress("Generating Deep Dungeon's Floors... Done!"); - } - DesertOfDeath.ApplyDesertModifications((bool)flags.DesertOfDeath, this, ZoneFormations, Overworld, NpcData, Dialogues, Music); - Spooky(TalkRoutines, NpcData, Dialogues, ZoneFormations, Maps, rng, flags); - BlackOrbMode(TalkRoutines, Dialogues, flags, preferences, rng, new MT19337(funRng.Next())); - Maps.ProcgenDungeons(rng); - DraculasCurse(Overworld, Teleporters, rng, flags); - - await this.Progress(); - - // Maps - GeneralMapHacks(flags, Overworld, Maps, ZoneFormations, TileSetsData, rng); - Maps.Update(ZoneFormations, rng); - if (flags.NoOverworld) await this.Progress("Linking NoOverworld's Map", 1); - NoOverworld(Overworld.DecompressedMap, Maps, Teleporters, TileSetsData, TalkRoutines, Dialogues, NpcData, flags, rng); - UpdateToFR(Maps, Teleporters, TileSetsData, flags, rng); - Teleporters.ShuffleEntrancesAndFloors(Overworld.OverworldMap, rng, flags); - Overworld.Update(Teleporters); - EncounterRates.ScaleEncounterRate(flags); - - // Tile Sets - TileSetsData.Update(flags, rng); - TileSetsData.UpdateTrapTiles(this, ZoneFormations, flags, rng); - await DamageTilesHack(flags, Overworld); - - await this.Progress(); - - // NPCs - Dialogues.UpdateNPCDialogues(flags); - PacifistBat(Maps, TalkRoutines, NpcData); - TalkRoutines.Update(flags); - ClassAsNPC(flags, TalkRoutines, NpcData, Dialogues, Maps, rng); - - // Relocate chests need to happen after NPCs, before logic - await new RelocateChests(this).RandomlyRelocateChests(rng, Maps, TileSetsData, Teleporters, NpcData, flags); - - // Spells - CraftNewSpellbook(EnemyScripts, flags, rng); - SpellBalanceHacks(flags, rng); - TranceHasStatusElement(flags.TranceHasStatusElement); - ShuffleMagicLevels(EnemyScripts, rng, (bool)flags.MagicLevels, (bool)flags.MagicPermissions, (bool)flags.MagicLevelsTiered, (bool)flags.MagicLevelsMixed); - SpellNames(flags, preferences, rng); - var extConsumables = new ExtConsumables(ShopData, this, flags, rng); - extConsumables.LoadSpells(); - - // Create items - Etherizer(flags.Etherizer, ItemsText); - - Weaponizer(flags, rng); - ArmorCrafter(flags, rng); - new RibbonShuffle(this, rng, flags, ItemsText, ArmorPermissions).Work(); - - ItemMagic(flags, rng); - - DoubleWeaponCritRates(flags.WeaponCritRate); - List weaponBlursesValues = Enumerable.Repeat(0, 40).ToList(); - RandomWeaponBonus(flags, preferences.CleanBlursedEquipmentNames, weaponBlursesValues, rng); - RandomArmorBonus(flags, preferences.CleanBlursedEquipmentNames, rng); - IncreaseWeaponBonus(flags.WeaponBonuses, flags.WeaponTypeBonusValue); - - // Starting Inventory - StartingItems = new StartingItems(new() { }, rng, flags, this); - - // Placement Context - var priceList = Get(0x37C00, 0x200).ToUShorts().Select(x => (int)x).ToList(); // Temporary until we extract price - PlacementContext = (flags.GameMode != GameModes.DeepDungeon) ? - new PlacementContext(StartingItems, new() { }, priceList, rng, flags) : - new PlacementContext(StartingItems, new() { }, DeepDungeon.PlacedItems, DeepDungeon.ChestLocations, priceList, rng, flags); - - // Shops - ShopData.ShuffleShops(rng, PlacementContext.ExcludedItemsFromShops, Teleporters.ConeriaTownEntranceItemShopIndex); - ShopData.ShuffleMagicLocations((bool)flags.MagicShopLocs, (bool)flags.MagicShopLocationPairs, rng); - ShopData.ShuffleMagicShops((bool)flags.MagicShops, rng); - extConsumables.AddNormalShopEntries(); - new ShopKiller(Maps, ShopData, rng, flags, this).KillShops(); - new LegendaryShops(rng, flags, Maps, ShopData, TileSetsData, this).PlaceShops(); - - await this.Progress("Building Placement Logic"); - - // Create Logic Checker - sanityChecker = new SanityCheckerV2(Maps, Overworld, NpcData, Teleporters, TileSetsData, this, ShopData.ItemShopSlot); - if (!sanityChecker.CheckSanity(ItemLocations.AllQuestItemLocations.ToList(), null, flags, true).Complete) throw new InsaneException("Not Completable"); - - await this.Progress(flags.VanillaPlacement ? "Placing Treasures" : "Shuffling Treasures"); - - // Item Placement - ItemPlacement itemPlacement = ItemPlacement.Create(this, flags, PlacementContext, ShopData.ItemShopSlot, Overworld, sanityChecker); - itemPlacement.PlaceItems(rng); - - NpcData.UpdateItemPlacement(itemPlacement.PlacedItems); - ShopData.UpdateShopSlotPlacement(itemPlacement.PlacedItems); - - List funMessages = new() - { - "Placing Out of Bound Bat", - "Cleaning up Lich's closet", - "Labelling pots in Sarda's Cave", - "Partying in the Bat Party Room", - "Buffing up NPC's path-blocking AI", - "Debugging WarMech's software", - "Knocking down some impertinent fools", - "Sending Garland 2,000 years in the past", - "Giving a snack to Titan while waiting for the main course", - "Disguising Astos", - "Cursing the Elf Prince", - "Stealing Matoya's Crystal", - "Abducting Princess Sara", - "Placing the worst skills in Medusa's script", - "Applying for a Bridge building permit", - "Reticulating Splines", - "Digging Cave Holes", - "Bottling the Fairy", - "Floating the Sky Castle", - "Locking the door in Temple of Fiends", - "Teaching Kraken Kung Fu", - "Raising the Lich", - }; - - funMessages.AddRange(Enumerable.Repeat("Finalizing", funMessages.Count * 4).ToList()); - - await this.Progress(funMessages.PickRandom(rng)); - - // Enemies - if ((bool)flags.AlternateFiends && !flags.SpookyFlag) await this.Progress("Creating new Fiends", 1); - AlternativeFiends(ExtAltFiends, EnemyScripts, rng, flags); - TransformFinalFormation(flags, rng); - DoEnemizer(EnemyScripts, ZoneFormations, flags, rng); - - ShuffleEnemyScripts(rng, flags); - EnemyScripts.ShuffleEnemySkillsSpells(this, rng, flags); - StatusAttacks(flags, rng); - ShuffleUnrunnable(rng, flags); - AllowStrikeFirstAndSurprise(flags.WaitWhenUnrunnable, (bool)flags.UnrunnablesStrikeFirstAndSurprise); - ShuffleSurpriseBonus((bool)flags.EnemyFormationsSurprise, rng); - - // After unrunnable shuffle and before formation shuffle - WarMechMode.Process(this, flags, NpcData, ZoneFormations, Dialogues, rng, Maps, warmMechFloor); - FightBahamut(flags, TalkRoutines, NpcData, ZoneFormations, Dialogues, Maps, EnemyScripts, rng); - Astos(NpcData, Dialogues, TalkRoutines, EnemyScripts, flags, rng); - EnableSwolePirates((bool)flags.SwolePirates); - ExtAltFiends.ExtendedFiendsUpdate(NpcData, Dialogues, this, rng); - - FiendShuffle((bool)flags.FiendShuffle, rng); - ScaleEnemyStats(rng, flags); - ScaleBossStats(rng, flags); - - // Encounters - ZoneFormations.ShuffleEnemyFormations(rng, flags.FormationShuffleMode, flags.EnemizerEnabled); - ZoneFormations.UnleashWarMECH(flags.WarMECHMode == WarMECHMode.Unleashed || flags.WarMECHMode == WarMECHMode.All); - - await this.Progress(); - - // Misc - RngTables.Update(flags, rng); - DisableMinimap(flags.DisableMinimap); - ImproveTurnOrderRandomization(flags.ImproveTurnOrderRandomization, rng); - SavingHacks(Overworld, flags); - ImprovedClinic(flags.ImprovedClinic && !(bool)flags.RecruitmentMode); - IncreaseDarkPenalty((bool)flags.IncreaseDarkPenalty); - SetPoisonMode(flags.PoisonMode, flags.PoisonSetDamageValue); - new QuickMiniMap(this, Overworld.DecompressedMap).EnableQuickMinimap(flags.SpeedHacks || Overworld.MapExchange != null, Music); - EnableAirBoat(flags); - OpenChestsInOrder(flags.OpenChestsInOrder && !flags.Archipelago); - SetRNG(flags); - - new TreasureStacks(this, flags).SetTreasureStacks(); - - await this.Progress(); - - NPCHints(rng, NpcData, Maps, Dialogues, flags, PlacementContext, sanityChecker, itemPlacement, ShopData); - SkyWarriorSpoilerBats(rng, flags, NpcData, Dialogues, EnemyScripts); - - MonsterInABox(itemPlacement, ZoneFormations, TileSetsData, NpcData, Dialogues, rng, flags); - - ExpGoldBoost(flags); - ScalePrices(ShopData, flags, rng, ((bool)flags.ClampMinimumPriceScale), ShopData.ItemShopSlot, flags.ImprovedClinic); - extConsumables.AddExtConsumables(); - - await this.Progress(); - - // Party - PartyGeneration(rng, flags, preferences); - PubReplaceClinic(rng, Maps.AttackedTown, flags); - - // Experience - ScaleAllAltExp(flags); - XpAdmissibility((bool)flags.NonesGainXP, flags.DeadsGainXP); - SetProgressiveScaleMode(flags); - var expChests = new ExpChests(itemPlacement.PlacedItems, this, flags, rng); - expChests.BuildExpChests(); - - // Classes Features - ClassesBalances(flags, rng); - ClassData.SetMPMax(flags); - ClassData.SetMpGainOnMaxGain(flags, this); - ClassData.RaiseThiefHitRate(flags); - ClassData.BuffThiefAGI(flags); - ClassData.EarlierHighTierMagicCharges(flags); - ClassData.Randomize(flags, rng, oldItemNames, ItemsText, this); - ClassData.ProcessStartWithRoutines(flags, weaponBlursesValues, this); - ClassData.PinkMage(flags); - ClassData.BlackKnight(flags); - ClassData.WhiteNinja(flags); - ClassData.Knightlvl4(flags, rng); - EnableRandomPromotions(flags, rng); - - await this.Progress(); - - - RollCredits(rng); - - - StatsTrackingHacks(flags, preferences); - if ((bool)flags.IsShipFree || flags.Archipelago) Overworld.SetShipLocation(255); - if (flags.TournamentSafe || preferences.CropScreen) ActivateCropScreen(); - - // Quality of Life Stuff - ShopUpgrade(flags, Dialogues, preferences); - QualityOfLifeHacks(flags, preferences); - UseVariablePaletteForCursorAndStone(preferences.ThirdBattlePalette || flags.ResourcePack != null); - EnableModernBattlefield(preferences.ModernBattlefield); - DynamicWindowColor(preferences.MenuColor); - - // Fun Stuff - ChangeLute(preferences.ChangeLute, Dialogues, new MT19337(funRng.Next())); - TitanSnack(preferences.TitanSnack, NpcData, Dialogues, new MT19337(funRng.Next())); - HurrayDwarfFate(preferences.HurrayDwarfFate, NpcData, Dialogues, new MT19337(funRng.Next())); - PaletteSwap(preferences.PaletteSwap && !flags.EnemizerEnabled, new MT19337(funRng.Next())); - TeamSteak(preferences.TeamSteak && !(bool)flags.RandomizeEnemizer); - FunEnemyNames(flags, preferences, new MT19337(funRng.Next())); - - await this.Progress(); - - // Custom Sprites - if (preferences.SpriteSheet != null) - { - using (var stream = new MemoryStream(Convert.FromBase64String(preferences.SpriteSheet))) - { - await SetCustomPlayerSprites(stream, preferences.ThirdBattlePalette, preferences.MapmanSlot); - } - } - - // Archipelago - if (flags.Archipelago) - { - Archipelago exporter = new Archipelago(this, itemPlacement, sanityChecker, expChests, PlacementContext, Overworld.Locations, seed, flags, unmodifiedFlags, preferences); - Utilities.ArchipelagoCache = exporter.Work(); - } - - // Spoilers - if (flags.Spoilers && sanityChecker != null) new ExtSpoiler(this, sanityChecker, ShopData, ItemsText, itemPlacement.PlacedItems, Overworld, PlacementContext, WeaponPermissions, ArmorPermissions, flags).WriteSpoiler(); - - // Write back everything - ItemsText.Write(this, flags.GameMode == GameModes.DeepDungeon ? new List() : ItemLists.UnusedGoldItems.ToList()); - TalkRoutines.Write(this); - NpcData.Write(TalkRoutines.ScriptPointers); - Dialogues.Write(); - ShopData.StoreData(); - - EnemyScripts.Write(this); - EncounterRates.Write(); - itemPlacement.Write(); - - Maps.Write(); - TileSetsData.Write(); - ZoneFormations.Write(this); - StartingItems.Write(); - RngTables.Write(this,flags); - Teleporters.Write(); - Overworld.Write(); - ArmorPermissions.Write(this); - WeaponPermissions.Write(this); - SpellPermissions.Write(this); - ClassData.Write(this); - MenuText.Write(this); - Music.Write(this, flags, preferences); - NewMusic.Write(this, preferences, flags, new MT19337(funRng.Next())); - - await this.Progress(); - - uint last_rng_value = rng.Next(); - - // Final ROM writes - WriteSeedAndFlags(seed.ToHex(), flags, flagsForRng, unmodifiedFlags, resourcesPackHash.ToHex(), last_rng_value); - if (flags.TournamentSafe) Put(0x3FFE3, Blob.FromHex("66696E616C2066616E74617379")); - - await this.Progress("Randomization Completed"); - } -} +using FF1Lib.Music; +using FF1Lib.Procgen; +using RomUtilities; +namespace FF1Lib; + +// ReSharper disable once InconsistentNaming +public partial class FF1Rom : NesRom +{ + public const int LevelRequirementsOffset = 0x6CC81; + public const int LevelRequirementsSize = 3; + public const int LevelRequirementsCount = 49; + + public const int GoldItemOffset = 108; // 108 items before gold chests + public const int GoldItemCount = 68; + //public List UnusedGoldItems = new List { 110, 111, 112, 113, 114, 116, 120, 121, 122, 124, 125, 127, 132, 158, 165, 166, 167, 168, 170, 171, 172 }; + + public ItemNames ItemsText; + public GearPermissions ArmorPermissions; + public GearPermissions WeaponPermissions; + public SpellPermissions SpellPermissions; + public GameClasses ClassData; + public RngTables RngTables; + public TileSetsData TileSetsData; + public ZoneFormations ZoneFormations; + public StandardMaps Maps; + public NpcObjectData NpcData; + public DialogueData Dialogues; + public MenuText MenuText; + public TalkRoutines TalkRoutines; + public StartingItems StartingItems; + public EncounterRate EncounterRates; + public EnemyScripts EnemyScripts; + public ShopData ShopData; + public MusicTracks Music; + public NewMusic NewMusic; + public ExtAltFiends ExtAltFiends; + + public DeepDungeon DeepDungeon; + + public OwMapExchange OverworldMapData; + public Teleporters Teleporters; + public Overworld Overworld; + + private SanityCheckerV2 sanityChecker = null; + private PlacementContext PlacementContext = null; + + private Blob SavedHash; + + public void LoadSharedDataTables() + { + ItemsText = new ItemNames(this); + ArmorPermissions = new GearPermissions(0x3BFA0, (int)Item.Cloth, this); + WeaponPermissions = new GearPermissions(0x3BF50, (int)Item.WoodenNunchucks, this); + SpellPermissions = new SpellPermissions(this); + ClassData = new GameClasses(WeaponPermissions, ArmorPermissions, SpellPermissions, this); + } + + public delegate Task ProgressMessage(int step, int max, string message); + + public delegate Task ReportProgress(string message="", int addMax=0); + + int currentStep = 0; + int maxSteps = 0; + public ProgressMessage ProgressCallback; + + public async Task Progress(string message="", int addMax=0) + { + maxSteps += addMax; + currentStep += 1; + if (ProgressCallback != null) { + await ProgressCallback(currentStep, maxSteps, message); + } + } + public async Task Randomize(Blob seed, Flags flags, Preferences preferences) + { + // Confirm ROM integrity + if (flags.TournamentSafe) AssureSafe(); + + // Copy flags for various use + Flags flagsForRng = flags.ShallowCopy(); + Flags unmodifiedFlags = flags.ShallowCopy(); + + // Setup Rng + Blob resourcesPackHash = GenerateRng(flagsForRng, seed); + + // Collapse tristate flags + flags = Flags.ConvertAllTriState(flags, rng); + + await this.Progress("Beginning Randomization", 15); + + // load resource pack data that needs to go into initial ROM before + // data is read + await this.LoadResourcePackPreROM(flags.ResourcePack, preferences); + await this.LoadFunTiles(preferences); + + // Load Initial Data + RngTables = new(this); + TileSetsData = new(this); + ZoneFormations = new(this); + Overworld = new(this, flags, ZoneFormations, rng); + await Overworld.LoadMapExchange(); + ItemsText = new ItemNames(this); + ArmorPermissions = new GearPermissions(0x3BFA0, (int)Item.Cloth, this); + WeaponPermissions = new GearPermissions(0x3BF50, (int)Item.WoodenNunchucks, this); + SpellPermissions = new SpellPermissions(this); + ClassData = new GameClasses(WeaponPermissions, ArmorPermissions, SpellPermissions, this); + Teleporters = new Teleporters(this, Overworld.MapExchangeData); + Maps = new StandardMaps(this, Teleporters, flags); + NpcData = new NpcObjectData(Maps, flags, rng, this); + TalkRoutines = new TalkRoutines(); + Dialogues = new DialogueData(this); + MenuText = new MenuText(this); + ShopData = new ShopData(flags, this); + EncounterRates = new EncounterRate(this); + EnemyScripts = new EnemyScripts(this); + Music = new MusicTracks(); + ExtAltFiends = new ExtAltFiends(flags); + + + await this.Progress(); + + // Expand ROM, move data around + GlobalHacks(); + + // load resource pack data that requires the ROM expansion that just took place + await this.LoadResourcePackPostROM(flags.ResourcePack, Dialogues, EnemyScripts, preferences); + + + TalkRoutines.TransferTalkRoutines(this, flags); + Dialogues.TransferDialogues(); + + // Apply general fixes and hacks + FF1Text.AddNewIcons(this, flags); + Music.ShuffleMusic(this, preferences, new MT19337(funRng.Next())); + NewMusic = new NewMusic(this); + Bugfixes(flags); + GlobalImprovements(flags, Maps, preferences); + MiscHacks(flags, rng); + var oldItemNames = ItemsText.ToList(); + MapIndex warmMechFloor = MapIndex.SkyPalace4F; + + // Load Ressources Packs Maps + LoadResourcePackMaps(flags.ResourcePack, Maps, Teleporters); + + await this.Progress(); + + // Game Modes + DeepDungeon = new DeepDungeon(Maps, Teleporters, NpcData, TileSetsData, flags, this); + if (flags.GameMode == GameModes.DeepDungeon) + { + await this.Progress("Generating Deep Dungeon's Floors...", 2); + + DeepDungeon.Generate(rng, Overworld, EncounterRates, ZoneFormations, Dialogues); + DeepDungeonFloorIndicator(); + warmMechFloor = (MapIndex)DeepDungeon.WarMechFloor; + + await this.Progress("Generating Deep Dungeon's Floors... Done!"); + } + DesertOfDeath.ApplyDesertModifications((bool)flags.DesertOfDeath, this, ZoneFormations, Overworld, NpcData, Dialogues, Music); + Spooky(TalkRoutines, NpcData, Dialogues, ZoneFormations, Maps, rng, flags); + BlackOrbMode(TalkRoutines, Dialogues, flags, preferences, rng, new MT19337(funRng.Next())); + Maps.ProcgenDungeons(rng); + DraculasCurse(Overworld, Teleporters, rng, flags); + + await this.Progress(); + + // Maps + GeneralMapHacks(flags, Overworld, Maps, ZoneFormations, TileSetsData, rng); + Maps.Update(ZoneFormations, rng); + if (flags.NoOverworld) await this.Progress("Linking NoOverworld's Map", 1); + NoOverworld(Overworld.DecompressedMap, Maps, Teleporters, TileSetsData, TalkRoutines, Dialogues, NpcData, flags, rng); + UpdateToFR(Maps, Teleporters, TileSetsData, flags, rng); + Teleporters.ShuffleEntrancesAndFloors(Overworld.OverworldMap, rng, flags); + Overworld.Update(Teleporters); + EncounterRates.ScaleEncounterRate(flags); + + // Tile Sets + TileSetsData.Update(flags, rng); + TileSetsData.UpdateTrapTiles(this, ZoneFormations, flags, rng); + await DamageTilesHack(flags, Overworld); + + await this.Progress(); + + // NPCs + Dialogues.UpdateNPCDialogues(flags); + PacifistBat(Maps, TalkRoutines, NpcData); + TalkRoutines.Update(flags); + ClassAsNPC(flags, TalkRoutines, NpcData, Dialogues, Maps, rng); + + // Relocate chests need to happen after NPCs, before logic + await new RelocateChests(this).RandomlyRelocateChests(rng, Maps, TileSetsData, Teleporters, NpcData, flags); + + // Spells + CraftNewSpellbook(EnemyScripts, flags, rng); + SpellBalanceHacks(flags, rng); + TranceHasStatusElement(flags.TranceHasStatusElement); + ShuffleMagicLevels(EnemyScripts, rng, (bool)flags.MagicLevels, (bool)flags.MagicPermissions, (bool)flags.MagicLevelsTiered, (bool)flags.MagicLevelsMixed); + SpellNames(flags, preferences, rng); + var extConsumables = new ExtConsumables(ShopData, this, flags, rng); + extConsumables.LoadSpells(); + + // Create items + Etherizer(flags.Etherizer, ItemsText); + + Weaponizer(flags, rng); + ArmorCrafter(flags, rng); + new RibbonShuffle(this, rng, flags, ItemsText, ArmorPermissions).Work(); + + ItemMagic(flags, rng); + + DoubleWeaponCritRates(flags.WeaponCritRate); + List weaponBlursesValues = Enumerable.Repeat(0, 40).ToList(); + RandomWeaponBonus(flags, preferences.CleanBlursedEquipmentNames, weaponBlursesValues, rng); + RandomArmorBonus(flags, preferences.CleanBlursedEquipmentNames, rng); + IncreaseWeaponBonus(flags.WeaponBonuses, flags.WeaponTypeBonusValue); + + // Starting Inventory + StartingItems = new StartingItems(new() { }, rng, flags, this); + + // Placement Context + var priceList = Get(0x37C00, 0x200).ToUShorts().Select(x => (int)x).ToList(); // Temporary until we extract price + PlacementContext = (flags.GameMode != GameModes.DeepDungeon) ? + new PlacementContext(StartingItems, new() { }, priceList, rng, flags) : + new PlacementContext(StartingItems, new() { }, DeepDungeon.PlacedItems, DeepDungeon.ChestLocations, priceList, rng, flags); + + // Shops + ShopData.ShuffleShops(rng, PlacementContext.ExcludedItemsFromShops, Teleporters.ConeriaTownEntranceItemShopIndex); + ShopData.ShuffleMagicLocations((bool)flags.MagicShopLocs, (bool)flags.MagicShopLocationPairs, rng); + ShopData.ShuffleMagicShops((bool)flags.MagicShops, rng); + extConsumables.AddNormalShopEntries(); + new ShopKiller(Maps, ShopData, rng, flags, this).KillShops(); + new LegendaryShops(rng, flags, Maps, ShopData, TileSetsData, this).PlaceShops(); + + await this.Progress("Building Placement Logic"); + + // Create Logic Checker + sanityChecker = new SanityCheckerV2(Maps, Overworld, NpcData, Teleporters, TileSetsData, this, ShopData.ItemShopSlot); + if (!sanityChecker.CheckSanity(ItemLocations.AllQuestItemLocations.ToList(), null, flags, true).Complete) throw new InsaneException("Not Completable"); + + await this.Progress(flags.VanillaPlacement ? "Placing Treasures" : "Shuffling Treasures"); + + // Item Placement + ItemPlacement itemPlacement = ItemPlacement.Create(this, flags, PlacementContext, ShopData.ItemShopSlot, Overworld, sanityChecker); + itemPlacement.PlaceItems(rng); + + NpcData.UpdateItemPlacement(itemPlacement.PlacedItems); + ShopData.UpdateShopSlotPlacement(itemPlacement.PlacedItems); + + List funMessages = new() + { + "Placing Out of Bound Bat", + "Cleaning up Lich's closet", + "Labelling pots in Sarda's Cave", + "Partying in the Bat Party Room", + "Buffing up NPC's path-blocking AI", + "Debugging WarMech's software", + "Knocking down some impertinent fools", + "Sending Garland 2,000 years in the past", + "Giving a snack to Titan while waiting for the main course", + "Disguising Astos", + "Cursing the Elf Prince", + "Stealing Matoya's Crystal", + "Abducting Princess Sara", + "Placing the worst skills in Medusa's script", + "Applying for a Bridge building permit", + "Reticulating Splines", + "Digging Cave Holes", + "Bottling the Fairy", + "Floating the Sky Castle", + "Locking the door in Temple of Fiends", + "Teaching Kraken Kung Fu", + "Raising the Lich", + }; + + funMessages.AddRange(Enumerable.Repeat("Finalizing", funMessages.Count * 4).ToList()); + + await this.Progress(funMessages.PickRandom(rng)); + + // Enemies + if ((bool)flags.AlternateFiends && !flags.SpookyFlag) await this.Progress("Creating new Fiends", 1); + AlternativeFiends(ExtAltFiends, EnemyScripts, rng, flags); + TransformFinalFormation(flags, rng); + DoEnemizer(EnemyScripts, ZoneFormations, flags, rng); + + ShuffleEnemyScripts(rng, flags); + EnemyScripts.ShuffleEnemySkillsSpells(this, rng, flags); + StatusAttacks(flags, rng); + ShuffleUnrunnable(rng, flags); + AllowStrikeFirstAndSurprise(flags.WaitWhenUnrunnable, (bool)flags.UnrunnablesStrikeFirstAndSurprise); + ShuffleSurpriseBonus((bool)flags.EnemyFormationsSurprise, rng); + + // After unrunnable shuffle and before formation shuffle + WarMechMode.Process(this, flags, NpcData, ZoneFormations, Dialogues, rng, Maps, warmMechFloor); + FightBahamut(flags, TalkRoutines, NpcData, ZoneFormations, Dialogues, Maps, EnemyScripts, rng); + Astos(NpcData, Dialogues, TalkRoutines, EnemyScripts, flags, rng); + EnableSwolePirates((bool)flags.SwolePirates); + ExtAltFiends.ExtendedFiendsUpdate(NpcData, Dialogues, this, rng); + + FiendShuffle((bool)flags.FiendShuffle, rng); + ScaleEnemyStats(rng, flags); + ScaleBossStats(rng, flags); + + // Encounters + ZoneFormations.ShuffleEnemyFormations(rng, flags.FormationShuffleMode, flags.EnemizerEnabled); + ZoneFormations.UnleashWarMECH(flags.WarMECHMode == WarMECHMode.Unleashed || flags.WarMECHMode == WarMECHMode.All); + + await this.Progress(); + + // Misc + RngTables.Update(flags, rng); + DisableMinimap(flags.DisableMinimap); + ImproveTurnOrderRandomization(flags.ImproveTurnOrderRandomization, rng); + SavingHacks(Overworld, flags); + ImprovedClinic(flags.ImprovedClinic && !(bool)flags.RecruitmentMode); + IncreaseDarkPenalty((bool)flags.IncreaseDarkPenalty); + IncreaseRegeneration((bool)flags.IncreaseRegeneration); + SetPoisonMode(flags.PoisonMode, flags.PoisonSetDamageValue); + new QuickMiniMap(this, Overworld.DecompressedMap).EnableQuickMinimap(flags.SpeedHacks || Overworld.MapExchange != null, Music); + EnableAirBoat(flags); + OpenChestsInOrder(flags.OpenChestsInOrder && !flags.Archipelago); + SetRNG(flags); + + new TreasureStacks(this, flags).SetTreasureStacks(); + + await this.Progress(); + + NPCHints(rng, NpcData, Maps, Dialogues, flags, PlacementContext, sanityChecker, itemPlacement, ShopData); + SkyWarriorSpoilerBats(rng, flags, NpcData, Dialogues, EnemyScripts); + + MonsterInABox(itemPlacement, ZoneFormations, TileSetsData, NpcData, Dialogues, rng, flags); + + ExpGoldBoost(flags); + ScalePrices(ShopData, flags, rng, ((bool)flags.ClampMinimumPriceScale), ShopData.ItemShopSlot, flags.ImprovedClinic); + extConsumables.AddExtConsumables(); + + await this.Progress(); + + // Party + PartyGeneration(rng, flags, preferences); + PubReplaceClinic(rng, Maps.AttackedTown, flags); + + // Experience + ScaleAllAltExp(flags); + XpAdmissibility((bool)flags.NonesGainXP, flags.DeadsGainXP); + SetProgressiveScaleMode(flags); + var expChests = new ExpChests(itemPlacement.PlacedItems, this, flags, rng); + expChests.BuildExpChests(); + + // Classes Features + ClassesBalances(flags, rng); + ClassData.SetMPMax(flags); + ClassData.SetMpGainOnMaxGain(flags, this); + ClassData.RaiseThiefHitRate(flags); + ClassData.BuffThiefAGI(flags); + ClassData.EarlierHighTierMagicCharges(flags); + ClassData.Randomize(flags, rng, oldItemNames, ItemsText, this); + ClassData.ProcessStartWithRoutines(flags, weaponBlursesValues, this); + ClassData.PinkMage(flags); + ClassData.BlackKnight(flags); + ClassData.WhiteNinja(flags); + ClassData.Knightlvl4(flags, rng); + EnableRandomPromotions(flags, rng); + + await this.Progress(); + + + RollCredits(rng); + + + StatsTrackingHacks(flags, preferences); + if ((bool)flags.IsShipFree || flags.Archipelago) Overworld.SetShipLocation(255); + if (flags.TournamentSafe || preferences.CropScreen) ActivateCropScreen(); + + // Quality of Life Stuff + ShopUpgrade(flags, Dialogues, preferences); + QualityOfLifeHacks(flags, preferences); + UseVariablePaletteForCursorAndStone(preferences.ThirdBattlePalette || flags.ResourcePack != null); + EnableModernBattlefield(preferences.ModernBattlefield); + DynamicWindowColor(preferences.MenuColor); + + // Fun Stuff + ChangeLute(preferences.ChangeLute, Dialogues, new MT19337(funRng.Next())); + TitanSnack(preferences.TitanSnack, NpcData, Dialogues, new MT19337(funRng.Next())); + HurrayDwarfFate(preferences.HurrayDwarfFate, NpcData, Dialogues, new MT19337(funRng.Next())); + PaletteSwap(preferences.PaletteSwap && !flags.EnemizerEnabled, new MT19337(funRng.Next())); + TeamSteak(preferences.TeamSteak && !(bool)flags.RandomizeEnemizer); + FunEnemyNames(flags, preferences, new MT19337(funRng.Next())); + + await this.Progress(); + + // Custom Sprites + if (preferences.SpriteSheet != null) + { + using (var stream = new MemoryStream(Convert.FromBase64String(preferences.SpriteSheet))) + { + await SetCustomPlayerSprites(stream, preferences.ThirdBattlePalette, preferences.MapmanSlot); + } + } + + // Archipelago + if (flags.Archipelago) + { + Archipelago exporter = new Archipelago(this, itemPlacement, sanityChecker, expChests, PlacementContext, Overworld.Locations, seed, flags, unmodifiedFlags, preferences); + Utilities.ArchipelagoCache = exporter.Work(); + } + + // Spoilers + if (flags.Spoilers && sanityChecker != null) new ExtSpoiler(this, sanityChecker, ShopData, ItemsText, itemPlacement.PlacedItems, Overworld, PlacementContext, WeaponPermissions, ArmorPermissions, flags).WriteSpoiler(); + + // Write back everything + ItemsText.Write(this, flags.GameMode == GameModes.DeepDungeon ? new List() : ItemLists.UnusedGoldItems.ToList()); + TalkRoutines.Write(this); + NpcData.Write(TalkRoutines.ScriptPointers); + Dialogues.Write(); + ShopData.StoreData(); + + EnemyScripts.Write(this); + EncounterRates.Write(); + itemPlacement.Write(); + + Maps.Write(); + TileSetsData.Write(); + ZoneFormations.Write(this); + StartingItems.Write(); + RngTables.Write(this,flags); + Teleporters.Write(); + Overworld.Write(); + ArmorPermissions.Write(this); + WeaponPermissions.Write(this); + SpellPermissions.Write(this); + ClassData.Write(this); + MenuText.Write(this); + Music.Write(this, flags, preferences); + NewMusic.Write(this, preferences, flags, new MT19337(funRng.Next())); + + await this.Progress(); + + uint last_rng_value = rng.Next(); + + // Final ROM writes + WriteSeedAndFlags(seed.ToHex(), flags, flagsForRng, unmodifiedFlags, resourcesPackHash.ToHex(), last_rng_value); + if (flags.TournamentSafe) Put(0x3FFE3, Blob.FromHex("66696E616C2066616E74617379")); + + await this.Progress("Randomization Completed"); + } +}