/// <summary>
        /// Searches for fetchable pickups for the given chore.
        /// </summary>
        /// <param name="chore">The chore to complete.</param>
        /// <returns>The pickup to fetch, or null if none are currently available.</returns>
        internal Pickupable FindFetchTarget(FetchChore chore)
        {
            Pickupable bestMatch = null;
            var        destination = chore.destination;
            float      required = chore.originalAmount, target = required * thresholdFraction,
                       canGet = 0.0f;

            foreach (var pickup in fmPickups)
            {
                var pickupable = pickup.pickupable;
                // Is this item accessible?
                if (FetchManager.IsFetchablePickup(pickupable, ref chore.tagBits, ref chore.
                                                   requiredTagBits, ref chore.forbiddenTagBits, destination))
                {
                    float amount = pickupable.UnreservedAmount;
                    if (bestMatch == null)
                    {
                        // Indicate if anything can be found at all
                        bestMatch = pickupable;
                        canGet    = amount;
                    }
                    if (amount >= target)
                    {
                        // Already have the best one in our sights
                        bestMatch = pickupable;
                        canGet    = amount;
                        break;
                    }
                }
            }
            // Do not start a fetch entry if nothing is available
            if (bestMatch != null)
            {
                Tag itemType = bestMatch.PrefabID();
                if (outstanding.TryGetValue(itemType, out FetchData current) && !current.
                    NeedsScan)
                {
                    // Retire it, with the best item we could do
                    outstanding.TryRemove(itemType, out _);
#if DEBUG
                    PUtil.LogDebug("{3} {0} ({2}) with {1:F2}".F(destination.name,
                                                                 canGet, itemType, (canGet >= target) ? "Complete" : "Retire"));
#endif
                }
                else if (canGet < target && outstanding.TryAdd(itemType, new FetchData(
                                                                   target)))
                {
                    // Start searching for a better option
#if DEBUG
                    PUtil.LogDebug("Find {0} ({3}): have {1:F2}, want {2:F2}".F(
                                       destination.name, canGet, target, itemType));
#endif
                    bestMatch = null;
                }
            }
            return(bestMatch);
        }
Example #2
0
            public static void Postfix(FetchManager __instance,
                                       Storage destination,
                                       ref TagBits tag_bits,
                                       ref TagBits required_tags,
                                       ref TagBits forbid_tags,
                                       float required_amount,
                                       ref Pickupable __result)
            {
                // only do this for the egg cracker
                if (!destination.ToString().Contains(__EGG_CRACKER_NAME))
                {
                    return;
                }
                List <FetchManager.Pickup> pickup_list = pickupListRef(__instance);

                List <Pickupable> egg_list = new List <Pickupable>();

                if (__DEBUG)
                {
                    Debug.Log(String.Format("Number of pickupbables available: {0}", pickup_list.Count));
                }

                // get a list of all the available eggs for this fetch order
                foreach (FetchManager.Pickup pickup in pickup_list)
                {
                    if (__DEBUG)
                    {
                        string debug_output = "Checking item on list:\n";

                        debug_output += "Position:\n";
                        UnityEngine.Vector3 pos = pickup.pickupable.GetTargetPoint();
                        debug_output += String.Format("X: {0}  Y: {1}  Z: {2}\n", pos.x, pos.y, pos.z);
                        debug_output += "\nTag bits:\n" + string.Join <Tag>(",", (IEnumerable <Tag>)tag_bits.GetTagsVerySlow());

                        // TODO: use below code taken from FetchManager.IsFetchablePickup() to log if each pickup is valid
                        // pickup_id.HasAnyTags_AssumeLaundered(ref tag_bits) && pickup_id.HasAllTags_AssumeLaundered(ref required_tags) && !pickup_id.HasAnyTags_AssumeLaundered(ref forbid_tags) && (!((Object)source != (Object)null) || (source.ignoreSourcePriority || !destination.ShouldOnlyTransferFromLowerPriority || !(destination.masterPriority <= source.masterPriority)) && (destination.storageNetworkID == -1 || destination.storageNetworkID != source.storageNetworkID));


                        debug_output += "------\n\n";

                        Debug.Log(debug_output);
                    }

                    if (FetchManager.IsFetchablePickup(pickup.pickupable, ref tag_bits, ref required_tags, ref forbid_tags, destination))
                    {
                        egg_list.Add(pickup.pickupable);
                    }
                }

                if (egg_list.Count == 0)
                {
                    __result = (Pickupable)null;
                }

                // sort the list of eggs by incubation in ascending order (lowest incubation first)
                int sort_egg_incubation(Pickupable x, Pickupable y)
                {
                    double x_incubation = Math.Round((x.gameObject.GetAmounts().Get(Db.Get().Amounts.Incubation)).value, 5);
                    double y_incubation = Math.Round((y.gameObject.GetAmounts().Get(Db.Get().Amounts.Incubation)).value, 5);

                    return(x_incubation.CompareTo(y_incubation));
                }

                // return the first egg in the list (least incubation)
                egg_list.Sort(sort_egg_incubation);

                if (__DEBUG)
                {
                    string debug_output = "Sorted list of eggs:\n";

                    foreach (Pickupable p in egg_list)
                    {
                        debug_output += "Position:\n";
                        UnityEngine.Vector3 pos = p.GetTargetPoint();
                        debug_output += String.Format("X: {0}  Y: {1}  Z: {2}\n", pos.x, pos.y, pos.z);

                        debug_output += String.Format("Incubation: {0}\n", Math.Round((p.gameObject.GetAmounts().Get(Db.Get().Amounts.Incubation)).value, 5));

                        debug_output += "------\n\n";
                    }

                    Debug.Log(debug_output);
                }

                __result = egg_list[0];
            }