Example #1
0
 public void ReloadConfigs()
 {
     ShotPattern.LoadAll();
     BaseItem.LoadAll();
     Game.m_npcGenerator.LoadTypes(true);
     Game.m_enemyGenerator.LoadTypes();
 }
Example #2
0
    public bool CanShoot(ShotPattern p_pattern)
    {
        if (Time.timeScale == 0f)
        {
            return(false);
        }

        object active = GetPatternInfo(p_pattern, "active");

        if (m_patterns.ContainsKey(p_pattern) && active != null && (bool)active)
        {
            return(false);
        }
        if (m_patternCooldown == 0)
        {
            return(true);
        }
        if (!CanLoop(p_pattern))
        {
            return(false);
        }
        if (p_pattern.m_bypassShooterCooldown)
        {
            return(true);
        }

        return(Time.time * 1000 >= m_lastShot + m_patternCooldown * 1000);
    }
Example #3
0
    public bool CanShoot(ShotPattern p_pattern)
    {
        if (Time.timeScale == 0f)
        {
            return(false);
        }

        if (p_pattern.m_active)
        {
            return(false);
        }
        if (m_patternCooldown == 0)
        {
            return(true);
        }
        if (m_entity && GetMana() - p_pattern.m_manaPerStep < 0)
        {
            return(false);
        }
        if (!CanLoop(p_pattern))
        {
            return(false);
        }
        if (p_pattern.m_bypassShooterCooldown)
        {
            return(true);
        }

        return(Time.time >= m_lastShot + m_patternCooldown);
    }
Example #4
0
    public bool CanLoop(ShotPattern p_pattern)
    {
        object lastLoopTimeObj = GetPatternInfo(p_pattern, "lastLoopTime");
        float  patternCooldown = p_pattern.m_patternCooldown;

        return(lastLoopTimeObj == null ? true : Time.time * 1000 >= (float)lastLoopTimeObj + patternCooldown * 1000);
    }
Example #5
0
    public virtual ShotPattern Clone()
    {
        ShotPattern pattern = (ShotPattern)Activator.CreateInstance(GetType());

        pattern.m_name                   = m_name;
        pattern.m_projectile             = m_projectile;
        pattern.m_projectileInfo         = m_projectileInfo;
        pattern.m_behaviours             = m_behaviours;
        pattern.m_shots                  = m_shots;
        pattern.m_manaPerStep            = m_manaPerStep;
        pattern.m_instant                = m_instant;
        pattern.m_loop                   = m_loop;
        pattern.m_loopsBeforeSwitch      = m_loopsBeforeSwitch;
        pattern.m_patternCooldown        = m_patternCooldown;
        pattern.m_bypassShooterCooldown  = m_bypassShooterCooldown;
        pattern.m_stepDelay              = m_stepDelay;
        pattern.m_nextPatterns           = m_nextPatterns;
        pattern.m_nextPatternSwitchDelay = m_nextPatternSwitchDelay;
        pattern.m_extraTooltipInfo       = m_extraTooltipInfo;

        m_active        = false;
        m_shotsFired    = 0;
        m_loops         = 0;
        m_lastLoopTime  = 0;
        m_forcedTarget  = Vector2.zero;
        m_spawnLocation = Vector3.zero;

        return(pattern);
    }
Example #6
0
    private IEnumerator PatternStep(ShotPattern p_pattern)
    {
        while (p_pattern.m_active)
        {
            float delay = p_pattern.m_stepDelay;

            if (p_pattern.m_instant)
            {
                delay = p_pattern.Instant(this);
            }
            else
            {
                delay = p_pattern.PreStep(this);
            }

            if (delay == -1)
            {
                delay = p_pattern.m_stepDelay;
            }

            m_patternLoopTimes[p_pattern.m_name] = p_pattern.m_lastLoopTime;

            yield return(new WaitForSeconds(delay));
        }
    }
Example #7
0
    private static ShotPattern Load(string p_json)
    {
        ShotPattern pattern = JsonUtility.FromJson <ShotPattern>(p_json);
        Type        type    = null;

        if (!pattern)
        {
            return(null);
        }

        switch (pattern.m_type.ToLower())
        {
        case "circle": type = typeof(CirclePattern); break;

        case "circlesection": type = typeof(CircleSectionPattern); break;

        case "shape": type = typeof(ShapePattern); break;

        case "wave": type = typeof(WavePattern); break;
        }

        if (type == null)
        {
            return(null);
        }

        return((ShotPattern)JsonUtility.FromJson(p_json, type));
    }
Example #8
0
    public bool CanLoop(ShotPattern p_pattern)
    {
        Stats statApplied     = (Stats)Enum.Parse(typeof(Stats), p_pattern.m_projectileInfo.m_statApplied);
        float patternCooldown = p_pattern.m_patternCooldown * statApplied.GetAlternateEffect(m_entity.m_stats.GetStat(statApplied));

        return(!m_patternLoopTimes.ContainsKey(p_pattern.m_name) ? true :
               Time.time >= m_patternLoopTimes[p_pattern.m_name] + patternCooldown);
    }
Example #9
0
    public object GetPatternInfo(ShotPattern p_pattern, string p_key)
    {
        DataHolder data = null;

        bool success = m_patterns.TryGetValue(p_pattern, out data);

        return(success ? data.Get(p_key) : null);
    }
Example #10
0
    public void SetPatternInfo(ShotPattern p_pattern, string p_key, object p_value)
    {
        if (!m_patterns.ContainsKey(p_pattern))
        {
            m_patterns.Add(p_pattern, new DataHolder());
        }

        m_patterns[p_pattern].Set(p_key, p_value);
    }
Example #11
0
    public void StopShooting(ShotPattern p_pattern)
    {
        SetPatternInfo(p_pattern, "active", false);

        if (p_pattern.m_nextPatterns.Count > 0)
        {
            StartCoroutine(Transition(p_pattern));
        }
    }
    public override void Die(Projectile p_projectile)
    {
        if (Random.Range(0f, 100f) <= m_chanceToExplode && !p_projectile.m_shooter.m_entity.m_isDead)
        {
            ShotPattern pattern = ShotPattern.Get(m_explosionPattern, false);

            pattern.m_spawnLocation = p_projectile.transform.position;
            p_projectile.m_shooter.Shoot(pattern);
        }
    }
Example #13
0
    public static ShotPattern Get(string p_name, bool p_reference)
    {
        List <ShotPattern> availablePatterns = m_useExternalPatterns ? m_combinedPatterns : m_patterns;
        ShotPattern        found             = availablePatterns.Find(sp => sp.m_name == p_name);

        if (found)
        {
            return(p_reference ? found : found.Clone());
        }

        return(null);
    }
Example #14
0
    public override void Use(Entity p_entity, int p_trainingLevel)
    {
        ShotPattern pattern = ShotPattern.Get(m_shotPatterns.Find(s => s.TrainingLevel == p_trainingLevel).Pattern, false);

        if (m_aimAtCursor)
        {
            pattern.m_forcedTarget = Camera.main.ScreenToWorldPoint((p_entity as Player).m_mouse.GetPosition());
        }

        pattern.m_manaPerStep = 0;

        p_entity.m_shooter.Shoot(pattern);
    }
Example #15
0
        public void TestChange()
        {
            ShotPatterns patterns = ShotPatterns.Create(new ShotPattern(0, Vector2.Zero, Effects.None));
            ShotPattern  p        = null;

            foreach (ShotPattern pattern in patterns)
            {
                p = pattern;
            }
            foreach (ShotPattern pattern in patterns)
            {
                Assert.AreNotSame(p, pattern, "ShotPattern can be edited externally.");
            }
        }
Example #16
0
    public bool ConsumeMana(ShotPattern p_pattern)
    {
        if (!m_entity)
        {
            return(true);
        }
        if (p_pattern.m_manaPerStep > 0 && GetMana() - p_pattern.m_manaPerStep < 0)
        {
            return(false);
        }

        m_entity.m_stats.AddModifier(Stats.MP, (int)-p_pattern.m_manaPerStep, 0);
        m_shotEvent.Invoke();

        return(true);
    }
Example #17
0
    public void StopShooting(ShotPattern p_pattern)
    {
        if (!m_patterns.Contains(p_pattern))
        {
            return;
        }

        p_pattern.m_active = false;
        m_patterns.Remove(p_pattern);

        m_patternLoopTimes[p_pattern.m_name] = p_pattern.m_lastLoopTime;

        if (p_pattern.m_nextPatterns.Count > 0)
        {
            StartCoroutine(Transition(p_pattern));
        }
    }
Example #18
0
    public void Shoot(ShotPattern p_pattern)
    {
        if (!CanShoot(p_pattern))
        {
            return;
        }

        m_lastShot = Time.time;

        m_patterns.Add(p_pattern);

        p_pattern.m_shotsFired = 0;
        p_pattern.m_loops      = 0;
        p_pattern.Init(this);
        p_pattern.m_active = true;

        StartCoroutine(PatternStep(p_pattern));
    }
Example #19
0
    private void Shoot(StateController p_controller)
    {
        ShotPattern        pattern  = ShotPattern.Get(m_patternToShoot, false);
        List <ShotPattern> patterns = new List <ShotPattern>();

        if (p_controller.m_shotPatterns.ContainsKey(this))
        {
            p_controller.m_shotPatterns.TryGetValue(this, out patterns);
        }

        patterns.Add(pattern);
        p_controller.m_shotPatterns[this] = patterns;

        if (m_forceTarget)
        {
            pattern.m_forcedTarget = p_controller.m_target.transform.position;
        }

        p_controller.m_entity.m_shooter.Shoot(pattern);
    }
Example #20
0
    public override string GetDescription(int p_trainingLevel, bool p_translate)
    {
        ShotPattern pattern     = ShotPattern.Get(m_shotPatterns.Find(s => s.TrainingLevel == p_trainingLevel).Pattern, true);
        string      description = m_descriptions.Find(d => d.TrainingLevel == p_trainingLevel).Description;

        if (p_translate)
        {
            description = Game.m_languages.GetLine(description);
        }

        return(description.Replace("{damage}", pattern.m_projectileInfo.m_damage.ToString())
               .Replace("{manaPerStep}", pattern.m_manaPerStep.ToString())
               .Replace("{manaCost}", m_manaCosts.Find(m => m.TrainingLevel == p_trainingLevel).Value.ToString())
               .Replace("{cooldown}", m_cooldowns.Find(m => m.TrainingLevel == p_trainingLevel).Value.ToString())
               .Replace("{shots}", pattern.m_shots.ToString())
               .Replace("{statApplied}", pattern.m_projectileInfo.m_statApplied.ToString())
               .Replace("{range}", pattern.m_projectileInfo.m_range.ToString())
               .Replace("{speed}", pattern.m_projectileInfo.m_speed.ToString())
               .Replace("{newLine}", "\n"));
    }
Example #21
0
    public void Shoot(ShotPattern p_pattern)
    {
        if (!CanShoot(p_pattern))
        {
            return;
        }

        m_lastShot = Time.time * 1000;

        if (!m_patterns.ContainsKey(p_pattern))
        {
            m_patterns.Add(p_pattern, new DataHolder());
        }

        SetPatternInfo(p_pattern, "shotsFired", 0);
        SetPatternInfo(p_pattern, "loops", 0);
        p_pattern.Init(this);
        SetPatternInfo(p_pattern, "active", true);

        StartCoroutine(PatternStep(p_pattern));
    }
Example #22
0
    public override void Use(Entity p_entity, string[] p_args)
    {
        if (p_args.Length == 0)
        {
            return;
        }

        bool        useLeft = p_args[0].ToLower() == "true";  // left or right, case insensitive
        ShotPattern pattern = ShotPattern.Get(useLeft ? m_leftClickPattern : m_rightClickPattern, false);

        if (pattern != null)
        {
            if (p_args.Length >= 2)
            {
                if (p_args[1].ToLower() == "true" && p_entity is Player)
                {
                    pattern.m_forcedTarget = Camera.main.ScreenToWorldPoint(((Player)p_entity).m_mouse.GetPosition());
                }
            }

            p_entity.m_shooter.Shoot(pattern);
        }
    }
Example #23
0
    private IEnumerator PatternStep(ShotPattern p_pattern)
    {
        while ((bool)GetPatternInfo(p_pattern, "active"))
        {
            float delay = p_pattern.m_stepDelay;

            if (p_pattern.m_instant)
            {
                delay = p_pattern.Instant(this);
            }
            else
            {
                delay = p_pattern.PreStep(this);
            }

            if (delay == -1)
            {
                delay = p_pattern.m_stepDelay;
            }

            yield return(new WaitForSeconds(delay));
        }
    }
Example #24
0
    void Update()
    {
        string fireButton = "Primary Fire";

        if (m_input.m_controllerId > 0)
        {
            fireButton += m_input.m_controllerId;
        }

        bool fire = Game.m_keybinds.GetButton(fireButton, m_input);

        if (fire)
        {
            ShotPattern toFire = m_shooter.GetCurrentPattern();

            if (toFire == null)
            {
                return;
            }

            m_shooter.SetPatternInfo(toFire, "forcedTarget", new Vector2(transform.position.x, transform.position.y + 1));
            m_shooter.Shoot(toFire);
        }
    }
Example #25
0
    static Game()
    {
        GameObject game = SafeFind("_app");

        m_setManager         = (PersistentSetManager)SafeComponent(game, "PersistentSetManager");
        m_options            = (OptionManager)SafeComponent(game, "OptionManager");
        m_languages          = (LanguageManager)SafeComponent(game, "LanguageManager");
        m_audio              = (AudioManager)SafeComponent(game, "AudioManager");
        m_projPool           = (ProjectilePooler)SafeComponent(SafeFind("ProjectilePooler"), "ProjectilePooler");
        m_npcGenerator       = (NPCGenerator)SafeComponent(game, "NPCGenerator");
        m_enemyGenerator     = (EnemyGenerator)SafeComponent(game, "EnemyGenerator");
        m_rewiredEventSystem = (RewiredStandaloneInputModule)SafeComponent(SafeFind("Rewired Event System"), "RewiredStandaloneInputModule");
        m_controlMapper      = (ControlMapper)SafeComponent(SafeFind("ControlMapper"), "ControlMapper");
        m_controlMapperMenu  = (Menu)SafeComponent(SafeFind("Canvas"), "Menu");

        ProjectileBehaviour.LoadAll();
        ShotPattern.LoadAll();
        BaseItem.LoadAll();
        Ability.LoadAll();
        Skill.LoadAll();
        State.LoadAll();

        m_controlMapperMenu.gameObject.SetActive(false);
    }
Example #26
0
    private IEnumerator Transition(ShotPattern p_pattern)
    {
        yield return(new WaitForSeconds(p_pattern.m_nextPatternSwitchDelay));

        p_pattern.Transition(this);
    }
Example #27
0
    public static void LoadAll()
    {
        m_patterns.Clear();
        m_externalPatterns.Clear();
        m_combinedPatterns.Clear();

        foreach (TextAsset loadedPattern in Resources.LoadAll <TextAsset>("ShotPatterns"))
        {
            ShotPattern pattern = Load(loadedPattern.text);

            if (pattern)
            {
                m_patterns.Add(pattern);
            }
        }

        List <string> files = new List <string>();

        FileSearch.RecursiveRetrieval(Application.dataPath + "/Data/ShotPatterns/", ref files);

        if (files.Count > 0)
        {
            foreach (string file in files)
            {
                if (file.ToLower().EndsWith(".json"))
                {
                    StreamReader reader  = new StreamReader(file);
                    ShotPattern  pattern = Load(reader.ReadToEnd());

                    if (pattern)
                    {
                        m_externalPatterns.Add(pattern);
                    }
                    reader.Close();
                }
            }
        }

        foreach (ShotPattern pattern in m_patterns)
        {
            ShotPattern external = m_externalPatterns.Find(sp => sp.m_name == pattern.m_name);

            if (external)
            {
                m_combinedPatterns.Add(external);
            }
            else
            {
                m_combinedPatterns.Add(pattern);
            }
        }

        if (m_externalPatterns.Count > 0)
        {
            foreach (ShotPattern external in m_externalPatterns)
            {
                if (!m_patterns.Exists(sp => sp.m_name == external.m_name))
                {
                    m_combinedPatterns.Add(external);
                }
            }
        }

        // foreach(ShotPattern pattern in m_combinedPatterns)
        // then generate the mana cost for each of them
    }
Example #28
0
    private void ShowShotPattern(float p_shotNumber, ShotPattern p_pattern, ref float p_panelHeight)
    {
        string shot           = "Shot " + p_shotNumber;
        string prefixColorTag = "<color=#" + ColorUtility.ToHtmlStringRGBA(Constants.YELLOW) + ">";
        string suffixColorTag = "</color>";

        TextMeshProUGUI cd = m_modifiableInfo.Find(ti => ti.m_name == shot + " CD").GetAligned <TextMeshProUGUI>(ref m_tooltipInfoOffset);

        cd.text  = Game.m_languages.FormatTexts(Get("{0}s cooldown"), prefixColorTag + p_pattern.m_patternCooldown.ToString() + suffixColorTag);
        cd.color = Constants.WHITE;

        string statColor = ColorUtility.ToHtmlStringRGBA(((Stats)Enum.Parse(typeof(Stats), p_pattern.m_projectileInfo.m_statApplied)).GetColor());

        m_modifiableInfo.Find(ti => ti.m_name == shot + " Label").Get <TextMeshProUGUI>(ref p_panelHeight, ref m_tooltipInfoOffset).text =
            Game.m_languages.FormatTexts(Get("Shot {0}"), p_shotNumber.ToString()) +
            " (+<color=#" + statColor + ">" +
            p_pattern.m_projectileInfo.m_statApplied.ToString() + "</color>)";

        if (p_pattern.m_projectileInfo.m_piercing)
        {
            m_modifiableInfo.Find(ti => ti.m_name == shot + " Piercing Text").GetAligned <TextMeshProUGUI>(ref m_tooltipInfoOffset).color = Constants.PURPLE;
        }

        m_modifiableInfo.Find(ti => ti.m_name == shot + " Background").GetAligned <Image>(ref m_tooltipInfoOffset);
        Image shotSprite = m_modifiableInfo.Find(ti => ti.m_name == shot + " Sprite").Get <Image>();

        shotSprite.sprite = Projectile.Get(p_pattern.m_projectile).GetComponent <SpriteRenderer>().sprite;

        TextMeshProUGUI shots = m_modifiableInfo.Find(ti => ti.m_name == shot + " Shots").Get <TextMeshProUGUI>(ref p_panelHeight, ref m_tooltipInfoOffset);

        shots.text  = Game.m_languages.FormatTexts(Get("Shots: {0}"), prefixColorTag + p_pattern.m_shots.ToString() + suffixColorTag);
        shots.color = Constants.WHITE;

        if (p_pattern.m_projectileInfo.m_armorPiercing)
        {
            m_modifiableInfo.Find(ti => ti.m_name == shot + " Armor Piercing Text")
            .GetAligned <TextMeshProUGUI>(ref m_tooltipInfoOffset).color = Constants.RED;
        }

        TextMeshProUGUI damage = m_modifiableInfo.Find(ti => ti.m_name == shot + " Damage").Get <TextMeshProUGUI>(ref p_panelHeight, ref m_tooltipInfoOffset);

        damage.text  = Game.m_languages.FormatTexts(Get("Damage: {0}"), prefixColorTag + p_pattern.m_projectileInfo.m_damage.ToString() + suffixColorTag);
        damage.color = Constants.WHITE;

        Sprite damageTypeIcon = DamageType.Get(p_pattern.m_projectileInfo.m_damageType).m_icon;

        if (damageTypeIcon)
        {
            Image damageType = m_modifiableInfo.Find(ti => ti.m_name == shot + " DamageType").Get <Image>();
            damageType.sprite = damageTypeIcon;
        }

        TextMeshProUGUI mana = m_modifiableInfo.Find(ti => ti.m_name == shot + " Mana").GetAligned <TextMeshProUGUI>(ref m_tooltipInfoOffset);

        mana.text  = Game.m_languages.FormatTexts(Get("{0} Mana"), p_pattern.m_manaPerStep.ToString());
        mana.color = Constants.MANA_BLUE;

        TextMeshProUGUI range = m_modifiableInfo.Find(ti => ti.m_name == shot + " Range").Get <TextMeshProUGUI>(ref p_panelHeight, ref m_tooltipInfoOffset);

        range.text  = Game.m_languages.FormatTexts(Get("Range: {0}"), prefixColorTag + p_pattern.m_projectileInfo.m_range.ToString() + suffixColorTag);
        range.color = Constants.WHITE;

        if (p_pattern.m_extraTooltipInfo.Length > 0)
        {
            TooltipInfo     extraInfo = m_modifiableInfo.Find(ti => ti.m_name == shot + " Extra Text");
            TextMeshProUGUI extra     = extraInfo.Get <TextMeshProUGUI>();
            extra.text = "";

            float basePrefHeight = LayoutUtility.GetPreferredHeight(extra.rectTransform);

            extra.text  = Get(p_pattern.m_extraTooltipInfo);
            extra.color = Constants.YELLOW;

            float extraPrefHeight = LayoutUtility.GetPreferredHeight(extra.rectTransform);
            if (basePrefHeight != extraPrefHeight)  // multiline
            {
                m_tooltipInfoOffset += extra.rectTransform.rect.y;
                m_tooltipInfoOffset += extraPrefHeight / 1.15f;

                // original 1.7f (pre-tmp)
                extra                = extraInfo.Get <TextMeshProUGUI>(ref m_panelHeight, ref m_tooltipInfoOffset, extraPrefHeight * 1.6f);
                m_panelHeight       -= extraPrefHeight * 1.6f - extraPrefHeight;
                m_tooltipInfoOffset -= extra.rectTransform.rect.y / 2;
            }
            else
            {
                extra = extraInfo.Get <TextMeshProUGUI>(ref m_panelHeight, ref m_tooltipInfoOffset);
            }
        }
    }
Example #29
0
    public void SetItem(Item p_item)
    {
        Entity holder = p_item.m_holder ? p_item.m_holder : p_item.m_inventory.m_interactor;

        if (m_modifiableInfo.Count == 0)
        {
            FillModifiableInfo();
        }

        foreach (TooltipInfo info in m_modifiableInfo)
        {
            info.m_info.SetActive(false);
        }

        m_panelHeight       = m_tooltipBorderSize * 2 + 12;
        m_tooltipInfoOffset = -(m_panelHeight / 2);
        BaseItem item = p_item.m_item;

        Show(m_panelHeight, true); // activating the tooltip (out of sight) to allow preferred heights to be fetched

        TextMeshProUGUI name = m_modifiableInfo.Find(ti => ti.m_name == "Item Name Text").Get <TextMeshProUGUI>(ref m_panelHeight, ref m_tooltipInfoOffset);

        name.text  = Get(item.GetDisplayName());
        name.color = item.m_nameColor.Value;

        if (item is Armor || item is Weapon)
        {
            TextMeshProUGUI type     = m_modifiableInfo.Find(ti => ti.m_name == "Item Type Text").GetAligned <TextMeshProUGUI>(ref m_tooltipInfoOffset);
            string          itemType = "";

            if (item is Armor)
            {
                itemType = (item as Armor).GetArmorType().ToString();
            }
            if (item is Weapon)
            {
                itemType = (item as Weapon).GetWeaponType().ToString();
            }

            type.text = Get(itemType);
        }

        TextMeshProUGUI slot = m_modifiableInfo.Find(ti => ti.m_name == "Slot Info Text").Get <TextMeshProUGUI>(ref m_panelHeight, ref m_tooltipInfoOffset);

        slot.text = Get(item.GetSlotInfoText());

        ShowSeparator(1);

        bool leftShotPattern  = false;
        bool rightShotPattern = false;

        if (item is Weapon)
        {
            Weapon weapon = item as Weapon;

            leftShotPattern = !String.IsNullOrEmpty(weapon.m_leftClickPattern) && ShotPattern.Get(weapon.m_leftClickPattern, true) != null;

            if (leftShotPattern)
            {
                ShowShotPattern(1, ShotPattern.Get(weapon.m_leftClickPattern, true), ref m_panelHeight);
                ShowSeparator(2);

                rightShotPattern = !String.IsNullOrEmpty(weapon.m_rightClickPattern) && ShotPattern.Get(weapon.m_rightClickPattern, true) != null;

                if (rightShotPattern)
                {
                    ShowShotPattern(2, ShotPattern.Get(weapon.m_rightClickPattern, true), ref m_panelHeight);
                    ShowSeparator(3);
                }
            }
        }

        if (item is Weapon || item is Armor)
        {
            int[] statGains = item is Weapon ? (item as Weapon).m_statGainValues : (item as Armor).m_statGainValues;

            if (statGains.Length == UnitStats.STAT_AMOUNT)
            {
                TextMeshProUGUI statGainText          = m_modifiableInfo.Find(ti => ti.m_name == "Stat Gain Text").Get <TextMeshProUGUI>();
                TextMeshProUGUI statComparisonOneText = m_modifiableInfo.Find(ti => ti.m_name == "Stat Comparison 1").Get <TextMeshProUGUI>();
                TextMeshProUGUI statComparisonTwoText = m_modifiableInfo.Find(ti => ti.m_name == "Stat Comparison 2").Get <TextMeshProUGUI>();
                int[]           comparisonOne         = item.m_equipmentSlots.Count >= 1 ?
                                                        BaseItem.GetStatGainDifferences(item, holder.m_equipment, item.m_equipmentSlots[0]) : new int[UnitStats.STAT_AMOUNT];
                int[] comparisonTwo = item.m_equipmentSlots.Count == 2 ?
                                      BaseItem.GetStatGainDifferences(item, holder.m_equipment, item.m_equipmentSlots[1]) : new int[UnitStats.STAT_AMOUNT];

                if (p_item.m_inventory == holder.m_equipment)
                {
                    comparisonOne = new int[UnitStats.STAT_AMOUNT];
                    comparisonTwo = new int[UnitStats.STAT_AMOUNT];
                }

                for (int i = 0; i < statGains.Length; ++i)
                {
                    if (statGains[i] == 0 && comparisonOne[i] == 0 && comparisonTwo[i] == 0)
                    {
                        continue;
                    }
                    if (!m_modifiableInfo.Exists(ti => ti.m_name == ((Stats)i).ToString() + " Gain Text"))
                    {
                        InstantiateStatText(((Stats)i).ToString() + " Gain Text", statGainText, transform);
                    }

                    TextMeshProUGUI statGain = m_modifiableInfo.Find(ti => ti.m_name == ((Stats)i).ToString() + " Gain Text")
                                               .Get <TextMeshProUGUI>(ref m_panelHeight, ref m_tooltipInfoOffset);
                    if (!m_modifiableInfo.Exists(ti => ti.m_name == ((Stats)i).ToString() + " Comparison 1"))
                    {
                        InstantiateStatText(((Stats)i).ToString() + " Comparison 1", statComparisonOneText, statGain.transform);
                    }
                    if (!m_modifiableInfo.Exists(ti => ti.m_name == ((Stats)i).ToString() + " Comparison 2"))
                    {
                        InstantiateStatText(((Stats)i).ToString() + " Comparison 2", statComparisonTwoText, statGain.transform);
                    }

                    TextMeshProUGUI statComparisonOne = m_modifiableInfo.Find(ti => ti.m_name == ((Stats)i).ToString() + " Comparison 1")
                                                        .Get <TextMeshProUGUI>();
                    TextMeshProUGUI statComparisonTwo = m_modifiableInfo.Find(ti => ti.m_name == ((Stats)i).ToString() + " Comparison 2")
                                                        .Get <TextMeshProUGUI>();

                    statGain.color = statGains[i] > 0 ? Constants.GREEN : (statGains[i] == 0 ? Constants.YELLOW : Constants.RED);
                    statGain.text  = (statGains[i] > 0 ? "+" : "") + statGains[i] + " " + ((Stats)i).ToString();

                    if (comparisonOne[i] != 0)
                    {
                        statComparisonOne.color = comparisonOne[i] > 0 ? Constants.GREEN : Constants.RED;
                        statComparisonOne.text  = "(" + (comparisonOne[i] > 0 ? "+" : "") + comparisonOne[i] + ")";
                    }
                    else
                    {
                        statComparisonOne.text = "";
                    }

                    if (comparisonTwo[i] != 0)
                    {
                        statComparisonTwo.color = comparisonTwo[i] > 0 ? Constants.GREEN : Constants.RED;
                        statComparisonTwo.text  = "(" + (comparisonTwo[i] > 0 ? "+" : "") + comparisonTwo[i] + ")";
                    }
                    else
                    {
                        statComparisonTwo.text = "";
                    }
                }
            }
        }

        string prefixColorTag = "<color=#" + ColorUtility.ToHtmlStringRGBA(Constants.YELLOW) + ">";
        string suffixColorTag = "</color>";

        if (item is Weapon || item is Armor)
        {
            TextMeshProUGUI durability = m_modifiableInfo.Find(ti => ti.m_name == "Durability")
                                         .Get <TextMeshProUGUI>(ref m_panelHeight, ref m_tooltipInfoOffset);
            durability.text  = Game.m_languages.FormatTexts(Get("Durability: {0}%"), prefixColorTag + p_item.m_durability + suffixColorTag);
            durability.color = Constants.WHITE;
        }

        TextMeshProUGUI sellPrice = m_modifiableInfo.Find(ti => ti.m_name == "Sell Price")
                                    .Get <TextMeshProUGUI>(ref m_panelHeight, ref m_tooltipInfoOffset);

        sellPrice.text  = Game.m_languages.FormatTexts(Get("Sell Price: {0}g"), prefixColorTag + item.m_sellPrice + suffixColorTag);
        sellPrice.color = Constants.WHITE;

        TooltipInfo     descInfo    = m_modifiableInfo.Find(ti => ti.m_name == "Item Description Text");
        TextMeshProUGUI description = descInfo.Get <TextMeshProUGUI>();

        description.text = "";

        float basePrefHeight = LayoutUtility.GetPreferredHeight(description.rectTransform);

        description.text     = Get(item.m_description);
        description.color    = Constants.YELLOW;
        m_tooltipInfoOffset += description.rectTransform.rect.y;

        float descPrefHeight = LayoutUtility.GetPreferredHeight(description.rectTransform);

        if (basePrefHeight != descPrefHeight)  // multiline
        {
            m_tooltipInfoOffset += descPrefHeight / 2f;

            description = descInfo.Get <TextMeshProUGUI>(ref m_panelHeight, ref m_tooltipInfoOffset, descPrefHeight);
        }
        else
        {
            description    = descInfo.Get <TextMeshProUGUI>(ref m_panelHeight, ref m_tooltipInfoOffset);
            m_panelHeight += basePrefHeight;
        }

        if (leftShotPattern)
        {
            PositionDamageType(1);
        }
        if (rightShotPattern)
        {
            PositionDamageType(2);
        }

        Show(m_panelHeight, false);         // resizing the panel again to fit and actually showing it
    }
	public override void Init(Projectile p_projectile) {
		m_pattern = ShotPattern.Get(m_shotPattern, false);
		m_started = false;
		m_initTime = Time.time;
	}