Esempio n. 1
0
        private static Thing BestWaterInInventory(Pawn holder, WaterPreferability minWaterPref = WaterPreferability.SeaWater, WaterPreferability maxWaterPref = WaterPreferability.ClearWater, float minStackWaterAmount = 0.0f, bool allowDrug = false)
        {
            // 所持品から探すのに所持品オブジェクトなし
            if (holder?.inventory == null)
            {
                return(null);
            }

            foreach (var thing in holder.inventory.innerContainer)
            {
                // 所持品をひとつずつチェック
                var waterAmount        = thing.GetWaterAmount();
                var waterPreferability = thing.GetWaterPreferability();

                if (thing.CanGetWater() && // 飲み物として飲めるもの
                    thing.CanDrinkWaterNow() && // 現在飲める状態にある
                    !thing.def.IsIngestible && // 食べ物ではない
                    waterPreferability >= minWaterPref && waterPreferability <= maxWaterPref && // 品質が指定範囲内
                    (allowDrug || !thing.def.IsDrug) && // ドラッグ許可か、そもそもドラッグでない
                    waterAmount * thing.stackCount >= minStackWaterAmount)
                {
                    // 水の量の最低値指定を満たしている
                    return(thing);
                }
            }

            // 条件に合うものが1個も見つからなかった
            return(null);
        }
Esempio n. 2
0
        public static ThingDef GetWaterThingDefFromWaterPreferability(WaterPreferability waterPreferability)
        {
            // 水の種類→水アイテム
            switch (waterPreferability)
            {
            case WaterPreferability.ClearWater:
                return(MizuDef.Thing_ClearWater);

            case WaterPreferability.NormalWater:
                return(MizuDef.Thing_NormalWater);

            case WaterPreferability.RawWater:
                return(MizuDef.Thing_RawWater);

            case WaterPreferability.MudWater:
                return(MizuDef.Thing_MudWater);

            case WaterPreferability.SeaWater:
                return(MizuDef.Thing_SeaWater);

            default:
                return(null);
            }
        }
Esempio n. 3
0
        private static Thing BestWaterSourceOnMap(Pawn getter, Pawn eater, bool priorQuality, WaterPreferability maxPref = WaterPreferability.ClearWater, bool allowDrug = false, bool allowForbidden = false, bool allowSociallyImproper = false)
        {
            if (!getter.CanManipulate() && getter != eater)
            {
                // 取得者は操作不可、取得者と摂取者が違う
                // →マップから取得して持ち運ぶことができない
                // →エラー
                Log.Error(string.Concat(getter, " tried to find food to bring to ", eater, " but ", getter, " is incapable of Manipulation."));
                return(null);
            }

            bool waterValidator(Thing t)
            {
                // 禁止されている&禁止を無視して取得してはいけない
                if (!allowForbidden && t.IsForbidden(getter))
                {
                    return(false);
                }

                // ドラッグ禁止&対象はドラッグ
                if (!allowDrug && t.def.IsDrug)
                {
                    return(false);
                }

                // 取得者が予約できない
                if (!getter.CanReserve(t))
                {
                    return(false);
                }

                var comp = t.TryGetComp <CompWaterSource>();

                // 水源として使用できない
                if (comp == null || !comp.IsWaterSource)
                {
                    return(false);
                }

                // 食べられるものは飲み物としては選ばれない
                if (t.def.IsIngestible)
                {
                    return(false);
                }

                // 操作が必要なのに操作できない
                if (comp.NeedManipulate && !getter.CanManipulate())
                {
                    return(false);
                }

                var waterTypeDef = MizuDef.Dic_WaterTypeDef[comp.WaterType];

                if (comp.SourceType == CompProperties_WaterSource.SourceType.Item)
                {
                    // 水分がない
                    if (!t.CanGetWater())
                    {
                        return(false);
                    }

                    // 水分を持っている=水アイテムである
                    var waterPreferability = t.GetWaterPreferability();

                    // 水の品質が範囲外
                    if (waterPreferability < WaterPreferability.SeaWater || waterPreferability > maxPref)
                    {
                        return(false);
                    }

                    // 現在飲める状態には無い
                    if (!t.CanDrinkWaterNow())
                    {
                        return(false);
                    }

                    // 入植者は囚人部屋のアイテムを扱えないことがあるが、そのことに関するチェックでダメならfalse
                    if (!IsWaterSourceOnMapSociallyProper(t, getter, eater, allowSociallyImproper))
                    {
                        return(false);
                    }

                    // 取得者がそれに気づいていない
                    if (!getter.AnimalAwareOf(t))
                    {
                        return(false);
                    }

                    return(true);
                }

                if (comp.SourceType != CompProperties_WaterSource.SourceType.Building)
                {
                    return(false);
                }

                // 取得者と摂取者が異なる(自分で飲みに行く必要がある)
                if (getter != eater)
                {
                    return(false);
                }

                // 水汲みに使えない
                if (!(t is IBuilding_DrinkWater drinkWaterBuilding))
                {
                    return(false);
                }

                // 水を飲む人が飲めない(能力が無い、水の量がない)
                if (!drinkWaterBuilding.CanDrinkFor(eater))
                {
                    return(false);
                }

                // 最大水質を超えていたらダメ
                if (waterTypeDef.waterPreferability > maxPref)
                {
                    return(false);
                }

                // 野生人?(派閥所属なし?)はダメ
                if (eater.IsWildMan())
                {
                    return(false);
                }

                // 自陣営or自陣営のホストの設備でなければダメ
                // 動物でない場合は、という条件を追加
                if (!eater.RaceProps.Animal && t.Faction != eater.Faction && t.Faction != eater.HostFaction)
                {
                    return(false);
                }

                // 使えない状態はダメ
                if (!drinkWaterBuilding.IsActivated)
                {
                    return(false);
                }

                // 入植者は囚人部屋のアイテムを扱えないことがあるが、そのことに関するチェックでダメならfalse
                if (!IsWaterSourceOnMapSociallyProper(t, getter, eater, allowSociallyImproper))
                {
                    return(false);
                }

                if (t.def.hasInteractionCell)
                {
                    // 使用場所がある
                    if (!t.InteractionCell.Standable(t.Map) || !eater.Map.reachability.CanReachNonLocal(getter.Position, new TargetInfo(t.InteractionCell, t.Map), PathEndMode.OnCell, TraverseParms.For(getter, Danger.Some)))
                    {
                        // 使用場所に立てない or 使用場所まで行けない
                        return(false);
                    }
                }
                else
                {
                    // 使用場所が無い
                    if (!getter.Map.reachability.CanReachNonLocal(getter.Position, new TargetInfo(t.Position, t.Map), PathEndMode.ClosestTouch, TraverseParms.For(getter, Danger.Some)))
                    {
                        // その設備にタッチできない
                        return(false);
                    }
                }

                return(true);

                // それ以外
            }

            if (getter.RaceProps.Humanlike)
            {
                // 取得者はHumanlikeである
                // →条件を満たすものの中から最適な物を探す
                return(SpawnedWaterSearchInnerScan(
                           eater,
                           getter.Position,
                           getter.Map.listerThings.ThingsInGroup(ThingRequestGroup.Everything).FindAll(
                               t =>
                {
                    if (t.CanDrinkWaterNow())
                    {
                        return true;
                    }

                    if (t is IBuilding_DrinkWater building && building.CanDrinkFor(eater))
                    {
                        return true;
                    }

                    return false;
                }),
                           PathEndMode.ClosestTouch,
                           TraverseParms.For(getter),
                           priorQuality,
                           9999f,
                           waterValidator));
            }

            // 取得者はHumanlikeではない

            // プレイヤー派閥に所属しているかどうかでリージョン?数を変える
            var searchRegionsMax = 30;

            if (getter.Faction == Faction.OfPlayer)
            {
                searchRegionsMax = 100;
            }

            var filtered = new HashSet <Thing>();

            foreach (var current in GenRadial.RadialDistinctThingsAround(getter.Position, getter.Map, 2f, true))
            {
                // 自分を中心に半径2以内の物をチェック
                if (current is Pawn pawn && pawn != getter && pawn.RaceProps.Animal && pawn.CurJob != null && pawn.CurJob.def == MizuDef.Job_DrinkWater && pawn.CurJob.GetTarget(TargetIndex.A).HasThing)
                {
                    // 自分ではない動物が現在水アイテムを摂取している
                    // →今まさに摂取している物は探索対象から除外
                    filtered.Add(pawn.CurJob.GetTarget(TargetIndex.A).Thing);
                }
            }

            var ignoreEntirelyForbiddenRegions = !allowForbidden && // 禁止物のアクセスは許可されていない
                                                 ForbidUtility.CaresAboutForbidden(getter, true) && getter.playerSettings?.EffectiveAreaRestrictionInPawnCurrentMap != null;    // 有効な制限エリアなし

            bool predicate(Thing t)
            {
                // アイテムが条件を満たしていない
                if (!waterValidator(t))
                {
                    return(false);
                }

                // すぐ近くで他の動物が飲んでいる水のリストに入っていない
                if (filtered.Contains(t))
                {
                    return(false);
                }

                // 水の品質が最低値未満
                if (t.GetWaterPreferability() < WaterPreferability.SeaWater)
                {
                    return(false);
                }

                return(true);
            }

            // 指定の条件下でアクセスできるものを探す

            // 水アイテムから
            var thing = GenClosest.ClosestThingReachable(getter.Position, getter.Map, ThingRequest.ForGroup(ThingRequestGroup.HaulableEver), PathEndMode.ClosestTouch, TraverseParms.For(getter), 9999f, predicate, null, 0, searchRegionsMax, false, RegionType.Set_Passable, ignoreEntirelyForbiddenRegions);

            if (thing != null)
            {
                return(thing);
            }

            // 水汲み設備
            thing = GenClosest.ClosestThingReachable(getter.Position, getter.Map, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.ClosestTouch, TraverseParms.For(getter), 9999f, predicate, null, 0, searchRegionsMax, false, RegionType.Set_Passable, ignoreEntirelyForbiddenRegions);
            if (thing != null)
            {
                return(thing);
            }

            // 条件を変えて再探索
            // 水アイテム
            thing = GenClosest.ClosestThingReachable(
                getter.Position,
                getter.Map,
                ThingRequest.ForGroup(ThingRequestGroup.HaulableEver),
                PathEndMode.ClosestTouch,
                TraverseParms.For(getter),
                9999f,
                waterValidator, // ここが変わった
                null,
                0,
                searchRegionsMax,
                false,
                RegionType.Set_Passable,
                ignoreEntirelyForbiddenRegions);
            if (thing != null)
            {
                return(thing);
            }

            // 水汲み設備
            thing = GenClosest.ClosestThingReachable(
                getter.Position,
                getter.Map,
                ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial),
                PathEndMode.ClosestTouch,
                TraverseParms.For(getter),
                9999f,
                waterValidator, // ここが変わった
                null,
                0,
                searchRegionsMax,
                false,
                RegionType.Set_Passable,
                ignoreEntirelyForbiddenRegions);
            return(thing);
        }