예제 #1
0
        static void Postfix(ref float y, float width, Thing thing, bool inventory = false)
        {
            // 所持品に含まれる水アイテムに、所持品を直接摂取するボタンを増やす
            // yは次の行のtop上端座標、widthは右端座標

            // db=DrinkButton
            const float dbWidth  = 24f;
            const float dbHeight = 24f;

            // 1アイコンにつき幅24f
            // 情報アイコン、ドロップアイコン、食べるアイコンを考慮すれば3個
            // 食べると飲むを分離できたはずなので2で良い
            float dbRight = width - 24f * 2;
            float dbTop   = y - 28f;

            Pawn   selPawn   = Find.Selector.SingleSelectedThing as Pawn;
            Corpse selCorpse = Find.Selector.SingleSelectedThing as Corpse;

            if (selPawn == null && selCorpse != null)
            {
                selPawn = selCorpse.InnerPawn;
            }

            // ポーンデータがないなら終了
            if (selPawn == null)
            {
                return;
            }

            // プレイヤーが操作するポーンではない、またはそのポーンは倒れている→終了
            if (!selPawn.IsColonistPlayerControlled || selPawn.Downed)
            {
                return;
            }

            // 水として飲めないアイテムなら終了
            if (!thing.CanGetWater() || !thing.CanDrinkWaterNow())
            {
                return;
            }

            // 水アイテムでなかったり、食べられるものは能動的に飲むことはできない
            var comp = thing.TryGetComp <CompWaterSource>();

            if (comp == null || comp.SourceType != CompProperties_WaterSource.SourceType.Item || thing.IsIngestibleFor(selPawn))
            {
                return;
            }

            // ツールチップとボタンを追加
            Rect dbRect = new Rect(dbRight - dbWidth, dbTop, dbWidth, dbHeight);

            TooltipHandler.TipRegion(dbRect, string.Format(MizuStrings.FloatMenuGetWater.Translate(), thing.LabelNoCount));
            if (Widgets.ButtonImage(dbRect, MizuGraphics.Texture_ButtonIngest))
            {
                SoundDefOf.Tick_High.PlayOneShotOnCamera(null);
                Job job = new Job(MizuDef.Job_DrinkWater, thing)
                {
                    count = MizuUtility.WillGetStackCountOf(selPawn, thing)
                };
                selPawn.jobs.TryTakeOrderedJob(job, JobTag.SatisfyingNeeds);
            }
        }
예제 #2
0
        public static float GetWater(Pawn getter, Thing thing, float waterWanted, bool withIngested)
        {
            // 摂取しようとしているものが既に消滅している(エラー)
            // 食事と同時に水分摂取する場合は既に消滅しているので無視する
            if (!withIngested && thing.Destroyed)
            {
                Log.Error(getter + " drank destroyed thing " + thing);
                return(0f);
            }

            // 現在飲めないはずのものを飲もうとしている(エラー)
            if (!thing.CanDrinkWaterNow())
            {
                Log.Error(getter + " drank CanDrinkWaterNow()=false thing " + thing);
                return(0f);
            }

            if (getter.needs.mood != null)
            {
                // 水分摂取による心情変化
                foreach (var thoughtDef in ThoughtsFromGettingWater(getter, thing))
                {
                    getter.needs.mood.thoughts.memories.TryGainMemory(thoughtDef);
                }
            }

            // 健康状態の変化
            var comp = thing.TryGetComp <CompWaterSource>();

            if (comp == null)
            {
                Log.Error("comp is null");
                return(0.0f);
            }

            if (!comp.IsWaterSource && comp.DependIngredients == false)
            {
                Log.Error("not watersource");
                return(0.0f);
            }

            if (comp.SourceType != CompProperties_WaterSource.SourceType.Item)
            {
                Log.Error("source type is not item");
                return(0.0f);
            }

            var waterType    = GetWaterType(thing);
            var waterTypeDef = MizuDef.Dic_WaterTypeDef[waterType];

            // 指定された健康状態になる
            if (waterTypeDef.hediffs != null)
            {
                foreach (var hediff in waterTypeDef.hediffs)
                {
                    getter.health.AddHediff(HediffMaker.MakeHediff(hediff, getter));
                }
            }

            // 確率で食中毒
            var animalFactor = getter.RaceProps.Humanlike ? 1f : 0.1f; // 動物は1/10に抑える

            if (Rand.Value < waterTypeDef.foodPoisonChance * animalFactor)
            {
                FoodUtility.AddFoodPoisoningHediff(getter, thing, FoodPoisonCause.Unknown);
            }

            // 摂取個数と摂取水分量の計算
            thing.GetWaterCalculateAmounts(waterWanted, withIngested, out var drankWaterItemCount, out var gotWaterAmount);

            if (withIngested)
            {
                // 食事の場合は後で個数を計算するのでここでは1個にする
                gotWaterAmount      = comp.WaterAmount;
                drankWaterItemCount = 1;
            }

            // 食事と同時に水分摂取する場合は既に消滅しているので消滅処理をスキップする
            if (withIngested || drankWaterItemCount <= 0)
            {
                return(gotWaterAmount);
            }

            if (drankWaterItemCount == thing.stackCount)
            {
                // アイテム消費数とスタック数が同じ
                // →完全消滅
                thing.Destroy();
            }
            else
            {
                // スタック数と異なる
                // →消費した数だけ減らす
                thing.SplitOff(drankWaterItemCount);
            }

            return(gotWaterAmount);
        }
예제 #3
0
        private static Toil DrinkSomeone(TargetIndex thingIndex, Func <Toil, Func <LocalTargetInfo> > funcGetter)
        {
            Toil toil = new Toil();

            toil.initAction = delegate
            {
                Pawn  actor = toil.actor;
                Thing thing = actor.CurJob.GetTarget(thingIndex).Thing;
                var   comp  = thing.TryGetComp <CompWaterSource>();
                if (comp == null || comp.SourceType != CompProperties_WaterSource.SourceType.Item)
                {
                    actor.jobs.EndCurrentJob(JobCondition.Incompletable, true);
                    return;
                }
                actor.rotationTracker.FaceCell(actor.Position);
                if (!thing.CanDrinkWaterNow())
                {
                    actor.jobs.EndCurrentJob(JobCondition.Incompletable, true);
                    return;
                }
                actor.jobs.curDriver.ticksLeftThisToil = comp.BaseDrinkTicks;
                if (thing.Spawned)
                {
                    thing.Map.physicalInteractionReservationManager.Reserve(actor, actor.CurJob, thing);
                }
            };
            toil.tickAction = delegate
            {
                toil.actor.GainComfortFromCellIfPossible();
            };
            toil.WithProgressBar(thingIndex, delegate
            {
                Pawn actor  = toil.actor;
                Thing thing = actor.CurJob.GetTarget(thingIndex).Thing;
                var comp    = thing.TryGetComp <CompWaterSource>();
                if (thing == null || comp == null || comp.SourceType != CompProperties_WaterSource.SourceType.Item)
                {
                    return(1f);
                }
                return(1f - (float)toil.actor.jobs.curDriver.ticksLeftThisToil / (float)comp.BaseDrinkTicks);
            }, false, -0.5f);
            toil.defaultCompleteMode = ToilCompleteMode.Delay;
            toil.FailOnDestroyedOrNull(thingIndex);
            toil.AddFinishAction(delegate
            {
                Pawn actor = toil.actor;
                if (actor == null)
                {
                    return;
                }
                if (actor.CurJob == null)
                {
                    return;
                }
                Thing thing = actor.CurJob.GetTarget(thingIndex).Thing;
                if (thing == null)
                {
                    return;
                }
                if (actor.Map.physicalInteractionReservationManager.IsReservedBy(actor, thing))
                {
                    actor.Map.physicalInteractionReservationManager.Release(actor, actor.CurJob, thing);
                }
            });

            // エフェクト追加
            toil.WithEffect(delegate
            {
                Pawn actor             = toil.actor;
                LocalTargetInfo target = toil.actor.CurJob.GetTarget(thingIndex);
                if (!target.HasThing)
                {
                    return(null);
                }
                EffecterDef effecter = null;
                var comp             = target.Thing.TryGetComp <CompWaterSource>();
                if (comp != null)
                {
                    effecter = comp.GetEffect;
                }
                return(effecter);
            }, funcGetter(toil));
            toil.PlaySustainerOrSound(delegate
            {
                Pawn actor = toil.actor;
                if (!actor.RaceProps.Humanlike)
                {
                    return(null);
                }
                LocalTargetInfo target = toil.actor.CurJob.GetTarget(thingIndex);
                if (!target.HasThing)
                {
                    return(null);
                }
                var comp = target.Thing.TryGetComp <CompWaterSource>();
                if (comp == null)
                {
                    return(null);
                }
                return(comp.Props.getSound);
            });
            return(toil);
        }
예제 #4
0
 private static bool CanNowGetWater(Thing water, Pawn pawn)
 {
     return(!water.IngestibleNow && water.CanDrinkWaterNow() && CanEverGetWater(water) &&
            (pawn.needs.Water().CurCategory >= ThirstCategory.Dehydration ||
             water.GetWaterPreferability() > WaterPreferability.NeverDrink));
 }