public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode) { var givesBuildableArea = actorNode.LastChildMatching("GivesBuildableArea"); if (givesBuildableArea != null) { givesBuildableArea.AddNode("AreaTypes", "building"); } var building = actorNode.LastChildMatching("Building"); if (building != null) { var requiresBuildableArea = new MiniYamlNode("RequiresBuildableArea", ""); requiresBuildableArea.AddNode("AreaTypes", "building"); var adjacent = building.LastChildMatching("Adjacent"); if (adjacent != null) { requiresBuildableArea.AddNode(adjacent); } actorNode.AddNode(requiresBuildableArea); building.RemoveNodes("Adjacent"); } yield break; }
public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode) { var poolNumber = 0; var ammoPools = actorNode.ChildrenMatching("AmmoPool").ToList(); foreach (var pool in ammoPools) { var selfReloads = pool.LastChildMatching("SelfReloads"); if (selfReloads == null || !selfReloads.NodeValue <bool>()) { continue; } poolNumber++; var reloadOnCond = new MiniYamlNode("ReloadAmmoPool@" + poolNumber, ""); var name = pool.LastChildMatching("Name"); if (name != null) { reloadOnCond.AddNode("AmmoPool", name.NodeValue <string>()); } var selfReloadDelay = pool.LastChildMatching("SelfReloadDelay"); if (selfReloadDelay != null) { selfReloadDelay.RenameKey("Delay"); reloadOnCond.AddNode(selfReloadDelay); pool.RemoveNodes("SelfReloadDelay"); } pool.RemoveNodes("SelfReloads"); var reloadCount = pool.LastChildMatching("ReloadCount"); if (reloadCount != null) { reloadCount.RenameKey("Count"); reloadOnCond.AddNode(reloadCount); pool.RemoveNodes("ReloadCount"); } var reset = pool.LastChildMatching("ResetOnFire"); if (reset != null) { reloadOnCond.AddNode(reset); pool.RemoveNodes("ResetOnFire"); } var rearmSound = pool.LastChildMatching("RearmSound"); if (rearmSound != null) { rearmSound.RenameKey("Sound"); reloadOnCond.AddNode(rearmSound); pool.RemoveNodes("RearmSound"); } actorNode.AddNode(reloadOnCond); } yield break; }
void AddShakeNode(MiniYamlNode actorNode) { var shake = new MiniYamlNode("ShakeOnDeath", ""); shake.AddNode("Duration", "15"); shake.AddNode("Intensity", "6"); actorNode.AddNode(shake); }
void UpdatePower(MiniYamlNode power) { var range = 1; var rangeNode = power.LastChildMatching("Range"); if (rangeNode != null) { range = rangeNode.NodeValue <int>(); if (range > 3) { locations.Add("{0} ({1})".F(rangeNode.Key, rangeNode.Location.Filename)); } power.RemoveNode(rangeNode); } var size = 2 * range + 1; power.AddNode(new MiniYamlNode("Dimensions", size.ToString() + ", " + size.ToString())); var footprint = string.Empty; var emptycell = range; var affectedcell = 1; for (var i = 0; i < size; i++) { for (var e = 0; e < emptycell; e++) { footprint += '_'; } for (var a = 0; a < affectedcell; a++) { footprint += 'x'; } for (var e = 0; e < emptycell; e++) { footprint += '_'; } if (i < range) { emptycell--; affectedcell += 2; } else { emptycell++; affectedcell -= 2; } footprint += ' '; } power.AddNode(new MiniYamlNode("Footprint", footprint)); }
public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode) { var autoSelectionSize = actorNode.LastChildMatching("AutoSelectionSize"); if (autoSelectionSize != null) { actorNode.AddNode("Interactable", ""); } var customSelectionSize = actorNode.LastChildMatching("CustomSelectionSize"); if (customSelectionSize != null) { var bounds = customSelectionSize.LastChildMatching("CustomBounds"); var customRenderSize = new MiniYamlNode("Interactable", ""); if (bounds != null) { customRenderSize.AddNode("Bounds", bounds.NodeValue <int[]>()); } actorNode.AddNode(customRenderSize); } var sd = actorNode.LastChildMatching("SelectionDecorations"); if (sd != null) { var boundsNode = sd.LastChildMatching("VisualBounds"); if (boundsNode != null) { boundsNode.RenameKey("DecorationBounds"); sd.RemoveNode(boundsNode); var selectable = actorNode.LastChildMatching("Selectable"); if (selectable == null) { selectable = new MiniYamlNode("Selectable", new MiniYaml("")); actorNode.AddNode(selectable); } selectable.AddNode(boundsNode); } } if (actorNode.LastChildMatching("-Selectable") != null && actorNode.LastChildMatching("Interactable") == null) { actorNode.AddNode("Interactable", ""); } actorNode.RemoveNodes("CustomSelectionSize"); actorNode.RemoveNodes("AutoSelectionSize"); yield break; }
public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode) { var gate = actorNode.LastChildMatching("Gate"); if (gate == null) { yield break; } var openSound = gate.LastChildMatching("OpeningSound"); var closeSound = gate.LastChildMatching("ClosingSound"); var closeDelay = gate.LastChildMatching("CloseDelay"); var transitDelay = gate.LastChildMatching("TransitionDelay"); var blockHeight = gate.LastChildMatching("BlocksProjectilesHeight"); var newGate = new MiniYamlNode("Gate", ""); gate.RenameKey("Building"); if (openSound != null) { newGate.AddNode(openSound); gate.RemoveNode(openSound); } if (closeSound != null) { newGate.AddNode(closeSound); gate.RemoveNode(closeSound); } if (closeDelay != null) { newGate.AddNode(closeDelay); gate.RemoveNode(closeDelay); } if (transitDelay != null) { newGate.AddNode(transitDelay); gate.RemoveNode(transitDelay); } if (blockHeight != null) { newGate.AddNode(blockHeight); gate.RemoveNode(blockHeight); } actorNode.AddNode(newGate); yield break; }
public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode) { var canPowerDown = actorNode.LastChildMatching("CanPowerDown"); if (canPowerDown == null) { yield break; } canPowerDown.AddNode("PowerdownCondition", "powerdown"); var image = canPowerDown.LastChildMatching("IndicatorImage"); var seq = canPowerDown.LastChildMatching("IndicatorSequence"); var pal = canPowerDown.LastChildMatching("IndicatorPalette"); var imageValue = image != null?image.NodeValue <string>() : "poweroff"; var seqValue = seq != null?seq.NodeValue <string>() : "offline"; var palValue = pal != null?pal.NodeValue <string>() : "chrome"; var indicator = new MiniYamlNode("WithDecoration@POWERDOWN", ""); indicator.AddNode("Image", imageValue); indicator.AddNode("Sequence", seqValue); indicator.AddNode("Palette", palValue); indicator.AddNode("RequiresCondition", "powerdown"); indicator.AddNode("ReferencePoint", "Center"); actorNode.AddNode(indicator); if (image != null) { canPowerDown.RemoveNodes("IndicatorImage"); } if (seq != null) { canPowerDown.RemoveNodes("IndicatorSequence"); } if (pal != null) { canPowerDown.RemoveNodes("IndicatorPalette"); } if (!displayed) { displayed = true; yield return("'CanPowerDown' now provides a condition. You might need to review your condition setup."); } }
public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode) { if (complete || actorNode.LastChildMatching("IsometricSelectable") != null) { yield break; } var height = 0; if (!selectionHeight.TryGetValue(actorNode.Key.ToLowerInvariant(), out height)) { yield break; } // Don't redefine the default value if (height == 24) { yield break; } var selection = new MiniYamlNode("IsometricSelectable", ""); selection.AddNode("Height", FieldSaver.FormatValue(height)); actorNode.AddNode(selection); }
public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode) { // Aircraft isn't conditional or otherwise supports multiple traits, so LastChildMatching is fine. var aircraftNode = actorNode.LastChildMatching("Aircraft"); if (aircraftNode != null) { var repairBuildings = aircraftNode.LastChildMatching("RepairBuildings"); if (repairBuildings != null) { var repariableNode = new MiniYamlNode("Repairable", ""); repairBuildings.MoveAndRenameNode(aircraftNode, repariableNode, "RepairBuildings"); var voice = aircraftNode.LastChildMatching("Voice"); if (voice != null) { repariableNode.AddNode(voice); } actorNode.AddNode(repariableNode); } } yield break; }
public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode) { // RepairableBuilding is hardcoded to only support one instance per actor var rb = actorNode.LastChildMatching("RepairableBuilding"); if (rb != null) { var imageNode = rb.LastChildMatching("IndicatorImage"); var sequenceNode = rb.LastChildMatching("IndicatorSequence"); var paletteNode = rb.LastChildMatching("IndicatorPalette"); var palettePrefixNode = rb.LastChildMatching("IndicatorPalettePrefix"); var decoration = new MiniYamlNode("WithBuildingRepairDecoration", ""); decoration.AddNode("Image", imageNode != null ? imageNode.Value.Value : "allyrepair"); decoration.AddNode("Sequence", sequenceNode != null ? sequenceNode.Value.Value : "repair"); decoration.AddNode("ReferencePoint", "Center"); if (paletteNode != null) { decoration.AddNode("Palette", paletteNode.Value.Value); } else { decoration.AddNode("Palette", palettePrefixNode != null ? palettePrefixNode.Value.Value : "player"); decoration.AddNode("IsPlayerPalette", true); } actorNode.AddNode(decoration); rb.RemoveNode(imageNode); rb.RemoveNode(sequenceNode); rb.RemoveNode(paletteNode); rb.RemoveNode(palettePrefixNode); } if (actorNode.LastChildMatching("-RepairableBuilding") != null) { actorNode.AddNode("-WithBuildingRepairDecoration", ""); } yield break; }
public override IEnumerable <string> UpdateChromeProviderNode(ModData modData, MiniYamlNode chromeProviderNode) { // Migrate image rectangles var regionsNode = new MiniYamlNode("Regions", ""); foreach (var n in chromeProviderNode.Value.Nodes) { if (n.Key == "Inherits") { continue; } // Reformat region as a list regionsNode.AddNode(n.Key, n.NodeValue <int[]>()); if (n.Value.Nodes.Any()) { overrideLocations.Add("{0}.{1} ({2})".F(chromeProviderNode.Key, n.Key, chromeProviderNode.Location.Filename)); } } chromeProviderNode.Value.Nodes.RemoveAll(n => n.Key != "Inherits"); // Migrate image definition chromeProviderNode.AddNode(new MiniYamlNode("Image", chromeProviderNode.Value.Value)); chromeProviderNode.Value.Value = ""; if (!ExtractPanelDefinition(chromeProviderNode, regionsNode)) { panelLocations.Add("{0} ({1})".F(chromeProviderNode.Key, chromeProviderNode.Location.Filename)); } if (regionsNode.Value.Nodes.Any()) { chromeProviderNode.AddNode(regionsNode); } yield break; }
public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode) { if (actorNode.ChildrenMatching("ResourceLayer").Any() && !actorNode.ChildrenMatching("ResourceRenderer").Any()) { locations.Add($"{actorNode.Key} ({actorNode.Location.Filename})"); var resourceRenderer = new MiniYamlNode("ResourceRenderer", ""); resourceRenderer.AddNode("RenderTypes", ""); actorNode.AddNode(resourceRenderer); } if (actorNode.ChildrenMatching("D2kResourceLayer").Any() && !actorNode.ChildrenMatching("D2kResourceRenderer").Any()) { actorNode.RenameChildrenMatching("D2kResourceLayer", "ResourceLayer"); locations.Add($"{actorNode.Key} ({actorNode.Location.Filename})"); var resourceRenderer = new MiniYamlNode("D2kResourceRenderer", ""); resourceRenderer.AddNode("RenderTypes", ""); actorNode.AddNode(resourceRenderer); } yield break; }
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; }
void ApplyChanges(MiniYamlNode actorNode, MiniYamlNode node) { // Type renamed to Types var type = node.LastChildMatching("Type"); if (type != null) type.RenameKey("Types"); // Allow(Allies|Neutral|Enemies) replaced with a ValidStances enum var stance = Stance.Neutral | Stance.Enemy; var allowAllies = node.LastChildMatching("AllowAllies"); if (allowAllies != null) { if (allowAllies.NodeValue<bool>()) stance |= Stance.Ally; else stance &= ~Stance.Ally; node.RemoveNode(allowAllies); } var allowNeutral = node.LastChildMatching("AllowNeutral"); if (allowNeutral != null) { if (allowNeutral.NodeValue<bool>()) stance |= Stance.Neutral; else stance &= ~Stance.Neutral; node.RemoveNode(allowNeutral); } var allowEnemies = node.LastChildMatching("AllowEnemies"); if (allowEnemies != null) { if (allowEnemies.NodeValue<bool>()) stance |= Stance.Enemy; else stance &= ~Stance.Enemy; node.RemoveNode(allowEnemies); } if (stance != (Stance.Neutral | Stance.Enemy)) node.AddNode("ValidStances", stance); }
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; }
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> 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; }
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) { var reportLocation = "{0} ({1})".F(actorNode.Key, actorNode.Location.Filename); var captureManager = actorNode.LastChildMatching("CaptureManager") ?? new MiniYamlNode("CaptureManager", ""); var usesCaptureManager = false; // Migrate External* foreach (var c in actorNode.ChildrenMatching("ExternalCapturable")) { c.RenameKey("Capturable"); if (c.RemoveNodes("CaptureCompleteTime") > 0) { externalDelayLocations.Add(reportLocation); } } foreach (var c in actorNode.ChildrenMatching("ExternalCaptures")) { c.RenameKey("Captures"); if (c.Key.StartsWith("-")) { continue; } c.AddNode("CaptureDelay", 375); var consumeNode = c.LastChildMatching("ConsumeActor"); if (consumeNode != null) { consumeNode.RenameKey("ConsumedByCapture"); } else { c.AddNode("ConsumedByCapture", false); } var conditionNode = c.LastChildMatching("CapturingCondition"); if (conditionNode != null) { conditionNode.MoveNode(c, captureManager); } var cursorNode = c.LastChildMatching("CaptureCursor"); if (cursorNode != null) { cursorNode.RenameKey("EnterCursor"); } else { c.AddNode("EnterCursor", "ability"); } var cursorBlockedNode = c.LastChildMatching("CaptureBlockedCursor"); if (cursorBlockedNode != null) { cursorBlockedNode.RenameKey("EnterBlockedCursor"); } else { c.AddNode("EnterBlockedCursor", "move-blocked"); } } var addBlinker = false; foreach (var c in actorNode.ChildrenMatching("ExternalCapturableBar")) { c.RenameKey("CapturableProgressBar"); addBlinker = true; } if (addBlinker) { actorNode.AddNode("CapturableProgressBlink", ""); } // Remove any CaptureThreshold nodes and restore the "building" default // These run on converted External* traits too foreach (var traitNode in actorNode.ChildrenMatching("Capturable")) { if (!traitNode.Key.StartsWith("-")) { usesCaptureManager = true; } if (traitNode.RemoveNodes("CaptureThreshold") + traitNode.RemoveNodes("Sabotage") > 0) { sabotageLocations.Add(reportLocation); } if (!traitNode.Key.StartsWith("-") && traitNode.LastChildMatching("Types") == null) { traitNode.AddNode("Types", "building"); } } foreach (var traitNode in actorNode.ChildrenMatching("Captures")) { if (!traitNode.Key.StartsWith("-")) { usesCaptureManager = true; } if (traitNode.LastChildMatching("CaptureTypes") == null) { traitNode.AddNode("CaptureTypes", "building"); } } if (usesCaptureManager && actorNode.LastChildMatching("CaptureManager") == null) { actorNode.AddNode(captureManager); captureManagerLocations.Add(reportLocation); } yield break; }
public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode) { var turretAttack = actorNode.LastChildMatching("WithTurretAttackAnimation"); if (turretAttack != null) { var attackSequence = turretAttack.LastChildMatching("AttackSequence"); var aimSequence = turretAttack.LastChildMatching("AimSequence"); var reloadPrefix = turretAttack.LastChildMatching("ReloadPrefix"); if (aimSequence != null) { aimAnimLocations.Add(Tuple.Create(actorNode.Key, actorNode.Location.Filename)); } if (reloadPrefix != null) { reloadPrefixLocations.Add(Tuple.Create(actorNode.Key, actorNode.Location.Filename)); } // If only AttackSequence is not null, just rename AttackSequence to Sequence. // If only the prefix isn't null (extremely unlikely, but you never know), just rename the trait. // If AttackSequence is null but AimSequence isn't, rename the trait and property. // If both aren't null, split/copy everything relevant to the new WithTurretAimAnimation. // If both are null (extremely unlikely), do nothing. if (attackSequence != null && aimSequence == null) { attackSequence.RenameKey("Sequence"); } else if (attackSequence == null && aimSequence == null && reloadPrefix != null) { turretAttack.RemoveNode(reloadPrefix); turretAttack.RenameKey("WithTurretAimAnimation"); } else if (attackSequence == null && aimSequence != null) { turretAttack.RenameKey("WithTurretAimAnimation"); aimSequence.RenameKey("Sequence"); if (reloadPrefix != null) { turretAttack.RemoveNode(reloadPrefix); } } else if (attackSequence != null && aimSequence != null) { var turretAim = new MiniYamlNode("WithTurretAimAnimation", ""); aimSequence.MoveAndRenameNode(turretAttack, turretAim, "Sequence"); var turret = turretAttack.LastChildMatching("Turret"); var armament = turretAttack.LastChildMatching("Armament"); if (reloadPrefix != null) { turretAttack.RemoveNode(reloadPrefix); } if (turret != null) { turretAim.AddNode(turret); } if (armament != null) { turretAim.AddNode(armament); } attackSequence.RenameKey("Sequence"); actorNode.AddNode(turretAim); } } var spriteTurret = actorNode.LastChildMatching("WithSpriteTurret"); if (spriteTurret != null) { var aimSequence = spriteTurret.LastChildMatching("AimSequence"); if (aimSequence != null) { aimAnimLocations.Add(Tuple.Create(actorNode.Key, actorNode.Location.Filename)); var aimAnim = new MiniYamlNode("WithTurretAimAnimation", ""); aimSequence.MoveAndRenameNode(spriteTurret, aimAnim, "Sequence"); actorNode.AddNode(aimAnim); } } var attackAnim = actorNode.LastChildMatching("WithAttackAnimation"); if (attackAnim != null) { var attackSequence = attackAnim.LastChildMatching("AttackSequence"); var aimSequence = attackAnim.LastChildMatching("AimSequence"); var reloadPrefix = attackAnim.LastChildMatching("ReloadPrefix"); if (aimSequence != null) { aimAnimLocations.Add(Tuple.Create(actorNode.Key, actorNode.Location.Filename)); } if (reloadPrefix != null) { reloadPrefixLocations.Add(Tuple.Create(actorNode.Key, actorNode.Location.Filename)); } // If only AttackSequence is not null, just rename AttackSequence to Sequence. // If only the prefix isn't null (extremely unlikely, but you never know), just rename the trait. // If AttackSequence is null but AimSequence isn't, rename the trait and property. // If both sequences aren't null, split/copy everything relevant to the new WithAimAnimation. // If both sequences and the prefix are null (extremely unlikely), do nothing. if (attackSequence != null && aimSequence == null && reloadPrefix == null) { attackSequence.RenameKey("Sequence"); } else if (attackSequence == null && aimSequence == null && reloadPrefix != null) { attackAnim.RemoveNode(reloadPrefix); attackAnim.RenameKey("WithAimAnimation"); } else if (attackSequence == null && aimSequence != null) { attackAnim.RenameKey("WithAimAnimation"); aimSequence.RenameKey("Sequence"); if (reloadPrefix != null) { attackAnim.RemoveNode(reloadPrefix); } } else if (attackSequence != null && aimSequence != null) { var aimAnim = new MiniYamlNode("WithAimAnimation", ""); aimSequence.MoveAndRenameNode(attackAnim, aimAnim, "Sequence"); var body = attackAnim.LastChildMatching("Body"); var armament = attackAnim.LastChildMatching("Armament"); if (reloadPrefix != null) { attackAnim.RemoveNode(reloadPrefix); } if (body != null) { aimAnim.AddNode(body); } if (armament != null) { aimAnim.AddNode(armament); } attackSequence.RenameKey("Sequence"); actorNode.AddNode(aimAnim); } } yield break; }
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; } var addNodes = new List <MiniYamlNode>(); // We add a 'default' HarvesterBotModule in any case, // and only add more for AIs that define custom values for one of its fields. var defaultHarvNode = new MiniYamlNode("HarvesterBotModule", ""); foreach (var hackyAINode in hackyAIs) { // HackyAIInfo.Name might contain spaces, so Type is better suited to be used as condition name var aiType = hackyAINode.LastChildMatching("Type").NodeValue <string>(); var conditionString = "enable-" + aiType + "-ai"; var requiresCondition = new MiniYamlNode("RequiresCondition", conditionString); var addGrantConditionOnBotOwner = true; 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(requiresCondition); 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 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(requiresCondition); } else { var oldValue = requiresConditionNode.NodeValue <string>(); if (oldValue.Contains(conditionString)) { continue; } requiresConditionNode.ReplaceValue(oldValue + " || " + conditionString); } } } addNodes.Add(defaultHarvNode); foreach (var node in addNodes) { actorNode.AddNode(node); } yield break; }
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; }
public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode) { var addNodes = new List <MiniYamlNode>(); foreach (var selectionDecorations in actorNode.ChildrenMatching("SelectionDecorations")) { customPips |= selectionDecorations.RemoveNodes("Palette") > 0; customPips |= selectionDecorations.RemoveNodes("Image") > 0; } foreach (var ammoPool in actorNode.ChildrenMatching("AmmoPool")) { var ammoPips = new MiniYamlNode("WithAmmoPipsDecoration", ""); ammoPips.AddNode("Position", "BottomLeft"); ammoPips.AddNode("RequiresSelection", "true"); var pipCountNode = ammoPool.LastChildMatching("PipCount"); if (pipCountNode != null) { ammoPool.RemoveNode(pipCountNode); var pipCount = pipCountNode.NodeValue <int>(); if (pipCount == 0) { addNodes.Add(new MiniYamlNode("-" + ammoPips.Key, "")); continue; } var ammoNode = ammoPool.LastChildMatching("Ammo"); var maxAmmo = ammoNode != null?ammoNode.NodeValue <int>() : 0; if (pipCount != maxAmmo) { ammoPips.AddNode("PipCount", pipCount); } } var pipTypeNode = ammoPool.LastChildMatching("PipType"); if (pipTypeNode != null) { ammoPool.RemoveNode(pipTypeNode); if (PipReplacements.TryGetValue(pipTypeNode.Value.Value.ToLowerInvariant(), out var sequence)) { ammoPips.AddNode("FullSequence", sequence); } } var pipTypeEmptyNode = ammoPool.LastChildMatching("PipTypeEmpty"); if (pipTypeEmptyNode != null) { ammoPool.RemoveNode(pipTypeEmptyNode); if (PipReplacements.TryGetValue(pipTypeEmptyNode.Value.Value.ToLowerInvariant(), out var sequence)) { ammoPips.AddNode("EmptySequence", sequence); } } addNodes.Add(ammoPips); locations.Add("{0}: {1} ({2})".F(actorNode.Key, ammoPips.Key, actorNode.Location.Filename)); } foreach (var cargo in actorNode.ChildrenMatching("Cargo")) { var cargoPips = new MiniYamlNode("WithCargoPipsDecoration", ""); cargoPips.AddNode("Position", "BottomLeft"); cargoPips.AddNode("RequiresSelection", "true"); var pipCountNode = cargo.LastChildMatching("PipCount"); if (pipCountNode != null) { cargo.RemoveNode(pipCountNode); var pipCount = pipCountNode.NodeValue <int>(); if (pipCount == 0) { addNodes.Add(new MiniYamlNode("-" + cargoPips.Key, "")); continue; } var maxWeightNode = cargo.LastChildMatching("MaxWeight"); var maxWeight = maxWeightNode != null?maxWeightNode.NodeValue <int>() : 0; if (pipCount != maxWeight) { cargoPips.AddNode("PipCount", pipCount); } } else { continue; } addNodes.Add(cargoPips); locations.Add("{0}: {1} ({2})".F(actorNode.Key, cargoPips.Key, actorNode.Location.Filename)); cargoPipLocations.Add("{0} ({1})".F(actorNode.Key, actorNode.Location.Filename)); } foreach (var passenger in actorNode.ChildrenMatching("Passenger")) { var pipTypeNode = passenger.LastChildMatching("PipType"); if (pipTypeNode != null) { pipTypeNode.RenameKey("CustomPipType"); pipTypeNode.Value.Value = pipTypeNode.Value.Value.ToLowerInvariant(); cargoCustomPips.Add(pipTypeNode.Value.Value); } } foreach (var harvester in actorNode.ChildrenMatching("Harvester")) { var harvesterPips = new MiniYamlNode("WithHarvesterPipsDecoration", ""); harvesterPips.AddNode("Position", "BottomLeft"); harvesterPips.AddNode("RequiresSelection", "true"); // Harvester hardcoded a default PipCount > 0 so we can't use that to determine whether // this is a definition or an override. Resources isn't ideal either, but is better than nothing var resourcesNode = harvester.LastChildMatching("Resources"); if (resourcesNode == null) { continue; } var pipCountNode = harvester.LastChildMatching("PipCount"); if (pipCountNode != null) { harvester.RemoveNode(pipCountNode); var pipCount = pipCountNode.NodeValue <int>(); if (pipCount == 0) { addNodes.Add(new MiniYamlNode("-" + harvesterPips.Key, "")); continue; } harvesterPips.AddNode("PipCount", pipCount); } else { harvesterPips.AddNode("PipCount", 7); } addNodes.Add(harvesterPips); locations.Add("{0}: {1} ({2})".F(actorNode.Key, harvesterPips.Key, actorNode.Location.Filename)); harvesterPipLocations.Add("{0} ({1})".F(actorNode.Key, actorNode.Location.Filename)); } foreach (var resourceType in actorNode.ChildrenMatching("ResourceType")) { var pipColor = "yellow"; var pipCountNode = resourceType.LastChildMatching("PipColor"); if (pipCountNode != null) { pipColor = pipCountNode.Value.Value.ToLowerInvariant(); resourceType.RemoveNode(pipCountNode); } var typeNode = resourceType.LastChildMatching("Type"); if (typeNode != null) { harvesterCustomPips.Add(typeNode.Value.Value, pipColor); } } foreach (var storesResources in actorNode.ChildrenMatching("StoresResources")) { var storagePips = new MiniYamlNode("WithResourceStoragePipsDecoration", ""); storagePips.AddNode("Position", "BottomLeft"); storagePips.AddNode("RequiresSelection", "true"); var pipCountNode = storesResources.LastChildMatching("PipCount"); if (pipCountNode != null) { storesResources.RemoveNode(pipCountNode); var pipCount = pipCountNode.NodeValue <int>(); if (pipCount == 0) { addNodes.Add(new MiniYamlNode("-" + storagePips.Key, "")); continue; } storagePips.AddNode("PipCount", pipCount); } else { continue; } // Default pip color changed from yellow to green for consistency with other pip traits var pipColorNode = storesResources.LastChildMatching("PipColor"); if (pipColorNode != null) { storesResources.RemoveNode(pipColorNode); var type = pipColorNode.Value.Value.ToLowerInvariant(); if (type != "green" && PipReplacements.TryGetValue(type, out var sequence)) { storagePips.AddNode("FullSequence", sequence); } } else { storagePips.AddNode("FullSequence", PipReplacements["yellow"]); } addNodes.Add(storagePips); locations.Add("{0}: {1} ({2})".F(actorNode.Key, storagePips.Key, actorNode.Location.Filename)); } foreach (var addNode in addNodes) { actorNode.AddNode(addNode); } yield break; }
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; }
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; }
bool ExtractPanelDefinition(MiniYamlNode chromeProviderNode, MiniYamlNode regionsNode) { var cNode = regionsNode.LastChildMatching("background"); var hasCenter = cNode != null; var hasEdges = edgeKeys.Any(k => regionsNode.LastChildMatching(k) != null); // Not a panel if (!hasCenter && !hasEdges) { return(true); } // Panels may define just the background if (hasCenter && !hasEdges) { var bgRect = cNode.NodeValue <Rectangle>(); chromeProviderNode.AddNode("PanelRegion", new[] { bgRect.X, bgRect.Y, 0, 0, bgRect.Width, bgRect.Height, 0, 0 }); chromeProviderNode.AddNode("PanelSides", PanelSides.Center); regionsNode.RemoveNode(cNode); return(true); } // Panels may define just the edges, or edges plus background var tlNode = regionsNode.LastChildMatching("corner-tl"); if (tlNode == null) { return(false); } var tlRect = tlNode.NodeValue <Rectangle>(); var tNode = regionsNode.LastChildMatching("border-t"); if (tNode == null) { return(false); } var tRect = tNode.NodeValue <Rectangle>(); if (tRect.Left != tlRect.Right || tRect.Top != tlRect.Top || tRect.Bottom != tlRect.Bottom) { return(false); } var trNode = regionsNode.LastChildMatching("corner-tr"); if (trNode == null) { return(false); } var trRect = trNode.NodeValue <Rectangle>(); if (trRect.Left != tRect.Right || trRect.Top != tRect.Top || trRect.Bottom != tRect.Bottom) { return(false); } var lNode = regionsNode.LastChildMatching("border-l"); if (lNode == null) { return(false); } var lRect = lNode.NodeValue <Rectangle>(); if (lRect.Left != tlRect.Left || lRect.Top != tlRect.Bottom || lRect.Right != tlRect.Right) { return(false); } var rNode = regionsNode.LastChildMatching("border-r"); if (rNode == null) { return(false); } var rRect = rNode.NodeValue <Rectangle>(); if (rRect.Left != trRect.Left || rRect.Top != trRect.Bottom || rRect.Bottom != lRect.Bottom || rRect.Right != trRect.Right) { return(false); } var blNode = regionsNode.LastChildMatching("corner-bl"); if (blNode == null) { return(false); } var blRect = blNode.NodeValue <Rectangle>(); if (blRect.Left != lRect.Left || blRect.Top != lRect.Bottom || blRect.Right != lRect.Right) { return(false); } var bNode = regionsNode.LastChildMatching("border-b"); if (bNode == null) { return(false); } var bRect = bNode.NodeValue <Rectangle>(); if (bRect.Left != blRect.Right || bRect.Top != blRect.Top || bRect.Bottom != blRect.Bottom || bRect.Right != tRect.Right) { return(false); } var brNode = regionsNode.LastChildMatching("corner-br"); if (brNode == null) { return(false); } var brRect = brNode.NodeValue <Rectangle>(); if (brRect.Left != bRect.Right || brRect.Top != bRect.Top || brRect.Bottom != bRect.Bottom || brRect.Right != rRect.Right) { return(false); } // Background definition may be omitted if (hasCenter) { var bgRect = cNode.NodeValue <Rectangle>(); if (bgRect.Left != lRect.Right || bgRect.Top != lRect.Top || bgRect.Bottom != lRect.Bottom || bgRect.Right != tRect.Right) { return(false); } } // Define the short-form panel region chromeProviderNode.AddNode("PanelRegion", new[] { tlRect.X, tlRect.Y, tlRect.Width, tlRect.Height, trRect.Left - tlRect.Right, blRect.Top - tlRect.Bottom, brRect.Width, brRect.Height }); if (!hasCenter) { chromeProviderNode.AddNode("PanelSides", PanelSides.Edges); } // Remove the now redundant regions regionsNode.RemoveNode(tlNode); regionsNode.RemoveNode(tNode); regionsNode.RemoveNode(trNode); regionsNode.RemoveNode(lNode); regionsNode.RemoveNode(rNode); regionsNode.RemoveNode(blNode); regionsNode.RemoveNode(bNode); regionsNode.RemoveNode(brNode); if (cNode != null) { regionsNode.RemoveNode(cNode); } return(true); }
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; }
public override IEnumerable <string> UpdateActorNode(ModData modData, MiniYamlNode actorNode) { var cpd = actorNode.LastChildMatching("CanPowerDown"); if (cpd == null) { yield break; } cpd.RenameKey("ToggleConditionOnOrder"); var upSound = cpd.LastChildMatching("PowerupSound"); if (upSound != null) { upSound.RenameKey("DisabledSound"); } var upSpeech = cpd.LastChildMatching("PowerupSpeech"); if (upSpeech != null) { upSpeech.RenameKey("DisabledSpeech"); } var downSound = cpd.LastChildMatching("PowerdownSound"); if (downSound != null) { downSound.RenameKey("EnabledSound"); } var downSpeech = cpd.LastChildMatching("PowerdownSpeech"); if (downSpeech != null) { downSpeech.RenameKey("EnabledSpeech"); } cpd.AddNode("OrderName", "PowerDown"); var condition = cpd.LastChildMatching("PowerdownCondition"); if (condition != null) { condition.RenameKey("Condition"); } else { cpd.AddNode("Condition", "powerdown"); } if (cpd.ChildrenMatching("CancelWhenDisabled").Any()) { cpd.RemoveNodes("CancelWhenDisabled"); yield return("CancelWhenDisabled was removed when CanPowerDown was replaced by ToggleConditionOnOrder.\n" + "Use PauseOnCondition instead of RequiresCondition to replicate the behavior of 'false'."); } actorNode.AddNode(new MiniYamlNode("PowerMultiplier@POWERDOWN", new MiniYaml("", new List <MiniYamlNode>() { new MiniYamlNode("RequiresCondition", condition.Value.Value), new MiniYamlNode("Modifier", "0") }))); yield break; }