public virtual bool Produce(Actor self, ActorInfo producee, string productionType, TypeDictionary inits, ManipulateActorCallback OnSpawnCallback) { if (IsTraitDisabled || IsTraitPaused || Reservable.IsReserved(self)) { return(false); } // Pick a spawn/exit point pair var exit = SelectExit(self, producee, productionType); if (exit != null || self.OccupiesSpace == null || !producee.HasTraitInfo <IOccupySpaceInfo>()) { DoProduction(self, producee, exit == null ? null : exit.Info, productionType, inits, OnSpawnCallback); return(true); } return(false); }
public virtual void DoProduction(Actor self, ActorInfo producee, ExitInfo exitinfo, string productionType, TypeDictionary inits, ManipulateActorCallback OnSpawnCallback) { var exit = CPos.Zero; var exitLocations = new List <CPos>(); // Clone the initializer dictionary for the new actor var td = new TypeDictionary(); foreach (var init in inits) { td.Add(init); } if (exitinfo != null && self.OccupiesSpace != null && producee.HasTraitInfo <IOccupySpaceInfo>()) { exit = self.Location + exitinfo.ExitCell; var spawn = self.CenterPosition + exitinfo.SpawnOffset; var to = self.World.Map.CenterOfCell(exit); var initialFacing = exitinfo.Facing; if (exitinfo.Facing < 0) { var delta = to - spawn; if (delta.HorizontalLengthSquared == 0) { var fi = producee.TraitInfoOrDefault <IFacingInfo>(); initialFacing = fi != null?fi.GetInitialFacing() : 0; } else { initialFacing = delta.Yaw.Facing; } } exitLocations = rp.Value != null && rp.Value.Path.Count > 0 ? rp.Value.Path : new List <CPos> { exit }; td.Add(new LocationInit(exit)); td.Add(new CenterPositionInit(spawn)); td.Add(new FacingInit(initialFacing)); if (exitinfo != null) { td.Add(new CreationActivityDelayInit(exitinfo.ExitDelay)); } } self.World.AddFrameEndTask(w => { var newUnit = self.World.CreateActor(producee.Name, td); OnSpawnCallback(newUnit); var move = newUnit.TraitOrDefault <IMove>(); if (exitinfo != null && move != null) { foreach (var cell in exitLocations) { newUnit.QueueActivity(new AttackMoveActivity(newUnit, () => move.MoveTo(cell, 1, evaluateNearestMovableCell: true, targetLineColor: Color.OrangeRed))); } } if (!self.IsDead) { foreach (var t in self.TraitsImplementing <INotifyProduction>()) { t.UnitProduced(self, newUnit, exit); } } var notifyOthers = self.World.ActorsWithTrait <INotifyOtherProduction>(); foreach (var notify in notifyOthers) { notify.Trait.UnitProducedByOther(notify.Actor, self, newUnit, productionType, td); } }); }