Beispiel #1
0
        private void Awake()
        {
            _magicRarityColor           = Config.Bind("Item Colors", "Magic Rarity Color", "Blue", "The color of Magic rarity items, the lowest magic item tier. (Optional, use an HTML hex color starting with # to have a custom color.) Available options: Red, Orange, Yellow, Green, Teal, Blue, Indigo, Purple, Pink, Gray");
            _magicMaterialIconColor     = Config.Bind("Item Colors", "Magic Crafting Material Icon Index", 5, "Indicates the color of the icon used for magic crafting materials. A number between 0 and 9. Available options: 0=Red, 1=Orange, 2=Yellow, 3=Green, 4=Teal, 5=Blue, 6=Indigo, 7=Purple, 8=Pink, 9=Gray");
            _rareRarityColor            = Config.Bind("Item Colors", "Rare Rarity Color", "Yellow", "The color of Rare rarity items, the second magic item tier. (Optional, use an HTML hex color starting with # to have a custom color.) Available options: Red, Orange, Yellow, Green, Teal, Blue, Indigo, Purple, Pink, Gray");
            _rareMaterialIconColor      = Config.Bind("Item Colors", "Rare Crafting Material Icon Index", 2, "Indicates the color of the icon used for rare crafting materials. A number between 0 and 9. Available options: 0=Red, 1=Orange, 2=Yellow, 3=Green, 4=Teal, 5=Blue, 6=Indigo, 7=Purple, 8=Pink, 9=Gray");
            _epicRarityColor            = Config.Bind("Item Colors", "Epic Rarity Color", "Purple", "The color of Epic rarity items, the third magic item tier. (Optional, use an HTML hex color starting with # to have a custom color.) Available options: Red, Orange, Yellow, Green, Teal, Blue, Indigo, Purple, Pink, Gray");
            _epicMaterialIconColor      = Config.Bind("Item Colors", "Epic Crafting Material Icon Index", 7, "Indicates the color of the icon used for epic crafting materials. A number between 0 and 9. Available options: 0=Red, 1=Orange, 2=Yellow, 3=Green, 4=Teal, 5=Blue, 6=Indigo, 7=Purple, 8=Pink, 9=Gray");
            _legendaryRarityColor       = Config.Bind("Item Colors", "Legendary Rarity Color", "Teal", "The color of Legendary rarity items, the highest magic item tier. (Optional, use an HTML hex color starting with # to have a custom color.) Available options: Red, Orange, Yellow, Green, Teal, Blue, Indigo, Purple, Pink, Gray");
            _legendaryMaterialIconColor = Config.Bind("Item Colors", "Legendary Crafting Material Icon Index", 4, "Indicates the color of the icon used for legendary crafting materials. A number between 0 and 9. Available options: 0=Red, 1=Orange, 2=Yellow, 3=Green, 4=Teal, 5=Blue, 6=Indigo, 7=Purple, 8=Pink, 9=Gray");
            _setItemColor                = Config.Bind("Item Colors", "Set Item Color", "#26ffff", "The color of set item text and the set item icon. Use a hex color, default is cyan");
            _magicRarityDisplayName      = Config.Bind("Rarity", "Magic Rarity Display Name", "Magic", "The name of the lowest rarity.");
            _rareRarityDisplayName       = Config.Bind("Rarity", "Rare Rarity Display Name", "Rare", "The name of the second rarity.");
            _epicRarityDisplayName       = Config.Bind("Rarity", "Epic Rarity Display Name", "Epic", "The name of the third rarity.");
            _legendaryRarityDisplayName  = Config.Bind("Rarity", "Legendary Rarity Display Name", "Legendary", "The name of the highest rarity.");
            UseScrollingCraftDescription = Config.Bind("Crafting UI", "Use Scrolling Craft Description", true, "Changes the item description in the crafting panel to scroll instead of scale when it gets too long for the space.");

            MagicItemEffectDefinitions.SetupMagicItemEffectDefinitions();

            LootRoller.Initialize(LoadJsonFile <LootConfig>("loottables.json"));
            PrintInfo();

            LoadAssets();

            ExtendedItemData.LoadExtendedItemData += SetupTestMagicItem;
            ExtendedItemData.LoadExtendedItemData += MagicItemComponent.OnNewExtendedItemData;
            ExtendedItemData.NewExtendedItemData  += MagicItemComponent.OnNewExtendedItemData;

            _harmony = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), PluginId);

            LootTableLoaded?.Invoke();
        }
Beispiel #2
0
        private static void WriteLootTableDrops(StringBuilder t, LootTable lootTable)
        {
            var highestLevel = lootTable.LeveledLoot != null && lootTable.LeveledLoot.Count > 0 ? lootTable.LeveledLoot.Max(x => x.Level) : 0;
            var limit        = Mathf.Max(3, highestLevel);

            for (var i = 0; i < limit; i++)
            {
                var level     = i + 1;
                var dropTable = LootRoller.GetDropsForLevel(lootTable, level, false);
                if (ArrayUtils.IsNullOrEmpty(dropTable))
                {
                    continue;
                }

                float total = dropTable.Sum(x => x.Length > 1 ? x[1] : 0);
                if (total > 0)
                {
                    t.AppendLine($"> | Drops (lvl {level}) | Weight (Chance) |");
                    t.AppendLine($"> | -- | -- |");
                    foreach (var drop in dropTable)
                    {
                        var count   = drop.Length > 0 ? drop[0] : 0;
                        var value   = drop.Length > 1 ? drop[1] : 0;
                        var percent = (value / total) * 100;
                        t.AppendLine($"> | {count} | {value} ({percent:0.#}%) |");
                    }
                }
                t.AppendLine();
            }
        }
Beispiel #3
0
        private void Awake()
        {
            _magicRarityColor           = Config.Bind("Item Colors", "Magic Rarity Color", "Blue", "The color of Magic rarity items, the lowest magic item tier. (Optional, use an HTML hex color starting with # to have a custom color.) Available options: Red, Orange, Yellow, Green, Teal, Blue, Indigo, Purple, Pink, Gray");
            _magicMaterialIconColor     = Config.Bind("Item Colors", "Magic Crafting Material Icon Index", 5, "Indicates the color of the icon used for magic crafting materials. A number between 0 and 9. Available options: 0=Red, 1=Orange, 2=Yellow, 3=Green, 4=Teal, 5=Blue, 6=Indigo, 7=Purple, 8=Pink, 9=Gray");
            _rareRarityColor            = Config.Bind("Item Colors", "Rare Rarity Color", "Yellow", "The color of Rare rarity items, the second magic item tier. (Optional, use an HTML hex color starting with # to have a custom color.) Available options: Red, Orange, Yellow, Green, Teal, Blue, Indigo, Purple, Pink, Gray");
            _rareMaterialIconColor      = Config.Bind("Item Colors", "Rare Crafting Material Icon Index", 2, "Indicates the color of the icon used for rare crafting materials. A number between 0 and 9. Available options: 0=Red, 1=Orange, 2=Yellow, 3=Green, 4=Teal, 5=Blue, 6=Indigo, 7=Purple, 8=Pink, 9=Gray");
            _epicRarityColor            = Config.Bind("Item Colors", "Epic Rarity Color", "Purple", "The color of Epic rarity items, the third magic item tier. (Optional, use an HTML hex color starting with # to have a custom color.) Available options: Red, Orange, Yellow, Green, Teal, Blue, Indigo, Purple, Pink, Gray");
            _epicMaterialIconColor      = Config.Bind("Item Colors", "Epic Crafting Material Icon Index", 7, "Indicates the color of the icon used for epic crafting materials. A number between 0 and 9. Available options: 0=Red, 1=Orange, 2=Yellow, 3=Green, 4=Teal, 5=Blue, 6=Indigo, 7=Purple, 8=Pink, 9=Gray");
            _legendaryRarityColor       = Config.Bind("Item Colors", "Legendary Rarity Color", "Teal", "The color of Legendary rarity items, the highest magic item tier. (Optional, use an HTML hex color starting with # to have a custom color.) Available options: Red, Orange, Yellow, Green, Teal, Blue, Indigo, Purple, Pink, Gray");
            _legendaryMaterialIconColor = Config.Bind("Item Colors", "Legendary Crafting Material Icon Index", 4, "Indicates the color of the icon used for legendary crafting materials. A number between 0 and 9. Available options: 0=Red, 1=Orange, 2=Yellow, 3=Green, 4=Teal, 5=Blue, 6=Indigo, 7=Purple, 8=Pink, 9=Gray");
            _setItemColor                = Config.Bind("Item Colors", "Set Item Color", "#26ffff", "The color of set item text and the set item icon. Use a hex color, default is cyan");
            _magicRarityDisplayName      = Config.Bind("Rarity", "Magic Rarity Display Name", "Magic", "The name of the lowest rarity.");
            _rareRarityDisplayName       = Config.Bind("Rarity", "Rare Rarity Display Name", "Rare", "The name of the second rarity.");
            _epicRarityDisplayName       = Config.Bind("Rarity", "Epic Rarity Display Name", "Epic", "The name of the third rarity.");
            _legendaryRarityDisplayName  = Config.Bind("Rarity", "Legendary Rarity Display Name", "Legendary", "The name of the highest rarity.");
            UseScrollingCraftDescription = Config.Bind("Crafting UI", "Use Scrolling Craft Description", true, "Changes the item description in the crafting panel to scroll instead of scale when it gets too long for the space.");
            _gatedItemTypeModeConfig     = Config.Bind("Balance", "Item Drop Limits", GatedItemTypeMode.MustKnowRecipe, "Sets how the drop system limits what item types can drop. Unlimited: no limits, exactly what's in the loot table will drop. MustKnowRecipe: items will drop so long as the player has discovered their recipe. MustHaveCrafted: items will only drop once the player has crafted one or picked one up. If an item type cannot drop, it will downgrade to an item of the same type and skill that the player has unlocked (i.e. swords will stay swords)");

            MagicItemEffectDefinitions.Initialize(LoadJsonFile <MagicItemEffectsList>("magiceffects.json"));
            LootRoller.Initialize(LoadJsonFile <LootConfig>("loottables.json"));
            GatedItemTypeHelper.Initialize(LoadJsonFile <ItemInfoConfig>("iteminfo.json"));
            RecipesHelper.Initialize(LoadJsonFile <RecipesConfig>("recipes.json"));
            PrintInfo();

            LoadAssets();

            ExtendedItemData.LoadExtendedItemData += SetupTestMagicItem;
            ExtendedItemData.LoadExtendedItemData += MagicItemComponent.OnNewExtendedItemData;
            ExtendedItemData.NewExtendedItemData  += MagicItemComponent.OnNewExtendedItemData;

            _harmony = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), PluginId);

            LootTableLoaded?.Invoke();
        }
Beispiel #4
0
        private static void ReplaceMagicEffect(ItemDrop.ItemData itemData, MagicItem magicItem, MagicItemEffect effect, int index)
        {
            var replacementEffectDef = GetReplacementEffectDef(effect);

            if (replacementEffectDef == null)
            {
                return;
            }

            var replacementEffect = LootRoller.RollEffect(replacementEffectDef, magicItem.Rarity);

            magicItem.Effects[index] = replacementEffect;
            itemData.Extended().Save();
        }
Beispiel #5
0
        private static void WriteLootTableItems(StringBuilder t, LootTable lootTable)
        {
            var highestLevel = lootTable.LeveledLoot != null && lootTable.LeveledLoot.Count > 0 ? lootTable.LeveledLoot.Max(x => x.Level) : 0;
            var limit        = Mathf.Max(3, highestLevel);

            for (var i = 0; i < limit; i++)
            {
                var level    = i + 1;
                var lootList = LootRoller.GetLootForLevel(lootTable, level, false);
                if (ArrayUtils.IsNullOrEmpty(lootList))
                {
                    continue;
                }

                WriteLootList(t, level, lootList);
            }
        }
Beispiel #6
0
        private static string GetMagicEffectCountTableLine(ItemRarity rarity)
        {
            var   effectCounts = LootRoller.GetEffectCountsPerRarity(rarity);
            float total        = effectCounts.Sum(x => x.Value);
            var   result       = $"|{rarity}|";

            for (var i = 1; i <= 6; ++i)
            {
                var valueString = " ";
                var i1          = i;
                if (effectCounts.TryFind(x => x.Key == i1, out var found))
                {
                    var value   = found.Value;
                    var percent = value / total * 100;
                    valueString = $"{value} ({percent:0.#}%)";
                }
                result += $"{valueString}|";
            }
            return(result);
        }
        public static void Postfix(Container __instance)
        {
            if (__instance == null || __instance.m_piece == null)
            {
                return;
            }

            var containerName = __instance.m_piece.name.Replace("(Clone)", "").Trim();
            var lootTable     = LootRoller.GetLootTable(containerName);

            if (lootTable != null)
            {
                var items = LootRoller.RollLootTable(lootTable, 1, __instance.m_piece.name, __instance.transform.position);
                Debug.Log($"Rolling on loot table: {containerName}, spawned {items.Count} items at drop point({__instance.transform.position.ToString("0")}).");
                foreach (var item in items)
                {
                    __instance.m_inventory.AddItem(item);
                    Debug.Log($"  - {item.m_shared.m_name}" + (item.IsMagic() ? $": {string.Join(", ", item.GetMagicItem().Effects.Select(x => x.EffectType.ToString()))}" : ""));
                }
            }
        }
Beispiel #8
0
        public static void OnCharacterDeath(string characterName, int level, Vector3 dropPoint)
        {
            var lootTables = LootRoller.GetLootTable(characterName, level);

            if (lootTables != null && lootTables.Count > 0)
            {
                List <GameObject> loot = LootRoller.RollLootTableAndSpawnObjects(lootTables, characterName, dropPoint);
                Debug.Log($"Rolling on loot table: {characterName} (lvl {level}), spawned {loot.Count} items at drop point({dropPoint}).");
                DropItems(loot, dropPoint);
                foreach (var l in loot)
                {
                    var itemData  = l.GetComponent <ItemDrop>().m_itemData;
                    var magicItem = itemData.GetMagicItem();
                    if (magicItem != null)
                    {
                        Debug.Log($"  - {itemData.m_shared.m_name} <{l.transform.position}>: {string.Join(", ", magicItem.Effects.Select(x => x.EffectType.ToString()))}");
                    }
                }
            }
            else
            {
                Debug.Log($"Could not find loot table for: {characterName} (lvl {level})");
            }
        }
Beispiel #9
0
        public static void SpawnMagicItemWithEffect(Console __instance, string[] args)
        {
            if (args.Length < 3)
            {
                EpicLoot.LogError("Specify effect and item name");
                return;
            }

            if (Player.m_localPlayer == null)
            {
                return;
            }

            var effectArg         = args[1];
            var itemPrefabNameArg = args[2];

            __instance.AddString($"magicitem - {itemPrefabNameArg} with effect: {effectArg}");

            var magicItemEffectDef = MagicItemEffectDefinitions.Get(effectArg);

            if (magicItemEffectDef == null)
            {
                __instance.AddString($"> Could not find effect: {effectArg}");
                return;
            }

            var itemPrefab = ObjectDB.instance.GetItemPrefab(itemPrefabNameArg);

            if (itemPrefab == null)
            {
                __instance.AddString($"> Could not find item: {itemPrefabNameArg}");
                return;
            }

            var fromItemData = itemPrefab.GetComponent <ItemDrop>().m_itemData;

            if (!EpicLoot.CanBeMagicItem(fromItemData))
            {
                __instance.AddString($"> Can't be magic item: {itemPrefabNameArg}");
                return;
            }

            var effectRequirements = magicItemEffectDef.Requirements;
            var itemRarity         = effectRequirements.AllowedRarities.Count == 0 ? ItemRarity.Legendary : effectRequirements.AllowedRarities.First();
            var rarityTable        = GetRarityTable(itemRarity.ToString());
            var loot = new LootTable
            {
                Object = "Console",
                Drops  = new[] { new[] { 1, 1 } },
                Loot   = new[]
                {
                    new LootDrop
                    {
                        Item   = itemPrefab.name,
                        Rarity = rarityTable
                    }
                }
            };

            var randomOffset = UnityEngine.Random.insideUnitSphere;
            var dropPoint    = Player.m_localPlayer.transform.position + Player.m_localPlayer.transform.forward * 3 + Vector3.up * 1.5f + randomOffset;

            // TODO add better hook for desired effect - currently effect will be discarded on next game load
            // if effect was added when magicItem had maximum of available effect
            // however still good for debug
            LootRoller.CheatForceMagicEffect = true;
            LootRoller.ForcedMagicEffect     = effectArg;
            LootRoller.RollLootTableAndSpawnObjects(loot, 1, loot.Object, dropPoint);
            LootRoller.CheatForceMagicEffect = false;
            LootRoller.ForcedMagicEffect     = string.Empty;
        }
Beispiel #10
0
        public static void MagicItem(Console __instance, string[] args)
        {
            var rarityArg   = args.Length >= 2 ? args[1] : "random";
            var itemArg     = args.Length >= 3 ? args[2] : "random";
            var count       = args.Length >= 4 ? int.Parse(args[3]) : 1;
            var effectCount = args.Length >= 5 ? int.Parse(args[4]) : -1;

            __instance.AddString($"magicitem - rarity:{rarityArg}, item:{itemArg}, count:{count}");

            var allItemNames = ObjectDB.instance.m_items
                               .Where(x => EpicLoot.CanBeMagicItem(x.GetComponent <ItemDrop>().m_itemData))
                               .Where(x => x.name != "HelmetDverger" && x.name != "BeltStrength" && x.name != "Wishbone")
                               .Select(x => x.name)
                               .ToList();

            if (Player.m_localPlayer == null)
            {
                return;
            }

            LootRoller.CheatEffectCount = effectCount;
            for (var i = 0; i < count; i++)
            {
                int[] rarityTable = GetRarityTable(rarityArg);

                var item = itemArg;
                if (item == "random")
                {
                    var weightedRandomTable = new WeightedRandomCollection <string>(_random, allItemNames, x => 1);
                    item = weightedRandomTable.Roll();
                }

                if (ObjectDB.instance.GetItemPrefab(item) == null)
                {
                    __instance.AddString($"> Could not find item: {item}");
                    break;
                }

                __instance.AddString($">  {i + 1} - rarity: [{string.Join(", ", rarityTable)}], item: {item}");

                var loot = new LootTable()
                {
                    Object = "Console",
                    Drops  = new[] { new[] { 1, 1 } },
                    Loot   = new[]
                    {
                        new LootDrop()
                        {
                            Item   = item,
                            Rarity = rarityTable,
                            Weight = 1
                        }
                    }
                };

                var randomOffset = UnityEngine.Random.insideUnitSphere;
                var dropPoint    = Player.m_localPlayer.transform.position + Player.m_localPlayer.transform.forward * 3 + Vector3.up * 1.5f + randomOffset;
                LootRoller.RollLootTableAndSpawnObjects(loot, 1, loot.Object, dropPoint);
            }
            LootRoller.CheatEffectCount = -1;
        }
Beispiel #11
0
        private static void SpawnLegendaryItemHelper(string legendaryID, string itemType, Terminal context)
        {
            if (!UniqueLegendaryHelper.TryGetLegendaryInfo(legendaryID, out var legendaryInfo))
            {
                if (context != null)
                {
                    context.AddString($"> Could not find info for legendaryID: ({legendaryID})");
                }
                return;
            }

            if (string.IsNullOrEmpty(itemType))
            {
                var dummyMagicItem = new MagicItem {
                    Rarity = ItemRarity.Legendary
                };
                var allowedItems = new List <ItemDrop>();
                foreach (var itemName in GatedItemTypeHelper.ItemInfoByID.Keys)
                {
                    var itemPrefab = ObjectDB.instance.GetItemPrefab(itemName);
                    if (itemPrefab == null)
                    {
                        continue;
                    }

                    var itemDrop = itemPrefab.GetComponent <ItemDrop>();
                    if (itemDrop == null)
                    {
                        continue;
                    }

                    var itemData = itemDrop.m_itemData;
                    if (legendaryInfo.Requirements.CheckRequirements(itemData, dummyMagicItem))
                    {
                        allowedItems.Add(itemDrop);
                    }
                }

                itemType = allowedItems.LastOrDefault()?.name;
            }

            if (string.IsNullOrEmpty(itemType))
            {
                itemType = "Club";
            }

            var loot = new LootTable
            {
                Object = "Console",
                Drops  = new[] { new float[] { 1, 1 } },
                Loot   = new[]
                {
                    new LootDrop
                    {
                        Item   = itemType,
                        Rarity = new float[] { 0, 0, 0, 1 }
                    }
                }
            };

            LootRoller.CheatForceLegendary = legendaryID;
            var previousDisableGatingState = LootRoller.CheatDisableGating;

            LootRoller.CheatDisableGating = true;

            var randomOffset = UnityEngine.Random.insideUnitSphere;
            var dropPoint    = Player.m_localPlayer.transform.position + Player.m_localPlayer.transform.forward * 3 + Vector3.up * 1.5f + randomOffset;

            LootRoller.RollLootTableAndSpawnObjects(loot, 1, loot.Object, dropPoint);

            LootRoller.CheatForceLegendary = null;
            LootRoller.CheatDisableGating  = previousDisableGatingState;
        }
Beispiel #12
0
        public static void SpawnMagicItemWithEffect(Terminal context, string[] args)
        {
            if (args.Length < 3)
            {
                EpicLoot.LogError("Specify effect and item name");
                return;
            }

            if (Player.m_localPlayer == null)
            {
                return;
            }

            var effectArg         = args[1];
            var itemPrefabNameArg = args[2];

            context.AddString($"magicitem - {itemPrefabNameArg} with effect: {effectArg}");

            var magicItemEffectDef = MagicItemEffectDefinitions.Get(effectArg);

            if (magicItemEffectDef == null)
            {
                context.AddString($"> Could not find effect: {effectArg}");
                return;
            }

            var itemPrefab = ObjectDB.instance.GetItemPrefab(itemPrefabNameArg);

            if (itemPrefab == null)
            {
                context.AddString($"> Could not find item: {itemPrefabNameArg}");
                return;
            }

            var fromItemData = itemPrefab.GetComponent <ItemDrop>().m_itemData;

            if (!EpicLoot.CanBeMagicItem(fromItemData))
            {
                context.AddString($"> Can't be magic item: {itemPrefabNameArg}");
                return;
            }

            var effectRequirements = magicItemEffectDef.Requirements;
            var itemRarity         = effectRequirements.AllowedRarities.Count == 0 ? ItemRarity.Magic : effectRequirements.AllowedRarities.First();
            var rarityTable        = GetRarityTable(itemRarity.ToString());
            var loot = new LootTable
            {
                Object = "Console",
                Drops  = new[] { new float[] { 1, 1 } },
                Loot   = new[]
                {
                    new LootDrop
                    {
                        Item   = itemPrefab.name,
                        Rarity = rarityTable
                    }
                }
            };

            var randomOffset = UnityEngine.Random.insideUnitSphere;
            var dropPoint    = Player.m_localPlayer.transform.position + Player.m_localPlayer.transform.forward * 3 + Vector3.up * 1.5f + randomOffset;

            LootRoller.CheatForceMagicEffect = true;
            LootRoller.ForcedMagicEffect     = effectArg;
            LootRoller.RollLootTableAndSpawnObjects(loot, 1, loot.Object, dropPoint);
            LootRoller.CheatForceMagicEffect = false;
            LootRoller.ForcedMagicEffect     = string.Empty;
        }
Beispiel #13
0
        public static void Postfix()
        {
            var player = Player.m_localPlayer;

            new Terminal.ConsoleCommand("magicitem", "", (args =>
            {
                MagicItem(args.Context, args.Args);
            }), true);
            new Terminal.ConsoleCommand("mi", "", (args =>
            {
                MagicItem(args.Context, args.Args);
            }), true);
            new Terminal.ConsoleCommand("magicitemwitheffect", "", (args =>
            {
                SpawnMagicItemWithEffect(args.Context, args.Args);
            }), true);
            new Terminal.ConsoleCommand("mieffect", "", (args =>
            {
                SpawnMagicItemWithEffect(args.Context, args.Args);
            }), true);
            new Terminal.ConsoleCommand("magicitemlegendary", "", (args =>
            {
                SpawnLegendaryMagicItem(args.Context, args.Args);
            }), true);
            new Terminal.ConsoleCommand("milegend", "", (args =>
            {
                SpawnLegendaryMagicItem(args.Context, args.Args);
            }), true);
            new Terminal.ConsoleCommand("magicitemset", "", (args =>
            {
                SpawnMagicItemSet(args.Context, args.Args);
            }), true);
            new Terminal.ConsoleCommand("miset", "", (args =>
            {
                SpawnMagicItemSet(args.Context, args.Args);
            }), true);
            new Terminal.ConsoleCommand("checkstackquality", "", (args =>
            {
                CheckStackQuality(args.Context);
            }));
            new Terminal.ConsoleCommand("magicmats", "", (args =>
            {
                SpawnMagicCraftingMaterials();
            }), true);
            new Terminal.ConsoleCommand("alwaysdrop", "", (args =>
            {
                ToggleAlwaysDrop(args.Context);
            }), true);
            new Terminal.ConsoleCommand("cheatgating", "", (args =>
            {
                LootRoller.CheatDisableGating = !LootRoller.CheatDisableGating;
                args.Context.AddString($"> Disable gating for magic item drops: {LootRoller.CheatDisableGating}");
            }), true);
            new Terminal.ConsoleCommand("testtreasuremap", "", (args =>
            {
                TestTreasureMap(args.Args);
            }), true);
            new Terminal.ConsoleCommand("testtm", "", (args =>
            {
                TestTreasureMap(args.Args);
            }), true);
            new Terminal.ConsoleCommand("resettreasuremap", "", (args =>
            {
                var saveData = player.GetAdventureSaveData();
                saveData.TreasureMaps.Clear();
                saveData.NumberOfTreasureMapsOrBountiesStarted = 0;
                player.SaveAdventureSaveData();
            }));
            new Terminal.ConsoleCommand("resettm", "", (args =>
            {
                var saveData = player.GetAdventureSaveData();
                saveData.TreasureMaps.Clear();
                saveData.NumberOfTreasureMapsOrBountiesStarted = 0;
                player.SaveAdventureSaveData();
            }));
            new Terminal.ConsoleCommand("debugtreasuremap", "", (args =>
            {
                Minimap_Patch.DebugMode = !Minimap_Patch.DebugMode;
                args.Context.AddString($"> Treasure Map Debug Mode: {Minimap_Patch.DebugMode}");
            }));
            new Terminal.ConsoleCommand("debugtm", "", (args =>
            {
                Minimap_Patch.DebugMode = !Minimap_Patch.DebugMode;
                args.Context.AddString($"> Treasure Map Debug Mode: {Minimap_Patch.DebugMode}");
            }));
            new Terminal.ConsoleCommand("resetbounties", "", (args =>
            {
                var saveData = player.GetAdventureSaveData();
                saveData.Bounties.Clear();
                player.SaveAdventureSaveData();
            }));
            new Terminal.ConsoleCommand("testbountynames", "", (args =>
            {
                var random = new Random();
                var count = (args.Length >= 2) ? int.Parse(args[1]) : 10;
                for (var i = 0; i < count; ++i)
                {
                    var name = BountiesAdventureFeature.GenerateTargetName(random);
                    args.Context.AddString(name);
                }
            }));
            new Terminal.ConsoleCommand("resetadventure", "", (args =>
            {
                var adventureComponent = player.GetComponent <AdventureComponent>();
                adventureComponent.SaveData = new AdventureSaveDataList();
                player.SaveAdventureSaveData();
            }));
            new Terminal.ConsoleCommand("bounties", "", (args =>
            {
                var interval = (args.Length >= 2) ? int.Parse(args[1]) : AdventureDataManager.Bounties.GetCurrentInterval();
                var availableBounties = AdventureDataManager.Bounties.GetAvailableBounties(interval, false);
                BountiesAdventureFeature.PrintBounties($"Bounties for Interval {interval}:", availableBounties);
            }));
            new Terminal.ConsoleCommand("playerbounties", "", (args =>
            {
                var availableBounties = player.GetAdventureSaveData().Bounties;
                BountiesAdventureFeature.PrintBounties($"Player Bounties:", availableBounties);
            }));
            new Terminal.ConsoleCommand("timescale", "", (args =>
            {
                var timeScale = (args.Length >= 2) ? float.Parse(args[1]) : 1;
                Time.timeScale = timeScale;
            }), true);
            new Terminal.ConsoleCommand("ts", "", (args =>
            {
                var timeScale = (args.Length >= 2) ? float.Parse(args[1]) : 1;
                Time.timeScale = timeScale;
            }), true);
            new Terminal.ConsoleCommand("gotomerchant", "", (args =>
            {
                if (ZoneSystem.instance.FindClosestLocation("Vendor_BlackForest", player.transform.position, out var location))
                {
                    player.TeleportTo(location.m_position + Vector3.right * 5, player.transform.rotation, true);
                }
            }), true);
            new Terminal.ConsoleCommand("gotom", "", (args =>
            {
                if (ZoneSystem.instance.FindClosestLocation("Vendor_BlackForest", player.transform.position, out var location))
                {
                    player.TeleportTo(location.m_position + Vector3.right * 5, player.transform.rotation, true);
                }
            }), true);
            new Terminal.ConsoleCommand("globalkeys", "", (args =>
            {
                if (ZoneSystem.instance != null)
                {
                    args.Context.AddString("> Print Global Keys:");
                    foreach (var globalKey in ZoneSystem.instance.GetGlobalKeys())
                    {
                        args.Context.AddString("> " + globalKey);
                    }
                }
            }));
            new Terminal.ConsoleCommand("fixresistances", "", (args =>
            {
                FixResistances(player);
            }));
            new Terminal.ConsoleCommand("lucktest", "", (args =>
            {
                var lootTable = args.Length > 1 ? args[1] : "Greydwarf";
                var luckFactor = args.Length > 2 ? float.Parse(args[2]) : 0;
                LootRoller.PrintLuckTest(lootTable, luckFactor);
            }));
            new Terminal.ConsoleCommand("lootres", "", (args =>
            {
                var lootTable = args.Length > 1 ? args[1] : "Greydwarf";
                var level = args.Length > 2 ? int.Parse(args[2]) : 1;
                var itemIndex = args.Length > 3 ? int.Parse(args[3]) : 0;
                LootRoller.PrintLootResolutionTest(lootTable, level, itemIndex);
            }));
            new Terminal.ConsoleCommand("resetcooldowns", "", (args =>
            {
                if (player != null)
                {
                    var abilityController = player.GetComponent <AbilityController>();
                    if (abilityController != null)
                    {
                        foreach (var ability in abilityController.CurrentAbilities)
                        {
                            ability.ResetCooldown();
                        }
                    }
                }
            }), true);
            new Terminal.ConsoleCommand("debugluck", "", (args => {
                LootRoller.DebugLuckFactor();
            }));
        }
        public static void MagicItem(Console __instance, string[] args)
        {
            var rarityArg = args.Length >= 2 ? args[1] : "random";
            var itemArg   = args.Length >= 3 ? args[2] : "random";
            var count     = args.Length >= 4 ? int.Parse(args[3]) : 1;

            __instance.AddString($"magicitem - rarity:{rarityArg}, item:{itemArg}, count:{count}");

            var items        = new List <GameObject>();
            var allItemNames = ObjectDB.instance.m_items
                               .Where(x => EpicLoot.CanBeMagicItem(x.GetComponent <ItemDrop>().m_itemData))
                               .Select(x => x.name)
                               .ToList();

            if (Player.m_localPlayer == null)
            {
                return;
            }

            for (var i = 0; i < count; i++)
            {
                var rarityTable = new[] { 1, 1, 1, 1 };
                switch (rarityArg.ToLowerInvariant())
                {
                case "magic":
                    rarityTable = new[] { 1, 0, 0, 0, };
                    break;

                case "rare":
                    rarityTable = new[] { 0, 1, 0, 0, };
                    break;

                case "epic":
                    rarityTable = new[] { 0, 0, 1, 0, };
                    break;

                case "legendary":
                    rarityTable = new[] { 0, 0, 0, 1, };
                    break;
                }

                var item = itemArg;
                if (item == "random")
                {
                    var weightedRandomTable = new WeightedRandomCollection <string>(_random, allItemNames, x => 1);
                    item = weightedRandomTable.Roll();
                }

                if (ObjectDB.instance.GetItemPrefab(item) == null)
                {
                    __instance.AddString($"> Could not find item: {item}");
                    break;
                }

                __instance.AddString($"  {i + 1} - rarity: [{string.Join(", ", rarityTable)}], item: {item}");

                var loot = new LootTable()
                {
                    Object = "Console",
                    Drops  = new[] { new[] { 1, 1 } },
                    Loot   = new[]
                    {
                        new LootDrop()
                        {
                            Item   = item,
                            Rarity = rarityTable
                        }
                    }
                };

                var randomOffset = UnityEngine.Random.insideUnitSphere;
                var dropPoint    = Player.m_localPlayer.transform.position + Player.m_localPlayer.transform.forward * 3 + Vector3.up * 1.5f + randomOffset;
                items.AddRange(LootRoller.RollLootTableAndSpawnObjects(loot, loot.Object, dropPoint));
            }
        }