fix actor leak bug

This commit is contained in:
Bob
2010-09-09 01:47:26 +12:00
parent c3fa9f7aa8
commit f70a6aafb1
3 changed files with 39 additions and 43 deletions

View File

@@ -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)

View File

@@ -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;

View File

@@ -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());