Deprecate the release-20181215 path
This commit is contained in:
@@ -1,60 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class AddCarryableHarvester : UpdateRule
|
||||
{
|
||||
public override string Name { get { return "Inform about the 'CarryableHarvester' trait."; } }
|
||||
public override string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
return "A 'CarryableHarvester' trait was added for harvesters that use 'AutoCarryable'.";
|
||||
}
|
||||
}
|
||||
|
||||
bool hasAutoCarryable;
|
||||
readonly List<string> harvesters = new List<string>();
|
||||
|
||||
public override IEnumerable<string> BeforeUpdate(ModData modData)
|
||||
{
|
||||
harvesters.Clear();
|
||||
yield break;
|
||||
}
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
|
||||
{
|
||||
if (!hasAutoCarryable)
|
||||
hasAutoCarryable = actorNode.ChildrenMatching("AutoCarryable").Any();
|
||||
|
||||
var harvester = actorNode.LastChildMatching("Harvester");
|
||||
if (harvester != null)
|
||||
harvesters.Add("{0} ({1})".F(actorNode.Key, harvester.Location.Filename));
|
||||
|
||||
yield break;
|
||||
}
|
||||
|
||||
public override IEnumerable<string> AfterUpdate(ModData modData)
|
||||
{
|
||||
if (!hasAutoCarryable || !harvesters.Any())
|
||||
yield break;
|
||||
|
||||
yield return "Detected an 'AutoCarryable' trait.\n" +
|
||||
"Review the following definitions and, if required,\n" +
|
||||
"add the new 'CarryableHarvester' trait.\n" +
|
||||
UpdateUtils.FormatMessageList(harvesters, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class AddRearmable : UpdateRule
|
||||
{
|
||||
public override string Name { get { return "Added Rearmable trait and move RearmBuildings properties there"; } }
|
||||
public override string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Added Rearmable trait and replaced Aircraft.RearmBuildings and\n" +
|
||||
"Minelayer.RearmBuildings with Rearmable.RearmActors.";
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class ChangeTakeOffSoundAndLandingSound : UpdateRule
|
||||
{
|
||||
public override string Name { get { return "Change 'TakeOffSound' and 'LandingSound' parameters within 'Aircraft' Trait."; } }
|
||||
public override string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
return "The 'TakeOffSound' and 'LandingSound' parameters within 'Aircraft' have been changed\n" +
|
||||
"to accept an array of playable sounds.\n" +
|
||||
"They were renamed to 'TakeOffSounds' and 'LandingSounds' respectively, to reflect this change.\n" +
|
||||
"Definitions of 'TakeOffSound' and 'LandingSound' will be automatically renamed.";
|
||||
}
|
||||
}
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
|
||||
{
|
||||
foreach (var aircraft in actorNode.ChildrenMatching("Aircraft"))
|
||||
{
|
||||
aircraft.RenameChildrenMatching("TakeOffSound", "TakeOffSounds");
|
||||
aircraft.RenameChildrenMatching("LandingSound", "LandingSounds");
|
||||
}
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class CloakRequiresConditionToPause : UpdateRule
|
||||
{
|
||||
public override string Name { get { return "Change Cloak>RequiresCondition to PauseOnCondition"; } }
|
||||
public override string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Disabling cloak trait now resets the delay to recloak to InitialCloakDelay.\n" +
|
||||
"To keep the old behaviour, you should pause the trait instead.";
|
||||
}
|
||||
}
|
||||
|
||||
bool displayedMessage;
|
||||
public override IEnumerable<string> AfterUpdate(ModData modData)
|
||||
{
|
||||
var message = "You may want to update the result of PauseOnCondition, as this update\n" +
|
||||
"just adds ! prefix to RequiresCondition's value to reverse it.";
|
||||
|
||||
if (!displayedMessage)
|
||||
yield return message;
|
||||
|
||||
displayedMessage = true;
|
||||
}
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
|
||||
{
|
||||
foreach (var node in actorNode.ChildrenMatching("Cloak").Where(t => t.ChildrenMatching("RequiresCondition").Any()))
|
||||
{
|
||||
var rc = node.LastChildMatching("RequiresCondition");
|
||||
|
||||
rc.ReplaceValue("!(" + rc.Value.Value + ")");
|
||||
rc.RenameKey("PauseOnCondition");
|
||||
}
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class DefineLevelUpImageDefault : UpdateRule
|
||||
{
|
||||
public override string Name { get { return "Unhardcoded LevelUpImage and LevelUpSequence on GainsExperience"; } }
|
||||
public override string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
return "GainsExperience was hardcoded to play a 'levelup' crate effect from 'crate-effects' image.";
|
||||
}
|
||||
}
|
||||
|
||||
static readonly string[] CrateActionTraits =
|
||||
{
|
||||
"DuplicateUnitCrateAction",
|
||||
"ExplodeCrateAction",
|
||||
"GiveCashCrateAction",
|
||||
"GiveMcvCrateAction",
|
||||
"GiveUnitCrateAction",
|
||||
"GrantExternalConditionCrateAction",
|
||||
"HealUnitsCrateAction",
|
||||
"HideMapCrateAction",
|
||||
"LevelUpCrateAction",
|
||||
"RevealMapCrateAction",
|
||||
"SupportPowerCrateAction"
|
||||
};
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
|
||||
{
|
||||
var levelUpImageNode = new MiniYamlNode("LevelUpImage", "crate-effects");
|
||||
foreach (var ge in actorNode.ChildrenMatching("GainsExperience"))
|
||||
ge.AddNode(levelUpImageNode);
|
||||
|
||||
foreach (var t in CrateActionTraits)
|
||||
{
|
||||
foreach (var ca in actorNode.ChildrenMatching(t))
|
||||
{
|
||||
var effect = ca.LastChildMatching("Effect");
|
||||
if (effect != null)
|
||||
effect.RenameKey("Sequence");
|
||||
}
|
||||
}
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class DefineNotificationDefaults : UpdateRule
|
||||
{
|
||||
public override string Name { get { return "Move mod-specific notifications to yaml"; } }
|
||||
public override string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Mod-specific default notifications values have been removed from several traits and the Radar widget\n" +
|
||||
"(" + traits.Select(f => f.Trait).JoinWith(", ") + ")\n" +
|
||||
"The mod chrome is updated automatically and uses of these traits are listed for inspection so the values can be overriden in yaml.";
|
||||
}
|
||||
}
|
||||
|
||||
class TraitWrapper
|
||||
{
|
||||
public readonly string Trait;
|
||||
public readonly Dictionary<string, string> Fields;
|
||||
public List<string> Uses = new List<string>();
|
||||
|
||||
public TraitWrapper(string trait, Dictionary<string, string> fields)
|
||||
{
|
||||
Trait = trait;
|
||||
Fields = fields;
|
||||
}
|
||||
}
|
||||
|
||||
TraitWrapper[] traits =
|
||||
{
|
||||
new TraitWrapper("PrimaryBuilding", new Dictionary<string, string>
|
||||
{
|
||||
{ "SelectionNotification", "PrimaryBuildingSelected" }
|
||||
}),
|
||||
new TraitWrapper("RepairableBuilding", new Dictionary<string, string>
|
||||
{
|
||||
{ "RepairingNotification", "Repairing" }
|
||||
}),
|
||||
new TraitWrapper("RepairsUnits", new Dictionary<string, string>
|
||||
{
|
||||
{ "StartRepairingNotification", "Repairing" }
|
||||
}),
|
||||
new TraitWrapper("GainsExperience", new Dictionary<string, string>
|
||||
{
|
||||
{ "LevelUpNotification", "LevelUp" }
|
||||
}),
|
||||
new TraitWrapper("MissionObjectives", new Dictionary<string, string>
|
||||
{
|
||||
{ "WinNotification", "Win" },
|
||||
{ "LoseNotification", "Lose" },
|
||||
{ "LeaveNotification", "Leave" }
|
||||
}),
|
||||
new TraitWrapper("PlaceBuilding", new Dictionary<string, string>
|
||||
{
|
||||
{ "NewOptionsNotification", "NewOptions" },
|
||||
{ "CannotPlaceNotification", "BuildingCannotPlaceAudio" }
|
||||
}),
|
||||
new TraitWrapper("PlayerResources", new Dictionary<string, string>
|
||||
{
|
||||
{ "CashTickUpNotification", "CashTickUp" },
|
||||
{ "CashTickDownNotification", "CashTickDown" }
|
||||
}),
|
||||
new TraitWrapper("ProductionQueue", new Dictionary<string, string>
|
||||
{
|
||||
{ "ReadyAudio", "UnitReady" },
|
||||
{ "BlockedAudio", "NoBuild" },
|
||||
{ "QueuedAudio", "Training" },
|
||||
{ "OnHoldAudio", "OnHold" },
|
||||
{ "CancelledAudio", "Cancelled" }
|
||||
}),
|
||||
new TraitWrapper("PowerManager", new Dictionary<string, string>
|
||||
{
|
||||
{ "SpeechNotification", "LowPower" }
|
||||
}),
|
||||
new TraitWrapper("Infiltrates", new Dictionary<string, string>
|
||||
{
|
||||
{ "Notification", "BuildingInfiltrated" }
|
||||
})
|
||||
};
|
||||
|
||||
string BuildMessage(TraitWrapper t)
|
||||
{
|
||||
return "Default notification values have been removed from {0}.\n".F(t.Trait) +
|
||||
"You may wish to explicitly define the following overrides:\n " + t.Trait + ":\n" +
|
||||
UpdateUtils.FormatMessageList(t.Fields.Select(kv => " " + kv.Key + ": " + kv.Value), separator: " ") +
|
||||
"\non the following actors (if they have not already been inherited from a parent).\n" +
|
||||
UpdateUtils.FormatMessageList(t.Uses);
|
||||
}
|
||||
|
||||
public override IEnumerable<string> AfterUpdate(ModData modData)
|
||||
{
|
||||
foreach (var t in traits)
|
||||
{
|
||||
if (t.Uses.Any())
|
||||
yield return BuildMessage(t);
|
||||
|
||||
t.Uses.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
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> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,481 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class ExtractHackyAIModules : UpdateRule
|
||||
{
|
||||
public override string Name { get { return "Split HackyAI logic handling to BotModules"; } }
|
||||
public override string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Most properties and logic are being moved from HackyAI\n" +
|
||||
"to *BotModules.";
|
||||
}
|
||||
}
|
||||
|
||||
readonly List<string> locations = new List<string>();
|
||||
bool messageShown;
|
||||
|
||||
readonly string[] harvesterFields =
|
||||
{
|
||||
"HarvesterEnemyAvoidanceRadius", "AssignRolesInterval"
|
||||
};
|
||||
|
||||
readonly string[] supportPowerFields =
|
||||
{
|
||||
"SupportPowerDecisions"
|
||||
};
|
||||
|
||||
readonly string[] baseBuilderFields =
|
||||
{
|
||||
"BuildingQueues",
|
||||
"DefenseQueues",
|
||||
"MinimumExcessPower",
|
||||
"MaximumExcessPower",
|
||||
"ExcessPowerIncrement",
|
||||
"ExcessPowerIncreaseThreshold",
|
||||
"StructureProductionInactiveDelay",
|
||||
"StructureProductionActiveDelay",
|
||||
"StructureProductionRandomBonusDelay",
|
||||
"StructureProductionResumeDelay",
|
||||
"MaximumFailedPlacementAttempts",
|
||||
"MaxResourceCellsToCheck",
|
||||
"CheckForNewBasesDelay",
|
||||
"MinBaseRadius",
|
||||
"MaxBaseRadius",
|
||||
"MinimumDefenseRadius",
|
||||
"MaximumDefenseRadius",
|
||||
"RallyPointScanRadius",
|
||||
"CheckForWaterRadius",
|
||||
"WaterTerrainTypes",
|
||||
"NewProductionCashThreshold",
|
||||
"BuildingCommonNames",
|
||||
"BuildingLimits",
|
||||
"BuildingFractions",
|
||||
};
|
||||
|
||||
readonly string[] copyBaseBuilderFields =
|
||||
{
|
||||
"MinBaseRadius",
|
||||
"MaxBaseRadius",
|
||||
};
|
||||
|
||||
readonly string[] captureManagerFields =
|
||||
{
|
||||
"CapturingActorTypes",
|
||||
"CapturableActorTypes",
|
||||
"MinimumCaptureDelay",
|
||||
"MaximumCaptureTargetOptions",
|
||||
"CheckCaptureTargetsForVisibility",
|
||||
"CapturableStances",
|
||||
};
|
||||
|
||||
readonly string[] squadManagerFields =
|
||||
{
|
||||
"SquadSize",
|
||||
"SquadSizeRandomBonus",
|
||||
"AssignRolesInterval",
|
||||
"RushInterval",
|
||||
"AttackForceInterval",
|
||||
"MinimumAttackForceDelay",
|
||||
"RushAttackScanRadius",
|
||||
"ProtectUnitScanRadius",
|
||||
"MaxBaseRadius",
|
||||
"MaximumDefenseRadius",
|
||||
"IdleScanRadius",
|
||||
"DangerScanRadius",
|
||||
"AttackScanRadius",
|
||||
"ProtectionScanRadius",
|
||||
"UnitsCommonNames",
|
||||
"BuildingCommonNames",
|
||||
};
|
||||
|
||||
readonly string[] squadManagerCommonNames =
|
||||
{
|
||||
"ConstructionYard",
|
||||
"NavalProduction",
|
||||
};
|
||||
|
||||
readonly string[] unitBuilderFields =
|
||||
{
|
||||
"IdleBaseUnitsMaximum",
|
||||
"UnitQueues",
|
||||
"UnitsToBuild",
|
||||
"UnitLimits",
|
||||
};
|
||||
|
||||
readonly string[] mcvManagerFields =
|
||||
{
|
||||
"AssignRolesInterval",
|
||||
"MinBaseRadius",
|
||||
"MaxBaseRadius",
|
||||
"RestrictMCVDeploymentFallbackToBase",
|
||||
"UnitsCommonNames",
|
||||
"BuildingCommonNames",
|
||||
};
|
||||
|
||||
public override IEnumerable<string> AfterUpdate(ModData modData)
|
||||
{
|
||||
if (!messageShown)
|
||||
yield return "You may want to check your AI yamls for possible redundant module entries.\n" +
|
||||
"Additionally, make sure the Player actor has the ConditionManager trait and add it manually if it doesn't.";
|
||||
|
||||
messageShown = true;
|
||||
|
||||
if (locations.Any())
|
||||
yield return "This update rule can only autoamtically update the base HackyAI definitions,\n" +
|
||||
"not any overrides in other files (unless they redefine Type).\n" +
|
||||
"You will have to manually check and possibly update the following locations:\n" +
|
||||
UpdateUtils.FormatMessageList(locations);
|
||||
|
||||
locations.Clear();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void ConvertFractionToInteger(MiniYamlNode node)
|
||||
{
|
||||
// Is the value a percentage or a 'real' float?
|
||||
var isPercentage = node.NodeValue<string>().Contains("%");
|
||||
if (isPercentage)
|
||||
{
|
||||
// Remove '%' first, then remove potential '.' and finally clamp to minimum of 1, unless the old value was really zero
|
||||
var oldValueAsString = node.NodeValue<string>().Split('%')[0];
|
||||
var oldValueWasZero = oldValueAsString == "0";
|
||||
var newValue = oldValueAsString.Split('.')[0];
|
||||
newValue = !oldValueWasZero && newValue == "0" ? "1" : newValue;
|
||||
|
||||
node.ReplaceValue(newValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
var oldValueAsFloat = node.NodeValue<float>();
|
||||
var oldValueWasZero = node.NodeValue<string>() == "0" || node.NodeValue<string>() == "0.0";
|
||||
var newValue = (int)(oldValueAsFloat * 100);
|
||||
|
||||
// Clamp to minimum of 1, unless the old value was really zero
|
||||
newValue = !oldValueWasZero && newValue == 0 ? 1 : newValue;
|
||||
|
||||
node.ReplaceValue(newValue.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class LowPowerSlowdownToModifier : UpdateRule
|
||||
{
|
||||
public override string Name { get { return "LowPowerSlowdown is renamed to LowPowerModifier"; } }
|
||||
public override string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
return "ProductionQueue.LowPowerSlowdown is renamed to LowPowerModifier, and\n" +
|
||||
"multiplied by 100 to allow multiplying the build time with non-integer values.\n" +
|
||||
"Also default value is changed to 100.";
|
||||
}
|
||||
}
|
||||
|
||||
readonly string[] queueTraits = { "ProductionQueue", "ClassicProductionQueue" };
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
|
||||
{
|
||||
foreach (var queue in queueTraits.SelectMany(t => actorNode.ChildrenMatching(t)))
|
||||
{
|
||||
var lowPower = queue.LastChildMatching("LowPowerSlowdown");
|
||||
if (lowPower != null)
|
||||
{
|
||||
if (lowPower.NodeValue<int>() == 1)
|
||||
queue.RemoveNodes("LowPowerSlowdown");
|
||||
else
|
||||
{
|
||||
lowPower.RenameKey("LowPowerModifier");
|
||||
lowPower.ReplaceValue((lowPower.NodeValue<int>() * 100).ToString());
|
||||
}
|
||||
}
|
||||
else
|
||||
queue.AddNode("LowPowerModifier", "300");
|
||||
}
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class MergeAttackPlaneAndHeli : UpdateRule
|
||||
{
|
||||
public override string Name { get { return "AttackPlane and AttackHeli were merged to AttackAircraft"; } }
|
||||
public override string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
return "The AttackPlane and AttackHeli traits were merged intto a single\n" +
|
||||
"AttackAircraft trait.";
|
||||
}
|
||||
}
|
||||
|
||||
bool displayedMessage;
|
||||
public override IEnumerable<string> AfterUpdate(ModData modData)
|
||||
{
|
||||
var message = "If an actor had a total of more than one AttackPlane and/or AttackHeli,\n"
|
||||
+ "you may want to check the update results for possible redundant entries.\n";
|
||||
|
||||
if (!displayedMessage)
|
||||
yield return message;
|
||||
|
||||
displayedMessage = true;
|
||||
}
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
|
||||
{
|
||||
var attackPlanes = actorNode.ChildrenMatching("AttackPlane");
|
||||
var attackHelis = actorNode.ChildrenMatching("AttackHeli");
|
||||
var attackPlanesTotal = attackPlanes.Count();
|
||||
var attackHelisTotal = attackHelis.Count();
|
||||
|
||||
if (attackPlanesTotal == 0 && attackHelisTotal == 0)
|
||||
yield break;
|
||||
else if (attackPlanesTotal == 1 && attackHelisTotal == 0)
|
||||
foreach (var attackPlane in attackPlanes)
|
||||
attackPlane.RenameKey("AttackAircraft");
|
||||
else if (attackPlanesTotal == 0 && attackHelisTotal == 1)
|
||||
foreach (var attackHeli in attackHelis)
|
||||
attackHeli.RenameKey("AttackAircraft");
|
||||
else
|
||||
{
|
||||
// If we got here, we have at least two AttackPlane/-Heli traits in total
|
||||
var attackPlanesCount = 0;
|
||||
foreach (var attackPlane in attackPlanes)
|
||||
{
|
||||
var suffixCount = attackPlanesCount > 0 ? attackPlanesCount.ToString() : "";
|
||||
attackPlane.RenameKey("AttackAircraft@Plane" + suffixCount, false, true);
|
||||
++attackPlanesCount;
|
||||
}
|
||||
|
||||
var attackHelisCount = 0;
|
||||
foreach (var attackHeli in attackHelis)
|
||||
{
|
||||
var suffixCount = attackHelisCount > 0 ? attackHelisCount.ToString() : "";
|
||||
attackHeli.RenameKey("AttackAircraft@Heli" + suffixCount, false, true);
|
||||
++attackHelisCount;
|
||||
}
|
||||
}
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class MergeCaptureTraits : UpdateRule
|
||||
{
|
||||
public override string Name { get { return "Merge and overhaul Captures traits"; } }
|
||||
public override string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
return "The internal and external capturing traits have been merged, and a new\n" +
|
||||
"CaptureManager trait has been added to help manage interactions between\n" +
|
||||
"actors and multiple trait instances. The Sabotage logic has also\n" +
|
||||
"moved from the Capturable trait to the Captures trait.\n" +
|
||||
"The External* traits are renamed, and the CaptureManager added wherever\n" +
|
||||
"the Capturable or Captures trait is used. The locations modified are\n" +
|
||||
"listed for inspection and manual cleanup";
|
||||
}
|
||||
}
|
||||
|
||||
readonly List<string> captureManagerLocations = new List<string>();
|
||||
readonly List<string> externalDelayLocations = new List<string>();
|
||||
readonly List<string> sabotageLocations = new List<string>();
|
||||
|
||||
public override IEnumerable<string> AfterUpdate(ModData modData)
|
||||
{
|
||||
if (captureManagerLocations.Any())
|
||||
yield return "The Captures and Capturable traits now depend on the\n" +
|
||||
"new CaptureManager trait. This trait has automatically been added\n" +
|
||||
"in the following definitions:\n" + UpdateUtils.FormatMessageList(captureManagerLocations) +
|
||||
"\nYou may wish to review these definitions and delete any redundant\n" +
|
||||
"instances that have already been inherited from a parent template.";
|
||||
|
||||
if (sabotageLocations.Any())
|
||||
yield return "The sabotage logic has been disabled by default, which affects\n" +
|
||||
"the following definitions:\n" + UpdateUtils.FormatMessageList(sabotageLocations) +
|
||||
"\nThe sabotage logic is now defined on the Captures trait, via the \n" +
|
||||
"SabotageThreshold field. You may need to define additional capture types\n" +
|
||||
"and Capturable traits if you wish to use multiple capture thresholds.";
|
||||
|
||||
if (externalDelayLocations.Any())
|
||||
yield return "The following actors have had their capture delays reset to 15 seconds:\n" +
|
||||
UpdateUtils.FormatMessageList(sabotageLocations) +
|
||||
"\nThe capture delay is now defined on the Captures trait, via the\n" +
|
||||
"CaptureDelay field. You may need to define additional capture types\n" +
|
||||
"and Capturable traits if you wish to use multiple capture delays.";
|
||||
|
||||
captureManagerLocations.Clear();
|
||||
sabotageLocations.Clear();
|
||||
externalDelayLocations.Clear();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class MergeRearmAndRepairAnimation : UpdateRule
|
||||
{
|
||||
public override string Name { get { return "WithRearmAnimation and WithRepairAnimation were merged to WithResupplyAnimation"; } }
|
||||
public override string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
return "The WithRearmAnimation and WithRepairAnimation traits were merged intto a single\n" +
|
||||
"WithResupplyAnimation trait.";
|
||||
}
|
||||
}
|
||||
|
||||
bool displayedMessage;
|
||||
public override IEnumerable<string> AfterUpdate(ModData modData)
|
||||
{
|
||||
var message = "If an actor had both a WithRearmAnimation and a WithRepairAnimation\n"
|
||||
+ "or multiple traits of either type, you may want to check the update results for possible\n"
|
||||
+ "redundant entries.\n";
|
||||
|
||||
if (!displayedMessage)
|
||||
yield return message;
|
||||
|
||||
displayedMessage = true;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class RefactorResourceLevelAnimating : UpdateRule
|
||||
{
|
||||
public override string Name { get { return "Streamlined traits animating player resource level"; } }
|
||||
public override string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Replaced WithSiloAnimation with WithResourceLevelSpriteBody and\n" +
|
||||
"renamed WithResources to WithResourceLevelOverlay.";
|
||||
}
|
||||
}
|
||||
|
||||
readonly List<string> locations = new List<string>();
|
||||
|
||||
public override IEnumerable<string> AfterUpdate(ModData modData)
|
||||
{
|
||||
if (locations.Any())
|
||||
yield return "WithSiloAnimation has been replaced by WithResourceLevelSpriteBody.\n" +
|
||||
"You may need to disable/remove any previous (including inherited) *SpriteBody traits\n" +
|
||||
"on the following actors:\n" +
|
||||
UpdateUtils.FormatMessageList(locations);
|
||||
|
||||
locations.Clear();
|
||||
}
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
|
||||
{
|
||||
foreach (var wr in actorNode.ChildrenMatching("WithResources"))
|
||||
wr.RenameKey("WithResourceLevelOverlay");
|
||||
|
||||
var siloAnims = actorNode.ChildrenMatching("WithSiloAnimation");
|
||||
foreach (var sa in siloAnims)
|
||||
{
|
||||
// If it's a trait removal, we only rename it.
|
||||
if (sa.IsRemoval())
|
||||
{
|
||||
sa.RenameKey("WithResourceLevelSpriteBody");
|
||||
continue;
|
||||
}
|
||||
|
||||
var sequence = sa.LastChildMatching("Sequence");
|
||||
var body = sa.LastChildMatching("Body");
|
||||
|
||||
if (sequence == null)
|
||||
{
|
||||
var newSequenceNode = new MiniYamlNode("Sequence", "stages");
|
||||
sa.AddNode(newSequenceNode);
|
||||
}
|
||||
|
||||
if (body != null)
|
||||
sa.RemoveNode(body);
|
||||
|
||||
sa.RenameKey("WithResourceLevelSpriteBody");
|
||||
locations.Add("{0} ({1})".F(actorNode.Key, sa.Location.Filename));
|
||||
}
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class RemoveAttackIgnoresVisibility : UpdateRule
|
||||
{
|
||||
public override string Name { get { return "IgnoresVisibility has been removed from Attack* traits."; } }
|
||||
public override string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
return "The IgnoresVisibility flag has been removed from the Attack* traits as part of a\n" +
|
||||
"wider rework of the fog-targeting behaviour. Mods that rely on this logic must\n" +
|
||||
"implement their own Attack* trait, similar to the AttackSwallow trait.";
|
||||
}
|
||||
}
|
||||
|
||||
static readonly string[] Traits =
|
||||
{
|
||||
"AttackFrontal",
|
||||
"AttackFollow",
|
||||
"AttackTurreted",
|
||||
"AttackOmni",
|
||||
"AttackBomber",
|
||||
"AttackPopupTurreted",
|
||||
"AttackTesla",
|
||||
"AttackSwallow"
|
||||
};
|
||||
|
||||
readonly List<string> locations = new List<string>();
|
||||
|
||||
public override IEnumerable<string> AfterUpdate(ModData modData)
|
||||
{
|
||||
if (locations.Any())
|
||||
yield return "The IgnoresVisibility flag has been removed from the targeting logic on the following actors:\n" +
|
||||
UpdateUtils.FormatMessageList(locations) + "\n\n" +
|
||||
"You may wish to enable TargetFrozenActors, or implement a custom Attack* trait like AttackSwallow\n" +
|
||||
"if you require visibility to be completely ignored.";
|
||||
|
||||
locations.Clear();
|
||||
}
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
|
||||
{
|
||||
foreach (var trait in Traits)
|
||||
foreach (var t in actorNode.ChildrenMatching(trait))
|
||||
if (t.RemoveNodes("IgnoresVisibility") > 0)
|
||||
locations.Add("{0} ({1})".F(actorNode.Key, actorNode.Location.Filename));
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class RemoveAttackSuicides : UpdateRule
|
||||
{
|
||||
public override string Name { get { return "AttackSuicides trait has been removed."; } }
|
||||
public override string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
return "The AttackSuicides trait has been removed, and should be replaced by\n" +
|
||||
"AttackFrontal + GrantConditionOnAttack + GrantConditionOnDeploy + a dummy\n" +
|
||||
"weapon for targeting. Affected actors are listed so that these traits can be defined.";
|
||||
}
|
||||
}
|
||||
|
||||
readonly List<string> locations = new List<string>();
|
||||
|
||||
public override IEnumerable<string> AfterUpdate(ModData modData)
|
||||
{
|
||||
if (locations.Any())
|
||||
yield return "The AttackSuicides trait has been removed from the following actors.\n" +
|
||||
"You must manually define AttackFrontal, GrantConditionOnAttack, GrantConditionOnDeploy\n" +
|
||||
"traits and create a dummy weapon to use for targeting:\n" +
|
||||
UpdateUtils.FormatMessageList(locations);
|
||||
|
||||
locations.Clear();
|
||||
}
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
|
||||
{
|
||||
if (actorNode.RemoveNodes("AttackSuicides") > 0)
|
||||
locations.Add("{0} ({1})".F(actorNode.Key, actorNode.Location.Filename));
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class RemoveHealthPercentageRing : UpdateRule
|
||||
{
|
||||
public override string Name { get { return "Remove ring support from HealthPercentageDamage warheads' Spread"; } }
|
||||
public override string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Setting a second value in this warheads' Spread to define a 'ring' is no longer supported.";
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class RemoveNegativeDamageFullHealthCheck : UpdateRule
|
||||
{
|
||||
public override string Name { get { return "Negative damage weapons are now valid against full-health targets."; } }
|
||||
public override string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Negative-damage weapons are no longer automatically invalid against targets that have full health.\n" +
|
||||
"Previous behaviour can be restored by enabling a Targetable trait using GrantConditionOnDamageState.\n" +
|
||||
"Affected weapons are listed so that conditions may be manually defined.";
|
||||
}
|
||||
}
|
||||
|
||||
static readonly string[] DamageWarheads =
|
||||
{
|
||||
"TargetDamage",
|
||||
"SpreadDamage",
|
||||
"HealthPercentageDamage"
|
||||
};
|
||||
|
||||
readonly Dictionary<string, List<string>> locations = new Dictionary<string, List<string>>();
|
||||
|
||||
public override IEnumerable<string> AfterUpdate(ModData modData)
|
||||
{
|
||||
if (locations.Any())
|
||||
yield return "The following weapons may now target actors that have full health. Review their\n" +
|
||||
"target types and, if necessary, use GrantConditionOnDamageState to enable\n" +
|
||||
"a conditional Targetable trait with the appropriate target type when damaged:\n" +
|
||||
UpdateUtils.FormatMessageList(locations.Select(
|
||||
kv => kv.Key + ":\n" + UpdateUtils.FormatMessageList(kv.Value)));
|
||||
|
||||
locations.Clear();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class RemoveRepairBuildingsFromAircraft : UpdateRule
|
||||
{
|
||||
public override string Name { get { return "Removed RepairBuildings from Aircraft"; } }
|
||||
public override string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Removed RepairBuildings from Aircraft in favor of using Repairable instead.";
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class RemoveResourceExplodeModifier : UpdateRule
|
||||
{
|
||||
public override string Name { get { return "Harvester and StoresResources traits no longer force Explodes.EmptyWeapon"; } }
|
||||
public override string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
return "The hardcoded behaviour forcing Explodes to use EmptyWeapon when the harvester/player has no\n" +
|
||||
"resources has been removed. Affected actors are listed so that conditions may be manually defined.";
|
||||
}
|
||||
}
|
||||
|
||||
readonly List<string> locations = new List<string>();
|
||||
|
||||
public override IEnumerable<string> AfterUpdate(ModData modData)
|
||||
{
|
||||
if (locations.Any())
|
||||
yield return "Review the following definitions and, if the actor uses Harvester or StoresResources,\n" +
|
||||
"define a new Explodes trait with the previous EmptyWeapon, enabled by Harvester.EmptyCondition or\n" +
|
||||
"GrantConditionOnPlayerResources.Condition (negated):\n" + UpdateUtils.FormatMessageList(locations);
|
||||
|
||||
locations.Clear();
|
||||
}
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
|
||||
{
|
||||
if (actorNode.LastChildMatching("Explodes") != null)
|
||||
locations.Add("{0} ({1})".F(actorNode.Key, actorNode.Location.Filename));
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class RemovedAutoCarryallCircleTurnSpeed : UpdateRule
|
||||
{
|
||||
public override string Name { get { return "Removed AutoCarryall idle circling turnspeed hardcoding"; } }
|
||||
public override string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Aircraft that circle while idle despite having CanHover (AutoCarryall) have their\n" +
|
||||
"turn speed during idle circling no longer hardcoded to 1/3 of regular TurnSpeed." +
|
||||
"Note that the new IdleTurnSpeed override works on all aircraft that circle when idle.";
|
||||
}
|
||||
}
|
||||
|
||||
bool showMessage;
|
||||
bool messageShown;
|
||||
|
||||
public override IEnumerable<string> AfterUpdate(ModData modData)
|
||||
{
|
||||
var message = "While circling idle, your AutoCarryall(s) will now turn at full TurnSpeed,\n" +
|
||||
"unless you manually define a custom IdleTurnSpeed.";
|
||||
|
||||
if (showMessage && !messageShown)
|
||||
yield return message;
|
||||
|
||||
showMessage = false;
|
||||
messageShown = true;
|
||||
}
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
|
||||
{
|
||||
var autoCarryall = actorNode.LastChildMatching("AutoCarryall");
|
||||
if (autoCarryall == null)
|
||||
yield break;
|
||||
|
||||
showMessage = true;
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class RemovedDemolishLocking : UpdateRule
|
||||
{
|
||||
public override string Name { get { return "Traits are no longer automatically disabled during the Demolition countdown"; } }
|
||||
public override string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Traits are no longer force-disabled during the Demolishing trait destruction countdown.\n" +
|
||||
"This affects the Production*, Transforms, Sellable, EjectOnDeath and ToggleConditionOnOrder traits.\n" +
|
||||
"Affected actors are listed so that conditions may be manually defined.";
|
||||
}
|
||||
}
|
||||
|
||||
static readonly string[] Traits =
|
||||
{
|
||||
"Production",
|
||||
"ProductionAirdrop",
|
||||
"ProductionFromMapEdge",
|
||||
"ProductionParadrop",
|
||||
"Transforms",
|
||||
"Sellable",
|
||||
"ToggleConditionOnOrder",
|
||||
"EjectOnDeath"
|
||||
};
|
||||
|
||||
readonly Dictionary<string, List<string>> locations = new Dictionary<string, List<string>>();
|
||||
|
||||
public override IEnumerable<string> AfterUpdate(ModData modData)
|
||||
{
|
||||
if (locations.Any())
|
||||
yield return "Review the following definitions and, if the actor is Demolishable,\n" +
|
||||
"define Demolishable.Condition and use this condition to disable them:\n" +
|
||||
UpdateUtils.FormatMessageList(locations.Select(
|
||||
kv => kv.Key + ":\n" + UpdateUtils.FormatMessageList(kv.Value)));
|
||||
|
||||
locations.Clear();
|
||||
}
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
|
||||
{
|
||||
var used = new List<string>();
|
||||
foreach (var t in Traits)
|
||||
if (actorNode.LastChildMatching(t, includeRemovals: false) != null)
|
||||
used.Add(t);
|
||||
|
||||
if (used.Any())
|
||||
{
|
||||
var location = "{0} ({1})".F(actorNode.Key, actorNode.Location.Filename);
|
||||
locations[location] = used;
|
||||
}
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class RemovedNotifyBuildComplete : UpdateRule
|
||||
{
|
||||
public override string Name { get { return "Traits are no longer automatically disabled during Building make-animations"; } }
|
||||
public override string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Traits are no longer force-disabled while the WithMakeAnimation trait is active.\n" +
|
||||
"This affects the With*Animation, With*Overlay, *Production, Attack*,\n" +
|
||||
"Transforms, Sellable, Gate, ToggleConditionOnOrder, and ConyardChronoReturn traits.\n" +
|
||||
"The AnnounceOnBuild trait has been replaced with a new VoiceAnnouncement trait.\n" +
|
||||
"Affected actors are listed so that conditions may be manually defined.";
|
||||
}
|
||||
}
|
||||
|
||||
static readonly string[] Traits =
|
||||
{
|
||||
"WithAcceptDeliveredCashAnimation",
|
||||
"WithBuildingPlacedAnimation",
|
||||
"WithBuildingPlacedOverlay",
|
||||
"WithChargeAnimation",
|
||||
"WithChargeOverlay",
|
||||
"WithDockedOverlay",
|
||||
"WithIdleAnimation",
|
||||
"WithIdleOverlay",
|
||||
"WithNukeLaunchAnimation",
|
||||
"WithNukeLaunchOverlay",
|
||||
"WithProductionDoorOverlay",
|
||||
"WithProductionOverlay",
|
||||
"WithRepairOverlay",
|
||||
"WithResources",
|
||||
"WithResupplyAnimation",
|
||||
"WithSiloAnimation",
|
||||
"WithSpriteTurret",
|
||||
"WithVoxelBarrel",
|
||||
"WithVoxelTurret",
|
||||
"WithDeliveryAnimation",
|
||||
"WithCrumbleOverlay",
|
||||
"WithDeliveryOverlay",
|
||||
"Production",
|
||||
"ProductionAirdrop",
|
||||
"ProductionFromMapEdge",
|
||||
"ProductionParadrop",
|
||||
"AttackFrontal",
|
||||
"AttackFollow",
|
||||
"AttackTurreted",
|
||||
"AttackOmni",
|
||||
"AttackBomber",
|
||||
"AttackPopupTurreted",
|
||||
"AttackTesla",
|
||||
"Transforms",
|
||||
"Sellable",
|
||||
"Gate",
|
||||
"ConyardChronoReturn",
|
||||
"ToggleConditionOnOrder",
|
||||
"VoiceAnnouncement"
|
||||
};
|
||||
|
||||
readonly Dictionary<string, List<string>> locations = new Dictionary<string, List<string>>();
|
||||
|
||||
public override IEnumerable<string> AfterUpdate(ModData modData)
|
||||
{
|
||||
if (locations.Any())
|
||||
yield return "Review the following definitions and, for those that are buildings,\n" +
|
||||
"define conditions to disable them while WithMakeAnimation is active:\n" +
|
||||
UpdateUtils.FormatMessageList(locations.Select(
|
||||
kv => kv.Key + ":\n" + UpdateUtils.FormatMessageList(kv.Value)));
|
||||
|
||||
locations.Clear();
|
||||
}
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
|
||||
{
|
||||
foreach (var announce in actorNode.ChildrenMatching("AnnounceOnBuild"))
|
||||
{
|
||||
announce.RenameKey("VoiceAnnouncement");
|
||||
if (announce.LastChildMatching("Voice") == null)
|
||||
announce.AddNode("Voice", "Build");
|
||||
}
|
||||
|
||||
var used = new List<string>();
|
||||
foreach (var t in Traits)
|
||||
if (actorNode.LastChildMatching(t) != null)
|
||||
used.Add(t);
|
||||
|
||||
if (used.Any())
|
||||
{
|
||||
var location = "{0} ({1})".F(actorNode.Key, actorNode.Location.Filename);
|
||||
locations[location] = used;
|
||||
}
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class RenameCrateActionNotification : UpdateRule
|
||||
{
|
||||
public override string Name { get { return "*CrateAction>Notification renamed to Sound"; } }
|
||||
public override string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
return "'*CrateAction' traits now have an actual `Notification` field.\n" +
|
||||
"The new `Sound` field does what the old `Notification` did.";
|
||||
}
|
||||
}
|
||||
|
||||
string[] traits =
|
||||
{
|
||||
"DuplicateUnitCrateAction",
|
||||
"ExplodeCrateAction",
|
||||
"GiveCashCrateAction",
|
||||
"GiveMcvCrateAction",
|
||||
"GiveUnitCrateAction",
|
||||
"GrantExternalConditionCrateAction",
|
||||
"HealUnitsCrateAction",
|
||||
"HideMapCrateAction",
|
||||
"LevelUpCrateAction",
|
||||
"RevelMapCrateAction",
|
||||
"SupportPowerCrateAction"
|
||||
};
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
|
||||
{
|
||||
foreach (var trait in traits)
|
||||
foreach (var action in actorNode.ChildrenMatching(trait))
|
||||
action.RenameChildrenMatching("Notification", "Sound");
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class RenameEditorTilesetFilter : UpdateRule
|
||||
{
|
||||
public override string Name { get { return "EditorTilesetFilter renamed to MapEditorData"; } }
|
||||
public override string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
return "The name EditorTilesetFilter was misleading and was renamed to MapEditorData.";
|
||||
}
|
||||
}
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
|
||||
{
|
||||
foreach (var data in actorNode.ChildrenMatching("EditorTilesetFilter"))
|
||||
data.RenameKey("MapEditorData");
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class ReplacedWithChargeAnimation : UpdateRule
|
||||
{
|
||||
public override string Name { get { return "Replaced WithChargeAnimation with WithChargeSpriteBody"; } }
|
||||
public override string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Replaced WithChargeAnimation with WithChargeSpriteBody.";
|
||||
}
|
||||
}
|
||||
|
||||
readonly List<string> locations = new List<string>();
|
||||
|
||||
public override IEnumerable<string> AfterUpdate(ModData modData)
|
||||
{
|
||||
if (locations.Any())
|
||||
yield return "WithChargeAnimation has been replaced by WithChargeSpriteBody.\n" +
|
||||
"You may need to disable/remove any previous (including inherited) *SpriteBody traits\n" +
|
||||
"on the following actors:\n" +
|
||||
UpdateUtils.FormatMessageList(locations);
|
||||
|
||||
locations.Clear();
|
||||
}
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
|
||||
{
|
||||
var chargeAnims = actorNode.ChildrenMatching("WithChargeAnimation");
|
||||
|
||||
foreach (var ca in chargeAnims)
|
||||
{
|
||||
// If it's a trait removal, we only rename it.
|
||||
if (ca.IsRemoval())
|
||||
{
|
||||
ca.RenameKey("WithChargeSpriteBody");
|
||||
continue;
|
||||
}
|
||||
|
||||
var sequence = ca.LastChildMatching("Sequence");
|
||||
var body = ca.LastChildMatching("Body");
|
||||
|
||||
if (sequence == null)
|
||||
{
|
||||
var newSequenceNode = new MiniYamlNode("Sequence", "active");
|
||||
ca.AddNode(newSequenceNode);
|
||||
}
|
||||
|
||||
if (body != null)
|
||||
ca.RemoveNode(body);
|
||||
|
||||
ca.RenameKey("WithChargeSpriteBody");
|
||||
locations.Add("{0} ({1})".F(actorNode.Key, ca.Location.Filename));
|
||||
}
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class RequireProductionType : UpdateRule
|
||||
{
|
||||
public override string Name { get { return "Require 'ProductionType' on 'ProductionBar'"; } }
|
||||
public override string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
return "The 'ProductionBar' trait now requires the 'ProductionType' to be set.\n" +
|
||||
"The value will be automatically set to the first value in 'Produces' of the first 'Production' trait.";
|
||||
}
|
||||
}
|
||||
|
||||
readonly string[] productionTraits = { "Production", "ProductionAirdrop", "ProductionParadrop", "ProductionFromMapEdge" };
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
|
||||
{
|
||||
foreach (var pb in actorNode.ChildrenMatching("ProductionBar"))
|
||||
{
|
||||
var type = pb.LastChildMatching("ProductionType");
|
||||
if (type != null)
|
||||
continue;
|
||||
|
||||
MiniYamlNode production = null;
|
||||
foreach (var trait in productionTraits)
|
||||
{
|
||||
if (production != null)
|
||||
break;
|
||||
|
||||
production = actorNode.ChildrenMatching(trait).FirstOrDefault();
|
||||
}
|
||||
|
||||
if (production == null)
|
||||
continue;
|
||||
|
||||
var produces = production.LastChildMatching("Produces");
|
||||
if (produces == null)
|
||||
continue;
|
||||
|
||||
var toAdd = produces.NodeValue<string[]>().FirstOrDefault();
|
||||
if (toAdd != null)
|
||||
pb.AddNode("ProductionType", toAdd);
|
||||
}
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,35 +34,6 @@ namespace OpenRA.Mods.Common.UpdateRules
|
||||
Justification = "Extracting update lists to temporary variables obfuscates the definitions.")]
|
||||
static readonly UpdatePath[] Paths =
|
||||
{
|
||||
new UpdatePath("release-20181215", "release-20190314", new UpdateRule[]
|
||||
{
|
||||
new AddCarryableHarvester(),
|
||||
new RenameEditorTilesetFilter(),
|
||||
new DefineNotificationDefaults(),
|
||||
new MergeRearmAndRepairAnimation(),
|
||||
new MergeCaptureTraits(),
|
||||
new RemovedNotifyBuildComplete(),
|
||||
new LowPowerSlowdownToModifier(),
|
||||
new ChangeTakeOffSoundAndLandingSound(),
|
||||
new RemoveHealthPercentageRing(),
|
||||
new RenameCrateActionNotification(),
|
||||
new RemoveRepairBuildingsFromAircraft(),
|
||||
new AddRearmable(),
|
||||
new MergeAttackPlaneAndHeli(),
|
||||
new RemovedDemolishLocking(),
|
||||
new RequireProductionType(),
|
||||
new CloakRequiresConditionToPause(),
|
||||
new ExtractHackyAIModules(),
|
||||
new RemoveNegativeDamageFullHealthCheck(),
|
||||
new RemoveResourceExplodeModifier(),
|
||||
new DefineLevelUpImageDefault(),
|
||||
new RemovedAutoCarryallCircleTurnSpeed(),
|
||||
new RemoveAttackIgnoresVisibility(),
|
||||
new ReplacedWithChargeAnimation(),
|
||||
new RefactorResourceLevelAnimating(),
|
||||
new RemoveAttackSuicides(),
|
||||
}),
|
||||
|
||||
new UpdatePath("release-20190314", "release-20191117", new UpdateRule[]
|
||||
{
|
||||
new MultipleDeploySounds(),
|
||||
|
||||
Reference in New Issue
Block a user