Fix crates spawning actors inside other actors

This commit is contained in:
Gustas
2023-05-07 13:53:05 +03:00
committed by Matthias Mailänder
parent 60fbecd4a7
commit 2de212710a
2 changed files with 35 additions and 35 deletions

View File

@@ -83,29 +83,31 @@ namespace OpenRA.Mods.Common.Traits
public override void Activate(Actor collector) public override void Activate(Actor collector)
{ {
var positionable = collector.OccupiesSpace as IPositionable; var positionable = collector.OccupiesSpace as IPositionable;
var candidateCells = collector.World.Map.FindTilesInCircle(collector.Location, info.MaxRadius) collector.World.AddFrameEndTask(w =>
.Where(c => positionable.CanEnterCell(c)).Shuffle(collector.World.SharedRandom)
.ToArray();
var duplicates = Math.Min(candidateCells.Length, info.MaxAmount);
// Restrict duplicate count to a maximum value
if (info.MaxDuplicateValue > 0)
{ {
var vi = collector.Info.TraitInfoOrDefault<ValuedInfo>(); var candidateCells = collector.World.Map.FindTilesInCircle(collector.Location, info.MaxRadius)
if (vi != null && vi.Cost > 0) .Where(c => positionable.CanEnterCell(c)).Shuffle(collector.World.SharedRandom)
duplicates = Math.Min(duplicates, info.MaxDuplicateValue / vi.Cost); .ToArray();
}
for (var i = 0; i < duplicates; i++) var duplicates = Math.Min(candidateCells.Length, info.MaxAmount);
{
var cell = candidateCells[i]; // Avoid modified closure bug // Restrict duplicate count to a maximum value
collector.World.AddFrameEndTask(w => w.CreateActor(collector.Info.Name, new TypeDictionary if (info.MaxDuplicateValue > 0)
{ {
new LocationInit(cell), var vi = collector.Info.TraitInfoOrDefault<ValuedInfo>();
new OwnerInit(info.Owner ?? collector.Owner.InternalName) if (vi != null && vi.Cost > 0)
})); duplicates = Math.Min(duplicates, info.MaxDuplicateValue / vi.Cost);
} }
for (var i = 0; i < duplicates; i++)
{
w.CreateActor(collector.Info.Name, new TypeDictionary
{
new LocationInit(candidateCells[i]),
new OwnerInit(info.Owner ?? collector.Owner.InternalName)
});
}
});
base.Activate(collector); base.Activate(collector);
} }

View File

@@ -38,7 +38,6 @@ namespace OpenRA.Mods.Common.Traits
{ {
readonly Actor self; readonly Actor self;
readonly GiveUnitCrateActionInfo info; readonly GiveUnitCrateActionInfo info;
readonly List<CPos> usedCells = new();
public GiveUnitCrateAction(Actor self, GiveUnitCrateActionInfo info) public GiveUnitCrateAction(Actor self, GiveUnitCrateActionInfo info)
: base(self, info) : base(self, info)
@@ -77,22 +76,21 @@ namespace OpenRA.Mods.Common.Traits
public override void Activate(Actor collector) public override void Activate(Actor collector)
{ {
foreach (var u in info.Units) collector.World.AddFrameEndTask(w =>
{ {
var unit = u; // avoiding access to modified closure foreach (var unit in info.Units)
var location = ChooseEmptyCellNear(collector, unit);
if (location != null)
{ {
usedCells.Add(location.Value); var location = ChooseEmptyCellNear(collector, unit);
collector.World.AddFrameEndTask( if (location != null)
w => w.CreateActor(unit, new TypeDictionary
{ {
new LocationInit(location.Value), w.CreateActor(unit, new TypeDictionary
new OwnerInit(info.Owner ?? collector.Owner.InternalName) {
})); new LocationInit(location.Value),
new OwnerInit(info.Owner ?? collector.Owner.InternalName)
});
}
} }
} });
base.Activate(collector); base.Activate(collector);
} }
@@ -109,8 +107,8 @@ namespace OpenRA.Mods.Common.Traits
CPos? ChooseEmptyCellNear(Actor a, string unit) CPos? ChooseEmptyCellNear(Actor a, string unit)
{ {
var possibleCells = GetSuitableCells(a.Location, unit).Where(c => !usedCells.Contains(c)).ToList(); var possibleCells = GetSuitableCells(a.Location, unit);
if (possibleCells.Count == 0) if (!possibleCells.Any())
return null; return null;
return possibleCells.Random(self.World.SharedRandom); return possibleCells.Random(self.World.SharedRandom);