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
|
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;
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
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
|
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); }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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); }
|
||||||
|
|||||||
@@ -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); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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[] 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); }
|
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.Race.Any() && !Info.Race.Contains(collector.Owner.Country.Race))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
foreach (string unit in Info.Units)
|
||||||
|
{
|
||||||
// avoid dumping tanks in the sea, and ships on dry land.
|
// avoid dumping tanks in the sea, and ships on dry land.
|
||||||
if (!GetSuitableCells(collector.Location).Any())
|
if (!GetSuitableCells(collector.Location, unit).Any()) return false;
|
||||||
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)
|
||||||
|
{
|
||||||
|
var unit = u; // avoiding access to modified closure
|
||||||
|
|
||||||
|
var location = ChooseEmptyCellNear(collector, unit);
|
||||||
if (location != null)
|
if (location != null)
|
||||||
|
{
|
||||||
|
usedCells.Add(location.Value);
|
||||||
collector.World.AddFrameEndTask(
|
collector.World.AddFrameEndTask(
|
||||||
w => w.CreateActor(Info.Unit, new TypeDictionary
|
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;
|
||||||
|
|
||||||
|
|||||||
@@ -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); }
|
||||||
|
|||||||
@@ -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); }
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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" />
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
Reference in New Issue
Block a user