public void Randomize(Blob seed, Flags flags, Preferences preferences) { var rng = new MT19337(BitConverter.ToUInt32(seed, 0)); // Spoilers => different rng immediately if (flags.Spoilers) { rng = new MT19337(rng.Next()); } UpgradeToMMC3(); MakeSpace(); Bank1E(); Bank1B(); EasterEggs(); DynamicWindowColor(preferences.MenuColor); PermanentCaravan(); ShiftEarthOrbDown(); CastableItemTargeting(); TeleportShuffle teleporters = new TeleportShuffle(); var palettes = OverworldMap.GeneratePalettes(Get(OverworldMap.MapPaletteOffset, MapCount * OverworldMap.MapPaletteSize).Chunk(OverworldMap.MapPaletteSize)); var overworldMap = new OverworldMap(this, flags, palettes, teleporters); var maps = ReadMaps(); var shopItemLocation = ItemLocations.CaravanItemShop1; #if DEBUG if (flags.ExperimentalFloorGeneration) { MapRequirements reqs; MapGeneratorStrategy strategy; MapGenerator generator = new MapGenerator(); if (flags.EFGWaterfall) { reqs = new MapRequirements { MapId = MapId.Waterfall, Rom = this, }; strategy = MapGeneratorStrategy.WaterfallClone; CompleteMap waterfall = generator.Generate(rng, strategy, reqs); // Should add more into the reqs so that this can be done inside the generator. teleporters.Waterfall.SetEntrance(waterfall.Entrance); overworldMap.PutOverworldTeleport(OverworldTeleportIndex.Waterfall, teleporters.Waterfall); maps[(int)MapId.Waterfall] = waterfall.Map; } if (flags.EFGEarth1) { reqs = new MapRequirements { MapId = MapId.EarthCaveB1, Rom = this, }; strategy = MapGeneratorStrategy.Square; var earthB1 = generator.Generate(rng, strategy, reqs); // Should add more into the reqs so that this can be done inside the generator. teleporters.EarthCave1.SetEntrance(earthB1.Entrance); overworldMap.PutOverworldTeleport(OverworldTeleportIndex.EarthCave1, teleporters.EarthCave1); maps[(int)MapId.EarthCaveB1] = earthB1.Map; } if (flags.EFGEarth2) { reqs = new MapRequirements { MapId = MapId.EarthCaveB2, Rom = this, }; strategy = MapGeneratorStrategy.Square; var earthB2 = generator.Generate(rng, strategy, reqs); // Should add more into the reqs so that this can be done inside the generator. teleporters.EarthCave2.SetEntrance(earthB2.Entrance); overworldMap.PutStandardTeleport(TeleportIndex.EarthCave2, teleporters.EarthCave2, OverworldTeleportIndex.EarthCave1); maps[(int)MapId.EarthCaveB2] = earthB2.Map; } } #endif if (preferences.ModernBattlefield) { EnableModernBattlefield(); } if (flags.TitansTrove) { EnableTitansTrove(maps); } if (flags.LefeinShops) { EnableLefeinShops(maps); } // This has to be done before we shuffle spell levels. if (flags.SpellBugs) { FixSpellBugs(); } if (flags.RebalanceSpells) { RebalanceSpells(); } if (flags.EnemySpellsTargetingAllies) { FixEnemyAOESpells(); } if (flags.ItemMagic) { ShuffleItemMagic(rng); } if (flags.ShortToFR) { ShortenToFR(maps, flags.PreserveFiendRefights, rng); } if (flags.Treasures && flags.ShardHunt && !flags.ChaosRush) { EnableShardHunt(rng, flags.ExtraShards ? rng.Between(24, 30) : 16, flags.NPCItems); } if (flags.TransformFinalFormation) { TransformFinalFormation((FinalFormation)rng.Between(0, Enum.GetValues(typeof(FinalFormation)).Length - 1)); } var maxRetries = 8; for (var i = 0; i < maxRetries; i++) { try { overworldMap = new OverworldMap(this, flags, palettes, teleporters); if ((flags.Entrances || flags.Floors || flags.Towns) && flags.Treasures && flags.NPCItems) { overworldMap.ShuffleEntrancesAndFloors(rng, flags); } if (flags.ShuffleObjectiveNPCs) { overworldMap.ShuffleObjectiveNPCs(rng); } IncentiveData incentivesData = new IncentiveData(rng, flags, overworldMap, shopItemLocation); if (flags.Shops) { var excludeItemsFromRandomShops = new List <Item>(); if (flags.Treasures) { excludeItemsFromRandomShops = incentivesData.ForcedItemPlacements.Select(x => x.Item).Concat(incentivesData.IncentiveItems).ToList(); } if (!flags.RandomWaresIncludesSpecialGear) { excludeItemsFromRandomShops.AddRange(ItemLists.SpecialGear); } shopItemLocation = ShuffleShops(rng, flags.ImmediatePureAndSoftRequired, flags.RandomWares, excludeItemsFromRandomShops, flags.WorldWealth); incentivesData = new IncentiveData(rng, flags, overworldMap, shopItemLocation); } if (flags.Treasures) { ShuffleTreasures(rng, flags, incentivesData, shopItemLocation, overworldMap, teleporters); } break; } catch (InsaneException e) { Console.WriteLine(e.Message); if (maxRetries > (i + 1)) { continue; } throw new InvalidOperationException(e.Message); } } if (flags.MagicShops) { ShuffleMagicShops(rng); } if (flags.MagicLevels) { FixWarpBug(); // The warp bug only needs to be fixed if the magic levels are being shuffled ShuffleMagicLevels(rng, flags.MagicPermissions); } /* * if (flags.WeaponPermissions) * { * ShuffleWeaponPermissions(rng); * } * * if (flags.ArmorPermissions) * { * ShuffleArmorPermissions(rng); * } */ if (flags.Rng) { ShuffleRng(rng); } if (flags.EnemyScripts) { ShuffleEnemyScripts(rng, flags.AllowUnsafePirates); } if (flags.EnemySkillsSpells) { ShuffleEnemySkillsSpells(rng); } if (flags.EnemyStatusAttacks) { if (flags.RandomStatusAttacks) { RandomEnemyStatusAttacks(rng, flags.AllowUnsafePirates); } else { ShuffleEnemyStatusAttacks(rng, flags.AllowUnsafePirates); } } if (flags.EnemyFormationsUnrunnable) { if (flags.EverythingUnrunnable) { CompletelyUnrunnable(); } else { ShuffleUnrunnable(rng); } } if (flags.UnrunnablesStrikeFirstAndSuprise) { AllowStrikeFirstAndSuprise(); } if (flags.EnemyFormationsSurprise) { ShuffleSurpriseBonus(rng); } // Put this before other encounter / trap tile edits. if (flags.AllowUnsafeMelmond) { EnableMelmondGhetto(); } // After unrunnable shuffle and before formation shuffle. Perfect! if (flags.WarMECHMode != WarMECHMode.Vanilla) { WarMECHNpc(flags.WarMECHMode, rng, maps); } if (flags.WarMECHMode == WarMECHMode.Unleashed) { UnleashWarMECH(); } if (flags.FiendShuffle) { FiendShuffle(rng); } if (flags.FormationShuffleMode != FormationShuffleModeEnum.None) { ShuffleEnemyFormations(rng, flags.FormationShuffleMode); } if (flags.EnemyTrapTiles) { ShuffleTrapTiles(rng, flags.RandomTrapFormations); } if (flags.OrdealsPillars) { ShuffleOrdeals(rng, maps); } if (flags.SkyCastle4FMazeMode == SkyCastle4FMazeMode.Maze) { DoSkyCastle4FMaze(rng, maps); } else if (flags.SkyCastle4FMazeMode == SkyCastle4FMazeMode.Teleporters) { ShuffleSkyCastle4F(rng, maps); } if (flags.ConfusedOldMen) { EnableConfusedOldMen(rng); } if (flags.EarlyOrdeals) { EnableEarlyOrdeals(); } if (flags.ChaosRush) { EnableChaosRush(); } if (flags.EarlySarda && !flags.NPCItems) { EnableEarlySarda(); } if (flags.EarlySage && !flags.NPCItems) { EnableEarlySage(); } if (flags.FreeBridge) { EnableFreeBridge(); } if (flags.FreeAirship) { EnableFreeAirship(); } if (flags.FreeOrbs) { EnableFreeOrbs(); } if (flags.FreeCanal) { EnableFreeCanal(); } if (flags.FreeLute) { EnableFreeLute(); } if (flags.NoPartyShuffle) { DisablePartyShuffle(); } if (flags.SpeedHacks) { EnableSpeedHacks(); } if (flags.IdentifyTreasures) { EnableIdentifyTreasures(); } if (flags.Dash) { EnableDash(); } if (flags.BuyTen) { EnableBuyTen(); } if (flags.WaitWhenUnrunnable) { ChangeUnrunnableRunToWait(); } if (flags.EnableCritNumberDisplay) { EnableCritNumberDisplay(); } if (flags.NPCSwatter) { EnableNPCSwatter(); } if (flags.EasyMode) { EnableEasyMode(); } if (flags.HouseMPRestoration || flags.HousesFillHp) { FixHouse(flags.HouseMPRestoration, flags.HousesFillHp); } if (flags.WeaponStats) { FixWeaponStats(); } if (flags.ChanceToRun) { FixChanceToRun(); } if (flags.EnemyStatusAttackBug) { FixEnemyStatusAttackBug(); } if (flags.BlackBeltAbsorb) { FixBBAbsorbBug(); } if (flags.BlackBeltMDEF) { RemakeStyleMasterMDEF(); } if (flags.ImproveTurnOrderRandomization) { ImproveTurnOrderRandomization(rng); } if (flags.EnemyElementalResistancesBug) { FixEnemyElementalResistances(); } if (preferences.FunEnemyNames) { FunEnemyNames(preferences.TeamSteak); } var itemText = ReadText(ItemTextPointerOffset, ItemTextPointerBase, ItemTextPointerCount); itemText[(int)Item.Ribbon].Trim(); ExpGoldBoost(flags.ExpBonus, flags.ExpMultiplier); ScalePrices(flags, itemText, rng, flags.ClampMinimumPriceScale, shopItemLocation); ScaleEncounterRate(flags.EncounterRate / 30.0, flags.DungeonEncounterRate / 30.0); overworldMap.ApplyMapEdits(); WriteMaps(maps); WriteText(itemText, ItemTextPointerOffset, ItemTextPointerBase, ItemTextOffset, UnusedGoldItems); if (flags.EnemyScaleFactor > 1) { ScaleEnemyStats(flags.EnemyScaleFactor, flags.WrapStatOverflow, flags.IncludeMorale, rng, flags.ClampMinimumStatScale); } if (flags.BossScaleFactor > 1) { ScaleBossStats(flags.BossScaleFactor, flags.WrapStatOverflow, flags.IncludeMorale, rng, flags.ClampMinimumBossStatScale); } PartyComposition(rng, flags); if (flags.RecruitmentMode) { PubReplaceClinic(rng); } if (flags.MapCanalBridge) { EnableCanalBridge(); } if (flags.NoDanMode) { NoDanMode(); } SetProgressiveScaleMode(flags.ProgressiveScaleMode); // We have to do "fun" stuff last because it alters the RNG state. RollCredits(rng); if (preferences.DisableDamageTileFlicker) { DisableDamageTileFlicker(); } if (preferences.ThirdBattlePalette) { UseVariablePaletteForCursorAndStone(); } if (preferences.PaletteSwap) { PaletteSwap(rng); } if (preferences.TeamSteak) { TeamSteak(); } if (preferences.Music != MusicShuffle.None) { ShuffleMusic(preferences.Music, rng); } WriteSeedAndFlags(Version, seed.ToHex(), Flags.EncodeFlagsText(flags)); ExtraTrackingAndInitCode(); }
public void Randomize(Blob seed, Flags flags, Preferences preferences) { MT19337 rng; using (SHA256 hasher = SHA256.Create()) { Blob FlagsBlob = Encoding.UTF8.GetBytes(Flags.EncodeFlagsText(flags)); Blob SeedAndFlags = Blob.Concat(new Blob[] { FlagsBlob, seed }); Blob hash = hasher.ComputeHash(SeedAndFlags); rng = new MT19337(BitConverter.ToUInt32(hash, 0)); } if (flags.TournamentSafe) { AssureSafe(); } UpgradeToMMC3(); MakeSpace(); Bank1E(); Bank1B(); EasterEggs(); DynamicWindowColor(preferences.MenuColor); PermanentCaravan(); ShiftEarthOrbDown(); CastableItemTargeting(); FixEnemyPalettes(); // fixes a bug in the original game's programming that causes third enemy slot's palette to render incorrectly FixWarpBug(); // The warp bug must be fixed for magic level shuffle and spellcrafter SeparateUnrunnables(); var talkroutines = new TalkRoutines(); var npcdata = new NPCdata(this); UpdateDialogs(npcdata); if (flags.TournamentSafe) { Put(0x3FFE3, Blob.FromHex("66696E616C2066616E74617379")); } flags = Flags.ConvertAllTriState(flags, rng); TeleportShuffle teleporters = new TeleportShuffle(); var palettes = OverworldMap.GeneratePalettes(Get(OverworldMap.MapPaletteOffset, MapCount * OverworldMap.MapPaletteSize).Chunk(OverworldMap.MapPaletteSize)); var overworldMap = new OverworldMap(this, flags, palettes, teleporters); var maps = ReadMaps(); var shopItemLocation = ItemLocations.CaravanItemShop1; var oldItemNames = ReadText(ItemTextPointerOffset, ItemTextPointerBase, ItemTextPointerCount); if (flags.EFGWaterfall || flags.EFGEarth1 || flags.EFGEarth2) { MapRequirements reqs; MapGeneratorStrategy strategy; MapGenerator generator = new MapGenerator(); if (flags.EFGWaterfall) { reqs = new MapRequirements { MapId = MapId.Waterfall, Rom = this, }; strategy = MapGeneratorStrategy.WaterfallClone; CompleteMap waterfall = generator.Generate(rng, strategy, reqs); // Should add more into the reqs so that this can be done inside the generator. teleporters.Waterfall.SetEntrance(waterfall.Entrance); overworldMap.PutOverworldTeleport(OverworldTeleportIndex.Waterfall, teleporters.Waterfall); maps[(int)MapId.Waterfall] = waterfall.Map; } if (flags.EFGEarth1) { reqs = new MapRequirements { MapId = MapId.EarthCaveB1, Rom = this, }; strategy = MapGeneratorStrategy.Square; var earthB1 = generator.Generate(rng, strategy, reqs); // Should add more into the reqs so that this can be done inside the generator. teleporters.EarthCave1.SetEntrance(earthB1.Entrance); overworldMap.PutOverworldTeleport(OverworldTeleportIndex.EarthCave1, teleporters.EarthCave1); maps[(int)MapId.EarthCaveB1] = earthB1.Map; } if (flags.EFGEarth2) { reqs = new MapRequirements { MapId = MapId.EarthCaveB2, Rom = this, }; strategy = MapGeneratorStrategy.Square; var earthB2 = generator.Generate(rng, strategy, reqs); // Should add more into the reqs so that this can be done inside the generator. teleporters.EarthCave2.SetEntrance(earthB2.Entrance); overworldMap.PutStandardTeleport(TeleportIndex.EarthCave2, teleporters.EarthCave2, OverworldTeleportIndex.EarthCave1); maps[(int)MapId.EarthCaveB2] = earthB2.Map; } } var flippedMaps = new List <MapId>(); if ((bool)flags.FlipDungeons) { flippedMaps = HorizontalFlipDungeons(rng, maps, teleporters, overworldMap); } if ((bool)flags.RandomizeFormationEnemizer) { DoEnemizer(rng, (bool)flags.RandomizeEnemizer, (bool)flags.RandomizeFormationEnemizer, flags.EnemizerDontMakeNewScripts); } if (preferences.ModernBattlefield) { EnableModernBattlefield(); } if ((bool)flags.TitansTrove) { EnableTitansTrove(maps); } if ((bool)flags.LefeinShops) { EnableLefeinShops(maps); } // This has to be done before we shuffle spell levels. if (flags.SpellBugs) { FixSpellBugs(); } //must be done before spells get shuffled around otherwise we'd be changing a spell that isnt lock if (flags.LockMode != LockHitMode.Vanilla) { ChangeLockMode(flags.LockMode); } if (flags.EnemySpellsTargetingAllies) { FixEnemyAOESpells(); } if (flags.AllSpellLevelsForKnightNinja) { KnightNinjaChargesForAllLevels(); } if (flags.BuffHealingSpells) { BuffHealingSpells(); } UpdateMagicAutohitThreshold(rng, flags.MagicAutohitThreshold); if ((bool)flags.GenerateNewSpellbook) { CraftNewSpellbook(rng, (bool)flags.SpellcrafterMixSpells, flags.LockMode, (bool)flags.MagicLevels, (bool)flags.SpellcrafterRetainPermissions); } if ((bool)flags.MagisizeWeapons) { MagisizeWeapons(rng, (bool)flags.MagisizeWeaponsBalanced); } if ((bool)flags.ItemMagic) { ShuffleItemMagic(rng, (bool)flags.BalancedItemMagicShuffle); } if ((bool)flags.GuaranteedRuseItem) { CraftRuseItem(); } if ((bool)flags.ShortToFR) { ShortenToFR(maps, (bool)flags.PreserveFiendRefights, (bool)flags.PreserveAllFiendRefights, rng); } if (((bool)flags.Treasures) && flags.ShardHunt && !flags.FreeOrbs) { EnableShardHunt(rng, talkroutines, flags.ShardCount); } if ((bool)flags.TransformFinalFormation && !flags.SpookyFlag) { TransformFinalFormation((FinalFormation)rng.Between(0, Enum.GetValues(typeof(FinalFormation)).Length - 1), flags.EvadeCap); } var maxRetries = 8; for (var i = 0; i < maxRetries; i++) { try { overworldMap = new OverworldMap(this, flags, palettes, teleporters); if (((bool)flags.Entrances || (bool)flags.Floors || (bool)flags.Towns) && ((bool)flags.Treasures) && ((bool)flags.NPCItems)) { overworldMap.ShuffleEntrancesAndFloors(rng, flags); // Disable the Princess Warp back to Castle Coneria if ((bool)flags.Entrances || (bool)flags.Floors) { talkroutines.ReplaceChunk(newTalkRoutines.Talk_Princess1, Blob.FromHex("20CC90"), Blob.FromHex("EAEAEA")); } } if ((bool)flags.Treasures && (bool)flags.ShuffleObjectiveNPCs) { overworldMap.ShuffleObjectiveNPCs(rng); } IncentiveData incentivesData = new IncentiveData(rng, flags, overworldMap, shopItemLocation); if (((bool)flags.Shops)) { var excludeItemsFromRandomShops = new List <Item>(); if ((bool)flags.Treasures) { excludeItemsFromRandomShops = incentivesData.ForcedItemPlacements.Select(x => x.Item).Concat(incentivesData.IncentiveItems).ToList(); } if (!((bool)flags.RandomWaresIncludesSpecialGear)) { excludeItemsFromRandomShops.AddRange(ItemLists.SpecialGear); if ((bool)flags.GuaranteedRuseItem) { excludeItemsFromRandomShops.Add(Item.PowerRod); } } if ((bool)flags.NoMasamune) { excludeItemsFromRandomShops.Add(Item.Masamune); } shopItemLocation = ShuffleShops(rng, (bool)flags.ImmediatePureAndSoftRequired, ((bool)flags.RandomWares), excludeItemsFromRandomShops, flags.WorldWealth); incentivesData = new IncentiveData(rng, flags, overworldMap, shopItemLocation); } if ((bool)flags.Treasures) { generatedPlacement = ShuffleTreasures(rng, flags, incentivesData, shopItemLocation, overworldMap, teleporters); } break; } catch (InsaneException e) { Console.WriteLine(e.Message); if (maxRetries > (i + 1)) { continue; } throw new InvalidOperationException(e.Message); } } // Change Astos routine so item isn't lost in wall of text if ((bool)flags.NPCItems || (bool)flags.NPCFetchItems || (bool)flags.ShuffleAstos) { talkroutines.Replace(newTalkRoutines.Talk_Astos, Blob.FromHex("A674F005BD2060F027A5738561202096B020A572203D96A575200096A476207F90207392A5611820109F201896A9F060A57060")); } npcdata.UpdateItemPlacement(generatedPlacement); if ((bool)flags.MagicShopLocs) { ShuffleMagicLocations(rng); } if (((bool)flags.MagicShops)) { ShuffleMagicShops(rng); } if (((bool)flags.MagicLevels)) { ShuffleMagicLevels(rng, ((bool)flags.MagicPermissions), (bool)flags.MagicLevelsTiered, (bool)flags.MagicLevelsMixed, (bool)!flags.GenerateNewSpellbook); } new StartingInventory(rng, flags, this).SetStartingInventory(); /* * if (flags.WeaponPermissions) * { * ShuffleWeaponPermissions(rng); * } * * if (flags.ArmorPermissions) * { * ShuffleArmorPermissions(rng); * } */ if (flags.SaveGameWhenGameOver) { EnableSaveOnDeath(flags); } // Ordered before RNG shuffle. In the event that both flags are on, RNG shuffle depends on this. if (((bool)flags.FixMissingBattleRngEntry)) { FixMissingBattleRngEntry(); } if (((bool)flags.Rng)) { ShuffleRng(rng); } if (((bool)flags.EnemyScripts)) { ShuffleEnemyScripts(rng, (bool)flags.AllowUnsafePirates, (bool)!flags.BossScriptsOnly, ((bool)flags.EnemySkillsSpellsTiered || (bool)flags.ScaryImps), (bool)flags.ScaryImps); } if (((bool)flags.EnemySkillsSpells)) { if ((bool)flags.EnemySkillsSpellsTiered && (bool)!flags.BossSkillsOnly) { GenerateBalancedEnemyScripts(rng, (bool)flags.SwolePirates); ShuffleEnemySkillsSpells(rng, false); } else { ShuffleEnemySkillsSpells(rng, (bool)!flags.BossSkillsOnly); } } if (((bool)flags.EnemyStatusAttacks)) { if (((bool)flags.RandomStatusAttacks)) { RandomEnemyStatusAttacks(rng, (bool)flags.AllowUnsafePirates, (bool)flags.DisableStunTouch); } else { ShuffleEnemyStatusAttacks(rng, (bool)flags.AllowUnsafePirates); } } if (flags.Runnability == Runnability.Random) { flags.Runnability = (Runnability)Rng.Between(rng, 0, 3); } if (flags.Runnability == Runnability.AllRunnable) { CompletelyRunnable(); } else if (flags.Runnability == Runnability.AllUnrunnable) { CompletelyUnrunnable(); } else if (flags.Runnability == Runnability.Shuffle) { ShuffleUnrunnable(rng); } // Always on to supply the correct changes for WaitWhenUnrunnable AllowStrikeFirstAndSurprise(flags.WaitWhenUnrunnable, (bool)flags.UnrunnablesStrikeFirstAndSurprise); if (((bool)flags.EnemyFormationsSurprise)) { ShuffleSurpriseBonus(rng); } // Put this before other encounter / trap tile edits. if ((bool)flags.AllowUnsafeMelmond) { EnableMelmondGhetto(flags.EnemizerEnabled); } // After unrunnable shuffle and before formation shuffle. Perfect! if (flags.WarMECHMode != WarMECHMode.Vanilla) { WarMECHNpc(flags.WarMECHMode, npcdata, rng, maps); } if (flags.WarMECHMode == WarMECHMode.Unleashed) { UnleashWarMECH(); } if ((bool)flags.ClassAsNpcFiends || (bool)flags.ClassAsNpcKeyNPC) { ClassAsNPC(flags, talkroutines, npcdata, flippedMaps, rng); } if ((bool)flags.FiendShuffle) { FiendShuffle(rng); } if (flags.FormationShuffleMode != FormationShuffleMode.None && !flags.EnemizerEnabled) { ShuffleEnemyFormations(rng, flags.FormationShuffleMode); } if ((bool)flags.RemoveTrapTiles) { RemoveTrapTiles(flags.EnemizerEnabled); } if (((bool)flags.EnemyTrapTiles) && !flags.EnemizerEnabled) { ShuffleTrapTiles(rng, ((bool)flags.RandomTrapFormations)); } if ((bool)flags.OrdealsPillars) { ShuffleOrdeals(rng, maps); } if (flags.SkyCastle4FMazeMode == SkyCastle4FMazeMode.Maze) { DoSkyCastle4FMaze(rng, maps); } else if (flags.SkyCastle4FMazeMode == SkyCastle4FMazeMode.Teleporters) { ShuffleSkyCastle4F(rng, maps); } if ((bool)flags.ConfusedOldMen) { EnableConfusedOldMen(rng); } if ((bool)flags.EarlyOrdeals) { EnableEarlyOrdeals(); } if (flags.ChaosRush) { EnableChaosRush(); } if ((bool)flags.EarlyKing) { EnableEarlyKing(npcdata); } if ((bool)flags.EarlySarda) { EnableEarlySarda(npcdata); } if ((bool)flags.EarlySage) { EnableEarlySage(npcdata); } if ((bool)flags.FreeBridge) { EnableFreeBridge(); } if ((bool)flags.FreeAirship) { EnableFreeAirship(); } if ((bool)flags.FreeShip) { EnableFreeShip(); } if (flags.FreeOrbs) { EnableFreeOrbs(); } if ((bool)flags.FreeCanal) { EnableFreeCanal((bool)flags.NPCItems, npcdata); } if ((bool)flags.FreeCanoe) { EnableFreeCanoe(); } if ((bool)flags.FreeLute) { EnableFreeLute(); } if ((bool)flags.FreeTail && !(bool)flags.NoTail) { EnableFreeTail(); } if (flags.NoPartyShuffle) { DisablePartyShuffle(); } if (flags.SpeedHacks) { EnableSpeedHacks(); } if (flags.IdentifyTreasures) { EnableIdentifyTreasures(); } if (flags.Dash) { EnableDash(); } if (flags.BuyTen) { EnableBuyQuantity(); } if (flags.WaitWhenUnrunnable) { ChangeUnrunnableRunToWait(); } if (flags.SpeedHacks && flags.EnableCritNumberDisplay) { EnableCritNumberDisplay(); } if (flags.BattleMagicMenuWrapAround) { BattleMagicMenuWrapAround(); } if (flags.NPCSwatter) { EnableNPCSwatter(npcdata); } if (flags.EasyMode) { EnableEasyMode(); } if ((bool)flags.TrappedChests || (bool)flags.TCMasaGuardian || (bool)flags.TrappedShards) { MonsterInABox(rng, flags); } if (flags.HouseMPRestoration || flags.HousesFillHp) { FixHouse(flags.HouseMPRestoration, flags.HousesFillHp); } if (flags.BBCritRate) { DontDoubleBBCritRates(); } if (flags.WeaponCritRate) { DoubleWeaponCritRates(); } //needs to go after item magic, moved after double weapon crit to have more control over the actual number of crit gained. if ((bool)flags.RandomWeaponBonus) { RandomWeaponBonus(rng, flags.RandomWeaponBonusLow, flags.RandomWeaponBonusHigh, (bool)flags.RandomWeaponBonusExcludeMasa); } if ((bool)flags.RandomArmorBonus) { RandomArmorBonus(rng, flags.RandomArmorBonusLow, flags.RandomArmorBonusHigh); } if (flags.WeaponBonuses) { IncreaseWeaponBonus(flags.WeaponTypeBonusValue); } if (flags.WeaponStats) { FixWeaponStats(); } if (flags.ChanceToRun) { FixChanceToRun(); } if (flags.EnemyStatusAttackBug) { FixEnemyStatusAttackBug(); } if (flags.BlackBeltAbsorb) { FixBBAbsorbBug(); } if (flags.MDefMode != MDEFGrowthMode.None) { MDefChanges(flags.MDefMode); } if (flags.ThiefHitRate) { ThiefHitRate(); } if (flags.ImproveTurnOrderRandomization) { ImproveTurnOrderRandomization(rng); } if (flags.FixHitChanceCap) { FixHitChanceCap(); } if (flags.EnemyElementalResistancesBug) { FixEnemyElementalResistances(); } if (preferences.FunEnemyNames && !flags.EnemizerEnabled) { FunEnemyNames(preferences.TeamSteak); } var itemText = ReadText(ItemTextPointerOffset, ItemTextPointerBase, ItemTextPointerCount); itemText[(int)Item.Ribbon] = itemText[(int)Item.Ribbon].Remove(7); if ((bool)flags.HintsVillage || (bool)flags.HintsDungeon) { if ((bool)flags.HintsDungeon) { SetDungeonNPC(flippedMaps, rng); } NPCHints(rng, npcdata, flags, overworldMap); } ExpGoldBoost(flags.ExpBonus, flags.ExpMultiplier); ScalePrices(flags, itemText, rng, ((bool)flags.ClampMinimumPriceScale), shopItemLocation); ScaleEncounterRate(flags.EncounterRate / 30.0, flags.DungeonEncounterRate / 30.0); overworldMap.ApplyMapEdits(); WriteMaps(maps); WriteText(itemText, ItemTextPointerOffset, ItemTextPointerBase, ItemTextOffset, UnusedGoldItems); if ((bool)flags.SwolePirates) { EnableSwolePirates(); } if (flags.EnemyScaleStatsHigh != 100 || flags.EnemyScaleStatsLow != 100 || ((bool)flags.SeparateEnemyHPScaling && (flags.EnemyScaleHpLow != 100 || flags.EnemyScaleHpHigh != 100))) { ScaleEnemyStats(rng, flags); } if (flags.BossScaleStatsHigh != 100 || flags.BossScaleStatsLow != 100 || ((bool)flags.SeparateBossHPScaling && (flags.BossScaleHpLow != 100 || flags.BossScaleHpHigh != 100))) { ScaleBossStats(rng, flags); } PartyComposition(rng, flags, preferences); if (((bool)flags.RecruitmentMode)) { PubReplaceClinic(rng, flags); } if ((bool)flags.ChangeMaxMP) { SetMPMax(flags.RedMageMaxMP, flags.WhiteMageMaxMP, flags.BlackMageMaxMP, flags.KnightMaxMP, flags.NinjaMaxMP); } if ((bool)flags.ShuffleAstos) { ShuffleAstos(flags, npcdata, talkroutines, rng); } if ((bool)flags.EnablePoolParty) { EnablePoolParty(flags, rng); } if ((bool)flags.MapCanalBridge) { EnableCanalBridge(); } if (flags.NoDanMode) { NoDanMode(); } SetProgressiveScaleMode(flags); if ((bool)flags.RandomizeClass) { RandomizeClass(rng, flags, oldItemNames); } if ((bool)flags.EnableRandomPromotions) { EnableRandomPromotions(flags, rng); } if (flags.DisableTentSaving) { CannotSaveOnOverworld(); } if (flags.DisableInnSaving) { CannotSaveAtInns(); } if (flags.PacifistMode && !flags.SpookyFlag) { PacifistEnd(talkroutines, npcdata, (bool)flags.EnemyTrapTiles || flags.EnemizerEnabled); } if (flags.ShopInfo) { ShopUpgrade(); } if (flags.SpookyFlag) { Spooky(talkroutines, npcdata, rng, flags); } if (flags.InventoryAutosort && !(preferences.RenounceAutosort)) { EnableInventoryAutosort(); } // We have to do "fun" stuff last because it alters the RNG state. // Back up Rng so that fun flags are uniform when different ones are selected uint funRngSeed = rng.Next(); RollCredits(rng); if (preferences.DisableDamageTileFlicker) { DisableDamageTileFlicker(); } if (preferences.ThirdBattlePalette) { UseVariablePaletteForCursorAndStone(); } if (preferences.PaletteSwap && !flags.EnemizerEnabled) { rng = new MT19337(funRngSeed); PaletteSwap(rng); } if (preferences.TeamSteak && !(bool)flags.RandomizeEnemizer) { TeamSteak(); } if (preferences.ChangeLute) { rng = new MT19337(funRngSeed); ChangeLute(rng); } rng = new MT19337(funRngSeed); HurrayDwarfFate(preferences.HurrayDwarfFate, npcdata, rng); if (preferences.Music != MusicShuffle.None) { rng = new MT19337(funRngSeed); ShuffleMusic(preferences.Music, rng); } if (preferences.DisableSpellCastFlash) { DisableSpellCastScreenFlash(); } npcdata.WriteNPCdata(this); talkroutines.WriteRoutines(this); talkroutines.UpdateNPCRoutines(this, npcdata); WriteSeedAndFlags(seed.ToHex(), Flags.EncodeFlagsText(flags)); ExtraTrackingAndInitCode(flags); }
private void ExtraTrackingAndInitCode(Flags flags) { // Expanded game init code, does several things: // - Encounter table emu/hardware fix // - track hard/soft resets // - initialize tracking variables if no game is saved PutInBank(0x0F, 0x8000, Blob.FromHex("A9008D00208D012085FEA90885FF85FDA51BC901D00160A901851BA94DC5F9F008A9FF85F585F685F7182088C8B049A94DC5F918F013ADA36469018DA364ADA46469008DA464189010ADA56469018DA564ADA66469008DA664A9008DFD64A200187D00647D00657D00667D0067E8D0F149FF8DFD64189010A2A0A9009D00609D0064E8D0F7EEFB64ADFB648DFB6060")); Put(0x7C012, Blob.FromHex("A90F2003FE200080EAEAEAEAEAEAEAEA")); // Move controller handling out of bank 1F // This bit of code is also altered to allow a hard reset using Up+A on controller 2 PutInBank(0x0F, 0x8200, Blob.FromHex("20108220008360")); PutInBank(0x0F, 0x8210, Blob.FromHex("A9018D1640A9008D1640A208AD16402903C9012620AD17402903C901261ECAD0EBA51EC988F008C948F001604C2EFE20A8FE20A8FE20A8FEA2FF9AA900851E9500CAD0FBA6004C12C0")); PutInBank(0x0F, 0x8300, Blob.FromHex("A5202903F002A2038611A520290CF0058A090C8511A52045212511452185214520AA2910F00EA5202910F002E623A521491085218A2920F00EA5202920F002E622A521492085218A2940F00EA5202940F002E625A521494085218A2980F00EA5202980F002E624A5214980852160")); PutInBank(0x1F, 0xD7C2, CreateLongJumpTableEntry(0x0F, 0x8200)); // Battles use 2 separate and independent controller handlers for a total of 3 (because why not), so we patch these to respond to Up+A also PutInBank(0x0F, 0x8580, Blob.FromHex("A0018C1640888C1640A008AD16404AB0014A6EB368AD17402903C901261E88D0EAA51EC988F00BC948F004ADB368604C2EFE20A8FE20A8FE20A8FEA2FF9AA900851E9500CAD0FBA6004C12C0")); PutInBank(0x1F, 0xD828, CreateLongJumpTableEntry(0x0F, 0x8580)); // PutInBank(0x0B, 0x9A06, Blob.FromHex("4C28D8")); Included in bank 1B changes PutInBank(0x0C, 0x97C7, Blob.FromHex("2027F22028D82029ABADB36860")); // Put LongJump routine 6 bytes after UpdateJoy used to be PutInBank(0x1F, 0xD7C8, Blob.FromHex("85E99885EA6885EB6885ECA001B1EB85EDC8B1EB85EEC8ADFC6085E8B1EB2003FEA9D748A9F548A5E9A4EA6CED0085E9A5E82003FEA5E960")); // LongJump entries can start at 0xD800 and must stop before 0xD850 (at which point additional space will need to be freed to make room) // Patches for various tracking variables follow: // Pedometer + chests opened PutInBank(0x0F, 0x8100, Blob.FromHex("18A532D027A52D2901F006A550D01DF00398D018ADA06069018DA060ADA16069008DA160ADA26069008DA260A52F8530A9FF8518A200A000BD00622904F001C8E8D0F5988DB7606060")); Put(0x7D023, Blob.FromHex("A90F2003FE200081")); // Count number of battles PutInBank(0x0F, 0x8400, Blob.FromHex("18ADA76069018DA7609003EEA86020A8FE60")); PutInBank(0x1F, 0xD800, CreateLongJumpTableEntry(0x0F, 0x8400)); PutInBank(0x1F, 0xF28D, Blob.FromHex("2000D8")); // Ambushes / Strike First PutInBank(0x0F, 0x8420, Blob.FromHex("AD5668C90B9015C95A901F18ADAB6069018DAB609014EEAC6018900E18ADA96069018DA9609003EEAA60AC5668AE576860")); PutInBank(0x1F, 0xD806, CreateLongJumpTableEntry(0x0F, 0x8420)); Put(0x313FB, Blob.FromHex("eaeaea2006D8")); // Runs PutInBank(0x0F, 0x8480, Blob.FromHex("AD5868F00E18ADAD6069018DAD609003EEAE60AD586860")); PutInBank(0x1F, 0xD81C, CreateLongJumpTableEntry(0x0F, 0x8480)); Put(0x32418, Blob.FromHex("201CD8")); // Physical Damage PutInBank(0x0F, 0x84B0, Blob.FromHex("8E7D68AD8768F01DADB2606D82688DB260ADB3606D83688DB360ADB46069008DB46018901AADAF606D82688DAF60ADB0606D83688DB060ADB16069008DB160AE7D6860")); PutInBank(0x1F, 0xD822, CreateLongJumpTableEntry(0x0F, 0x84B0)); Put(0x32968, Blob.FromHex("2022D8")); // Magic Damage PutInBank(0x0F, 0x8500, Blob.FromHex("AD8A6C2980F01CADB2606D58688DB260ADB3606D59688DB360ADB46069008DB460901AADAF606D58688DAF60ADB0606D59688DB060ADB16069008DB160A912A212A00160")); PutInBank(0x1F, 0xD83A, CreateLongJumpTableEntry(0x0F, 0x8500)); PutInBank(0x0C, 0xB8ED, Blob.FromHex("203AD8eaeaea")); // Party Wipes PutInBank(0x0F, 0x85D0, Blob.FromHex("EEB564A9008DFD64A200187D00647D00657D00667D0067E8D0F149FF8DFD64A952854B60")); PutInBank(0x1F, 0xD82E, CreateLongJumpTableEntry(0x0F, 0x85D0)); //PutInBank(0x0B, 0x9AF5, Blob.FromHex("202ED8EAEA")); included in 1B changes // "Nothing Here"s PutInBank(0x0F, 0x8600, Blob.FromHex("A54429C2D005A545F00360A900EEB66060")); PutInBank(0x1F, 0xD834, CreateLongJumpTableEntry(0x0F, 0x8600)); PutInBank(0x1F, 0xCBF3, Blob.FromHex("4C34D8")); // Add select button handler on game start menu to change color PutInBank(0x0F, 0x8620, Blob.FromHex("203CC4A662A9488540ADFB60D003EEFB60A522F022EEFB60ADFB60C90D300EF007A9018DFB60D005A90F8DFB60A90085222029EBA90060A90160")); PutInBank(0x1F, 0xD840, CreateLongJumpTableEntry(0x0F, 0x8620)); Put(0x3A1B5, Blob.FromHex("2040D8D0034C56A1EA")); // Move Most of LoadBorderPalette_Blue out of the way to do a dynamic version. PutInBank(0x0F, 0x8700, Blob.FromHex("988DCE038DEE03A90F8DCC03A9008DCD03A9308DCF0360")); // Move DrawCommandMenu out of Bank F so we can add no Escape to it PutInBank(0x0F, 0x8740, Blob.FromHex("A000A200B91BFA9D9E6AE8C01BD015AD916D2903F00EA9139D9E6AE8C8A9F79D9E6AE8C8E005D0052090F6A200C8C01ED0D260")); // Create a clone of IsOnBridge that checks the canal too. PutInBank(0x0F, 0x8780, Blob.FromHex("AD0860F014A512CD0960D00DA513CD0A60D006A90085451860A512CD0D60D00DA513CD0E60D006A900854518603860")); // BB Absorb fix. //PutInBank(0x0F, 0x8800, Blob.FromHex("A000B186C902F005C908F00160A018B186301BC8B1863016C8B1863011C8B186300CA026B1861869010AA0209186A01CB186301AC8B1863015C8B1863010C8B186300BA026B186186901A022918660")); // Copyright overhaul, see 0F_8960_DrawSeedAndFlags.asm PutInBank(0x0F, 0x8980, Blob.FromHex("A9238D0620A9208D0620A200BD00898D0720E8E060D0F560")); // Fast Battle Boxes PutInBank(0x0F, 0x8A00, Blob.FromHex("A940858AA922858BA91E8588A969858960")); PutInBank(0x0F, 0x8A20, Blob.FromHex($"A9{BattleBoxDrawInRows}8DB96820A1F420E8F4A5881869208588A58969008589A58A186920858AA58B6900858BCEB968D0DE60")); // Fast Battle Boxes Undraw (Similar... yet different!) PutInBank(0x0F, 0x8A80, Blob.FromHex("A9A0858AA923858BA97E8588A96A858960")); PutInBank(0x0F, 0x8AA0, Blob.FromHex($"A9{BattleBoxUndrawRows}8DB96820A1F420E8F4A58838E9208588A589E9008589A58A38E920858AA58BE900858BCEB968D0DE60")); // Softlock fix Put(0x7C956, Blob.FromHex("A90F2003FE4C008B")); PutInBank(0x0F, 0x8B00, Blob.FromHex("BAE030B01E8A8D1001A9F4AAA9FBA8BD0001990001CA88E010D0F4AD1001186907AA9AA52948A52A48A50D48A54848A549484C65C9")); // Change INT to MDEF in the Status screen Put(0x388F5, Blob.FromHex("968D8E8F")); Data[0x38DED] = 0x25; //Key Items + Progressive Scaling if (flags.ProgressiveScaleMode == ProgressiveScaleMode.OrbProgressiveSlow || flags.ProgressiveScaleMode == ProgressiveScaleMode.OrbProgressiveMedium || flags.ProgressiveScaleMode == ProgressiveScaleMode.OrbProgressiveFast || flags.ProgressiveScaleMode == ProgressiveScaleMode.OrbProgressiveVFast) { if (flags.ShardHunt) { PutInBank(0x0F, 0x9000, Blob.FromHex("AD35608DB86060")); } else { PutInBank(0x0F, 0x9000, Blob.FromHex("A200AD3160F001E8AD3260F001E8AD3360F001E8AD3460F001E88EB86060")); } } else { PutInBank(0x0F, 0x9000, Blob.FromHex("A200AD2160F001E8AD2260F001E8AD2560F001E8AD2A60F001E8AD2B60F001E8AD2C60F001E8AD2E60F001E8AD3060F001E8AD0060F001E8AD1260F001E8AD0460F001E8AD0860F001E8AD0C60D001E8AD2360D007AD0A622902F001E8AD2460D007AD05622902F001E8AD2660D007AD08622902F001E8AD2760D007AD09622902F001E8AD2860D007AD0B622902F001E8AD2960D007AD14622901D001E8AD2D60D007AD0E622902F001E8AD2F60D007AD13622903F001E88EB86060")); } PutInBank(0x1F, 0xCFCB, CreateLongJumpTableEntry(0x0F, 0x9100)); //Division routine PutInBank(0x0F, 0x90C0, Blob.FromHex("8A48A9008513A210261026112613A513C5129004E512851326102611CAD0EDA513851268AA60")); // Progressive scaling also writes to 0x9100 approaching 200 bytes, begin next Put at 0x9200. // Replace Overworld to Floor and Floor to Floor teleport code to JSR out to 0x9200 to set X / Y AND inroom from unused high bit of X. PutInBank(0x1F, 0xC1E2, Blob.FromHex("A9002003FEA545293FAABD00AC8510BD20AC8511BD40AC8548AABDC0AC8549A90F2003FE200092EAEAEAEAEAEA")); PutInBank(0x1F, 0xC968, Blob.FromHex("A9002003FEA645BD00AD8510BD40AD8511BD80AD8548AABDC0AC8549A90F2003FE200092EAEA")); PutInBank(0x0F, 0x9200, Blob.FromHex("A200A5100A9002A2814A38E907293F8529A5110A9002860D4A38E907293F852A60")); // Critical hit display for number of hits PutInBank(0x0F, 0x9280, FF1Text.TextToBytes("Critical hit!!", false)); PutInBank(0x0F, 0x9290, FF1Text.TextToBytes(" Critical hits!", false)); PutInBank(0x0F, 0x92A0, Blob.FromHex("AD6B68C901F01EA2019D3A6BA9118D3A6BA900E89D3A6BA0FFC8E8B990929D3A6BD0F6F00EA2FFA0FFC8E8B980929D3A6BD0F6A23AA06BA904201CF7EEF86A60")); // Enable 3 palettes in battle PutInBank(0x1F, 0xFDF1, CreateLongJumpTableEntry(0x0F, 0x9380)); PutInBank(0x0F, 0x9380, Blob.FromHex("ADD16A2910F00BA020B9336D99866B88D0F7ADD16A290F8DD16A20A1F4AD0220A9028D1440A93F8D0620A9008D0620A000B9876B8D0720C8C020D0F5A93F8D0620A9008D06208D06208D062060")); }
public void Randomize(Blob seed, Flags flags) { var rng = new MT19337(BitConverter.ToUInt32(seed, 0)); UpgradeToMMC3(); MakeSpaceIn1F(); EasterEggs(); DynamicWindowColor(); PermanentCaravan(); ShiftEarthOrbDown(); var overworldMap = new OverworldMap(this, flags); var maps = ReadMaps(); var incentivesData = new IncentiveData(rng, flags, overworldMap.MapLocationRequirements); var shopItemLocation = ItemLocations.CaravanItemShop1; if (flags.ModernBattlefield) { EnableModernBattlefield(); } if (flags.TitansTrove) { EnableTitansTrove(maps); } // This has to be done before we shuffle spell levels. if (flags.SpellBugs) { FixSpellBugs(); } if (flags.EnemySpellsTargetingAllies) { FixEnemyAOESpells(); } if (flags.ItemMagic) { ShuffleItemMagic(rng); } if (flags.Shops) { var excludeItemsFromRandomShops = flags.Treasures ? incentivesData.ForcedItemPlacements.Select(x => x.Item).Concat(incentivesData.IncentiveItems).ToList() : new List <Item>(); shopItemLocation = ShuffleShops(rng, flags.EnemyStatusAttacks, flags.RandomWares, excludeItemsFromRandomShops); } if (flags.Treasures || flags.NPCItems || flags.NPCFetchItems) { ShuffleTreasures(rng, flags, incentivesData, shopItemLocation, overworldMap.MapLocationRequirements); } if (flags.Treasures && flags.ShardHunt && !flags.ChaosRush) { EnableShardHunt(rng, flags.ExtraShards ? rng.Between(24, 30) : 16, maps, flags.NPCItems); } if (flags.TransformFinalFormation) { TransformFinalFormation((FinalFormation)rng.Between(0, Enum.GetValues(typeof(FinalFormation)).Length - 1)); } if (flags.MagicShops) { ShuffleMagicShops(rng); } if (flags.MagicLevels) { FixWarpBug(); // The warp bug only needs to be fixed if the magic levels are being shuffled ShuffleMagicLevels(rng, flags.MagicPermissions); } if (flags.Rng) { ShuffleRng(rng); } if (flags.EnemyScripts) { ShuffleEnemyScripts(rng, flags.AllowUnsafePirates); } if (flags.EnemySkillsSpells) { ShuffleEnemySkillsSpells(rng); } if (flags.EnemyStatusAttacks) { ShuffleEnemyStatusAttacks(rng, flags.AllowUnsafePirates); } if (flags.EnemyFormationsUnrunnable) { ShuffleUnrunnable(rng); } if (flags.EnemyFormationsSurprise) { ShuffleSurpriseBonus(rng); } if (flags.EnemyFormationsFrequency) { ShuffleEnemyFormations(rng); } if (flags.OrdealsPillars) { ShuffleOrdeals(rng, maps); } if (flags.SkyCastle4FTeleporters) { ShuffleSkyCastle4F(rng, maps); } if (flags.CrownlessOrdeals) { EnableEarlyOrdeals(); } if (flags.ChaosRush) { EnableChaosRush(); } if (flags.EarlySarda && !flags.NPCItems) { EnableEarlySarda(); } if (flags.EarlySage && !flags.NPCItems) { EnableEarlySage(); } if (flags.FreeBridge) { EnableFreeBridge(); } if (flags.FreeAirship) { EnableFreeAirship(); } if (flags.FreeOrbs) { EnableFreeOrbs(); } if (flags.NoPartyShuffle) { DisablePartyShuffle(); } if (flags.SpeedHacks) { EnableSpeedHacks(); } if (flags.IdentifyTreasures) { EnableIdentifyTreasures(); } if (flags.Dash) { EnableDash(); } if (flags.BuyTen) { EnableBuyTen(); } if (flags.WaitWhenUnrunnable) { ChangeUnrunnableRunToWait(); } if (flags.EasyMode) { EnableEasyMode(); } if (flags.HouseMPRestoration) { FixHouse(); } if (flags.WeaponStats) { FixWeaponStats(); } if (flags.ChanceToRun) { FixChanceToRun(); } if (flags.EnemyStatusAttackBug) { FixEnemyStatusAttackBug(); } if (flags.BlackBeltAbsorb) { FixBBAbsorbBug(); } if (flags.ImproveTurnOrderRandomization) { ImproveTurnOrderRandomization(rng); } if (flags.EnemyElementalResistancesBug) { FixEnemyElementalResistances(); } if (flags.FunEnemyNames) { FunEnemyNames(flags.TeamSteak); } var itemText = ReadText(ItemTextPointerOffset, ItemTextPointerBase, ItemTextPointerCount); FixVanillaRibbon(itemText); ExpGoldBoost(flags.ExpBonus, flags.ExpMultiplier); ScalePrices(flags.PriceScaleFactor, flags.ExpMultiplier, flags.VanillaStartingGold, itemText, rng); overworldMap.ApplyMapEdits(); WriteMaps(maps); WriteText(itemText, ItemTextPointerOffset, ItemTextPointerBase, ItemTextOffset, UnusedGoldItems); if (flags.EnemyScaleFactor > 1) { ScaleEnemyStats(flags.EnemyScaleFactor, rng); } if (flags.ForcedPartyMembers > 0) { PartyRandomize(rng, flags.ForcedPartyMembers); } if (flags.MapCanalBridge) { EnableCanalBridge(); } // We have to do "fun" stuff last because it alters the RNG state. RollCredits(rng); if (flags.PaletteSwap) { PaletteSwap(rng); } if (flags.TeamSteak) { TeamSteak(); } if (flags.Music != MusicShuffle.None) { ShuffleMusic(flags.Music, rng); } WriteSeedAndFlags(Version, seed.ToHex(), Flags.EncodeFlagsText(flags)); ExtraTrackingAndInitCode(); }
public static List <Item> GetIncentivePool(Flags flags) { var incentivePool = new List <Item>(); if (flags.IncentivizeMasamune ?? false) { incentivePool.Add(Item.Masamune); } if (flags.IncentivizeKatana ?? false) { incentivePool.Add(Item.Katana); } if (flags.IncentivizeVorpal ?? false) { incentivePool.Add(Item.Vorpal); } if (flags.IncentivizeDefCastWeapon ?? false) { incentivePool.Add(Item.Defense); } if (flags.IncentivizeOffCastWeapon ?? false) { incentivePool.Add(Item.ThorHammer); } if (flags.IncentivizeOpal ?? false) { incentivePool.Add(Item.Opal); } if (flags.IncentivizeOtherCastArmor ?? false) { incentivePool.Add(Item.PowerGauntlets); } if (flags.IncentivizeDefCastArmor ?? false) { incentivePool.Add(Item.WhiteShirt); } if (flags.IncentivizeOffCastArmor ?? false) { incentivePool.Add(Item.BlackShirt); } if (flags.IncentivizeRibbon ?? false) { incentivePool.Add(Item.Ribbon); } if (flags.IncentivizeSlab ?? false) { incentivePool.Add(Item.Slab); } if (flags.IncentivizeRuby ?? false) { incentivePool.Add(Item.Ruby); } if (flags.IncentivizeFloater ?? false) { incentivePool.Add(Item.Floater); } if (flags.IncentivizeTnt ?? false) { incentivePool.Add(Item.Tnt); } if (flags.IncentivizeCrown ?? false) { incentivePool.Add(Item.Crown); } if (flags.IncentivizeTail ?? false) { incentivePool.Add(Item.Tail); } if (flags.IncentivizeAdamant ?? false) { incentivePool.Add(Item.Adamant); } if (flags.IncentivizeBridge) { incentivePool.Add(Item.Bridge); } if (flags.IncentivizeLute ?? false) { incentivePool.Add(Item.Lute); } if (flags.IncentivizeShip ?? false) { incentivePool.Add(Item.Ship); } if (flags.IncentivizeRod ?? false) { incentivePool.Add(Item.Rod); } if (flags.IncentivizeCanoe ?? false) { incentivePool.Add(Item.Canoe); } if (flags.IncentivizeCube ?? false) { incentivePool.Add(Item.Cube); } if (flags.IncentivizeBottle ?? false) { incentivePool.Add(Item.Bottle); } if (flags.IncentivizeKey ?? false) { incentivePool.Add(Item.Key); } if (flags.IncentivizeCrystal ?? false) { incentivePool.Add(Item.Crystal); } if (flags.IncentivizeOxyale ?? false) { incentivePool.Add(Item.Oxyale); } if (flags.IncentivizeCanal ?? false) { incentivePool.Add(Item.Canal); } if (flags.IncentivizeHerb ?? false) { incentivePool.Add(Item.Herb); } if (flags.IncentivizeChime ?? false) { incentivePool.Add(Item.Chime); } if (flags.IncentivizeXcalber ?? false) { incentivePool.Add(Item.Xcalber); } return(incentivePool.Concat(ItemLists.AllQuestItems).Distinct().ToList()); }
public void Randomize(Blob seed, Flags flags) { var rng = new MT19337(BitConverter.ToUInt32(seed, 0)); UpgradeToMMC3(); MakeSpaceIn1F(); EasterEggs(); DynamicWindowColor(); PermanentCaravan(); ShiftEarthOrbDown(); var palettes = OverworldMap.GeneratePalettes(Get(OverworldMap.MapPaletteOffset, MapCount * OverworldMap.MapPaletteSize).Chunk(OverworldMap.MapPaletteSize)); var overworldMap = new OverworldMap(this, flags, palettes); var maps = ReadMaps(); var shopItemLocation = ItemLocations.CaravanItemShop1; if (flags.ModernBattlefield) { EnableModernBattlefield(); } if (flags.TitansTrove) { EnableTitansTrove(maps); } // This has to be done before we shuffle spell levels. if (flags.SpellBugs) { FixSpellBugs(); } if (flags.EnemySpellsTargetingAllies) { FixEnemyAOESpells(); } if (flags.ItemMagic) { ShuffleItemMagic(rng); } if (flags.ShortToFR) { ShortenToFR(maps, flags.PreserveFiendRefights, rng); } if (flags.Treasures && flags.ShardHunt && !flags.ChaosRush) { EnableShardHunt(rng, flags.ExtraShards ? rng.Between(24, 30) : 16, flags.NPCItems); } if (flags.TransformFinalFormation) { TransformFinalFormation((FinalFormation)rng.Between(0, Enum.GetValues(typeof(FinalFormation)).Length - 1)); } var maxRetries = 500; for (var i = 0; i < maxRetries; i++) { try { overworldMap = new OverworldMap(this, flags, palettes); if ((flags.Entrances || flags.Floors || flags.Towns) && flags.Treasures && flags.NPCItems) { overworldMap.ShuffleEntrancesAndFloors(rng, flags); } var incentivesData = new IncentiveData(rng, flags, overworldMap); if (flags.Shops) { var excludeItemsFromRandomShops = flags.Treasures ? incentivesData.ForcedItemPlacements.Select(x => x.Item).Concat(incentivesData.IncentiveItems).ToList() : new List <Item>(); shopItemLocation = ShuffleShops(rng, flags.EnemyStatusAttacks, flags.RandomWares, excludeItemsFromRandomShops); } if (flags.Treasures) { ShuffleTreasures(rng, flags, incentivesData, shopItemLocation, overworldMap); } break; } catch (InsaneException) { Console.WriteLine("Insane seed. Retrying"); if (maxRetries > (i + 1)) { continue; } throw new InvalidOperationException("Failed Sanity Check too many times"); } } if (flags.MagicShops) { ShuffleMagicShops(rng); } if (flags.MagicLevels) { FixWarpBug(); // The warp bug only needs to be fixed if the magic levels are being shuffled ShuffleMagicLevels(rng, flags.MagicPermissions); } if (flags.Rng) { ShuffleRng(rng); } if (flags.EnemyScripts) { ShuffleEnemyScripts(rng, flags.AllowUnsafePirates); } if (flags.EnemySkillsSpells) { ShuffleEnemySkillsSpells(rng); } if (flags.EnemyStatusAttacks) { ShuffleEnemyStatusAttacks(rng, flags.AllowUnsafePirates); } if (flags.EnemyFormationsUnrunnable) { ShuffleUnrunnable(rng); } if (flags.EnemyFormationsSurprise) { ShuffleSurpriseBonus(rng); } if (flags.EnemyFormationsFrequency) { ShuffleEnemyFormations(rng); } if (flags.EnemyTrapTiles) { ShuffleTrapTiles(rng, flags.RandomTrapFormations); } if (flags.OrdealsPillars) { ShuffleOrdeals(rng, maps); } if (flags.SkyCastle4FTeleporters) { ShuffleSkyCastle4F(rng, maps); } if (flags.ConfusedOldMen) { EnableConfusedOldMen(rng); } if (flags.CrownlessOrdeals) { EnableEarlyOrdeals(); } if (flags.ChaosRush) { EnableChaosRush(); } if (flags.EarlySarda && !flags.NPCItems) { EnableEarlySarda(); } if (flags.EarlySage && !flags.NPCItems) { EnableEarlySage(); } if (flags.FreeBridge) { EnableFreeBridge(); } if (flags.FreeAirship) { EnableFreeAirship(); } if (flags.FreeOrbs) { EnableFreeOrbs(); } if (flags.NoPartyShuffle) { DisablePartyShuffle(); } if (flags.SpeedHacks) { EnableSpeedHacks(); } if (flags.IdentifyTreasures) { EnableIdentifyTreasures(); } if (flags.Dash) { EnableDash(); } if (flags.BuyTen) { EnableBuyTen(); } if (flags.WaitWhenUnrunnable) { ChangeUnrunnableRunToWait(); } if (flags.EnableCritNumberDisplay) { EnableCritNumberDisplay(); } if (flags.EasyMode) { EnableEasyMode(); } if (flags.HouseMPRestoration) { FixHouse(); } if (flags.WeaponStats) { FixWeaponStats(); } if (flags.ChanceToRun) { FixChanceToRun(); } if (flags.EnemyStatusAttackBug) { FixEnemyStatusAttackBug(); } if (flags.BlackBeltAbsorb) { FixBBAbsorbBug(); } if (flags.ImproveTurnOrderRandomization) { ImproveTurnOrderRandomization(rng); } if (flags.EnemyElementalResistancesBug) { FixEnemyElementalResistances(); } if (flags.FunEnemyNames) { FunEnemyNames(flags.TeamSteak); } var itemText = ReadText(ItemTextPointerOffset, ItemTextPointerBase, ItemTextPointerCount); // var dialogueText = ReadText(DialogueTextPointerOffset, DialogueTextPointerBase, DialogueTextPointerCount); FixVanillaRibbon(itemText); ExpGoldBoost(flags.ExpBonus, flags.ExpMultiplier); ScalePrices(flags, itemText, rng, shopItemLocation); ScaleEncounterRate(flags.EncounterRate / 30.0, flags.DungeonEncounterRate / 30.0); if (flags.WarMECHMode != WarMECHMode.Vanilla) { WarMECHNpc(flags.WarMECHMode, rng, maps); } overworldMap.ApplyMapEdits(); WriteMaps(maps); WriteText(itemText, ItemTextPointerOffset, ItemTextPointerBase, ItemTextOffset, UnusedGoldItems); // WriteText(dialogueText, DialogueTextPointerOffset, DialogueTextPointerBase, DialogueTextOffset); if (flags.EnemyScaleFactor > 1) { ScaleEnemyStats(flags.EnemyScaleFactor, flags.WrapStatOverflow, flags.IncludeMorale, rng); } if (flags.BossScaleFactor > 1) { ScaleBossStats(flags.BossScaleFactor, flags.WrapStatOverflow, flags.IncludeMorale, rng); } if (flags.ForcedPartyMembers > 0) { PartyRandomize(rng, flags.ForcedPartyMembers); } if (flags.MapCanalBridge) { EnableCanalBridge(); } SetProgressiveScaleMode(flags.ProgressiveScaleMode); // We have to do "fun" stuff last because it alters the RNG state. RollCredits(rng); if (flags.PaletteSwap) { PaletteSwap(rng); } if (flags.TeamSteak) { TeamSteak(); } if (flags.Music != MusicShuffle.None) { ShuffleMusic(flags.Music, rng); } WriteSeedAndFlags(Version, seed.ToHex(), Flags.EncodeFlagsText(flags)); ExtraTrackingAndInitCode(); }
public IncNameHintSource(MT19337 _rng, NPCdata _npcData, Flags _flags, OverworldMap _overworldMap, FF1Rom _rom) : base(_rng, _npcData, _flags, _overworldMap, _rom) { }
public void PartyComposition(MT19337 rng, Flags flags) { var options = new List <FF1Class>(); // Do each slot - so ugly! if (flags.FIGHTER1) { options.Add(FF1Class.Fighter); } if (flags.THIEF1) { options.Add(FF1Class.Thief); } if (flags.BLACK_BELT1) { options.Add(FF1Class.BlackBelt); } if (flags.RED_MAGE1) { options.Add(FF1Class.RedMage); } if (flags.WHITE_MAGE1) { options.Add(FF1Class.WhiteMage); } if (flags.BLACK_MAGE1) { options.Add(FF1Class.BlackMage); } updateCharacterFromOptions(1, flags.FORCED1, options, rng); if (flags.FIGHTER2) { options.Add(FF1Class.Fighter); } if (flags.THIEF2) { options.Add(FF1Class.Thief); } if (flags.BLACK_BELT2) { options.Add(FF1Class.BlackBelt); } if (flags.RED_MAGE2) { options.Add(FF1Class.RedMage); } if (flags.WHITE_MAGE2) { options.Add(FF1Class.WhiteMage); } if (flags.BLACK_MAGE2) { options.Add(FF1Class.BlackMage); } if (flags.NONE_CLASS2) { options.Add(FF1Class.None); } updateCharacterFromOptions(2, flags.FORCED2, options, rng); if (flags.FIGHTER3) { options.Add(FF1Class.Fighter); } if (flags.THIEF3) { options.Add(FF1Class.Thief); } if (flags.BLACK_BELT3) { options.Add(FF1Class.BlackBelt); } if (flags.RED_MAGE3) { options.Add(FF1Class.RedMage); } if (flags.WHITE_MAGE3) { options.Add(FF1Class.WhiteMage); } if (flags.BLACK_MAGE3) { options.Add(FF1Class.BlackMage); } if (flags.NONE_CLASS3) { options.Add(FF1Class.None); } updateCharacterFromOptions(3, flags.FORCED3, options, rng); if (flags.FIGHTER4) { options.Add(FF1Class.Fighter); } if (flags.THIEF4) { options.Add(FF1Class.Thief); } if (flags.BLACK_BELT4) { options.Add(FF1Class.BlackBelt); } if (flags.RED_MAGE4) { options.Add(FF1Class.RedMage); } if (flags.WHITE_MAGE4) { options.Add(FF1Class.WhiteMage); } if (flags.BLACK_MAGE4) { options.Add(FF1Class.BlackMage); } if (flags.NONE_CLASS4) { options.Add(FF1Class.None); } updateCharacterFromOptions(4, flags.FORCED4, options, rng); // Load stats for None PutInBank(0x1F, 0xC783, Blob.FromHex("2080B3C931F053EA")); PutInBank(0x00, 0xB380, Blob.FromHex("BD0061C9FFD013A9019D0161A9009D07619D08619D0961A931600A0A0A0AA860")); //clinic stuff PutInBank(0x0E, 0xA6F3, Blob.FromHex("203E9B")); PutInBank(0x0E, 0x9B3E, Blob.FromHex("BD0061C9FFD00568684C16A7BD016160")); // curing ailments out of battle, allow the waste of things in battle PutInBank(0x0E, 0xB388, Blob.FromHex("2077C2EAEAEAEAEAEAEAEA")); PutInBank(0x1F, 0xC277, CreateLongJumpTableEntry(0x0F, 0x8BB0)); PutInBank(0x0F, 0x8BB0, Blob.FromHex("A5626A6A6A29C0AABD0061C9FFD003A90060BD016160")); // Better Battle sprite, in 0C_9910_DrawCharacter.asm PutInBank(0x0F, 0x8BD0, Blob.FromHex("A86A6A6AAABD0061C9FFF00898AABDA86B8DB36860")); PutInBank(0x0C, 0x9910, Blob.FromHex("20A4C8C9FFD001608A0A0AA8")); PutInBank(0x1F, 0xC8A4, CreateLongJumpTableEntry(0x0F, 0x8BD0)); // MapMan for Nones PutInBank(0x1F, 0xE92E, Blob.FromHex("20608FEAEAEAEA")); PutInBank(0x02, 0x8F60, Blob.FromHex("A9008510AD0061C9FFF00160A92560")); // Draw Complex String extension for class FF PutInBank(0x1F, 0xC27D, Blob.FromHex("C9FFF0041869F060203EE0A997853EA9C2853F2045DE4C4EE0EA973CA800")); PutInBank(0x1F, 0xDF0C, Blob.FromHex("207DC2")); // Skip targeting None with aoe spells PutInBank(0x0C, 0xB453, Blob.FromHex("20AAC8C9FFF015EA")); PutInBank(0x1F, 0xC8AA, CreateLongJumpTableEntry(0x0F, 0x8BF0)); PutInBank(0x0F, 0x8BF0, Blob.FromHex("ADCE6BAA6A6A6AA8B90061C9FFF0068A09808D8A6C60")); // Rewrite class promotion to not promote NONEs, See 0E_95AE_DoClassChange.asm PutInBank(0x0E, 0x95AE, Blob.FromHex("A203BCD095B900613006186906990061CA10EFE65660")); PutInBank(0x0E, 0x95D0, Blob.FromHex("C0804000")); // lut used by the above code }
public ViewModelFlags() { Flags = new Flags(); }
public FloorHintsHintSource(MT19337 _rng, NPCdata _npcData, Flags _flags, OverworldMap _overworldMap, FF1Rom _rom) : base(_rng, _npcData, _flags, _overworldMap, _rom) { Prices = new ItemPrices(_rom); }
public static Flags DecodeFlagsText(string text) { var sum = StringToBigInteger(text); var flags = new Flags { Spoilers = GetBoolean(ref sum), AllowStartAreaDanager = GetBoolean(ref sum), WorldWealth = (WorldWealth)GetNumeric(ref sum, Enum.GetValues(typeof(WorldWealth)).Cast <int>().Max() + 1), FormationShuffleMode = (FormationShuffleModeEnum)GetNumeric(ref sum, Enum.GetValues(typeof(FormationShuffleModeEnum)).Cast <int>().Max() + 1), FiendShuffle = GetBoolean(ref sum), EFGEarth2 = GetBoolean(ref sum), EFGEarth1 = GetBoolean(ref sum), EFGWaterfall = GetBoolean(ref sum), ExperimentalFloorGeneration = GetBoolean(ref sum), ClampMinimumPriceScale = GetBoolean(ref sum), ClampMinimumBossStatScale = GetBoolean(ref sum), ClampMinimumStatScale = GetBoolean(ref sum), RecruitmentMode = GetBoolean(ref sum), ArmorPermissions = GetBoolean(ref sum), WeaponPermissions = GetBoolean(ref sum), FORCED4 = GetBoolean(ref sum), FORCED3 = GetBoolean(ref sum), FORCED2 = GetBoolean(ref sum), FORCED1 = GetBoolean(ref sum), NONE_CLASS4 = GetBoolean(ref sum), NONE_CLASS3 = GetBoolean(ref sum), NONE_CLASS2 = GetBoolean(ref sum), BLACK_MAGE4 = GetBoolean(ref sum), WHITE_MAGE4 = GetBoolean(ref sum), RED_MAGE4 = GetBoolean(ref sum), BLACK_BELT4 = GetBoolean(ref sum), THIEF4 = GetBoolean(ref sum), FIGHTER4 = GetBoolean(ref sum), BLACK_MAGE3 = GetBoolean(ref sum), WHITE_MAGE3 = GetBoolean(ref sum), RED_MAGE3 = GetBoolean(ref sum), BLACK_BELT3 = GetBoolean(ref sum), THIEF3 = GetBoolean(ref sum), FIGHTER3 = GetBoolean(ref sum), BLACK_MAGE2 = GetBoolean(ref sum), WHITE_MAGE2 = GetBoolean(ref sum), RED_MAGE2 = GetBoolean(ref sum), BLACK_BELT2 = GetBoolean(ref sum), THIEF2 = GetBoolean(ref sum), FIGHTER2 = GetBoolean(ref sum), BLACK_MAGE1 = GetBoolean(ref sum), WHITE_MAGE1 = GetBoolean(ref sum), RED_MAGE1 = GetBoolean(ref sum), BLACK_BELT1 = GetBoolean(ref sum), THIEF1 = GetBoolean(ref sum), FIGHTER1 = GetBoolean(ref sum), ProgressiveScaleMode = (ProgressiveScaleMode)GetNumeric(ref sum, Enum.GetValues(typeof(ProgressiveScaleMode)).Cast <int>().Max() + 1), DungeonEncounterRate = GetNumeric(ref sum, 46), EncounterRate = GetNumeric(ref sum, 46), ExpBonus = GetNumeric(ref sum, 51) * 10, ExpMultiplier = (GetNumeric(ref sum, 41) + 10) / 10.0, PriceScaleFactor = (GetNumeric(ref sum, 41) + 10) / 10.0, BossScaleFactor = (GetNumeric(ref sum, 41) + 10) / 10.0, EnemyScaleFactor = (GetNumeric(ref sum, 41) + 10) / 10.0, NoDanMode = GetBoolean(ref sum), RandomWaresIncludesSpecialGear = GetBoolean(ref sum), IncludeMorale = GetBoolean(ref sum), WrapPriceOverflow = GetBoolean(ref sum), WrapStatOverflow = GetBoolean(ref sum), StartingGold = GetBoolean(ref sum), ImproveTurnOrderRandomization = GetBoolean(ref sum), EnemyElementalResistancesBug = GetBoolean(ref sum), EnemySpellsTargetingAllies = GetBoolean(ref sum), EnemyStatusAttackBug = GetBoolean(ref sum), NPCSwatter = GetBoolean(ref sum), BlackBeltMDEF = GetBoolean(ref sum), BlackBeltAbsorb = GetBoolean(ref sum), SpellBugs = GetBoolean(ref sum), ChanceToRun = GetBoolean(ref sum), WeaponStats = GetBoolean(ref sum), HouseMPRestoration = GetBoolean(ref sum), WaitWhenUnrunnable = GetBoolean(ref sum), IdentifyTreasures = GetBoolean(ref sum), BuyTen = GetBoolean(ref sum), Dash = GetBoolean(ref sum), NoPartyShuffle = GetBoolean(ref sum), SpeedHacks = GetBoolean(ref sum), HousesFillHp = GetBoolean(ref sum), EasyMode = GetBoolean(ref sum), FreeCanal = GetBoolean(ref sum), EnableCritNumberDisplay = GetBoolean(ref sum), FreeOrbs = GetBoolean(ref sum), FreeAirship = GetBoolean(ref sum), FreeBridge = GetBoolean(ref sum), OnlyRequireGameIsBeatable = GetBoolean(ref sum), ShuffleObjectiveNPCs = GetBoolean(ref sum), EarlyOrdeals = GetBoolean(ref sum), EarlySage = GetBoolean(ref sum), EarlySarda = GetBoolean(ref sum), IncentivizeOtherCastWeapon = GetBoolean(ref sum), IncentivizeOffCastWeapon = GetBoolean(ref sum), IncentivizeDefCastWeapon = GetBoolean(ref sum), IncentivizeOtherCastArmor = GetBoolean(ref sum), IncentivizeOffCastArmor = GetBoolean(ref sum), IncentivizeDefCastArmor = GetBoolean(ref sum), IncentivizeRibbon = GetBoolean(ref sum), IncentivizeOpal = GetBoolean(ref sum), IncentivizeMasamune = GetBoolean(ref sum), BetterTrapChests = GetBoolean(ref sum), IncentivizeTitansTrove = GetBoolean(ref sum), IncentivizeSkyPalace = GetBoolean(ref sum), IncentivizeMarshKeyLocked = GetBoolean(ref sum), IncentivizeConeria = GetBoolean(ref sum), IncentivizeSeaShrine = GetBoolean(ref sum), IncentivizeOrdeals = GetBoolean(ref sum), IncentivizeIceCave = GetBoolean(ref sum), IncentivizeVolcano = GetBoolean(ref sum), IncentivizeEarth = GetBoolean(ref sum), IncentivizeMarsh = GetBoolean(ref sum), ClassicItemPlacement = GetBoolean(ref sum), IncentivizeShipAndCanal = GetBoolean(ref sum), IncentivizeCanoeItem = GetBoolean(ref sum), IncentivizeAirship = GetBoolean(ref sum), IncentivizeFetchItems = GetBoolean(ref sum), IncentivizeMainItems = GetBoolean(ref sum), IncentivizeTail = GetBoolean(ref sum), IncentivizeFetchNPCs = GetBoolean(ref sum), IncentivizeFreeNPCs = GetBoolean(ref sum), EntrancesMixedWithTowns = GetBoolean(ref sum), EntrancesIncludesDeadEnds = GetBoolean(ref sum), MapOpenProgressionExtended = GetBoolean(ref sum), AllowDeepTowns = GetBoolean(ref sum), AllowDeepCastles = GetBoolean(ref sum), Floors = GetBoolean(ref sum), Towns = GetBoolean(ref sum), Entrances = GetBoolean(ref sum), MapOpenProgression = GetBoolean(ref sum), ConfusedOldMen = GetBoolean(ref sum), LefeinShops = GetBoolean(ref sum), TitansTrove = GetBoolean(ref sum), SkyCastle4FMazeMode = (SkyCastle4FMazeMode)GetNumeric(ref sum, Enum.GetValues(typeof(SkyCastle4FMazeMode)).Cast <int>().Max() + 1), OrdealsPillars = GetBoolean(ref sum), WarMECHMode = (WarMECHMode)GetNumeric(ref sum, Enum.GetValues(typeof(WarMECHMode)).Cast <int>().Max() + 1), AllowUnsafeMelmond = GetBoolean(ref sum), AllowUnsafePirates = GetBoolean(ref sum), RandomStatusAttacks = GetBoolean(ref sum), EnemyStatusAttacks = GetBoolean(ref sum), EnemySkillsSpells = GetBoolean(ref sum), EnemyScripts = GetBoolean(ref sum), RandomTrapFormations = GetBoolean(ref sum), EnemyTrapTiles = GetBoolean(ref sum), UnrunnablesStrikeFirstAndSuprise = GetBoolean(ref sum), EnemyFormationsSurprise = GetBoolean(ref sum), EnemyFormationsUnrunnable = GetBoolean(ref sum), EverythingUnrunnable = GetBoolean(ref sum), Rng = GetBoolean(ref sum), RebalanceSpells = GetBoolean(ref sum), ItemMagic = GetBoolean(ref sum), MagicPermissions = GetBoolean(ref sum), MagicLevels = GetBoolean(ref sum), MagicShops = GetBoolean(ref sum), PreserveFiendRefights = GetBoolean(ref sum), ShortToFR = GetBoolean(ref sum), ChaosRush = GetBoolean(ref sum), TransformFinalFormation = GetBoolean(ref sum), ExtraShards = GetBoolean(ref sum), ShardHunt = GetBoolean(ref sum), RandomLoot = GetBoolean(ref sum), RandomWares = GetBoolean(ref sum), NPCFetchItems = GetBoolean(ref sum), NPCItems = GetBoolean(ref sum), Treasures = GetBoolean(ref sum), Shops = GetBoolean(ref sum) }; return(flags); }
public static string EncodeFlagsText(Flags flags) { BigInteger sum = 0; sum = AddBoolean(sum, flags.Shops); sum = AddBoolean(sum, flags.Treasures); sum = AddBoolean(sum, flags.NPCItems); sum = AddBoolean(sum, flags.NPCFetchItems); sum = AddBoolean(sum, flags.RandomWares); sum = AddBoolean(sum, flags.RandomLoot); sum = AddBoolean(sum, flags.ShardHunt); sum = AddBoolean(sum, flags.ExtraShards); sum = AddBoolean(sum, flags.TransformFinalFormation); sum = AddBoolean(sum, flags.ChaosRush); sum = AddBoolean(sum, flags.ShortToFR); sum = AddBoolean(sum, flags.PreserveFiendRefights); sum = AddBoolean(sum, flags.MagicShops); sum = AddBoolean(sum, flags.MagicLevels); sum = AddBoolean(sum, flags.MagicPermissions); sum = AddBoolean(sum, flags.ItemMagic); sum = AddBoolean(sum, flags.RebalanceSpells); sum = AddBoolean(sum, flags.Rng); sum = AddBoolean(sum, flags.EverythingUnrunnable); sum = AddBoolean(sum, flags.EnemyFormationsUnrunnable); sum = AddBoolean(sum, flags.EnemyFormationsSurprise); sum = AddBoolean(sum, flags.UnrunnablesStrikeFirstAndSuprise); sum = AddBoolean(sum, flags.EnemyTrapTiles); sum = AddBoolean(sum, flags.RandomTrapFormations); sum = AddBoolean(sum, flags.EnemyScripts); sum = AddBoolean(sum, flags.EnemySkillsSpells); sum = AddBoolean(sum, flags.EnemyStatusAttacks); sum = AddBoolean(sum, flags.RandomStatusAttacks); sum = AddBoolean(sum, flags.AllowUnsafePirates); sum = AddBoolean(sum, flags.AllowUnsafeMelmond); sum = AddNumeric(sum, Enum.GetValues(typeof(WarMECHMode)).Cast <int>().Max() + 1, (int)flags.WarMECHMode); sum = AddBoolean(sum, flags.OrdealsPillars); sum = AddNumeric(sum, Enum.GetValues(typeof(SkyCastle4FMazeMode)).Cast <int>().Max() + 1, (int)flags.SkyCastle4FMazeMode); sum = AddBoolean(sum, flags.TitansTrove); sum = AddBoolean(sum, flags.LefeinShops); sum = AddBoolean(sum, flags.ConfusedOldMen); sum = AddBoolean(sum, flags.MapOpenProgression); sum = AddBoolean(sum, flags.Entrances); sum = AddBoolean(sum, flags.Towns); sum = AddBoolean(sum, flags.Floors); sum = AddBoolean(sum, flags.AllowDeepCastles); sum = AddBoolean(sum, flags.AllowDeepTowns); sum = AddBoolean(sum, flags.MapOpenProgressionExtended); sum = AddBoolean(sum, flags.EntrancesIncludesDeadEnds); sum = AddBoolean(sum, flags.EntrancesMixedWithTowns); sum = AddBoolean(sum, flags.IncentivizeFreeNPCs); sum = AddBoolean(sum, flags.IncentivizeFetchNPCs); sum = AddBoolean(sum, flags.IncentivizeTail); sum = AddBoolean(sum, flags.IncentivizeMainItems); sum = AddBoolean(sum, flags.IncentivizeFetchItems); sum = AddBoolean(sum, flags.IncentivizeAirship); sum = AddBoolean(sum, flags.IncentivizeCanoeItem); sum = AddBoolean(sum, flags.IncentivizeShipAndCanal); sum = AddBoolean(sum, flags.ClassicItemPlacement); sum = AddBoolean(sum, flags.IncentivizeMarsh); sum = AddBoolean(sum, flags.IncentivizeEarth); sum = AddBoolean(sum, flags.IncentivizeVolcano); sum = AddBoolean(sum, flags.IncentivizeIceCave); sum = AddBoolean(sum, flags.IncentivizeOrdeals); sum = AddBoolean(sum, flags.IncentivizeSeaShrine); sum = AddBoolean(sum, flags.IncentivizeConeria); sum = AddBoolean(sum, flags.IncentivizeMarshKeyLocked); sum = AddBoolean(sum, flags.IncentivizeSkyPalace); sum = AddBoolean(sum, flags.IncentivizeTitansTrove); sum = AddBoolean(sum, flags.BetterTrapChests); sum = AddBoolean(sum, flags.IncentivizeMasamune); sum = AddBoolean(sum, flags.IncentivizeOpal); sum = AddBoolean(sum, flags.IncentivizeRibbon); sum = AddBoolean(sum, flags.IncentivizeDefCastArmor); sum = AddBoolean(sum, flags.IncentivizeOffCastArmor); sum = AddBoolean(sum, flags.IncentivizeOtherCastArmor); sum = AddBoolean(sum, flags.IncentivizeDefCastWeapon); sum = AddBoolean(sum, flags.IncentivizeOffCastWeapon); sum = AddBoolean(sum, flags.IncentivizeOtherCastWeapon); sum = AddBoolean(sum, flags.EarlySarda); sum = AddBoolean(sum, flags.EarlySage); sum = AddBoolean(sum, flags.EarlyOrdeals); sum = AddBoolean(sum, flags.ShuffleObjectiveNPCs); sum = AddBoolean(sum, flags.OnlyRequireGameIsBeatable); sum = AddBoolean(sum, flags.FreeBridge); sum = AddBoolean(sum, flags.FreeAirship); sum = AddBoolean(sum, flags.FreeOrbs); sum = AddBoolean(sum, flags.EnableCritNumberDisplay); sum = AddBoolean(sum, flags.FreeCanal); sum = AddBoolean(sum, flags.EasyMode); sum = AddBoolean(sum, flags.HousesFillHp); sum = AddBoolean(sum, flags.SpeedHacks); sum = AddBoolean(sum, flags.NoPartyShuffle); sum = AddBoolean(sum, flags.Dash); sum = AddBoolean(sum, flags.BuyTen); sum = AddBoolean(sum, flags.IdentifyTreasures); sum = AddBoolean(sum, flags.WaitWhenUnrunnable); sum = AddBoolean(sum, flags.HouseMPRestoration); sum = AddBoolean(sum, flags.WeaponStats); sum = AddBoolean(sum, flags.ChanceToRun); sum = AddBoolean(sum, flags.SpellBugs); sum = AddBoolean(sum, flags.BlackBeltAbsorb); sum = AddBoolean(sum, flags.BlackBeltMDEF); sum = AddBoolean(sum, flags.NPCSwatter); sum = AddBoolean(sum, flags.EnemyStatusAttackBug); sum = AddBoolean(sum, flags.EnemySpellsTargetingAllies); sum = AddBoolean(sum, flags.EnemyElementalResistancesBug); sum = AddBoolean(sum, flags.ImproveTurnOrderRandomization); sum = AddBoolean(sum, flags.StartingGold); sum = AddBoolean(sum, flags.WrapStatOverflow); sum = AddBoolean(sum, flags.WrapPriceOverflow); sum = AddBoolean(sum, flags.IncludeMorale); sum = AddBoolean(sum, flags.RandomWaresIncludesSpecialGear); sum = AddBoolean(sum, flags.NoDanMode); sum = AddNumeric(sum, 41, (int)(10.0 * flags.EnemyScaleFactor) - 10); sum = AddNumeric(sum, 41, (int)(10.0 * flags.BossScaleFactor) - 10); sum = AddNumeric(sum, 41, (int)(10.0 * flags.PriceScaleFactor) - 10); sum = AddNumeric(sum, 41, (int)(10.0 * flags.ExpMultiplier) - 10); sum = AddNumeric(sum, 51, (int)(flags.ExpBonus / 10.0)); sum = AddNumeric(sum, 46, (int)flags.EncounterRate); sum = AddNumeric(sum, 46, (int)flags.DungeonEncounterRate); sum = AddNumeric(sum, Enum.GetValues(typeof(ProgressiveScaleMode)).Cast <int>().Max() + 1, (int)flags.ProgressiveScaleMode); sum = AddBoolean(sum, flags.FIGHTER1); sum = AddBoolean(sum, flags.THIEF1); sum = AddBoolean(sum, flags.BLACK_BELT1); sum = AddBoolean(sum, flags.RED_MAGE1); sum = AddBoolean(sum, flags.WHITE_MAGE1); sum = AddBoolean(sum, flags.BLACK_MAGE1); sum = AddBoolean(sum, flags.FIGHTER2); sum = AddBoolean(sum, flags.THIEF2); sum = AddBoolean(sum, flags.BLACK_BELT2); sum = AddBoolean(sum, flags.RED_MAGE2); sum = AddBoolean(sum, flags.WHITE_MAGE2); sum = AddBoolean(sum, flags.BLACK_MAGE2); sum = AddBoolean(sum, flags.FIGHTER3); sum = AddBoolean(sum, flags.THIEF3); sum = AddBoolean(sum, flags.BLACK_BELT3); sum = AddBoolean(sum, flags.RED_MAGE3); sum = AddBoolean(sum, flags.WHITE_MAGE3); sum = AddBoolean(sum, flags.BLACK_MAGE3); sum = AddBoolean(sum, flags.FIGHTER4); sum = AddBoolean(sum, flags.THIEF4); sum = AddBoolean(sum, flags.BLACK_BELT4); sum = AddBoolean(sum, flags.RED_MAGE4); sum = AddBoolean(sum, flags.WHITE_MAGE4); sum = AddBoolean(sum, flags.BLACK_MAGE4); sum = AddBoolean(sum, flags.NONE_CLASS2); sum = AddBoolean(sum, flags.NONE_CLASS3); sum = AddBoolean(sum, flags.NONE_CLASS4); sum = AddBoolean(sum, flags.FORCED1); sum = AddBoolean(sum, flags.FORCED2); sum = AddBoolean(sum, flags.FORCED3); sum = AddBoolean(sum, flags.FORCED4); sum = AddBoolean(sum, flags.WeaponPermissions); sum = AddBoolean(sum, flags.ArmorPermissions); sum = AddBoolean(sum, flags.RecruitmentMode); sum = AddBoolean(sum, flags.ClampMinimumStatScale); sum = AddBoolean(sum, flags.ClampMinimumBossStatScale); sum = AddBoolean(sum, flags.ClampMinimumPriceScale); sum = AddBoolean(sum, flags.ExperimentalFloorGeneration); sum = AddBoolean(sum, flags.EFGWaterfall); sum = AddBoolean(sum, flags.EFGEarth1); sum = AddBoolean(sum, flags.EFGEarth2); sum = AddBoolean(sum, flags.FiendShuffle); sum = AddNumeric(sum, Enum.GetValues(typeof(FormationShuffleModeEnum)).Cast <int>().Max() + 1, (int)flags.FormationShuffleMode); sum = AddNumeric(sum, Enum.GetValues(typeof(WorldWealth)).Cast <int>().Max() + 1, (int)flags.WorldWealth); sum = AddBoolean(sum, flags.AllowStartAreaDanager); sum = AddBoolean(sum, flags.Spoilers); return(BigIntegerToString(sum)); }