/// <summary>
        /// Update <see cref="CompAwesomeInventoryLoadout.InventoryMargins"/> whenever a new loadout is assigned to pawn.
        /// </summary>
        /// <param name="newLoadout"> The new loadout assigned to pawn. </param>
        public void UpdateForNewLoadout(AwesomeInventoryLoadout newLoadout)
        {
            if (newLoadout == null || this.Loadout == newLoadout)
            {
                return;
            }

            if (this.InventoryMargins == null)
            {
                this.InventoryMargins = new Dictionary <ThingGroupSelector, int>();
            }
            else
            {
                this.InventoryMargins.Clear();
            }

            this.Loadout?.RemoveAddNewThingGroupSelectorCallback(this.AddNewThingGroupSelectorCallback);
            this.Loadout?.RemoveRemoveThingGroupSelectorCallback(this.RemoveThingGroupSelectorCallback);
            this.Loadout?.RemoveStackCountChangedCallback(this.StackCountChangedCallback);

            this.UpdateInventoryMargin(newLoadout);

            newLoadout.AddAddNewThingGroupSelectorCallback(this.AddNewThingGroupSelectorCallback);
            newLoadout.AddRemoveThingGroupSelectorCallback(this.RemoveThingGroupSelectorCallback);
            newLoadout.AddStackCountChangedCallback(this.StackCountChangedCallback);

            Loadout      = newLoadout;
            _initialized = true;
        }
示例#2
0
        /// <summary>
        /// Add loadout to manager and the game's outfit database.
        /// </summary>
        /// <param name="loadout"> Loadout to add. </param>
        public static void AddLoadout(AwesomeInventoryLoadout loadout)
        {
            ValidateArg.NotNull(loadout, nameof(loadout));

            _loadouts.Add(loadout);
            Current.Game.outfitDatabase.AllOutfits.Add(loadout);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="AwesomeInventoryLoadout"/> class.
        /// </summary>
        /// <param name="pawn"> Initialize <see cref="AwesomeInventoryLoadout"/> with items on this <paramref name="pawn"/>. </param>
        public AwesomeInventoryLoadout(Pawn pawn)
        {
            ValidateArg.NotNull(pawn, nameof(pawn));

            this.AddItems(pawn.equipment?.AllEquipmentListForReading);
            this.AddItems(pawn.apparel?.WornApparel);
            this.AddItems(pawn.inventory?.innerContainer);

            if (pawn.outfits?.CurrentOutfit?.filter is ThingFilter filter)
            {
                this.filter.CopyAllowancesFrom(filter);
            }
            else
            {
                this.filter.SetAllow(ThingCategoryDefOf.Apparel, true);
            }

            this.uniqueId = Current.Game.outfitDatabase.AllOutfits.Max(o => o.uniqueId) + 1;
            CompAwesomeInventoryLoadout compLoadout = pawn.TryGetComp <CompAwesomeInventoryLoadout>();

            this.label = compLoadout?.Loadout == null
                ? AwesomeInventoryLoadout.GetDefaultLoadoutName(pawn)
                : LoadoutManager.GetIncrementalLabel(compLoadout.Loadout.label);

            pawn.SetLoadout(this);
        }
示例#4
0
        /// <summary>
        /// Set Pawn's loadout. Called by a harmony patch, Pawn_OutfitTracker_CurrentOutfit.
        /// </summary>
        /// <param name="pawn"> Set loadout on this <paramref name="pawn"/>. </param>
        /// <param name="loadout"> Loadout to assign to <paramref name="pawn"/>. </param>
        /// <param name="delay"> If true, put jobs for changing apparel in job queue, otherwise, execute jobs immediately. </param>
        /// <param name="forced"> If true, update pawn's comp for <paramref name="loadout"/> even though it is the same as current loadout. </param>
        public static void SetLoadout(this Pawn pawn, AwesomeInventoryLoadout loadout, bool delay = false, bool forced = false)
        {
            if (pawn.TryGetComp <CompAwesomeInventoryLoadout>() is CompAwesomeInventoryLoadout comp)
            {
                if (comp.Loadout == loadout && !forced)
                {
                    return;
                }

                ApparelOptionUtility.StopDressingJobs(pawn);
                comp.UpdateForNewLoadout(loadout, delay, forced: forced);

                if (loadout == pawn.outfits.CurrentOutfit)
                {
                    return;
                }

                pawn.outfits.CurrentOutfit = loadout;

                if (!comp.HotSwapCostume?.InSameLoadoutTree(loadout) ?? true)
                {
                    comp.HotSwapCostume       = null;
                    comp.LoadoutBeforeHotSwap = null;
                    comp.HotswapState         = CompAwesomeInventoryLoadout.HotSwapState.Inactive;
                }
            }
        }
        /// <summary>
        /// Remove outfit from <see cref="LoadoutManager"/>.
        /// </summary>
        /// <param name="loadout"> Loadout to remove. </param>
        /// <param name="fromOutfit"> If ture, this method is called from <see cref="OutfitDatabase.TryDelete(Outfit)"/>. </param>
        /// <returns> Returns true if loadout is rmeoved successfully. </returns>
        public static bool TryRemoveLoadout(AwesomeInventoryLoadout loadout, bool fromOutfit = false)
        {
            ValidateArg.NotNull(loadout, nameof(loadout));

            List <Pawn> pawns = PawnsFinder.AllMapsCaravansAndTravelingTransportPods_Alive_Colonists;
            List <AwesomeInventoryLoadout> loadouts = loadout.Costumes.Concat(loadout).ToList();

            foreach (AwesomeInventoryLoadout l in loadouts)
            {
                foreach (Pawn pawn in pawns)
                {
                    if (pawn.outfits?.CurrentOutfit == l)
                    {
                        Messages.Message("OutfitInUse".Translate(pawn), MessageTypeDefOf.RejectInput, false);
                        return(false);
                    }
                }
            }

            foreach (AwesomeInventoryLoadout l in loadouts)
            {
                _loadouts.Remove(l);
                Current.Game.outfitDatabase.AllOutfits.Remove(l);

                if (l is AwesomeInventoryCostume costume)
                {
                    RemoveHotSwapCostume(costume);
                }
            }

            return(true);
        }
示例#6
0
 /// <summary>
 /// Check if <paramref name="loadout"/> is in the same family tree of this costume.
 /// </summary>
 /// <param name="loadout"> loadout to check. </param>
 /// <returns> Returns true if <paramref name="loadout"/> is the parent or sibling of this costume. </returns>
 public virtual bool InSameLoadoutTree(AwesomeInventoryLoadout loadout)
 {
     return(this.CostumeOf(loadout) ||
            (loadout is AwesomeInventoryCostume costume
             &&
             this.SibilingOf(costume)));
 }
示例#7
0
        /// <summary>
        /// Initializes a new instance of the <see cref="AwesomeInventoryCostume"/> class.
        /// </summary>
        /// <param name="loadout"> The loadout this costume creates from. </param>
        public AwesomeInventoryCostume(AwesomeInventoryLoadout loadout)
            : base(loadout, true)
        {
            ValidateArg.NotNull(loadout, nameof(loadout));

            this.label = string.Concat(loadout.label, UIText.Costume.TranslateSimple());
            this.Base  = loadout;
        }
 /// <summary>
 /// Handle callback from <see cref="OutfitDatabase.TryDelete(Outfit)"/>.
 /// </summary>
 /// <param name="loadout"> Loadout to delete. </param>
 public static void TryRemoveLoadoutCallback(AwesomeInventoryLoadout loadout)
 {
     _loadouts.Remove(loadout);
     if (loadout?.GetType() == typeof(AwesomeInventoryLoadout))
     {
         foreach (AwesomeInventoryCostume costume in loadout.Costumes)
         {
             _loadouts.Remove(costume);
             Current.Game.outfitDatabase.AllOutfits.Remove(costume);
         }
     }
 }
        /// <summary>
        /// Initializes a new instance of the <see cref="AwesomeInventoryLoadout"/> class.
        /// </summary>
        /// <param name="other"> Copy <paramref name="other"/> to this loadout. </param>
        public AwesomeInventoryLoadout(AwesomeInventoryLoadout other)
        {
            ValidateArg.NotNull(other, nameof(other));

            foreach (ThingGroupSelector selector in other._thingGroupSelectors)
            {
                ThingGroupSelector newSelector = new ThingGroupSelector(selector);
                this.Add(newSelector);
            }

            this.uniqueId = Current.Game.outfitDatabase.AllOutfits.Max(o => o.uniqueId) + 1;
            this.label    = LoadoutManager.GetIncrementalLabel(other.label);
        }
示例#10
0
        /// <summary>
        /// Save states of this costume to xml.
        /// </summary>
        public override void ExposeData()
        {
            AwesomeInventoryLoadout b = this.Base;

            Scribe_Collections.Look(ref _costumeItems, nameof(_costumeItems), LookMode.Reference);
            Scribe_References.Look(ref b, nameof(this.Base));

            this.Base = b;
            if (Scribe.mode == LoadSaveMode.PostLoadInit)
            {
                _thingGroupSelectors = this.Base.ThingGroupSelectors;
                _thingGroupSelectors.ForEach(g => this.Add(g, true));
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="AwesomeInventoryLoadout"/> class.
        /// </summary>
        /// <param name="pawn"> Initialize <see cref="AwesomeInventoryLoadout"/> with items on this <paramref name="pawn"/>. </param>
        public AwesomeInventoryLoadout(Pawn pawn)
        {
            ValidateArg.NotNull(pawn, nameof(pawn));

            this.AddItems(pawn.equipment?.AllEquipmentListForReading);
            this.AddItems(pawn.apparel?.WornApparel);
            this.AddItems(pawn.inventory?.innerContainer);

            this.uniqueId = Current.Game.outfitDatabase.AllOutfits.Max(o => o.uniqueId) + 1;
            CompAwesomeInventoryLoadout compLoadout = pawn.TryGetComp <CompAwesomeInventoryLoadout>();

            this.label = compLoadout?.Loadout == null
                ? AwesomeInventoryLoadout.GetDefaultLoadoutName(pawn)
                : LoadoutManager.GetIncrementalLabel(compLoadout.Loadout.label);

            pawn.SetLoadout(this);
        }
        /// <summary>
        /// Set Pawn's loadout. Called by a harmony patch, Pawn_OutfitTracker_CurrentOutfit.
        /// </summary>
        /// <param name="pawn"> Set loadout on this <paramref name="pawn"/>. </param>
        /// <param name="loadout"> Loadout to assign to <paramref name="pawn"/>. </param>
        public static void SetLoadout(this Pawn pawn, AwesomeInventoryLoadout loadout)
        {
            if (pawn.TryGetComp <CompAwesomeInventoryLoadout>() is CompAwesomeInventoryLoadout comp)
            {
                if (comp.Loadout == loadout)
                {
                    return;
                }

                comp.UpdateForNewLoadout(loadout);
                if (loadout == pawn.outfits.CurrentOutfit)
                {
                    return;
                }

                pawn.outfits.CurrentOutfit = loadout;
            }
        }
示例#13
0
        /// <summary>
        /// Remove outfit from <see cref="LoadoutManager"/>.
        /// </summary>
        /// <param name="loadout"> Loadout to remove. </param>
        /// <param name="fromOutfit"> If ture, this method is called from <see cref="OutfitDatabase.TryDelete(Outfit)"/>. </param>
        /// <returns> Returns true if loadout is rmeoved successfully. </returns>
        public static bool TryRemoveLoadout(AwesomeInventoryLoadout loadout, bool fromOutfit = false)
        {
            if (fromOutfit)
            {
                _loadouts.Remove(loadout);
                return(true);
            }
            else
            {
                AcceptanceReport report = Current.Game.outfitDatabase.TryDelete(loadout);
                if (report.Accepted)
                {
                    return(true);
                }

                Messages.Message(report.Reason, MessageTypeDefOf.RejectInput, historical: false);
                return(false);
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="AwesomeInventoryLoadout"/> class.
        /// </summary>
        /// <param name="other"> Copy <paramref name="other"/> to this loadout. </param>
        /// <param name="shallow"> Make a shallow copy for costume. </param>
        public AwesomeInventoryLoadout(AwesomeInventoryLoadout other, bool shallow = false)
        {
            ValidateArg.NotNull(other, nameof(other));

            this.uniqueId = Current.Game.outfitDatabase.AllOutfits.Max(o => o.uniqueId) + 1;
            this.label    = LoadoutManager.GetIncrementalLabel(other.label);

            if (shallow)
            {
                _thingGroupSelectors = other._thingGroupSelectors;
                _blacklistSelectors  = other._blacklistSelectors;
                this.filter          = other.filter;
                _isDirty             = true;
                foreach (ThingGroupSelector selector in _thingGroupSelectors)
                {
                    this.AddAddNewThingSelectorCallbackTo(selector);
                    this.AddRemoveThingSelectorCallbackTo(selector);
                    this.AddStackCountChangedCallbackTo(selector);
                }
            }
            else
            {
                foreach (ThingGroupSelector selector in other._thingGroupSelectors)
                {
                    ThingGroupSelector newSelector = new ThingGroupSelector(selector);
                    this.Add(newSelector);
                }

                foreach (ThingGroupSelector selector in other._blacklistSelectors)
                {
                    ThingGroupSelector newSelector = new ThingGroupSelector(selector);
                    this.AddToBlacklist(newSelector);
                }

                this.filter.CopyAllowancesFrom(other.filter);

                this.CopyCostumeFrom(other);
            }
        }
        /// <summary>
        /// Change getup when switch loadout.
        /// </summary>
        /// <param name="newLoadout"> New loadout pawn switch to. </param>
        protected void ChangeCostume(AwesomeInventoryLoadout newLoadout)
        {
            ValidateArg.NotNull(newLoadout, nameof(newLoadout));

            if (newLoadout is AwesomeInventoryCostume costume)
            {
                ConcurrentBag <Apparel> wornApparels = new ConcurrentBag <Apparel>();
                Parallel.ForEach(
                    Partitioner.Create(_pawn.apparel.WornApparel)
                    , (Apparel apparel) =>
                {
                    if (!costume.CostumeItems.Any(c => c.Allows(apparel, out _)))
                    {
                        wornApparels.Add(apparel);
                    }
                });
                if (wornApparels.Any())
                {
                    _pawn.jobs.StopAll(true);
                    foreach (Apparel apparel in wornApparels)
                    {
                        Job job = JobMaker.MakeJob(AwesomeInventory_JobDefOf.AwesomeInventory_Undress, apparel);
                        if (_pawn.CurJob == null)
                        {
                            _pawn.jobs.StartJob(job);
                        }
                        else
                        {
                            _pawn.jobs.jobQueue.EnqueueLast(job);
                        }
                    }
                }

                if (costume.CostumeItems.Any())
                {
                    ConcurrentBag <Thing> things = new ConcurrentBag <Thing>();
                    Parallel.ForEach(
                        Partitioner.Create(costume.CostumeItems)
                        , (ThingGroupSelector selector) =>
                    {
                        Thing thing = _pawn.inventory.innerContainer.FirstOrDefault(t => selector.Allows(t, out _));
                        if (thing != null)
                        {
                            things.Add(thing);
                        }
                    });

                    if (things.Any())
                    {
                        if (_pawn.jobs.curJob.def != AwesomeInventory_JobDefOf.AwesomeInventory_Undress)
                        {
                            _pawn.jobs.StopAll(true);
                        }

                        foreach (Thing thing in things.Distinct())
                        {
                            if (thing.def.IsApparel)
                            {
                                Job job = new DressJob(AwesomeInventory_JobDefOf.AwesomeInventory_Dress, thing, false);
                                if (_pawn.CurJob == null)
                                {
                                    _pawn.jobs.StartJob(job);
                                }
                                else
                                {
                                    _pawn.jobs.jobQueue.EnqueueLast(job);
                                }
                            }
                            else if (thing.def.IsWeapon)
                            {
                                Job job = JobMaker.MakeJob(AwesomeInventory_JobDefOf.AwesomeInventory_MapEquip, thing);
                                if (_pawn.CurJob == null)
                                {
                                    _pawn.jobs.StartJob(job);
                                }
                                else
                                {
                                    _pawn.jobs.jobQueue.EnqueueLast(job);
                                }
                            }
                        }
                    }
                }
            }
        }
示例#16
0
        /// <summary>
        /// Check if this costume is derived from <paramref name="loadout"/>.
        /// </summary>
        /// <param name="loadout"> Loadout used for query. </param>
        /// <returns> Returns true if this costume is derived from <paramref name="loadout"/>. </returns>
        public virtual bool CostumeOf(AwesomeInventoryLoadout loadout)
        {
            ValidateArg.NotNull(loadout, nameof(loadout));

            return(loadout.Costumes.Contains(this));
        }