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.")]
|
Justification = "Extracting update lists to temporary variables obfuscates the definitions.")]
|
||||||
static readonly UpdatePath[] Paths =
|
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 UpdatePath("release-20190314", "release-20191117", new UpdateRule[]
|
||||||
{
|
{
|
||||||
new MultipleDeploySounds(),
|
new MultipleDeploySounds(),
|
||||||
|
|||||||
Reference in New Issue
Block a user