コード例 #1
0
        public static void TransferWeaponsToCorrectInventory(List <Pawn> pawns)
        {
            if (!(pawns?.Count > 0))
            {
                return;
            }

            var missingWeaponsForPawn   = new Dictionary <Pawn, List <ThingDefStuffDefPair> >();
            var availableThings         = new List <ThingWithComps>();
            var availableBiocodedThings = new Dictionary <Pawn, List <ThingWithComps> >();

            foreach (var pawn in pawns)
            {
                var pawnThings = new List <ThingWithComps>();

                // add equipped weapon to list
                if (pawn.equipment?.Primary != null)
                {
                    pawnThings.Add(pawn.equipment.Primary);
                }

                // add all weapons in inventory to list
                var inventory = pawn.inventory?.innerContainer;
                if (inventory != null)
                {
                    // filter out all weapons in inventory
                    foreach (var thing in inventory)
                    {
                        if ((thing.def.IsMeleeWeapon || thing.def.IsRangedWeapon) &&
                            thing is ThingWithComps thingWithComps)
                        {
                            pawnThings.Add(thingWithComps);
                        }
                    }
                }

                // check if we are looking at a colonist with an inventory
                if (pawn?.IsColonist == true)
                {
                    var pawnWeapons = new List <ThingDefStuffDefPair>(CompSidearmMemory.GetMemoryCompForPawn(pawn)?.RememberedWeapons);

                    // first remove things biocoded to this pawn; no-one else can use them anyway
                    for (int i = 0; i < pawnThings.Count;)
                    {
                        var thing = pawnThings[i];

                        // check if thing is biocoded to this pawn
                        var biocode = thing.TryGetComp <CompBiocodable>();
                        if (biocode?.Biocoded == true)
                        {
                            if (biocode.CodedPawn == pawn)
                            {
                                // remove from remembered weapon list
                                var weaponMemory = thing.toThingDefStuffDefPair();
                                if (weaponMemory != null)
                                {
                                    pawnWeapons.Remove(weaponMemory);
                                }
                            }
                            else
                            {
                                // add biocoded thing to their own list
                                var codedPawn = biocode.CodedPawn;
                                if (!availableBiocodedThings.ContainsKey(codedPawn))
                                {
                                    availableBiocodedThings.Add(codedPawn, new List <ThingWithComps>());
                                }
                                availableBiocodedThings[codedPawn].Add(thing);
                            }

                            // remove from thing list
                            pawnThings.Remove(thing);
                            continue;
                        }
                        i++;
                    }

                    // then remove things that fit the remembered weapons found on the pawn
                    if (pawnWeapons.Count > 0)
                    {
                        for (int i = 0; i < pawnThings.Count;)
                        {
                            var thing = pawnThings[i];

                            // check if thing is remembered
                            var weaponMemory = thing.toThingDefStuffDefPair();
                            if (weaponMemory != null && pawnWeapons.Contains(weaponMemory))
                            {
                                // remove remembered weapon and the thing that fits it
                                pawnWeapons.Remove(weaponMemory);
                                pawnThings.Remove(thing);
                                continue;
                            }
                            i++;
                        }
                    }

                    // finally all weapons still in the pawn's remembered weapons list are missing; we will look for them on other pawns
                    if (pawnWeapons.Count > 0 && !missingWeaponsForPawn.ContainsKey(pawn))
                    {
                        missingWeaponsForPawn.Add(pawn, new List <ThingDefStuffDefPair>());
                    }
                    foreach (var weapon in pawnWeapons)
                    {
                        missingWeaponsForPawn[pawn].Add(weapon);
                    }
                }

                // all things in the pawn's thing list are not remembered weapons for this pawn; they can be used by other pawns
                foreach (var thing in pawnThings)
                {
                    availableThings.Add(thing);
                }
            }

            // sort by quality; this way we should give every pawn the best weapon, unless they got a biocoded one
            availableThings.SortByDescending((thing) =>
            {
                QualityUtility.TryGetQuality(thing, out QualityCategory qc);
                return((int)qc);
            });

            // transfer unassigned weapons to pawns missing sidearms
            foreach (var entry in missingWeaponsForPawn)
            {
                var pawn           = entry.Key;
                var missingWeapons = entry.Value;

                List <ThingWithComps> biocodedToThisPawn = null;
                if (availableBiocodedThings.ContainsKey(pawn))
                {
                    biocodedToThisPawn = availableBiocodedThings[pawn];
                }

                // iterate over every missing weapon
                for (int i = 0; i < missingWeapons.Count;)
                {
                    var weaponMemory = missingWeapons[i];

                    // check available biocoded weapons first
                    if (biocodedToThisPawn != null)
                    {
                        // iterate over biocoded items
                        for (int j = 0; biocodedToThisPawn.Count > j;)
                        {
                            // get ThingDefStuffDefPair for thing
                            var thing       = biocodedToThisPawn[j];
                            var thingMemory = thing.toThingDefStuffDefPair();

                            // check if thing fits weapon memory
                            if (weaponMemory.Equals(thingMemory))
                            {
                                //Log.Message($"Transferring '{thing}' from '{ThingOwnerUtility.GetAnyParent<Pawn>(thing)}' ({thing.ParentHolder}) to '{pawn}' [biocoded]");
                                // transfer weapon
                                if (thing.holdingOwner.TryTransferToContainer(thing, pawn.inventory.innerContainer, 1) == 1)
                                {
                                    // remove weapon from missing weapons list and thing from unassigned things list
                                    missingWeapons.Remove(weaponMemory);
                                    biocodedToThisPawn.Remove(thing);
                                    goto CONTINUE;
                                }

                                // if it gets here, tranferring the weapon failed; this should obviously not happen
                                Log.Error($"Failed to transfer '{thing}' from '{ThingOwnerUtility.GetAnyParent<Pawn>(thing)}' ({thing.ParentHolder}) to '{pawn}'! [biocoded]");
                            }
                            j++;
                        }
                    }

                    // for each missing weapon, we check all things to find it
                    for (int j = 0; j < availableThings.Count;)
                    {
                        // get ThingDefStuffDefPair for thing
                        var thing       = availableThings[j];
                        var thingMemory = thing.toThingDefStuffDefPair();

                        // all things in this list should have a ThingDefStuffDefPair, remove it if it does not
                        if (thingMemory == null)
                        {
                            Log.Warning($"'{thing}' had null ThingDefStuffDefPair; removing from unassigned things");
                            availableThings.Remove(thing);
                            continue;
                        }

                        // check if thing fits weapon memory
                        if (weaponMemory.Equals(thingMemory))
                        {
                            //Log.Message($"Transferring '{thing}' from '{ThingOwnerUtility.GetAnyParent<Pawn>(thing)}' ({thing.ParentHolder}) to '{pawn}' [standard]");
                            // transfer weapon
                            if (thing.holdingOwner.TryTransferToContainer(thing, pawn.inventory.innerContainer, 1) == 1)
                            {
                                // remove weapon from missing weapons list and thing from unassigned things list
                                missingWeapons.Remove(weaponMemory);
                                availableThings.Remove(thing);
                                goto CONTINUE;
                            }

                            // if it gets here, tranferring the weapon failed; this should obviously not happen
                            Log.Error($"Failed to transfer '{thing}' from '{ThingOwnerUtility.GetAnyParent<Pawn>(thing)}' ({thing.ParentHolder}) to '{pawn}'! [standard]");
                        }
                        j++;
                    }
                    i++;

                    // if missing weapon was found go here without increasing the index
                    CONTINUE :;
                }
            }
        }