fix actor leak bug
This commit is contained in:
@@ -88,7 +88,6 @@ namespace OpenRA.Traits
|
|||||||
|
|
||||||
Shroud shroud;
|
Shroud shroud;
|
||||||
UnitInfluence uim;
|
UnitInfluence uim;
|
||||||
BuildingInfluence bim;
|
|
||||||
bool canShareCell;
|
bool canShareCell;
|
||||||
|
|
||||||
public Mobile(ActorInitializer init, MobileInfo info)
|
public Mobile(ActorInitializer init, MobileInfo info)
|
||||||
@@ -98,7 +97,6 @@ namespace OpenRA.Traits
|
|||||||
|
|
||||||
shroud = self.World.WorldActor.Trait<Shroud>();
|
shroud = self.World.WorldActor.Trait<Shroud>();
|
||||||
uim = self.World.WorldActor.Trait<UnitInfluence>();
|
uim = self.World.WorldActor.Trait<UnitInfluence>();
|
||||||
bim = self.World.WorldActor.Trait<BuildingInfluence>();
|
|
||||||
canShareCell = self.HasTrait<SharesCell>();
|
canShareCell = self.HasTrait<SharesCell>();
|
||||||
|
|
||||||
if (init.Contains<LocationInit>())
|
if (init.Contains<LocationInit>())
|
||||||
@@ -208,50 +206,47 @@ namespace OpenRA.Traits
|
|||||||
|
|
||||||
public bool CanEnterCell(int2 p)
|
public bool CanEnterCell(int2 p)
|
||||||
{
|
{
|
||||||
return CanEnterCell(p, null, true);
|
return CanEnterCell( p, null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual bool CanEnterCell(int2 cell, Actor ignoreActor, bool checkTransientActors)
|
public virtual bool CanEnterCell( int2 cell, Actor ignoreActor, bool checkTransientActors )
|
||||||
{
|
{
|
||||||
if (MovementCostForCell(self, cell) == float.PositiveInfinity)
|
return CanEnterCell( Info, self.World, cell, ignoreActor, checkTransientActors );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool CanEnterCell( MobileInfo mobileInfo, World world, int2 cell, Actor ignoreActor, bool checkTransientActors )
|
||||||
|
{
|
||||||
|
if (MovementCostForCell(mobileInfo, world, cell) == float.PositiveInfinity)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
var bim = world.WorldActor.Trait<BuildingInfluence>();
|
||||||
|
var uim = world.WorldActor.Trait<UnitInfluence>();
|
||||||
|
|
||||||
// Check for buildings
|
// Check for buildings
|
||||||
var building = bim.GetBuildingBlocking(cell);
|
var building = bim.GetBuildingBlocking(cell);
|
||||||
if (building != null && building != ignoreActor)
|
if (building != null && building != ignoreActor)
|
||||||
{
|
{
|
||||||
if (Info.Crushes == null)
|
if (mobileInfo.Crushes == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var crushable = building.TraitsImplementing<ICrushable>();
|
var crushable = building.TraitsImplementing<ICrushable>();
|
||||||
if (crushable.Count() == 0)
|
if (crushable.Count() == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!crushable.Any(b => b.CrushClasses.Intersect(Info.Crushes).Any()))
|
if (!crushable.Any(b => b.CrushClasses.Intersect(mobileInfo.Crushes).Any()))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check mobile actors
|
// Check mobile actors
|
||||||
if (checkTransientActors && uim.AnyUnitsAt(cell))
|
if (checkTransientActors && uim.AnyUnitsAt(cell))
|
||||||
{
|
{
|
||||||
var actors = uim.GetUnitsAt(cell).Where(a => a != self && a != ignoreActor).ToArray();
|
var actors = uim.GetUnitsAt(cell).Where(a => a != ignoreActor).ToArray();
|
||||||
var nonshareable = canShareCell ? actors : actors.Where(a => !a.HasTrait<SharesCell>()).ToArray();
|
|
||||||
|
|
||||||
if (canShareCell)
|
|
||||||
{
|
|
||||||
var shareable = actors.Where(a => a.HasTrait<SharesCell>());
|
|
||||||
|
|
||||||
// only allow 5 in a cell
|
|
||||||
if (shareable.Count() >= 5)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We can enter a cell with nonshareable units only if we can crush all of them
|
// We can enter a cell with nonshareable units only if we can crush all of them
|
||||||
if (Info.Crushes == null && nonshareable.Length > 0)
|
if (mobileInfo.Crushes == null && actors.Length > 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (nonshareable.Length > 0 && nonshareable.Any(a => !(a.HasTrait<ICrushable>() &&
|
if (actors.Length > 0 && actors.Any(a => !(a.HasTrait<ICrushable>() &&
|
||||||
a.TraitsImplementing<ICrushable>().Any(b => b.CrushClasses.Intersect(Info.Crushes).Any()))))
|
a.TraitsImplementing<ICrushable>().Any(b => b.CrushClasses.Intersect(mobileInfo.Crushes).Any()))))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,16 +265,21 @@ namespace OpenRA.Traits
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual float MovementCostForCell(Actor self, int2 cell)
|
public float MovementCostForCell( Actor self, int2 cell )
|
||||||
{
|
{
|
||||||
if (!self.World.Map.IsInMap(cell.X,cell.Y))
|
return MovementCostForCell( Info, self.World, cell );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float MovementCostForCell(MobileInfo info, World world, int2 cell)
|
||||||
|
{
|
||||||
|
if (!world.Map.IsInMap(cell.X,cell.Y))
|
||||||
return float.PositiveInfinity;
|
return float.PositiveInfinity;
|
||||||
|
|
||||||
var type = self.World.GetTerrainType(cell);
|
var type = world.GetTerrainType(cell);
|
||||||
if (!Info.TerrainSpeeds.ContainsKey(type))
|
if (!info.TerrainSpeeds.ContainsKey(type))
|
||||||
return float.PositiveInfinity;
|
return float.PositiveInfinity;
|
||||||
|
|
||||||
return Info.TerrainSpeeds[type].Cost;
|
return info.TerrainSpeeds[type].Cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual float MovementSpeedForCell(Actor self, int2 cell)
|
public virtual float MovementSpeedForCell(Actor self, int2 cell)
|
||||||
|
|||||||
@@ -37,8 +37,13 @@ namespace OpenRA.Traits
|
|||||||
Info = info;
|
Info = info;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DoProduction(Actor self, Actor newUnit, ExitInfo exitinfo)
|
public void DoProduction(Actor self, ActorInfo producee, ExitInfo exitinfo)
|
||||||
{
|
{
|
||||||
|
var newUnit = self.World.CreateActor(false, producee.Name, new TypeDictionary
|
||||||
|
{
|
||||||
|
new OwnerInit( self.Owner ),
|
||||||
|
});
|
||||||
|
|
||||||
var exit = self.Location + exitinfo.ExitCell;
|
var exit = self.Location + exitinfo.ExitCell;
|
||||||
var spawn = self.CenterLocation + exitinfo.SpawnOffset;
|
var spawn = self.CenterLocation + exitinfo.SpawnOffset;
|
||||||
|
|
||||||
@@ -86,21 +91,17 @@ namespace OpenRA.Traits
|
|||||||
|
|
||||||
public virtual bool Produce( Actor self, ActorInfo producee )
|
public virtual bool Produce( Actor self, ActorInfo producee )
|
||||||
{
|
{
|
||||||
var newUnit = self.World.CreateActor(false, producee.Name, new TypeDictionary
|
|
||||||
{
|
|
||||||
new OwnerInit( self.Owner ),
|
|
||||||
});
|
|
||||||
|
|
||||||
// Todo: remove assumption on Mobile;
|
// Todo: remove assumption on Mobile;
|
||||||
// required for 3-arg CanEnterCell
|
// required for 3-arg CanEnterCell
|
||||||
var mobile = newUnit.Trait<Mobile>();
|
//var mobile = newUnit.Trait<Mobile>();
|
||||||
|
var mobileInfo = producee.Traits.Get<MobileInfo>();
|
||||||
|
|
||||||
// Pick a spawn/exit point pair
|
// Pick a spawn/exit point pair
|
||||||
// Todo: Reorder in a synced random way
|
// Todo: Reorder in a synced random way
|
||||||
foreach (var s in self.Info.Traits.WithInterface<ExitInfo>())
|
foreach (var s in self.Info.Traits.WithInterface<ExitInfo>())
|
||||||
if (mobile.CanEnterCell(self.Location + s.ExitCell,self,true))
|
if( Mobile.CanEnterCell( mobileInfo, self.World, self.Location + s.ExitCell,self,true ) )
|
||||||
{
|
{
|
||||||
DoProduction(self, newUnit, s);
|
DoProduction(self, producee, s);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -52,11 +52,6 @@ namespace OpenRA.Mods.Cnc
|
|||||||
});
|
});
|
||||||
|
|
||||||
var cargo = a.Trait<Cargo>();
|
var cargo = a.Trait<Cargo>();
|
||||||
var newUnit = self.World.CreateActor(false, producee.Name, new TypeDictionary
|
|
||||||
{
|
|
||||||
new OwnerInit( self.Owner ),
|
|
||||||
});
|
|
||||||
cargo.Load(a, newUnit);
|
|
||||||
a.QueueActivity(new Fly(self.Location + new int2(6,0)));
|
a.QueueActivity(new Fly(self.Location + new int2(6,0)));
|
||||||
a.QueueActivity(new Land(Target.FromActor(self)));
|
a.QueueActivity(new Land(Target.FromActor(self)));
|
||||||
a.QueueActivity(new CallFunc(() =>
|
a.QueueActivity(new CallFunc(() =>
|
||||||
@@ -64,7 +59,7 @@ namespace OpenRA.Mods.Cnc
|
|||||||
if (self.IsDead())
|
if (self.IsDead())
|
||||||
return;
|
return;
|
||||||
rb.PlayCustomAnimRepeating(self, "idle");
|
rb.PlayCustomAnimRepeating(self, "idle");
|
||||||
self.World.AddFrameEndTask(ww => DoProduction(self, cargo.Unload(self), exit));
|
self.World.AddFrameEndTask(ww => DoProduction(self, producee, exit));
|
||||||
}));
|
}));
|
||||||
a.QueueActivity(new Fly(endPos));
|
a.QueueActivity(new Fly(endPos));
|
||||||
a.QueueActivity(new RemoveSelf());
|
a.QueueActivity(new RemoveSelf());
|
||||||
|
|||||||
Reference in New Issue
Block a user