protected override void OnFirstRun(Actor self) { var aircraft = self.Trait <Aircraft>(); var host = aircraft.GetActorBelow(); if (host == null) { return; } if (aircraft.IsPlane) { ChildActivity = ActivityUtils.SequenceActivities( aircraft.GetResupplyActivities(host) .Append(new AllowYieldingReservation(self)) .Append(new WaitFor(() => NextInQueue != null || aircraft.ReservedActor == null)) .ToArray()); } else { // Helicopters should take off from their helipad immediately after resupplying. // HACK: Append NextInQueue to TakeOff to avoid moving to the Rallypoint (if NextInQueue is non-null). ChildActivity = ActivityUtils.SequenceActivities( aircraft.GetResupplyActivities(host) .Append(new AllowYieldingReservation(self)) .Append(new TakeOff(self)).Append(NextInQueue).ToArray()); } }
public override Activity Tick(Actor self) { if (cargo.IsDead || !carryall.IsBusy) { carryall.UnreserveCarryable(); return(NextActivity); } switch (state) { case State.Intercept: state = State.LockCarryable; return(ActivityUtils.SequenceActivities(movement.MoveWithinRange(Target.FromActor(cargo), WDist.FromCells(4)), this)); case State.LockCarryable: // Last check if (carryable.StandbyForPickup(self)) { state = State.MoveToCarryable; return(this); } // We got cancelled carryall.UnreserveCarryable(); return(NextActivity); case State.MoveToCarryable: // We arrived, move on top if (self.Location == cargo.Location) { state = State.Turn; return(this); } return(ActivityUtils.SequenceActivities(movement.MoveTo(cargo.Location, 0), this)); case State.Turn: // Align facing and Land if (selfFacing.Facing != cargoFacing.Facing) { return(ActivityUtils.SequenceActivities(new Turn(self, cargoFacing.Facing), this)); } state = State.Pickup; return(ActivityUtils.SequenceActivities(new HeliLand(self, false), new Wait(10), this)); case State.Pickup: // Remove our carryable from world self.World.AddFrameEndTask(w => cargo.World.Remove(cargo)); carryall.AttachCarryable(cargo); state = State.TakeOff; return(this); case State.TakeOff: if (HeliFly.AdjustAltitude(self, aircraft, aircraft.Info.CruiseAltitude)) { return(this); } return(NextActivity); } return(NextActivity); }
public void ResolveOrder(Actor self, Order order) { if (order.OrderString == "Repair") { // Repair orders are only valid for own/allied actors, // which are guaranteed to never be frozen. if (order.Target.Type != TargetType.Actor) { return; } if (!CanRepairAt(order.Target.Actor) || (!CanRepair() && !CanRearm())) { return; } if (!order.Queued) { self.CancelActivity(); } self.SetTargetLine(order.Target, Color.Green); self.QueueActivity(new WaitForTransport(self, ActivityUtils.SequenceActivities(new MoveAdjacentTo(self, order.Target), new CallFunc(() => AfterReachActivities(self, order, movement))))); TryCallTransport(self, order.Target, new CallFunc(() => AfterReachActivities(self, order, movement))); } }
public Activity VisualMove(Actor self, WPos fromPos, WPos toPos) { // TODO: Ignore repulsion when moving return(ActivityUtils.SequenceActivities(self, new CallFunc(() => SetVisualPosition(self, fromPos)), new Fly(self, Target.FromPos(toPos)))); }
Activity TryDeployTick(Actor self, out MiningState state) { // Wait for child wait activity to be done. // Could be wait or could be move to. if (ChildActivity != null) { ChildActivity = ActivityUtils.RunActivity(self, ChildActivity); state = MiningState.TryDeploy; return(this); } if (!deploy.IsValidTerrain(self.Location)) { // If we can't deploy, go back to scan state so that we scan try deploy again. state = MiningState.Scan; return(this); } // Issue deploy order and enter deploying state. //if (deploy. == DeployState.Undeployed) //{ IsInterruptible = false; tranforms.DeployTransform(true); //} state = MiningState.Deploying; return(this); }
public override Activity Tick(Actor self) { // Refuse to take off if it would land immediately again. if (plane.ForceLanding) { Cancel(self); return(NextActivity); } if (IsCanceled || !target.IsValidFor(self)) { return(NextActivity); } if (target.IsInRange(self.CenterPosition, minRange)) { var directVector = target.CenterPosition - self.CenterPosition; Fly.FlyToward(self, plane, (directVector.Yaw + WAngle.FromDegrees(180)).Facing, plane.Info.CruiseAltitude); return(this); } if (target.IsInRange(self.CenterPosition, maxRange)) { Fly.FlyToward(self, plane, plane.Facing, plane.Info.CruiseAltitude); return(this); } return(ActivityUtils.SequenceActivities(new Fly(self, target, minRange, maxRange), this)); }
public override Activity Tick(Actor self) { if (IsCanceled) { return(CanceledTick(self)); } // Check target validity if not exiting or done if (nextState != EnterState.Done && (target.Type != TargetType.Actor || !target.IsValidFor(self))) { AbortOrExit(self); } // If no current activity, tick next activity if (inner == null && FindAndTransitionToNextState(self) == EnterState.Done) { return(CanceledTick(self)); } // Run inner activity/InsideTick inner = inner == this ? InsideTick(self) : ActivityUtils.RunActivity(self, inner); // If we are finished, move on to next activity if (inner == null && nextState == EnterState.Done) { return(NextActivity); } return(this); }
public override Activity Tick(Actor self) { if (plane.ForceLanding) { return(NextActivity); } if (IsCanceled || self.IsDead) { return(NextActivity); } if (!isCalculated) { Calculate(self); } if (dest == null || dest.IsDead) { var nearestAfld = ChooseAirfield(self, false); if (nearestAfld != null) { return(ActivityUtils.SequenceActivities( new Fly(self, Target.FromActor(nearestAfld), WDist.Zero, plane.Info.WaitDistanceFromResupplyBase), new FlyCircle(self, plane.Info.NumberOfTicksToVerifyAvailableAirport), this)); } else { //Prevent a infinite loop in case we'd return to the activity that called ReturnToBase in the first place.Go idle instead Cancel(self); return(NextActivity); } } List <Activity> landingProcedures = new List <Activity>(); var turnRadius = CalculateTurnRadius(planeInfo.Speed); landingProcedures.Add(new Fly(self, Target.FromPos(w1), WDist.Zero, new WDist(turnRadius * 3))); landingProcedures.Add(new Fly(self, Target.FromPos(w2))); landingProcedures.Add(new Fly(self, Target.FromPos(w3), WDist.Zero, new WDist(turnRadius / 2))); if (ShouldLandAtBuilding(self, dest)) { plane.MakeReservation(dest); landingProcedures.Add(new Land(self, Target.FromActor(dest))); landingProcedures.Add(new ResupplyAircraft(self)); } if (!abortOnResupply) { landingProcedures.Add(NextActivity); } return(ActivityUtils.SequenceActivities(landingProcedures.ToArray())); }
public override Activity Tick(Actor self) { if (IsCanceled) { return(NextActivity); } if (dest == null || dest.IsDead || Reservable.IsReserved(dest)) { dest = ChooseHelipad(self, true); } var initialFacing = heli.Info.InitialFacing; if (dest == null || dest.IsDead) { var nearestHpad = ChooseHelipad(self, false); if (nearestHpad == null) { return(ActivityUtils.SequenceActivities(new Turn(self, initialFacing), new HeliLand(self, true), NextActivity)); } else { var distanceFromHelipad = (nearestHpad.CenterPosition - self.CenterPosition).HorizontalLength; var distanceLength = heli.Info.WaitDistanceFromResupplyBase.Length; // If no pad is available, move near one and wait if (distanceFromHelipad > distanceLength) { var randomPosition = WVec.FromPDF(self.World.SharedRandom, 2) * distanceLength / 1024; var target = Target.FromPos(nearestHpad.CenterPosition + randomPosition); return(ActivityUtils.SequenceActivities(new HeliFly(self, target, WDist.Zero, heli.Info.WaitDistanceFromResupplyBase), this)); } return(this); } } var exit = dest.Info.TraitInfos <ExitInfo>().FirstOrDefault(); var offset = (exit != null) ? exit.SpawnOffset : WVec.Zero; if (ShouldLandAtBuilding(self, dest)) { heli.MakeReservation(dest); return(ActivityUtils.SequenceActivities( new HeliFly(self, Target.FromPos(dest.CenterPosition + offset)), new Turn(self, initialFacing), new HeliLand(self, false), new ResupplyAircraft(self), !abortOnResupply ? NextActivity : null)); } return(ActivityUtils.SequenceActivities( new HeliFly(self, Target.FromPos(dest.CenterPosition + offset)), NextActivity)); }
public void Tick() { var wasIdle = IsIdle; CurrentActivity = ActivityUtils.RunActivity(this, CurrentActivity); if (!wasIdle && IsIdle) { foreach (var n in becomingIdles) { n.OnBecomingIdle(this); } // If IsIdle is true, it means the last CurrentActivity.Tick returned null. // If a next activity has been queued via OnBecomingIdle, we need to start running it now, // to avoid an 'empty' null tick where the actor will (visibly, if moving) do nothing. CurrentActivity = ActivityUtils.RunActivity(this, CurrentActivity); } else if (wasIdle) { foreach (var tickIdle in tickIdles) { tickIdle.TickIdle(this); } } }
public override Activity Tick(Actor self) { if (ChildActivity != null) { ChildActivity = ActivityUtils.RunActivityTick(self, ChildActivity); if (ChildActivity != null) { return(this); } } if (IsCanceling) { return(NextActivity); } var target = targets.ClosestTo(self); if (target == null) { return(this); } QueueChild(self, new AttackMoveActivity(self, () => move.MoveTo(target.Location, 2)), true); QueueChild(self, new Wait(25)); return(this); }
public override Activity Tick(Actor self) { if (ChildActivity != null) { ChildActivity = ActivityUtils.RunActivityTick(self, ChildActivity); if (ChildActivity != null) { return(this); } } if (IsCanceling || !attack.CanAttack(self, target)) { return(NextActivity); } if (attack.charges == 0) { return(this); } foreach (var notify in self.TraitsImplementing <INotifyTeslaCharging>()) { notify.Charging(self, target); } if (!string.IsNullOrEmpty(attack.info.ChargeAudio)) { Game.Sound.Play(SoundType.World, attack.info.ChargeAudio, self.CenterPosition); } QueueChild(self, new Wait(attack.info.InitialChargeDelay), true); QueueChild(self, new ChargeFire(attack, target)); return(this); }
public override Activity Tick(Actor self) { if (move == null || refuels == null || fueltank == null) { return(NextActivity); } self.SetTargetLine(target, Color.Green); var act = ActivityUtils.SequenceActivities( new MoveAdjacentTo(self, target), move.MoveTo(host.Location + refuels.Info.RefuelOffset, 0), new CallFunc(() => refuels.RefuelUnit(host, self)), new WaitFor(() => fueltank.IsFull, true)); var rp = host.TraitOrDefault <RallyPoint>(); if (rp != null) { act.Queue(new CallFunc(() => { self.SetTargetLine(Target.FromCell(self.World, rp.Location), Color.Green); self.QueueActivity(move.MoveTo(rp.Location, host)); })); } return(ActivityUtils.SequenceActivities(act, NextActivity)); }
public override Activity Tick(Actor self) { if (ChildActivity != null) { ChildActivity = ActivityUtils.RunActivityTick(self, ChildActivity); if (ChildActivity != null) { return(this); } } if (IsCanceling || !attack.CanAttack(self, target)) { return(NextActivity); } if (attack.charges == 0) { return(NextActivity); } attack.DoAttack(self, target); QueueChild(self, new Wait(attack.info.ChargeDelay), true); return(this); }
public override Activity Tick(Actor self) { // Do turn first, if needed. if (ChildActivity != null) { ChildActivity = ActivityUtils.RunActivityTick(self, ChildActivity); return(this); } // Without this, turn for facing deploy angle will be canceled and immediately deploy! if (IsCanceling) { return(NextActivity); } if (IsInterruptible) { IsInterruptible = false; // must DEPLOY from now. deploy.Deploy(); return(this); } // Wait for deployment if (deploy.DeployState == DeployState.Deploying) { return(this); } // Failed or success, we are going to NextActivity. // Deploy() at the first run would have put DeployState == Deploying so // if we are back to DeployState.Undeployed, it means deploy failure. // Parent activity will see the status and will take appropriate action. return(NextActivity); }
public static Activity GenericApproachDockActivities(Actor host, Actor client, Dock dock, Activity requester, bool goThroughHost = false) { var air = client.TraitOrDefault <Aircraft>(); if (air != null) { if (air.IsPlane) { // Let's reload. The assumption here is that for aircrafts, there are no waiting docks. System.Diagnostics.Debug.Assert(requester is ReturnToBase, "Wrong parameter for landing"); var rtb = requester as ReturnToBase; } var angle = dock.Info.DockAngle; if (angle < 0) { angle = client.Info.TraitInfo <AircraftInfo>().InitialFacing; } return(ActivityUtils.SequenceActivities( new HeliFly(client, Target.FromPos(dock.CenterPosition)), new Turn(client, angle), new HeliLand(client, false))); } if (goThroughHost) { return(client.Trait <IMove>().MoveTo(dock.Location, host)); } else { return(client.Trait <IMove>().MoveTo(dock.Location, 0)); } }
public override Activity Tick(Actor self) { cargo.Unloading = false; if (IsCanceled || cargo.IsEmpty(self)) { return(NextActivity); } foreach (var inu in notifiers) { inu.Unloading(self); } var actor = cargo.Peek(self); var spawn = self.CenterPosition; var exitSubCell = ChooseExitSubCell(actor); if (exitSubCell == null) { self.NotifyBlocker(BlockedExitCells(actor)); return(ActivityUtils.SequenceActivities(new Wait(10), this)); } cargo.Unload(self); self.World.AddFrameEndTask(w => { if (actor.Disposed) { return; } var move = actor.Trait <IMove>(); var pos = actor.Trait <IPositionable>(); var bunkerPassenger = actor.TraitOrDefault <BunkerPassenger>(); bunkerPassenger.RevokeCondition();//Disable the condition actor.CancelActivity(); pos.SetVisualPosition(actor, spawn); actor.QueueActivity(move.MoveIntoWorld(actor, exitSubCell.Value.First, exitSubCell.Value.Second)); actor.SetTargetLine(Target.FromCell(w, exitSubCell.Value.First, exitSubCell.Value.Second), Color.Green, false); if (cargo.Info.WillDisappear) { w.Add(actor); } }); if (!unloadAll || cargo.IsEmpty(self)) { return(NextActivity); } cargo.Unloading = true; return(this); }
public override Activity Tick(Actor self) { if (ChildActivity != null) { ChildActivity = ActivityUtils.RunActivity(self, ChildActivity); if (ChildActivity != null) { return(this); } } if (IsCanceling || target.Type == TargetType.Invalid) { return(NextActivity); } if (mobile.IsTraitDisabled || mobile.IsTraitPaused) { return(this); } var currentPos = self.CenterPosition; var targetPos = target.Positions.PositionClosestTo(currentPos); // Give up if the target has moved too far if (targetMovementThreshold > WDist.Zero && (targetPos - targetStartPos).LengthSquared > targetMovementThreshold.LengthSquared) { return(NextActivity); } // Turn if required var delta = targetPos - currentPos; var facing = delta.HorizontalLengthSquared != 0 ? delta.Yaw.Facing : mobile.Facing; if (facing != mobile.Facing) { var turn = ActivityUtils.RunActivity(self, new Turn(self, facing)); if (turn != null) { QueueChild(self, turn); } return(this); } // Can complete the move in this step var speed = mobile.MovementSpeedForCell(self, self.Location); if (delta.LengthSquared <= speed * speed) { mobile.SetVisualPosition(self, targetPos); return(NextActivity); } // Move towards the target mobile.SetVisualPosition(self, currentPos + delta * speed / delta.Length); return(this); }
public override Activity Tick(Actor self) { if (NextActivity != null) { return(NextActivity); } // Find the nearest best refinery if not explicitly ordered to a specific refinery: if (harv.OwnerLinkedProc == null || !harv.OwnerLinkedProc.IsInWorld) { // Maybe we lost the owner-linked refinery: harv.OwnerLinkedProc = null; if (self.World.WorldTick - chosenTicks > NextChooseTime) { harv.ChooseNewProc(self, null); chosenTicks = self.World.WorldTick; } } else { harv.LinkProc(self, harv.OwnerLinkedProc); } if (harv.LinkedProc == null || !harv.LinkedProc.IsInWorld) { harv.ChooseNewProc(self, null); } // No refineries exist; check again after delay defined in Harvester. if (harv.LinkedProc == null) { return(ActivityUtils.SequenceActivities(new Wait(harv.Info.SearchForDeliveryBuildingDelay), this)); } var proc = harv.LinkedProc; var iao = proc.Trait <IAcceptResources>(); self.SetTargetLine(Target.FromActor(proc), Color.Green, false); if (self.Location != proc.Location + iao.DeliveryOffset) { var notify = self.TraitsImplementing <INotifyHarvesterAction>(); var next = new DeliverResources(self); foreach (var n in notify) { n.MovingToRefinery(self, proc.Location + iao.DeliveryOffset, next); } return(ActivityUtils.SequenceActivities(movement.MoveTo(proc.Location + iao.DeliveryOffset, 0), this)); } if (!isDocking) { isDocking = true; iao.OnDock(self, this); } return(ActivityUtils.SequenceActivities(new Wait(10), this)); }
public Activity MoveToTarget(Actor self, Target target) { if (!Info.CanHover) { return(new Fly(self, target, WDist.FromCells(3), WDist.FromCells(5))); } return(ActivityUtils.SequenceActivities(new HeliFly(self, target), new Turn(self, Info.InitialFacing))); }
/// <summary> /// Returns unique hash for the <paramref name="activity"/> instance. /// <seealso cref="ActivityUtils.GetActivityHash"/>. /// </summary> /// <param name="activity">Activity instance.</param> /// <param name="userConnection"><see cref="UserConnection"/> instance.</param> /// <returns>Unique hash for the <paramref name="activity"/> instance.</returns> protected virtual string GetActivityHash(Entity activity, UserConnection userConnection) { TimeZoneInfo currentTimeZone = userConnection.CurrentUser.TimeZone; return(ActivityUtils.GetActivityHash(activity.GetTypedColumnValue <string>("Title"), string.Empty, activity.GetTypedColumnValue <DateTime>("StartDate").Date, activity.GetTypedColumnValue <DateTime>("DueDate").Date, activity.GetTypedColumnValue <Guid>("PriorityId"), activity.GetTypedColumnValue <Guid>("StatusId").ToString(), currentTimeZone)); }
public override Activity Tick(Actor self) { var targetIsValid = Target.IsValidFor(self); if (Target.Type == TargetT.Actor && canHideUnderFog && !Target.Actor.CanBeViewedByPlayer(self.Owner)) { if (inner != null) { inner.Cancel(self); } self.SetTargetLine(Target.FromCell(self.World, targetPosition), Color.Green); return(ActivityUtils.RunActivity(self, new AttackMoveActivity(self, Mobile.MoveTo(targetPosition, 0)))); } //Inner move order has completed if (inner == null) { if (IsCanceled || !repath || !targetIsValid) { return(NextActivity); } //Target has moved,and MoveAdjacentTo is still valid. inner = Mobile.MoveTo(() => CalculatePathToTarget(self)); repath = false; } if (targetIsValid) { //Check if the target has moved var oldTargetPosition = targetPosition; targetPosition = self.World.Map.CellContaining(Target.CenterPosition); var shouldStop = ShouldStop(self, oldTargetPosition); if (shouldStop || (!repath && ShouldRepath(self, oldTargetPosition))) { //Finish moving into the next cell and then repath. if (inner != null) { inner.Cancel(self); } repath = !shouldStop; } } else { //Target became invalid.Move to its last known position. Target = Target.FromCell(self.World, targetPosition); } //Ticks the inner move activity to actually move the actor. inner = ActivityUtils.RunActivity(self, inner); return(this); }
public override Activity Tick(Actor self) { if (ChildActivity != null) { ChildActivity = ActivityUtils.RunActivityTick(self, ChildActivity); return(this); } if (IsCanceling) { return(NextActivity); } if (rearmableInfo != null && ammoPools.Any(p => p.Info.Name == info.AmmoPoolName && !p.HasAmmo())) { // Rearm (and possibly repair) at rearm building, then back out here to refill the minefield some more var rearmTarget = self.World.Actors.Where(a => self.Owner.Stances[a.Owner] == Stance.Ally && rearmableInfo.RearmActors.Contains(a.Info.Name)) .ClosestTo(self); if (rearmTarget == null) { return(NextActivity); } // Add a CloseEnough range of 512 to the Rearm/Repair activities in order to ensure that we're at the host actor QueueChild(self, new MoveAdjacentTo(self, Target.FromActor(rearmTarget)), true); QueueChild(self, movement.MoveTo(self.World.Map.CellContaining(rearmTarget.CenterPosition), rearmTarget)); QueueChild(self, new Resupply(self, rearmTarget, new WDist(512))); return(this); } if ((minefield == null || minefield.Contains(self.Location)) && ShouldLayMine(self, self.Location)) { LayMine(self); QueueChild(self, new Wait(20), true); // A little wait after placing each mine, for show return(this); } if (minefield != null && minefield.Length > 0) { // Don't get stuck forever here for (var n = 0; n < 20; n++) { var p = minefield.Random(self.World.SharedRandom); if (ShouldLayMine(self, p)) { QueueChild(self, movement.MoveTo(p, 0), true); return(this); } } } // TODO: Return somewhere likely to be safe (near rearm building) so we're not sitting out in the minefield. return(NextActivity); }
Activity CanceledTick(Actor self) { if (inner == null) { return(ActivityUtils.RunActivity(self, NextActivity)); } inner.Cancel(self); inner.Queue(NextActivity); return(ActivityUtils.RunActivity(self, inner)); }
/// <summary> /// Sets mailbox identifier in email draft. /// </summary> /// <param name="activity"><see cref="Activity"/> instance.</param> /// <param name="emailMessage"><see cref="EmailMessage"/> instance.</param> protected void SetMailboxInEMD(Entity activity, EmailMessage emailMessage) { var helper = ClassFactory.Get <EmailMessageHelper>( new ConstructorArgument("userConnection", UserConnection)); var headers = emailMessage.HeaderProperties.ToDictionary(pair => pair.Name, pair => pair.Value); var ticks = ActivityUtils.GetSendDateTicks(UserConnection, activity); headers["SendDateTicks"] = ticks.ToString(); helper.CreateEmailMessage(activity, Guid.Empty, headers, true); }
public Activity VisualMove(Actor self, WPos fromPos, WPos toPos, CPos cell) { var speed = MovementSpeedForCell(self, cell); var length = speed > 0 ? (toPos - fromPos).Length / speed : 0; var delta = toPos - fromPos; var facing = delta.HorizontalLengthSquared != 0 ? delta.Yaw.Facing : Facing; return(ActivityUtils.SequenceActivities(new Turn(self, facing), new Drag(self, fromPos, toPos, length))); }
public override Activity Tick(Actor self) { if (IsCanceled) { wsb.PlayCustomAnimationRepeating(self, wsb.Info.Sequence); playanim = true; if (externalCondition != null) { Game.Debug("revoke: " + token); externalCondition.TryRevokeCondition(self, dockactor, token); } return(NextActivity); } if (ChildActivity != null) { ActivityUtils.RunActivity(self, ChildActivity); return(this); } if (playanim) { playanim = false; QueueChild(self.Trait <IMove>().VisualMove(self, self.CenterPosition, _d.CenterPosition)); QueueChild(new CallFunc(() => { var facing = self.Trait <IFacing>(); if (dockactor != null && facing != null && lockfacing) { var desiredFacing = (dockactor.CenterPosition - self.CenterPosition).HorizontalLengthSquared != 0 ? (dockactor.CenterPosition - self.CenterPosition).Yaw.Facing : facing.Facing; facing.Facing = desiredFacing; } wsb.PlayCustomAnimationRepeating(self, info.PreySequence); Game.Debug("Manager: " + externalCondition); if (externalCondition != null) { token = externalCondition.GrantCondition(dockactor, self); } })); } if (self.Info.TraitInfo <AcolytePreyInfo>().LeechesResources&& --ticks <= 0) { Leech(self); ticks = self.Info.TraitInfo <AcolytePreyInfo>().leechinterval; } return(this); }
public override Activity Tick(Actor self) { if (move == null || refuelsNear == null) { return(NextActivity); } self.SetTargetLine(target, Color.Green); return(ActivityUtils.SequenceActivities(move.MoveWithinRange(target, refuelsNear.Info.Range), NextActivity)); }
public override Activity Tick(Actor self) { switch (dockingState) { case DockingState.Wait: return(this); case DockingState.Turn: dockingState = DockingState.Dock; if (IsDragRequired) { return(ActivityUtils.SequenceActivities(new Turn(self, DockAngle), new Drag(self, StartDrag, EndDrag, DragLength), this)); } return(ActivityUtils.SequenceActivities(new Turn(self, DockAngle), this)); case DockingState.Dock: if (Refinery.IsInWorld && !Refinery.IsDead) { foreach (var nd in Refinery.TraitsImplementing <INotifyDocking>()) { nd.Docked(Refinery, self); } } return(OnStateDock(self)); case DockingState.Loop: if (!Refinery.IsInWorld || Refinery.IsDead || Harv.TickUnload(self, Refinery)) { dockingState = DockingState.Undock; } return(this); case DockingState.Undock: return(OnStateUndock(self)); case DockingState.Complete: if (Refinery.IsInWorld && !Refinery.IsDead) { foreach (var nd in Refinery.TraitsImplementing <INotifyDocking>()) { nd.Undocked(Refinery, self); } } Harv.LastLinkedProc = Harv.LinkedProc; Harv.LinkProc(self, null); if (IsDragRequired) { return(ActivityUtils.SequenceActivities(new Drag(self, EndDrag, StartDrag, DragLength), NextActivity)); } return(NextActivity); } throw new InvalidOperationException("Invalid harvester dock state."); }
public override Activity Tick(Actor self) { cargo.Unloading = false; if (IsCanceled || cargo.IsEmpty(self)) { return(NextActivity); } foreach (var cloak in cloaks) { if (cloak.Info.UncloakOn.HasFlag(UncloakType.Unload)) { cloak.Uncloak(); } } var actor = cargo.Peek(self); var spawn = self.CenterPosition; var exitSubCell = ChooseExitSubCell(actor); if (exitSubCell == null) { self.NotifyBlocker(BlockedExitCells(actor)); return(ActivityUtils.SequenceActivities(new Wait(10), this)); } cargo.Unload(self); self.World.AddFrameEndTask(w => { if (actor.Disposed) { return; } var move = actor.Trait <IMove>(); var pos = actor.Trait <IPositionable>(); actor.CancelActivity(); pos.SetVisualPosition(actor, spawn); actor.QueueActivity(move.MoveIntoWorld(actor, exitSubCell.Value.First, exitSubCell.Value.Second)); actor.SetTargetLine(Target.FromCell(w, exitSubCell.Value.First, exitSubCell.Value.Second), Color.Green, false); w.Add(actor); }); if (!unloadAll || cargo.IsEmpty(self)) { return(NextActivity); } cargo.Unloading = true; return(this); }