public void SetupBoss(Character c, BossTemplate template)
        {
            BasicResurrectSetup(c);

            MoveAndSetActive(c);

            // change light color to red
            Light light = c.GetComponent <Light>() ?? c.gameObject.AddComponent <Light>();

            light.color     = Color.red;
            light.range     = 4;
            light.intensity = 2.0f;

            // override name
            At.SetValue(template.Name, typeof(Character), c, "m_name");
            At.SetValue("", typeof(Character), c, "m_nameLocKey");

            // set HP
            float healthTarget = template.Health + (300 * (global.BossesSpawned - 1));
            Stat  maxHP        = new Stat(healthTarget);

            At.SetValue(maxHP, typeof(CharacterStats), c.Stats, "m_maxHealthStat");
            c.Stats.FullHealth();

            // start boss coroutine
            StartCoroutine(BossCoroutine(c, template));
        }
        private void SetupWeapon(Weapon weapon, BossTemplate template, float templateMod, float weaponTemplateScale)
        {
            weapon.InstantLoadWeapon();

            // set boss weapon template
            if (template != null)
            {
                At.SetValue(template.weaponDamages, typeof(WeaponStats), weapon.Stats, "BaseDamage");
                weapon.Stats.Impact += templateMod;

                for (int i = 0; i < weapon.Stats.Attacks.Count(); i++)
                {
                    List <float> stepDamage = new List <float>();
                    float        stepImpact = template.weaponImpact;

                    foreach (DamageType dtype in template.weaponDamages.List)
                    {
                        stepDamage.Add(dtype.Damage + (0.5f * templateMod));
                    }

                    global.statUtil.SetScaledDamages(weapon.Type, i, ref stepDamage, ref stepImpact);
                    weapon.Stats.Attacks[i].Damage    = stepDamage;
                    weapon.Stats.Attacks[i].Knockback = stepImpact + templateMod;

                    weapon.LoadedVisual.transform.localScale = new Vector3(1, 1, 1) * weaponTemplateScale;
                }
            }
        }
        // ============== CUSTOM NPC GEAR ===============

        private void SetupEquipment(Character c, List <int> itemIDs, BossTemplate template = null, float templateMod = 0f, float weaponTemplateScale = 1.0f)
        {
            foreach (int id in itemIDs)
            {
                Item item = ItemManager.Instance.GenerateItemNetwork(id);

                if (template != null)
                {
                    // set weapon 2H type
                    if (item is Weapon w)
                    {
                        w.TwoHand = template.TwoHandType;
                        w.Type    = template.WeaponType;
                    }
                }

                c.Inventory.TakeItem(item, false);
                At.Call(c.Inventory.Equipment, "EquipWithoutAssociating", new object[] { item, false });
                item.ProcessInit();

                if (item is Weapon weapon && weapon.Type != Weapon.WeaponType.Shield)
                {
                    SetupWeapon(weapon, template, templateMod, weaponTemplateScale);
                }
            }
        }
        // ==================== BOSS SETUP =====================

        public void SpawnBoss(BossTemplate template)
        {
            if (CharacterManager.Instance.Characters.Values
                .Find(x =>
                      x.name.ToLower().Contains("newbanditequip") &&
                      !x.name.ToLower().Contains("archer"))
                is Character c)
            {
                SetupBoss(c, template);
                StartCoroutine(global.gui.SetMessage(template.Name + " Challenges You!", 5));
            }
        }
        private void GenerateDroptable(Character c, BossTemplate template)
        {
            int b = global.BossesSpawned - 1;
            int r = UnityEngine.Random.Range(template.DropTable.MinDrops + b, template.DropTable.MaxDrops + b);

            for (int i = 0; i < r; i++)
            {
                // get the max dice value
                int maxdice = 0;
                int j;
                for (j = 0; j < template.DropTable.DroppedItems.Count; j++)
                {
                    maxdice += template.DropTable.ItemChances[j];
                }

                // generate a random roll, and check which item range it falls in
                int r2         = UnityEngine.Random.Range(0, maxdice - 1);
                int dropID     = -1;
                int currentMax = 0;

                for (j = 0; j < template.DropTable.DroppedItems.Count; j++)
                {
                    currentMax += template.DropTable.ItemChances[j]; // add the current item chance to the max value

                    if (r2 < currentMax)                             // if the roll was less than this max
                    {
                        dropID = template.DropTable.DroppedItems[j]; // set the drop ID (otherwise, increase the max value and check next item)
                        break;
                    }
                }
                if (dropID != -1)
                {
                    // generate a random quantity
                    int r3 = UnityEngine.Random.Range(template.DropTable.ItemMinQtys[j], template.DropTable.ItemMaxQtys[j]);
                    int k;
                    for (k = 0; k < r3; k++)
                    {
                        // for each quantity, spawn an take the item
                        Item item = ItemManager.Instance.GenerateItemNetwork(dropID);
                        item.transform.parent = c.Inventory.Pouch.transform;
                    }
                }
            }
        }
        private void LateUpdateBossFix(Character c, BossTemplate template)
        {
            float transformScale = Mathf.Clamp(1.1f + (0.1f * global.BossesSpawned), 1.1f, 1.6f);
            float statMod        = 5 * global.BossesSpawned;

            // transform scale
            c.transform.localScale = new Vector3(1, 1, 1) * transformScale;
            // fix UI bar pos
            c.UIBarOffSet = new Vector3(0, 1, 0) * transformScale;

            DestroyEquipment(c);

            SetupEquipment(c, global.CurrentTemplate.BossTemplate.Equipment, global.CurrentTemplate.BossTemplate, statMod, transformScale);

            // add imbue fx (just fire rag for visuals, no major damage)
            var preset = ResourcesPrefabManager.Instance.GetEffectPreset(202);

            if (preset is ImbueEffectPreset fireRag)
            {
                c.CurrentWeapon.AddImbueEffect(fireRag, 240);
            }

            // set resistances
            List <Stat> newDmgRes = new List <Stat>();

            for (int i = 0; i < 9; i++)
            {
                float resTarget = template.Resistances[i];

                resTarget = Mathf.Clamp(resTarget + statMod, resTarget, 90);

                Stat stat = new Stat(resTarget);
                newDmgRes.Add(stat);
            }
            At.SetValue(newDmgRes.ToArray(), typeof(CharacterStats), c.Stats, "m_damageResistance");

            Stat impRes = new Stat(Mathf.Clamp(template.impactRes + statMod, template.impactRes, 90));

            At.SetValue(impRes, typeof(CharacterStats), c.Stats, "m_impactResistance");

            // final fix
            c.gameObject.SetActive(false);
            c.gameObject.SetActive(true);
        }
        private IEnumerator BossCoroutine(Character c, BossTemplate template)
        {
            while (!c.IsLateInitDone)
            {
                yield return(null);
            }

            yield return(new WaitForSeconds(0.2f));

            LateUpdateBossFix(c, template);

            // wait til boss is dead
            while (c.Health > 0)
            {
                global.TimeSpentOnBosses += Time.deltaTime;
                yield return(null);
            }

            // drop table
            GenerateDroptable(c, template);

            global.BossActive = false;
            global.ShouldRest = true;
        }