예제 #1
0
        protected virtual void AddLocalizedGameString(AbilityTalentBase abilityTalentBase)
        {
            GameStringWriter.AddAbilityTalentName(abilityTalentBase.AbilityTalentId.Id, abilityTalentBase.Name);

            if (!string.IsNullOrEmpty(abilityTalentBase.Tooltip?.Life?.LifeCostTooltip?.RawDescription))
            {
                GameStringWriter.AddAbilityTalentLifeTooltip(abilityTalentBase.AbilityTalentId.Id, GetTooltip(abilityTalentBase.Tooltip.Life.LifeCostTooltip, FileOutputOptions.DescriptionType));
            }

            if (!string.IsNullOrEmpty(abilityTalentBase.Tooltip?.Energy?.EnergyTooltip?.RawDescription))
            {
                GameStringWriter.AddAbilityTalentEnergyTooltip(abilityTalentBase.AbilityTalentId.Id, GetTooltip(abilityTalentBase.Tooltip.Energy.EnergyTooltip, FileOutputOptions.DescriptionType));
            }

            if (!string.IsNullOrEmpty(abilityTalentBase.Tooltip?.Cooldown?.CooldownTooltip?.RawDescription))
            {
                GameStringWriter.AddAbilityTalentCooldownTooltip(abilityTalentBase.AbilityTalentId.Id, GetTooltip(abilityTalentBase.Tooltip.Cooldown.CooldownTooltip, FileOutputOptions.DescriptionType));
            }

            if (!string.IsNullOrEmpty(abilityTalentBase.Tooltip?.ShortTooltip?.RawDescription))
            {
                GameStringWriter.AddAbilityTalentShortTooltip(abilityTalentBase.AbilityTalentId.Id, GetTooltip(abilityTalentBase.Tooltip.ShortTooltip, FileOutputOptions.DescriptionType));
            }

            if (!string.IsNullOrEmpty(abilityTalentBase.Tooltip?.FullTooltip?.RawDescription))
            {
                GameStringWriter.AddAbilityTalentFullTooltip(abilityTalentBase.AbilityTalentId.Id, GetTooltip(abilityTalentBase.Tooltip.FullTooltip, FileOutputOptions.DescriptionType));
            }
        }
예제 #2
0
        protected void SetButtonData(XElement buttonElement, AbilityTalentBase abilityTalentBase)
        {
            if (buttonElement == null)
            {
                throw new ArgumentNullException(nameof(buttonElement));
            }
            if (abilityTalentBase == null)
            {
                throw new ArgumentNullException(nameof(abilityTalentBase));
            }

            string?parentValue = buttonElement.Attribute("parent")?.Value;

            if (!string.IsNullOrEmpty(parentValue) && parentValue != DefaultDataButton.CButtonDefaultBaseId)
            {
                XElement?parentElement = GameData.MergeXmlElements(GameData.Elements("CButton").Where(x => x.Attribute("id")?.Value == parentValue), false);
                if (parentElement != null)
                {
                    SetButtonData(parentElement, abilityTalentBase);
                }
            }

            SetTooltipDescriptions(buttonElement, abilityTalentBase);
            SetTooltipData(buttonElement, abilityTalentBase);
        }
        private void SetEffectData(XElement effectElement, AbilityTalentBase abilityTalentBase)
        {
            if (effectElement == null)
            {
                throw new ArgumentNullException(nameof(effectElement));
            }
            if (abilityTalentBase == null)
            {
                throw new ArgumentNullException(nameof(abilityTalentBase));
            }

            string effectValue = effectElement.Attribute("value")?.Value;

            if (!string.IsNullOrEmpty(effectValue))
            {
                // see if we can find a create unit
                XElement effectTypeElement = GameData.MergeXmlElements(GameData.ElementsIncluded(Configuration.GamestringXmlElements("Effect"), effectValue));
                if (effectTypeElement != null)
                {
                    foreach (XElement element in effectTypeElement.Elements())
                    {
                        string elementName = element.Name.LocalName.ToUpper();

                        if (elementName == "EFFECTARRAY" || elementName == "CASEDEFAULT" || elementName == "PRODUCEDUNITARRAY")
                        {
                            FindCreateUnit(element.Attribute("value")?.Value, abilityTalentBase);
                        }
                        else if (elementName == "CASEARRAY")
                        {
                            FindCreateUnit(element.Attribute("Effect")?.Value, abilityTalentBase);
                        }
                    }
                }
            }
        }
예제 #4
0
        /// <summary>
        /// Set the tooltip descriptions.
        /// </summary>
        /// <param name="buttonElement"></param>
        /// <param name="abilityTalentBase"></param>
        protected void SetTooltipDescriptions(XElement buttonElement, AbilityTalentBase abilityTalentBase)
        {
            if (buttonElement == null)
            {
                throw new ArgumentNullException(nameof(buttonElement));
            }
            if (abilityTalentBase == null)
            {
                throw new ArgumentNullException(nameof(abilityTalentBase));
            }

            string?buttonId = buttonElement.Attribute("id")?.Value;

            string name = GameData.GetGameString(DefaultData.ButtonData?.ButtonName?.Replace(DefaultData.IdPlaceHolder, buttonId, StringComparison.OrdinalIgnoreCase));

            if (!string.IsNullOrEmpty(name))
            {
                abilityTalentBase.Name = name;
            }

            if (string.IsNullOrEmpty(abilityTalentBase.Name))
            {
                abilityTalentBase.Name = GameData.GetGameString(DefaultData.AbilData?.AbilName.Replace(DefaultData.IdPlaceHolder, buttonId, StringComparison.OrdinalIgnoreCase));
            }

            // full
            if (DefaultData.ButtonData?.ButtonTooltip != null && GameData.TryGetGameString(DefaultData.ButtonData.ButtonTooltip.Replace(DefaultData.IdPlaceHolder, buttonId, StringComparison.OrdinalIgnoreCase), out string?fullDescription))
            {
                abilityTalentBase.Tooltip.FullTooltip = new TooltipDescription(fullDescription ?? string.Empty, Localization);
            }

            // short
            if (DefaultData.ButtonData?.ButtonSimpleDisplayText != null && GameData.TryGetGameString(DefaultData.ButtonData.ButtonSimpleDisplayText.Replace(DefaultData.IdPlaceHolder, buttonId, StringComparison.OrdinalIgnoreCase), out string?shortDescription))
            {
                abilityTalentBase.Tooltip.ShortTooltip = new TooltipDescription(shortDescription ?? string.Empty, Localization);
            }
        }
예제 #5
0
        protected override XElement AbilityTalentInfoElement(AbilityTalentBase abilityTalentBase)
        {
            if (FileOutputOptions.IsLocalizedText)
            {
                AddLocalizedGameString(abilityTalentBase);
            }

            return(new XElement(
                       XmlConvert.EncodeName(abilityTalentBase.AbilityTalentId.ReferenceId),
                       string.IsNullOrEmpty(abilityTalentBase.AbilityTalentId.ButtonId) ? null : new XAttribute("buttonId", abilityTalentBase.AbilityTalentId.ButtonId),
                       string.IsNullOrEmpty(abilityTalentBase.Name) || FileOutputOptions.IsLocalizedText ? null : new XAttribute("name", abilityTalentBase.Name),
                       new XAttribute("abilityType", abilityTalentBase.AbilityType.ToString()),
                       abilityTalentBase.IsActive ? new XAttribute("isActive", abilityTalentBase.IsActive) : null,
                       abilityTalentBase.IsPassive ? new XAttribute("isPassive", abilityTalentBase.IsPassive) : null,
                       abilityTalentBase.IsQuest ? new XAttribute("isQuest", abilityTalentBase.IsQuest) : null,
                       string.IsNullOrEmpty(abilityTalentBase.IconFileName) ? null : new XElement("Icon", Path.ChangeExtension(abilityTalentBase.IconFileName?.ToLower(), StaticImageExtension)),
                       abilityTalentBase.Tooltip.Cooldown.ToggleCooldown.HasValue ? new XElement("ToggleCooldown", abilityTalentBase.Tooltip.Cooldown.ToggleCooldown.Value) : null,
                       UnitAbilityTalentLifeCost(abilityTalentBase.Tooltip.Life),
                       UnitAbilityTalentEnergyCost(abilityTalentBase.Tooltip.Energy),
                       UnitAbilityTalentCharges(abilityTalentBase.Tooltip.Charges),
                       UnitAbilityTalentCooldown(abilityTalentBase.Tooltip.Cooldown),
                       string.IsNullOrEmpty(abilityTalentBase.Tooltip.ShortTooltip?.RawDescription) || FileOutputOptions.IsLocalizedText ? null : new XElement("ShortTooltip", GetTooltip(abilityTalentBase.Tooltip.ShortTooltip, FileOutputOptions.DescriptionType)),
                       string.IsNullOrEmpty(abilityTalentBase.Tooltip.FullTooltip?.RawDescription) || FileOutputOptions.IsLocalizedText ? null : new XElement("FullTooltip", GetTooltip(abilityTalentBase.Tooltip.FullTooltip, FileOutputOptions.DescriptionType))));
        }
        private void FindCreateUnit(string effectId, AbilityTalentBase abilityTalentBase)
        {
            if (abilityTalentBase == null)
            {
                throw new ArgumentNullException(nameof(abilityTalentBase));
            }

            if (!string.IsNullOrEmpty(effectId))
            {
                // find CEffectCreateUnit
                XElement effectCreateUnitElement = GameData.MergeXmlElements(GameData.Elements("CEffectCreateUnit").Where(x => x.Attribute("id")?.Value == effectId), false);
                if (effectCreateUnitElement != null)
                {
                    string spawnUnitValue = effectCreateUnitElement.Element("SpawnUnit")?.Attribute("value")?.Value;
                    if (!string.IsNullOrEmpty(spawnUnitValue))
                    {
                        if (GameData.Elements("CUnit").Where(x => x.Attribute("id")?.Value == spawnUnitValue).Any())
                        {
                            abilityTalentBase.AddCreatedUnit(spawnUnitValue);
                        }
                    }
                }
            }
        }
        protected override JObject AbilityTalentInfoElement(AbilityTalentBase abilityTalentBase)
        {
            if (FileOutputOptions.IsLocalizedText)
            {
                AddLocalizedGameString(abilityTalentBase);
            }

            JObject info = new JObject
            {
                { "nameId", abilityTalentBase.AbilityTalentId.ReferenceId },
            };

            if (!string.IsNullOrEmpty(abilityTalentBase.AbilityTalentId.ButtonId))
            {
                info.Add("buttonId", abilityTalentBase.AbilityTalentId.ButtonId);
            }

            if (!string.IsNullOrEmpty(abilityTalentBase.Name) && !FileOutputOptions.IsLocalizedText)
            {
                info.Add("name", abilityTalentBase.Name);
            }

            if (!string.IsNullOrEmpty(abilityTalentBase.IconFileName))
            {
                info.Add("icon", Path.ChangeExtension(abilityTalentBase.IconFileName?.ToLowerInvariant(), ".png"));
            }

            if (abilityTalentBase.Tooltip.Cooldown.ToggleCooldown.HasValue)
            {
                info.Add("toggleCooldown", abilityTalentBase.Tooltip.Cooldown.ToggleCooldown.Value);
            }

            JProperty?life = UnitAbilityTalentLifeCost(abilityTalentBase.Tooltip.Life);

            if (life != null)
            {
                info.Add(life);
            }

            JProperty?energy = UnitAbilityTalentEnergyCost(abilityTalentBase.Tooltip.Energy);

            if (energy != null)
            {
                info.Add(energy);
            }

            JProperty?charges = UnitAbilityTalentCharges(abilityTalentBase.Tooltip.Charges);

            if (charges != null)
            {
                info.Add(charges);
            }

            JProperty?cooldown = UnitAbilityTalentCooldown(abilityTalentBase.Tooltip.Cooldown);

            if (cooldown != null)
            {
                info.Add(cooldown);
            }

            if (!string.IsNullOrEmpty(abilityTalentBase.Tooltip.ShortTooltip?.RawDescription) && !FileOutputOptions.IsLocalizedText)
            {
                info.Add("shortTooltip", GetTooltip(abilityTalentBase.Tooltip.ShortTooltip, FileOutputOptions.DescriptionType));
            }

            if (!string.IsNullOrEmpty(abilityTalentBase.Tooltip.FullTooltip?.RawDescription) && !FileOutputOptions.IsLocalizedText)
            {
                info.Add("fullTooltip", GetTooltip(abilityTalentBase.Tooltip.FullTooltip, FileOutputOptions.DescriptionType));
            }

            info.Add("abilityType", abilityTalentBase.AbilityTalentId.AbilityType.ToString());

            if (abilityTalentBase.IsActive && abilityTalentBase is Talent)
            {
                info.Add("isActive", abilityTalentBase.IsActive);
            }
            else if (!abilityTalentBase.IsActive && abilityTalentBase is Ability)
            {
                info.Add("isActive", abilityTalentBase.IsActive);
            }

            if (abilityTalentBase.AbilityTalentId.IsPassive)
            {
                info.Add("isPassive", abilityTalentBase.AbilityTalentId.IsPassive);
            }

            if (abilityTalentBase.IsQuest)
            {
                info.Add("isQuest", abilityTalentBase.IsQuest);
            }

            return(info);
        }
예제 #8
0
    /// <summary>
    /// Sets the <see cref="AbilityTalentBase"/> data of the <see cref="Ability"/>.
    /// </summary>
    /// <param name="abilityTalentBase">The <see cref="AbilityTalentBase"/> data to be set.</param>
    /// <param name="abilityTalentElement">The <see cref="JsonElement"/> to read from.</param>
    /// <exception cref="ArgumentNullException"><paramref name="abilityTalentBase"/> is <see langword="null"/>.</exception>
    protected virtual void SetAbilityTalentBase(AbilityTalentBase abilityTalentBase, JsonElement abilityTalentElement)
    {
        ArgumentNullException.ThrowIfNull(abilityTalentBase, nameof(abilityTalentBase));

        abilityTalentBase.AbilityTalentId.ReferenceId = abilityTalentElement.GetProperty("nameId").GetString() ?? string.Empty;

        if (abilityTalentElement.TryGetProperty("buttonId", out JsonElement buttonElement))
        {
            abilityTalentBase.AbilityTalentId.ButtonId = buttonElement.GetString() ?? string.Empty;
        }

        if (abilityTalentElement.TryGetProperty("name", out JsonElement nameElement))
        {
            abilityTalentBase.Name = nameElement.GetString();
        }

        if (abilityTalentElement.TryGetProperty("icon", out JsonElement iconElement))
        {
            abilityTalentBase.IconFileName = iconElement.GetString();
        }
        if (abilityTalentElement.TryGetProperty("toggleCooldown", out JsonElement toggleCooldownElement))
        {
            abilityTalentBase.Tooltip.Cooldown.ToggleCooldown = toggleCooldownElement.GetDouble();
        }

        if (abilityTalentElement.TryGetProperty("lifeTooltip", out JsonElement lifeTooltipElement))
        {
            abilityTalentBase.Tooltip.Life.LifeCostTooltip = SetTooltipDescription(lifeTooltipElement.GetString(), Localization);
        }

        if (abilityTalentElement.TryGetProperty("energyTooltip", out JsonElement energyTooltipElement))
        {
            abilityTalentBase.Tooltip.Energy.EnergyTooltip = SetTooltipDescription(energyTooltipElement.GetString(), Localization);
        }

        // charges
        if (abilityTalentElement.TryGetProperty("charges", out JsonElement chargeElement))
        {
            abilityTalentBase.Tooltip.Charges.CountMax = chargeElement.GetProperty("countMax").GetInt32();

            if (chargeElement.TryGetProperty("countUse", out JsonElement countUseElement))
            {
                abilityTalentBase.Tooltip.Charges.CountUse = countUseElement.GetInt32();
            }
            if (chargeElement.TryGetProperty("countStart", out JsonElement countStartElement))
            {
                abilityTalentBase.Tooltip.Charges.CountStart = countStartElement.GetInt32();
            }
            if (chargeElement.TryGetProperty("hideCount", out JsonElement hideCountElement))
            {
                abilityTalentBase.Tooltip.Charges.IsHideCount = hideCountElement.GetBoolean();
            }
            if (chargeElement.TryGetProperty("recastCooldown", out JsonElement recastCooldownElement))
            {
                abilityTalentBase.Tooltip.Charges.RecastCooldown = recastCooldownElement.GetDouble();
            }
        }

        if (abilityTalentElement.TryGetProperty("cooldownTooltip", out JsonElement cooldownTooltipElement))
        {
            abilityTalentBase.Tooltip.Cooldown.CooldownTooltip = SetTooltipDescription(cooldownTooltipElement.GetString(), Localization);
        }

        if (abilityTalentElement.TryGetProperty("shortTooltip", out JsonElement shortTooltipElement))
        {
            abilityTalentBase.Tooltip.ShortTooltip = SetTooltipDescription(shortTooltipElement.GetString(), Localization);
        }

        if (abilityTalentElement.TryGetProperty("fullTooltip", out JsonElement fullTooltipElement))
        {
            abilityTalentBase.Tooltip.FullTooltip = SetTooltipDescription(fullTooltipElement.GetString(), Localization);
        }

        if (Enum.TryParse(abilityTalentElement.GetProperty("abilityType").GetString(), out AbilityTypes abilityTypes))
        {
            abilityTalentBase.AbilityTalentId.AbilityType = abilityTypes;
        }
        else
        {
            abilityTalentBase.AbilityTalentId.AbilityType = AbilityTypes.Unknown;
        }

        if (abilityTalentElement.TryGetProperty("isActive", out JsonElement isActiveElement))
        {
            abilityTalentBase.IsActive = isActiveElement.GetBoolean();
        }
        if (abilityTalentElement.TryGetProperty("isPassive", out JsonElement isPassiveElement))
        {
            abilityTalentBase.AbilityTalentId.IsPassive = isPassiveElement.GetBoolean();
        }
        if (abilityTalentElement.TryGetProperty("isQuest", out JsonElement isQuestElement))
        {
            abilityTalentBase.IsQuest = isQuestElement.GetBoolean();
        }
    }
예제 #9
0
 protected abstract TU AbilityTalentInfoElement(AbilityTalentBase abilityTalentBase);
예제 #10
0
 protected override void AddLocalizedGameString(AbilityTalentBase abilityTalentBase)
 {
     base.AddLocalizedGameString(abilityTalentBase);
 }
예제 #11
0
        /// <summary>
        /// Sets the ability data.
        /// </summary>
        /// <param name="abilityElement">The ability element.</param>
        /// <param name="abilityTalentBase"></param>
        /// <param name="abilIndex"></param>
        protected void SetAbilityTalentData(XElement abilityElement, AbilityTalentBase abilityTalentBase, string abilIndex)
        {
            if (abilityElement == null)
            {
                throw new ArgumentNullException(nameof(abilityElement));
            }
            if (abilityTalentBase == null)
            {
                throw new ArgumentNullException(nameof(abilityTalentBase));
            }

            // parent lookup
            string?parentValue = abilityElement.Attribute("parent")?.Value;

            if (!string.IsNullOrEmpty(parentValue))
            {
                XElement?parentElement = GameData.MergeXmlElements(GameData.Elements(abilityElement.Name.LocalName).Where(x => x.Attribute("id")?.Value == parentValue));
                if (parentElement != null)
                {
                    SetAbilityTalentData(parentElement, abilityTalentBase, abilIndex);
                }
            }

            // don't want these
            if (parentValue == "attack" || abilityElement.Name.LocalName == "CAbilAttack")
            {
                abilityTalentBase.AbilityTalentId.ReferenceId = string.Empty;
            }

            Action?setCmdButtonArrayDataAction = null;
            bool   isAutoCast   = false;
            bool   isAutoCastOn = false;

            // look through all elements to set all the data
            foreach (XElement element in abilityElement.Elements())
            {
                string elementName = element.Name.LocalName.ToUpperInvariant();

                if (elementName == "COST")
                {
                    SetCostData(element, abilityTalentBase);
                }
                else if (elementName == "EFFECT")
                {
                    SetEffectData(element, abilityTalentBase);
                }
                else if (elementName == "CMDBUTTONARRAY")
                {
                    string?indexValue = element.Attribute("index")?.Value;

                    if (!string.IsNullOrEmpty(indexValue) && abilIndex == indexValue)
                    {
                        setCmdButtonArrayDataAction = () => SetCmdButtonArrayData(element, abilityTalentBase);
                    }
                    else if (!string.IsNullOrEmpty(indexValue))
                    {
                        // only set if index is execute
                        // cancel is also an available index, but it doesn't seem to be used in HOTS
                        if (indexValue.Equals("Execute", StringComparison.OrdinalIgnoreCase))
                        {
                            setCmdButtonArrayDataAction = () => SetCmdButtonArrayData(element, abilityTalentBase);
                        }
                    }
                }
                else if (elementName == "PRODUCEDUNITARRAY")
                {
                    string?elementValue = element.Attribute("value")?.Value;

                    if (!string.IsNullOrEmpty(elementValue))
                    {
                        if (GameData.Elements("CUnit").Where(x => x.Attribute("id")?.Value == elementValue).Any())
                        {
                            abilityTalentBase.CreatedUnits.Add(elementValue);
                        }
                    }
                }
                else if (elementName == "NAME") // ability name
                {
                    string?valueAttribute = element.Attribute("value")?.Value;

                    if (string.IsNullOrEmpty(abilityTalentBase.Name) && !string.IsNullOrEmpty(valueAttribute) && GameData.TryGetGameString(valueAttribute, out string?value))
                    {
                        abilityTalentBase.Name = value;
                    }
                }
                else if (elementName == "PARENTABIL")
                {
                    string?parentAbilityValue = element.Attribute("value")?.Value;
                    if (!string.IsNullOrEmpty(parentAbilityValue))
                    {
                        XElement?parentAbilityElement = GetAbilityElements(parentAbilityValue).FirstOrDefault();
                        if (parentAbilityElement != null)
                        {
                            string?defaultButtonFace = parentAbilityElement.Element("CmdButtonArray")?.Attribute("DefaultButtonFace")?.Value;

                            abilityTalentBase.ParentLink = new AbilityTalentId(parentAbilityValue, defaultButtonFace ?? parentAbilityValue);
                        }
                    }
                }
                else if (elementName == "FLAGS")
                {
                    string?index = element.Attribute("index")?.Value.ToUpperInvariant();

                    if (index == "AUTOCAST" && element.Attribute("value")?.Value == "1")
                    {
                        isAutoCast = true;
                    }
                    else if (index == "AUTOCASTON" && element.Attribute("value")?.Value == "1")
                    {
                        isAutoCastOn = true;
                    }
                }
            }

            if (isAutoCast && isAutoCastOn)
            {
                abilityTalentBase.IsActive = false;
            }

            // must execute the cmdButtonArrayData last
            setCmdButtonArrayDataAction?.Invoke();
        }
예제 #12
0
        /// <summary>
        /// Set all element data found in the button element.
        /// </summary>
        /// <param name="buttonElement"></param>
        /// <param name="abilityTalentBase"></param>
        protected void SetTooltipData(XElement buttonElement, AbilityTalentBase abilityTalentBase)
        {
            if (buttonElement == null)
            {
                throw new ArgumentNullException(nameof(buttonElement));
            }
            if (abilityTalentBase == null)
            {
                throw new ArgumentNullException(nameof(abilityTalentBase));
            }

            string defaultEnergyValue = GameData.GetGameString(DefaultData.HeroEnergyTypeManaText);

            // "UI/Tooltip/Abil/<Type>
            string?vitalEnergyValueTextTemp;
            string?vitalLifeValueTextTemp;

            string overrideTextTemp = string.Empty;

            // look through each element to set overrides
            foreach (XElement element in buttonElement.Elements())
            {
                string elementName = element.Name.LocalName.ToUpperInvariant();

                if (elementName == "NAME")
                {
                    abilityTalentBase.Name = GameData.GetGameString(element.Attribute("value")?.Value);
                }
                else if (elementName == "ICON")
                {
                    abilityTalentBase.IconFileName = Path.GetFileName(PathHelper.GetFilePath(element.Attribute("value")?.Value)) ?? string.Empty;
                }
                else if (elementName == "TOOLTIP")
                {
                    string?fullTooltipValue = element.Attribute("value")?.Value;

                    if (!string.IsNullOrEmpty(fullTooltipValue) && GameData.TryGetGameString(fullTooltipValue, out string?fullDescription))
                    {
                        abilityTalentBase.Tooltip.FullTooltip = new TooltipDescription(fullDescription ?? string.Empty, Localization);
                    }
                }
                else if (elementName == "SIMPLEDISPLAYTEXT")
                {
                    string?shortTooltipValue = element.Attribute("value")?.Value;

                    if (!string.IsNullOrEmpty(shortTooltipValue) && GameData.TryGetGameString(shortTooltipValue, out string?shortDescription))
                    {
                        abilityTalentBase.Tooltip.ShortTooltip = new TooltipDescription(shortDescription ?? string.Empty, Localization);
                    }
                }
                else if (elementName == "TOOLTIPVITALNAME")
                {
                    string?index = element.Attribute("index")?.Value;

                    if (index == "Energy")
                    {
                        vitalEnergyValueTextTemp = element.Attribute("value")?.Value;

                        if (string.IsNullOrEmpty(vitalEnergyValueTextTemp))
                        {
                            abilityTalentBase.Tooltip.Energy.EnergyTooltip = null;
                        }
                        else if (GameData.TryGetGameString(vitalEnergyValueTextTemp, out string?overrideVitalName))
                        {
                            if (string.IsNullOrEmpty(abilityTalentBase.Tooltip.Energy.EnergyTooltip?.RawDescription))
                            {
                                abilityTalentBase.Tooltip.Energy.EnergyTooltip = new TooltipDescription(overrideVitalName !);
                            }
                            else if (overrideVitalName !.Contains(DefaultData.ReplacementCharacter, StringComparison.OrdinalIgnoreCase) && abilityTalentBase.Tooltip.Energy.EnergyValue.HasValue)
                            {
                                abilityTalentBase.Tooltip.Energy.EnergyTooltip = new TooltipDescription(overrideVitalName.Replace(DefaultData.ReplacementCharacter, abilityTalentBase.Tooltip.Energy.EnergyValue.ToString(), StringComparison.OrdinalIgnoreCase));
                            }
                            else if (overrideVitalName.Contains(DefaultData.ReplacementCharacter, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(abilityTalentBase.Tooltip.Energy.EnergyTooltip.RawDescription) && !overrideTextTemp !.StartsWith(defaultEnergyValue, StringComparison.OrdinalIgnoreCase))
                            {
                                if (string.IsNullOrEmpty(overrideTextTemp))
                                {
                                    abilityTalentBase.Tooltip.Energy.EnergyTooltip = new TooltipDescription(string.Empty);
                                }
                                else
                                {
                                    abilityTalentBase.Tooltip.Energy.EnergyTooltip = new TooltipDescription(overrideVitalName.Replace(DefaultData.ReplacementCharacter, overrideTextTemp, StringComparison.OrdinalIgnoreCase));
                                }
                            }
                        }
                    }
                    else if (index == "Life")
                    {
                        vitalLifeValueTextTemp = element.Attribute("value")?.Value;

                        if (string.IsNullOrEmpty(vitalLifeValueTextTemp))
                        {
                            abilityTalentBase.Tooltip.Life.LifeCostTooltip = null;
                        }
                        else if (GameData.TryGetGameString(vitalLifeValueTextTemp, out string?overrideVitalName))
                        {
                            if (string.IsNullOrEmpty(abilityTalentBase.Tooltip.Life.LifeCostTooltip?.RawDescription))
                            {
                                abilityTalentBase.Tooltip.Life.LifeCostTooltip = new TooltipDescription(overrideVitalName !);
                            }
                            else if (overrideVitalName !.Contains(DefaultData.ReplacementCharacter, StringComparison.OrdinalIgnoreCase))
                            {
                                abilityTalentBase.Tooltip.Life.LifeCostTooltip = new TooltipDescription(overrideVitalName.Replace(DefaultData.ReplacementCharacter, abilityTalentBase.Tooltip.Life.LifeValue.ToString(), StringComparison.OrdinalIgnoreCase));
                            }
                            else
                            {
                                abilityTalentBase.Tooltip.Life.LifeCostTooltip = new TooltipDescription(overrideVitalName.Replace(DefaultData.ReplacementCharacter, abilityTalentBase.Tooltip.Life.LifeCostTooltip.RawDescription, StringComparison.OrdinalIgnoreCase));
                            }
                        }
                    }
                }
        private void SetCmdButtonArrayData(XElement cmdButtonArrayElement, AbilityTalentBase abilityTalentBase)
        {
            if (cmdButtonArrayElement == null)
            {
                throw new ArgumentNullException(nameof(cmdButtonArrayElement));
            }
            if (abilityTalentBase == null)
            {
                throw new ArgumentNullException(nameof(abilityTalentBase));
            }

            string defaultButtonFace = cmdButtonArrayElement.Attribute("DefaultButtonFace")?.Value ?? cmdButtonArrayElement.Element("DefaultButtonFace")?.Attribute("value")?.Value;
            string requirement       = cmdButtonArrayElement.Attribute("Requirements")?.Value ?? cmdButtonArrayElement.Element("Requirements")?.Attribute("value")?.Value;

            if (string.IsNullOrEmpty(abilityTalentBase.AbilityTalentId.ButtonId))
            {
                abilityTalentBase.AbilityTalentId.ButtonId = defaultButtonFace;
            }

            // check only the face value (fullTooltipNameId), we could also check the defaultButtonFace but it was chosen not to
            XElement buttonElement = GameData.MergeXmlElements(GameData.Elements("CButton")?.Where(x => x.Attribute("id")?.Value == abilityTalentBase.AbilityTalentId.ButtonId), false);

            if (buttonElement != null)
            {
                SetButtonData(buttonElement, abilityTalentBase);
            }

            if (!string.IsNullOrEmpty(requirement))
            {
                if (requirement == "HeroHasNoDeadBehaviorAndNotInBase")
                {
                    return;
                }

                if (requirement == "IsMounted")
                {
                    abilityTalentBase.ParentLink = new AbilityTalentId("Mount", "SummonMount"); // ability id of the standard Mount ability
                    return;
                }

                XElement requirementElement = GameData.MergeXmlElements(GameData.Elements("CRequirement").Where(x => x.Attribute("id")?.Value == requirement));
                if (requirementElement != null)
                {
                    foreach (XElement element in requirementElement.Elements())
                    {
                        string elementName = element.Name.LocalName.ToUpper();

                        if (elementName == "NODEARRAY")
                        {
                            string indexValue = element.Attribute("index")?.Value;
                            string linkValue  = element.Attribute("Link")?.Value;

                            if (linkValue == "EqCountBehaviorHeroGenericPregameAbilitySuppressionCompleteOnlyAtUnit0")
                            {
                                return;
                            }

                            if (linkValue == "0")
                            {
                                abilityTalentBase.AbilityTalentId.ReferenceId = string.Empty;
                                return;
                            }
                        }
                    }
                }
            }
        }
        private void SetCostData(XElement costElement, AbilityTalentBase abilityTalentBase)
        {
            if (costElement == null)
            {
                throw new ArgumentNullException(nameof(costElement));
            }
            if (abilityTalentBase == null)
            {
                throw new ArgumentNullException(nameof(abilityTalentBase));
            }

            XElement chargeElement = costElement.Element("Charge");

            if (chargeElement != null)
            {
                XElement countMaxElement   = chargeElement.Element("CountMax");
                XElement countStartElement = chargeElement.Element("CountStart");
                XElement countUseElement   = chargeElement.Element("CountUse");
                XElement hideCountElement  = chargeElement.Element("HideCount");
                XElement timeUseElement    = chargeElement.Element("TimeUse");

                // as attributes
                if (countMaxElement != null || countStartElement != null || countUseElement != null || hideCountElement != null || timeUseElement != null)
                {
                    if (countMaxElement != null)
                    {
                        abilityTalentBase.Tooltip.Charges.CountMax = int.Parse(GameData.GetValueFromAttribute(countMaxElement.Attribute("value").Value));
                    }

                    if (countStartElement != null)
                    {
                        abilityTalentBase.Tooltip.Charges.CountStart = int.Parse(GameData.GetValueFromAttribute(countStartElement.Attribute("value").Value));
                    }

                    if (countUseElement != null)
                    {
                        abilityTalentBase.Tooltip.Charges.CountUse = int.Parse(GameData.GetValueFromAttribute(countUseElement.Attribute("value").Value));
                    }

                    if (hideCountElement != null)
                    {
                        abilityTalentBase.Tooltip.Charges.IsHideCount = int.Parse(GameData.GetValueFromAttribute(hideCountElement.Attribute("value").Value)) == 1 ? true : false;
                    }

                    if (timeUseElement != null)
                    {
                        string cooldownValue = GameData.GetValueFromAttribute(timeUseElement.Attribute("value").Value);

                        string replaceText;
                        if (abilityTalentBase.Tooltip.Charges.CountMax.HasValue && abilityTalentBase.Tooltip.Charges.CountMax.Value > 1)
                        {
                            replaceText = GameData.GetGameString(DefaultData.StringChargeCooldownColon); // Charge Cooldown:<space>
                        }
                        else
                        {
                            replaceText = GameData.GetGameString(DefaultData.StringCooldownColon); // Cooldown:<space>
                        }
                        if (cooldownValue == "1")
                        {
                            abilityTalentBase.Tooltip.Cooldown.CooldownTooltip = new TooltipDescription(GameData.GetGameString(DefaultData.AbilTooltipCooldownText)
                                                                                                        .Replace(GameData.GetGameString(DefaultData.StringCooldownColon), replaceText)
                                                                                                        .Replace(DefaultData.ReplacementCharacter, cooldownValue));
                        }
                        else
                        {
                            abilityTalentBase.Tooltip.Cooldown.CooldownTooltip = new TooltipDescription(GameData.GetGameString(DefaultData.AbilTooltipCooldownPluralText)
                                                                                                        .Replace(GameData.GetGameString(DefaultData.StringCooldownColon), replaceText)
                                                                                                        .Replace(DefaultData.ReplacementCharacter, cooldownValue));
                        }
                    }
                }
                else // as elements
                {
                    XAttribute countMaxAttribute   = chargeElement.Attribute("CountMax");
                    XAttribute countStartAttribute = chargeElement.Attribute("CountStart");
                    XAttribute countUseAttribute   = chargeElement.Attribute("CountUse");
                    XAttribute hideCountAttribute  = chargeElement.Attribute("HideCount");
                    XAttribute timeUseAttribute    = chargeElement.Attribute("TimeUse");
                    if (countMaxAttribute != null)
                    {
                        abilityTalentBase.Tooltip.Charges.CountMax = int.Parse(GameData.GetValueFromAttribute(countMaxAttribute.Value));
                    }

                    if (countStartAttribute != null)
                    {
                        abilityTalentBase.Tooltip.Charges.CountStart = int.Parse(GameData.GetValueFromAttribute(countStartAttribute.Value));
                    }

                    if (countUseAttribute != null)
                    {
                        abilityTalentBase.Tooltip.Charges.CountUse = int.Parse(GameData.GetValueFromAttribute(countUseAttribute.Value));
                    }

                    if (hideCountAttribute != null)
                    {
                        abilityTalentBase.Tooltip.Charges.IsHideCount = int.Parse(GameData.GetValueFromAttribute(hideCountAttribute.Value)) == 1 ? true : false;
                    }

                    if (timeUseAttribute != null)
                    {
                        string cooldownValue = timeUseAttribute.Value;

                        string replaceText;
                        if (abilityTalentBase.Tooltip.Charges.CountMax.HasValue && abilityTalentBase.Tooltip.Charges.CountMax.Value > 1)
                        {
                            replaceText = GameData.GetGameString(DefaultData.StringChargeCooldownColon); // Charge Cooldown:<space>
                        }
                        else
                        {
                            replaceText = GameData.GetGameString(DefaultData.StringCooldownColon); // Cooldown:<space>
                        }
                        if (!string.IsNullOrEmpty(cooldownValue))
                        {
                            if (cooldownValue == "1")
                            {
                                abilityTalentBase.Tooltip.Cooldown.CooldownTooltip = new TooltipDescription(GameData.GetGameString(DefaultData.AbilTooltipCooldownText)
                                                                                                            .Replace(GameData.GetGameString(DefaultData.StringCooldownColon), replaceText)
                                                                                                            .Replace(DefaultData.ReplacementCharacter, cooldownValue));
                            }
                            else
                            {
                                abilityTalentBase.Tooltip.Cooldown.CooldownTooltip = new TooltipDescription(GameData.GetGameString(DefaultData.AbilTooltipCooldownPluralText)
                                                                                                            .Replace(GameData.GetGameString(DefaultData.StringCooldownColon), replaceText)
                                                                                                            .Replace(DefaultData.ReplacementCharacter, cooldownValue));
                            }
                        }
                    }
                }
            }

            // cooldown
            XElement cooldownElement = costElement.Element("Cooldown");

            if (cooldownElement != null)
            {
                string cooldownValue = GameData.GetValueFromAttribute(cooldownElement.Attribute("TimeUse")?.Value);
                if (!string.IsNullOrEmpty(cooldownValue))
                {
                    if (abilityTalentBase.Tooltip.Charges.HasCharges)
                    {
                        abilityTalentBase.Tooltip.Charges.RecastCooldown = double.Parse(cooldownValue);
                    }
                    else
                    {
                        double cooldown = double.Parse(cooldownValue);

                        if (cooldown == 1)
                        {
                            abilityTalentBase.Tooltip.Cooldown.CooldownTooltip = new TooltipDescription(GameData.GetGameString(DefaultData.AbilTooltipCooldownText).Replace(DefaultData.ReplacementCharacter, cooldownValue));
                        }
                        else if (cooldown >= 1)
                        {
                            abilityTalentBase.Tooltip.Cooldown.CooldownTooltip = new TooltipDescription(GameData.GetGameString(DefaultData.AbilTooltipCooldownPluralText).Replace(DefaultData.ReplacementCharacter, cooldownValue));
                        }

                        if (cooldown < 1)
                        {
                            abilityTalentBase.Tooltip.Cooldown.ToggleCooldown = cooldown;
                        }
                    }
                }
            }

            // vitals
            XElement vitalElement = costElement.Element("Vital");

            if (vitalElement != null)
            {
                string vitalIndex = GameData.GetValueFromAttribute(vitalElement.Attribute("index").Value);
                string vitalValue = GameData.GetValueFromAttribute(vitalElement.Attribute("value").Value);

                if (vitalIndex == "Energy")
                {
                    abilityTalentBase.Tooltip.Energy.EnergyValue   = double.Parse(vitalValue);
                    abilityTalentBase.Tooltip.Energy.EnergyTooltip = new TooltipDescription(DescriptionValidator.Validate(GameData.GetGameString(DefaultData.ButtonData.ButtonTooltipEnergyVitalName).Replace(DefaultData.ReplacementCharacter, vitalValue)));
                }
            }
        }
        /// <summary>
        /// Set all element data found in the button element.
        /// </summary>
        /// <param name="abilityTalentBase"></param>
        protected void SetTooltipData(XElement buttonElement, AbilityTalentBase abilityTalentBase)
        {
            if (buttonElement == null)
            {
                throw new ArgumentNullException(nameof(buttonElement));
            }
            if (abilityTalentBase == null)
            {
                throw new ArgumentNullException(nameof(abilityTalentBase));
            }

            string defaultEnergyValue = GameData.GetGameString(DefaultData.HeroEnergyTypeManaText);

            // "UI/Tooltip/Abil/<Type>
            string vitalEnergyValueTextTemp;
            string vitalLifeValueTextTemp;

            string overrideTextTemp = string.Empty;

            // look through each element to set overrides
            foreach (XElement element in buttonElement.Elements())
            {
                string elementName = element.Name.LocalName.ToUpper();

                if (elementName == "NAME")
                {
                    abilityTalentBase.Name = GameData.GetGameString(element.Attribute("value").Value);
                }
                else if (elementName == "ICON")
                {
                    abilityTalentBase.IconFileName = Path.GetFileName(PathHelper.GetFilePath(element.Attribute("value").Value));
                }
                else if (elementName == "TOOLTIP")
                {
                    string fullTooltipValue = element.Attribute("value").Value;

                    if (GameData.TryGetGameString(fullTooltipValue, out string fullDescription))
                    {
                        abilityTalentBase.Tooltip.FullTooltip = new TooltipDescription(fullDescription, Localization);
                    }
                }
                else if (elementName == "SIMPLEDISPLAYTEXT")
                {
                    string shortTooltipValue = element.Attribute("value").Value;

                    if (GameData.TryGetGameString(shortTooltipValue, out string shortDescription))
                    {
                        abilityTalentBase.Tooltip.ShortTooltip = new TooltipDescription(shortDescription, Localization);
                    }
                }
                else if (elementName == "TOOLTIPVITALNAME")
                {
                    string index = element.Attribute("index")?.Value;

                    if (index == "Energy")
                    {
                        vitalEnergyValueTextTemp = element.Attribute("value").Value;

                        if (string.IsNullOrEmpty(vitalEnergyValueTextTemp))
                        {
                            abilityTalentBase.Tooltip.Energy.EnergyTooltip = null;
                        }
                        else if (GameData.TryGetGameString(vitalEnergyValueTextTemp, out string overrideVitalName))
                        {
                            if (string.IsNullOrEmpty(abilityTalentBase.Tooltip.Energy.EnergyTooltip?.RawDescription))
                            {
                                abilityTalentBase.Tooltip.Energy.EnergyTooltip = new TooltipDescription(DescriptionValidator.Validate(overrideVitalName));
                            }
                            else if (overrideVitalName.Contains(DefaultData.ReplacementCharacter) && abilityTalentBase.Tooltip.Energy.EnergyValue.HasValue)
                            {
                                abilityTalentBase.Tooltip.Energy.EnergyTooltip = new TooltipDescription(DescriptionValidator.Validate(overrideVitalName.Replace(DefaultData.ReplacementCharacter, abilityTalentBase.Tooltip.Energy.EnergyValue.ToString())));
                            }
                            else if (overrideVitalName.Contains(DefaultData.ReplacementCharacter) && !string.IsNullOrEmpty(abilityTalentBase.Tooltip.Energy.EnergyTooltip.RawDescription) && !overrideTextTemp.StartsWith(defaultEnergyValue))
                            {
                                if (string.IsNullOrEmpty(overrideTextTemp))
                                {
                                    abilityTalentBase.Tooltip.Energy.EnergyTooltip = new TooltipDescription(string.Empty);
                                }
                                else
                                {
                                    abilityTalentBase.Tooltip.Energy.EnergyTooltip = new TooltipDescription(DescriptionValidator.Validate(overrideVitalName.Replace(DefaultData.ReplacementCharacter, overrideTextTemp)));
                                }
                            }
                        }
                    }
                    else if (index == "Life")
                    {
                        vitalLifeValueTextTemp = element.Attribute("value").Value;

                        if (string.IsNullOrEmpty(vitalLifeValueTextTemp))
                        {
                            abilityTalentBase.Tooltip.Life.LifeCostTooltip = null;
                        }
                        else if (GameData.TryGetGameString(vitalLifeValueTextTemp, out string overrideVitalName))
                        {
                            if (string.IsNullOrEmpty(abilityTalentBase.Tooltip.Life.LifeCostTooltip?.RawDescription))
                            {
                                abilityTalentBase.Tooltip.Life.LifeCostTooltip = new TooltipDescription(DescriptionValidator.Validate(overrideVitalName));
                            }
                            else if (overrideVitalName.Contains(DefaultData.ReplacementCharacter))
                            {
                                abilityTalentBase.Tooltip.Life.LifeCostTooltip = new TooltipDescription(DescriptionValidator.Validate(overrideVitalName.Replace(DefaultData.ReplacementCharacter, abilityTalentBase.Tooltip.Life.LifeValue.ToString())));
                            }
                            else
                            {
                                abilityTalentBase.Tooltip.Life.LifeCostTooltip = new TooltipDescription(DescriptionValidator.Validate(overrideVitalName.Replace(DefaultData.ReplacementCharacter, abilityTalentBase.Tooltip.Life.LifeCostTooltip.RawDescription)));
                            }
                        }
                    }
                }
                else if (elementName == "TOOLTIPVITALOVERRIDETEXT")
                {
                    if (GameData.TryGetGameString(element.Attribute("value").Value, out string text))
                    {
                        if (element.Attribute("index")?.Value == "Energy")
                        {
                            // check if overriding text starts with the energy text
                            if (!new TooltipDescription(DescriptionValidator.Validate(text)).PlainText.StartsWith(defaultEnergyValue))
                            {
                                if (GameData.TryGetGameString(DefaultData.ButtonData.ButtonTooltipEnergyVitalName, out string energyText)) // default
                                {
                                    overrideTextTemp = text;
                                    text             = DescriptionValidator.Validate(energyText.Replace(DefaultData.ReplacementCharacter, text));
                                }
                            }

                            abilityTalentBase.Tooltip.Energy.EnergyTooltip = new TooltipDescription(text);
                        }
                        else if (element.Attribute("index")?.Value == "Life")
                        {
                            abilityTalentBase.Tooltip.Life.LifeCostTooltip = new TooltipDescription(DescriptionValidator.Validate(abilityTalentBase.Tooltip.Life.LifeCostTooltip.RawDescription.Replace(DefaultData.ReplacementCharacter, text)));
                        }
                    }
                }
                else if (elementName == "TOOLTIPCOOLDOWNOVERRIDETEXT")
                {
                    string overrideValueText = element.Attribute("value").Value;
                    if (GameData.TryGetGameString(overrideValueText, out string text))
                    {
                        if (!text.StartsWith(GameData.GetGameString(DefaultData.StringCooldownColon)))
                        {
                            text = $"{GameData.GetGameString(DefaultData.StringCooldownColon)}{text}";
                        }

                        abilityTalentBase.Tooltip.Cooldown.CooldownTooltip = new TooltipDescription(DescriptionValidator.Validate(text));
                    }
                }
                else if (elementName == "TOOLTIPFLAGS")
                {
                    string index = element.Attribute("index").Value;

                    if (index == "ShowName" && element.Attribute("value").Value == "0")
                    {
                        abilityTalentBase.Name = string.Empty;
                    }
                    else if (index == "ShowHotkey")
                    {
                    }
                    else if (index == "ShowUsage" && element.Attribute("value").Value == "0")
                    {
                        abilityTalentBase.Tooltip.Life.LifeCostTooltip = null;
                        abilityTalentBase.Tooltip.Energy.EnergyTooltip = null;
                    }
                    else if (index == "ShowTime")
                    {
                    }
                    else if (index == "ShowCooldown" && element.Attribute("value").Value == "0")
                    {
                        // ignore, always show the cooldown
                    }
                    else if (index == "ShowRequirements")
                    {
                    }
                    else if (index == "ShowAutocast")
                    {
                    }
                }
            }

            // check if the life and energy string contain the replacement character
            if (abilityTalentBase.Tooltip.Life?.LifeCostTooltip != null && abilityTalentBase.Tooltip.Life.LifeCostTooltip.RawDescription.Contains(DefaultData.ReplacementCharacter))
            {
                abilityTalentBase.Tooltip.Life.LifeCostTooltip = null;
            }
            if (abilityTalentBase.Tooltip.Energy?.EnergyTooltip != null && abilityTalentBase.Tooltip.Energy.EnergyTooltip.RawDescription.Contains(DefaultData.ReplacementCharacter))
            {
                abilityTalentBase.Tooltip.Energy.EnergyTooltip = null;
            }
        }