Beispiel #1
0
        protected override void ExecuteCore(LivingEntity source, LivingEntity target)
        {
            var targetName = (target is Player) ? "You are" : $"The {target.Name} is";

            var hp = Rng.Between(_minHeal, _maxHeal);

            OnExecuted(new ActionCommandEventArgs($"{targetName} healed for {hp} points"));
            target.Heal(hp);

            //One use item
            target.RemoveFromInventory(_item.Id, 1);
        }
        protected override void ExecuteCore(LivingEntity source, LivingEntity target)
        {
            var sourceName = (source is Player) ? "You" : $"The {source.Name}";
            var targetName = (target is Player) ? "You" : $"The {target.Name}";

            var dmg = Rng.Between(_minDmg, _maxDmg);

            if (dmg == 0)
            {
                OnExecuted(new ActionCommandEventArgs($"{sourceName} missed"));
            }
            else
            {
                OnExecuted(new ActionCommandEventArgs($"{sourceName} hit {targetName} for {dmg} damage"));
                target.TakeDamage(dmg);
            };
        }
Beispiel #3
0
        //TODO: Use MonsterInstance instead
        public virtual Monster CreateInstance()
        {
            var instance = new Monster(Id, Name, MaximumHitPoints, RewardXP, ImagePath, Gold);

            //Figure out loot
            foreach (var loot in _lootTable)
            {
                if (Rng.Between(1, 100) <= loot.Percentage)
                {
                    instance.AddToInventory(ItemFactory.NewItem(loot.Id));
                }
            }
            ;

            instance.CurrentWeapon = CurrentWeapon;

            return(instance);
        }
        private static Call Create(Action <Chat, CallScenario> scriptBuilder, CallResolution requestedOption)
        {
            var correctResolution = Rng.Between(requestedOption, CallResolution.Reject, 0.70);
            var scenario          = CallScenarioFactory.Create(Job.ReturnSpecialistLevel1, PatienceLevel.Random);
            var chat = InitChat(scenario);

            scriptBuilder(chat, scenario);
            AddPlayerRequestConfirmation(scenario);

            var purchase = CreatePurchase(scenario, correctResolution);

            Debug.WriteLine($"CallResolution: Requested {requestedOption}. Expects {correctResolution} for {purchase.ProductName}");
            var history = Purchase.CreateInfiniteWith(purchase).Take(1000).Where(x => x.PurchasedWithinLast(90));

            scenario.Purchases = history;
            scenario.Target    = new Optional <Purchase>(purchase);
            return(new Call(chat, scenario, correctResolution, Level1Options));
        }
Beispiel #5
0
        public Monster GetEncounter()
        {
            if (!Encounters.Any())
            {
                return(null);
            }

            var totalChance = Encounters.Sum(x => x.Percentage);
            var result      = Rng.Between(1, totalChance);

            var total = 0;

            foreach (var encounter in Encounters)
            {
                total += encounter.Percentage;
                if (result <= total)
                {
                    return(MonsterFactory.Get(encounter.Id));
                }
            }
            ;

            return(null);
        }
Beispiel #6
0
        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();
            }
            else if (flags.BuyTenOld)
            {
                EnableBuyTen();
            }

            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);
            }

            if (flags.Etherizer && !flags.HouseMPRestoration && !flags.HousesFillHp)
            {
                Etherizer();
                itemText[(int)Item.Tent]  = "ETHR@p";
                itemText[(int)Item.Cabin] = "DRY@p ";
                itemText[(int)Item.House] = "XETH@p";
            }

            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);
        }
Beispiel #7
0
        public void MagisizeWeapons(MT19337 rng, bool balanced)
        {
            var Spells = GetSpells();

            if (!balanced)
            {
                Spells.RemoveAll(spell => spell.Data[4] == 0);
                foreach (Item weapon in ItemLists.AllWeapons.Except(ItemLists.AllMagicItem).ToList())
                {
                    WriteItemSpellData(Spells.SpliceRandom(rng), weapon);
                }
            }
            else
            {
                var tieredSpells = new List <List <MagicSpell> > {
                    Spells.GetRange(0, 16), Spells.GetRange(16, 16), Spells.GetRange(32, 16), Spells.GetRange(48, 16)
                };

                var commonOdds = new List <int> {
                    0, 0, 0, 0, 1, 1, 1, 1, 2, 2
                };
                var rareOdds = new List <int> {
                    0, 1, 1, 1, 2, 2, 2, 3, 3, 3
                };
                var legendaryOdds = new List <int> {
                    1, 2, 2, 2, 3, 3, 3, 3, 3, 3
                };

                for (int i = 0; i < 4; i++)
                {
                    tieredSpells[i].RemoveAll(spell => spell.Data[4] == 0);
                }

                foreach (Item weapon in ItemLists.CommonWeaponTier)
                {
                    var selectedTier = commonOdds.PickRandom(rng);
                    while (tieredSpells[selectedTier].Count == 0)
                    {
                        selectedTier = commonOdds.PickRandom(rng);
                    }

                    WriteItemSpellData(tieredSpells[selectedTier].SpliceRandom(rng), weapon);
                }

                foreach (Item weapon in ItemLists.RareWeaponTier.Except(ItemLists.AllMagicItem).ToList())
                {
                    var selectedTier = rareOdds.PickRandom(rng);
                    while (tieredSpells[selectedTier].Count == 0)
                    {
                        selectedTier = rareOdds.PickRandom(rng);
                    }

                    WriteItemSpellData(tieredSpells[selectedTier].SpliceRandom(rng), weapon);
                }

                foreach (Item weapon in ItemLists.LegendaryWeaponTier)
                {
                    var selectedTier = legendaryOdds.PickRandom(rng);
                    while (tieredSpells[selectedTier].Count == 0)
                    {
                        selectedTier = legendaryOdds.PickRandom(rng);
                    }

                    WriteItemSpellData(tieredSpells[selectedTier].SpliceRandom(rng), weapon);
                }

                foreach (Item weapon in ItemLists.UberTier)
                {
                    var selectedTier = Rng.Between(rng, 0, 3);
                    while (tieredSpells[selectedTier].Count == 0)
                    {
                        selectedTier = Rng.Between(rng, 0, 3);
                    }

                    WriteItemSpellData(tieredSpells[selectedTier].SpliceRandom(rng), weapon);
                }
            }
        }
Beispiel #8
0
        public void MonsterInABox(MT19337 rng, Flags flags)
        {
            const int lut_TreasureOffset = 0x3100;
            const int BANK_SMINFO        = 0x00;
            const int lut_TileSMsetProp  = 0x8800;            // BANK_SMINFO - page                        - 0x100 bytes x 8  (2 bytes per)

            // Replace OpenTreasureChest routine, see 11_8EC0_CheckTrap.asm
            PutInBank(0x1F, 0xDD78, Blob.FromHex("A9002003FEA645BD00B18561A9112003FE20A08E8A60"));

            // Check for trapped monster routine, see 11_8EC0_CheckTrap.asm
            PutInBank(0x11, 0x8EA0, Blob.FromHex("A5612080B1B045A645BD008FF03A856AA56148A9008561A9C0203D96A56A200096A903CD866BD0096820189668684C4396688561A97BC56AF00B20EE8E201896A2F08645604C38C920EE8E60AA6018A5612010B4A445B90062090499006260"));

            InsertDialogs(0x110, "Monster-in-a-box!");             // 0xC0

            List <IRewardSource> validChests = new();
            var chestMonsterList             = new byte[0x100];
            var treasureList = Get(lut_TreasureOffset, 0x100);

            // Select treasures
            var betterEquipmentList = ItemLists.UberTier.Concat(ItemLists.LegendaryArmorTier).Concat(ItemLists.LegendaryWeaponTier).Concat(ItemLists.RareArmorTier).Concat(ItemLists.RareWeaponTier);

            var RangeKeyItems       = ItemLocations.AllTreasures.Where(x => !x.IsUnused && ItemLists.AllQuestItems.Contains((Item)treasureList[x.Address - lut_TreasureOffset]));
            var RangeShards         = ItemLocations.AllTreasures.Where(x => !x.IsUnused && treasureList[x.Address - lut_TreasureOffset] == (int)Item.Shard);
            var RangeBetterTreasure = ItemLocations.AllTreasures.Where(x => !x.IsUnused && betterEquipmentList.Contains((Item)treasureList[x.Address - lut_TreasureOffset]));
            var RangeRandom         = ItemLocations.AllTreasures.Where(x => !x.IsUnused && !RangeKeyItems.Contains(x) && !RangeShards.Contains(x)  && !RangeBetterTreasure.Contains(x));
            var RangeMasamune       = ItemLocations.AllTreasures.Where(x => !x.IsUnused && treasureList[x.Address - lut_TreasureOffset] == (int)Item.Masamune);

            if (flags.TCKeyItems == TCOptions.Pooled)
            {
                validChests.AddRange(RangeKeyItems);
            }

            if (flags.TCShards == TCOptions.Pooled)
            {
                validChests.AddRange(RangeShards);
            }

            if (flags.TCBetterTreasure == TCOptions.Pooled)
            {
                validChests.AddRange(RangeBetterTreasure);
            }

            if (flags.TCExcludeCommons == false)
            {
                validChests.AddRange(RangeRandom);
            }

            if ((bool)flags.TCMasaGuardian == true)
            {
                validChests.RemoveAll(x => treasureList[x.Address - lut_TreasureOffset] == (int)Item.Masamune);
            }

            if (flags.TCProtectIncentives == true)
            {
                validChests.RemoveAll(x => GetIncentiveList(flags).Contains((Item)treasureList[x.Address - lut_TreasureOffset]));
            }

            int maxChests        = 0;
            int guaranteedChests = ((flags.TCKeyItems == TCOptions.All) ? RangeKeyItems.Count() : 0) + ((flags.TCShards == TCOptions.All) ? RangeShards.Count() : 0) + ((flags.TCBetterTreasure == TCOptions.All) ? RangeBetterTreasure.Count() : 0) + (((bool)flags.TCMasaGuardian) ? RangeMasamune.Count() : 0) + (((bool)flags.TrappedChaos) ? 1 : 0);

            if (flags.TCChestCount == 13)
            {
                maxChests = Rng.Between(rng, 20, (240 - guaranteedChests));
            }
            else if (flags.TCChestCount > 0)
            {
                maxChests = Math.Max(0, (flags.TCChestCount * 20) - guaranteedChests);
            }
            else
            {
                maxChests = 0;
            }

            // Get encounters
            const byte spookyZomBull = 0xB2;
            const byte spookyZombieD = 0xCB;
            const byte fightBahamut  = 0xF1;

            List <byte> altEncountersList = Enumerable.Range(128, FirstBossEncounterIndex).Select(value => (byte)value).ToList();

            altEncountersList.Add(0xFF);             // IronGol

            if ((bool)flags.SpookyFlag)
            {
                altEncountersList.Remove(spookyZomBull);
                altEncountersList.Remove(spookyZombieD);
            }

            if ((bool)flags.FightBahamut)
            {
                altEncountersList.Remove(fightBahamut);
            }

            List <byte>         encounters      = new();
            List <List <byte> > encountersGroup = new();

            // Formations List for Vanilla Spikes & Local Formations
            List <byte> castleEncounters = new() { 0x84, 0x8C, 0x8D, 0x92 };
            List <byte> caveEncounters   = new() { 0x9D, 0x9C, 0x95, 0x97 };
            List <byte> cardiaEncounters = new() { 0xAA, 0xB0, 0xCB, 0xCE, 0xD9 };

            // Formations List for Vanilla Spikes
            List <byte> tofEncounters       = new() { 0x10 };
            List <byte> nwcastleEncounters  = new() { 0x18, 0x1D };
            List <byte> marshEncounters     = new() { 0x1C, 0x15 };
            List <byte> earthEncounters     = new() { 0x21, 0x1E, 0x1F, 0x6E, 0x6F };
            List <byte> volcEncounters      = new() { 0x27, 0x28, 0x29, 0x2A };
            List <byte> iceEncounters       = new() { 0x2C, 0x2D, 0x2F, 0x30, 0x69, };
            List <byte> ordealsEncounters   = new() { 0x3F, 0x4F, 0x4B };
            List <byte> waterfallEncounters = new() { 0x4A };
            List <byte> seaEncounters       = new() { 0x44, 0x45, 0x49, 0x4A };
            List <byte> mirageEncounters    = new() { 0x4E };
            List <byte> tofrEncounters      = new() { 0x46 };

            if (flags.TCFormations == FormationPool.Random)
            {
                flags.TCFormations = (FormationPool)Rng.Between(rng, 0, 4);
            }

            switch (flags.TCFormations)
            {
            case FormationPool.AltFormationDist:
                List <List <byte> > baseEncounterList = new();
                for (int i = 0; i < 3; i++)
                {
                    baseEncounterList.Add(new List <byte>(altEncountersList));
                    baseEncounterList.Last().Shuffle(rng);
                }
                encounters = baseEncounterList.SelectMany(x => x).ToList();
                break;

            case FormationPool.AltFormationRng:
                encounters = altEncountersList;
                break;

            case FormationPool.LocalFormations:
                encountersGroup = Get(ZoneFormationsOffset + (8 * 0x40), 8 * 0x40).Chunk(0x08).Select(x => x.ToBytes().Select(y => (byte)(y | 0x80)).ToList()).ToList();

                encountersGroup[(int)MapId.ConeriaCastle1F]   = castleEncounters;
                encountersGroup[(int)MapId.ElflandCastle]     = castleEncounters;
                encountersGroup[(int)MapId.NorthwestCastle]   = castleEncounters;
                encountersGroup[(int)MapId.CastleOfOrdeals1F] = castleEncounters;

                encountersGroup[(int)MapId.Cardia]         = cardiaEncounters;
                encountersGroup[(int)MapId.BahamutsRoomB1] = cardiaEncounters;
                encountersGroup[(int)MapId.BahamutsRoomB2] = cardiaEncounters;

                encountersGroup[(int)MapId.DwarfCave]   = caveEncounters;
                encountersGroup[(int)MapId.SardasCave]  = caveEncounters;
                encountersGroup[(int)MapId.MatoyasCave] = caveEncounters;

                break;

            case FormationPool.VanillaSpikes:
                encountersGroup = new() {
                    castleEncounters,
                    castleEncounters,
                    castleEncounters,
                    castleEncounters,
                    castleEncounters,
                    castleEncounters,
                    castleEncounters,
                    castleEncounters,
                    castleEncounters,
                    castleEncounters,
                    nwcastleEncounters,
                    ordealsEncounters,
                    tofEncounters,
                    earthEncounters,
                    volcEncounters,
                    iceEncounters,
                    cardiaEncounters,
                    cardiaEncounters,
                    waterfallEncounters,
                    caveEncounters,
                    caveEncounters,
                    caveEncounters,
                    marshEncounters,
                    mirageEncounters,
                    castleEncounters,
                    ordealsEncounters,
                    ordealsEncounters,
                    marshEncounters,
                    marshEncounters,
                    earthEncounters,
                    earthEncounters,
                    earthEncounters,
                    earthEncounters,
                    volcEncounters,
                    volcEncounters,
                    volcEncounters,
                    volcEncounters,
                    iceEncounters,
                    iceEncounters,
                    cardiaEncounters,
                    mirageEncounters,
                    mirageEncounters,
                    seaEncounters,
                    seaEncounters,
                    seaEncounters,
                    seaEncounters,
                    seaEncounters,
                    mirageEncounters,
                    mirageEncounters,
                    mirageEncounters,
                    mirageEncounters,
                    mirageEncounters,
                    tofrEncounters,
                    tofrEncounters,
                    tofrEncounters,
                    tofrEncounters,
                    tofrEncounters,
                    tofrEncounters,
                    tofrEncounters,
                    tofrEncounters,
                    caveEncounters,
                };
                break;

            case FormationPool.Fiends:
                encounters = Enumerable.Range(0x77, 4).Select(value => (byte)value).ToList();
                break;

            case FormationPool.Phantom:
                encounters = new List <byte> {
                    0x46
                };
                break;
            }

            int altFormationPosition = 0;
            var chestsMapLocations   = ItemLocations.GetTreasuresMapLocation().ToDictionary(x => x.Key, x => ItemLocations.MapLocationToMapId[x.Value]);

            byte GetEncounter(int i)
            {
                if (flags.TCFormations == FormationPool.LocalFormations || flags.TCFormations == FormationPool.VanillaSpikes)
                {
                    return(encountersGroup[(int)chestsMapLocations[i]].PickRandom(rng));
                }
                else if (flags.TCFormations == FormationPool.AltFormationDist)
                {
                    return(encounters[altFormationPosition++]);
                }
                else
                {
                    return(encounters.PickRandom(rng));
                }
            }

            // Process pool first
            if (maxChests > 0)
            {
                maxChests = Math.Min(maxChests, validChests.Count);

                for (int i = 0; i < maxChests; i++)
                {
                    var selectedChest = validChests.SpliceRandom(rng).Address - lut_TreasureOffset;
                    chestMonsterList[selectedChest] = GetEncounter(selectedChest);
                }
            }

            // Better Treasure
            if (flags.TCBetterTreasure == TCOptions.All)
            {
                for (int i = 0; i < 0x100; i++)
                {
                    if (betterEquipmentList.Contains((Item)treasureList[i]))
                    {
                        chestMonsterList[i] = GetEncounter(i);
                    }
                }
            }

            // Key Items
            if (flags.TCKeyItems == TCOptions.All)
            {
                for (int i = 0; i < 0x100; i++)
                {
                    if (ItemLists.AllQuestItems.Contains((Item)treasureList[i]))
                    {
                        chestMonsterList[i] = GetEncounter(i);
                    }
                }
            }

            // Shards
            if (flags.TCShards == TCOptions.All)
            {
                for (int i = 0; i < 0x100; i++)
                {
                    if (treasureList[i] == (byte)Item.Shard)
                    {
                        chestMonsterList[i] = GetEncounter(i);
                    }
                }
            }

            // Masamune
            if ((bool)flags.TCMasaGuardian)
            {
                for (int i = 0; i < 0x100; i++)
                {
                    if (treasureList[i] == (byte)Item.Masamune)
                    {
                        chestMonsterList[i] = (byte)WarMECHFormationIndex;
                    }
                }
            }

            // Chaos
            if ((bool)flags.TrappedChaos)
            {
                List <MapLocation> disallowedLocations = new() { MapLocation.TempleOfFiends1Room1, MapLocation.TempleOfFiends1Room2, MapLocation.TempleOfFiends2, MapLocation.TempleOfFiends3, MapLocation.TempleOfFiendsAir, MapLocation.TempleOfFiendsChaos, MapLocation.TempleOfFiendsEarth, MapLocation.TempleOfFiendsFire, MapLocation.TempleOfFiendsPhantom, MapLocation.TempleOfFiendsWater, MapLocation.MatoyasCave, MapLocation.DwarfCave };

                validChests.RemoveAll(x => disallowedLocations.Contains(x.MapLocation));

                // Replace a random chest if there's no valid location left for Chaos
                if (!validChests.Any())
                {
                    validChests = RangeRandom.ToList();
                    validChests.RemoveAll(x => disallowedLocations.Contains(x.MapLocation) || ((bool)flags.TCMasaGuardian == true && treasureList[x.Address - lut_TreasureOffset] == (int)Item.Masamune) || ((bool)flags.TCProtectIncentives == true && GetIncentiveList(flags).Contains((Item)treasureList[x.Address - lut_TreasureOffset])));
                }

                chestMonsterList[validChests.SpliceRandom(rng).Address - lut_TreasureOffset] = ChaosFormationIndex;
            }


            //Spoilers

            /*
             * int count = 0;
             * for (int i = 0; i < 0x100; i++)
             * {
             *      if (chestMonsterList[i] > 0)
             *      {
             *              count++;
             *              Console.WriteLine(count + ". " + ItemLocations.AllTreasures.Where(x => (x.Address - lut_TreasureOffset) == i).First().Name + " -> " + Enum.GetName((Item)treasureList[i]));
             *      }
             * }
             */

            // Mark trapped chests
            if ((bool)flags.TCIndicator)
            {
                for (int i = 0; i < 8; i++)
                {
                    for (int j = 0; j < 0x80; j++)
                    {
                        var tempTileProperties = GetFromBank(BANK_SMINFO, lut_TileSMsetProp + (i * 0x100) + (j * 2), 2);
                        if ((tempTileProperties[0] & (byte)TilePropFunc.TP_SPEC_TREASURE) > 0 && (tempTileProperties[0] & (byte)TilePropFunc.TP_NOMOVE) > 0)
                        {
                            if (chestMonsterList[(int)tempTileProperties[1]] > 0)
                            {
                                TileSM temptile = new((byte)j, i, this);
                                temptile.TileGraphic = new List <byte> {
                                    0x2A, 0x7C, 0x3A, 0x3B
                                };
                                temptile.Write(this);
                            }
                        }
                    }
                }
            }

            // Insert trapped chest list
            PutInBank(0x11, 0x8F00, chestMonsterList);
        }

        public void SetChaosForMIAB(NPCdata npcdata)
        {
            npcdata.SetRoutine((ObjectId)0x1A, newTalkRoutines.Talk_4Orb);
            npcdata.GetTalkArray((ObjectId)0x1A)[(int)TalkArrayPos.dialogue_1] = 0x30;
            npcdata.GetTalkArray((ObjectId)0x1A)[(int)TalkArrayPos.dialogue_2] = 0x30;
            npcdata.GetTalkArray((ObjectId)0x1A)[(int)TalkArrayPos.dialogue_3] = 0x30;
            Data[MapObjGfxOffset + 0x18] = 0xF4;
            Data[MapObjGfxOffset + 0x19] = 0xF4;
            Data[MapObjGfxOffset + 0x1A] = 0xF4;
            PutInBank(0x00, 0xA000 + ((byte)MapId.TempleOfFiendsRevisitedChaos * 0x30) + 0x18, Blob.FromHex("000F1636000F1636"));

            Dictionary <int, string> newgarlanddialogue = new Dictionary <int, string>();

            newgarlanddialogue.Add(0x2E, "That's right, it's me,\nBurtReynoldz. Didn't\nexpect to see me, right?");
            newgarlanddialogue.Add(0x2F, "Many moons ago I managed\nto run away from Chaos.\nAnd lo and behold,\nI BECAME Chaos. I took\nhis place.");
            newgarlanddialogue.Add(0x30, "Okay, I won't fight you.\nSome say you can find\nthe other Chaos hidden\nsomewhere in a chest.\nGood luck!");

            InsertDialogs(newgarlanddialogue);
        }

        public static List <Item> GetIncentiveList(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.IncentivizePowerRod ?? false)
            {
                incentivePool.Add(Item.PowerRod);
            }
            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.IncentivizeXcalber ?? false)
            {
                incentivePool.Add(Item.Xcalber);
            }

            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.IncentivizeCrystal ?? false)
            {
                incentivePool.Add(Item.Crystal);
            }
            if (flags.IncentivizeBottle ?? false)
            {
                incentivePool.Add(Item.Bottle);
            }
            if (flags.IncentivizeHerb ?? false)
            {
                incentivePool.Add(Item.Herb);
            }

            if (flags.IncentivizeKey ?? false)
            {
                incentivePool.Add(Item.Key);
            }
            if (flags.IncentivizeOxyale ?? false)
            {
                incentivePool.Add(Item.Oxyale);
            }
            if (flags.IncentivizeLute ?? false)
            {
                incentivePool.Add(Item.Lute);
            }
            if (flags.IncentivizeRod ?? false)
            {
                incentivePool.Add(Item.Rod);
            }
            if (flags.IncentivizeCube ?? false)
            {
                incentivePool.Add(Item.Cube);
            }
            if (flags.IncentivizeChime ?? false)
            {
                incentivePool.Add(Item.Chime);
            }

            if (flags.IncentivizeBridge ?? false)
            {
                incentivePool.Add(Item.Bridge);
            }
            if (flags.IncentivizeShip ?? false)
            {
                incentivePool.Add(Item.Ship);
            }
            if (flags.IncentivizeCanoe ?? false)
            {
                incentivePool.Add(Item.Canoe);
            }
            if (flags.IncentivizeCanal ?? false)
            {
                incentivePool.Add(Item.Canal);
            }

            return(incentivePool.ToList());
        }
    }
}