Merge pull request #5921 from UberWaffe/CrateMultiUnits

Crate updates.
This commit is contained in:
Chris Forbes
2014-07-23 09:50:54 +12:00
16 changed files with 374 additions and 63 deletions

View File

@@ -17,15 +17,22 @@ namespace OpenRA.Mods.RA
public class CrateActionInfo : ITraitInfo public class CrateActionInfo : ITraitInfo
{ {
[Desc("Chance of getting this crate, assuming the collector is compatible.")] [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.")] [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.")] [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.")] [Desc("Audio clip to play when the crate is collected.")]
public string Notification = null; public readonly string Notification = null;
[ActorReference]
public string[] ExcludedActorTypes = { }; [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); } 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) public int GetSelectionSharesOuter(Actor collector)
{ {
if (self.World.WorldTick < info.TimeDelay)
return 0;
if (info.ExcludedActorTypes.Contains(collector.Info.Name)) if (info.ExcludedActorTypes.Contains(collector.Info.Name))
return 0; return 0;

View File

@@ -8,17 +8,31 @@
*/ */
#endregion #endregion
using System.Linq;
namespace OpenRA.Mods.RA.Crates namespace OpenRA.Mods.RA.Crates
{ {
[Desc("Grants the collector the ability to cloak.")]
public class CloakCrateActionInfo : CrateActionInfo 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 override object Create(ActorInitializer init) { return new CloakCrateAction(init.self, this); }
} }
public class CloakCrateAction : CrateAction public class CloakCrateAction : CrateAction
{ {
CloakCrateActionInfo Info;
public CloakCrateAction(Actor self, CloakCrateActionInfo info) public CloakCrateAction(Actor self, CloakCrateActionInfo info)
: base(self, info) { } : base(self, info)
{
Info = info;
}
public override int GetSelectionShares(Actor collector) public override int GetSelectionShares(Actor collector)
{ {
@@ -32,6 +46,25 @@ namespace OpenRA.Mods.RA.Crates
public override void Activate(Actor collector) public override void Activate(Actor collector)
{ {
collector.Trait<Cloak>().ReceivedCloakCrate(collector); collector.Trait<Cloak>().ReceivedCloakCrate(collector);
var inRange = self.World.FindActorsInCircle(self.CenterPosition, Info.Range);
inRange = inRange.Where(a =>
(a.Owner == collector.Owner) &&
(a != collector) &&
(a.TraitOrDefault<Cloak>() != null) &&
(a.TraitOrDefault<Cloak>().AcceptsCloakCrate));
if (inRange.Any())
{
if (Info.MaxExtraCollectors > -1)
inRange = inRange.Take(Info.MaxExtraCollectors);
if (inRange.Any())
foreach (Actor actor in inRange)
{
actor.Trait<Cloak>().ReceivedCloakCrate(actor);
}
}
base.Activate(collector); base.Activate(collector);
} }
} }

View File

@@ -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<CPos> usedCells = new List<CPos>();
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<ITargetableInfo>();
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<ValuedInfo>().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<CPos> GetSuitableCells(CPos near, string unitName)
{
var mi = self.World.Map.Rules.Actors[unitName].Traits.Get<MobileInfo>();
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);
}
}
}

View File

@@ -12,10 +12,11 @@ using OpenRA.Traits;
namespace OpenRA.Mods.RA namespace OpenRA.Mods.RA
{ {
[Desc("Fires a weapon at the location when collected.")]
class ExplodeCrateActionInfo : CrateActionInfo class ExplodeCrateActionInfo : CrateActionInfo
{ {
[WeaponReference] [Desc("The weapon to fire upon collection.")]
public string Weapon = null; [WeaponReference] public string Weapon = null;
public override object Create(ActorInitializer init) { return new ExplodeCrateAction(init.self, this); } public override object Create(ActorInitializer init) { return new ExplodeCrateAction(init.self, this); }
} }

View File

@@ -13,9 +13,13 @@ using OpenRA.Traits;
namespace OpenRA.Mods.RA namespace OpenRA.Mods.RA
{ {
[Desc("Gives cash to the collector.")]
class GiveCashCrateActionInfo : CrateActionInfo class GiveCashCrateActionInfo : CrateActionInfo
{ {
[Desc("Amount of cash to give.")]
public int Amount = 2000; public int Amount = 2000;
[Desc("Should the collected amount be displayed as a cash tick?")]
public bool UseCashTick = false; public bool UseCashTick = false;
public override object Create(ActorInitializer init) { return new GiveCashCrateAction(init.self, this); } public override object Create(ActorInitializer init) { return new GiveCashCrateAction(init.self, this); }

View File

@@ -12,9 +12,12 @@ using System.Linq;
namespace OpenRA.Mods.RA.Crates namespace OpenRA.Mods.RA.Crates
{ {
[Desc("Spawns units when collected.","Adjust selection shares when player has no base.")]
class GiveMcvCrateActionInfo : GiveUnitCrateActionInfo class GiveMcvCrateActionInfo : GiveUnitCrateActionInfo
{ {
[Desc("The selection shares to use if the collector has no base.")]
public int NoBaseSelectionShares = 1000; public int NoBaseSelectionShares = 1000;
public override object Create(ActorInitializer init) { return new GiveMcvCrateAction(init.self, this); } public override object Create(ActorInitializer init) { return new GiveMcvCrateAction(init.self, this); }
} }

View File

@@ -16,36 +16,40 @@ using OpenRA.Traits;
namespace OpenRA.Mods.RA.Crates namespace OpenRA.Mods.RA.Crates
{ {
[Desc("Spawns units when collected.")]
class GiveUnitCrateActionInfo : CrateActionInfo class GiveUnitCrateActionInfo : CrateActionInfo
{ {
[Desc("The list of units to spawn.")]
[ActorReference] [ActorReference]
[Desc("Unit to give")] public readonly string[] Units = { };
public readonly string Unit = null;
[Desc("Override the owner of the newly spawned unit: e.g Creeps or Neutral")]
public readonly string Owner = null;
[Desc("Races that are allowed to trigger this action")] [Desc("Races that are allowed to trigger this action")]
public readonly string[] Race = null; public readonly string[] ValidRaces = { };
[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); } public override object Create(ActorInitializer init) { return new GiveUnitCrateAction(init.self, this); }
} }
class GiveUnitCrateAction : CrateAction class GiveUnitCrateAction : CrateAction
{ {
GiveUnitCrateActionInfo Info; public readonly GiveUnitCrateActionInfo Info;
readonly List<CPos> usedCells = new List<CPos>();
public GiveUnitCrateAction(Actor self, GiveUnitCrateActionInfo info) public GiveUnitCrateAction(Actor self, GiveUnitCrateActionInfo info)
: base(self, info) { Info = info; } : base(self, info) { Info = info; }
public bool CanGiveTo(Actor collector) public bool CanGiveTo(Actor collector)
{ {
if (Info.Race != null && !Info.Race.Contains(collector.Owner.Country.Race)) if (Info.ValidRaces.Any() && !Info.ValidRaces.Contains(collector.Owner.Country.Race))
return false; return false;
// avoid dumping tanks in the sea, and ships on dry land. foreach (string unit in Info.Units)
if (!GetSuitableCells(collector.Location).Any()) {
return false; // avoid dumping tanks in the sea, and ships on dry land.
if (!GetSuitableCells(collector.Location, unit).Any()) return false;
}
return true; return true;
} }
@@ -58,21 +62,28 @@ namespace OpenRA.Mods.RA.Crates
public override void Activate(Actor collector) public override void Activate(Actor collector)
{ {
var location = ChooseEmptyCellNear(collector); foreach (var u in Info.Units)
if (location != null) {
collector.World.AddFrameEndTask( var unit = u; // avoiding access to modified closure
w => w.CreateActor(Info.Unit, new TypeDictionary
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) new OwnerInit(Info.Owner ?? collector.Owner.InternalName)
})); }));
}
}
base.Activate(collector); base.Activate(collector);
} }
IEnumerable<CPos> GetSuitableCells(CPos near) IEnumerable<CPos> GetSuitableCells(CPos near, string unitName)
{ {
var mi = self.World.Map.Rules.Actors[Info.Unit].Traits.Get<MobileInfo>(); var mi = self.World.Map.Rules.Actors[unitName].Traits.Get<MobileInfo>();
for (var i = -1; i < 2; i++) for (var i = -1; i < 2; i++)
for (var j = -1; j < 2; j++) for (var j = -1; j < 2; j++)
@@ -80,9 +91,9 @@ namespace OpenRA.Mods.RA.Crates
yield return near + new CVec(i, j); 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) if (possibleCells.Length == 0)
return null; return null;

View File

@@ -13,6 +13,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.RA.Crates namespace OpenRA.Mods.RA.Crates
{ {
[Desc("Heals all actors that belong to the owner of the collector.")]
class HealUnitsCrateActionInfo : CrateActionInfo class HealUnitsCrateActionInfo : CrateActionInfo
{ {
public override object Create(ActorInitializer init) { return new HealUnitsCrateAction(init.self, this); } public override object Create(ActorInitializer init) { return new HealUnitsCrateAction(init.self, this); }

View File

@@ -10,6 +10,7 @@
namespace OpenRA.Mods.RA namespace OpenRA.Mods.RA
{ {
[Desc("Hides the entire map in shroud.")]
class HideMapCrateActionInfo : CrateActionInfo class HideMapCrateActionInfo : CrateActionInfo
{ {
public override object Create(ActorInitializer init) { return new HideMapCrateAction(init.self, this); } public override object Create(ActorInitializer init) { return new HideMapCrateAction(init.self, this); }

View File

@@ -8,19 +8,34 @@
*/ */
#endregion #endregion
using System.Linq;
namespace OpenRA.Mods.RA namespace OpenRA.Mods.RA
{ {
[Desc("Gives experience levels to the collector.")]
class LevelUpCrateActionInfo : CrateActionInfo class LevelUpCrateActionInfo : CrateActionInfo
{ {
[Desc("Number of experience levels to give.")]
public readonly int Levels = 1; 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); } public override object Create(ActorInitializer init) { return new LevelUpCrateAction(init.self, this); }
} }
class LevelUpCrateAction : CrateAction class LevelUpCrateAction : CrateAction
{ {
LevelUpCrateActionInfo Info;
public LevelUpCrateAction(Actor self, LevelUpCrateActionInfo info) public LevelUpCrateAction(Actor self, LevelUpCrateActionInfo info)
: base(self,info) {} : base(self, info)
{
Info = info;
}
public override int GetSelectionShares(Actor collector) public override int GetSelectionShares(Actor collector)
{ {
@@ -37,6 +52,29 @@ namespace OpenRA.Mods.RA
gainsExperience.GiveLevels(((LevelUpCrateActionInfo)info).Levels); 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<GainsExperience>() != null) &&
(a.TraitOrDefault<GainsExperience>().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<GainsExperience>();
if (gainsExperience != null)
gainsExperience.GiveLevels(((LevelUpCrateActionInfo)info).Levels);
});
}
}
base.Activate(collector); base.Activate(collector);
} }
} }

View File

@@ -12,9 +12,12 @@ using OpenRA.Traits;
namespace OpenRA.Mods.RA namespace OpenRA.Mods.RA
{ {
[Desc("Reveals the entire map.")]
class RevealMapCrateActionInfo : CrateActionInfo class RevealMapCrateActionInfo : CrateActionInfo
{ {
[Desc("Should the map also be revealed for the allies of the collector's owner.")]
public readonly bool IncludeAllies = false; public readonly bool IncludeAllies = false;
public override object Create(ActorInitializer init) { return new RevealMapCrateAction(init.self, this); } public override object Create(ActorInitializer init) { return new RevealMapCrateAction(init.self, this); }
} }

View File

@@ -13,10 +13,12 @@ using OpenRA.Traits;
namespace OpenRA.Mods.RA.Crates namespace OpenRA.Mods.RA.Crates
{ {
[Desc("Gives a supportpower to the collector.")]
class SupportPowerCrateActionInfo : CrateActionInfo class SupportPowerCrateActionInfo : CrateActionInfo
{ {
[ActorReference] [Desc("Which proxy actor, which grants the support power, to spawn.")]
public readonly string Proxy = null; [ActorReference] public readonly string Proxy = null;
public override object Create(ActorInitializer init) { return new SupportPowerCrateAction(init.self, this); } public override object Create(ActorInitializer init) { return new SupportPowerCrateAction(init.self, this); }
} }

View File

@@ -8,30 +8,42 @@
*/ */
#endregion #endregion
using System.Linq;
namespace OpenRA.Mods.RA.Crates namespace OpenRA.Mods.RA.Crates
{ {
[Desc("Grants an upgrade to the collector.")]
public class UnitUpgradeCrateActionInfo : CrateActionInfo public class UnitUpgradeCrateActionInfo : CrateActionInfo
{ {
[Desc("The upgrade to grant.")]
public readonly UnitUpgrade? Upgrade = null; public readonly UnitUpgrade? Upgrade = null;
[Desc("The number of levels of the upgrade to grant.")]
public readonly int Levels = 1; 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 override object Create(ActorInitializer init) { return new UnitUpgradeCrateAction(init.self, this); }
} }
public class UnitUpgradeCrateAction : CrateAction public class UnitUpgradeCrateAction : CrateAction
{ {
UnitUpgradeCrateActionInfo crateInfo; UnitUpgradeCrateActionInfo Info;
public UnitUpgradeCrateAction(Actor self, UnitUpgradeCrateActionInfo info) public UnitUpgradeCrateAction(Actor self, UnitUpgradeCrateActionInfo info)
: base(self, info) : base(self, info)
{ {
crateInfo = info; Info = info;
} }
public override int GetSelectionShares(Actor collector) public override int GetSelectionShares(Actor collector)
{ {
var up = collector.TraitOrDefault<GainsUnitUpgrades>(); var up = collector.TraitOrDefault<GainsUnitUpgrades>();
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) public override void Activate(Actor collector)
@@ -40,9 +52,32 @@ namespace OpenRA.Mods.RA.Crates
{ {
var gainsStatBonuses = collector.TraitOrDefault<GainsUnitUpgrades>(); var gainsStatBonuses = collector.TraitOrDefault<GainsUnitUpgrades>();
if (gainsStatBonuses != null) 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<GainsUnitUpgrades>() != null) &&
(a.TraitOrDefault<GainsUnitUpgrades>().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<GainsUnitUpgrades>();
if (gainsStatBonuses != null)
gainsStatBonuses.GiveUnitUpgrade(Info.Upgrade, Info.Levels);
});
}
}
base.Activate(collector); base.Activate(collector);
} }
} }

View File

@@ -117,6 +117,7 @@
<Compile Include="Air\Aircraft.cs" /> <Compile Include="Air\Aircraft.cs" />
<Compile Include="Air\AttackHeli.cs" /> <Compile Include="Air\AttackHeli.cs" />
<Compile Include="Air\AttackPlane.cs" /> <Compile Include="Air\AttackPlane.cs" />
<Compile Include="Crates\DuplicateUnitCrateAction.cs" />
<Compile Include="Effects\Beacon.cs" /> <Compile Include="Effects\Beacon.cs" />
<Compile Include="Player\PlaceBeacon.cs" /> <Compile Include="Player\PlaceBeacon.cs" />
<Compile Include="MenuPaletteEffect.cs" /> <Compile Include="MenuPaletteEffect.cs" />

View File

@@ -20,61 +20,75 @@ CRATE:
SelectionShares: 40 SelectionShares: 40
GiveUnitCrateAction@Trike: GiveUnitCrateAction@Trike:
SelectionShares: 20 SelectionShares: 20
Unit: trike Units: trike
GiveUnitCrateAction@Raider: GiveUnitCrateAction@Raider:
SelectionShares: 15 SelectionShares: 15
Unit: raider Units: raider
ValidRaces: ordos
GiveUnitCrateAction@Quad: GiveUnitCrateAction@Quad:
SelectionShares: 40 SelectionShares: 40
Unit: quad Units: quad
GiveUnitCrateAction@CombatA: GiveUnitCrateAction@CombatA:
SelectionShares: 10 SelectionShares: 10
Unit: combata Units: combata
ValidRaces: atreides
GiveUnitCrateAction@CombatH: GiveUnitCrateAction@CombatH:
SelectionShares: 10 SelectionShares: 10
Unit: combath Units: combath
ValidRaces: harkonnen
GiveUnitCrateAction@CombatO: GiveUnitCrateAction@CombatO:
SelectionShares: 10 SelectionShares: 10
Unit: combato Units: combato
ValidRaces: ordos
GiveUnitCrateAction@SiegeTank: GiveUnitCrateAction@SiegeTank:
SelectionShares: 10 SelectionShares: 10
Unit: siegetank Units: siegetank
GiveUnitCrateAction@MissileTank: GiveUnitCrateAction@MissileTank:
SelectionShares: 10 SelectionShares: 10
Unit: missiletank Units: missiletank
GiveUnitCrateAction@StealthRaider: GiveUnitCrateAction@StealthRaider:
SelectionShares: 7 SelectionShares: 7
Unit: stealthraider Units: stealthraider
ValidRaces: ordos
GiveUnitCrateAction@Fremen: GiveUnitCrateAction@Fremen:
SelectionShares: 5 SelectionShares: 5
Unit: fremen Units: fremen,fremen
ValidRaces: atreides
GiveUnitCrateAction@Sardaukar: GiveUnitCrateAction@Sardaukar:
SelectionShares: 8 SelectionShares: 8
Unit: sardaukar Units: sardaukar,sardaukar
ValidRaces: harkonnen
GiveUnitCrateAction@Saboteur: GiveUnitCrateAction@Saboteur:
SelectionShares: 3 SelectionShares: 3
Unit: saboteur Units: saboteur,saboteur
ValidRaces: ordos
GiveUnitCrateAction@SonicTank: GiveUnitCrateAction@SonicTank:
SelectionShares: 5 SelectionShares: 5
Unit: sonictank Units: sonictank
ValidRaces: atreides
GiveUnitCrateAction@Devast: GiveUnitCrateAction@Devast:
SelectionShares: 2 SelectionShares: 2
Unit: devast Units: devast
ValidRaces: harkonnen
GiveUnitCrateAction@DeviatorTank: GiveUnitCrateAction@DeviatorTank:
SelectionShares: 5 SelectionShares: 5
Unit: deviatortank Units: deviatortank
ValidRaces: ordos
GiveMcvCrateAction@Atreides: GiveMcvCrateAction@Atreides:
SelectionShares: 0 SelectionShares: 0
NoBaseSelectionShares: 9001 NoBaseSelectionShares: 9001
Unit: mcva Units: mcva
ValidRaces: atreides
GiveMcvCrateAction@Harkonnen: GiveMcvCrateAction@Harkonnen:
SelectionShares: 0 SelectionShares: 0
NoBaseSelectionShares: 9001 NoBaseSelectionShares: 9001
Unit: mcvh Units: mcvh
ValidRaces: harkonnen
GiveMcvCrateAction@Ordos: GiveMcvCrateAction@Ordos:
SelectionShares: 0 SelectionShares: 0
NoBaseSelectionShares: 9001 NoBaseSelectionShares: 9001
Unit: mcvo Units: mcvo
ValidRaces: ordos
RenderSprites: RenderSprites:
Palette: effect Palette: effect
WithCrateBody: WithCrateBody:

View File

@@ -89,31 +89,64 @@ CRATE:
SelectionShares: 5 SelectionShares: 5
Proxy: powerproxy.parabombs Proxy: powerproxy.parabombs
Effect: parabombs Effect: parabombs
DuplicateUnitCrateAction:
SelectionShares: 10
MaxAmount: 5
MinAmount: 1
MaxDuplicatesWorth: 1500
GiveMcvCrateAction: GiveMcvCrateAction:
SelectionShares: 2 SelectionShares: 2
NoBaseSelectionShares: 100 NoBaseSelectionShares: 100
Unit: mcv Units: mcv
GiveUnitCrateAction@jeep: GiveUnitCrateAction@jeep:
SelectionShares: 7 SelectionShares: 7
Unit: jeep Units: jeep
ValidRaces: allies
TimeDelay: 3000
GiveUnitCrateAction@arty: GiveUnitCrateAction@arty:
SelectionShares: 6 SelectionShares: 6
Unit: arty Units: arty
ValidRaces: allies
TimeDelay: 4500
GiveUnitCrateAction@v2rl: GiveUnitCrateAction@v2rl:
SelectionShares: 6 SelectionShares: 6
Unit: v2rl Units: v2rl
ValidRaces: soviet
TimeDelay: 4500
GiveUnitCrateAction@1tnk: GiveUnitCrateAction@1tnk:
SelectionShares: 5 SelectionShares: 5
Unit: 1tnk Units: 1tnk
ValidRaces: allies
TimeDelay: 3000
GiveUnitCrateAction@2tnk: GiveUnitCrateAction@2tnk:
SelectionShares: 4 SelectionShares: 4
Unit: 2tnk Units: 2tnk
ValidRaces: allies
TimeDelay: 4500
GiveUnitCrateAction@3tnk: GiveUnitCrateAction@3tnk:
SelectionShares: 4 SelectionShares: 4
Unit: 3tnk Units: 3tnk
ValidRaces: soviet
TimeDelay: 4500
GiveUnitCrateAction@4tnk: GiveUnitCrateAction@4tnk:
SelectionShares: 3 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: RenderSprites:
Palette: effect Palette: effect
WithCrateBody: WithCrateBody: