예제 #1
0
        public void LoadFromHeroLab(XmlNode xmlStatBlockBaseNode)
        {
            Timekeeper.Start("load_char_attrib");
            foreach (CharacterAttrib objAttribute in AttributeList.Concat(SpecialAttributeList))
            {
                objAttribute.UnbindAttribute();
            }
            AttributeList.Clear();
            SpecialAttributeList.Clear();
            XmlDocument objXmlDocument  = XmlManager.Load(_objCharacter.IsCritter ? "critters.xml" : "metatypes.xml");
            XmlNode     xmlMetatypeNode = objXmlDocument.SelectSingleNode("/chummer/metatypes/metatype[name = \"" + _objCharacter.Metatype + "\"]");
            XmlNode     xmlCharNode     = xmlMetatypeNode?.SelectSingleNode("metavariants/metavariant[name = \"" + _objCharacter.Metavariant + "\"]") ?? xmlMetatypeNode;
            // We only want to remake attributes for shifters in career mode, because they only get their second set of attributes when exporting from create mode into career mode
            XmlNode xmlCharNodeAnimalForm = _objCharacter.MetatypeCategory == "Shapeshifter" && _objCharacter.Created ? xmlMetatypeNode : null;

            foreach (string strAttribute in AttributeStrings)
            {
                // First, remake the attribute

                CharacterAttrib objAttribute = null;
                switch (CharacterAttrib.ConvertToAttributeCategory(strAttribute))
                {
                case CharacterAttrib.AttributeCategory.Special:
                    objAttribute = new CharacterAttrib(_objCharacter, strAttribute, CharacterAttrib.AttributeCategory.Special);
                    objAttribute = RemakeAttribute(objAttribute, xmlCharNode);
                    SpecialAttributeList.Add(objAttribute);
                    break;

                case CharacterAttrib.AttributeCategory.Standard:
                    objAttribute = new CharacterAttrib(_objCharacter, strAttribute, CharacterAttrib.AttributeCategory.Standard);
                    objAttribute = RemakeAttribute(objAttribute, xmlCharNode);
                    AttributeList.Add(objAttribute);
                    break;
                }
                if (xmlCharNodeAnimalForm != null)
                {
                    switch (CharacterAttrib.ConvertToAttributeCategory(strAttribute))
                    {
                    case CharacterAttrib.AttributeCategory.Special:
                        objAttribute = new CharacterAttrib(_objCharacter, strAttribute, CharacterAttrib.AttributeCategory.Special);
                        objAttribute = RemakeAttribute(objAttribute, xmlCharNodeAnimalForm);
                        SpecialAttributeList.Add(objAttribute);
                        break;

                    case CharacterAttrib.AttributeCategory.Shapeshifter:
                        objAttribute = new CharacterAttrib(_objCharacter, strAttribute, CharacterAttrib.AttributeCategory.Shapeshifter);
                        objAttribute = RemakeAttribute(objAttribute, xmlCharNodeAnimalForm);
                        AttributeList.Add(objAttribute);
                        break;
                    }
                }

                // Then load in attribute karma levels (we'll adjust these later if the character is in Create mode)
                if (strAttribute == "ESS") // Not Essence though, this will get modified automatically instead of having its value set to the one HeroLab displays
                {
                    continue;
                }
                XmlNode xmlHeroLabAttributeNode = xmlStatBlockBaseNode.SelectSingleNode("attributes/attribute[@name = \"" + GetAttributeEnglishName(strAttribute) + "\"]");
                XmlNode xmlAttributeBaseNode    = xmlHeroLabAttributeNode?.SelectSingleNode("@base");
                if (xmlAttributeBaseNode != null &&
                    int.TryParse(xmlAttributeBaseNode.InnerText, out int intHeroLabAttributeBaseValue))
                {
                    int intAttributeMinimumValue = GetAttributeByName(strAttribute).MetatypeMinimum;
                    if (intHeroLabAttributeBaseValue == intAttributeMinimumValue)
                    {
                        continue;
                    }
                    if (objAttribute != null)
                    {
                        objAttribute.Karma = intHeroLabAttributeBaseValue - intAttributeMinimumValue;
                    }
                }
            }

            if (!_objCharacter.Created && _objCharacter.BuildMethodHasSkillPoints)
            {
                // Allocate Attribute Points
                int             intAttributePointCount = _objCharacter.TotalAttributes;
                CharacterAttrib objAttributeToPutPointsInto;
                // First loop through attributes where costs can be 100% covered with points
                do
                {
                    objAttributeToPutPointsInto = null;
                    int intAttributeToPutPointsIntoTotalKarmaCost = 0;
                    foreach (CharacterAttrib objLoopAttribute in AttributeList)
                    {
                        if (objLoopAttribute.Karma == 0)
                        {
                            continue;
                        }
                        // Put points into the attribute with the highest total karma cost.
                        // In case of ties, pick the one that would need more points to cover it (the other one will hopefully get picked up at a later cycle)
                        int intLoopTotalKarmaCost = objLoopAttribute.TotalKarmaCost;
                        if (objAttributeToPutPointsInto == null || (objLoopAttribute.Karma <= intAttributePointCount &&
                                                                    (intLoopTotalKarmaCost > intAttributeToPutPointsIntoTotalKarmaCost ||
                                                                     (intLoopTotalKarmaCost == intAttributeToPutPointsIntoTotalKarmaCost && objLoopAttribute.Karma > objAttributeToPutPointsInto.Karma))))
                        {
                            objAttributeToPutPointsInto = objLoopAttribute;
                            intAttributeToPutPointsIntoTotalKarmaCost = intLoopTotalKarmaCost;
                        }
                    }

                    if (objAttributeToPutPointsInto != null)
                    {
                        objAttributeToPutPointsInto.Base  = objAttributeToPutPointsInto.Karma;
                        intAttributePointCount           -= objAttributeToPutPointsInto.Karma;
                        objAttributeToPutPointsInto.Karma = 0;
                    }
                } while (objAttributeToPutPointsInto != null && intAttributePointCount > 0);

                // If any points left over, then put them all into the attribute with the highest karma cost
                if (intAttributePointCount > 0 && AttributeList.Any(x => x.Karma != 0))
                {
                    int intHighestTotalKarmaCost = 0;
                    foreach (CharacterAttrib objLoopAttribute in AttributeList)
                    {
                        if (objLoopAttribute.Karma == 0)
                        {
                            continue;
                        }
                        // Put points into the attribute with the highest total karma cost.
                        // In case of ties, pick the one that would need more points to cover it (the other one will hopefully get picked up at a later cycle)
                        int intLoopTotalKarmaCost = objLoopAttribute.TotalKarmaCost;
                        if (objAttributeToPutPointsInto == null ||
                            intLoopTotalKarmaCost > intHighestTotalKarmaCost ||
                            (intLoopTotalKarmaCost == intHighestTotalKarmaCost && objLoopAttribute.Karma > objAttributeToPutPointsInto.Karma))
                        {
                            objAttributeToPutPointsInto = objLoopAttribute;
                            intHighestTotalKarmaCost    = intLoopTotalKarmaCost;
                        }
                    }

                    if (objAttributeToPutPointsInto != null)
                    {
                        objAttributeToPutPointsInto.Base   = intAttributePointCount;
                        objAttributeToPutPointsInto.Karma -= intAttributePointCount;
                    }
                }

                // Allocate Special Attribute Points
                intAttributePointCount = _objCharacter.TotalSpecial;
                // First loop through attributes where costs can be 100% covered with points
                do
                {
                    objAttributeToPutPointsInto = null;
                    int intAttributeToPutPointsIntoTotalKarmaCost = 0;
                    foreach (CharacterAttrib objLoopAttribute in SpecialAttributeList)
                    {
                        if (objLoopAttribute.Karma == 0)
                        {
                            continue;
                        }
                        // Put points into the attribute with the highest total karma cost.
                        // In case of ties, pick the one that would need more points to cover it (the other one will hopefully get picked up at a later cycle)
                        int intLoopTotalKarmaCost = objLoopAttribute.TotalKarmaCost;
                        if (objAttributeToPutPointsInto == null || (objLoopAttribute.Karma <= intAttributePointCount &&
                                                                    (intLoopTotalKarmaCost > intAttributeToPutPointsIntoTotalKarmaCost ||
                                                                     (intLoopTotalKarmaCost == intAttributeToPutPointsIntoTotalKarmaCost && objLoopAttribute.Karma > objAttributeToPutPointsInto.Karma))))
                        {
                            objAttributeToPutPointsInto = objLoopAttribute;
                            intAttributeToPutPointsIntoTotalKarmaCost = intLoopTotalKarmaCost;
                        }
                    }

                    if (objAttributeToPutPointsInto != null)
                    {
                        objAttributeToPutPointsInto.Base  = objAttributeToPutPointsInto.Karma;
                        intAttributePointCount           -= objAttributeToPutPointsInto.Karma;
                        objAttributeToPutPointsInto.Karma = 0;
                    }
                } while (objAttributeToPutPointsInto != null);

                // If any points left over, then put them all into the attribute with the highest karma cost
                if (intAttributePointCount > 0 && SpecialAttributeList.Any(x => x.Karma != 0))
                {
                    int intHighestTotalKarmaCost = 0;
                    foreach (CharacterAttrib objLoopAttribute in SpecialAttributeList)
                    {
                        if (objLoopAttribute.Karma == 0)
                        {
                            continue;
                        }
                        // Put points into the attribute with the highest total karma cost.
                        // In case of ties, pick the one that would need more points to cover it (the other one will hopefully get picked up at a later cycle)
                        int intLoopTotalKarmaCost = objLoopAttribute.TotalKarmaCost;
                        if (objAttributeToPutPointsInto == null ||
                            intLoopTotalKarmaCost > intHighestTotalKarmaCost ||
                            (intLoopTotalKarmaCost == intHighestTotalKarmaCost && objLoopAttribute.Karma > objAttributeToPutPointsInto.Karma))
                        {
                            objAttributeToPutPointsInto = objLoopAttribute;
                            intHighestTotalKarmaCost    = intLoopTotalKarmaCost;
                        }
                    }

                    if (objAttributeToPutPointsInto != null)
                    {
                        objAttributeToPutPointsInto.Base   = intAttributePointCount;
                        objAttributeToPutPointsInto.Karma -= intAttributePointCount;
                    }
                }
            }
            ResetBindings();
            _objCharacter.RefreshAttributeBindings();
            Timekeeper.Finish("load_char_attrib");
        }
예제 #2
0
        public void Create(XmlNode charNode, int intValue, int intMinModifier = 0, int intMaxModifier = 0)
        {
            Timekeeper.Start("create_char_attrib");
            foreach (CharacterAttrib objAttribute in AttributeList.Concat(SpecialAttributeList))
            {
                objAttribute.UnbindAttribute();
            }
            AttributeList.Clear();
            SpecialAttributeList.Clear();

            foreach (string strAttribute in AttributeStrings)
            {
                CharacterAttrib objAttribute;
                switch (CharacterAttrib.ConvertToAttributeCategory(strAttribute))
                {
                case CharacterAttrib.AttributeCategory.Special:
                    objAttribute = new CharacterAttrib(_objCharacter, strAttribute, CharacterAttrib.AttributeCategory.Special);
                    SpecialAttributeList.Add(objAttribute);
                    break;

                case CharacterAttrib.AttributeCategory.Standard:
                    objAttribute = new CharacterAttrib(_objCharacter, strAttribute, CharacterAttrib.AttributeCategory.Standard);
                    AttributeList.Add(objAttribute);
                    break;
                }
            }

            _objCharacter.BOD.AssignLimits(CommonFunctions.ExpressionToString(charNode["bodmin"]?.InnerText, intValue, intMinModifier), CommonFunctions.ExpressionToString(charNode["bodmax"]?.InnerText, intValue, intMaxModifier), CommonFunctions.ExpressionToString(charNode["bodaug"]?.InnerText, intValue, intMaxModifier));
            _objCharacter.AGI.AssignLimits(CommonFunctions.ExpressionToString(charNode["agimin"]?.InnerText, intValue, intMinModifier), CommonFunctions.ExpressionToString(charNode["agimax"]?.InnerText, intValue, intMaxModifier), CommonFunctions.ExpressionToString(charNode["agiaug"]?.InnerText, intValue, intMaxModifier));
            _objCharacter.REA.AssignLimits(CommonFunctions.ExpressionToString(charNode["reamin"]?.InnerText, intValue, intMinModifier), CommonFunctions.ExpressionToString(charNode["reamax"]?.InnerText, intValue, intMaxModifier), CommonFunctions.ExpressionToString(charNode["reaaug"]?.InnerText, intValue, intMaxModifier));
            _objCharacter.STR.AssignLimits(CommonFunctions.ExpressionToString(charNode["strmin"]?.InnerText, intValue, intMinModifier), CommonFunctions.ExpressionToString(charNode["strmax"]?.InnerText, intValue, intMaxModifier), CommonFunctions.ExpressionToString(charNode["straug"]?.InnerText, intValue, intMaxModifier));
            _objCharacter.CHA.AssignLimits(CommonFunctions.ExpressionToString(charNode["chamin"]?.InnerText, intValue, intMinModifier), CommonFunctions.ExpressionToString(charNode["chamax"]?.InnerText, intValue, intMaxModifier), CommonFunctions.ExpressionToString(charNode["chaaug"]?.InnerText, intValue, intMaxModifier));
            _objCharacter.INT.AssignLimits(CommonFunctions.ExpressionToString(charNode["intmin"]?.InnerText, intValue, intMinModifier), CommonFunctions.ExpressionToString(charNode["intmax"]?.InnerText, intValue, intMaxModifier), CommonFunctions.ExpressionToString(charNode["intaug"]?.InnerText, intValue, intMaxModifier));
            _objCharacter.LOG.AssignLimits(CommonFunctions.ExpressionToString(charNode["logmin"]?.InnerText, intValue, intMinModifier), CommonFunctions.ExpressionToString(charNode["logmax"]?.InnerText, intValue, intMaxModifier), CommonFunctions.ExpressionToString(charNode["logaug"]?.InnerText, intValue, intMaxModifier));
            _objCharacter.WIL.AssignLimits(CommonFunctions.ExpressionToString(charNode["wilmin"]?.InnerText, intValue, intMinModifier), CommonFunctions.ExpressionToString(charNode["wilmax"]?.InnerText, intValue, intMaxModifier), CommonFunctions.ExpressionToString(charNode["wilaug"]?.InnerText, intValue, intMaxModifier));
            _objCharacter.MAG.AssignLimits(CommonFunctions.ExpressionToString(charNode["magmin"]?.InnerText, intValue, intMinModifier), CommonFunctions.ExpressionToString(charNode["magmax"]?.InnerText, intValue, intMaxModifier), CommonFunctions.ExpressionToString(charNode["magaug"]?.InnerText, intValue, intMaxModifier));
            _objCharacter.RES.AssignLimits(CommonFunctions.ExpressionToString(charNode["resmin"]?.InnerText, intValue, intMinModifier), CommonFunctions.ExpressionToString(charNode["resmax"]?.InnerText, intValue, intMaxModifier), CommonFunctions.ExpressionToString(charNode["resaug"]?.InnerText, intValue, intMaxModifier));
            _objCharacter.EDG.AssignLimits(CommonFunctions.ExpressionToString(charNode["edgmin"]?.InnerText, intValue, intMinModifier), CommonFunctions.ExpressionToString(charNode["edgmax"]?.InnerText, intValue, intMaxModifier), CommonFunctions.ExpressionToString(charNode["edgaug"]?.InnerText, intValue, intMaxModifier));
            _objCharacter.DEP.AssignLimits(CommonFunctions.ExpressionToString(charNode["depmin"]?.InnerText, intValue, intMinModifier), CommonFunctions.ExpressionToString(charNode["depmax"]?.InnerText, intValue, intMaxModifier), CommonFunctions.ExpressionToString(charNode["depaug"]?.InnerText, intValue, intMaxModifier));
            _objCharacter.MAGAdept.AssignLimits(CommonFunctions.ExpressionToString(charNode["magmin"]?.InnerText, intValue, intMinModifier), CommonFunctions.ExpressionToString(charNode["magmax"]?.InnerText, intValue, intMaxModifier), CommonFunctions.ExpressionToString(charNode["magaug"]?.InnerText, intValue, intMaxModifier));
            _objCharacter.ESS.AssignLimits(CommonFunctions.ExpressionToString(charNode["essmin"]?.InnerText, intValue, 0), CommonFunctions.ExpressionToString(charNode["essmax"]?.InnerText, intValue, 0), CommonFunctions.ExpressionToString(charNode["essaug"]?.InnerText, intValue, 0));

            Attributes = new ObservableCollection <CharacterAttrib>
            {
                _objCharacter.BOD,
                _objCharacter.AGI,
                _objCharacter.REA,
                _objCharacter.STR,
                _objCharacter.CHA,
                _objCharacter.INT,
                _objCharacter.LOG,
                _objCharacter.WIL,
                _objCharacter.EDG
            };
            if (_objCharacter.MAGEnabled)
            {
                Attributes.Add(_objCharacter.MAG);
                if (_objCharacter.Options.MysAdeptSecondMAGAttribute && _objCharacter.IsMysticAdept)
                {
                    Attributes.Add(_objCharacter.MAGAdept);
                }
            }
            if (_objCharacter.RESEnabled)
            {
                Attributes.Add(_objCharacter.RES);
            }
            if (_objCharacter.DEPEnabled)
            {
                Attributes.Add(_objCharacter.DEP);
            }
            ResetBindings();
            _objCharacter.RefreshAttributeBindings();
            Timekeeper.Finish("create_char_attrib");
        }
예제 #3
0
        public void Load(XmlNode xmlSavedCharacterNode)
        {
            Timekeeper.Start("load_char_attrib");
            foreach (CharacterAttrib objAttribute in AttributeList.Concat(SpecialAttributeList))
            {
                objAttribute.UnbindAttribute();
            }
            AttributeList.Clear();
            SpecialAttributeList.Clear();
            XmlDocument objXmlDocument  = XmlManager.Load(_objCharacter.IsCritter ? "critters.xml" : "metatypes.xml");
            XmlNode     xmlMetatypeNode = objXmlDocument.SelectSingleNode("/chummer/metatypes/metatype[name = \"" + _objCharacter.Metatype + "\"]");
            XmlNode     xmlCharNode     = xmlMetatypeNode?.SelectSingleNode("metavariants/metavariant[name = \"" + _objCharacter.Metavariant + "\"]") ?? xmlMetatypeNode;
            // We only want to remake attributes for shifters in career mode, because they only get their second set of attributes when exporting from create mode into career mode
            XmlNode xmlCharNodeAnimalForm = _objCharacter.MetatypeCategory == "Shapeshifter" && _objCharacter.Created ? xmlMetatypeNode : null;

            foreach (string strAttribute in AttributeStrings)
            {
                XmlNodeList lstAttributeNodes = xmlSavedCharacterNode.SelectNodes("attributes/attribute[name = \"" + strAttribute + "\"]");
                // Couldn't find the appopriate attribute in the loaded file, so regenerate it from scratch.
                if (lstAttributeNodes == null || lstAttributeNodes.Count == 0 || xmlCharNodeAnimalForm != null && _objCharacter.LastSavedVersion < new Version("5.200.25"))
                {
                    CharacterAttrib objAttribute;
                    switch (CharacterAttrib.ConvertToAttributeCategory(strAttribute))
                    {
                    case CharacterAttrib.AttributeCategory.Special:
                        objAttribute = new CharacterAttrib(_objCharacter, strAttribute, CharacterAttrib.AttributeCategory.Special);
                        objAttribute = RemakeAttribute(objAttribute, xmlCharNode);
                        SpecialAttributeList.Add(objAttribute);
                        break;

                    case CharacterAttrib.AttributeCategory.Standard:
                        objAttribute = new CharacterAttrib(_objCharacter, strAttribute, CharacterAttrib.AttributeCategory.Standard);
                        objAttribute = RemakeAttribute(objAttribute, xmlCharNode);
                        AttributeList.Add(objAttribute);
                        break;
                    }

                    if (xmlCharNodeAnimalForm == null)
                    {
                        continue;
                    }
                    objAttribute = new CharacterAttrib(_objCharacter, strAttribute, CharacterAttrib.AttributeCategory.Shapeshifter);
                    objAttribute = RemakeAttribute(objAttribute, xmlCharNodeAnimalForm);
                    switch (CharacterAttrib.ConvertToAttributeCategory(objAttribute.Abbrev))
                    {
                    case CharacterAttrib.AttributeCategory.Special:
                        SpecialAttributeList.Add(objAttribute);
                        break;

                    case CharacterAttrib.AttributeCategory.Shapeshifter:
                        AttributeList.Add(objAttribute);
                        break;
                    }
                }
                else
                {
                    foreach (XmlNode xmlAttributeNode in lstAttributeNodes)
                    {
                        CharacterAttrib objAttribute;
                        switch (CharacterAttrib.ConvertToAttributeCategory(strAttribute))
                        {
                        case CharacterAttrib.AttributeCategory.Special:
                            objAttribute = new CharacterAttrib(_objCharacter, strAttribute, CharacterAttrib.AttributeCategory.Special);
                            objAttribute.Load(xmlAttributeNode);
                            SpecialAttributeList.Add(objAttribute);
                            break;

                        case CharacterAttrib.AttributeCategory.Standard:
                            objAttribute = new CharacterAttrib(_objCharacter, strAttribute, CharacterAttrib.AttributeCategory.Standard);
                            objAttribute.Load(xmlAttributeNode);
                            AttributeList.Add(objAttribute);
                            break;
                        }
                    }
                }
            }

            Attributes = new ObservableCollection <CharacterAttrib>
            {
                _objCharacter.BOD,
                _objCharacter.AGI,
                _objCharacter.REA,
                _objCharacter.STR,
                _objCharacter.CHA,
                _objCharacter.INT,
                _objCharacter.LOG,
                _objCharacter.WIL,
                _objCharacter.EDG
            };
            if (_objCharacter.MAGEnabled)
            {
                Attributes.Add(_objCharacter.MAG);
                if (_objCharacter.Options.MysAdeptSecondMAGAttribute && _objCharacter.IsMysticAdept)
                {
                    Attributes.Add(_objCharacter.MAGAdept);
                }
            }
            if (_objCharacter.RESEnabled)
            {
                Attributes.Add(_objCharacter.RES);
            }
            if (_objCharacter.DEPEnabled)
            {
                Attributes.Add(_objCharacter.DEP);
            }
            ResetBindings();
            _objCharacter.RefreshAttributeBindings();
            Timekeeper.Finish("load_char_attrib");
        }
예제 #4
0
        public AttributeControl(CharacterAttrib attribute)
        {
            if (attribute == null)
            {
                return;
            }
            _objAttribute = attribute;
            _objCharacter = attribute.CharacterObject;

            InitializeComponent();
            this.UpdateLightDarkMode();
            this.TranslateWinForm();

            SuspendLayout();
            _dataSource = _objCharacter.AttributeSection.GetAttributeBindingByName(AttributeName);
            _objCharacter.AttributeSection.PropertyChanged += AttributePropertyChanged;
            //Display
            lblName.DoOneWayDataBinding("Text", _dataSource, nameof(CharacterAttrib.DisplayNameFormatted));
            lblValue.DoOneWayDataBinding("Text", _dataSource, nameof(CharacterAttrib.DisplayValue));
            lblLimits.DoOneWayDataBinding("Text", _dataSource, nameof(CharacterAttrib.AugmentedMetatypeLimits));
            lblValue.DoOneWayDataBinding("ToolTipText", _dataSource, nameof(CharacterAttrib.ToolTip));
            if (_objCharacter.Created)
            {
                cmdImproveATT = new ButtonWithToolTip
                {
                    Anchor                  = AnchorStyles.Right,
                    AutoSize                = true,
                    AutoSizeMode            = AutoSizeMode.GrowAndShrink,
                    Image                   = Resources.add,
                    Margin                  = new Padding(3, 0, 3, 0),
                    MinimumSize             = new Size(24, 24),
                    Name                    = "cmdImproveATT",
                    UseVisualStyleBackColor = true
                };
                cmdImproveATT.Click += cmdImproveATT_Click;
                cmdImproveATT.DoOneWayDataBinding("ToolTipText", _dataSource, nameof(CharacterAttrib.UpgradeToolTip));
                cmdImproveATT.DoOneWayDataBinding("Enabled", _dataSource, nameof(CharacterAttrib.CanUpgradeCareer));
                cmdImproveATT.UpdateLightDarkMode();
                cmdImproveATT.TranslateWinForm();
                flpRight.Controls.Add(cmdImproveATT);
                if (AttributeName == "EDG")
                {
                    cmdBurnEdge = new ButtonWithToolTip
                    {
                        Anchor                  = AnchorStyles.Right,
                        AutoSize                = true,
                        AutoSizeMode            = AutoSizeMode.GrowAndShrink,
                        Image                   = Resources.fire,
                        Margin                  = new Padding(3, 0, 3, 0),
                        MinimumSize             = new Size(24, 24),
                        Name                    = "cmdBurnEdge",
                        ToolTipText             = LanguageManager.GetString("Tip_CommonBurnEdge"),
                        UseVisualStyleBackColor = true
                    };
                    cmdBurnEdge.Click += cmdBurnEdge_Click;
                    cmdBurnEdge.UpdateLightDarkMode();
                    cmdBurnEdge.TranslateWinForm();
                    flpRight.Controls.Add(cmdBurnEdge);
                }
            }
            else
            {
                while (_objAttribute.KarmaMaximum < 0 && _objAttribute.Base > 0)
                {
                    _objAttribute.Base -= 1;
                }
                // Very rough fix for when Karma values somehow exceed KarmaMaximum after loading in. This shouldn't happen in the first place, but this ad-hoc patch will help fix crashes.
                if (_objAttribute.Karma > _objAttribute.KarmaMaximum)
                {
                    _objAttribute.Karma = _objAttribute.KarmaMaximum;
                }

                nudKarma = new NumericUpDownEx
                {
                    Anchor              = AnchorStyles.Right,
                    AutoSize            = true,
                    InterceptMouseWheel = NumericUpDownEx.InterceptMouseWheelMode.WhenMouseOver,
                    Margin              = new Padding(3, 0, 3, 0),
                    Maximum             = new decimal(new[] { 99, 0, 0, 0 }),
                    MinimumSize         = new Size(35, 0),
                    Name = "nudKarma"
                };
                nudKarma.BeforeValueIncrement += nudKarma_BeforeValueIncrement;
                nudKarma.ValueChanged         += nudKarma_ValueChanged;
                nudBase = new NumericUpDownEx
                {
                    Anchor              = AnchorStyles.Right,
                    AutoSize            = true,
                    InterceptMouseWheel = NumericUpDownEx.InterceptMouseWheelMode.WhenMouseOver,
                    Margin              = new Padding(3, 0, 3, 0),
                    Maximum             = new decimal(new[] { 99, 0, 0, 0 }),
                    MinimumSize         = new Size(35, 0),
                    Name = "nudBase"
                };
                nudBase.BeforeValueIncrement += nudBase_BeforeValueIncrement;
                nudBase.ValueChanged         += nudBase_ValueChanged;

                nudBase.DoOneWayDataBinding("Visible", _objCharacter, nameof(Character.EffectiveBuildMethodUsesPriorityTables));
                nudBase.DoOneWayDataBinding("Maximum", _dataSource, nameof(CharacterAttrib.PriorityMaximum));
                nudBase.DoDatabinding("Value", _dataSource, nameof(CharacterAttrib.Base));
                nudBase.DoOneWayDataBinding("Enabled", _dataSource, nameof(CharacterAttrib.BaseUnlocked));
                nudBase.InterceptMouseWheel = GlobalOptions.InterceptMode;

                nudKarma.DoOneWayDataBinding("Maximum", _dataSource, nameof(CharacterAttrib.KarmaMaximum));
                nudKarma.DoDatabinding("Value", _dataSource, nameof(CharacterAttrib.Karma));
                nudKarma.InterceptMouseWheel = GlobalOptions.InterceptMode;

                nudBase.UpdateLightDarkMode();
                nudBase.TranslateWinForm();
                nudKarma.UpdateLightDarkMode();
                nudKarma.TranslateWinForm();

                flpRight.Controls.Add(nudKarma);
                flpRight.Controls.Add(nudBase);
            }

            ResumeLayout();
        }
예제 #5
0
        public SkillControl(Skill objSkill)
        {
            if (objSkill == null)
            {
                return;
            }
            _objSkill           = objSkill;
            _objAttributeActive = objSkill.AttributeObject;
            if (_objAttributeActive != null)
            {
                _objAttributeActive.PropertyChanged += Attribute_PropertyChanged;
            }
            InitializeComponent();
            SuspendLayout();
            pnlAttributes.SuspendLayout();
            tlpMain.SuspendLayout();
            tlpRight.SuspendLayout();
            try
            {
                //Display
                _fntNormalName = lblName.Font;
                _fntItalicName = new Font(_fntNormalName, FontStyle.Italic);
                _fntNormal     = btnAttribute.Font;
                _fntItalic     = new Font(_fntNormal, FontStyle.Italic);

                if (!_objSkill.Default)
                {
                    lblName.Font = _fntItalicName;
                }
                lblName.DoOneWayDataBinding("Text", objSkill, nameof(Skill.CurrentDisplayName));
                lblName.DoOneWayDataBinding("ForeColor", objSkill, nameof(Skill.PreferredColor));
                lblName.DoOneWayDataBinding("ToolTipText", objSkill, nameof(Skill.HtmlSkillToolTip));

                btnAttribute.DoOneWayDataBinding("Text", objSkill, nameof(Skill.DisplayAttribute));

                RefreshPoolTooltipAndDisplay();

                // Creating controls outside of the designer saves on handles if the controls would be invisible anyway
                if (objSkill.AllowDelete) // For active skills, can only change by going from Create to Career mode, so no databinding necessary
                {
                    cmdDelete = new Button
                    {
                        AutoSize                = true,
                        AutoSizeMode            = AutoSizeMode.GrowAndShrink,
                        Dock                    = DockStyle.Fill,
                        Margin                  = new Padding(3, 0, 3, 0),
                        Name                    = "cmdDelete",
                        Tag                     = "String_Delete",
                        Text                    = "Delete",
                        UseVisualStyleBackColor = true
                    };
                    cmdDelete.Click += cmdDelete_Click;
                    tlpRight.Controls.Add(cmdDelete, 4, 0);
                }

                if (objSkill.CharacterObject.Created)
                {
                    lblCareerRating = new Label
                    {
                        Anchor    = AnchorStyles.Right,
                        AutoSize  = true,
                        Margin    = new Padding(3, 6, 3, 6),
                        Name      = "lblCareerRating",
                        Text      = "00",
                        TextAlign = ContentAlignment.MiddleRight
                    };
                    btnCareerIncrease = new ButtonWithToolTip
                    {
                        Anchor                  = AnchorStyles.Right,
                        AutoSize                = true,
                        AutoSizeMode            = AutoSizeMode.GrowAndShrink,
                        ImageDpi96              = Resources.add,
                        ImageDpi192             = Resources.add1,
                        MinimumSize             = new Size(24, 24),
                        Name                    = "btnCareerIncrease",
                        Padding                 = new Padding(1),
                        UseVisualStyleBackColor = true
                    };
                    btnCareerIncrease.Click += btnCareerIncrease_Click;

                    lblCareerRating.DoOneWayDataBinding("Text", objSkill, nameof(Skill.Rating));
                    btnCareerIncrease.DoOneWayDataBinding("Enabled", objSkill, nameof(Skill.CanUpgradeCareer));
                    btnCareerIncrease.DoOneWayDataBinding("ToolTipText", objSkill, nameof(Skill.UpgradeToolTip));

                    tlpMain.Controls.Add(lblCareerRating, 2, 0);
                    tlpMain.Controls.Add(btnCareerIncrease, 3, 0);

                    btnAddSpec = new ButtonWithToolTip
                    {
                        Anchor                  = AnchorStyles.Right,
                        AutoSize                = true,
                        AutoSizeMode            = AutoSizeMode.GrowAndShrink,
                        ImageDpi96              = Resources.add,
                        ImageDpi192             = Resources.add1,
                        MinimumSize             = new Size(24, 24),
                        Name                    = "btnAddSpec",
                        Padding                 = new Padding(1),
                        UseVisualStyleBackColor = true
                    };
                    btnAddSpec.Click += btnAddSpec_Click;
                    lblCareerSpec     = new Label
                    {
                        Anchor    = AnchorStyles.Left,
                        AutoSize  = true,
                        Margin    = new Padding(3, 6, 3, 6),
                        Name      = "lblCareerSpec",
                        Text      = "[Specializations]",
                        TextAlign = ContentAlignment.MiddleLeft
                    };
                    lblCareerSpec.DoOneWayDataBinding("Text", objSkill, nameof(Skill.CurrentDisplaySpecialization));
                    btnAddSpec.DoOneWayDataBinding("Enabled", objSkill, nameof(Skill.CanAffordSpecialization));
                    btnAddSpec.DoOneWayDataBinding("Visible", objSkill, nameof(Skill.CanHaveSpecs));
                    btnAddSpec.DoOneWayDataBinding("ToolTipText", objSkill, nameof(Skill.AddSpecToolTip));

                    tlpRight.Controls.Add(lblCareerSpec, 0, 0);
                    tlpRight.Controls.Add(btnAddSpec, 1, 0);

                    using (new FetchSafelyFromPool <List <ListItem> >(Utils.ListItemListPool,
                                                                      out List <ListItem> lstAttributeItems))
                    {
                        foreach (string strLoopAttribute in AttributeSection.AttributeStrings)
                        {
                            if (strLoopAttribute == "MAGAdept")
                            {
                                if (!objSkill.CharacterObject.Settings.MysAdeptSecondMAGAttribute)
                                {
                                    continue;
                                }
                                lstAttributeItems.Add(new ListItem(strLoopAttribute, LanguageManager.MAGAdeptString()));
                            }
                            else
                            {
                                string strAttributeShort = LanguageManager.GetString(
                                    "String_Attribute" + strLoopAttribute + "Short", GlobalSettings.Language, false);
                                lstAttributeItems.Add(new ListItem(strLoopAttribute,
                                                                   !string.IsNullOrEmpty(strAttributeShort)
                                                                       ? strAttributeShort
                                                                       : strLoopAttribute));
                            }
                        }

                        cboSelectAttribute = new ElasticComboBox
                        {
                            Dock              = DockStyle.Fill,
                            DropDownStyle     = ComboBoxStyle.DropDownList,
                            FormattingEnabled = true,
                            Margin            = new Padding(3, 0, 3, 0),
                            Name              = "cboSelectAttribute"
                        };
                        cboSelectAttribute.BeginUpdate();
                        cboSelectAttribute.PopulateWithListItems(lstAttributeItems);
                        cboSelectAttribute.SelectedValue = _objSkill.AttributeObject.Abbrev;
                        cboSelectAttribute.EndUpdate();
                        cboSelectAttribute.DropDownClosed += cboSelectAttribute_Closed;
                        pnlAttributes.Controls.Add(cboSelectAttribute);
                    }
                }
                else
                {
                    nudSkill = new NumericUpDownEx
                    {
                        Anchor              = AnchorStyles.Right,
                        AutoSize            = true,
                        InterceptMouseWheel = NumericUpDownEx.InterceptMouseWheelMode.WhenMouseOver,
                        Margin              = new Padding(3, 2, 3, 2),
                        Maximum             = new decimal(new[] { 99, 0, 0, 0 }),
                        Name = "nudSkill"
                    };
                    nudKarma = new NumericUpDownEx
                    {
                        Anchor              = AnchorStyles.Right,
                        AutoSize            = true,
                        InterceptMouseWheel = NumericUpDownEx.InterceptMouseWheelMode.WhenMouseOver,
                        Margin              = new Padding(3, 2, 3, 2),
                        Maximum             = new decimal(new[] { 99, 0, 0, 0 }),
                        Name = "nudKarma"
                    };

                    // Trick to make it seem like the button is a label (+ onclick method not doing anything in Create mode)
                    btnAttribute.FlatAppearance.MouseDownBackColor = Color.Transparent;
                    btnAttribute.FlatAppearance.MouseOverBackColor = Color.Transparent;

                    nudSkill.DoOneWayDataBinding("Visible", objSkill.CharacterObject,
                                                 nameof(objSkill.CharacterObject.EffectiveBuildMethodUsesPriorityTables));
                    nudSkill.DoDataBinding("Value", objSkill, nameof(Skill.Base));
                    nudSkill.DoOneWayDataBinding("Enabled", objSkill, nameof(Skill.BaseUnlocked));
                    nudSkill.InterceptMouseWheel = GlobalSettings.InterceptMode;
                    nudKarma.DoDataBinding("Value", objSkill, nameof(Skill.Karma));
                    nudKarma.DoOneWayDataBinding("Enabled", objSkill, nameof(Skill.KarmaUnlocked));
                    nudKarma.InterceptMouseWheel = GlobalSettings.InterceptMode;

                    tlpMain.Controls.Add(nudSkill, 2, 0);
                    tlpMain.Controls.Add(nudKarma, 3, 0);

                    if (objSkill.IsExoticSkill)
                    {
                        lblCareerSpec = new Label
                        {
                            Anchor    = AnchorStyles.Left,
                            AutoSize  = true,
                            Margin    = new Padding(3, 6, 3, 6),
                            Name      = "lblCareerSpec",
                            Text      = "[Specializations]",
                            TextAlign = ContentAlignment.MiddleLeft
                        };
                        lblCareerSpec.DoOneWayDataBinding("Text", objSkill, nameof(Skill.CurrentDisplaySpecialization));
                        tlpRight.Controls.Add(lblCareerSpec, 0, 0);
                    }
                    else
                    {
                        cboSpec = new ElasticComboBox
                        {
                            Anchor            = AnchorStyles.Left | AnchorStyles.Right,
                            AutoCompleteMode  = AutoCompleteMode.Suggest,
                            FormattingEnabled = true,
                            Margin            = new Padding(3, 0, 3, 0),
                            Name    = "cboSpec",
                            Sorted  = true,
                            TabStop = false
                        };
                        cboSpec.BeginUpdate();
                        cboSpec.PopulateWithListItems(objSkill.CGLSpecializations);
                        cboSpec.EndUpdate();
                        cboSpec.DoOneWayDataBinding("Enabled", objSkill, nameof(Skill.CanHaveSpecs));
                        cboSpec.Text         = objSkill.CurrentDisplaySpecialization;
                        cboSpec.TextChanged += cboSpec_TextChanged;
                        _blnUpdatingSpec     = false;
                        _tmrSpecChangeTimer  = new Timer {
                            Interval = 1000
                        };
                        _tmrSpecChangeTimer.Tick += SpecChangeTimer_Tick;
                        chkKarma = new ColorableCheckBox(components)
                        {
                            Anchor             = AnchorStyles.Left,
                            AutoSize           = true,
                            DefaultColorScheme = true,
                            Margin             = new Padding(3, 4, 3, 4),
                            Name = "chkKarma",
                            UseVisualStyleBackColor = true
                        };
                        chkKarma.DoOneWayDataBinding("Visible", objSkill.CharacterObject,
                                                     nameof(objSkill.CharacterObject.EffectiveBuildMethodUsesPriorityTables));
                        chkKarma.DoDataBinding("Checked", objSkill, nameof(Skill.BuyWithKarma));
                        chkKarma.DoOneWayDataBinding("Enabled", objSkill, nameof(Skill.CanHaveSpecs));
                        tlpRight.Controls.Add(cboSpec, 0, 0);
                        tlpRight.Controls.Add(chkKarma, 1, 0);

                        // Hacky way of fixing a weird UI issue caused by items of a combobox only being populated from the DataSource after the combobox is added
                        _blnUpdatingSpec = true;
                        cboSpec.Text     = objSkill.CurrentDisplaySpecialization;
                        _blnUpdatingSpec = false;
                    }
                }

                this.DoOneWayDataBinding("Enabled", objSkill, nameof(Skill.Enabled));
                this.DoOneWayDataBinding("BackColor", objSkill, nameof(Skill.PreferredControlColor));

                AdjustForDpi();
                this.UpdateLightDarkMode();
                this.TranslateWinForm(blnDoResumeLayout: false);

                foreach (ToolStripItem tssItem in cmsSkillLabel.Items)
                {
                    tssItem.UpdateLightDarkMode();
                    tssItem.TranslateToolStripItemsRecursively();
                }
            }
            finally
            {
                _blnLoading = false;
                tlpRight.ResumeLayout();
                tlpMain.ResumeLayout();
                pnlAttributes.ResumeLayout();
                ResumeLayout(true);
                _objSkill.PropertyChanged += Skill_PropertyChanged;
            }
        }
예제 #6
0
        public SkillControl2(Skill skill)
        {
            if (skill == null)
            {
                return;
            }
            _skill = skill;
            InitializeComponent();
            SuspendLayout();

            this.TranslateWinForm();

            foreach (ToolStripItem tssItem in cmsSkillLabel.Items)
            {
                tssItem.TranslateToolStripItemsRecursively();
            }

            this.DoDatabinding("Enabled", skill, nameof(Skill.Enabled));

            //Display
            _normalName = lblName.Font;
            _italicName = new Font(lblName.Font, FontStyle.Italic);

            this.DoDatabinding("BackColor", skill, nameof(Skill.PreferredControlColor));

            lblName.DoDatabinding("Text", skill, nameof(Skill.CurrentDisplayName));
            lblName.DoDatabinding("ForeColor", skill, nameof(Skill.PreferredColor));
            lblName.DoDatabinding("ToolTipText", skill, nameof(Skill.HtmlSkillToolTip));

            lblModifiedRating.DoDatabinding("ToolTipText", skill, nameof(Skill.PoolToolTip));
            lblModifiedRating.DoDatabinding("Text", skill, nameof(Skill.DisplayPool));

            _attributeActive        = skill.AttributeObject;
            _skill.PropertyChanged += Skill_PropertyChanged;

            nudSkill.Visible = !skill.CharacterObject.Created && skill.CharacterObject.BuildMethodHasSkillPoints;
            nudKarma.Visible = !skill.CharacterObject.Created;
            chkKarma.Visible = !skill.CharacterObject.Created;
            cboSpec.Visible  = !skill.CharacterObject.Created;

            cboSelectAttribute.Visible = false;
            btnCareerIncrease.Visible  = skill.CharacterObject.Created;
            lblCareerSpec.Visible      = skill.CharacterObject.Created;
            btnAddSpec.Visible         = skill.CharacterObject.Created;
            lblAttribute.Visible       = skill.CharacterObject.Created;
            btnAttribute.Visible       = skill.CharacterObject.Created;
            lblCareerRating.Visible    = skill.CharacterObject.Created;

            _normal = btnAttribute.Font;
            _italic = new Font(_normal, FontStyle.Italic);

            if (skill.CharacterObject.Created)
            {
                lblModifiedRating.Location = new Point(256 - 13, 4);

                lblCareerRating.DoDatabinding("Text", skill, nameof(Skill.Rating));

                btnCareerIncrease.DoDatabinding("Enabled", skill, nameof(Skill.CanUpgradeCareer));
                btnCareerIncrease.DoDatabinding("ToolTipText", skill, nameof(Skill.UpgradeToolTip));
                btnAddSpec.DoDatabinding("Enabled", skill, nameof(Skill.CanAffordSpecialization));
                btnAddSpec.DoDatabinding("Visible", skill, nameof(Skill.CanHaveSpecs));
                btnAddSpec.DoDatabinding("ToolTipText", skill, nameof(Skill.AddSpecToolTip));

                lblCareerSpec.DoDatabinding("Text", skill, nameof(Skill.CurrentDisplaySpecialization));

                lblAttribute.Visible = false;  //Was true, cannot think it should be

                btnAttribute.DoDatabinding("Text", skill, nameof(Skill.DisplayAttribute));
                btnAttribute.Visible = true;

                SetupDropdown();
            }
            else
            {
                lblAttribute.DoDatabinding("Text", skill, nameof(Skill.DisplayAttribute));
                //Up down boxes
                nudKarma.DoDatabinding("Value", skill, nameof(Skill.Karma));
                nudSkill.DoDatabinding("Value", skill, nameof(Skill.Base));

                nudSkill.DoDatabinding("Visible", skill.CharacterObject, nameof(skill.CharacterObject.BuildMethodHasSkillPoints));
                nudSkill.DoDatabinding("Enabled", skill, nameof(Skill.BaseUnlocked));
                nudSkill.DoDatabinding("InterceptMouseWheel", skill.CharacterObject.Options, nameof(CharacterOptions.InterceptMode));
                nudKarma.DoDatabinding("Enabled", skill, nameof(Skill.KarmaUnlocked));
                nudKarma.DoDatabinding("InterceptMouseWheel", skill.CharacterObject.Options, nameof(CharacterOptions.InterceptMode));

                chkKarma.DoDatabinding("Visible", skill.CharacterObject, nameof(skill.CharacterObject.BuildMethodHasSkillPoints));
                chkKarma.DoDatabinding("Checked", skill, nameof(Skill.BuyWithKarma));
                chkKarma.DoDatabinding("Enabled", skill, nameof(Skill.CanHaveSpecs));

                cboSpec.BeginUpdate();
                if (skill.IsExoticSkill)
                {
                    cboSpec.Enabled = false;
                    cboSpec.DoDatabinding("Text", skill, nameof(Skill.CurrentDisplaySpecialization));
                }
                else
                {
                    //dropdown/spec
                    cboSpec.DoDatabinding("Enabled", skill, nameof(Skill.CanHaveSpecs));
                    cboSpec.DataSource    = skill.CGLSpecializations;
                    cboSpec.DisplayMember = nameof(ListItem.Name);
                    cboSpec.ValueMember   = nameof(ListItem.Value);
                    cboSpec.SelectedIndex = -1;
                    cboSpec.DoDatabinding("Text", skill, nameof(Skill.Specialization));
                }
                cboSpec.EndUpdate();
            }

            //Delete button
            cmdDelete.Visible = skill.AllowDelete;
            if (skill.AllowDelete)
            {
                cmdDelete.Click += (sender, args) =>
                {
                    if (!skill.CharacterObject.ConfirmDelete(LanguageManager.GetString(skill.IsExoticSkill ? "Message_DeleteExoticSkill" : "Message_DeleteSkill",
                                                                                       GlobalOptions.Language)))
                    {
                        return;
                    }
                    skill.UnbindSkill();
                    skill.CharacterObject.SkillsSection.Skills.Remove(skill);
                    skill.CharacterObject.SkillsSection.SkillsDictionary.Remove(skill.IsExoticSkill
                        ? skill.Name + " (" + skill.DisplaySpecialization(GlobalOptions.DefaultLanguage) + ')'
                        : skill.Name);
                };

                if (skill.CharacterObject.Created)
                {
                    btnAddSpec.Location = new Point(btnAddSpec.Location.X - cmdDelete.Width, btnAddSpec.Location.Y);
                }
            }

            lblName.Font           = !_skill.Default ? _italicName : _normalName;
            lblModifiedRating.Text = _skill.DisplayOtherAttribute(_attributeActive.TotalValue, _attributeActive.Abbrev);

            _blnLoading = false;

            ResumeLayout();
        }
예제 #7
0
        public static bool TestNodeRequirements(XmlNode node, Character character, out string name,
                                                string strIgnoreQuality        = "", XmlDocument objMetatypeDocument = null, XmlDocument objCritterDocument = null,
                                                XmlDocument objQualityDocument = null)
        {
            XmlNode nameNode;
            string  strNodeInnerText = node.InnerText;
            string  strNodeName      = node["name"]?.InnerText ?? string.Empty;

            switch (node.Name)
            {
            case "attribute":
                // Check to see if an Attribute meets a requirement.
                CharacterAttrib objAttribute   = character.GetAttribute(strNodeName);
                int             intTargetValue = Convert.ToInt32(node["total"].InnerText);
                name = $"\n\t{objAttribute.DisplayAbbrev} {intTargetValue}";
                // Special cases for when we want to check if a special attribute is enabled
                if (intTargetValue == 1)
                {
                    if (objAttribute.Abbrev == "MAG")
                    {
                        return(character.MAGEnabled);
                    }
                    if (objAttribute.Abbrev == "RES")
                    {
                        return(character.RESEnabled);
                    }
                    if (objAttribute.Abbrev == "DEP")
                    {
                        return(character.DEPEnabled);
                    }
                }
                return(objAttribute.TotalValue >= intTargetValue);

            case "attributetotal":
                string strNodeAttributes = node["attributes"].InnerText;
                int    intNodeVal        = Convert.ToInt32(node["val"].InnerText);
                // Check if the character's Attributes add up to a particular total.
                string strAttributes = AttributeSection.AttributeStrings.Aggregate(strNodeAttributes,
                                                                                   (current, strAttribute) => current.Replace(strAttribute, character.GetAttribute(strAttribute).DisplayAbbrev));
                name          = $"\n\t{strAttributes} {intNodeVal}";
                strAttributes = AttributeSection.AttributeStrings.Aggregate(strNodeAttributes,
                                                                            (current, strAttribute) => current.Replace(strAttribute, character.GetAttribute(strAttribute).Value.ToString()));
                XmlDocument     objXmlDocument = new XmlDocument();
                XPathNavigator  nav            = objXmlDocument.CreateNavigator();
                XPathExpression xprAttributes  = nav.Compile(strAttributes);
                return(Convert.ToInt32(nav.Evaluate(xprAttributes)) >= intNodeVal);

            case "careerkarma":
                // Check Career Karma requirement.
                name = "\n\t" + LanguageManager.GetString("Message_SelectQuality_RequireKarma")
                       .Replace("{0}", strNodeInnerText);
                return(character.CareerKarma >= Convert.ToInt32(strNodeInnerText));

            case "critterpower":
                // Run through all of the Powers the character has and see if the current required item exists.
                if (character.CritterEnabled && character.CritterPowers != null)
                {
                    CritterPower critterPower = character.CritterPowers.FirstOrDefault(p => p.Name == strNodeInnerText);
                    if (critterPower != null)
                    {
                        name = critterPower.DisplayNameShort;
                        return(true);
                    }
                    XmlDocument critterPowers = XmlManager.Load("critterpowers.xml");
                    nameNode =
                        critterPowers.SelectSingleNode($"/chummer/powers/power[name = \"{strNodeInnerText}\"]");
                    name = nameNode["translate"] != null
                            ? "\n\t" + nameNode["translate"].InnerText
                            : "\n\t" + strNodeInnerText;
                    name += $" ({LanguageManager.GetString("Tab_Critter")})";
                    return(false);
                }
                break;

            case "bioware":
            case "cyberware":
            {
                int count = Convert.ToInt32(node.Attributes?["count"]?.InnerText ?? "1");
                name  = null;
                name += node.Name == "cyberware"
                            ? "\n\t" + LanguageManager.GetString("Label_Cyberware") + strNodeInnerText
                            : "\n\t" + LanguageManager.GetString("Label_Bioware") + strNodeInnerText;
                string strWareNodeSelectAttribute = node.Attributes?["select"]?.InnerText ?? string.Empty;
                return(character.Cyberware.DeepCount(x => x.Children, objCyberware =>
                                                     objCyberware.Name == strNodeInnerText && string.IsNullOrEmpty(objCyberware.PlugsIntoModularMount) &&
                                                     (string.IsNullOrEmpty(strWareNodeSelectAttribute) || strWareNodeSelectAttribute == objCyberware.Extra)) >= count);
            }

            case "biowarecontains":
            case "cyberwarecontains":
            {
                int count = Convert.ToInt32(node.Attributes?["count"]?.InnerText ?? "1");
                name  = null;
                name += node.Name == "cyberware"
                            ? "\n\t" + LanguageManager.GetString("Label_Cyberware") + strNodeInnerText
                            : "\n\t" + LanguageManager.GetString("Label_Bioware") + strNodeInnerText;
                Improvement.ImprovementSource source = Improvement.ImprovementSource.Cyberware;
                if (node.Name == "biowarecontains")
                {
                    source = Improvement.ImprovementSource.Bioware;
                }
                string strWareContainsNodeSelectAttribute = node.Attributes?["select"]?.InnerText ?? string.Empty;
                return(character.Cyberware.DeepCount(x => x.Children, objCyberware =>
                                                     objCyberware.SourceType == source && string.IsNullOrEmpty(objCyberware.PlugsIntoModularMount) && objCyberware.Name.Contains(strNodeInnerText) &&
                                                     (string.IsNullOrEmpty(strWareContainsNodeSelectAttribute) || strWareContainsNodeSelectAttribute == objCyberware.Extra)) >= count);
            }

            case "damageresistance":
                // Damage Resistance must be a particular value.
                name = "\n\t" + LanguageManager.GetString("String_DamageResistance");
                return(character.BOD.TotalValue + ImprovementManager.ValueOf(character, Improvement.ImprovementType.DamageResistance) >=
                       Convert.ToInt32(strNodeInnerText));

            case "ess":
                string objEssNodeGradeAttributeText = node.Attributes?["grade"]?.InnerText ?? string.Empty;
                if (!string.IsNullOrEmpty(objEssNodeGradeAttributeText))
                {
                    decimal decGrade =
                        character.Cyberware.Where(
                            objCyberware =>
                            objCyberware.Grade.Name.Contains(objEssNodeGradeAttributeText))
                        .Sum(objCyberware => objCyberware.CalculatedESS());
                    if (strNodeInnerText.StartsWith('-'))
                    {
                        // Essence must be less than the value.
                        name = "\n\t" +
                               LanguageManager.GetString(
                            "Message_SelectQuality_RequireESSGradeBelow")
                               .Replace("{0}", strNodeInnerText)
                               .Replace("{1}", objEssNodeGradeAttributeText)
                               .Replace("{2}", decGrade.ToString(CultureInfo.InvariantCulture));
                        return(decGrade <
                               Convert.ToDecimal(strNodeInnerText.TrimStart('-'), GlobalOptions.InvariantCultureInfo));
                    }
                    // Essence must be equal to or greater than the value.
                    name = "\n\t" +
                           LanguageManager.GetString(
                        "Message_SelectQuality_RequireESSGradeAbove")
                           .Replace("{0}", strNodeInnerText)
                           .Replace("{1}", objEssNodeGradeAttributeText)
                           .Replace("{2}", decGrade.ToString(CultureInfo.InvariantCulture));
                    return(decGrade >= Convert.ToDecimal(strNodeInnerText, GlobalOptions.InvariantCultureInfo));
                }
                // Check Essence requirement.
                if (strNodeInnerText.StartsWith('-'))
                {
                    // Essence must be less than the value.
                    name = "\n\t" +
                           LanguageManager.GetString(
                        "Message_SelectQuality_RequireESSBelow")
                           .Replace("{0}", strNodeInnerText)
                           .Replace("{1}", character.Essence.ToString(CultureInfo.InvariantCulture));
                    return(character.Essence <
                           Convert.ToDecimal(strNodeInnerText.TrimStart('-'), GlobalOptions.InvariantCultureInfo));
                }
                // Essence must be equal to or greater than the value.
                name = "\n\t" +
                       LanguageManager.GetString(
                    "Message_SelectQuality_RequireESSAbove")
                       .Replace("{0}", strNodeInnerText)
                       .Replace("{1}", character.Essence.ToString(CultureInfo.InvariantCulture));
                return(character.Essence >= Convert.ToDecimal(strNodeInnerText, GlobalOptions.InvariantCultureInfo));

            case "group":
                // Check that clustered options are present (Magical Tradition + Skill 6, for example)
                string result = string.Empty;
                if (node.ChildNodes.Cast <XmlNode>().Any(childNode => !TestNodeRequirements(childNode, character, out result, strIgnoreQuality,
                                                                                            objMetatypeDocument,
                                                                                            objCritterDocument, objQualityDocument)))
                {
                    name = result;
                    return(false);
                }
                name = result;
                return(true);

            case "initiategrade":
                // Character's initiate grade must be higher than or equal to the required value.
                name = "\n\t" + LanguageManager.GetString("String_InitiateGrade") + " >= " + strNodeInnerText;
                return(character.InitiateGrade >= Convert.ToInt32(strNodeInnerText));

            case "martialtechnique":
                // Character needs a specific Martial Arts technique.
                XmlNode martialDoc = XmlManager.Load("martialarts.xml");
                nameNode = martialDoc.SelectSingleNode($"/chummer/techniques/technique[name = \"{strNodeInnerText}\"]");
                name     = nameNode["translate"] != null
                        ? "\n\t" + nameNode["translate"].InnerText
                        : "\n\t" + strNodeInnerText;
                name += $" ({LanguageManager.GetString("String_MartialArt")})";
                return(character.MartialArts.Any(martialart => martialart.Advantages.Any(technique => technique.Name == strNodeInnerText)));

            case "metamagic":
                XmlNode metamagicDoc = XmlManager.Load("metamagic.xml");
                nameNode =
                    metamagicDoc.SelectSingleNode($"/chummer/metamagics/metamagic[name = \"{strNodeInnerText}\"]");
                name = nameNode["translate"] != null
                        ? "\n\t" + nameNode["translate"].InnerText
                        : "\n\t" + strNodeInnerText;
                name += $" ({LanguageManager.GetString("String_Metamagic")})";
                return(character.Metamagics.Any(objMetamagic => objMetamagic.Name == strNodeInnerText));

            case "metamagicart":
            case "art":
                XmlNode metamagicArtDoc = XmlManager.Load("metamagic.xml");
                nameNode =
                    metamagicArtDoc.SelectSingleNode($"/chummer/arts/art[name = \"{strNodeInnerText}\"]");
                name = nameNode["translate"] != null
                        ? "\n\t" + nameNode["translate"].InnerText
                        : "\n\t" + strNodeInnerText;
                name += $" ({LanguageManager.GetString("String_Art")})";
                if (character.Options.IgnoreArt)
                {
                    if (node.Name == "art")
                    {
                        return(true);
                    }
                    foreach (Metamagic metamagic in character.Metamagics)
                    {
                        XmlNode metaNode =
                            metamagicArtDoc.SelectSingleNode($"/chummer/metamagics/metamagic[name = \"{metamagic.Name}\"]/required");
                        if (metaNode?.InnerXml.Contains($"<art>{strNodeInnerText}</art>") == true)
                        {
                            return(metaNode.InnerXml.Contains($"<art>{strNodeInnerText}</art>"));
                        }
                        metaNode =
                            metamagicArtDoc.SelectSingleNode($"/chummer/metamagics/metamagic[name = \"{metamagic.Name}\"]/forbidden");
                        if (metaNode?.InnerXml.Contains($"<art>{strNodeInnerText}</art>") == true)
                        {
                            return(metaNode.InnerXml.Contains($"<art>{strNodeInnerText}</art>"));
                        }
                    }
                    return(false);
                }
                return(character.Arts.Any(art => art.Name == strNodeInnerText));

            case "metatype":
                // Check the Metatype restriction.
                nameNode =
                    objMetatypeDocument.SelectSingleNode($"/chummer/metatypes/metatype[name = \"{strNodeInnerText}\"]") ??
                    objCritterDocument.SelectSingleNode($"/chummer/metatypes/metatype[name = \"{strNodeInnerText}\"]");
                name = nameNode["translate"] != null
                        ? "\n\t" + nameNode["translate"].InnerText
                        : "\n\t" + strNodeInnerText;
                name += $" ({LanguageManager.GetString("String_Metatype")})";
                return(strNodeInnerText == character.Metatype);

            case "metatypecategory":
                // Check the Metatype Category restriction.
                nameNode =
                    objMetatypeDocument.SelectSingleNode($"/chummer/categories/category[. = \"{strNodeInnerText}\"]") ??
                    objCritterDocument.SelectSingleNode($"/chummer/categories/category[. = \"{strNodeInnerText}\"]");
                name = nameNode?.Attributes["translate"] != null
                        ? "\n\t" + nameNode.Attributes["translate"]?.InnerText
                        : "\n\t" + strNodeInnerText;
                name += LanguageManager.GetString("String_MetatypeCategory");
                return(strNodeInnerText == character.MetatypeCategory);

            case "metavariant":
                // Check the Metavariant restriction.
                nameNode =
                    objMetatypeDocument.SelectSingleNode($"/chummer/metavariants/metavariant[name = \"{strNodeInnerText}\"]") ??
                    objCritterDocument.SelectSingleNode($"/chummer/metavariants/metavariant[name = \"{strNodeInnerText}\"]");
                name = nameNode["translate"] != null
                        ? "\n\t" + nameNode["translate"].InnerText
                        : "\n\t" + strNodeInnerText;
                name += $" ({LanguageManager.GetString("String_Metavariant")})";
                return(strNodeInnerText == character.Metavariant);

            case "power":
                // Run through all of the Powers the character has and see if the current required item exists.
                Power power = character.Powers.FirstOrDefault(p => p.Name == strNodeInnerText);
                if (power != null)
                {
                    name = power.DisplayNameShort;
                    return(true);
                }
                XmlDocument xmlPowers = XmlManager.Load("powers.xml");
                nameNode =
                    xmlPowers.SelectSingleNode($"/chummer/powers/power[name = \"{strNodeInnerText}\"]");
                name = nameNode["translate"] != null
                        ? "\n\t" + nameNode["translate"].InnerText
                        : "\n\t" + strNodeInnerText;
                name += $" ({LanguageManager.GetString("Tab_Adept")})";
                return(false);

            case "quality":
                Quality quality =
                    character.Qualities.FirstOrDefault(q => q.Name == strNodeInnerText && q.Name != strIgnoreQuality);
                if (quality != null)
                {
                    name = quality.DisplayNameShort;
                    return(true);
                }
                // ReSharper disable once RedundantIfElseBlock (Suppresses node warning)
                else
                {
                    nameNode =
                        objQualityDocument.SelectSingleNode($"/chummer/qualities/quality[name = \"{strNodeInnerText}\"]");
                    name = nameNode?["translate"] != null
                            ? "\n\t" + nameNode["translate"].InnerText
                            : "\n\t" + strNodeInnerText;
                    name += $" ({LanguageManager.GetString("String_Quality")})";
                    return(false);
                }

            case "skill":
                // Check if the character has the required Skill.
                if (node["type"] != null)
                {
                    KnowledgeSkill s = character.SkillsSection.KnowledgeSkills
                                       .Where(objSkill => objSkill.Name == strNodeName &&
                                              (node["spec"] == null ||
                                               objSkill.Specializations.Any(objSpec => objSpec.Name == node["spec"]?.InnerText)))
                                       .FirstOrDefault(objSkill => objSkill.TotalBaseRating >= Convert.ToInt32(node["val"]?.InnerText));

                    if (s != null)
                    {
                        name = s.DisplayName;
                        if (node["spec"] != null && !character.Improvements.Any(objImprovement => objImprovement.ImproveType == Improvement.ImprovementType.DisableSpecializationEffects && objImprovement.UniqueName == s.Name && string.IsNullOrEmpty(objImprovement.Condition)))
                        {
                            name += $" ({node["spec"].InnerText})";
                        }
                        if (node["val"] != null)
                        {
                            name += $" {node["val"].InnerText}";
                        }
                        return(true);
                    }
                }
                else
                {
                    if (!string.IsNullOrEmpty(strNodeName))
                    {
                        Skill s = character.SkillsSection.GetActiveSkill(strNodeName);
                        // Exotic Skill
                        if (s == null && node["spec"] != null)
                        {
                            s = character.SkillsSection.GetActiveSkill(strNodeName + " (" + node["spec"].InnerText + ")");
                        }
                        if (s != null && (node["spec"] == null || s.Specializations.Any(objSpec => objSpec.Name == node["spec"]?.InnerText)) && s.TotalBaseRating >= Convert.ToInt32(node["val"]?.InnerText))
                        {
                            name = s.DisplayName;
                            if (node["spec"] != null && !character.Improvements.Any(objImprovement => objImprovement.ImproveType == Improvement.ImprovementType.DisableSpecializationEffects && objImprovement.UniqueName == s.Name && string.IsNullOrEmpty(objImprovement.Condition)))
                            {
                                name += $" ({node["spec"].InnerText})";
                            }
                            if (node["val"] != null)
                            {
                                name += $" {node["val"].InnerText}";
                            }
                            return(true);
                        }
                    }
                }
                XmlDocument xmlSkills = XmlManager.Load("skills.xml");
                nameNode =
                    xmlSkills.SelectSingleNode($"/chummer/skills/skill[name = \"{strNodeName}\"]");
                name = nameNode?["translate"] != null
                        ? "\n\t" + nameNode["translate"].InnerText
                        : "\n\t" + strNodeName;
                if (node["spec"] != null)
                {
                    name += $" ({node["spec"].InnerText})";
                }
                if (node["val"] != null)
                {
                    name += $" {node["val"].InnerText}";
                }
                name += $" ({LanguageManager.GetString("Tab_Skills")})";
                return(false);

            case "skillgrouptotal":
                {
                    // Check if the total combined Ratings of Skill Groups adds up to a particular total.
                    int    intTotal  = 0;
                    var    strGroups = node["skillgroups"].InnerText.Split('+');
                    string outString = "\n\t";
                    for (int i = 0; i <= strGroups.Length - 1; i++)
                    {
                        foreach (SkillGroup objGroup in character.SkillsSection.SkillGroups)
                        {
                            if (objGroup.Name == strGroups[i])
                            {
                                outString += objGroup.DisplayName + ", ";
                                intTotal  += objGroup.Rating;
                                break;
                            }
                        }
                    }
                    name  = outString;
                    name += $" ({LanguageManager.GetString("String_ExpenseSkillGroup")})";
                    return(intTotal >= Convert.ToInt32(node["val"].InnerText));
                }

            case "spell":
                // Check for a specific Spell.
                XmlDocument xmlSpell = XmlManager.Load("spells.xml");
                nameNode =
                    xmlSpell.SelectSingleNode($"/chummer/spells/spell[name = \"{strNodeInnerText}\"]");
                name = nameNode["translate"] != null
                        ? "\n\t" + nameNode["translate"].InnerText
                        : "\n\t" + strNodeInnerText;
                name += $" ({LanguageManager.GetString("String_DescSpell")})";
                return(character.Spells.Any(spell => spell.Name == strNodeInnerText));

            case "spellcategory":
                // Check for a specified amount of a particular Spell category.
                XmlDocument xmlSpells = XmlManager.Load("spells.xml");
                nameNode =
                    xmlSpells.SelectSingleNode($"/chummer/categories/category[. = \"{strNodeName}\"]");
                name = nameNode["translate"] != null
                        ? "\n\t" + nameNode["translate"].InnerText
                        : "\n\t" + strNodeInnerText;
                name += $" ({LanguageManager.GetString("String_SpellCategory")})";
                return(character.Spells.Count(objSpell => objSpell.Category == strNodeName) >= Convert.ToInt32(node["count"].InnerText));

            case "spelldescriptor":
                // Check for a specified amount of a particular Spell Descriptor.
                name = "\n\t" + LanguageManager.GetString("Label_Descriptors") + " >= " + node["count"].InnerText;
                return(character.Spells.Count(objSpell => objSpell.Descriptors.Contains(strNodeName)) >= Convert.ToInt32(node["count"].InnerText));

            case "streetcredvsnotoriety":
                // Street Cred must be higher than Notoriety.
                name = "\n\t" + LanguageManager.GetString("String_StreetCred") + " >= " +
                       LanguageManager.GetString("String_Notoriety");
                return(character.StreetCred >= character.Notoriety);

            case "tradition":
                // Character needs a specific Tradition.
                XmlDocument xmlTradition = XmlManager.Load("traditions.xml");
                nameNode =
                    xmlTradition.SelectSingleNode($"/chummer/traditions/tradition[name = \"{strNodeInnerText}\"]");
                name = nameNode["translate"] != null
                        ? "\n\t" + nameNode["translate"].InnerText
                        : "\n\t" + strNodeInnerText;
                name += $" ({LanguageManager.GetString("String_Tradition")})";
                return(character.MagicTradition == strNodeInnerText);

            default:
                Utils.BreakIfDebug();
                break;
            }
            name = strNodeInnerText;
            return(false);
        }
예제 #8
0
        public void Load(XmlNode xmlSavedCharacterNode)
        {
            Timekeeper.Start("load_char_attrib");
            foreach (CharacterAttrib objAttribute in AttributeList.Concat(SpecialAttributeList))
            {
                objAttribute.UnbindAttribute();
            }
            AttributeList.Clear();
            SpecialAttributeList.Clear();
            XmlDocument objXmlDocument  = XmlManager.Load(_objCharacter.IsCritter ? "critters.xml" : "metatypes.xml");
            XmlNode     xmlMetatypeNode = objXmlDocument.SelectSingleNode("/chummer/metatypes/metatype[name = \"" + _objCharacter.Metatype + "\"]");
            XmlNode     xmlCharNode     = xmlMetatypeNode?.SelectSingleNode("metavariants/metavariant[name = \"" + _objCharacter.Metavariant + "\"]") ?? xmlMetatypeNode;
            // We only want to remake attributes for shifters in career mode, because they only get their second set of attributes when exporting from create mode into career mode
            XmlNode xmlCharNodeAnimalForm = _objCharacter.MetatypeCategory == "Shapeshifter" && _objCharacter.Created ? xmlMetatypeNode : null;

            foreach (string strAttribute in AttributeStrings)
            {
                XmlNodeList lstAttributeNodes = xmlSavedCharacterNode.SelectNodes("attributes/attribute[name = \"" + strAttribute + "\"]");
                // Couldn't find the appopriate attribute in the loaded file, so regenerate it from scratch.
                if (lstAttributeNodes == null || lstAttributeNodes.Count == 0)
                {
                    CharacterAttrib objAttribute = new CharacterAttrib(_objCharacter, strAttribute);
                    objAttribute = RemakeAttribute(objAttribute, xmlCharNode);
                    switch (CharacterAttrib.ConvertToAttributeCategory(objAttribute.Abbrev))
                    {
                    case CharacterAttrib.AttributeCategory.Special:
                        SpecialAttributeList.Add(objAttribute);
                        break;

                    case CharacterAttrib.AttributeCategory.Standard:
                        AttributeList.Add(objAttribute);
                        break;
                    }
                    if (xmlCharNodeAnimalForm != null)
                    {
                        objAttribute = new CharacterAttrib(_objCharacter, strAttribute, CharacterAttrib.AttributeCategory.Shapeshifter);
                        objAttribute = RemakeAttribute(objAttribute, xmlCharNodeAnimalForm);
                        switch (CharacterAttrib.ConvertToAttributeCategory(objAttribute.Abbrev))
                        {
                        case CharacterAttrib.AttributeCategory.Special:
                            SpecialAttributeList.Add(objAttribute);
                            break;

                        case CharacterAttrib.AttributeCategory.Standard:
                            AttributeList.Add(objAttribute);
                            break;
                        }
                    }
                }
                else
                {
                    foreach (XmlNode xmlAttributeNode in lstAttributeNodes)
                    {
                        CharacterAttrib att = new CharacterAttrib(_objCharacter, strAttribute);
                        att.Load(xmlAttributeNode);
                        switch (CharacterAttrib.ConvertToAttributeCategory(att.Abbrev))
                        {
                        case CharacterAttrib.AttributeCategory.Special:
                            SpecialAttributeList.Add(att);
                            break;

                        case CharacterAttrib.AttributeCategory.Standard:
                            AttributeList.Add(att);
                            break;
                        }
                    }
                }
            }
            ResetBindings();
            Timekeeper.Finish("load_char_attrib");
        }
예제 #9
0
        public SkillControl2(Skill skill)
        {
            _skill = skill;
            InitializeComponent();
            SuspendLayout();

            DataBindings.Add("Enabled", skill, nameof(Skill.Enabled), false, DataSourceUpdateMode.OnPropertyChanged);

            //Display
            if (!skill.Default)
            {
                lblName.Font = new Font(lblName.Font, FontStyle.Italic);
            }
            if (!String.IsNullOrWhiteSpace(_skill.Notes))
            {
                lblName.ForeColor = Color.SaddleBrown;
            }

            lblName.DataBindings.Add("Text", skill, nameof(Skill.DisplayName));

            skill.PropertyChanged += Skill_PropertyChanged;

            _attributeActive = skill.AttributeObject;
            _attributeActive.PropertyChanged += AttributeActiveOnPropertyChanged;
            Skill_PropertyChanged(null, null);              //if null it updates all
            _normal = btnAttribute.Font;
            _italic = new Font(_normal, FontStyle.Italic);
            if (skill.CharacterObject.Created)
            {
                lblModifiedRating.Location = new Point(256 - 13, 4);

                lblCareerRating.DataBindings.Add("Text", skill, nameof(Skill.Rating), false,
                                                 DataSourceUpdateMode.OnPropertyChanged);
                lblCareerRating.Visible = true;

                btnCareerIncrease.Visible = true;
                btnCareerIncrease.DataBindings.Add("Enabled", skill, nameof(Skill.CanUpgradeCareer), false,
                                                   DataSourceUpdateMode.OnPropertyChanged);
                nudSkill.Visible = false;
                nudKarma.Visible = false;
                chkKarma.Visible = false;

                cboSpec.Visible = false;


                lblCareerSpec.DataBindings.Add("Text", skill, nameof(skill.DisplaySpecialization), false, DataSourceUpdateMode.OnPropertyChanged);
                lblCareerSpec.Visible = true;

                lblAttribute.Visible = false;                  //Was true, cannot think it should be

                btnAttribute.DataBindings.Add("Text", skill, nameof(Skill.DisplayAttribute));
                btnAttribute.Visible = true;

                SetupDropdown();
            }
            else
            {
                lblAttribute.DataBindings.Add("Text", skill, nameof(Skill.DisplayAttribute));
                //Up down boxes
                nudKarma.DataBindings.Add("Value", skill, nameof(Skill.Karma), false, DataSourceUpdateMode.OnPropertyChanged);
                nudSkill.DataBindings.Add("Value", skill, nameof(Skill.Base), false, DataSourceUpdateMode.OnPropertyChanged);

                nudSkill.DataBindings.Add("Enabled", skill, nameof(Skill.BaseUnlocked), false,
                                          DataSourceUpdateMode.OnPropertyChanged);
                nudKarma.DataBindings.Add("Enabled", skill, nameof(Skill.KarmaUnlocked), false,
                                          DataSourceUpdateMode.OnPropertyChanged);
                if (skill.CharacterObject.BuildMethod.HaveSkillPoints())
                {
                    chkKarma.DataBindings.Add("Checked", skill, nameof(Skill.BuyWithKarma), false,
                                              DataSourceUpdateMode.OnPropertyChanged);
                    chkKarma.DataBindings.Add("Enabled", skill, nameof(Skill.CanHaveSpecs), false, DataSourceUpdateMode.OnPropertyChanged);
                }
                else
                {
                    chkKarma.Visible = false;
                }

                cboSpec.BeginUpdate();
                if (skill.IsExoticSkill)
                {
                    cboSpec.Enabled = false;
                    cboSpec.DataBindings.Add("Text", skill, nameof(Skill.DisplaySpecialization), false, DataSourceUpdateMode.OnPropertyChanged);
                }
                else
                {
                    //dropdown/spec
                    cboSpec.DisplayMember = nameof(ListItem.Name);
                    cboSpec.ValueMember   = nameof(ListItem.Value);
                    cboSpec.DataBindings.Add("Enabled", skill, nameof(Skill.CanHaveSpecs), false,
                                             DataSourceUpdateMode.OnPropertyChanged);
                    cboSpec.SelectedIndex = -1;
                    cboSpec.DataSource    = skill.CGLSpecializations;

                    cboSpec.DataBindings.Add("Text", skill, nameof(Skill.Specialization), false, DataSourceUpdateMode.OnPropertyChanged);
                }
                cboSpec.EndUpdate();
            }

            //Delete button
            if (skill.AllowDelete)
            {
                cmdDelete.Visible = true;
                cmdDelete.Click  += (sender, args) => { skill.CharacterObject.SkillsSection.Skills.Remove(skill); };

                if (skill.CharacterObject.Created)
                {
                    btnAddSpec.Location = new Point(btnAddSpec.Location.X - cmdDelete.Width, btnAddSpec.Location.Y);
                }
            }

            ResumeLayout();
        }
예제 #10
0
 public void ResetBinding(CharacterAttrib attrib)
 {
     _dataSource.DataSource = attrib;
 }
예제 #11
0
        public SkillControl2(Skill objSkill)
        {
            if (objSkill == null)
            {
                return;
            }
            _objSkill           = objSkill;
            _objAttributeActive = objSkill.AttributeObject;
            InitializeComponent();
            SkillControl2_DpiChangedAfterParent(null, EventArgs.Empty);
            this.UpdateLightDarkMode();
            this.TranslateWinForm();

            foreach (ToolStripItem tssItem in cmsSkillLabel.Items)
            {
                tssItem.UpdateLightDarkMode();
                tssItem.TranslateToolStripItemsRecursively();
            }

            SuspendLayout();

            //Display
            _fntNormalName = lblName.Font;
            _fntItalicName = new Font(_fntNormalName, FontStyle.Italic);
            _fntNormal     = btnAttribute.Font;
            _fntItalic     = new Font(_fntNormal, FontStyle.Italic);

            if (!_objSkill.Default)
            {
                lblName.Font = _fntItalicName;
            }
            lblName.DoOneWayDataBinding("Text", objSkill, nameof(Skill.CurrentDisplayName));
            lblName.DoOneWayDataBinding("ForeColor", objSkill, nameof(Skill.PreferredColor));
            lblName.DoOneWayDataBinding("ToolTipText", objSkill, nameof(Skill.HtmlSkillToolTip));

            btnAttribute.DoOneWayDataBinding("Text", objSkill, nameof(Skill.DisplayAttribute));

            lblModifiedRating.Text        = objSkill.DisplayOtherAttribute(_objAttributeActive.Abbrev);
            lblModifiedRating.ToolTipText = objSkill.CompileDicepoolTooltip(_objAttributeActive.Abbrev);

            // Creating controls outside of the designer saves on handles if the controls would be invisible anyway
            if (objSkill.AllowDelete) // For active skills, can only change by going from Create to Career mode, so no databinding necessary
            {
                cmdDelete = new Button
                {
                    AutoSize                = true,
                    AutoSizeMode            = AutoSizeMode.GrowAndShrink,
                    Dock                    = DockStyle.Fill,
                    Margin                  = new Padding(3, 0, 3, 0),
                    Name                    = "cmdDelete",
                    Tag                     = "String_Delete",
                    Text                    = "Delete",
                    UseVisualStyleBackColor = true
                };
                cmdDelete.Click += cmdDelete_Click;
                cmdDelete.UpdateLightDarkMode();
                cmdDelete.TranslateWinForm();
                tlpRight.Controls.Add(cmdDelete, 4, 0);
            }

            int intMinimumSize;

            using (Graphics g = CreateGraphics())
                intMinimumSize = (int)(25 * g.DpiX / 96.0f);

            if (objSkill.CharacterObject.Created)
            {
                lblCareerRating = new Label
                {
                    Anchor      = AnchorStyles.Right,
                    AutoSize    = true,
                    MinimumSize = new Size(intMinimumSize, 0),
                    Name        = "lblCareerRating",
                    Text        = "00",
                    TextAlign   = ContentAlignment.MiddleRight
                };
                btnCareerIncrease = new ButtonWithToolTip
                {
                    Anchor                  = AnchorStyles.Right,
                    AutoSize                = true,
                    AutoSizeMode            = AutoSizeMode.GrowAndShrink,
                    Image                   = Resources.add,
                    Margin                  = new Padding(3, 0, 3, 0),
                    Name                    = "btnCareerIncrease",
                    Padding                 = new Padding(1),
                    UseVisualStyleBackColor = true
                };
                btnCareerIncrease.Click += btnCareerIncrease_Click;

                lblCareerRating.DoOneWayDataBinding("Text", objSkill, nameof(Skill.Rating));
                btnCareerIncrease.DoOneWayDataBinding("Enabled", objSkill, nameof(Skill.CanUpgradeCareer));
                btnCareerIncrease.DoOneWayDataBinding("ToolTipText", objSkill, nameof(Skill.UpgradeToolTip));

                lblCareerRating.UpdateLightDarkMode();
                lblCareerRating.TranslateWinForm();
                btnCareerIncrease.UpdateLightDarkMode();
                btnCareerIncrease.TranslateWinForm();
                tlpMain.Controls.Add(lblCareerRating, 2, 0);
                tlpMain.Controls.Add(btnCareerIncrease, 3, 0);

                btnAddSpec = new ButtonWithToolTip
                {
                    Anchor                  = AnchorStyles.Right,
                    AutoSize                = true,
                    AutoSizeMode            = AutoSizeMode.GrowAndShrink,
                    Image                   = Resources.add,
                    Margin                  = new Padding(3, 0, 3, 0),
                    Name                    = "btnAddSpec",
                    Padding                 = new Padding(1),
                    UseVisualStyleBackColor = true
                };
                btnAddSpec.Click += btnAddSpec_Click;
                lblCareerSpec     = new Label
                {
                    Anchor    = AnchorStyles.Left,
                    AutoSize  = true,
                    Name      = "lblCareerSpec",
                    Text      = "[Specializations]",
                    TextAlign = ContentAlignment.MiddleLeft
                };
                lblCareerSpec.DoOneWayDataBinding("Text", objSkill, nameof(Skill.CurrentDisplaySpecialization));
                btnAddSpec.DoOneWayDataBinding("Enabled", objSkill, nameof(Skill.CanAffordSpecialization));
                btnAddSpec.DoOneWayDataBinding("Visible", objSkill, nameof(Skill.CanHaveSpecs));
                btnAddSpec.DoOneWayDataBinding("ToolTipText", objSkill, nameof(Skill.AddSpecToolTip));

                lblCareerSpec.UpdateLightDarkMode();
                lblCareerSpec.TranslateWinForm();
                btnAddSpec.UpdateLightDarkMode();
                btnAddSpec.TranslateWinForm();
                tlpRight.Controls.Add(lblCareerSpec, 0, 0);
                tlpRight.Controls.Add(btnAddSpec, 1, 0);

                List <ListItem> lstAttributeItems = new List <ListItem>(AttributeSection.AttributeStrings.Count);
                foreach (string strLoopAttribute in AttributeSection.AttributeStrings)
                {
                    if (strLoopAttribute == "MAGAdept")
                    {
                        if (!objSkill.CharacterObject.Options.MysAdeptSecondMAGAttribute)
                        {
                            continue;
                        }
                        lstAttributeItems.Add(new ListItem(strLoopAttribute, LanguageManager.MAGAdeptString()));
                    }
                    else
                    {
                        string strAttributeShort = LanguageManager.GetString("String_Attribute" + strLoopAttribute + "Short", GlobalOptions.Language, false);
                        lstAttributeItems.Add(new ListItem(strLoopAttribute, !string.IsNullOrEmpty(strAttributeShort) ? strAttributeShort : strLoopAttribute));
                    }
                }

                cboSelectAttribute = new ElasticComboBox
                {
                    Anchor            = AnchorStyles.Left | AnchorStyles.Right,
                    DropDownStyle     = ComboBoxStyle.DropDownList,
                    FormattingEnabled = true,
                    Margin            = new Padding(3, 0, 3, 0),
                    Name = "cboSelectAttribute"
                };
                cboSelectAttribute.DropDownClosed += cboSelectAttribute_Closed;
                cboSelectAttribute.BeginUpdate();
                cboSelectAttribute.DataSource    = null;
                cboSelectAttribute.DataSource    = lstAttributeItems;
                cboSelectAttribute.DisplayMember = nameof(ListItem.Name);
                cboSelectAttribute.ValueMember   = nameof(ListItem.Value);
                cboSelectAttribute.SelectedValue = _objSkill.AttributeObject.Abbrev;
                cboSelectAttribute.EndUpdate();
                cboSelectAttribute.UpdateLightDarkMode();
                cboSelectAttribute.TranslateWinForm();
                pnlAttributes.Controls.Add(cboSelectAttribute);
            }
            else
            {
                nudSkill = new NumericUpDownEx
                {
                    Anchor              = AnchorStyles.Right,
                    AutoSize            = true,
                    InterceptMouseWheel = NumericUpDownEx.InterceptMouseWheelMode.WhenMouseOver,
                    Margin              = new Padding(3, 2, 3, 2),
                    Maximum             = new decimal(new[] { 99, 0, 0, 0 }),
                    Name = "nudSkill"
                };
                nudKarma = new NumericUpDownEx
                {
                    Anchor              = AnchorStyles.Right,
                    AutoSize            = true,
                    InterceptMouseWheel = NumericUpDownEx.InterceptMouseWheelMode.WhenMouseOver,
                    Margin              = new Padding(3, 2, 3, 2),
                    Maximum             = new decimal(new[] { 99, 0, 0, 0 }),
                    Name = "nudKarma"
                };

                // Trick to make it seem like the button is a label (+ onclick method not doing anything in Create mode)
                btnAttribute.FlatAppearance.MouseDownBackColor = Color.Transparent;
                btnAttribute.FlatAppearance.MouseOverBackColor = Color.Transparent;

                nudSkill.DoOneWayDataBinding("Visible", objSkill.CharacterObject, nameof(objSkill.CharacterObject.EffectiveBuildMethodUsesPriorityTables));
                nudSkill.DoDatabinding("Value", objSkill, nameof(Skill.Base));
                nudSkill.DoOneWayDataBinding("Enabled", objSkill, nameof(Skill.BaseUnlocked));
                nudSkill.InterceptMouseWheel = GlobalOptions.InterceptMode;
                nudKarma.DoDatabinding("Value", objSkill, nameof(Skill.Karma));
                nudKarma.DoOneWayDataBinding("Enabled", objSkill, nameof(Skill.KarmaUnlocked));
                nudKarma.InterceptMouseWheel = GlobalOptions.InterceptMode;

                nudSkill.UpdateLightDarkMode();
                nudSkill.TranslateWinForm();
                nudKarma.UpdateLightDarkMode();
                nudKarma.TranslateWinForm();
                tlpMain.Controls.Add(nudSkill, 2, 0);
                tlpMain.Controls.Add(nudKarma, 3, 0);

                if (objSkill.IsExoticSkill)
                {
                    lblCareerSpec = new Label
                    {
                        Anchor    = AnchorStyles.Left,
                        AutoSize  = true,
                        Name      = "lblCareerSpec",
                        Text      = "[Specializations]",
                        TextAlign = ContentAlignment.MiddleLeft
                    };
                    lblCareerSpec.DoOneWayDataBinding("Text", objSkill, nameof(Skill.CurrentDisplaySpecialization));
                    lblCareerSpec.UpdateLightDarkMode();
                    lblCareerSpec.TranslateWinForm();
                    tlpRight.Controls.Add(lblCareerSpec, 0, 0);
                }
                else
                {
                    cboSpec = new ElasticComboBox
                    {
                        Anchor            = AnchorStyles.Left | AnchorStyles.Right,
                        AutoCompleteMode  = AutoCompleteMode.Suggest,
                        FormattingEnabled = true,
                        Margin            = new Padding(3, 0, 3, 0),
                        Name    = "cboSpec",
                        Sorted  = true,
                        TabStop = false
                    };
                    cboSpec.BeginUpdate();
                    cboSpec.DataSource    = null;
                    cboSpec.DataSource    = objSkill.CGLSpecializations;
                    cboSpec.DisplayMember = nameof(ListItem.Name);
                    cboSpec.ValueMember   = nameof(ListItem.Value);
                    cboSpec.SelectedIndex = -1;
                    cboSpec.DoDatabinding("Text", objSkill, nameof(Skill.Specialization));
                    cboSpec.DoOneWayDataBinding("Enabled", objSkill, nameof(Skill.CanHaveSpecs));
                    cboSpec.EndUpdate();
                    cboSpec.UpdateLightDarkMode();
                    cboSpec.TranslateWinForm();
                    chkKarma = new ColorableCheckBox(components)
                    {
                        Anchor             = AnchorStyles.Left,
                        AutoSize           = true,
                        DefaultColorScheme = true,
                        Margin             = new Padding(3, 0, 3, 0),
                        Name = "chkKarma",
                        UseVisualStyleBackColor = true
                    };
                    chkKarma.DoOneWayDataBinding("Visible", objSkill.CharacterObject, nameof(objSkill.CharacterObject.EffectiveBuildMethodUsesPriorityTables));
                    chkKarma.DoDatabinding("Checked", objSkill, nameof(Skill.BuyWithKarma));
                    chkKarma.DoOneWayDataBinding("Enabled", objSkill, nameof(Skill.CanHaveSpecs));
                    chkKarma.UpdateLightDarkMode();
                    chkKarma.TranslateWinForm();
                    tlpRight.Controls.Add(cboSpec, 0, 0);
                    tlpRight.Controls.Add(chkKarma, 1, 0);
                }
            }

            this.DoOneWayDataBinding("Enabled", objSkill, nameof(Skill.Enabled));
            this.DoOneWayDataBinding("BackColor", objSkill, nameof(Skill.PreferredControlColor));

            ResumeLayout(true);

            _blnLoading = false;

            _objSkill.PropertyChanged += Skill_PropertyChanged;
        }
예제 #12
0
        public SkillControl2(Skill objSkill)
        {
            if (objSkill == null)
            {
                return;
            }
            _objSkill           = objSkill;
            _objAttributeActive = objSkill.AttributeObject;
            InitializeComponent();
            SuspendLayout();

            this.TranslateWinForm();

            foreach (ToolStripItem tssItem in cmsSkillLabel.Items)
            {
                tssItem.TranslateToolStripItemsRecursively();
            }

            //Display
            _fntNormalName = lblName.Font;
            _fntItalicName = new Font(_fntNormalName, FontStyle.Italic);
            _fntNormal     = btnAttribute.Font;
            _fntItalic     = new Font(_fntNormal, FontStyle.Italic);

            if (!_objSkill.Default)
            {
                lblName.Font = _fntItalicName;
            }
            lblName.DoOneWayDataBinding("Text", objSkill, nameof(Skill.CurrentDisplayName));
            lblName.DoOneWayDataBinding("ForeColor", objSkill, nameof(Skill.PreferredColor));
            lblName.DoOneWayDataBinding("ToolTipText", objSkill, nameof(Skill.HtmlSkillToolTip));

            btnAttribute.DoOneWayDataBinding("Text", objSkill, nameof(Skill.DisplayAttribute));

            lblModifiedRating.Text        = objSkill.DisplayOtherAttribute(_objAttributeActive.TotalValue, _objAttributeActive.Abbrev);
            lblModifiedRating.ToolTipText = objSkill.CompileDicepoolTooltip(_objAttributeActive.Abbrev);

            if (objSkill.AllowDelete) // For active skills, can only change by going from Create to Career mode, so no databinding necessary
            {
                cmdDelete.Visible = true;
            }

            if (objSkill.CharacterObject.Created)
            {
                flpButtonsCreate.Visible = false;
                tlpSpecsCreate.Visible   = false;
                flpButtonsCareer.Dock    = DockStyle.Fill;
                tlpSpecsCareer.Dock      = DockStyle.Fill;

                lblCareerRating.DoOneWayDataBinding("Text", objSkill, nameof(Skill.Rating));
                btnCareerIncrease.DoOneWayDataBinding("Enabled", objSkill, nameof(Skill.CanUpgradeCareer));
                btnCareerIncrease.DoOneWayDataBinding("ToolTipText", objSkill, nameof(Skill.UpgradeToolTip));

                lblCareerSpec.DoOneWayDataBinding("Text", objSkill, nameof(Skill.CurrentDisplaySpecialization));
                btnAddSpec.DoOneWayDataBinding("Enabled", objSkill, nameof(Skill.CanAffordSpecialization));
                btnAddSpec.DoOneWayDataBinding("Visible", objSkill, nameof(Skill.CanHaveSpecs));
                btnAddSpec.DoOneWayDataBinding("ToolTipText", objSkill, nameof(Skill.AddSpecToolTip));

                List <ListItem> lstAttributeItems = new List <ListItem>(AttributeSection.AttributeStrings.Count);
                foreach (string strLoopAttribute in AttributeSection.AttributeStrings)
                {
                    string strAttributeShort = LanguageManager.GetString("String_Attribute" + strLoopAttribute + "Short", GlobalOptions.Language, false);
                    lstAttributeItems.Add(new ListItem(strLoopAttribute, !string.IsNullOrEmpty(strAttributeShort) ? strAttributeShort : strLoopAttribute));
                }
                cboSelectAttribute.BeginUpdate();
                cboSelectAttribute.DataSource    = null;
                cboSelectAttribute.DisplayMember = nameof(ListItem.Name);
                cboSelectAttribute.ValueMember   = nameof(ListItem.Value);
                cboSelectAttribute.DataSource    = lstAttributeItems;
                cboSelectAttribute.SelectedValue = _objSkill.AttributeObject.Abbrev;
                cboSelectAttribute.EndUpdate();
            }
            else
            {
                flpButtonsCareer.Visible = false;
                flpButtonsCreate.Dock    = DockStyle.Fill;

                // Trick to make it seem like the button is a label (+ onclick method not doing anything in Create mode)
                btnAttribute.FlatAppearance.MouseDownBackColor = btnAttribute.BackColor;
                btnAttribute.FlatAppearance.MouseOverBackColor = btnAttribute.BackColor;

                nudSkill.DoOneWayDataBinding("Visible", objSkill.CharacterObject, nameof(objSkill.CharacterObject.BuildMethodHasSkillPoints));
                nudSkill.DoDatabinding("Value", objSkill, nameof(Skill.Base));
                nudSkill.DoOneWayDataBinding("Enabled", objSkill, nameof(Skill.BaseUnlocked));
                nudSkill.DoOneWayDataBinding("InterceptMouseWheel", objSkill.CharacterObject.Options, nameof(CharacterOptions.InterceptMode));
                nudKarma.DoDatabinding("Value", objSkill, nameof(Skill.Karma));
                nudKarma.DoOneWayDataBinding("Enabled", objSkill, nameof(Skill.KarmaUnlocked));
                nudKarma.DoOneWayDataBinding("InterceptMouseWheel", objSkill.CharacterObject.Options, nameof(CharacterOptions.InterceptMode));

                if (objSkill.IsExoticSkill)
                {
                    tlpSpecsCreate.Visible = false;
                    tlpSpecsCareer.Dock    = DockStyle.Fill;
                    btnAddSpec.Visible     = false;
                    lblCareerSpec.DoOneWayDataBinding("Text", objSkill, nameof(Skill.CurrentDisplaySpecialization));
                }
                else
                {
                    tlpSpecsCareer.Visible = false;
                    tlpSpecsCreate.Dock    = DockStyle.Fill;
                    cboSpec.BeginUpdate();
                    cboSpec.DataSource    = null;
                    cboSpec.DisplayMember = nameof(ListItem.Name);
                    cboSpec.ValueMember   = nameof(ListItem.Value);
                    cboSpec.DataSource    = objSkill.CGLSpecializations;
                    cboSpec.SelectedIndex = -1;
                    cboSpec.DoDatabinding("Text", objSkill, nameof(Skill.Specialization));
                    cboSpec.DoOneWayDataBinding("Enabled", objSkill, nameof(Skill.CanHaveSpecs));
                    cboSpec.EndUpdate();
                }

                chkKarma.DoOneWayDataBinding("Visible", objSkill.CharacterObject, nameof(objSkill.CharacterObject.BuildMethodHasSkillPoints));
                chkKarma.DoDatabinding("Checked", objSkill, nameof(Skill.BuyWithKarma));
                chkKarma.DoOneWayDataBinding("Enabled", objSkill, nameof(Skill.CanHaveSpecs));
            }

            this.DoOneWayDataBinding("Enabled", objSkill, nameof(Skill.Enabled));
            this.DoOneWayDataBinding("BackColor", objSkill, nameof(Skill.PreferredControlColor));

            ResumeLayout(true);

            _blnLoading = false;

            _objSkill.PropertyChanged += Skill_PropertyChanged;
        }
예제 #13
0
        public SkillControl2(Skill skill)
        {
            this._skill = skill;
            InitializeComponent();

            DataBindings.Add("Enabled", skill, nameof(Skill.Enabled), false, DataSourceUpdateMode.OnPropertyChanged);

            //Display
            if (!skill.Default)
            {
                lblName.Font = new Font(lblName.Font, FontStyle.Italic);
            }
            if (!String.IsNullOrWhiteSpace(_skill.Notes))
            {
                lblName.ForeColor = Color.SaddleBrown;
            }

            lblName.DataBindings.Add("Text", skill, nameof(Skill.DisplayName));

            skill.PropertyChanged += Skill_PropertyChanged;

            _attributeActive = skill.AttributeObject;
            _attributeActive.PropertyChanged += AttributeActiveOnPropertyChanged;
            Skill_PropertyChanged(null, null);  //if null it updates all

            _normal = btnAttribute.Font;
            _italic = new Font(_normal, FontStyle.Italic);
            if (skill.CharacterObject.Created)
            {
                lblModifiedRating.Location = new Point(256 - 13, 4);

                lblCareerRating.DataBindings.Add("Text", skill, nameof(Skill.Rating), false,
                    DataSourceUpdateMode.OnPropertyChanged);
                lblCareerRating.Visible = true;

                btnCareerIncrease.Visible = true;
                btnCareerIncrease.DataBindings.Add("Enabled", skill, nameof(Skill.CanUpgradeCareer), false,
                    DataSourceUpdateMode.OnPropertyChanged);
                nudSkill.Visible = false;
                nudKarma.Visible = false;
                chkKarma.Visible = false;

                cboSpec.Visible = false;

                lblCareerSpec.DataBindings.Add("Text", skill, nameof(skill.DisplaySpecialization), false, DataSourceUpdateMode.OnPropertyChanged);
                lblCareerSpec.Visible = true;

                lblAttribute.Visible = false;  //Was true, cannot think it should be

                btnAttribute.DataBindings.Add("Text", skill, nameof(Skill.DisplayAttribute));
                btnAttribute.Visible = true;

                SetupDropdown();
            }
            else
            {
                lblAttribute.DataBindings.Add("Text", skill, nameof(Skill.DisplayAttribute));

                //Up down boxes
                nudKarma.DataBindings.Add("Value", skill, nameof(Skill.Karma), false, DataSourceUpdateMode.OnPropertyChanged);
                nudSkill.DataBindings.Add("Value", skill, nameof(Skill.Base), false, DataSourceUpdateMode.OnPropertyChanged);

                nudSkill.DataBindings.Add("Enabled", skill, nameof(Skill.BaseUnlocked), false,
                    DataSourceUpdateMode.OnPropertyChanged);
                nudKarma.DataBindings.Add("Enabled", skill, nameof(Skill.KarmaUnlocked), false,
                    DataSourceUpdateMode.OnPropertyChanged);

                if (skill.CharacterObject.BuildMethod.HaveSkillPoints())
                {
                    chkKarma.DataBindings.Add("Checked", skill, nameof(Skill.BuyWithKarma), false,
                        DataSourceUpdateMode.OnPropertyChanged);
                    chkKarma.DataBindings.Add("Enabled", skill, nameof(Skill.CanHaveSpecs), false, DataSourceUpdateMode.OnPropertyChanged);
                }
                else
                {
                    chkKarma.Visible = false;
                }

                if (skill.IsExoticSkill)
                {
                    cboSpec.Enabled = false;
                    cboSpec.DataBindings.Add("Text", skill, nameof(Skill.DisplaySpecialization), false, DataSourceUpdateMode.OnPropertyChanged);

                }
                else
                {
                    //dropdown/spec
                    cboSpec.DataSource = skill.CGLSpecializations;
                    cboSpec.DisplayMember = nameof(ListItem.Name);
                    cboSpec.ValueMember = nameof(ListItem.Value);
                    cboSpec.DataBindings.Add("Enabled", skill, nameof(Skill.CanHaveSpecs), false,
                        DataSourceUpdateMode.OnPropertyChanged);
                    cboSpec.SelectedIndex = -1;

                    cboSpec.DataBindings.Add("Text", skill, nameof(Skill.Specialization), false, DataSourceUpdateMode.OnPropertyChanged);

                }
            }

            //Delete button
            if (skill.AllowDelete)
            {
                cmdDelete.Visible = true;
                cmdDelete.Click += (sender, args) => { skill.CharacterObject.SkillsSection.Skills.Remove(skill); };

                if (skill.CharacterObject.Created)
                {
                    btnAddSpec.Location = new Point(btnAddSpec.Location.X - cmdDelete.Width, btnAddSpec.Location.Y);
                }
            }
        }
예제 #14
0
        private void cboSelectAttribute_Closed(object sender, EventArgs e)
        {
            btnAttribute.Visible = true;
            cboSelectAttribute.Visible = false;
            _attributeActive.PropertyChanged -= AttributeActiveOnPropertyChanged;
            _attributeActive = _skill.CharacterObject.GetAttribute((string) cboSelectAttribute.SelectedValue);

            btnAttribute.Font = _attributeActive == _skill.AttributeObject ? _normal : _italic;
            btnAttribute.Text = cboSelectAttribute.Text;

            _attributeActive.PropertyChanged += AttributeActiveOnPropertyChanged;
            AttributeActiveOnPropertyChanged(null, null);

            CustomAttributeChanged?.Invoke(this, EventArgs.Empty);
        }
예제 #15
0
        public SkillControl2(Skill skill)
        {
            _skill = skill;
            InitializeComponent();
            SuspendLayout();

            foreach (ToolStripItem objItem in cmsSkillLabel.Items)
            {
                LanguageManager.TranslateToolStripItemsRecursively(objItem, GlobalOptions.Language);
            }

            Utils.DoDatabinding(this, "Enabled", skill, nameof(Skill.Enabled));

            //Display
            _normalName = lblName.Font;
            _italicName = new Font(lblName.Font, FontStyle.Italic);

            Utils.DoDatabinding(this, "BackColor", skill, nameof(Skill.PreferredControlColor));

            Utils.DoDatabinding(lblName, "Text", skill, nameof(Skill.DisplayName));
            Utils.DoDatabinding(lblName, "ForeColor", skill, nameof(Skill.PreferredColor));
            Utils.DoDatabinding(lblName, "ToolTipText", skill, nameof(Skill.SkillToolTip));

            Utils.DoDatabinding(lblModifiedRating, "ToolTipText", skill, nameof(Skill.PoolToolTip));

            _attributeActive        = skill.AttributeObject;
            _skill.PropertyChanged += Skill_PropertyChanged;
            _skill.CharacterObject.AttributeSection.PropertyChanged += AttributeSection_PropertyChanged;
            Skill_PropertyChanged(null, null);  //if null it updates all

            nudSkill.Visible = !skill.CharacterObject.Created && skill.CharacterObject.BuildMethodHasSkillPoints;
            nudKarma.Visible = !skill.CharacterObject.Created;
            chkKarma.Visible = !skill.CharacterObject.Created;
            cboSpec.Visible  = !skill.CharacterObject.Created;

            cboSelectAttribute.Visible = false;
            btnCareerIncrease.Visible  = skill.CharacterObject.Created;
            lblCareerSpec.Visible      = skill.CharacterObject.Created;
            btnAddSpec.Visible         = skill.CharacterObject.Created;
            lblAttribute.Visible       = skill.CharacterObject.Created;
            btnAttribute.Visible       = skill.CharacterObject.Created;
            lblCareerRating.Visible    = skill.CharacterObject.Created;

            _normal = btnAttribute.Font;
            _italic = new Font(_normal, FontStyle.Italic);

            if (skill.CharacterObject.Created)
            {
                lblModifiedRating.Location = new Point(256 - 13, 4);

                lblCareerRating.DataBindings.Add("Text", skill, nameof(Skill.Rating), false,
                                                 DataSourceUpdateMode.OnPropertyChanged);

                btnCareerIncrease.DataBindings.Add("Enabled", skill, nameof(Skill.CanUpgradeCareer), false, DataSourceUpdateMode.OnPropertyChanged);
                btnCareerIncrease.DataBindings.Add("ToolTipText", skill, nameof(Skill.UpgradeToolTip), false, DataSourceUpdateMode.OnPropertyChanged);
                btnAddSpec.DataBindings.Add("Enabled", skill, nameof(Skill.CanAffordSpecialization), false, DataSourceUpdateMode.OnPropertyChanged);
                btnAddSpec.DataBindings.Add("Visible", skill, nameof(Skill.CanHaveSpecs), false, DataSourceUpdateMode.OnPropertyChanged);
                btnAddSpec.DataBindings.Add("ToolTipText", skill, nameof(Skill.AddSpecToolTip), false, DataSourceUpdateMode.OnPropertyChanged);

                lblCareerSpec.DataBindings.Add("Text", skill, nameof(Skill.DisplaySpecialization), false, DataSourceUpdateMode.OnPropertyChanged);

                lblAttribute.Visible = false;  //Was true, cannot think it should be

                btnAttribute.DataBindings.Add("Text", skill, nameof(Skill.DisplayAttribute));
                btnAttribute.Visible = true;

                SetupDropdown();
            }
            else
            {
                lblAttribute.DataBindings.Add("Text", skill, nameof(Skill.DisplayAttribute));
                //Up down boxes
                nudKarma.DataBindings.Add("Value", skill, nameof(Skill.Karma), false, DataSourceUpdateMode.OnPropertyChanged);
                nudSkill.DataBindings.Add("Value", skill, nameof(Skill.Base), false, DataSourceUpdateMode.OnPropertyChanged);

                nudSkill.DataBindings.Add("Visible", skill.CharacterObject, nameof(skill.CharacterObject.BuildMethodHasSkillPoints), false, DataSourceUpdateMode.OnPropertyChanged);
                nudSkill.DataBindings.Add("Enabled", skill, nameof(Skill.BaseUnlocked), false,
                                          DataSourceUpdateMode.OnPropertyChanged);
                nudSkill.DataBindings.Add("InterceptMouseWheel", skill.CharacterObject.Options, nameof(CharacterOptions.InterceptMode), false,
                                          DataSourceUpdateMode.OnPropertyChanged);
                nudKarma.DataBindings.Add("Enabled", skill, nameof(Skill.KarmaUnlocked), false,
                                          DataSourceUpdateMode.OnPropertyChanged);
                nudKarma.DataBindings.Add("InterceptMouseWheel", skill.CharacterObject.Options, nameof(CharacterOptions.InterceptMode), false,
                                          DataSourceUpdateMode.OnPropertyChanged);

                chkKarma.DataBindings.Add("Visible", skill.CharacterObject, nameof(skill.CharacterObject.BuildMethodHasSkillPoints), false, DataSourceUpdateMode.OnPropertyChanged);
                chkKarma.DataBindings.Add("Checked", skill, nameof(Skill.BuyWithKarma), false, DataSourceUpdateMode.OnPropertyChanged);
                chkKarma.DataBindings.Add("Enabled", skill, nameof(Skill.CanHaveSpecs), false, DataSourceUpdateMode.OnPropertyChanged);

                cboSpec.BeginUpdate();
                if (skill.IsExoticSkill)
                {
                    cboSpec.Enabled = false;
                    cboSpec.DataBindings.Add("Text", skill, nameof(Skill.DisplaySpecialization), false, DataSourceUpdateMode.OnPropertyChanged);
                }
                else
                {
                    //dropdown/spec
                    cboSpec.DisplayMember = nameof(ListItem.Name);
                    cboSpec.ValueMember   = nameof(ListItem.Value);
                    cboSpec.DataBindings.Add("Enabled", skill, nameof(Skill.CanHaveSpecs), false, DataSourceUpdateMode.OnPropertyChanged);
                    cboSpec.SelectedIndex = -1;
                    cboSpec.DataSource    = skill.CGLSpecializations;

                    cboSpec.DataBindings.Add("Text", skill, nameof(Skill.Specialization), false, DataSourceUpdateMode.OnPropertyChanged);
                }
                cboSpec.EndUpdate();
            }

            //Delete button
            cmdDelete.Visible = skill.AllowDelete;
            if (skill.AllowDelete)
            {
                cmdDelete.Click += (sender, args) =>
                {
                    skill.UnbindSkill();
                    skill.CharacterObject.SkillsSection.Skills.Remove(skill);
                    skill.CharacterObject.SkillsSection.SkillsDictionary.Remove(skill.IsExoticSkill ? skill.Name + " (" + skill.DisplaySpecializationMethod(GlobalOptions.Language) + ')' : skill.Name);
                };

                if (skill.CharacterObject.Created)
                {
                    btnAddSpec.Location = new Point(btnAddSpec.Location.X - cmdDelete.Width, btnAddSpec.Location.Y);
                }
            }

            ResumeLayout();
        }
예제 #16
0
        //TODO: Might be a better location for this; Class names are screwy.
        /// <summary>
        ///     Evaluates requirements of a given node against a given Character object.
        /// </summary>
        /// <param name="objXmlNode">XmlNode of the object.</param>
        /// <param name="blnShowMessage">Should warning messages about whether the object has failed to validate be shown?</param>
        /// <param name="objCharacter">Character Object.</param>
        /// <param name="objQualityDocument"></param>
        /// <param name="strIgnoreQuality">
        ///     Name of a Quality that should be ignored. Typically used when swapping Qualities in
        ///     career mode.
        /// </param>
        /// <param name="strLocalName"></param>
        /// <param name="objMetatypeDocument"></param>
        /// <param name="objCritterDocument"></param>
        /// <param name="strSourceName">Name of the improvement that called this (if it was called by an improvement adding it)</param>
        /// <returns></returns>
        public static bool RequirementsMet(XmlNode objXmlNode, bool blnShowMessage, Character objCharacter, XmlDocument objMetatypeDocument = null, XmlDocument objCritterDocument = null, XmlDocument objQualityDocument = null, string strIgnoreQuality = "", string strLocalName = "", string strSourceName = "", string strLocation = "")
        {
            // Ignore the rules.
            if (objCharacter.IgnoreRules)
            {
                return(true);
            }
            if (objXmlNode == null)
            {
                return(false);
            }
            if (objMetatypeDocument == null)
            {
                objMetatypeDocument = XmlManager.Load("metatypes.xml");
            }
            if (objCritterDocument == null)
            {
                objCritterDocument = XmlManager.Load("critters.xml");
            }
            if (objQualityDocument == null)
            {
                objQualityDocument = XmlManager.Load("qualities.xml");
            }
            // See if the character is in career mode but would want to add a chargen-only Quality
            if (objCharacter.Created)
            {
                if (objXmlNode["chargenonly"] != null && objXmlNode["chargenonly"]?.InnerText != "no")
                {
                    if (blnShowMessage)
                    {
                        MessageBox.Show(LanguageManager.GetString("Message_SelectGeneric_ChargenRestriction").Replace("{0}", strLocalName),
                                        LanguageManager.GetString("MessageTitle_SelectGeneric_Restriction").Replace("{0}", strLocalName),
                                        MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                    return(false);
                }
            }
            // See if the character is using priority-based gen and is trying to add a Quality that can only be added through priorities
            else if ((objCharacter.BuildMethod == CharacterBuildMethod.Priority || objCharacter.BuildMethod == CharacterBuildMethod.SumtoTen) && objXmlNode["onlyprioritygiven"] != null && objXmlNode["onlyprioritygiven"]?.InnerText != "no")
            {
                if (blnShowMessage)
                {
                    MessageBox.Show(LanguageManager.GetString("MessageTitle_SelectGeneric_PriorityRestriction").Replace("{0}", strLocalName),
                                    LanguageManager.GetString("MessageTitle_SelectGeneric_Restriction").Replace("{0}", strLocalName),
                                    MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                return(false);
            }
            // See if the character already has this Quality and whether or not multiple copies are allowed.
            string strLimitString = string.Empty;
            // If the limit at chargen is different from the actual limit, we need to make sure we fetch the former if the character is in Create mode
            string strChargenLimitString = objXmlNode["chargenlimit"]?.InnerText;

            if (!string.IsNullOrWhiteSpace(strChargenLimitString) && !objCharacter.Created)
            {
                strLimitString = strChargenLimitString;
            }
            else
            {
                strLimitString = objXmlNode["limit"]?.InnerText;
                // Default case is each quality can only be taken once
                if (string.IsNullOrWhiteSpace(strLimitString))
                {
                    if (objXmlNode.Name == "quality" || objXmlNode.Name == "cyberware" || objXmlNode.Name == "bioware")
                    {
                        strLimitString = "1";
                    }
                    else
                    {
                        strLimitString = "no";
                    }
                }
            }
            if (strLimitString != "no")
            {
                XmlDocument    objDummyDoc  = new XmlDocument();
                XPathNavigator objNavigator = objDummyDoc.CreateNavigator();
                foreach (string strAttribute in AttributeSection.AttributeStrings)
                {
                    CharacterAttrib objLoopAttribute = objCharacter.GetAttribute(strAttribute);
                    strLimitString = strLimitString.Replace("{" + strAttribute + "}", objLoopAttribute.TotalValue.ToString());
                    strLimitString = strLimitString.Replace("{" + strAttribute + "Base}", objLoopAttribute.TotalBase.ToString());
                }
                foreach (string strLimb in Character.LimbStrings)
                {
                    int objLoopLimbCount = objCharacter.LimbCount(strLimb);
                    if (!string.IsNullOrEmpty(strLocation))
                    {
                        objLoopLimbCount /= 2;
                    }
                    strLimitString = strLimitString.Replace("{" + strLimb + "}", objLoopLimbCount.ToString());
                }
                try
                {
                    XPathExpression objExpression = objNavigator.Compile(strLimitString);
                    strLimitString = objNavigator.Evaluate(objExpression).ToString();
                }
                catch (XPathException)
                {
                    strLimitString = "1";
                }

                string limitTitle   = LanguageManager.GetString("MessageTitle_SelectGeneric_Limit").Replace("{0}", strLocalName);
                string limitMessage = LanguageManager.GetString("Message_SelectGeneric_Limit").Replace("{0}", strLocalName);

                List <string> lstNamesIncludedInLimit = new List <string>();
                if (objXmlNode["name"] != null)
                {
                    lstNamesIncludedInLimit.Add(objXmlNode["name"].InnerText);
                }

                // We could set this to a list immediately, but I'd rather the pointer start at null so that no list ends up getting selected for the "default" case below
                IEnumerable <INamedItem> objListToCheck = null;
                bool blnCheckCyberwareChildren          = false;
                switch (objXmlNode.Name)
                {
                case "quality":
                {
                    objListToCheck = objCharacter.Qualities.Where(objQuality => objQuality.SourceName == strSourceName);
                    break;
                }

                case "metamagic":
                {
                    objListToCheck = objCharacter.Metamagics;
                    break;
                }

                case "art":
                {
                    objListToCheck = objCharacter.Arts;
                    break;
                }

                case "enhancement":
                {
                    objListToCheck = objCharacter.Enhancements;
                    break;
                }

                case "power":
                {
                    objListToCheck = objCharacter.Powers;
                    break;
                }

                case "critterpower":
                {
                    objListToCheck = objCharacter.CritterPowers;
                    break;
                }

                case "cyberware":
                case "bioware":
                {
                    blnCheckCyberwareChildren = true;
                    break;
                }

                default:
                {
                    Utils.BreakIfDebug();
                    break;
                }
                }

                int intLimit         = Convert.ToInt32(strLimitString);
                int intExtendedLimit = intLimit;
                if (objXmlNode["limitwithinclusions"] != null)
                {
                    intExtendedLimit = Convert.ToInt32(objXmlNode["limitwithinclusions"].InnerText);
                }
                int intCount         = 0;
                int intExtendedCount = 0;
                if (objListToCheck != null || blnCheckCyberwareChildren)
                {
                    if (blnCheckCyberwareChildren)
                    {
                        if (string.IsNullOrEmpty(strLocation))
                        {
                            intCount = objCharacter.Cyberware.DeepCount(x => x.Children, x => x.Name != strIgnoreQuality && string.IsNullOrEmpty(x.PlugsIntoModularMount) && lstNamesIncludedInLimit.Any(strName => strName == x.Name));
                        }
                        // We only want to check against 'ware that is on the same side as this one
                        else
                        {
                            intCount = objCharacter.Cyberware.DeepCount(x => x.Children, x => x.Name != strIgnoreQuality && string.IsNullOrEmpty(x.PlugsIntoModularMount) && x.Location == strLocation && lstNamesIncludedInLimit.Any(strName => strName == x.Name));
                        }
                    }
                    else
                    {
                        intCount = objListToCheck.Count(objItem => objItem.Name != strIgnoreQuality && lstNamesIncludedInLimit.Any(objLimitName => objLimitName == objItem.Name));
                    }
                    intExtendedCount = intCount;
                    // In case one item is split up into multiple entries with different names, e.g. Indomitable quality, we need to be able to check all those entries against the limit
                    if (objXmlNode["includeinlimit"] != null)
                    {
                        foreach (XmlNode objChildXml in objXmlNode["includeinlimit"].ChildNodes)
                        {
                            lstNamesIncludedInLimit.Add(objChildXml.InnerText);
                        }

                        if (blnCheckCyberwareChildren)
                        {
                            if (string.IsNullOrEmpty(strLocation))
                            {
                                intExtendedCount = objCharacter.Cyberware.DeepCount(x => x.Children, objItem => objItem.Name != strIgnoreQuality && string.IsNullOrEmpty(objItem.PlugsIntoModularMount) && lstNamesIncludedInLimit.Any(objLimitName => objLimitName == objItem.Name));
                            }
                            // We only want to check against 'ware that is on the same side as this one
                            else
                            {
                                intExtendedCount = objCharacter.Cyberware.DeepCount(x => x.Children, x => x.Name != strIgnoreQuality && string.IsNullOrEmpty(x.PlugsIntoModularMount) && x.Location == strLocation && lstNamesIncludedInLimit.Any(strName => strName == x.Name));
                            }
                        }
                        else
                        {
                            intExtendedCount = objListToCheck.Count(objItem => objItem.Name != strIgnoreQuality && lstNamesIncludedInLimit.Any(objLimitName => objLimitName == objItem.Name));
                        }
                    }
                }
                if (intCount >= intLimit || intExtendedCount >= intExtendedLimit)
                {
                    if (blnShowMessage)
                    {
                        limitMessage = limitMessage.Replace("{1}", intLimit == 0 ? "1" : intLimit.ToString());
                        MessageBox.Show(limitMessage, limitTitle, MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                    return(false);
                }
            }

            if (objXmlNode.InnerXml.Contains("forbidden"))
            {
                string forbiddenTitle   = LanguageManager.GetString("MessageTitle_SelectGeneric_Restriction").Replace("{0}", strLocalName);
                string forbiddenMessage = LanguageManager.GetString("Message_SelectGeneric_Restriction").Replace("{0}", strLocalName);
                // Loop through the oneof requirements.
                XmlNodeList objXmlForbiddenList = objXmlNode.SelectNodes("forbidden/oneof");
                if (objXmlForbiddenList != null)
                {
                    foreach (XmlNode objXmlOneOf in objXmlForbiddenList)
                    {
                        XmlNodeList objXmlOneOfList = objXmlOneOf.ChildNodes;

                        foreach (XmlNode objXmlForbidden in objXmlOneOfList)
                        {
                            // The character is not allowed to take the Quality, so display a message and uncheck the item.
                            if (TestNodeRequirements(objXmlForbidden, objCharacter, out string name, strIgnoreQuality, objMetatypeDocument,
                                                     objCritterDocument, objQualityDocument))
                            {
                                if (blnShowMessage)
                                {
                                    MessageBox.Show(
                                        forbiddenMessage + name, forbiddenTitle,
                                        MessageBoxButtons.OK, MessageBoxIcon.Information);
                                }
                                return(false);
                            }
                        }
                    }
                }
            }

            if (objXmlNode.InnerXml.Contains("required"))
            {
                string requiredTitle     = LanguageManager.GetString("MessageTitle_SelectGeneric_Requirement").Replace("{0}", strLocalName);
                string requiredMessage   = LanguageManager.GetString("Message_SelectGeneric_Requirement").Replace("{0}", strLocalName);
                string strRequirement    = string.Empty;
                bool   blnRequirementMet = true;

                // Loop through the oneof requirements.
                XmlNodeList objXmlRequiredList = objXmlNode.SelectNodes("required/oneof");
                foreach (XmlNode objXmlOneOf in objXmlRequiredList)
                {
                    bool   blnOneOfMet        = false;
                    string strThisRequirement = "\n" +
                                                LanguageManager.GetString("Message_SelectQuality_OneOf");
                    XmlNodeList objXmlOneOfList = objXmlOneOf.ChildNodes;
                    foreach (XmlNode objXmlRequired in objXmlOneOfList)
                    {
                        blnOneOfMet = TestNodeRequirements(objXmlRequired, objCharacter, out string name, strIgnoreQuality,
                                                           objMetatypeDocument,
                                                           objCritterDocument, objQualityDocument);

                        if (blnOneOfMet)
                        {
                            break;
                        }
                        strThisRequirement += name;
                    }

                    // Update the flag for requirements met.
                    blnRequirementMet = blnRequirementMet && blnOneOfMet;
                    strRequirement   += strThisRequirement;
                }

                if (blnRequirementMet || blnShowMessage)
                {
                    // Loop through the allof requirements.
                    objXmlRequiredList = objXmlNode.SelectNodes("required/allof");
                    foreach (XmlNode objXmlAllOf in objXmlRequiredList)
                    {
                        bool   blnAllOfMet        = true;
                        string strThisRequirement = "\n" +
                                                    LanguageManager.GetString("Message_SelectQuality_AllOf");
                        XmlNodeList objXmlAllOfList = objXmlAllOf.ChildNodes;
                        foreach (XmlNode objXmlRequired in objXmlAllOfList)
                        {
                            bool blnFound = TestNodeRequirements(objXmlRequired, objCharacter, out string name, strIgnoreQuality,
                                                                 objMetatypeDocument,
                                                                 objCritterDocument, objQualityDocument);

                            // If this item was not found, fail the AllOfMet condition.
                            if (!blnFound)
                            {
                                blnAllOfMet = false;
                                if (blnShowMessage)
                                {
                                    strThisRequirement += name;
                                }
                                else
                                {
                                    break;
                                }
                            }
                        }

                        // Update the flag for requirements met.
                        blnRequirementMet = blnRequirementMet && blnAllOfMet;
                        strRequirement   += strThisRequirement;
                    }
                }

                // The character has not met the requirements, so display a message and uncheck the item.
                if (!blnRequirementMet)
                {
                    requiredMessage += strRequirement;

                    if (blnShowMessage)
                    {
                        MessageBox.Show(requiredMessage, requiredTitle,
                                        MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                    return(false);
                }
            }
            return(true);
        }
예제 #17
0
 public void addCharacter(CharacterAttrib obj)
 {
     characters.Add(obj);
 }
예제 #18
0
        public void Load(XmlDocument xmlDoc)
        {
            Timekeeper.Start("load_char_attrib");
            AttributeList.Clear();
            SpecialAttributeList.Clear();
            XmlDocument objXmlDocument = XmlManager.Load(_character.IsCritter ? "critters.xml" : "metatypes.xml");
            XmlNode     objCharNode    = objXmlDocument.SelectSingleNode("/chummer/metatypes/metatype[name = \"" + _character.Metatype + "\"]/metavariants/metavariant[name = \"" + _character.Metavariant + "\"]")
                                         ?? objXmlDocument.SelectSingleNode("/chummer/metatypes/metatype[name = \"" + _character.Metatype + "\"]");
            XmlNode objCharNodeAnimalForm = null;

            // We only want to remake attributes for shifters in career mode, because they only get their second set of attributes when exporting from create mode into career mode
            if (_character.MetatypeCategory == "Shapeshifter" && _character.Created)
            {
                objCharNodeAnimalForm = objXmlDocument.SelectSingleNode("/chummer/metatypes/metatype[name = \"" + _character.Metatype + "\"]");
            }
            foreach (string s in AttributeStrings)
            {
                XmlNodeList attNodeList = xmlDoc.SelectNodes("/character/attributes/attribute[name = \"" + s + "\"]");
                // Couldn't find the appopriate attribute in the loaded file, so regenerate it from scratch.
                if (attNodeList.Count == 0)
                {
                    CharacterAttrib att = new CharacterAttrib(_character, s);
                    att = RemakeAttribute(att, objCharNode);
                    switch (att.ConvertToAttributeCategory(att.Abbrev))
                    {
                    case CharacterAttrib.AttributeCategory.Special:
                        SpecialAttributeList.Add(att);
                        break;

                    case CharacterAttrib.AttributeCategory.Standard:
                        AttributeList.Add(att);
                        break;
                    }
                    if (objCharNodeAnimalForm != null)
                    {
                        att = new CharacterAttrib(_character, s, CharacterAttrib.AttributeCategory.Shapeshifter);
                        att = RemakeAttribute(att, objCharNodeAnimalForm);
                        switch (att.ConvertToAttributeCategory(att.Abbrev))
                        {
                        case CharacterAttrib.AttributeCategory.Special:
                            SpecialAttributeList.Add(att);
                            break;

                        case CharacterAttrib.AttributeCategory.Standard:
                            AttributeList.Add(att);
                            break;
                        }
                    }
                }
                else
                {
                    foreach (XmlNode attNode in attNodeList)
                    {
                        CharacterAttrib att = new CharacterAttrib(_character, s);
                        att.Load(attNode);
                        switch (att.ConvertToAttributeCategory(att.Abbrev))
                        {
                        case CharacterAttrib.AttributeCategory.Special:
                            SpecialAttributeList.Add(att);
                            break;

                        case CharacterAttrib.AttributeCategory.Standard:
                            AttributeList.Add(att);
                            break;
                        }
                    }
                }
            }
            ResetBindings();
            Timekeeper.Finish("load_char_attrib");
        }