Пример #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 = 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;
                    }
                }

                // 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)
                    {
                        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");
        }