#region Copyright & License Information /* * Copyright 2007-2015 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, * see COPYING. */ #endregion using System.Collections.Generic; using System.Drawing; using System.Linq; using OpenRA.Activities; using OpenRA.Mods.Common.Traits; using OpenRA.Primitives; using OpenRA.Traits; namespace OpenRA.Mods.Common.Activities { public class UnloadCargo : Activity { readonly Actor self; readonly Cargo cargo; readonly Cloak cloak; readonly bool unloadAll; public UnloadCargo(Actor self, bool unloadAll) { this.self = self; cargo = self.Trait(); cloak = self.TraitOrDefault(); this.unloadAll = unloadAll; } public Pair? ChooseExitSubCell(Actor passenger) { var pos = passenger.Trait(); return cargo.CurrentAdjacentCells .Shuffle(self.World.SharedRandom) .Select(c => Pair.New(c, pos.GetAvailableSubCell(c))) .Cast?>() .FirstOrDefault(s => s.Value.Second != SubCell.Invalid); } IEnumerable BlockedExitCells(Actor passenger) { var pos = passenger.Trait(); // Find the cells that are blocked by transient actors return cargo.CurrentAdjacentCells .Where(c => pos.CanEnterCell(c, null, true) != pos.CanEnterCell(c, null, false)); } public override Activity Tick(Actor self) { cargo.Unloading = false; if (IsCanceled || cargo.IsEmpty(self)) return NextActivity; if (cloak != null && cloak.Info.UncloakOnUnload) cloak.Uncloak(); var actor = cargo.Peek(self); var spawn = self.CenterPosition; var exitSubCell = ChooseExitSubCell(actor); if (exitSubCell == null) { self.NotifyBlocker(BlockedExitCells(actor)); return Util.SequenceActivities(new Wait(10), this); } cargo.Unload(self); self.World.AddFrameEndTask(w => { if (actor.Disposed) return; var move = actor.Trait(); var pos = actor.Trait(); 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; } } }