From 94b1f53ebf5171838a11ab6e76b09ba0dcad29b8 Mon Sep 17 00:00:00 2001 From: UberWaffe Date: Thu, 10 Jul 2014 20:55:02 +0200 Subject: [PATCH] Rebased. (+1 squashed commits) Squashed commits: [43010a0] Fixes. (+1 squashed commits) Squashed commits: [94ee90e] Fixes. (+1 squashed commits) Squashed commits: [ef827c7] Style cop updates. Updates to LevelUp, Cloak, and UnitUpgrade to allow multiple units within range, plus maximum extra unit limit. (+1 squashed commits) Squashed commits: [2103b01] Dupe crate action updates and fixes. (+2 squashed commit) Squashed commit: [0f4df4a] Added DuplicateUnitCrateAction. [2787fa1] Clarity update. (+1 squashed commits) Squashed commits: [93ddc3b] Crate updates. +Multiple units per crate allowed. +Allow time delay on crate actions. --- OpenRA.Mods.RA/CrateAction.cs | 22 +++- OpenRA.Mods.RA/Crates/CloakCrateAction.cs | 35 ++++- .../Crates/DuplicateUnitCrateAction.cs | 121 ++++++++++++++++++ OpenRA.Mods.RA/Crates/ExplodeCrateAction.cs | 5 +- OpenRA.Mods.RA/Crates/GiveCashCrateAction.cs | 4 + OpenRA.Mods.RA/Crates/GiveMcvCrateAction.cs | 3 + OpenRA.Mods.RA/Crates/GiveUnitCrateAction.cs | 53 +++++--- OpenRA.Mods.RA/Crates/HealUnitsCrateAction.cs | 1 + OpenRA.Mods.RA/Crates/HideMapCrateAction.cs | 1 + OpenRA.Mods.RA/Crates/LevelUpCrateAction.cs | 40 +++++- OpenRA.Mods.RA/Crates/RevealMapCrateAction.cs | 3 + .../Crates/SupportPowerCrateAction.cs | 6 +- .../Crates/UnitUpgradeCrateAction.cs | 43 ++++++- OpenRA.Mods.RA/OpenRA.Mods.RA.csproj | 1 + mods/d2k/rules/misc.yaml | 50 +++++--- mods/ra/rules/misc.yaml | 49 +++++-- 16 files changed, 374 insertions(+), 63 deletions(-) create mode 100644 OpenRA.Mods.RA/Crates/DuplicateUnitCrateAction.cs diff --git a/OpenRA.Mods.RA/CrateAction.cs b/OpenRA.Mods.RA/CrateAction.cs index c72221e039..997220719e 100644 --- a/OpenRA.Mods.RA/CrateAction.cs +++ b/OpenRA.Mods.RA/CrateAction.cs @@ -17,15 +17,22 @@ namespace OpenRA.Mods.RA public class CrateActionInfo : ITraitInfo { [Desc("Chance of getting this crate, assuming the collector is compatible.")] - public int SelectionShares = 10; + public readonly int SelectionShares = 10; + [Desc("An animation defined in sequence yaml(s) to draw.")] - public string Effect = null; + public readonly string Effect = null; + [Desc("Palette to draw the animation in.")] - public string Palette = "effect"; + public readonly string Palette = "effect"; + [Desc("Audio clip to play when the crate is collected.")] - public string Notification = null; - [ActorReference] - public string[] ExcludedActorTypes = { }; + public readonly string Notification = null; + + [Desc("The earliest time (in ticks) that this crate action can occur on.")] + public readonly int TimeDelay = 0; + + [Desc("Actor types that this crate action will not occur for.")] + [ActorReference] public string[] ExcludedActorTypes = { }; public virtual object Create(ActorInitializer init) { return new CrateAction(init.self, this); } } @@ -43,6 +50,9 @@ namespace OpenRA.Mods.RA public int GetSelectionSharesOuter(Actor collector) { + if (self.World.WorldTick < info.TimeDelay) + return 0; + if (info.ExcludedActorTypes.Contains(collector.Info.Name)) return 0; diff --git a/OpenRA.Mods.RA/Crates/CloakCrateAction.cs b/OpenRA.Mods.RA/Crates/CloakCrateAction.cs index dcba86a96e..160a4b9c32 100644 --- a/OpenRA.Mods.RA/Crates/CloakCrateAction.cs +++ b/OpenRA.Mods.RA/Crates/CloakCrateAction.cs @@ -8,17 +8,31 @@ */ #endregion +using System.Linq; + namespace OpenRA.Mods.RA.Crates { + [Desc("Grants the collector the ability to cloak.")] public class CloakCrateActionInfo : CrateActionInfo { + [Desc("The range to search for extra collectors in.", "Extra collectors will also be granted the crate action.")] + public readonly WRange Range = new WRange(3); + + [Desc("The maximum number of extra collectors to grant the crate action to.")] + public readonly int MaxExtraCollectors = 4; + public override object Create(ActorInitializer init) { return new CloakCrateAction(init.self, this); } } public class CloakCrateAction : CrateAction { + CloakCrateActionInfo Info; + public CloakCrateAction(Actor self, CloakCrateActionInfo info) - : base(self, info) { } + : base(self, info) + { + Info = info; + } public override int GetSelectionShares(Actor collector) { @@ -32,6 +46,25 @@ namespace OpenRA.Mods.RA.Crates public override void Activate(Actor collector) { collector.Trait().ReceivedCloakCrate(collector); + + var inRange = self.World.FindActorsInCircle(self.CenterPosition, Info.Range); + inRange = inRange.Where(a => + (a.Owner == collector.Owner) && + (a != collector) && + (a.TraitOrDefault() != null) && + (a.TraitOrDefault().AcceptsCloakCrate)); + if (inRange.Any()) + { + if (Info.MaxExtraCollectors > -1) + inRange = inRange.Take(Info.MaxExtraCollectors); + + if (inRange.Any()) + foreach (Actor actor in inRange) + { + actor.Trait().ReceivedCloakCrate(actor); + } + } + base.Activate(collector); } } diff --git a/OpenRA.Mods.RA/Crates/DuplicateUnitCrateAction.cs b/OpenRA.Mods.RA/Crates/DuplicateUnitCrateAction.cs new file mode 100644 index 0000000000..797bdf6276 --- /dev/null +++ b/OpenRA.Mods.RA/Crates/DuplicateUnitCrateAction.cs @@ -0,0 +1,121 @@ +#region Copyright & License Information +/* + * Copyright 2007-2014 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. For more information, + * see COPYING. + */ +#endregion + +using System.Collections.Generic; +using System.Linq; +using OpenRA.Mods.RA.Move; +using OpenRA.Primitives; +using OpenRA.Traits; + +namespace OpenRA.Mods.RA.Crates +{ + [Desc("Creates duplicates of the actor that collects the crate.")] + class DuplicateUnitCrateActionInfo : CrateActionInfo + { + [Desc("The maximum number of duplicates to make.")] + public readonly int MaxAmount = 2; + + [Desc("The minimum number of duplicates to make.","Overrules MaxDuplicatesWorth.")] + public readonly int MinAmount = 1; + + [Desc("The maximum total cost allowed for the duplicates.","Duplication stops if the total worth will exceed this number.","-1 = no limit")] + public readonly int MaxDuplicatesWorth = -1; + + [Desc("The list of unit types we are allowed to duplicate.")] + public readonly string[] ValidDuplicateTypes = { "Ground", "Water" }; + + [Desc("Which races this crate action can occur for.")] + public readonly string[] ValidRaces = { }; + + [Desc("Is the new duplicates given to a specific owner, regardless of whom collected it?")] + public readonly string Owner = null; + + public override object Create(ActorInitializer init) { return new DuplicateUnitCrateAction(init.self, this); } + } + + class DuplicateUnitCrateAction : CrateAction + { + public readonly DuplicateUnitCrateActionInfo Info; + readonly List usedCells = new List(); + + public DuplicateUnitCrateAction(Actor self, DuplicateUnitCrateActionInfo info) + : base(self, info) { Info = info; } + + public bool CanGiveTo(Actor collector) + { + if (Info.ValidRaces.Any() && !Info.ValidRaces.Contains(collector.Owner.Country.Race)) + return false; + + var targetable = collector.Info.Traits.GetOrDefault(); + if (targetable == null || + !Info.ValidDuplicateTypes.Intersect(targetable.GetTargetTypes()).Any()) + return false; + + if (!GetSuitableCells(collector.Location, collector.Info.Name).Any()) return false; + + return true; + } + + public override int GetSelectionShares(Actor collector) + { + if (!CanGiveTo(collector)) return 0; + return base.GetSelectionShares(collector); + } + + public override void Activate(Actor collector) + { + int AllowedWorthLeft = Info.MaxDuplicatesWorth; + int DupesMade = 0; + + while ((DupesMade < Info.MaxAmount) && (AllowedWorthLeft > 0) || (DupesMade < Info.MinAmount)) + { + //If the collector has a cost, and we have a max duplicate worth, then update how much dupe worth is left + var unitCost = collector.Info.Traits.Get().Cost; + AllowedWorthLeft -= (Info.MaxDuplicatesWorth > 0) ? unitCost : 0; + if ((AllowedWorthLeft < 0) && (DupesMade >= Info.MinAmount)) + break; + + DupesMade++; + + var location = ChooseEmptyCellNear(collector, collector.Info.Name); + if (location != null) + { + usedCells.Add(location.Value); + collector.World.AddFrameEndTask( + w => w.CreateActor(collector.Info.Name, new TypeDictionary + { + new LocationInit(location.Value), + new OwnerInit(Info.Owner ?? collector.Owner.InternalName) + })); + } + } + base.Activate(collector); + } + + IEnumerable GetSuitableCells(CPos near, string unitName) + { + var mi = self.World.Map.Rules.Actors[unitName].Traits.Get(); + + for (var i = -3; i < 4; i++) + for (var j = -3; j < 4; j++) + if (mi.CanEnterCell(self.World, self, near + new CVec(i, j), null, true, true)) + yield return near + new CVec(i, j); + } + + CPos? ChooseEmptyCellNear(Actor a, string unit) + { + var possibleCells = GetSuitableCells(a.Location, unit).Where(c => !usedCells.Contains(c)).ToArray(); + if (possibleCells.Length == 0) + return null; + + return possibleCells.Random(self.World.SharedRandom); + } + } +} diff --git a/OpenRA.Mods.RA/Crates/ExplodeCrateAction.cs b/OpenRA.Mods.RA/Crates/ExplodeCrateAction.cs index e9bea7cad7..39bd0acf1d 100644 --- a/OpenRA.Mods.RA/Crates/ExplodeCrateAction.cs +++ b/OpenRA.Mods.RA/Crates/ExplodeCrateAction.cs @@ -12,10 +12,11 @@ using OpenRA.Traits; namespace OpenRA.Mods.RA { + [Desc("Fires a weapon at the location when collected.")] class ExplodeCrateActionInfo : CrateActionInfo { - [WeaponReference] - public string Weapon = null; + [Desc("The weapon to fire upon collection.")] + [WeaponReference] public string Weapon = null; public override object Create(ActorInitializer init) { return new ExplodeCrateAction(init.self, this); } } diff --git a/OpenRA.Mods.RA/Crates/GiveCashCrateAction.cs b/OpenRA.Mods.RA/Crates/GiveCashCrateAction.cs index f94182c75b..89c9f170ff 100644 --- a/OpenRA.Mods.RA/Crates/GiveCashCrateAction.cs +++ b/OpenRA.Mods.RA/Crates/GiveCashCrateAction.cs @@ -13,9 +13,13 @@ using OpenRA.Traits; namespace OpenRA.Mods.RA { + [Desc("Gives cash to the collector.")] class GiveCashCrateActionInfo : CrateActionInfo { + [Desc("Amount of cash to give.")] public int Amount = 2000; + + [Desc("Should the collected amount be displayed as a cash tick?")] public bool UseCashTick = false; public override object Create(ActorInitializer init) { return new GiveCashCrateAction(init.self, this); } diff --git a/OpenRA.Mods.RA/Crates/GiveMcvCrateAction.cs b/OpenRA.Mods.RA/Crates/GiveMcvCrateAction.cs index d0c4f1c31f..4f4aaf9f64 100644 --- a/OpenRA.Mods.RA/Crates/GiveMcvCrateAction.cs +++ b/OpenRA.Mods.RA/Crates/GiveMcvCrateAction.cs @@ -12,9 +12,12 @@ using System.Linq; namespace OpenRA.Mods.RA.Crates { + [Desc("Spawns units when collected.","Adjust selection shares when player has no base.")] class GiveMcvCrateActionInfo : GiveUnitCrateActionInfo { + [Desc("The selection shares to use if the collector has no base.")] public int NoBaseSelectionShares = 1000; + public override object Create(ActorInitializer init) { return new GiveMcvCrateAction(init.self, this); } } diff --git a/OpenRA.Mods.RA/Crates/GiveUnitCrateAction.cs b/OpenRA.Mods.RA/Crates/GiveUnitCrateAction.cs index 53b1274b04..6ae23ddbd4 100644 --- a/OpenRA.Mods.RA/Crates/GiveUnitCrateAction.cs +++ b/OpenRA.Mods.RA/Crates/GiveUnitCrateAction.cs @@ -16,36 +16,40 @@ using OpenRA.Traits; namespace OpenRA.Mods.RA.Crates { + [Desc("Spawns units when collected.")] class GiveUnitCrateActionInfo : CrateActionInfo { + [Desc("The list of units to spawn.")] [ActorReference] - [Desc("Unit to give")] - public readonly string Unit = null; - - [Desc("Override the owner of the newly spawned unit: e.g Creeps or Neutral")] - public readonly string Owner = null; + public readonly string[] Units = { }; [Desc("Races that are allowed to trigger this action")] - public readonly string[] Race = null; + public readonly string[] Race = { }; + + [Desc("Override the owner of the newly spawned unit: e.g. Creeps or Neutral")] + public readonly string Owner = null; public override object Create(ActorInitializer init) { return new GiveUnitCrateAction(init.self, this); } } class GiveUnitCrateAction : CrateAction { - GiveUnitCrateActionInfo Info; + public readonly GiveUnitCrateActionInfo Info; + readonly List usedCells = new List(); public GiveUnitCrateAction(Actor self, GiveUnitCrateActionInfo info) : base(self, info) { Info = info; } public bool CanGiveTo(Actor collector) { - if (Info.Race != null && !Info.Race.Contains(collector.Owner.Country.Race)) + if (Info.Race.Any() && !Info.Race.Contains(collector.Owner.Country.Race)) return false; - // avoid dumping tanks in the sea, and ships on dry land. - if (!GetSuitableCells(collector.Location).Any()) - return false; + foreach (string unit in Info.Units) + { + // avoid dumping tanks in the sea, and ships on dry land. + if (!GetSuitableCells(collector.Location, unit).Any()) return false; + } return true; } @@ -58,21 +62,28 @@ namespace OpenRA.Mods.RA.Crates public override void Activate(Actor collector) { - var location = ChooseEmptyCellNear(collector); - if (location != null) - collector.World.AddFrameEndTask( - w => w.CreateActor(Info.Unit, new TypeDictionary + foreach (var u in Info.Units) + { + var unit = u; // avoiding access to modified closure + + var location = ChooseEmptyCellNear(collector, unit); + if (location != null) + { + usedCells.Add(location.Value); + collector.World.AddFrameEndTask( + w => w.CreateActor(unit, new TypeDictionary { - new LocationInit(location.Value ), + new LocationInit(location.Value), new OwnerInit(Info.Owner ?? collector.Owner.InternalName) })); - + } + } base.Activate(collector); } - IEnumerable GetSuitableCells(CPos near) + IEnumerable GetSuitableCells(CPos near, string unitName) { - var mi = self.World.Map.Rules.Actors[Info.Unit].Traits.Get(); + var mi = self.World.Map.Rules.Actors[unitName].Traits.Get(); for (var i = -1; i < 2; i++) for (var j = -1; j < 2; j++) @@ -80,9 +91,9 @@ namespace OpenRA.Mods.RA.Crates yield return near + new CVec(i, j); } - CPos? ChooseEmptyCellNear(Actor a) + CPos? ChooseEmptyCellNear(Actor a, string unit) { - var possibleCells = GetSuitableCells(a.Location).ToArray(); + var possibleCells = GetSuitableCells(a.Location, unit).Where(c => !usedCells.Contains(c)).ToArray(); if (possibleCells.Length == 0) return null; diff --git a/OpenRA.Mods.RA/Crates/HealUnitsCrateAction.cs b/OpenRA.Mods.RA/Crates/HealUnitsCrateAction.cs index fd96a9ae80..9df0aa8359 100644 --- a/OpenRA.Mods.RA/Crates/HealUnitsCrateAction.cs +++ b/OpenRA.Mods.RA/Crates/HealUnitsCrateAction.cs @@ -13,6 +13,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.RA.Crates { + [Desc("Heals all actors that belong to the owner of the collector.")] class HealUnitsCrateActionInfo : CrateActionInfo { public override object Create(ActorInitializer init) { return new HealUnitsCrateAction(init.self, this); } diff --git a/OpenRA.Mods.RA/Crates/HideMapCrateAction.cs b/OpenRA.Mods.RA/Crates/HideMapCrateAction.cs index 70574406e9..09b8ec2372 100644 --- a/OpenRA.Mods.RA/Crates/HideMapCrateAction.cs +++ b/OpenRA.Mods.RA/Crates/HideMapCrateAction.cs @@ -10,6 +10,7 @@ namespace OpenRA.Mods.RA { + [Desc("Hides the entire map in shroud.")] class HideMapCrateActionInfo : CrateActionInfo { public override object Create(ActorInitializer init) { return new HideMapCrateAction(init.self, this); } diff --git a/OpenRA.Mods.RA/Crates/LevelUpCrateAction.cs b/OpenRA.Mods.RA/Crates/LevelUpCrateAction.cs index 496ea51a96..f544cd37c7 100644 --- a/OpenRA.Mods.RA/Crates/LevelUpCrateAction.cs +++ b/OpenRA.Mods.RA/Crates/LevelUpCrateAction.cs @@ -8,19 +8,34 @@ */ #endregion +using System.Linq; + namespace OpenRA.Mods.RA { + [Desc("Gives experience levels to the collector.")] class LevelUpCrateActionInfo : CrateActionInfo { + [Desc("Number of experience levels to give.")] public readonly int Levels = 1; + [Desc("The range to search for extra collectors in.", "Extra collectors will also be granted the crate action.")] + public readonly WRange Range = new WRange(3); + + [Desc("The maximum number of extra collectors to grant the crate action to.")] + public readonly int MaxExtraCollectors = 4; + public override object Create(ActorInitializer init) { return new LevelUpCrateAction(init.self, this); } } class LevelUpCrateAction : CrateAction { + LevelUpCrateActionInfo Info; + public LevelUpCrateAction(Actor self, LevelUpCrateActionInfo info) - : base(self,info) {} + : base(self, info) + { + Info = info; + } public override int GetSelectionShares(Actor collector) { @@ -37,6 +52,29 @@ namespace OpenRA.Mods.RA gainsExperience.GiveLevels(((LevelUpCrateActionInfo)info).Levels); }); + var inRange = self.World.FindActorsInCircle(self.CenterPosition, Info.Range); + inRange = inRange.Where(a => + (a.Owner == collector.Owner) && + (a != collector) && + (a.TraitOrDefault() != null) && + (a.TraitOrDefault().CanGainLevel)); + if (inRange.Any()) + { + if (Info.MaxExtraCollectors > -1) + inRange = inRange.Take(Info.MaxExtraCollectors); + + if (inRange.Any()) + foreach (Actor actor in inRange) + { + actor.World.AddFrameEndTask(w => + { + var gainsExperience = actor.TraitOrDefault(); + if (gainsExperience != null) + gainsExperience.GiveLevels(((LevelUpCrateActionInfo)info).Levels); + }); + } + } + base.Activate(collector); } } diff --git a/OpenRA.Mods.RA/Crates/RevealMapCrateAction.cs b/OpenRA.Mods.RA/Crates/RevealMapCrateAction.cs index 23eb67bf8f..9389c93dfc 100644 --- a/OpenRA.Mods.RA/Crates/RevealMapCrateAction.cs +++ b/OpenRA.Mods.RA/Crates/RevealMapCrateAction.cs @@ -12,9 +12,12 @@ using OpenRA.Traits; namespace OpenRA.Mods.RA { + [Desc("Reveals the entire map.")] class RevealMapCrateActionInfo : CrateActionInfo { + [Desc("Should the map also be revealed for the allies of the collector's owner.")] public readonly bool IncludeAllies = false; + public override object Create(ActorInitializer init) { return new RevealMapCrateAction(init.self, this); } } diff --git a/OpenRA.Mods.RA/Crates/SupportPowerCrateAction.cs b/OpenRA.Mods.RA/Crates/SupportPowerCrateAction.cs index 2d8da8e32e..c6440a6900 100644 --- a/OpenRA.Mods.RA/Crates/SupportPowerCrateAction.cs +++ b/OpenRA.Mods.RA/Crates/SupportPowerCrateAction.cs @@ -13,10 +13,12 @@ using OpenRA.Traits; namespace OpenRA.Mods.RA.Crates { + [Desc("Gives a supportpower to the collector.")] class SupportPowerCrateActionInfo : CrateActionInfo { - [ActorReference] - public readonly string Proxy = null; + [Desc("Which proxy actor, which grants the support power, to spawn.")] + [ActorReference] public readonly string Proxy = null; + public override object Create(ActorInitializer init) { return new SupportPowerCrateAction(init.self, this); } } diff --git a/OpenRA.Mods.RA/Crates/UnitUpgradeCrateAction.cs b/OpenRA.Mods.RA/Crates/UnitUpgradeCrateAction.cs index fdc8d00520..bab5b01445 100644 --- a/OpenRA.Mods.RA/Crates/UnitUpgradeCrateAction.cs +++ b/OpenRA.Mods.RA/Crates/UnitUpgradeCrateAction.cs @@ -8,30 +8,42 @@ */ #endregion +using System.Linq; + namespace OpenRA.Mods.RA.Crates { + [Desc("Grants an upgrade to the collector.")] public class UnitUpgradeCrateActionInfo : CrateActionInfo { + [Desc("The upgrade to grant.")] public readonly UnitUpgrade? Upgrade = null; + + [Desc("The number of levels of the upgrade to grant.")] public readonly int Levels = 1; + [Desc("The range to search for extra collectors in.","Extra collectors will also be granted the crate action.")] + public readonly WRange Range = new WRange(3); + + [Desc("The maximum number of extra collectors to grant the crate action to.","-1 = no limit")] + public readonly int MaxExtraCollectors = 4; + public override object Create(ActorInitializer init) { return new UnitUpgradeCrateAction(init.self, this); } } public class UnitUpgradeCrateAction : CrateAction { - UnitUpgradeCrateActionInfo crateInfo; + UnitUpgradeCrateActionInfo Info; public UnitUpgradeCrateAction(Actor self, UnitUpgradeCrateActionInfo info) : base(self, info) { - crateInfo = info; + Info = info; } public override int GetSelectionShares(Actor collector) { var up = collector.TraitOrDefault(); - return up != null && up.CanGainUnitUpgrade(crateInfo.Upgrade) ? info.SelectionShares : 0; + return up != null && up.CanGainUnitUpgrade(Info.Upgrade) ? info.SelectionShares : 0; } public override void Activate(Actor collector) @@ -40,9 +52,32 @@ namespace OpenRA.Mods.RA.Crates { var gainsStatBonuses = collector.TraitOrDefault(); if (gainsStatBonuses != null) - gainsStatBonuses.GiveUnitUpgrade(crateInfo.Upgrade, crateInfo.Levels); + gainsStatBonuses.GiveUnitUpgrade(Info.Upgrade, Info.Levels); }); + var inRange = self.World.FindActorsInCircle(self.CenterPosition, Info.Range); + inRange = inRange.Where(a => + (a.Owner == collector.Owner) && + (a != collector) && + (a.TraitOrDefault() != null) && + (a.TraitOrDefault().CanGainUnitUpgrade(Info.Upgrade))); + if (inRange.Any()) + { + if (Info.MaxExtraCollectors > -1) + inRange = inRange.Take(Info.MaxExtraCollectors); + + if (inRange.Any()) + foreach (Actor actor in inRange) + { + actor.World.AddFrameEndTask(w => + { + var gainsStatBonuses = actor.TraitOrDefault(); + if (gainsStatBonuses != null) + gainsStatBonuses.GiveUnitUpgrade(Info.Upgrade, Info.Levels); + }); + } + } + base.Activate(collector); } } diff --git a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj index 6b357803dc..d54222bf87 100644 --- a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj +++ b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj @@ -117,6 +117,7 @@ + diff --git a/mods/d2k/rules/misc.yaml b/mods/d2k/rules/misc.yaml index 13e6e8a445..78eec36622 100644 --- a/mods/d2k/rules/misc.yaml +++ b/mods/d2k/rules/misc.yaml @@ -20,61 +20,75 @@ CRATE: SelectionShares: 40 GiveUnitCrateAction@Trike: SelectionShares: 20 - Unit: trike + Units: trike GiveUnitCrateAction@Raider: SelectionShares: 15 - Unit: raider + Units: raider + ValidRaces: ordos GiveUnitCrateAction@Quad: SelectionShares: 40 - Unit: quad + Units: quad GiveUnitCrateAction@CombatA: SelectionShares: 10 - Unit: combata + Units: combata + ValidRaces: atreides GiveUnitCrateAction@CombatH: SelectionShares: 10 - Unit: combath + Units: combath + ValidRaces: harkonnen GiveUnitCrateAction@CombatO: SelectionShares: 10 - Unit: combato + Units: combato + ValidRaces: ordos GiveUnitCrateAction@SiegeTank: SelectionShares: 10 - Unit: siegetank + Units: siegetank GiveUnitCrateAction@MissileTank: SelectionShares: 10 - Unit: missiletank + Units: missiletank GiveUnitCrateAction@StealthRaider: SelectionShares: 7 - Unit: stealthraider + Units: stealthraider + ValidRaces: ordos GiveUnitCrateAction@Fremen: SelectionShares: 5 - Unit: fremen + Units: fremen,fremen + ValidRaces: atreides GiveUnitCrateAction@Sardaukar: SelectionShares: 8 - Unit: sardaukar + Units: sardaukar,sardaukar + ValidRaces: harkonnen GiveUnitCrateAction@Saboteur: SelectionShares: 3 - Unit: saboteur + Units: saboteur,saboteur + ValidRaces: ordos GiveUnitCrateAction@SonicTank: SelectionShares: 5 - Unit: sonictank + Units: sonictank + ValidRaces: atreides GiveUnitCrateAction@Devast: SelectionShares: 2 - Unit: devast + Units: devast + ValidRaces: harkonnen GiveUnitCrateAction@DeviatorTank: SelectionShares: 5 - Unit: deviatortank + Units: deviatortank + ValidRaces: ordos GiveMcvCrateAction@Atreides: SelectionShares: 0 NoBaseSelectionShares: 9001 - Unit: mcva + Units: mcva + ValidRaces: atreides GiveMcvCrateAction@Harkonnen: SelectionShares: 0 NoBaseSelectionShares: 9001 - Unit: mcvh + Units: mcvh + ValidRaces: harkonnen GiveMcvCrateAction@Ordos: SelectionShares: 0 NoBaseSelectionShares: 9001 - Unit: mcvo + Units: mcvo + ValidRaces: ordos RenderSprites: Palette: effect WithCrateBody: diff --git a/mods/ra/rules/misc.yaml b/mods/ra/rules/misc.yaml index e7330b0fc9..2e471b0e0f 100644 --- a/mods/ra/rules/misc.yaml +++ b/mods/ra/rules/misc.yaml @@ -89,31 +89,64 @@ CRATE: SelectionShares: 5 Proxy: powerproxy.parabombs Effect: parabombs + DuplicateUnitCrateAction: + SelectionShares: 10 + MaxAmount: 5 + MinAmount: 1 + MaxDuplicatesWorth: 1500 GiveMcvCrateAction: SelectionShares: 2 NoBaseSelectionShares: 100 - Unit: mcv + Units: mcv GiveUnitCrateAction@jeep: SelectionShares: 7 - Unit: jeep + Units: jeep + ValidRaces: allies + TimeDelay: 3000 GiveUnitCrateAction@arty: SelectionShares: 6 - Unit: arty + Units: arty + ValidRaces: allies + TimeDelay: 4500 GiveUnitCrateAction@v2rl: SelectionShares: 6 - Unit: v2rl + Units: v2rl + ValidRaces: soviet + TimeDelay: 4500 GiveUnitCrateAction@1tnk: SelectionShares: 5 - Unit: 1tnk + Units: 1tnk + ValidRaces: allies + TimeDelay: 3000 GiveUnitCrateAction@2tnk: SelectionShares: 4 - Unit: 2tnk + Units: 2tnk + ValidRaces: allies + TimeDelay: 4500 GiveUnitCrateAction@3tnk: SelectionShares: 4 - Unit: 3tnk + Units: 3tnk + ValidRaces: soviet + TimeDelay: 4500 GiveUnitCrateAction@4tnk: SelectionShares: 3 - Unit: 4tnk + Units: 4tnk + ValidRaces: soviet + TimeDelay: 9000 + GiveUnitCrateAction@squadlight: + SelectionShares: 7 + Units: e1,e1,e1,e3,e3 + ValidRaces: allies, soviet + GiveUnitCrateAction@squadheavyallies: + SelectionShares: 7 + Units: e1,e1,e1,e1,e3,e3,e3,e6,medi + ValidRaces: allies + TimeDelay: 4500 + GiveUnitCrateAction@squadheavysoviet: + SelectionShares: 7 + Units: e1,e1,e4,e4,e3,e3,e3 + ValidRaces: soviet + TimeDelay: 4500 RenderSprites: Palette: effect WithCrateBody: