Пример #1
0
        public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
        {
            foreach (var at in actorNode.ChildrenMatching("AttackMove"))
            {
                foreach (var node in at.ChildrenMatching("AttackMoveScanCondition"))
                {
                    node.RenameKey("AttackMoveCondition");
                }

                foreach (var node in at.ChildrenMatching("AssaultMoveScanCondition"))
                {
                    node.RenameKey("AssaultMoveCondition");
                }
            }

            yield break;
        }
Пример #2
0
        public override IEnumerable <string> UpdateChromeNode(ModData modData, MiniYamlNode chromeNode)
        {
            foreach (var node in chromeNode.ChildrenMatching("Radar"))
            {
                if (!node.ChildrenMatching("SoundUp").Any())
                {
                    node.AddNode("SoundUp", "RadarUp");
                }

                if (!node.ChildrenMatching("SoundDown").Any())
                {
                    node.AddNode("SoundDown", "RadarDown");
                }
            }

            yield break;
        }
Пример #3
0
        public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
        {
            // Repairable isn't conditional or otherwise supports multiple traits, so LastChildMatching should be fine.
            foreach (var placeBuilding in actorNode.ChildrenMatching("ChronoshiftPower"))
            {
                placeBuilding.RenameChildrenMatching("OverlaySpriteGroup", "FootprintImage");
                placeBuilding.RenameChildrenMatching("InvalidTileSequencePrefix", "InvalidFootprintSequence");
                placeBuilding.RenameChildrenMatching("SourceTileSequencePrefix", "SourceFootprintSequence");
                foreach (var valid in placeBuilding.ChildrenMatching("ValidTileSequencePrefix"))
                {
                    valid.RenameKey("ValidFootprintSequence");
                    valid.Value.Value = valid.Value.Value.Substring(0, valid.Value.Value.Length - 1);
                }
            }

            yield break;
        }
Пример #4
0
        public override IEnumerable <string> UpdateWeaponNode(ModData modData, MiniYamlNode weaponNode)
        {
            foreach (var node in weaponNode.ChildrenMatching("Warhead"))
            {
                if (node.NodeValue <string>() == "HealthPercentageDamage")
                {
                    foreach (var spreadNode in node.ChildrenMatching("Spread"))
                    {
                        var oldValue = spreadNode.NodeValue <string[]>();
                        if (oldValue.Length > 1)
                        {
                            spreadNode.ReplaceValue(oldValue[0]);
                        }
                    }
                }
            }

            yield break;
        }
Пример #5
0
        public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
        {
            foreach (var kv in TraitFields)
            {
                foreach (var traitNode in actorNode.ChildrenMatching(kv.Key))
                {
                    foreach (var fieldName in kv.Value)
                    {
                        foreach (var fieldNode in traitNode.ChildrenMatching(fieldName))
                        {
                            var value = fieldNode.NodeValue <int>();
                            fieldNode.Value.Value = value != -1 ? FieldSaver.FormatValue(value != 255 ? 4 * value : 1023) : "";
                        }
                    }
                }
            }

            yield break;
        }
Пример #6
0
        public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
        {
            foreach (var fallsToEarth in actorNode.ChildrenMatching("FallsToEarth"))
            {
                var spinsNode = fallsToEarth.LastChildMatching("Spins");
                if (spinsNode != null)
                {
                    var spins = spinsNode.NodeValue <bool>();
                    if (!spins)
                    {
                        fallsToEarth.AddNode("MaximumSpinSpeed", "0");
                    }

                    fallsToEarth.RemoveNode(spinsNode);
                    locations.Add("{0} ({1})".F(actorNode.Key, actorNode.Location.Filename));
                }
            }

            yield break;
        }
Пример #7
0
        public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
        {
            var grants = actorNode.ChildrenMatching("GrantConditionOnDeploy");

            foreach (var g in grants)
            {
                var deploy = g.LastChildMatching("DeploySound");
                if (deploy != null)
                {
                    deploy.RenameKey("DeploySounds");
                }

                var undeploy = g.LastChildMatching("UndeploySound");
                if (undeploy != null)
                {
                    undeploy.RenameKey("UndeploySounds");
                }
            }

            yield break;
        }
Пример #8
0
        public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
        {
            foreach (var aircraft in actorNode.ChildrenMatching("Aircraft"))
            {
                var canHover = aircraft.LastChildMatching("CanHover");
                if (canHover != null && canHover.NodeValue <bool>())
                {
                    if (!aircraft.ChildrenMatching("TakeOffOnResupply").Any())
                    {
                        aircraft.AddNode("TakeOffOnResupply", true);
                    }

                    if (!aircraft.ChildrenMatching("VTOL").Any())
                    {
                        aircraft.AddNode("VTOL", true);
                    }
                }
            }

            yield break;
        }
Пример #9
0
        public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
        {
            foreach (var a in actorNode.ChildrenMatching("Armament"))
            {
                var muzzleSplitFacings = a.LastChildMatching("MuzzleSplitFacings");
                var sequenceNode       = a.LastChildMatching("MuzzleSequence");
                if (muzzleSplitFacings != null && sequenceNode != null)
                {
                    var sequence = sequenceNode.Value.Value;
                    var facings  = muzzleSplitFacings.NodeValue <int>() - 1;
                    var actor    = actorNode.Key.ToLowerInvariant();
                    yield return("The Armament muzzle effect has been removed from {0} ({1}).\n".F(actor, actorNode.Location.Filename) +
                                 "If you would like to restore the muzzle effect you must redefine `MuzzleSequence: {0}`\n".F(sequence) +
                                 "and replace the {0}0-{1} sequence definitions with a single `{0}` sequence that uses\n".F(sequence, facings) +
                                 "the Combine syntax to assemble the different facing sprites.");

                    a.RemoveNode(muzzleSplitFacings);
                    a.RemoveNode(sequenceNode);
                }
            }
        }
Пример #10
0
        public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
        {
            if (actorNode.Key != "Player")
            {
                yield break;
            }

            var hackyAIs = actorNode.ChildrenMatching("HackyAI");

            if (!hackyAIs.Any())
            {
                yield break;
            }

            foreach (var hackyAINode in hackyAIs)
            {
                // We no longer support individual values for each AI,
                // and in practice the default of 5 has proven to be a solid middle-ground,
                // so just removing any custom value and notifying the modder about it should suffice.
                var minQuotient = hackyAINode.LastChildMatching("MinOrderQuotientPerTick");
                if (minQuotient != null)
                {
                    hackyAINode.RemoveNode(minQuotient);
                    if (!showMessage)
                    {
                        showMessage = true;
                    }
                }
            }

            var botOrderManager = actorNode.LastChildMatching("BotOrderManager");

            if (botOrderManager == null)
            {
                var addBotOrderManager = new MiniYamlNode("BotOrderManager", "");
                actorNode.AddNode(addBotOrderManager);
            }

            yield break;
        }
Пример #11
0
        public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
        {
            var aircraftTraits = actorNode.ChildrenMatching("Aircraft");

            foreach (var aircraft in aircraftTraits)
            {
                var canHover     = false;
                var canHoverNode = aircraft.LastChildMatching("CanHover");
                if (canHoverNode != null)
                {
                    canHover = canHoverNode.NodeValue <bool>();
                }
                else
                {
                    yield break;
                }

                aircraft.AddNode("CanSlide", canHover.ToString());
            }

            yield break;
        }
        public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
        {
            var nukePowerTraits = actorNode.ChildrenMatching("NukePower");

            foreach (var nukePowerTrait in nukePowerTraits)
            {
                var traitName  = nukePowerTrait.Key;
                var weaponNode = nukePowerTrait.ChildrenMatching("MissileWeapon").FirstOrDefault();
                if (weaponNode == null)
                {
                    continue;
                }

                var weaponName = weaponNode.Value.Value;

                weaponsToUpdate.Add(new Tuple <string, string, string>(weaponName, traitName, "{0} ({1})".F(actorNode.Key, actorNode.Location.Filename)));

                nukePowerTrait.RemoveNodes("FlashType");
            }

            yield break;
        }
Пример #13
0
        public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
        {
            var modId = modData.Manifest.Id;

            foreach (var bo in actorNode.ChildrenMatching("BodyOrientation"))
            {
                var usesClassicFacings = false;
                var facingFudgeNode    = bo.LastChildMatching("UseClassicFacingFudge");
                if (facingFudgeNode != null)
                {
                    usesClassicFacings = facingFudgeNode.NodeValue <bool>();
                    bo.RemoveNode(facingFudgeNode);
                }

                if (usesClassicFacings)
                {
                    bo.RenameKey("ClassicFacingBodyOrientation");
                    locations.Add("{0} ({1})".F(actorNode.Key, actorNode.Location.Filename));
                }
            }

            yield break;
        }
Пример #14
0
        public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
        {
            foreach (var t in traits)
            {
                foreach (var traitNode in actorNode.ChildrenMatching(t.Trait))
                {
                    foreach (var f in t.Fields)
                    {
                        var node = traitNode.LastChildMatching(f.Key);
                        if (node == null)
                        {
                            var location = "{0} ({1})".F(actorNode.Key, traitNode.Location.Filename);
                            if (!t.Uses.Contains(location))
                            {
                                t.Uses.Add(location);
                            }
                        }
                    }
                }
            }

            yield break;
        }
        public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
        {
            foreach (var gcod in actorNode.ChildrenMatching("GrantConditionOnDeploy"))
            {
                var canUndeploy = gcod.LastChildMatching("CanUndeploy");
                if (canUndeploy == null)
                {
                    continue;
                }

                gcod.RemoveNode(canUndeploy);

                if (canUndeploy.NodeValue <bool>())
                {
                    continue;
                }

                var deployedCondition = gcod.LastChildMatching("DeployedCondition");
                gcod.AddNode("PauseOnCondition", deployedCondition.Value.Value);
            }

            yield break;
        }
        public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
        {
            var nukePowers = actorNode.ChildrenMatching("NukePower").ToList();

            foreach (var nuke in nukePowers)
            {
                var activation = nuke.LastChildMatching("ActivationSequence");
                if (activation == null)
                {
                    continue;
                }

                var sequence = activation.NodeValue <string>();
                nuke.RemoveNode(activation);
                actorNode.AddNode("WithNukeLaunchAnimation", "");
                if (sequence != "active")
                {
                    actorNode.LastChildMatching("WithNukeLaunchAnimation").AddNode("Sequence", sequence);
                }
            }

            yield break;
        }
        public override IEnumerable <string> UpdateWeaponNode(ModData modData, MiniYamlNode weaponNode)
        {
            var used = new List <string>();

            foreach (var node in weaponNode.ChildrenMatching("Warhead"))
            {
                foreach (var warhead in DamageWarheads)
                {
                    if (node.NodeValue <string>() == warhead && node.ChildrenMatching("Damage").Any(d => d.NodeValue <int>() < 0))
                    {
                        used.Add(node.Key);
                    }
                }

                if (used.Any())
                {
                    var location = "{0} ({1})".F(weaponNode.Key, node.Location.Filename);
                    locations[location] = used;
                }
            }

            yield break;
        }
Пример #18
0
        public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
        {
            foreach (var layer in actorNode.ChildrenMatching("SmudgeLayer"))
            {
                var chance = layer.LastChildMatching("SmokePercentage");
                if (chance != null)
                {
                    chance.RenameKey("SmokeChance");
                }
                else
                {
                    layer.AddNode("SmokeChance", FieldSaver.FormatValue("25"));
                }

                var image = layer.LastChildMatching("SmokeType");
                if (image != null)
                {
                    image.RenameKey("SmokeImage");
                }
                else
                {
                    layer.AddNode("SmokeImage", FieldSaver.FormatValue("smoke_m"));
                }

                var sequences = layer.LastChildMatching("SmokeSequence");
                if (sequences != null)
                {
                    sequences.RenameKey("SmokeSequences");
                }
                else
                {
                    layer.AddNode("SmokeSequences", FieldSaver.FormatValue("idle"));
                }
            }

            yield break;
        }
Пример #19
0
        public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
        {
            var addNodes = new List <MiniYamlNode>();

            foreach (var burns in actorNode.ChildrenMatching("Burns"))
            {
                var anim      = burns.LastChildMatching("Anim");
                var animValue = anim != null?anim.NodeValue <string>() : "1";

                var damage      = burns.LastChildMatching("Damage");
                var damageValue = damage != null?damage.NodeValue <int>() : 1;

                var interval      = burns.LastChildMatching("Interval");
                var intervalValue = interval != null?interval.NodeValue <int>() : 8;

                var overlay = new MiniYamlNode("WithIdleOverlay@Burns", "");
                overlay.AddNode("Image", FieldSaver.FormatValue("fire"));
                overlay.AddNode("Sequence", FieldSaver.FormatValue(animValue));
                overlay.AddNode("IsDecoration", FieldSaver.FormatValue(true));
                addNodes.Add(overlay);

                var changesHealth = new MiniYamlNode("ChangesHealth", "");
                changesHealth.AddNode("Step", FieldSaver.FormatValue(-damageValue));
                changesHealth.AddNode("StartIfBelow", FieldSaver.FormatValue(101));
                changesHealth.AddNode("Delay", FieldSaver.FormatValue(intervalValue));
                addNodes.Add(changesHealth);
            }

            actorNode.RemoveNodes("Burns");

            foreach (var addNode in addNodes)
            {
                actorNode.AddNode(addNode);
            }

            yield break;
        }
Пример #20
0
        public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
        {
            var aircraft       = actorNode.LastChildMatching("Aircraft");
            var attackAircraft = actorNode.ChildrenMatching("AttackAircraft");

            if (aircraft != null)
            {
                var abortOnResupply = aircraft.LastChildMatching("AbortOnResupply");
                if (abortOnResupply == null)
                {
                    yield break;
                }

                // Only add field to AttackAircraft if explicitly set to 'false'
                if (!abortOnResupply.NodeValue <bool>())
                {
                    if (attackAircraft.Any())
                    {
                        foreach (var a in attackAircraft)
                        {
                            a.AddNode(abortOnResupply);
                        }
                    }
                    else
                    {
                        var newAttackAircraft = new MiniYamlNode("AttackAircraft", "");
                        newAttackAircraft.AddNode(abortOnResupply);
                        actorNode.AddNode(newAttackAircraft);
                    }
                }

                aircraft.RemoveNode(abortOnResupply);
            }

            yield break;
        }
Пример #21
0
        public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
        {
            var addNodes = new List <MiniYamlNode>();

            var aircraft = modData.DefaultRules.Actors.Values.Where(a => a.HasTraitInfo <AircraftInfo>() && a.HasTraitInfo <AttackBaseInfo>()).Select(a => a.Name);
            var airUnits = new MiniYamlNode("AirUnitsTypes", FieldSaver.FormatValue(aircraft.ToList()));

            addNodes.Add(airUnits);

            var vips       = modData.DefaultRules.Actors.Values.Where(a => a.HasTraitInfo <HarvesterInfo>() || a.HasTraitInfo <BaseBuildingInfo>() || (a.HasTraitInfo <BuildingInfo>() && a.HasTraitInfo <BuildableInfo>() && !a.HasTraitInfo <LineBuildInfo>() && !a.HasTraitInfo <PlugInfo>())).Select(a => a.Name);
            var protection = new MiniYamlNode("ProtectionTypes", FieldSaver.FormatValue(vips.ToList()));

            addNodes.Add(protection);

            foreach (var squadManager in actorNode.ChildrenMatching("SquadManagerBotModule"))
            {
                foreach (var addNode in addNodes)
                {
                    squadManager.AddNode(addNode);
                }
            }

            yield break;
        }
Пример #22
0
        public override IEnumerable <string> UpdateWeaponNode(ModData modData, MiniYamlNode weaponNode)
        {
            foreach (var projectileNode in weaponNode.ChildrenMatching("Projectile"))
            {
                if (projectileNode.Value.Value == null)
                {
                    continue;
                }

                if (ProjectileFields.TryGetValue(projectileNode.Value.Value, out var fieldNames))
                {
                    foreach (var fieldName in fieldNames)
                    {
                        foreach (var fieldNode in projectileNode.ChildrenMatching(fieldName))
                        {
                            var value = fieldNode.NodeValue <int>();
                            fieldNode.Value.Value = FieldSaver.FormatValue(value != 255 ? 4 * value : 1023);
                        }
                    }
                }
            }

            yield break;
        }
Пример #23
0
 public static MiniYamlNode LastChildMatching(this MiniYamlNode node, string match, bool includeRemovals = true)
 {
     return(node.ChildrenMatching(match, includeRemovals: includeRemovals).LastOrDefault());
 }
Пример #24
0
        public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
        {
            foreach (var resourceNode in actorNode.ChildrenMatching("ResourceType"))
            {
                var typeNode = resourceNode.LastChildMatching("Type");
                if (typeNode != null)
                {
                    var resourceLayerNode = new MiniYamlNode(typeNode.Value.Value, "");
                    resourceLayer.Nodes.Add(resourceLayerNode);

                    var resourceRendererNode = new MiniYamlNode(typeNode.Value.Value, "");
                    resourceRenderer.Nodes.Add(resourceRendererNode);

                    var indexNode = resourceNode.LastChildMatching("ResourceType");
                    if (indexNode != null)
                    {
                        indexNode.RenameKey("ResourceIndex");
                        resourceLayerNode.AddNode(indexNode);
                    }

                    var terrainTypeNode = resourceNode.LastChildMatching("TerrainType");
                    if (terrainTypeNode != null)
                    {
                        resourceLayerNode.AddNode(terrainTypeNode);
                    }

                    var allowedTerrainNode = resourceNode.LastChildMatching("AllowedTerrainTypes");
                    if (allowedTerrainNode != null)
                    {
                        resourceLayerNode.AddNode(allowedTerrainNode);
                    }

                    var maxDensityNode = resourceNode.LastChildMatching("MaxDensity");
                    if (maxDensityNode != null)
                    {
                        resourceLayerNode.AddNode(maxDensityNode);
                    }

                    var valueNode = resourceNode.LastChildMatching("ValuePerUnit");
                    if (valueNode != null)
                    {
                        values.Nodes.Add(new MiniYamlNode(typeNode.Value.Value, valueNode.Value.Value));
                    }

                    var imageNode = resourceNode.LastChildMatching("Image");
                    if (imageNode != null)
                    {
                        resourceRendererNode.AddNode(imageNode);
                    }

                    var sequencesNode = resourceNode.LastChildMatching("Sequences");
                    if (sequencesNode != null)
                    {
                        resourceRendererNode.AddNode(sequencesNode);
                    }

                    var paletteNode = resourceNode.LastChildMatching("Palette");
                    if (paletteNode != null)
                    {
                        resourceRendererNode.AddNode(paletteNode);
                    }

                    var nameNode = resourceNode.LastChildMatching("Name");
                    if (nameNode != null)
                    {
                        resourceRendererNode.AddNode(nameNode);
                    }
                }
                else
                {
                    yield return("Unable to process definition:\n" +
                                 resourceNode.Value.ToLines(resourceNode.Key).JoinWith("\n") + "\n\n" +
                                 "This override has been removed and must be manually reimplemented if still needed.");
                }
            }

            actorNode.RemoveNodes("ResourceType");

            foreach (var resourceRendererNode in actorNode.ChildrenMatching("ResourceRenderer"))
            {
                resourceRendererNode.RemoveNodes("RenderTypes");
            }

            foreach (var resourceRendererNode in actorNode.ChildrenMatching("D2kResourceRenderer"))
            {
                resourceRendererNode.RemoveNodes("RenderTypes");
            }
        }
        public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
        {
            foreach (var announce in actorNode.ChildrenMatching("AnnounceOnKill"))
            {
                var intervalNode = announce.LastChildMatching("Interval");
                if (intervalNode != null)
                {
                    var interval = intervalNode.NodeValue <int>();
                    intervalNode.Value.Value = FieldSaver.FormatValue(interval * 1000);
                }
            }

            foreach (var notifier in actorNode.ChildrenMatching("BaseAttackNotifier"))
            {
                var notifyIntervalNode = notifier.LastChildMatching("NotifyInterval");
                if (notifyIntervalNode != null)
                {
                    var notifyInterval = notifyIntervalNode.NodeValue <int>();
                    notifyIntervalNode.Value.Value = FieldSaver.FormatValue(notifyInterval * 1000);
                }
            }

            foreach (var notifier in actorNode.ChildrenMatching("HarvesterAttackNotifier"))
            {
                var notifyIntervalNode = notifier.LastChildMatching("NotifyInterval");
                if (notifyIntervalNode != null)
                {
                    var notifyInterval = notifyIntervalNode.NodeValue <int>();
                    notifyIntervalNode.Value.Value = FieldSaver.FormatValue(notifyInterval * 1000);
                }
            }

            foreach (var rsw in actorNode.ChildrenMatching("ResourceStorageWarning"))
            {
                var adviceIntervalNode = rsw.LastChildMatching("AdviceInterval");
                if (adviceIntervalNode != null)
                {
                    var adviceInterval = adviceIntervalNode.NodeValue <int>();
                    adviceIntervalNode.Value.Value = FieldSaver.FormatValue(adviceInterval * 1000);
                }
            }

            foreach (var pm in actorNode.ChildrenMatching("PowerManager"))
            {
                var adviceIntervalNode = pm.LastChildMatching("AdviceInterval");
                if (adviceIntervalNode != null)
                {
                    var adviceInterval = adviceIntervalNode.NodeValue <int>();
                    adviceIntervalNode.Value.Value = FieldSaver.FormatValue(adviceInterval * 40);
                }
            }

            foreach (var pr in actorNode.ChildrenMatching("PlayerResources"))
            {
                var noFundsIntervalNode = pr.LastChildMatching("InsufficientFundsNotificationDelay");
                if (noFundsIntervalNode != null)
                {
                    var noFundsInterval = noFundsIntervalNode.NodeValue <int>();
                    noFundsIntervalNode.Value.Value = FieldSaver.FormatValue(noFundsInterval * 40);
                    noFundsIntervalNode.RenameKey("InsufficientFundsNotificationInterval");
                }
            }

            yield break;
        }
        public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
        {
            var rearmAnims       = actorNode.ChildrenMatching("WithRearmAnimation");
            var repairAnims      = actorNode.ChildrenMatching("WithRepairAnimation");
            var rearmAnimsTotal  = rearmAnims.Count();
            var repairAnimsTotal = repairAnims.Count();

            if (rearmAnimsTotal == 0 && repairAnimsTotal == 0)
            {
                yield break;
            }
            else if (rearmAnimsTotal == 1 && repairAnimsTotal == 0)
            {
                foreach (var rearmAnim in rearmAnims)
                {
                    rearmAnim.RenameKey("WithResupplyAnimation");
                }
            }
            else if (rearmAnimsTotal == 0 && repairAnimsTotal == 1)
            {
                foreach (var repairAnim in repairAnims)
                {
                    repairAnim.RenameKey("WithResupplyAnimation");
                }
            }
            else if (rearmAnimsTotal == 1 && repairAnimsTotal == 1)
            {
                var rearmAnim         = rearmAnims.First();
                var repairAnim        = repairAnims.First();
                var rearmSequence     = rearmAnim.LastChildMatching("Sequence");
                var rearmBody         = rearmAnim.LastChildMatching("Body");
                var repairSequence    = repairAnim.LastChildMatching("Sequence");
                var repairBody        = repairAnim.LastChildMatching("Body");
                var matchingSequences = (rearmSequence == null && repairSequence == null) ||
                                        (rearmSequence != null && repairSequence != null && rearmSequence.Value.Value == repairSequence.Value.Value);
                var matchingBodies = (rearmBody == null && repairBody == null) ||
                                     (rearmBody != null && repairBody != null && rearmBody.Value.Value == repairBody.Value.Value);

                // If neither animation strays from the default values, we can safely merge them
                if (matchingSequences && matchingBodies)
                {
                    rearmAnim.RenameKey("WithResupplyAnimation");
                    actorNode.RemoveNode(repairAnim);
                }
                else
                {
                    rearmAnim.RenameKey("WithResupplyAnimation@Rearm", false, true);
                    repairAnim.RenameKey("WithResupplyAnimation@Repair", false, true);
                }
            }
            else
            {
                // If we got here, we have more than one of at least one of the two animation traits.
                var rearmAnimCount = 0;
                foreach (var rearmAnim in rearmAnims)
                {
                    ++rearmAnimCount;
                    rearmAnim.RenameKey("WithResupplyAnimation@Rearm" + rearmAnimCount.ToString(), false, true);
                    var playOnRearmNode = new MiniYamlNode("PlayAnimationOn", "Rearm");
                    rearmAnim.AddNode(playOnRearmNode);
                }

                var repairAnimCount = 0;
                foreach (var repairAnim in repairAnims)
                {
                    ++repairAnimCount;
                    repairAnim.RenameKey("WithResupplyAnimation@Repair" + repairAnimCount.ToString(), false, true);
                    var playOnRepairNode = new MiniYamlNode("PlayAnimationOn", "Repair");
                    repairAnim.AddNode(playOnRepairNode);
                }
            }

            yield break;
        }
Пример #27
0
        public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
        {
            if (actorNode.Key != "Player")
            {
                yield break;
            }

            var dummyAIs = actorNode.ChildrenMatching("DummyAI");

            foreach (var dummyAINode in dummyAIs)
            {
                dummyAINode.RenameKey("DummyBot");
            }

            var hackyAIRemovals = actorNode.ChildrenMatching("-HackyAI");

            foreach (var hackyAIRemovalNode in hackyAIRemovals)
            {
                hackyAIRemovalNode.RenameKey("-ModularBot");
            }

            var hackyAIs = actorNode.ChildrenMatching("HackyAI", includeRemovals: false);

            if (!hackyAIs.Any())
            {
                yield break;
            }

            var addNodes = new List <MiniYamlNode>();

            // We add a 'default' HarvesterBotModule in any case (unless the file doesn't contain any HackyAI base definition),
            // and only add more for AIs that define custom values for one of its fields.
            var defaultHarvNode = new MiniYamlNode("HarvesterBotModule", "");

            // We add a 'default' BuildingRepairBotModule in any case,
            // and just don't enable it for AIs that had 'ShouldRepairBuildings: false'.
            var defaultRepairNode = new MiniYamlNode("BuildingRepairBotModule", "");

            foreach (var hackyAINode in hackyAIs)
            {
                // HackyAIInfo.Name might contain spaces, so Type is better suited to be used as condition name.
                // Type can be 'null' if the place we're updating is overriding the default rules (like a map's rules.yaml).
                // If that's the case, it's better to not perform most of the updates on this particular yaml file,
                // as most - or more likely all - necessary updates will already have been performed on the base ai yaml.
                var aiTypeNode = hackyAINode.LastChildMatching("Type");
                var aiType     = aiTypeNode != null?aiTypeNode.NodeValue <string>() : null;

                if (aiType == null)
                {
                    locations.Add("{0} ({1})".F(hackyAINode.Key, hackyAINode.Location.Filename));
                    continue;
                }

                var conditionString = "enable-" + aiType + "-ai";

                var addGrantConditionOnBotOwner = true;

                // Don't add GrantConditionOnBotOwner if it's already been added with matching condition
                var grantBotConditions = actorNode.ChildrenMatching("GrantConditionOnBotOwner");
                foreach (var grant in grantBotConditions)
                {
                    if (grant.LastChildMatching("Condition").NodeValue <string>() == conditionString)
                    {
                        addGrantConditionOnBotOwner = false;
                    }
                }

                if (addGrantConditionOnBotOwner)
                {
                    var grantNode      = new MiniYamlNode("GrantConditionOnBotOwner@" + aiType, "");
                    var grantCondition = new MiniYamlNode("Condition", conditionString);
                    var bot            = new MiniYamlNode("Bots", aiType);
                    grantNode.AddNode(grantCondition);
                    grantNode.AddNode(bot);
                    addNodes.Add(grantNode);
                }

                if (harvesterFields.Any(f => hackyAINode.ChildrenMatching(f).Any()))
                {
                    var harvNode = new MiniYamlNode("HarvesterBotModule@" + aiType, "");
                    harvNode.AddNode(new MiniYamlNode("RequiresCondition", conditionString));

                    foreach (var hf in harvesterFields)
                    {
                        var fieldNode = hackyAINode.LastChildMatching(hf);
                        if (fieldNode != null)
                        {
                            if (hf == "AssignRolesInterval")
                            {
                                fieldNode.MoveAndRenameNode(hackyAINode, harvNode, "ScanForIdleHarvestersInterval");
                            }
                            else
                            {
                                fieldNode.MoveNode(hackyAINode, harvNode);
                            }
                        }
                    }

                    addNodes.Add(harvNode);
                }
                else
                {
                    // We want the default harvester module to be enabled for every AI that didn't customise one of its fields,
                    // so we need to update RequiresCondition to be enabled on any of the conditions granted by these AIs,
                    // but only if the condition hasn't been added yet.
                    var requiresConditionNode = defaultHarvNode.LastChildMatching("RequiresCondition");
                    if (requiresConditionNode == null)
                    {
                        defaultHarvNode.AddNode(new MiniYamlNode("RequiresCondition", conditionString));
                    }
                    else
                    {
                        var oldValue = requiresConditionNode.NodeValue <string>();
                        if (oldValue.Contains(conditionString))
                        {
                            continue;
                        }

                        requiresConditionNode.ReplaceValue(oldValue + " || " + conditionString);
                    }
                }

                if (supportPowerFields.Any(f => hackyAINode.ChildrenMatching(f).Any()))
                {
                    var spNode = new MiniYamlNode("SupportPowerBotModule@" + aiType, "");
                    spNode.AddNode(new MiniYamlNode("RequiresCondition", conditionString));

                    foreach (var spf in supportPowerFields)
                    {
                        var fieldNode = hackyAINode.LastChildMatching(spf);
                        if (fieldNode != null)
                        {
                            fieldNode.MoveAndRenameNode(hackyAINode, spNode, "Decisions");
                        }
                    }

                    addNodes.Add(spNode);
                }

                if (baseBuilderFields.Any(f => hackyAINode.ChildrenMatching(f).Any()))
                {
                    var bmNode = new MiniYamlNode("BaseBuilderBotModule@" + aiType, "");
                    bmNode.AddNode(new MiniYamlNode("RequiresCondition", conditionString));

                    foreach (var bmf in baseBuilderFields)
                    {
                        var fieldNode = hackyAINode.LastChildMatching(bmf);
                        if (fieldNode != null)
                        {
                            if (fieldNode.KeyMatches("BuildingFractions", includeRemovals: false))
                            {
                                var buildingNodes = fieldNode.Value.Nodes;
                                foreach (var n in buildingNodes)
                                {
                                    ConvertFractionToInteger(n);
                                }
                            }

                            if (copyBaseBuilderFields.Any(f => f == bmf))
                            {
                                bmNode.AddNode(fieldNode);
                            }
                            else if (fieldNode.KeyMatches("BuildingCommonNames", includeRemovals: false))
                            {
                                foreach (var n in fieldNode.Value.Nodes)
                                {
                                    bmNode.AddNode(n.Key + "Types", n.Value.Value);
                                }
                            }
                            else
                            {
                                fieldNode.MoveNode(hackyAINode, bmNode);
                            }
                        }
                    }

                    addNodes.Add(bmNode);
                }

                // We want the default repair module to be enabled for every AI that didn't disable 'ShouldRepairBuildings',
                // so we need to update RequiresCondition to be enabled on any of the conditions granted by these AIs,
                // but only if the condition hasn't been added yet.
                var shouldRepairNode     = hackyAINode.LastChildMatching("ShouldRepairBuildings");
                var enableBuildingRepair = shouldRepairNode == null || shouldRepairNode.NodeValue <bool>();
                if (enableBuildingRepair)
                {
                    var requiresConditionNode = defaultRepairNode.LastChildMatching("RequiresCondition");
                    if (requiresConditionNode == null)
                    {
                        defaultRepairNode.AddNode(new MiniYamlNode("RequiresCondition", conditionString));
                    }
                    else
                    {
                        var oldValue = requiresConditionNode.NodeValue <string>();
                        if (oldValue.Contains(conditionString))
                        {
                            continue;
                        }

                        requiresConditionNode.ReplaceValue(oldValue + " || " + conditionString);
                    }
                }

                if (captureManagerFields.Any(f => hackyAINode.ChildrenMatching(f).Any()))
                {
                    var node = new MiniYamlNode("CaptureManagerBotModule@" + aiType, "");
                    node.AddNode(new MiniYamlNode("RequiresCondition", conditionString));

                    foreach (var field in captureManagerFields)
                    {
                        var fieldNode = hackyAINode.LastChildMatching(field);
                        if (fieldNode != null)
                        {
                            fieldNode.MoveNode(hackyAINode, node);
                        }
                    }

                    addNodes.Add(node);
                }

                if (squadManagerFields.Any(f => hackyAINode.ChildrenMatching(f).Any()))
                {
                    var node = new MiniYamlNode("SquadManagerBotModule@" + aiType, "");
                    node.AddNode(new MiniYamlNode("RequiresCondition", conditionString));

                    foreach (var field in squadManagerFields)
                    {
                        var fieldNode = hackyAINode.LastChildMatching(field);
                        if (fieldNode != null)
                        {
                            if (fieldNode.KeyMatches("UnitsCommonNames", includeRemovals: false))
                            {
                                var mcvNode        = fieldNode.LastChildMatching("Mcv");
                                var excludeNode    = fieldNode.LastChildMatching("ExcludeFromSquads");
                                var navalUnitsNode = fieldNode.LastChildMatching("NavalUnits");

                                // In the old code, actors listed under Mcv were also excluded from squads.
                                // However, Mcv[Types] is moved to McvManagerBotModule now, so we need to add them under ExcludeFromSquads as well.
                                if (excludeNode == null && mcvNode != null)
                                {
                                    node.AddNode("ExcludeFromSquadsTypes", mcvNode.Value.Value);
                                }
                                else if (excludeNode != null && mcvNode != null)
                                {
                                    var mcvValue     = mcvNode.NodeValue <string>();
                                    var excludeValue = excludeNode.NodeValue <string>();
                                    node.AddNode("ExcludeFromSquadsTypes", excludeValue + ", " + mcvValue);
                                }

                                if (navalUnitsNode != null)
                                {
                                    node.AddNode("NavalUnitsTypes", navalUnitsNode.Value.Value);
                                }
                            }
                            else if (fieldNode.KeyMatches("BuildingCommonNames", includeRemovals: false))
                            {
                                foreach (var b in fieldNode.Value.Nodes)
                                {
                                    if (squadManagerCommonNames.Any(f => f == b.Key))
                                    {
                                        node.AddNode(b.Key + "Types", b.Value.Value);
                                    }
                                }
                            }
                            else if (fieldNode.KeyMatches("AssignRolesInterval") || fieldNode.KeyMatches("MaxBaseRadius"))
                            {
                                node.AddNode(fieldNode.Key, fieldNode.Value.Value);
                            }
                            else
                            {
                                fieldNode.MoveNode(hackyAINode, node);
                            }
                        }
                    }

                    addNodes.Add(node);
                }

                if (unitBuilderFields.Any(f => hackyAINode.ChildrenMatching(f).Any()))
                {
                    var node = new MiniYamlNode("UnitBuilderBotModule@" + aiType, "");
                    node.AddNode(new MiniYamlNode("RequiresCondition", conditionString));

                    foreach (var field in unitBuilderFields)
                    {
                        var fieldNode = hackyAINode.LastChildMatching(field);
                        if (fieldNode != null)
                        {
                            if (fieldNode.KeyMatches("UnitsToBuild", includeRemovals: false))
                            {
                                var unitNodes = fieldNode.Value.Nodes;
                                foreach (var n in unitNodes)
                                {
                                    ConvertFractionToInteger(n);
                                }
                            }

                            fieldNode.MoveNode(hackyAINode, node);
                        }
                    }

                    addNodes.Add(node);
                }

                if (mcvManagerFields.Any(f => hackyAINode.ChildrenMatching(f).Any()))
                {
                    var node = new MiniYamlNode("McvManagerBotModule@" + aiType, "");
                    node.AddNode(new MiniYamlNode("RequiresCondition", conditionString));

                    foreach (var field in mcvManagerFields)
                    {
                        var fieldNode = hackyAINode.LastChildMatching(field);
                        if (fieldNode != null)
                        {
                            if (fieldNode.KeyMatches("UnitsCommonNames", includeRemovals: false))
                            {
                                var mcvNode = fieldNode.LastChildMatching("Mcv");
                                if (mcvNode != null)
                                {
                                    mcvNode.MoveAndRenameNode(hackyAINode, node, "McvTypes");
                                }

                                // Nothing left that needs UnitCommonNames, so we can finally remove it
                                hackyAINode.RemoveNode(fieldNode);
                            }
                            else if (fieldNode.KeyMatches("BuildingCommonNames", includeRemovals: false))
                            {
                                foreach (var n in fieldNode.Value.Nodes)
                                {
                                    if (n.KeyMatches("VehiclesFactory"))
                                    {
                                        node.AddNode("McvFactoryTypes", n.Value.Value);
                                    }
                                    else if (n.KeyMatches("ConstructionYard"))
                                    {
                                        node.AddNode("ConstructionYardTypes", n.Value.Value);
                                    }
                                }

                                // Nothing left that needs BuildingCommonNames, so we can finally remove it
                                hackyAINode.RemoveNode(fieldNode);
                            }
                            else
                            {
                                fieldNode.MoveNode(hackyAINode, node);
                            }
                        }
                    }

                    addNodes.Add(node);
                }

                hackyAINode.RenameKey("ModularBot");
            }

            // Only add module if any bot is using/enabling it.
            var harvRequiresConditionNode = defaultHarvNode.LastChildMatching("RequiresCondition");

            if (harvRequiresConditionNode != null)
            {
                addNodes.Add(defaultHarvNode);
            }

            // Only add module if any bot is using/enabling it.
            var repRequiresConditionNode = defaultRepairNode.LastChildMatching("RequiresCondition");

            if (repRequiresConditionNode != null)
            {
                addNodes.Add(defaultRepairNode);
            }

            foreach (var node in addNodes)
            {
                actorNode.AddNode(node);
            }

            yield break;
        }
Пример #28
0
        public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
        {
            var locationKey = $"{actorNode.Key} ({actorNode.Location.Filename})";
            var anyConditionalSmokeTrail = false;

            foreach (var smokeTrail in actorNode.ChildrenMatching("SmokeTrailWhenDamaged"))
            {
                var spriteNode = smokeTrail.LastChildMatching("Sprite");
                if (spriteNode != null)
                {
                    smokeTrail.RenameChildrenMatching("Sprite", "Image");
                }
                else
                {
                    smokeTrail.AddNode("Image", FieldSaver.FormatValue("smokey"));
                }

                var intervalNode = smokeTrail.LastChildMatching("Interval");
                if (intervalNode != null)
                {
                    var interval = intervalNode.NodeValue <int>();
                    smokeTrail.RenameChildrenMatching("Interval", "MovingInterval");
                    smokeTrail.AddNode("StationaryInterval", FieldSaver.FormatValue(interval));
                }
                else
                {
                    smokeTrail.AddNode("MovingInterval", FieldSaver.FormatValue(3));
                    smokeTrail.AddNode("StationaryInterval", FieldSaver.FormatValue(3));
                }

                var minDamageNode = smokeTrail.LastChildMatching("MinDamage");
                var isConditional = true;
                if (minDamageNode != null)
                {
                    var minDamage = minDamageNode.NodeValue <string>();
                    if (minDamage == "Undamaged")
                    {
                        isConditional = false;
                    }
                    else if (minDamage != "Heavy")
                    {
                        locations.GetOrAdd(locationKey).Add(smokeTrail.Key);
                    }

                    smokeTrail.RemoveNode(minDamageNode);
                }

                smokeTrail.AddNode("SpawnAtLastPosition", FieldSaver.FormatValue(false));
                smokeTrail.AddNode("TrailWhileStationary", FieldSaver.FormatValue(true));
                smokeTrail.AddNode("Type", FieldSaver.FormatValue("CenterPosition"));

                if (isConditional)
                {
                    smokeTrail.AddNode("RequiresCondition", FieldSaver.FormatValue("enable-smoke"));
                    anyConditionalSmokeTrail = true;
                }

                smokeTrail.RenameChildrenMatching("Sequence", "Sequences");
                smokeTrail.RenameChildrenMatching("Offset", "Offsets");
                smokeTrail.RenameKey("LeavesTrails");
            }

            if (anyConditionalSmokeTrail)
            {
                var grantCondition = new MiniYamlNode("GrantConditionOnDamageState@SmokeTrail", "");
                grantCondition.AddNode("Condition", FieldSaver.FormatValue("enable-smoke"));
                actorNode.AddNode(grantCondition);
            }

            yield break;
        }
Пример #29
0
        public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
        {
            var aircraftNodes  = actorNode.ChildrenMatching("Aircraft");
            var minelayerNodes = actorNode.ChildrenMatching("Minelayer");
            var ammoPoolNodes  = actorNode.ChildrenMatching("AmmoPool");
            var addNodes       = new List <MiniYamlNode>();

            var ammoPoolNames = new List <string>()
            {
                "primary"
            };

            foreach (var ap in ammoPoolNodes)
            {
                var poolName = ap.LastChildMatching("Name");
                if (poolName != null && poolName.NodeValue <string>() != "primary")
                {
                    ammoPoolNames.Add(poolName.NodeValue <string>());
                }
            }

            var rearmableAdded = false;

            foreach (var aircraftNode in aircraftNodes)
            {
                var rearmBuildings = aircraftNode.LastChildMatching("RearmBuildings");
                if (rearmBuildings != null)
                {
                    if (!rearmableAdded)
                    {
                        var rearmableNode = new MiniYamlNode("Rearmable", "");
                        rearmBuildings.MoveAndRenameNode(aircraftNode, rearmableNode, "RearmActors");

                        // If the list has more than one entry, at least one of them won't be "primary"
                        if (ammoPoolNames.Count > 1)
                        {
                            var ammoPools = new MiniYamlNode("AmmoPools", string.Join(", ", ammoPoolNames));
                            rearmableNode.AddNode(ammoPools);
                        }

                        addNodes.Add(rearmableNode);
                        rearmableAdded = true;
                    }
                    else
                    {
                        aircraftNode.RemoveNodes("RearmBuildings");
                    }
                }
            }

            // If it's a minelayer, it won't be an aircraft and rearmableAdded should still be false, so we can use it here
            foreach (var minelayerNode in minelayerNodes)
            {
                var rearmableNode = new MiniYamlNode("Rearmable", "");

                var rearmBuildings = minelayerNode.LastChildMatching("RearmBuildings");
                if (!rearmableAdded)
                {
                    if (rearmBuildings != null)
                    {
                        rearmBuildings.MoveAndRenameNode(minelayerNode, rearmableNode, "RearmActors");
                    }
                    else
                    {
                        rearmableNode.AddNode(new MiniYamlNode("RearmActors", "fix"));
                    }

                    // If the list has more than one entry, at least one of them won't be "primary"
                    if (ammoPoolNames.Count > 1)
                    {
                        var ammoPools = new MiniYamlNode("AmmoPools", string.Join(", ", ammoPoolNames));
                        rearmableNode.AddNode(ammoPools);
                    }

                    addNodes.Add(rearmableNode);
                    rearmableAdded = true;
                }
                else if (rearmableAdded && rearmBuildings != null)
                {
                    minelayerNode.RemoveNodes("RearmBuildings");
                }
            }

            foreach (var node in addNodes)
            {
                actorNode.AddNode(node);
            }

            yield break;
        }
        public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
        {
            var addNodes = new List <MiniYamlNode>();

            foreach (var mobileNode in actorNode.ChildrenMatching("Mobile"))
            {
                var checkFields = locomotorFields.Append(subterraneanFields).Append(jumpjetFields);
                if (checkFields.Any(f => mobileNode.ChildrenMatching(f).Any()))
                {
                    locations.Add(Tuple.Create(actorNode.Key, actorNode.Location.Filename));
                }

                var tunnelConditionNode = mobileNode.LastChildMatching("TunnelCondition");
                if (tunnelConditionNode != null)
                {
                    var grantNode = new MiniYamlNode("GrantConditionOnTunnelLayer", "");
                    tunnelConditionNode.MoveAndRenameNode(mobileNode, grantNode, "Condition");
                    addNodes.Add(grantNode);
                }

                var subterraneanNode = mobileNode.LastChildMatching("Subterranean");
                if (subterraneanNode != null)
                {
                    subterraneanUsed = true;

                    mobileNode.RemoveNodes("Subterranean");
                    var conditionNode = mobileNode.LastChildMatching("SubterraneanCondition");
                    if (conditionNode != null)
                    {
                        conditionNode.RenameKey("Condition");
                    }

                    var transitionImageNode    = mobileNode.LastChildMatching("SubterraneanTransitionImage");
                    var transitionSequenceNode = mobileNode.LastChildMatching("SubterraneanTransitionSequence");
                    var transitionPaletteNode  = mobileNode.LastChildMatching("SubterraneanTransitionPalette");
                    var transitionSoundNode    = mobileNode.LastChildMatching("SubterraneanTransitionSound");

                    var nodes = new[]
                    {
                        conditionNode,
                        transitionImageNode,
                        transitionSequenceNode,
                        transitionPaletteNode,
                        transitionSoundNode
                    };

                    if (nodes.Any(n => n != null))
                    {
                        var grantNode = new MiniYamlNode("GrantConditionOnSubterraneanLayer", "");
                        foreach (var node in nodes)
                        {
                            if (node != null)
                            {
                                node.MoveNode(mobileNode, grantNode);
                            }
                        }

                        addNodes.Add(grantNode);
                    }
                }

                var jumpjetNode = mobileNode.LastChildMatching("Jumpjet");
                if (jumpjetNode != null)
                {
                    jumpjetUsed = true;

                    mobileNode.RemoveNodes("Jumpjet");
                    var conditionNode = mobileNode.LastChildMatching("JumpjetCondition");
                    if (conditionNode != null)
                    {
                        var grantNode = new MiniYamlNode("GrantConditionOnJumpjetLayer", "");
                        conditionNode.MoveAndRenameNode(mobileNode, grantNode, "Condition");
                        addNodes.Add(grantNode);
                    }
                }
            }

            foreach (var node in addNodes)
            {
                actorNode.AddNode(node);
            }

            yield break;
        }