void StreamCommandData <TDoc, TCursor>(IO.TagElementStream <TDoc, TCursor, string> s, XML.BXmlSerializerInterface xs)
                where TDoc : class
                where TCursor : class
            {
                const string attr_name = "CommandData";

                switch (CommandType)
                {
                case BProtoObjectCommandType.Research:                 // proto tech
                    xs.StreamDBID(s, attr_name, ref CommandData, DatabaseObjectKind.Tech, false, XML.XmlUtil.kSourceAttr);
                    break;

                case BProtoObjectCommandType.TrainUnit:                 // proto object
                case BProtoObjectCommandType.Build:
                case BProtoObjectCommandType.BuildOther:
                    xs.StreamDBID(s, attr_name, ref CommandData, DatabaseObjectKind.Object, false, XML.XmlUtil.kSourceAttr);
                    break;

                case BProtoObjectCommandType.TrainSquad:                 // proto squad
                    xs.StreamDBID(s, attr_name, ref CommandData, DatabaseObjectKind.Squad, false, XML.XmlUtil.kSourceAttr);
                    break;

                case BProtoObjectCommandType.ChangeMode:                 // unused
                    s.StreamAttributeEnum(attr_name, ref CommandDataSM);
                    break;

                case BProtoObjectCommandType.Ability:
                    xs.StreamDBID(s, attr_name, ref CommandData, DatabaseObjectKind.Ability, false, XML.XmlUtil.kSourceAttr);
                    break;

                case BProtoObjectCommandType.Power:
                    xs.StreamDBID(s, attr_name, ref CommandData, DatabaseObjectKind.Power, false, XML.XmlUtil.kSourceAttr);
                    break;
                }
            }
 public void StreamDamageModifier <TDoc, TCursor>(IO.TagElementStream <TDoc, TCursor, string> s, XML.BXmlSerializerInterface xs)
     where TDoc : class
     where TCursor : class
 {
     xs.StreamDBID(s, "WeaponType", ref DmgMod_WeapType, DatabaseObjectKind.WeaponType, false, XML.XmlUtil.kSourceAttr);
     xs.StreamDBID(s, "DamageType", ref DmgMod_DmgType, DatabaseObjectKind.DamageType, false, XML.XmlUtil.kSourceAttr);
 }
            public void StreamCost <TDoc, TCursor>(IO.TagElementStream <TDoc, TCursor, string> s, XML.BXmlSerializerInterface xs, bool isResourceOptional = false)
                where TDoc : class
                where TCursor : class
            {
                xs.StreamTypeName(s, "Resource", ref Cost_Type, GameDataObjectKind.Cost, isResourceOptional, XML.XmlUtil.kSourceAttr);
                bool streamedUnitType = xs.StreamDBID(s, "UnitType", ref Cost_UnitType, DatabaseObjectKind.Object, true, XML.XmlUtil.kSourceAttr);

                // #HACK deal with hand edited data in Halo Wars
                if (!streamedUnitType && s.IsReading)
                {
                    xs.StreamDBID(s, "unitType", ref Cost_UnitType, DatabaseObjectKind.Object, true, XML.XmlUtil.kSourceAttr);
                }
            }
            public void StreamTrainLimit <TDoc, TCursor>(IO.TagElementStream <TDoc, TCursor, string> s, XML.BXmlSerializerInterface xs, DatabaseObjectKind kind)
                where TDoc : class
                where TCursor : class
            {
                // #NOTE engine parses these as "UnitType" and "SquadType", but its parser ignores case

                if (kind == DatabaseObjectKind.Object)
                {
                    xs.StreamDBID(s, "unitType", ref TrainLimitType, kind, false, XML.XmlUtil.kSourceAttr);
                }
                else if (kind == DatabaseObjectKind.Squad)
                {
                    xs.StreamDBID(s, "squadType", ref TrainLimitType, kind, false, XML.XmlUtil.kSourceAttr);
                }
            }
        void StreamValueID <TDoc, TCursor>(IO.TagElementStream <TDoc, TCursor, string> s, XML.BXmlSerializerInterface xs)
            where TDoc : class
            where TCursor : class
        {
            DatabaseObjectKind kind = ObjectKind;

            if (kind != DatabaseObjectKind.None)
            {
                xs.StreamDBID(s, XML.XmlUtil.kNoXmlName, ref mValueID, kind, false, XML.XmlUtil.kSourceCursor);
            }
        }
        void StreamXmlObjectData <TDoc, TCursor>(IO.TagElementStream <TDoc, TCursor, string> s, XML.BXmlSerializerInterface xs)
            where TDoc : class
            where TCursor : class
        {
            // Unused - SubTypes (with data) which no techs in HW1 made use of
            switch (mDU.SubType)
            {
                #region Unused
            case BObjectDataType.RateAmount:
            case BObjectDataType.RateMultiplier:
                xs.StreamTypeName(s, "Rate", ref mDU.ID, GameDataObjectKind.Rate, false, XML.XmlUtil.kSourceAttr);
                break;
                #endregion

            case BObjectDataType.CommandEnable:
            case BObjectDataType.CommandSelectable:             // Unused
                mDU.StreamCommand(s, xs);
                break;

            case BObjectDataType.Cost:
                mDU.StreamCost(s, xs);
                break;

                #region Unused
            case BObjectDataType.DamageModifier:
                mDU.StreamDamageModifier(s, xs);
                break;
                #endregion

            case BObjectDataType.PopCap:
            case BObjectDataType.PopMax:
                // #NOTE engine parses this as "PopType", but its parser ignores case
                xs.StreamTypeName(s, "popType", ref mDU.ID, GameDataObjectKind.Pop, false, XML.XmlUtil.kSourceAttr);
                break;

                #region Unused
            case BObjectDataType.UnitTrainLimit:
                mDU.StreamTrainLimit(s, xs, DatabaseObjectKind.Object);
                break;

            case BObjectDataType.SquadTrainLimit:
                mDU.StreamTrainLimit(s, xs, DatabaseObjectKind.Squad);
                break;
                #endregion

            case BObjectDataType.PowerRechargeTime:
            case BObjectDataType.PowerUseLimit:
            case BObjectDataType.PowerLevel:
                // #NOTE engine parses this as "Power", but its parser ignores case
                xs.StreamDBID(s, "power", ref mDU.ID, DatabaseObjectKind.Power, false, XML.XmlUtil.kSourceAttr);
                break;

            case BObjectDataType.ImpactEffect:
                // #NOTE engine parses this as "ImpactEffect", but its parser ignores case
                xs.StreamDBID(s, "impactEffect", ref mDU.ID, DatabaseObjectKind.ImpactEffect, false, XML.XmlUtil.kSourceAttr);
                break;

                #region Unused
            case BObjectDataType.DisplayNameID:
                xs.StreamStringID(s, "StringID", ref mDU.ID, XML.XmlUtil.kSourceAttr);
                break;
                #endregion

            case BObjectDataType.Icon:
            // #NOTE engine actually doesn't explicitly handle this case when loading, but it is supported at runtime for Squads
            case BObjectDataType.AltIcon:
                mDU.StreamIcon(s, xs);
                break;

            case BObjectDataType.TurretYawRate:
            case BObjectDataType.TurretPitchRate:
                // #TODO need to validate this type so that Targets.Count==1, TargetType=ProtoUnit, and resolve the Hardpoint name
                s.StreamStringOpt("Hardpoint", ref mDU.TurretRate_HardpointName, false);
                break;

            case BObjectDataType.AbilityRecoverTime:
                xs.StreamDBID(s, "Ability", ref mDU.ID, DatabaseObjectKind.Ability, false, XML.XmlUtil.kSourceAttr);
                break;

            case BObjectDataType.HPBar:
                // #TODO need to make an BProtoHPBar reference
                s.StreamStringOpt("hpbar", ref mDU.HPBar_Name, false);
                break;

                #region Unused
            case BObjectDataType.DeathSpawn:
                xs.StreamDBID(s, "squadName", ref mDU.ID, DatabaseObjectKind.Squad, false, XML.XmlUtil.kSourceAttr);
                break;
                #endregion

                #region Object effects
            // although some apply to squads too
            case BObjectDataType.Enable:             // Amount>0
            case BObjectDataType.Shieldpoints:
            case BObjectDataType.Hitpoints:
            case BObjectDataType.AmmoMax:
            case BObjectDataType.LOS:
            case BObjectDataType.MaximumVelocity:
                #region Weapon effects
            case BObjectDataType.MaximumRange:
            case BObjectDataType.Damage:
            case BObjectDataType.MinRange:
            case BObjectDataType.AOERadius:
            case BObjectDataType.AOEPrimaryTargetFactor:
            case BObjectDataType.AOEDistanceFactor:
            case BObjectDataType.AOEDamageFactor:
            case BObjectDataType.Accuracy:
            case BObjectDataType.MaxDeviation:
            case BObjectDataType.MovingMaxDeviation:
            case BObjectDataType.DataAccuracyDistanceFactor:
            case BObjectDataType.AccuracyDeviationFactor:
            case BObjectDataType.MaxVelocityLead:
            case BObjectDataType.MaxDamagePerRam:
            case BObjectDataType.ReflectDamageFactor:
            case BObjectDataType.AirBurstSpan:
            case BObjectDataType.DOTrate:
            case BObjectDataType.DOTduration:
            case BObjectDataType.Stasis:

            case BObjectDataType.Projectile:
                #endregion
                #region ProtoAction effects
            case BObjectDataType.WorkRate:
            case BObjectDataType.ActionEnable:
            case BObjectDataType.BoardTime:
                #endregion
            case BObjectDataType.BuildPoints:
            case BObjectDataType.AutoCloak:             // Amount>0
            case BObjectDataType.MoveWhileCloaked:      // Amount>0
            case BObjectDataType.AttackWhileCloaked:    // Amount>0
            case BObjectDataType.Bounty:
            case BObjectDataType.MaxContained:
            case BObjectDataType.AbilityDisabled:             // Amount>0
            case BObjectDataType.AmmoRegenRate:
            case BObjectDataType.ShieldRegenRate:
            case BObjectDataType.ShieldRegenDelay:
                #endregion
                #region Squad effects
            case BObjectDataType.Level:
            case BObjectDataType.TechLevel:
                #endregion
            case BObjectDataType.ResearchPoints:             // Tech and TechAll only
                #region Player effects
            case BObjectDataType.ResourceTrickleRate:
            case BObjectDataType.BountyResource:             // Amount!=0, uses Cost
            case BObjectDataType.RepairCost:
            case BObjectDataType.RepairTime:
            case BObjectDataType.WeaponPhysicsMultiplier:
                #endregion
            default:
                mDU.StreamCost(s, xs, isResourceOptional: true);
                break;
            }
        }