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.
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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<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);
|
||||
}
|
||||
}
|
||||
|
||||
121
OpenRA.Mods.RA/Crates/DuplicateUnitCrateAction.cs
Normal file
121
OpenRA.Mods.RA/Crates/DuplicateUnitCrateAction.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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); }
|
||||
}
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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); }
|
||||
}
|
||||
|
||||
|
||||
@@ -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<CPos> usedCells = new List<CPos>();
|
||||
|
||||
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<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 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;
|
||||
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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<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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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); }
|
||||
}
|
||||
|
||||
|
||||
@@ -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); }
|
||||
}
|
||||
|
||||
|
||||
@@ -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<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)
|
||||
@@ -40,9 +52,32 @@ namespace OpenRA.Mods.RA.Crates
|
||||
{
|
||||
var gainsStatBonuses = collector.TraitOrDefault<GainsUnitUpgrades>();
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,6 +117,7 @@
|
||||
<Compile Include="Air\Aircraft.cs" />
|
||||
<Compile Include="Air\AttackHeli.cs" />
|
||||
<Compile Include="Air\AttackPlane.cs" />
|
||||
<Compile Include="Crates\DuplicateUnitCrateAction.cs" />
|
||||
<Compile Include="Effects\Beacon.cs" />
|
||||
<Compile Include="Player\PlaceBeacon.cs" />
|
||||
<Compile Include="MenuPaletteEffect.cs" />
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user