private static float FoodSourceOptimality(Pawn eater, Thing t, float dist) { float num = 300f; num -= dist; ThingDef thingDef = (!(t is Building_NutrientPasteDispenser)) ? t.def : ThingDefOf.MealNutrientPaste; FoodPreferability preferability = thingDef.ingestible.preferability; if (preferability != FoodPreferability.NeverForNutrition) { if (preferability == FoodPreferability.DesperateOnly) { num -= 150f; } CompRottable compRottable = t.TryGetComp <CompRottable>(); if (compRottable != null) { if (compRottable.Stage == RotStage.Dessicated) { return(-9999999f); } if (compRottable.Stage == RotStage.Fresh && compRottable.TicksUntilRotAtCurrentTemp < 30000) { num += 12f; } } if (eater.needs != null && eater.needs.mood != null) { List <ThoughtDef> list = FoodUtility.ThoughtsFromIngesting(eater, t); for (int i = 0; i < list.Count; i++) { num += FoodOptimalityEffectFromMoodCurve.Evaluate(list[i].stages[0].baseMoodEffect); } } num += thingDef.ingestible.optimalityOffset; return(num); } return(-9999999f); }
protected override void IngestedCalculateAmounts(Pawn ingester, float nutritionWanted, out int numTaken, out float nutritionIngested) { BodyPartRecord bodyPartRecord = this.GetBestBodyPartToEat(ingester, nutritionWanted); if (bodyPartRecord == null) { Log.Error(string.Concat(new object[] { ingester, " ate ", this, " but no body part was found. Replacing with core part." }), false); bodyPartRecord = this.InnerPawn.RaceProps.body.corePart; } float bodyPartNutrition = FoodUtility.GetBodyPartNutrition(this, bodyPartRecord); if (bodyPartRecord == this.InnerPawn.RaceProps.body.corePart) { if (PawnUtility.ShouldSendNotificationAbout(this.InnerPawn) && this.InnerPawn.RaceProps.Humanlike) { Messages.Message("MessageEatenByPredator".Translate(new object[] { this.InnerPawn.LabelShort, ingester.LabelIndefinite() }).CapitalizeFirst(), ingester, MessageTypeDefOf.NegativeEvent, true); } numTaken = 1; } else { Hediff_MissingPart hediff_MissingPart = (Hediff_MissingPart)HediffMaker.MakeHediff(HediffDefOf.MissingBodyPart, this.InnerPawn, bodyPartRecord); hediff_MissingPart.lastInjury = HediffDefOf.Bite; hediff_MissingPart.IsFresh = true; this.InnerPawn.health.AddHediff(hediff_MissingPart, null, null, null); numTaken = 0; } nutritionIngested = bodyPartNutrition; }
public override float GetPriority(Pawn pawn) { Need_Food food = pawn.needs.food; if (food == null) { return(0f); } if (pawn.needs.food.CurCategory < HungerCategory.Starving && FoodUtility.ShouldBeFedBySomeone(pawn)) { return(0f); } if (food.CurCategory < minCategory) { return(0f); } if (food.CurLevelPercentage < pawn.RaceProps.FoodLevelPercentageWantEat) { return(9.5f); } return(0f); }
// // Methods // public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false) { Pawn pawn2 = t as Pawn; if (pawn2 == null || pawn2 == pawn) { return(false); } if (!pawn2.RaceProps.Humanlike || pawn2.ageTracker.CurLifeStageIndex > AgeStage.Toddler) { return(false); } if (pawn2.needs.food == null || pawn2.needs.food.CurLevelPercentage > pawn2.needs.food.PercentageThreshHungry + 0.02) { return(false); } if (!pawn2.InBed()) { return(false); } if (!FeedPatientUtility.ShouldBeFed(pawn2)) { return(false); } if (!pawn.CanReserveAndReach(t, PathEndMode.ClosestTouch, Danger.Deadly, 1, -1, null, forced)) { return(false); } Thing thing; ThingDef thingDef; if (!FoodUtility.TryFindBestFoodSourceFor(pawn, pawn2, pawn2.needs.food.CurCategory == HungerCategory.UrgentlyHungry, out thing, out thingDef, false, true, false, false, false) && !ChildrenUtility.CanBreastfeed(pawn)) { JobFailReason.Is("NoFood".Translate()); return(false); } return(true); }
static void Postfix(Thing __result, ThingDef def, ThingDef stuff) { if (!Settings.add_meal_ingredients || __result == null || !__result.def.IsIngestible) { return; } CompIngredients ings = __result.TryGetComp <CompIngredients>(); if (ings == null || ings.ingredients.Count > 0) { return; } RecipeDef d = hTable.TryGetValue(def); if (d == null) { d = DefDatabase <RecipeDef> .AllDefsListForReading.Where(x => !x.ingredients.NullOrEmpty() && x.products.Any(y => y.thingDef == def)).RandomElement(); if (d == null) { return; } hTable.Add(def, d); } foreach (IngredientCount c in d.ingredients) { ThingDef td = c.filter.AllowedThingDefs.Where( x => x.IsIngestible && !x.comps.Any(y => y.compClass == typeof(CompIngredients)) && !FoodUtility.IsHumanlikeMeat(x) && (x.ingestible.specialThoughtAsIngredient == null || x.ingestible.specialThoughtAsIngredient.stages[0].baseMoodEffect >= 0) ).RandomElement(); if (td != null) { ings.RegisterIngredient(td); } } }
protected override void IngestedCalculateAmounts(Pawn ingester, float nutritionWanted, out int numTaken, out float nutritionIngested) { //Determine part to take var part = GetBestBodyPartToEat(ingester, nutritionWanted); if (part == null) { Log.Error(ingester + " ate " + this + " but no body part was found. Replacing with core part."); part = InnerPawn.RaceProps.body.corePart; } //Determine the nutrition to gain float nut = FoodUtility.GetBodyPartNutrition(this, part); //Affect this thing //If ate core part, remove the whole corpse //Otherwise, remove the eaten body part if (part == InnerPawn.RaceProps.body.corePart) { if (PawnUtility.ShouldSendNotificationAbout(InnerPawn) && InnerPawn.RaceProps.Humanlike) { Messages.Message("MessageEatenByPredator".Translate(InnerPawn.LabelShort, ingester.Named("PREDATOR"), InnerPawn.Named("EATEN")).CapitalizeFirst(), ingester, MessageTypeDefOf.NegativeEvent); } numTaken = 1; } else { var missing = (Hediff_MissingPart)HediffMaker.MakeHediff(HediffDefOf.MissingBodyPart, InnerPawn, part); missing.lastInjury = HediffDefOf.Bite; missing.IsFresh = true; InnerPawn.health.AddHediff(missing); numTaken = 0; } nutritionIngested = nut; }
/// <summary> /// Counts all available nutrition in the printer. /// </summary> /// <returns>Total nutrition.</returns> public float CountNutrition() { float totalNutrition = 0f; //Count nutrition. foreach (Thing item in thingHolder) { Corpse corpse = item as Corpse; if (corpse != null) { totalNutrition += FoodUtility.GetBodyPartNutrition(corpse, corpse.InnerPawn.RaceProps.body.corePart); } else { if (item.def.IsIngestible) { totalNutrition += (item.def?.ingestible.CachedNutrition ?? 0.05f) * item.stackCount; } } } return(totalNutrition); }
protected override Job TryGiveJob(Pawn pawn) { Predicate <Thing> predicate = (Thing x) => x.def.category == ThingCategory.Pawn && HasJobOnThing(pawn, x); Thing t = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode, TraverseParms.For(pawn, MaxPathDanger(pawn), TraverseMode.ByPawn), 100f, predicate, PotentialWorkThingsGlobal(pawn)); if (t is null) { return(null); } Pawn pawn2 = (Pawn)t; if (TryFindBestFoodSourceFor(pawn, pawn2, pawn2.needs.food.CurCategory == HungerCategory.Starving, out Thing foodSource, out ThingDef foodDef, canRefillDispenser: false, canUseInventory: true, canUsePackAnimalInventory: true)) { float nutrition = FoodUtility.GetNutrition(foodSource, foodDef); Job job = JobMaker.MakeJob(JobDefOf.FeedPatient); job.targetA = foodSource; job.targetB = pawn2; job.count = FoodUtility.WillIngestStackCountOf(pawn2, foodDef, nutrition); return(job); } return(null); }
static void Postfix(ref float __result, Pawn eater, Thing foodSource, ThingDef foodDef, float dist, bool takingToInventory = false) { if (!Settings.prefer_spoiling_meals) { return; } const float qday = 2500f * 6f; const float aday = qday * 4f; CompRottable compRottable = foodSource.TryGetComp <CompRottable>(); if (compRottable != null) { float t = compRottable.PropsRot.TicksToRotStart - compRottable.RotProgress; float num = 0; if (eater.needs != null && eater.needs.mood != null) { List <FoodUtility.ThoughtFromIngesting> list = FoodUtility.ThoughtsFromIngesting(eater, foodSource, foodDef); for (int i = 0; i < list.Count; i++) { num += ((SimpleCurve)LFoodOptimalityEffectFromMoodCurve.GetValue(null)).Evaluate(list[i].thought.stages[0].baseMoodEffect); } } // if (num < 6f) { num = 6f; } // if (t > 0 && t < aday * 2f) { __result += (float)Math.Truncate(num * (1f + (aday * 2f - t) / qday) * 0.5f); } //Log.Message($"{foodSource}={__result}({Math.Truncate(num * (1f + (aday * 2f - t) / qday) * 0.4f)})"); } }
static void Postfix(Thing __instance, float __result, Pawn ingester, float nutritionWanted) { if (__result > 0) { bool isHumanLike = false; if (FoodUtility.IsHumanlikeMeat(__instance.def)) { isHumanLike = true; } else { CompIngredients compIngredients = __instance.TryGetComp <CompIngredients>(); if (compIngredients != null) { foreach (var ing in compIngredients.ingredients) { if (FoodUtility.IsHumanlikeMeat(ing)) { isHumanLike = true; break; } } } } if (isHumanLike && ingester.RaceProps.Humanlike) { var progress = CanibalismProgression.For(ingester); if (!progress.Locked) { progress.Add(__result); progress.TryBecomeCannibal(); } } } }
static bool Prefix(ref List <FoodUtility.ThoughtFromIngesting> __result, Pawn ingester, Thing foodSource, ThingDef foodDef) { if (foodDef != PackedMeat.MysteriousPackDef && foodDef != PackedMeat.OddPackDef && foodDef != PackedMeat.RegularPackDef) { return(true); } // var compIngredients = foodSource.TryGetComp <CompIngredients>(); if (compIngredients == null) { return(true); } // List <FoodUtility.ThoughtFromIngesting> l = new List <FoodUtility.ThoughtFromIngesting>(); foreach (var ing in compIngredients.ingredients) { Thing dummy = ThingMaker.MakeThing(ing); l.AddRange(FoodUtility.ThoughtsFromIngesting(ingester, dummy, ing)); } __result = l; return(false); }
static int getflags(CompIngredients compIngredients) { int b = 0; //0 - clean; //1 - positive //2 - negative //4 - humanlike foreach (var ing in compIngredients.ingredients) { if (!ing.IsIngestible) { continue; } else if (FoodUtility.IsHumanlikeMeat(ing)) { b = b | 4; } else if (ing.ingestible.specialThoughtAsIngredient != null) { if (ing.ingestible.specialThoughtAsIngredient.stages.Count > 0) { //if(ing.ingestible.specialThoughtAsIngredient.stages[0].baseMoodEffect > 0) // b = b | 1; //else if (!Settings.odd_is_normal && ing.ingestible.specialThoughtAsIngredient.stages[0].baseMoodEffect < 0) { b = b | 2; } } } } return(b); }
protected override Job TryGiveJob(Pawn pawn) { FoodUtility_Patch.forWendigo = true; Need_Food food = pawn.needs.food; if (food == null || (int)food.CurCategory < (int)minCategory || food.CurLevelPercentage > maxLevelPercentage) { FoodUtility_Patch.forWendigo = false; return(null); } bool allowCorpse = true; bool desperate = pawn.needs.food.CurCategory == HungerCategory.Starving; if (!FoodUtility.TryFindBestFoodSourceFor(pawn, pawn, desperate, out var foodSource, out var foodDef, canRefillDispenser: true, canUseInventory: true, allowForbidden: false, allowCorpse, allowSociallyImproper: false, pawn.IsWildMan(), forceScanWholeMap)) { FoodUtility_Patch.forWendigo = false; return(null); } Pawn pawn2 = foodSource as Pawn; if (pawn2 != null) { Job job = JobMaker.MakeJob(JobDefOf.PredatorHunt, pawn2); job.killIncappedTarget = true; FoodUtility_Patch.forWendigo = false; return(job); } FoodUtility_Patch.forWendigo = true; float nutrition = FoodUtility.GetNutrition(foodSource, foodDef); Job job3 = JobMaker.MakeJob(WendigoDefOf.RCW_Ingest, foodSource); job3.count = FoodUtility.WillIngestStackCountOf(pawn, foodDef, nutrition); FoodUtility_Patch.forWendigo = false; return(job3); }
private bool ValidateHunt(FoodSearchItem item) { if (item.FoodCategory != FoodCategory.Hunt) { return(true); } if (parameters.Getter != parameters.Eater) { traceOutput?.AppendLine($"Rejecting {item.Thing}: will not hunt for others"); return(false); } if (parameters.Getter == item.Thing) { traceOutput?.AppendLine($"Rejecting {item.Thing}: {parameters.Getter} will not hunt self"); return(false); } var pawn = item.Thing as Pawn; if (pawn == null) { traceOutput?.AppendLine($"Rejecting {item.Thing}: unable to find Pawn reference for hunting evaluation"); return(false); } if (!FoodUtility.IsAcceptablePreyFor(parameters.Getter, pawn)) { traceOutput?.AppendLine($"Rejecting {item.Thing}: not acceptable prey for {parameters.Getter}"); return(false); } return(true); }
protected override Job TryGiveJob(Pawn pawn) { bool allowCorpse = true; bool desperate = pawn.needs.food.CurCategory == HungerCategory.Starving; var foodSource = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.ClosestTouch, TraverseParms.For(pawn), 9999, (Thing x) => x is Pawn victim && victim.RaceProps.Humanlike && victim.Downed && pawn.CanReserve(victim)); ThingDef foodDef = (foodSource as Pawn)?.Corpse?.def; if (foodSource is null && !FoodUtility.TryFindBestFoodSourceFor(pawn, pawn, desperate, out foodSource, out foodDef, canRefillDispenser: true, canUseInventory: true, allowForbidden: false, allowCorpse, allowSociallyImproper: false, pawn.IsWildMan(), forceScanWholeMap)) { return(null); } Pawn pawn2 = foodSource as Pawn; if (pawn2 != null && !pawn2.Downed) { Job job = JobMaker.MakeJob(JobDefOf.PredatorHunt, pawn2); job.killIncappedTarget = true; return(job); } float nutrition = FoodUtility.GetNutrition(foodSource, foodDef); Job job3 = JobMaker.MakeJob(BETADefOf.BETA_Ingest, foodSource); if (pawn2 != null) { job3.count = 1; } else { job3.count = FoodUtility.WillIngestStackCountOf(pawn, foodDef, nutrition); } return(job3); }
private BodyPartRecord GetBestBodyPartToEat(Pawn ingester, float nutritionWanted) { IEnumerable <BodyPartRecord> source = from x in InnerPawn.health.hediffSet.GetNotMissingParts() where x.depth == BodyPartDepth.Outside && FoodUtility.GetBodyPartNutrition(InnerPawn, x) > 0.001f select x; if (!source.Any()) { return(null); } return(source.MinBy((BodyPartRecord x) => Mathf.Abs(FoodUtility.GetBodyPartNutrition(InnerPawn, x) - nutritionWanted))); }
// Token: 0x0600017C RID: 380 RVA: 0x0000DB3C File Offset: 0x0000BF3C public bool TryFindBestFoodSourceFor(Pawn getter, Pawn eater, bool desperate, out Thing foodSource, out ThingDef foodDef, bool canRefillDispenser = true, bool canUseInventory = true, bool allowForbidden = false, bool allowCorpse = true, bool allowSociallyImproper = false, bool allowHarvest = false, bool forceScanWholeMap = false) { bool flag = getter.RaceProps.ToolUser && getter.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation); bool flag2 = !eater.IsTeetotaler(); Thing thing = null; ThingDef thingDef = null; ThingDef foodDef2 = thingDef; bool allowPlant = getter == eater; Thing thing2 = FoodUtility.BestFoodSourceOnMap(getter, eater, desperate, out foodDef2, FoodPreferability.Undefined, allowPlant, flag2, allowCorpse, true, canRefillDispenser, allowForbidden, allowSociallyImproper, allowHarvest, forceScanWholeMap); if (thing == null && thing2 == null) { if (canUseInventory && flag) { FoodPreferability minFoodPref = FoodPreferability.DesperateOnly; bool allowDrug = flag2; thing = FoodUtility.BestFoodInInventory(getter, eater, minFoodPref, FoodPreferability.MealLavish, 0f, allowDrug); if (thing != null) { foodSource = thing; foodDef = FoodUtility.GetFinalIngestibleDef(foodSource, false); return(true); } } if (thing2 == null && getter == eater && (getter.RaceProps.predator || (getter.IsWildMan() && !getter.IsPrisoner))) { Pawn pawn = BestPawnToHuntForPredator(getter, forceScanWholeMap); if (pawn != null) { foodSource = pawn; foodDef = FoodUtility.GetFinalIngestibleDef(foodSource, false); return(true); } } foodSource = null; foodDef = null; return(false); } if (thing == null && thing2 != null) { foodSource = thing2; foodDef = thingDef; return(true); } ThingDef finalIngestibleDef = FoodUtility.GetFinalIngestibleDef(thing, false); if (thing2 == null) { foodSource = thing; foodDef = finalIngestibleDef; return(true); } float num = FoodUtility.FoodOptimality(eater, thing2, thingDef, (float)(getter.Position - thing2.Position).LengthManhattan, false); float num2 = FoodUtility.FoodOptimality(eater, thing, finalIngestibleDef, 0f, false); num2 -= 32f; if (num > num2) { foodSource = thing2; foodDef = thingDef; return(true); } foodSource = thing; foodDef = FoodUtility.GetFinalIngestibleDef(foodSource, false); return(true); }
public static Toil DrinkFromBuilding(TargetIndex buildingIndex) { int initialTicks = 1; Toil toil = new Toil(); toil.initAction = delegate { var actor = toil.actor; var thing = actor.CurJob.GetTarget(buildingIndex).Thing; var comp = thing.TryGetComp <CompWaterSource>(); var building = thing as IBuilding_DrinkWater; if (actor.needs == null || actor.needs.water() == null || building == null || comp == null || !comp.IsWaterSource) { actor.jobs.EndCurrentJob(JobCondition.Incompletable); return; } var need_water = actor.needs.water(); var waterTypeDef = MizuDef.Dic_WaterTypeDef[comp.WaterType]; // 向きを変更 actor.rotationTracker.FaceCell(actor.Position); // 作業量 actor.jobs.curDriver.ticksLeftThisToil = (int)(comp.BaseDrinkTicks * need_water.WaterWanted); initialTicks = actor.jobs.curDriver.ticksLeftThisToil; if (actor.needs.mood != null) { // 水分摂取による心情変化 foreach (var thoughtDef in MizuUtility.ThoughtsFromGettingWater(actor, thing)) { actor.needs.mood.thoughts.memories.TryGainMemory(thoughtDef); } } // 指定された健康状態になる if (waterTypeDef.hediffs != null) { foreach (var hediff in waterTypeDef.hediffs) { actor.health.AddHediff(HediffMaker.MakeHediff(hediff, actor)); } } // 確率で食中毒 if (Rand.Value < waterTypeDef.foodPoisonChance) { FoodUtility.AddFoodPoisoningHediff(actor, thing, FoodPoisonCause.Unknown); } }; toil.tickAction = delegate { toil.actor.GainComfortFromCellIfPossible(); var need_water = toil.actor.needs.water(); var thing = toil.actor.CurJob.GetTarget(buildingIndex).Thing; var comp = thing.TryGetComp <CompWaterSource>(); var building = thing as IBuilding_DrinkWater; if (thing == null || comp == null || !comp.IsWaterSource || building == null || building.IsEmpty) { toil.actor.jobs.EndCurrentJob(JobCondition.Incompletable); return; } // 徐々に飲む float riseNeedWater = 1 / (float)comp.BaseDrinkTicks; need_water.CurLevel = Mathf.Min(need_water.CurLevel + riseNeedWater, need_water.MaxLevel); building.DrawWater(riseNeedWater * Need_Water.NeedWaterVolumePerDay); }; toil.WithProgressBar(buildingIndex, delegate { return(1f - (float)toil.actor.jobs.curDriver.ticksLeftThisToil / initialTicks); }, false, -0.5f); toil.defaultCompleteMode = ToilCompleteMode.Delay; toil.FailOn((t) => { Pawn actor = toil.actor; var target = actor.CurJob.GetTarget(buildingIndex); if (target.Thing.def.hasInteractionCell) { // 使用場所があるなら使用場所基準 return(target.Thing.InteractionCell.IsForbidden(actor) || !actor.CanReach(target.Thing.InteractionCell, PathEndMode.OnCell, Danger.Deadly)); } else { // 使用場所がないなら設備の場所基準 return(target.Thing.Position.IsForbidden(actor) || !actor.CanReach(target.Thing.Position, PathEndMode.ClosestTouch, Danger.Deadly)); } }); // エフェクト追加 toil.PlaySustainerOrSound(delegate { return(DefDatabase <SoundDef> .GetNamed("Ingest_Beer")); }); return(toil); }
// Decompiled code is painful to read... Continue at your own risk public static List <FloatMenuOption> ChoicesForThing(Thing thing, Pawn pawn) { List <FloatMenuOption> opts = new List <FloatMenuOption>(); Thing t = thing; // Copied from FloatMenuMakerMap.AddHumanlikeOrders if (t.def.ingestible != null && pawn.RaceProps.CanEverEat(t) && t.IngestibleNow) { string text; if (t.def.ingestible.ingestCommandString.NullOrEmpty()) { text = "ConsumeThing".Translate(new NamedArgument[] { t.LabelShort }); } else { text = string.Format(t.def.ingestible.ingestCommandString, t.LabelShort); } if (!t.IsSociallyProper(pawn)) { text = text + " (" + "ReservedForPrisoners".Translate() + ")"; } FloatMenuOption item7; if (t.def.IsNonMedicalDrug && pawn.IsTeetotaler()) { item7 = new FloatMenuOption(text + " (" + TraitDefOf.DrugDesire.DataAtDegree(-1).label + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else if (!pawn.CanReach(t, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn)) { item7 = new FloatMenuOption(text + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else { MenuOptionPriority priority2 = (!(t is Corpse)) ? MenuOptionPriority.Default : MenuOptionPriority.Low; item7 = FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(text, delegate() { t.SetForbidden(false, true); Job job = new Job(JobDefOf.Ingest, t); job.count = FoodUtility.WillIngestStackCountOf(pawn, t.def, t.GetStatValue(StatDefOf.Nutrition, true)); pawn.jobs.TryTakeOrderedJob(job, JobTag.Misc); }, priority2, null, null, 0f, null, null), pawn, t, "ReservedBy"); } opts.Add(item7); } // Add equipment commands // Copied from FloatMenuMakerMap.AddHumanlikeOrders if (thing is ThingWithComps equipment && equipment.GetComp <CompEquippable>() != null) { string labelShort = equipment.LabelShort; FloatMenuOption item4; if (equipment.def.IsWeapon && pawn.story.WorkTagIsDisabled(WorkTags.Violent)) { item4 = new FloatMenuOption("CannotEquip".Translate(new NamedArgument[] { labelShort }) + " (" + "IsIncapableOfViolenceLower".Translate(new NamedArgument[] { pawn.LabelShort }) + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else if (!pawn.CanReach(equipment, PathEndMode.ClosestTouch, Danger.Deadly, false, TraverseMode.ByPawn)) { item4 = new FloatMenuOption("CannotEquip".Translate(new NamedArgument[] { labelShort }) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else if (!pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation)) { item4 = new FloatMenuOption("CannotEquip".Translate(new NamedArgument[] { labelShort }) + " (" + "Incapable".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else { string text5 = "Equip".Translate(new NamedArgument[] { labelShort }); if (equipment.def.IsRangedWeapon && pawn.story != null && pawn.story.traits.HasTrait(TraitDefOf.Brawler)) { text5 = text5 + " " + "EquipWarningBrawler".Translate(); } item4 = FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(text5, delegate() { equipment.SetForbidden(false, true); pawn.jobs.TryTakeOrderedJob(new Job(JobDefOf.Equip, equipment), JobTag.Misc); MoteMaker.MakeStaticMote(equipment.DrawPos, equipment.Map, ThingDefOf.Mote_FeedbackEquip, 1f); PlayerKnowledgeDatabase.KnowledgeDemonstrated(ConceptDefOf.EquippingWeapons, KnowledgeAmount.Total); }, MenuOptionPriority.High, null, null, 0f, null, null), pawn, equipment, "ReservedBy"); } opts.Add(item4); } // Add clothing commands Apparel apparel = thing as Apparel; if (apparel != null) { FloatMenuOption item5; if (!pawn.CanReach(apparel, PathEndMode.ClosestTouch, Danger.Deadly, false, TraverseMode.ByPawn)) { item5 = new FloatMenuOption("CannotWear".Translate(new NamedArgument[] { apparel.Label }) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else if (!ApparelUtility.HasPartsToWear(pawn, apparel.def)) { item5 = new FloatMenuOption("CannotWear".Translate(new NamedArgument[] { apparel.Label }) + " (" + "CannotWearBecauseOfMissingBodyParts".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null); } else { item5 = FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("ForceWear".Translate(new NamedArgument[] { apparel.LabelShort }), delegate() { apparel.SetForbidden(false, true); Job job = new Job(JobDefOf.Wear, apparel); pawn.jobs.TryTakeOrderedJob(job, JobTag.Misc); }, MenuOptionPriority.High, null, null, 0f, null, null), pawn, apparel, "ReservedBy"); } opts.Add(item5); } // Add caravan commands if (pawn.IsFormingCaravan()) { if (thing != null && thing.def.EverHaulable) { Pawn packTarget = GiveToPackAnimalUtility.UsablePackAnimalWithTheMostFreeSpace(pawn) ?? pawn; JobDef jobDef = (packTarget != pawn) ? JobDefOf.GiveToPackAnimal : JobDefOf.TakeInventory; if (!pawn.CanReach(thing, PathEndMode.ClosestTouch, Danger.Deadly, false, TraverseMode.ByPawn)) { opts.Add(new FloatMenuOption("CannotLoadIntoCaravan".Translate(new NamedArgument[] { thing.Label }) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null)); } else if (MassUtility.WillBeOverEncumberedAfterPickingUp(packTarget, thing, 1)) { opts.Add(new FloatMenuOption("CannotLoadIntoCaravan".Translate(new NamedArgument[] { thing.Label }) + " (" + "TooHeavy".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null)); } else { LordJob_FormAndSendCaravan lordJob = (LordJob_FormAndSendCaravan)pawn.GetLord().LordJob; float capacityLeft = CaravanFormingUtility.CapacityLeft(lordJob); if (thing.stackCount == 1) { float capacityLeft4 = capacityLeft - thing.GetStatValue(StatDefOf.Mass, true); opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(CaravanFormingUtility.AppendOverweightInfo("LoadIntoCaravan".Translate(new NamedArgument[] { thing.Label }), capacityLeft4), delegate() { thing.SetForbidden(false, false); Job job = new Job(jobDef, thing); job.count = 1; job.checkEncumbrance = (packTarget == pawn); pawn.jobs.TryTakeOrderedJob(job, JobTag.Misc); }, MenuOptionPriority.High, null, null, 0f, null, null), pawn, thing, "ReservedBy")); } else { if (MassUtility.WillBeOverEncumberedAfterPickingUp(packTarget, thing, thing.stackCount)) { opts.Add(new FloatMenuOption("CannotLoadIntoCaravanAll".Translate(new NamedArgument[] { thing.Label }) + " (" + "TooHeavy".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null)); } else { float capacityLeft2 = capacityLeft - (float)thing.stackCount * thing.GetStatValue(StatDefOf.Mass, true); opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(CaravanFormingUtility.AppendOverweightInfo("LoadIntoCaravanAll".Translate(new NamedArgument[] { thing.Label }), capacityLeft2), delegate() { thing.SetForbidden(false, false); Job job = new Job(jobDef, thing); job.count = thing.stackCount; job.checkEncumbrance = (packTarget == pawn); pawn.jobs.TryTakeOrderedJob(job, JobTag.Misc); }, MenuOptionPriority.High, null, null, 0f, null, null), pawn, thing, "ReservedBy")); } opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("LoadIntoCaravanSome".Translate(new NamedArgument[] { thing.LabelNoCount }), delegate() { int to = Mathf.Min(MassUtility.CountToPickUpUntilOverEncumbered(packTarget, thing), thing.stackCount); Dialog_Slider window = new Dialog_Slider(delegate(int val) { float capacityLeft3 = capacityLeft - (float)val * thing.GetStatValue(StatDefOf.Mass, true); return(CaravanFormingUtility.AppendOverweightInfo(string.Format("LoadIntoCaravanCount".Translate(new NamedArgument[] { thing.LabelNoCount }), val), capacityLeft3)); }, 1, to, delegate(int count) { thing.SetForbidden(false, false); Job job = new Job(jobDef, thing); job.count = count; job.checkEncumbrance = (packTarget == pawn); pawn.jobs.TryTakeOrderedJob(job, JobTag.Misc); }, int.MinValue); Find.WindowStack.Add(window); }, MenuOptionPriority.High, null, null, 0f, null, null), pawn, thing, "ReservedBy")); } } } } if (opts.Count == 0) { opts.Add(new FloatMenuOption("NoneBrackets".Translate(), null) { Disabled = true }); } return(opts); }
public override void LordToilTick() { base.LordToilTick(); var customParams = CustomParams; var data = Data; if (lord.ticksInToil == StartBuildingDelay) { lord.CurLordToil.UpdateAllDuties(); } if (lord.ticksInToil > StartBuildingDelay && lord.ticksInToil % 500 == 0) { UpdateAllDuties(); } if (Find.TickManager.TicksGame % 500 == 0) { if (!(from frame in Frames where !frame.Destroyed select frame).Any <Frame>()) { if (!(from blue in data.blueprints where !blue.Destroyed select blue).Any <Blueprint>() && !base.Map.listerThings.ThingsInGroup(ThingRequestGroup.BuildingArtificial).Any((Thing b) => b.Faction == lord.faction && b.def.building.buildingTags.Contains("Artillery"))) { lord.ReceiveMemo("NoArtillery"); return; } } var arties = Artillery; int shellCount = 0; int foodCount = 0; for (int i = 0; i < GenRadial.NumCellsInRadius(20); i++) { IntVec3 c = data.siegeCenter + GenRadial.RadialPattern[i]; if (c.InBounds(Map)) { List <Thing> thingList = c.GetThingList(Map); for (int j = 0; j < thingList.Count; j++) { var curThing = thingList[j]; if (curThing.def.IsShell && arties.Any(a => CustomSiegeUtility.AcceptsShell(a, curThing.def))) { shellCount += curThing.stackCount; } if (curThing.def == customParams.mealDef) { foodCount += curThing.stackCount; } } } } // Prevent the shellpocalypse today! if (arties.Any() && shellCount < ReplenishAtShells) { bool allowEMP = false; var techLevel = lord.faction.def.techLevel; var distinctArtillery = data.artilleryCounts.Keys.ToList(); var shellCountsToGive = new Dictionary <ThingDef, int>(); for (int i = 0; i < ShellReplenishCount; i++) { var artillery = distinctArtillery.RandomElementByWeight(a => data.artilleryCounts[a]); ThingDef shellDef = TurretGunUtility.TryFindRandomShellDef(artillery, allowEMP, true, techLevel, false, 250f); if (shellDef != null) { if (shellCountsToGive.ContainsKey(shellDef)) { shellCountsToGive[shellDef]++; } else { shellCountsToGive.Add(shellDef, 1); } } } foreach (var shell in shellCountsToGive) { DropSupplies(shell.Key, shell.Value); } } if (foodCount < FoodUtility.StackCountForNutrition(ReplenishAtMeals, customParams.mealDef.GetStatValueAbstract(StatDefOf.Nutrition))) { DropSupplies(customParams.mealDef, FoodUtility.StackCountForNutrition(MealReplenishCount, customParams.mealDef.GetStatValueAbstract(StatDefOf.Nutrition))); } } }
public static bool AddHumanlikeOrders(Vector3 clickPos, Pawn pawn, List <FloatMenuOption> opts) { IntVec3 c = IntVec3.FromVector3(clickPos); foreach (Thing thing in c.GetThingList(pawn.Map)) { Pawn pawn2; if ((pawn2 = (thing as Pawn)) != null) { Lord lord = pawn2.GetLord(); if (lord != null && lord.CurLordToil != null) { IEnumerable <FloatMenuOption> enumerable = lord.CurLordToil.ExtraFloatMenuOptions(pawn2, pawn); if (enumerable != null) { foreach (FloatMenuOption item8 in enumerable) { opts.Add(item8); } } } } } if (pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation)) { foreach (LocalTargetInfo item9 in GenUI.TargetsAt_NewTemp(clickPos, TargetingParameters.ForArrest(pawn), thingsOnly: true)) { bool flag = item9.HasThing && item9.Thing is Pawn && ((Pawn)item9.Thing).IsWildMan(); if (pawn.Drafted || flag) { if (item9.Thing is Pawn && (pawn.InSameExtraFaction((Pawn)item9.Thing, ExtraFactionType.HomeFaction) || pawn.InSameExtraFaction((Pawn)item9.Thing, ExtraFactionType.MiniFaction))) { opts.Add(new FloatMenuOption("CannotArrest".Translate() + ": " + "SameFaction".Translate((Pawn)item9.Thing), null)); } else if (!pawn.CanReach(item9, PathEndMode.OnCell, Danger.Deadly)) { opts.Add(new FloatMenuOption("CannotArrest".Translate() + ": " + "NoPath".Translate().CapitalizeFirst(), null)); } else { Pawn pTarg2 = (Pawn)item9.Thing; Action action = delegate { Building_Bed building_Bed3 = RestUtility.FindBedFor(pTarg2, pawn, sleeperWillBePrisoner: true, checkSocialProperness: false); if (building_Bed3 == null) { building_Bed3 = RestUtility.FindBedFor(pTarg2, pawn, sleeperWillBePrisoner: true, checkSocialProperness: false, ignoreOtherReservations: true); } if (building_Bed3 == null) { Messages.Message("CannotArrest".Translate() + ": " + "NoPrisonerBed".Translate(), pTarg2, MessageTypeDefOf.RejectInput, historical: false); } else { Job job19 = JobMaker.MakeJob(JobDefOf.Arrest, pTarg2, building_Bed3); job19.count = 1; pawn.jobs.TryTakeOrderedJob(job19); if (pTarg2.Faction != null && ((pTarg2.Faction != Faction.OfPlayer && !pTarg2.Faction.Hidden) || pTarg2.IsQuestLodger())) { TutorUtility.DoModalDialogIfNotKnown(ConceptDefOf.ArrestingCreatesEnemies, pTarg2.GetAcceptArrestChance(pawn).ToStringPercent()); } } }; opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("TryToArrest".Translate(item9.Thing.LabelCap, item9.Thing, pTarg2.GetAcceptArrestChance(pawn).ToStringPercent()), action, MenuOptionPriority.High, null, item9.Thing), pawn, pTarg2)); } } } } foreach (Thing thing2 in c.GetThingList(pawn.Map)) { Thing t = thing2; if (t.def.ingestible != null && pawn.RaceProps.CanEverEat(t) && t.IngestibleNow) { string text = (!t.def.ingestible.ingestCommandString.NullOrEmpty()) ? string.Format(t.def.ingestible.ingestCommandString, t.LabelShort) : ((string)"ConsumeThing".Translate(t.LabelShort, t)); if (!t.IsSociallyProper(pawn)) { text = text + ": " + "ReservedForPrisoners".Translate().CapitalizeFirst(); } FloatMenuOption floatMenuOption; if (t.def.IsNonMedicalDrug && pawn.IsTeetotaler()) { floatMenuOption = new FloatMenuOption(text + ": " + TraitDefOf.DrugDesire.DataAtDegree(-1).GetLabelCapFor(pawn), null); } else if (FoodUtility.InappropriateForTitle(t.def, pawn, allowIfStarving: true)) { floatMenuOption = new FloatMenuOption(text + ": " + "FoodBelowTitleRequirements".Translate(pawn.royalty.MostSeniorTitle.def.GetLabelFor(pawn)), null); } else if (!pawn.CanReach(t, PathEndMode.OnCell, Danger.Deadly)) { floatMenuOption = new FloatMenuOption(text + ": " + "NoPath".Translate().CapitalizeFirst(), null); } else { MenuOptionPriority priority = (t is Corpse) ? MenuOptionPriority.Low : MenuOptionPriority.Default; int maxAmountToPickup = FoodUtility.GetMaxAmountToPickup(t, pawn, FoodUtility.WillIngestStackCountOf(pawn, t.def, t.GetStatValue(StatDefOf.Nutrition))); floatMenuOption = FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(text, delegate { int maxAmountToPickup2 = FoodUtility.GetMaxAmountToPickup(t, pawn, FoodUtility.WillIngestStackCountOf(pawn, t.def, t.GetStatValue(StatDefOf.Nutrition))); if (maxAmountToPickup2 != 0) { t.SetForbidden(value: false); Job job18 = JobMaker.MakeJob(JobDefOf.Ingest, t); job18.count = maxAmountToPickup2; pawn.jobs.TryTakeOrderedJob(job18); } }, priority), pawn, t); if (maxAmountToPickup == 0) { floatMenuOption.action = null; } } opts.Add(floatMenuOption); } } foreach (LocalTargetInfo item10 in GenUI.TargetsAt_NewTemp(clickPos, TargetingParameters.ForQuestPawnsWhoWillJoinColony(pawn), thingsOnly: true)) { Pawn toHelpPawn = (Pawn)item10.Thing; FloatMenuOption item4 = pawn.CanReach(item10, PathEndMode.Touch, Danger.Deadly) ? FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(toHelpPawn.IsPrisoner ? "FreePrisoner".Translate() : "OfferHelp".Translate(), delegate { pawn.jobs.TryTakeOrderedJob(JobMaker.MakeJob(JobDefOf.OfferHelp, toHelpPawn)); }, MenuOptionPriority.RescueOrCapture, null, toHelpPawn), pawn, toHelpPawn) : new FloatMenuOption("CannotGoNoPath".Translate(), null); opts.Add(item4); } if (pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation)) { foreach (Thing thing3 in c.GetThingList(pawn.Map)) { Corpse corpse = thing3 as Corpse; if (corpse != null && corpse.IsInValidStorage()) { StoragePriority priority2 = StoreUtility.CurrentHaulDestinationOf(corpse).GetStoreSettings().Priority; if (StoreUtility.TryFindBestBetterNonSlotGroupStorageFor(corpse, pawn, pawn.Map, priority2, Faction.OfPlayer, out IHaulDestination haulDestination, acceptSamePriority: true) && haulDestination.GetStoreSettings().Priority == priority2 && haulDestination is Building_Grave) { Building_Grave grave = haulDestination as Building_Grave; string label = "PrioritizeGeneric".Translate("Burying".Translate(), corpse.Label); opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(label, delegate { pawn.jobs.TryTakeOrderedJob(HaulAIUtility.HaulToContainerJob(pawn, corpse, grave)); }), pawn, new LocalTargetInfo(corpse))); } } } foreach (LocalTargetInfo item11 in GenUI.TargetsAt_NewTemp(clickPos, TargetingParameters.ForRescue(pawn), thingsOnly: true)) { Pawn victim3 = (Pawn)item11.Thing; if (!victim3.InBed() && pawn.CanReserveAndReach(victim3, PathEndMode.OnCell, Danger.Deadly, 1, -1, null, ignoreOtherReservations: true) && !victim3.mindState.WillJoinColonyIfRescued) { if (!victim3.IsPrisonerOfColony && (!victim3.InMentalState || victim3.health.hediffSet.HasHediff(HediffDefOf.Scaria)) && (victim3.Faction == Faction.OfPlayer || victim3.Faction == null || !victim3.Faction.HostileTo(Faction.OfPlayer))) { opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("Rescue".Translate(victim3.LabelCap, victim3), delegate { Building_Bed building_Bed2 = RestUtility.FindBedFor(victim3, pawn, sleeperWillBePrisoner: false, checkSocialProperness: false); if (building_Bed2 == null) { building_Bed2 = RestUtility.FindBedFor(victim3, pawn, sleeperWillBePrisoner: false, checkSocialProperness: false, ignoreOtherReservations: true); } if (building_Bed2 == null) { string t3 = (!victim3.RaceProps.Animal) ? ((string)"NoNonPrisonerBed".Translate()) : ((string)"NoAnimalBed".Translate()); Messages.Message("CannotRescue".Translate() + ": " + t3, victim3, MessageTypeDefOf.RejectInput, historical: false); } else { Job job17 = JobMaker.MakeJob(JobDefOf.Rescue, victim3, building_Bed2); job17.count = 1; pawn.jobs.TryTakeOrderedJob(job17); PlayerKnowledgeDatabase.KnowledgeDemonstrated(ConceptDefOf.Rescuing, KnowledgeAmount.Total); } }, MenuOptionPriority.RescueOrCapture, null, victim3), pawn, victim3)); } if (victim3.RaceProps.Humanlike && (victim3.InMentalState || victim3.Faction != Faction.OfPlayer || (victim3.Downed && (victim3.guilt.IsGuilty || victim3.IsPrisonerOfColony)))) { TaggedString taggedString = "Capture".Translate(victim3.LabelCap, victim3); if (victim3.Faction != null && victim3.Faction != Faction.OfPlayer && !victim3.Faction.Hidden && !victim3.Faction.HostileTo(Faction.OfPlayer) && !victim3.IsPrisonerOfColony) { taggedString += ": " + "AngersFaction".Translate().CapitalizeFirst(); } opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(taggedString, delegate { Building_Bed building_Bed = RestUtility.FindBedFor(victim3, pawn, sleeperWillBePrisoner: true, checkSocialProperness: false); if (building_Bed == null) { building_Bed = RestUtility.FindBedFor(victim3, pawn, sleeperWillBePrisoner: true, checkSocialProperness: false, ignoreOtherReservations: true); } if (building_Bed == null) { Messages.Message("CannotCapture".Translate() + ": " + "NoPrisonerBed".Translate(), victim3, MessageTypeDefOf.RejectInput, historical: false); } else { Job job16 = JobMaker.MakeJob(JobDefOf.Capture, victim3, building_Bed); job16.count = 1; pawn.jobs.TryTakeOrderedJob(job16); PlayerKnowledgeDatabase.KnowledgeDemonstrated(ConceptDefOf.Capturing, KnowledgeAmount.Total); if (victim3.Faction != null && victim3.Faction != Faction.OfPlayer && !victim3.Faction.Hidden && !victim3.Faction.HostileTo(Faction.OfPlayer) && !victim3.IsPrisonerOfColony) { Messages.Message("MessageCapturingWillAngerFaction".Translate(victim3.Named("PAWN")).AdjustedFor(victim3), victim3, MessageTypeDefOf.CautionInput, historical: false); } } }, MenuOptionPriority.RescueOrCapture, null, victim3), pawn, victim3)); } } } foreach (LocalTargetInfo item12 in GenUI.TargetsAt_NewTemp(clickPos, TargetingParameters.ForRescue(pawn), thingsOnly: true)) { LocalTargetInfo localTargetInfo = item12; Pawn victim2 = (Pawn)localTargetInfo.Thing; if (victim2.Downed && pawn.CanReserveAndReach(victim2, PathEndMode.OnCell, Danger.Deadly, 1, -1, null, ignoreOtherReservations: true) && Building_CryptosleepCasket.FindCryptosleepCasketFor(victim2, pawn, ignoreOtherReservations: true) != null) { string text2 = "CarryToCryptosleepCasket".Translate(localTargetInfo.Thing.LabelCap, localTargetInfo.Thing); JobDef jDef = JobDefOf.CarryToCryptosleepCasket; Action action2 = delegate { Building_CryptosleepCasket building_CryptosleepCasket = Building_CryptosleepCasket.FindCryptosleepCasketFor(victim2, pawn); if (building_CryptosleepCasket == null) { building_CryptosleepCasket = Building_CryptosleepCasket.FindCryptosleepCasketFor(victim2, pawn, ignoreOtherReservations: true); } if (building_CryptosleepCasket == null) { Messages.Message("CannotCarryToCryptosleepCasket".Translate() + ": " + "NoCryptosleepCasket".Translate(), victim2, MessageTypeDefOf.RejectInput, historical: false); } else { Job job15 = JobMaker.MakeJob(jDef, victim2, building_CryptosleepCasket); job15.count = 1; pawn.jobs.TryTakeOrderedJob(job15); } }; if (victim2.IsQuestLodger()) { text2 += " (" + "CryptosleepCasketGuestsNotAllowed".Translate() + ")"; opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(text2, null, MenuOptionPriority.Default, null, victim2), pawn, victim2)); } else if (victim2.GetExtraHostFaction() != null) { text2 += " (" + "CryptosleepCasketGuestPrisonersNotAllowed".Translate() + ")"; opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(text2, null, MenuOptionPriority.Default, null, victim2), pawn, victim2)); } else { opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(text2, action2, MenuOptionPriority.Default, null, victim2), pawn, victim2)); } } } if (ModsConfig.RoyaltyActive) { foreach (LocalTargetInfo item13 in GenUI.TargetsAt_NewTemp(clickPos, TargetingParameters.ForShuttle(pawn), thingsOnly: true)) { LocalTargetInfo localTargetInfo2 = item13; Pawn victim = (Pawn)localTargetInfo2.Thing; Predicate <Thing> validator = (Thing thing) => thing.TryGetComp <CompShuttle>()?.IsAllowedNow(victim) ?? false; Thing shuttleThing = GenClosest.ClosestThingReachable(victim.Position, victim.Map, ThingRequest.ForDef(ThingDefOf.Shuttle), PathEndMode.ClosestTouch, TraverseParms.For(pawn), 9999f, validator); if (shuttleThing != null && pawn.CanReserveAndReach(victim, PathEndMode.OnCell, Danger.Deadly, 1, -1, null, ignoreOtherReservations: true) && !pawn.WorkTypeIsDisabled(WorkTypeDefOf.Hauling)) { string label2 = "CarryToShuttle".Translate(localTargetInfo2.Thing); Action action3 = delegate { CompShuttle compShuttle = shuttleThing.TryGetComp <CompShuttle>(); if (!compShuttle.LoadingInProgressOrReadyToLaunch) { TransporterUtility.InitiateLoading(Gen.YieldSingle(compShuttle.Transporter)); } Job job14 = JobMaker.MakeJob(JobDefOf.HaulToTransporter, victim, shuttleThing); job14.ignoreForbidden = true; job14.count = 1; pawn.jobs.TryTakeOrderedJob(job14); }; opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(label2, action3), pawn, victim)); } } } } foreach (LocalTargetInfo item14 in GenUI.TargetsAt_NewTemp(clickPos, TargetingParameters.ForStrip(pawn), thingsOnly: true)) { LocalTargetInfo stripTarg = item14; FloatMenuOption item5 = pawn.CanReach(stripTarg, PathEndMode.ClosestTouch, Danger.Deadly) ? ((stripTarg.Pawn == null || !stripTarg.Pawn.HasExtraHomeFaction()) ? FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("Strip".Translate(stripTarg.Thing.LabelCap, stripTarg.Thing), delegate { stripTarg.Thing.SetForbidden(value: false, warnOnFail: false); pawn.jobs.TryTakeOrderedJob(JobMaker.MakeJob(JobDefOf.Strip, stripTarg)); StrippableUtility.CheckSendStrippingImpactsGoodwillMessage(stripTarg.Thing); }), pawn, stripTarg) : new FloatMenuOption("CannotStrip".Translate(stripTarg.Thing.LabelCap, stripTarg.Thing) + ": " + "QuestRelated".Translate().CapitalizeFirst(), null)) : new FloatMenuOption("CannotStrip".Translate(stripTarg.Thing.LabelCap, stripTarg.Thing) + ": " + "NoPath".Translate().CapitalizeFirst(), null); opts.Add(item5); } ThingWithComps equipment; if (pawn.equipment != null) { equipment = null; List <Thing> thingList = c.GetThingList(pawn.Map); for (int i = 0; i < thingList.Count; i++) { if (thingList[i].TryGetComp <CompEquippable>() != null) { equipment = (ThingWithComps)thingList[i]; break; } } if (equipment != null) { string labelShort = equipment.LabelShort; FloatMenuOption item6; string cantReason; if (equipment.def.IsWeapon && pawn.WorkTagIsDisabled(WorkTags.Violent)) { item6 = new FloatMenuOption("CannotEquip".Translate(labelShort) + ": " + "IsIncapableOfViolenceLower".Translate(pawn.LabelShort, pawn), null); } else if (!pawn.CanReach(equipment, PathEndMode.ClosestTouch, Danger.Deadly)) { item6 = new FloatMenuOption("CannotEquip".Translate(labelShort) + ": " + "NoPath".Translate().CapitalizeFirst(), null); } else if (!pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation)) { item6 = new FloatMenuOption("CannotEquip".Translate(labelShort) + ": " + "Incapable".Translate(), null); } else if (equipment.IsBurning()) { item6 = new FloatMenuOption("CannotEquip".Translate(labelShort) + ": " + "BurningLower".Translate(), null); } else if (pawn.IsQuestLodger() && !EquipmentUtility.QuestLodgerCanEquip(equipment, pawn)) { item6 = new FloatMenuOption("CannotEquip".Translate(labelShort) + ": " + "QuestRelated".Translate().CapitalizeFirst(), null); } else if (!EquipmentUtility.CanEquip_NewTmp(equipment, pawn, out cantReason, checkBonded: false)) { item6 = new FloatMenuOption("CannotEquip".Translate(labelShort) + ": " + cantReason.CapitalizeFirst(), null); } else { string text3 = "Equip".Translate(labelShort); if (equipment.def.IsRangedWeapon && pawn.story != null && pawn.story.traits.HasTrait(TraitDefOf.Brawler)) { text3 += " " + "EquipWarningBrawler".Translate(); } if (EquipmentUtility.AlreadyBondedToWeapon(equipment, pawn)) { text3 += " " + "BladelinkAlreadyBonded".Translate(); TaggedString dialogText = "BladelinkAlreadyBondedDialog".Translate(pawn.Named("PAWN"), equipment.Named("WEAPON"), pawn.equipment.bondedWeapon.Named("BONDEDWEAPON")); item6 = FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(text3, delegate { Find.WindowStack.Add(new Dialog_MessageBox(dialogText)); }, MenuOptionPriority.High), pawn, equipment); } else { item6 = FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(text3, delegate { string personaWeaponConfirmationText = EquipmentUtility.GetPersonaWeaponConfirmationText(equipment, pawn); if (!personaWeaponConfirmationText.NullOrEmpty()) { Find.WindowStack.Add(new Dialog_MessageBox(personaWeaponConfirmationText, "Yes".Translate(), delegate { Equip(); }, "No".Translate())); } else { Equip(); } }, MenuOptionPriority.High), pawn, equipment); } } opts.Add(item6); } } foreach (Pair <CompReloadable, Thing> item15 in ReloadableUtility.FindPotentiallyReloadableGear(pawn, c.GetThingList(pawn.Map))) { CompReloadable comp = item15.First; Thing second = item15.Second; string text4 = "Reload".Translate(comp.parent.Named("GEAR"), NamedArgumentUtility.Named(comp.AmmoDef, "AMMO")) + " (" + comp.LabelRemaining + ")"; List <Thing> chosenAmmo; if (!pawn.CanReach(second, PathEndMode.ClosestTouch, Danger.Deadly)) { opts.Add(new FloatMenuOption(text4 + ": " + "NoPath".Translate().CapitalizeFirst(), null)); } else if (!comp.NeedsReload(allowForcedReload: true)) { opts.Add(new FloatMenuOption(text4 + ": " + "ReloadFull".Translate(), null)); } else if ((chosenAmmo = ReloadableUtility.FindEnoughAmmo(pawn, second.Position, comp, forceReload: true)) == null) { opts.Add(new FloatMenuOption(text4 + ": " + "ReloadNotEnough".Translate(), null)); } else { Action action4 = delegate { pawn.jobs.TryTakeOrderedJob(JobGiver_Reload.MakeReloadJob(comp, chosenAmmo)); }; opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(text4, action4), pawn, second)); } } if (pawn.apparel != null) { if (pawn.Map.thingGrid.ThingAt(c, ThingCategory.Item) is Apparel apparel) { string key = "CannotWear"; string key2 = "ForceWear"; if (apparel.def.apparel.LastLayer.IsUtilityLayer) { key = "CannotEquipApparel"; key2 = "ForceEquipApparel"; } string cantReason2; FloatMenuOption item7 = (!pawn.CanReach(apparel, PathEndMode.ClosestTouch, Danger.Deadly)) ? new FloatMenuOption(key.Translate(apparel.Label, apparel) + ": " + "NoPath".Translate().CapitalizeFirst(), null) : (apparel.IsBurning() ? new FloatMenuOption(key.Translate(apparel.Label, apparel) + ": " + "Burning".Translate(), null) : (pawn.apparel.WouldReplaceLockedApparel(apparel) ? new FloatMenuOption(key.Translate(apparel.Label, apparel) + ": " + "WouldReplaceLockedApparel".Translate().CapitalizeFirst(), null) : ((!ApparelUtility.HasPartsToWear(pawn, apparel.def)) ? new FloatMenuOption(key.Translate(apparel.Label, apparel) + ": " + "CannotWearBecauseOfMissingBodyParts".Translate(), null) : (EquipmentUtility.CanEquip_NewTmp(apparel, pawn, out cantReason2) ? FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(key2.Translate(apparel.LabelShort, apparel), delegate { apparel.SetForbidden(value: false); Job job13 = JobMaker.MakeJob(JobDefOf.Wear, apparel); pawn.jobs.TryTakeOrderedJob(job13); }, MenuOptionPriority.High), pawn, apparel) : new FloatMenuOption(key.Translate(apparel.Label, apparel) + ": " + cantReason2, null))))); opts.Add(item7); } } if (pawn.IsFormingCaravan()) { Thing item3 = c.GetFirstItem(pawn.Map); if (item3 != null && item3.def.EverHaulable && item3.def.canLoadIntoCaravan) { Pawn packTarget = GiveToPackAnimalUtility.UsablePackAnimalWithTheMostFreeSpace(pawn) ?? pawn; JobDef jobDef = (packTarget == pawn) ? JobDefOf.TakeInventory : JobDefOf.GiveToPackAnimal; if (!pawn.CanReach(item3, PathEndMode.ClosestTouch, Danger.Deadly)) { opts.Add(new FloatMenuOption("CannotLoadIntoCaravan".Translate(item3.Label, item3) + ": " + "NoPath".Translate().CapitalizeFirst(), null)); } else if (MassUtility.WillBeOverEncumberedAfterPickingUp(packTarget, item3, 1)) { opts.Add(new FloatMenuOption("CannotLoadIntoCaravan".Translate(item3.Label, item3) + ": " + "TooHeavy".Translate(), null)); } else { LordJob_FormAndSendCaravan lordJob = (LordJob_FormAndSendCaravan)pawn.GetLord().LordJob; float capacityLeft = CaravanFormingUtility.CapacityLeft(lordJob); if (item3.stackCount == 1) { float capacityLeft2 = capacityLeft - item3.GetStatValue(StatDefOf.Mass); opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(CaravanFormingUtility.AppendOverweightInfo("LoadIntoCaravan".Translate(item3.Label, item3), capacityLeft2), delegate { item3.SetForbidden(value: false, warnOnFail: false); Job job12 = JobMaker.MakeJob(jobDef, item3); job12.count = 1; job12.checkEncumbrance = (packTarget == pawn); pawn.jobs.TryTakeOrderedJob(job12); }, MenuOptionPriority.High), pawn, item3)); } else { if (MassUtility.WillBeOverEncumberedAfterPickingUp(packTarget, item3, item3.stackCount)) { opts.Add(new FloatMenuOption("CannotLoadIntoCaravanAll".Translate(item3.Label, item3) + ": " + "TooHeavy".Translate(), null)); } else { float capacityLeft3 = capacityLeft - (float)item3.stackCount * item3.GetStatValue(StatDefOf.Mass); opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(CaravanFormingUtility.AppendOverweightInfo("LoadIntoCaravanAll".Translate(item3.Label, item3), capacityLeft3), delegate { item3.SetForbidden(value: false, warnOnFail: false); Job job11 = JobMaker.MakeJob(jobDef, item3); job11.count = item3.stackCount; job11.checkEncumbrance = (packTarget == pawn); pawn.jobs.TryTakeOrderedJob(job11); }, MenuOptionPriority.High), pawn, item3)); } opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("LoadIntoCaravanSome".Translate(item3.LabelNoCount, item3), delegate { int to3 = Mathf.Min(MassUtility.CountToPickUpUntilOverEncumbered(packTarget, item3), item3.stackCount); Dialog_Slider window3 = new Dialog_Slider(delegate(int val) { float capacityLeft4 = capacityLeft - (float)val * item3.GetStatValue(StatDefOf.Mass); return(CaravanFormingUtility.AppendOverweightInfo(string.Format("LoadIntoCaravanCount".Translate(item3.LabelNoCount, item3), val), capacityLeft4)); }, 1, to3, delegate(int count) { item3.SetForbidden(value: false, warnOnFail: false); Job job10 = JobMaker.MakeJob(jobDef, item3); job10.count = count; job10.checkEncumbrance = (packTarget == pawn); pawn.jobs.TryTakeOrderedJob(job10); }); Find.WindowStack.Add(window3); }, MenuOptionPriority.High), pawn, item3)); } } } } if (!pawn.Map.IsPlayerHome && !pawn.IsFormingCaravan()) { Thing item2 = c.GetFirstItem(pawn.Map); if (item2 != null && item2.def.EverHaulable) { if (!pawn.CanReach(item2, PathEndMode.ClosestTouch, Danger.Deadly)) { opts.Add(new FloatMenuOption("CannotPickUp".Translate(item2.Label, item2) + ": " + "NoPath".Translate().CapitalizeFirst(), null)); } else if (MassUtility.WillBeOverEncumberedAfterPickingUp(pawn, item2, 1)) { opts.Add(new FloatMenuOption("CannotPickUp".Translate(item2.Label, item2) + ": " + "TooHeavy".Translate(), null)); } else if (item2.stackCount == 1) { opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("PickUp".Translate(item2.Label, item2), delegate { item2.SetForbidden(value: false, warnOnFail: false); Job job9 = JobMaker.MakeJob(JobDefOf.TakeInventory, item2); job9.count = 1; job9.checkEncumbrance = true; pawn.jobs.TryTakeOrderedJob(job9); }, MenuOptionPriority.High), pawn, item2)); } else { if (MassUtility.WillBeOverEncumberedAfterPickingUp(pawn, item2, item2.stackCount)) { opts.Add(new FloatMenuOption("CannotPickUpAll".Translate(item2.Label, item2) + ": " + "TooHeavy".Translate(), null)); } else { opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("PickUpAll".Translate(item2.Label, item2), delegate { item2.SetForbidden(value: false, warnOnFail: false); Job job8 = JobMaker.MakeJob(JobDefOf.TakeInventory, item2); job8.count = item2.stackCount; job8.checkEncumbrance = true; pawn.jobs.TryTakeOrderedJob(job8); }, MenuOptionPriority.High), pawn, item2)); } opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("PickUpSome".Translate(item2.LabelNoCount, item2), delegate { int to2 = Mathf.Min(MassUtility.CountToPickUpUntilOverEncumbered(pawn, item2), item2.stackCount); Dialog_Slider window2 = new Dialog_Slider("PickUpCount".Translate(item2.LabelNoCount, item2), 1, to2, delegate(int count) { item2.SetForbidden(value: false, warnOnFail: false); Job job7 = JobMaker.MakeJob(JobDefOf.TakeInventory, item2); job7.count = count; job7.checkEncumbrance = true; pawn.jobs.TryTakeOrderedJob(job7); }); Find.WindowStack.Add(window2); }, MenuOptionPriority.High), pawn, item2)); } } } if (!pawn.Map.IsPlayerHome && !pawn.IsFormingCaravan()) { Thing item = c.GetFirstItem(pawn.Map); if (item != null && item.def.EverHaulable) { Pawn bestPackAnimal = GiveToPackAnimalUtility.UsablePackAnimalWithTheMostFreeSpace(pawn); if (bestPackAnimal != null) { if (!pawn.CanReach(item, PathEndMode.ClosestTouch, Danger.Deadly)) { opts.Add(new FloatMenuOption("CannotGiveToPackAnimal".Translate(item.Label, item) + ": " + "NoPath".Translate().CapitalizeFirst(), null)); } else if (MassUtility.WillBeOverEncumberedAfterPickingUp(bestPackAnimal, item, 1)) { opts.Add(new FloatMenuOption("CannotGiveToPackAnimal".Translate(item.Label, item) + ": " + "TooHeavy".Translate(), null)); } else if (item.stackCount == 1) { opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("GiveToPackAnimal".Translate(item.Label, item), delegate { item.SetForbidden(value: false, warnOnFail: false); Job job6 = JobMaker.MakeJob(JobDefOf.GiveToPackAnimal, item); job6.count = 1; pawn.jobs.TryTakeOrderedJob(job6); }, MenuOptionPriority.High), pawn, item)); } else { if (MassUtility.WillBeOverEncumberedAfterPickingUp(bestPackAnimal, item, item.stackCount)) { opts.Add(new FloatMenuOption("CannotGiveToPackAnimalAll".Translate(item.Label, item) + ": " + "TooHeavy".Translate(), null)); } else { opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("GiveToPackAnimalAll".Translate(item.Label, item), delegate { item.SetForbidden(value: false, warnOnFail: false); Job job5 = JobMaker.MakeJob(JobDefOf.GiveToPackAnimal, item); job5.count = item.stackCount; pawn.jobs.TryTakeOrderedJob(job5); }, MenuOptionPriority.High), pawn, item)); } opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("GiveToPackAnimalSome".Translate(item.LabelNoCount, item), delegate { int to = Mathf.Min(MassUtility.CountToPickUpUntilOverEncumbered(bestPackAnimal, item), item.stackCount); Dialog_Slider window = new Dialog_Slider("GiveToPackAnimalCount".Translate(item.LabelNoCount, item), 1, to, delegate(int count) { item.SetForbidden(value: false, warnOnFail: false); Job job4 = JobMaker.MakeJob(JobDefOf.GiveToPackAnimal, item); job4.count = count; pawn.jobs.TryTakeOrderedJob(job4); }); Find.WindowStack.Add(window); }, MenuOptionPriority.High), pawn, item)); } } } } if (!pawn.Map.IsPlayerHome && pawn.Map.exitMapGrid.MapUsesExitGrid) { foreach (LocalTargetInfo item16 in GenUI.TargetsAt_NewTemp(clickPos, TargetingParameters.ForRescue(pawn), thingsOnly: true)) { Pawn p = (Pawn)item16.Thing; if (p.Faction == Faction.OfPlayer || p.IsPrisonerOfColony || CaravanUtility.ShouldAutoCapture(p, Faction.OfPlayer)) { IntVec3 exitSpot; if (!pawn.CanReach(p, PathEndMode.ClosestTouch, Danger.Deadly)) { opts.Add(new FloatMenuOption("CannotCarryToExit".Translate(p.Label, p) + ": " + "NoPath".Translate().CapitalizeFirst(), null)); } else if (!RCellFinder.TryFindBestExitSpot(pawn, out exitSpot)) { opts.Add(new FloatMenuOption("CannotCarryToExit".Translate(p.Label, p) + ": " + "NoPath".Translate().CapitalizeFirst(), null)); } else { TaggedString taggedString2 = (p.Faction == Faction.OfPlayer || p.IsPrisonerOfColony) ? "CarryToExit".Translate(p.Label, p) : "CarryToExitAndCapture".Translate(p.Label, p); opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(taggedString2, delegate { Job job3 = JobMaker.MakeJob(JobDefOf.CarryDownedPawnToExit, p, exitSpot); job3.count = 1; job3.failIfCantJoinOrCreateCaravan = true; pawn.jobs.TryTakeOrderedJob(job3); }, MenuOptionPriority.High), pawn, item16)); } } } } if (pawn.equipment != null && pawn.equipment.Primary != null && GenUI.TargetsAt_NewTemp(clickPos, TargetingParameters.ForSelf(pawn), thingsOnly: true).Any()) { if (pawn.IsQuestLodger() && !EquipmentUtility.QuestLodgerCanUnequip(pawn.equipment.Primary, pawn)) { opts.Add(new FloatMenuOption("CannotDrop".Translate(pawn.equipment.Primary.Label, pawn.equipment.Primary) + ": " + "QuestRelated".Translate().CapitalizeFirst(), null)); } else { Action action5 = delegate { pawn.jobs.TryTakeOrderedJob(JobMaker.MakeJob(JobDefOf.DropEquipment, pawn.equipment.Primary)); }; opts.Add(new FloatMenuOption("Drop".Translate(pawn.equipment.Primary.Label, pawn.equipment.Primary), action5, MenuOptionPriority.Default, null, pawn)); } } foreach (LocalTargetInfo item17 in GenUI.TargetsAt_NewTemp(clickPos, TargetingParameters.ForTrade(), thingsOnly: true)) { if (!pawn.CanReach(item17, PathEndMode.OnCell, Danger.Deadly)) { opts.Add(new FloatMenuOption("CannotTrade".Translate() + ": " + "NoPath".Translate().CapitalizeFirst(), null)); } else if (pawn.skills.GetSkill(SkillDefOf.Social).TotallyDisabled) { opts.Add(new FloatMenuOption("CannotPrioritizeWorkTypeDisabled".Translate(SkillDefOf.Social.LabelCap), null)); } else if (!pawn.CanTradeWith(((Pawn)item17.Thing).Faction, ((Pawn)item17.Thing).TraderKind)) { opts.Add(new FloatMenuOption("CannotTradeMissingTitleAbility".Translate(), null)); } else { Pawn pTarg = (Pawn)item17.Thing; Action action6 = delegate { Job job2 = JobMaker.MakeJob(JobDefOf.TradeWithPawn, pTarg); job2.playerForced = true; pawn.jobs.TryTakeOrderedJob(job2); PlayerKnowledgeDatabase.KnowledgeDemonstrated(ConceptDefOf.InteractingWithTraders, KnowledgeAmount.Total); }; string t2 = ""; if (pTarg.Faction != null) { t2 = " (" + pTarg.Faction.Name + ")"; } opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("TradeWith".Translate(pTarg.LabelShort + ", " + pTarg.TraderKind.label) + t2, action6, MenuOptionPriority.InitiateSocial, null, item17.Thing), pawn, pTarg)); } } foreach (LocalTargetInfo casket in GenUI.TargetsAt_NewTemp(clickPos, TargetingParameters.ForOpen(pawn), thingsOnly: true)) { if (!pawn.CanReach(casket, PathEndMode.OnCell, Danger.Deadly)) { opts.Add(new FloatMenuOption("CannotOpen".Translate(casket.Thing) + ": " + "NoPath".Translate().CapitalizeFirst(), null)); } else if (!pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation)) { opts.Add(new FloatMenuOption("CannotOpen".Translate(casket.Thing) + ": " + "Incapable".Translate(), null)); } else if (casket.Thing.Map.designationManager.DesignationOn(casket.Thing, DesignationDefOf.Open) == null) { opts.Add(FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("Open".Translate(casket.Thing), delegate { Job job = JobMaker.MakeJob(JobDefOf.Open, casket.Thing); job.ignoreDesignations = true; pawn.jobs.TryTakeOrderedJob(job); }, MenuOptionPriority.High), pawn, casket.Thing)); } } foreach (Thing item18 in pawn.Map.thingGrid.ThingsAt(c)) { foreach (FloatMenuOption floatMenuOption2 in item18.GetFloatMenuOptions(pawn)) { opts.Add(floatMenuOption2); } } void Equip() { equipment.SetForbidden(value: false); pawn.jobs.TryTakeOrderedJob(JobMaker.MakeJob(JobDefOf.Equip, equipment)); MoteMaker.MakeStaticMote(equipment.DrawPos, equipment.Map, ThingDefOf.Mote_FeedbackEquip); PlayerKnowledgeDatabase.KnowledgeDemonstrated(ConceptDefOf.EquippingWeapons, KnowledgeAmount.Total); } return(false); }
//原函数返回食物的优先选择程度值 static bool Prefix(ref float __result, Pawn eater, Thing foodSource, ThingDef foodDef, float dist, bool takingToInventory = false) { //Log.Message("{0} start analysis food {1}".Translate(eater.Label, foodDef.label)); float num = 300f; //基础数值 num -= dist; //距离 switch (foodDef.ingestible.preferability) //垃圾食物 { case FoodPreferability.NeverForNutrition: __result = -9999999f; return(false); case FoodPreferability.DesperateOnly: num -= 150f; break; case FoodPreferability.DesperateOnlyForHumanlikes: if (eater.RaceProps.Humanlike) { num -= 150f; } break; } CompRottable compRottable = foodSource.TryGetComp <CompRottable>();//变质组件 if (compRottable != null) { if (compRottable.Stage == RotStage.Dessicated)//已经变质风干的食物 { __result = -9999999f; return(false); } //会快要变质的新鲜食物 if (!takingToInventory && compRottable.Stage == RotStage.Fresh && compRottable.TicksUntilRotAtCurrentTemp < 30000) { num += 13.3f; } } bool badFood = false; if (eater.needs != null && eater.needs.mood != null) { float theXi = ModSetting.moodInfluenceX;//心情影响附加系数 //心情接近轻微崩溃阈值时增大心情影响附加系数 //心情在严重崩溃阈值以下 if (eater.needs.mood.CurLevel < eater.mindState.mentalBreaker.BreakThresholdExtreme) { theXi += 0.77f; } //心情在中度崩溃阈值以下 else if (eater.needs.mood.CurLevel < eater.mindState.mentalBreaker.BreakThresholdMajor) { theXi += 0.60f; } //心情在轻微崩溃阈值以下 else if (eater.needs.mood.CurLevel < eater.mindState.mentalBreaker.BreakThresholdMinor) { theXi += 0.43f; } //心情接近轻微崩溃阈值 else if (eater.needs.mood.CurLevel < eater.mindState.mentalBreaker.BreakThresholdMinor + 0.06f) { theXi += 0.25f; } //Log.Message("mood {0} theXi {1}".Translate(eater.needs.mood.CurLevel, theXi)); List <ThoughtDef> list = FoodUtility.ThoughtsFromIngesting(eater, foodSource, foodDef);//eater对食物的看法 for (int i = 0; i < list.Count; i++) { //计算出心情影响曲线函数值后乘以心情影响附加系数 num += FoodOptimalityEffectFromMoodCurve.Evaluate(list[i].stages[0].baseMoodEffect) * theXi; if (list[i].stages[0].baseMoodEffect < 0) { badFood = true; //掉心情的为“坏食物” } } } if (foodDef.ingestible != null) { if (eater.RaceProps.Humanlike) { num += foodDef.ingestible.optimalityOffsetHumanlikes;//食物类型人类接受程度 } else if (eater.RaceProps.Animal) { num += foodDef.ingestible.optimalityOffsetFeedingAnimals; } } if (!badFood && compRottable != null && eater.RaceProps.Humanlike)//不是“坏食物”并且会变质的,只对人类有效的附加随机值 { float randomt; if (!ModData.foodClassRandomVal.ContainsKey(foodDef.defName)) { randomt = Rand.Range(0f, ModSetting.randomLevel); ModData.foodClassRandomVal[foodDef.defName] = randomt; } else { randomt = ModData.foodClassRandomVal[foodDef.defName]; } float downXi = 1f; if (ModSetting.priorityRoomFood && ModData.findedInventoryFoodID == foodSource.GetUniqueLoadID()) { ModData.findedInventoryFoodID = null; downXi = 0.2f; } //Log.Message("downXi = " + downXi); //通过增加一个随机值来提高食物的优选程度 if (ModData.GetLastFoodType(eater) == foodDef.defName) { num += randomt * ModSetting.lastFoodInfluenceX * downXi; } else if (ModData.GetLlastFoodType(eater) == foodDef.defName) { num += randomt * ModSetting.llastFoodInfluenceX * downXi; } else { num += randomt * downXi; } } //Log.Warning("warn"); //Log.Message("food {0} val = {1}".Translate(foodSource.GetUniqueLoadID(), num)); __result = num; //函数返回值:优选程度 return(false); //跳过原函数 }
static bool Prefix(HungerCategory ___minCategory, float ___maxLevelPercentage, ref float __result, Pawn pawn) { //Log.Message("1"); Need_Food food = pawn.needs.food; if (food == null) { __result = 0f; return(false); } //Log.Message("2"); if (pawn.needs.food.CurCategory < HungerCategory.Starving && FoodUtility.ShouldBeFedBySomeone(pawn)) { __result = 0f; return(false); } //Log.Message("3"); if (food.CurCategory < ___minCategory) { __result = 0f; return(false); } //Log.Message("4"); if (food.CurLevelPercentage > ___maxLevelPercentage) { __result = 0f; return(false); } //Log.Message("5"); if (pawn.RaceProps.Humanlike) { if (food.CurLevelPercentage < pawn.RaceProps.FoodLevelPercentageWantEat + ModSetting.eatThreshold) { if (pawn.timetable == null) { if (food.CurLevelPercentage < pawn.RaceProps.FoodLevelPercentageWantEat) { __result = 9.5f; } else { __result = 0f; } return(false); } //Log.Message("6"); TimeAssignmentDef timeAssignmentDef = (pawn.timetable == null) ? TimeAssignmentDefOf.Anything : pawn.timetable.CurrentAssignment; if (timeAssignmentDef != TimeAssignmentDefDinner.DinnerDef) { //Log.Message("7"); if (pawn.timetable.GetAssignment((GenLocalDate.HourOfDay(pawn) + 1) % 24) == TimeAssignmentDefDinner.DinnerDef && food.CurLevelPercentage > pawn.RaceProps.FoodLevelPercentageWantEat * 0.48f) {//下一小时是dinner时间并且饥饿度百分比>0.45就不吃饭 __result = 0f; return(false); } if (pawn.timetable.GetAssignment((GenLocalDate.HourOfDay(pawn) + 2) % 24) == TimeAssignmentDefDinner.DinnerDef && food.CurLevelPercentage > pawn.RaceProps.FoodLevelPercentageWantEat * 0.8f) {//下2小时是dinner时间并且饥饿度百分比>0.8就不吃饭 __result = 0f; return(false); } //Log.Message("8"); if (food.CurLevelPercentage < pawn.RaceProps.FoodLevelPercentageWantEat) { __result = 9.5f; } else { __result = 0f; } return(false); } if (food.CurLevelPercentage < pawn.RaceProps.FoodLevelPercentageWantEat) { __result = 9.5f; } else { __result = 7.25f; } return(false); } else { __result = 0; } //Log.Message("{0} food priority = {1}".Translate(pawn.Label, __result)); } else if (food.CurLevelPercentage < pawn.RaceProps.FoodLevelPercentageWantEat) { __result = 9.5f; } else { __result = 0f; } return(false); }
/// <summary> /// Gets the best food source on the map for the given getter and eater pawns /// </summary> /// this function gets the best food source on the map for the given pawns, making sure to optimize for the case where /// a humanoid pawn can eat plants /// <param name="getter">The getter.</param> /// <param name="eater">The eater.</param> /// <param name="desperate">if set to <c>true</c> [desperate].</param> /// <param name="foodDef">The food definition.</param> /// <param name="maxPref">The maximum preference.</param> /// <param name="allowPlant">if set to <c>true</c> [allow plant].</param> /// <param name="allowDrug">if set to <c>true</c> [allow drug].</param> /// <param name="allowCorpse">if set to <c>true</c> [allow corpse].</param> /// <param name="allowDispenserFull">if set to <c>true</c> [allow dispenser full].</param> /// <param name="allowDispenserEmpty">if set to <c>true</c> [allow dispenser empty].</param> /// <param name="allowForbidden">if set to <c>true</c> [allow forbidden].</param> /// <param name="allowSociallyImproper">if set to <c>true</c> [allow socially improper].</param> /// <param name="allowHarvest">if set to <c>true</c> [allow harvest].</param> /// <param name="forceScanWholeMap">if set to <c>true</c> [force scan whole map].</param> /// <param name="ignoreReservations">if set to <c>true</c> [ignore reservations].</param> /// <param name="minPrefOverride">The minimum preference override.</param> /// <returns></returns> public static Thing BestFoodSourceOnMapOptimized( [NotNull] Pawn getter, [NotNull] Pawn eater, bool desperate, out ThingDef foodDef, FoodPreferability maxPref = FoodPreferability.MealLavish, bool allowPlant = true, bool allowDrug = true, bool allowCorpse = true, bool allowDispenserFull = true, bool allowDispenserEmpty = true, bool allowForbidden = false, bool allowSociallyImproper = false, bool allowHarvest = false, bool forceScanWholeMap = false, bool ignoreReservations = false, FoodPreferability minPrefOverride = FoodPreferability.Undefined) { foodDef = null; HungerCategory foodCurCategory = eater.needs.food.CurCategory; bool getterCanManipulate = getter.IsToolUser() && getter.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation); if (!getterCanManipulate && getter != eater) { Log.Error(getter + " tried to find food to bring to " + eater + " but " + getter + " is incapable of Manipulation."); return(null); } FoodPreferability minPref; if (minPrefOverride != FoodPreferability.Undefined) { minPref = minPrefOverride; } else if (!eater.NonHumanlikeOrWildMan()) //with the new patch, to 'recruit' sapient former humans pawns will need { if (!desperate) { if (foodCurCategory >= HungerCategory.UrgentlyHungry) { minPref = FoodPreferability.RawBad; } else { minPref = FoodPreferability.MealAwful; } } else { minPref = FoodPreferability.DesperateOnly; } } else { minPref = FoodPreferability.NeverForNutrition; } bool FoodValidator(Thing t) { if (allowDispenserFull && getterCanManipulate && t is Building_NutrientPasteDispenser nutrientPDispenser) { if (ThingDefOf.MealNutrientPaste.ingestible.preferability < minPref || ThingDefOf.MealNutrientPaste.ingestible.preferability > maxPref || !eater.WillEat(ThingDefOf.MealNutrientPaste, getter) || t.Faction != getter.Faction && t.Faction != getter.HostFaction || !allowForbidden && t.IsForbidden(getter) || !nutrientPDispenser.powerComp.PowerOn || !allowDispenserEmpty && !nutrientPDispenser.HasEnoughFeedstockInHoppers() || !t.InteractionCell.Standable(t.Map) || !IsFoodSourceOnMapSociallyProper(t, getter, eater, allowSociallyImproper) || !getter.Map.reachability.CanReachNonLocal(getter.Position, new TargetInfo(t.InteractionCell, t.Map), PathEndMode.OnCell, TraverseParms.For(getter, Danger.Some))) { return(false); } } else { FoodPreferability pref = GetAdjustedPreferability(eater, t); if (pref < minPref || pref > maxPref) { return(false); } if (!eater.WillEat(t, getter)) { return(false); } if (!t.def.IsNutritionGivingIngestible || !t.IngestibleNow) { return(false); } if (!allowCorpse && t is Corpse || !allowDrug && t.def.IsDrug || !allowForbidden && t.IsForbidden(getter) || !desperate && t.IsNotFresh() || t.IsDessicated() || !IsFoodSourceOnMapSociallyProper(t, getter, eater, allowSociallyImproper) || !getter.AnimalAwareOf(t) && !forceScanWholeMap || !ignoreReservations && !getter.CanReserve((LocalTargetInfo)t, 10, 1)) { return(false); } } return(true); } ThingRequest thingRequest; if (!CanEatPlants(eater, allowPlant, foodCurCategory)) { thingRequest = ThingRequest.ForGroup(ThingRequestGroup.FoodSourceNotPlantOrTree); } else { thingRequest = ThingRequest.ForGroup(ThingRequestGroup.FoodSource); } Thing bestThing; if (getter.IsHumanlike()) { //TODO split up search for hungry humanlike into 2 phases //whole map search for good food //small search for good plants bestThing = SpawnedFoodSearchInnerScan(eater, getter.Position, getter.Map.listerThings.ThingsMatching(thingRequest), PathEndMode.ClosestTouch, TraverseParms.For(getter), 9999f, FoodValidator); if (allowHarvest & getterCanManipulate) { int searchRegionsMax = !forceScanWholeMap || bestThing != null ? 30 : -1; bool HarvestValidator(Thing x) { var t = (Plant)x; if (!t.HarvestableNow) { return(false); } ThingDef harvestedThingDef = t.def.plant.harvestedThingDef; return(harvestedThingDef.IsNutritionGivingIngestible && eater.WillEat(harvestedThingDef, getter) && getter.CanReserve((LocalTargetInfo)t) && (allowForbidden || !t.IsForbidden(getter)) && (bestThing == null || FoodUtility.GetFinalIngestibleDef(bestThing) .ingestible.preferability < harvestedThingDef.ingestible.preferability)); } Thing foodSource = GenClosest.ClosestThingReachable(getter.Position, getter.Map, ThingRequest.ForGroup(ThingRequestGroup.HarvestablePlant), PathEndMode.Touch, TraverseParms.For(getter), 9999f, HarvestValidator, null, 0, searchRegionsMax); if (foodSource != null) { bestThing = foodSource; foodDef = FoodUtility.GetFinalIngestibleDef(foodSource, true); } } if (foodDef == null && bestThing != null) { foodDef = FoodUtility.GetFinalIngestibleDef(bestThing); } } else { int maxRegionsToScan = GetMaxRegionsToScan(getter, forceScanWholeMap, foodCurCategory); //this is where the lag comes from //humanlikes alwayse scan the whole map filtered.Clear(); foreach (Thing thing in GenRadial.RadialDistinctThingsAround(getter.Position, getter.Map, 2f, true)) { var pawn = thing as Pawn; if (pawn != null && pawn != getter && pawn.RaceProps.Animal && pawn.CurJob != null && pawn.CurJob.def == JobDefOf.Ingest && pawn.CurJob.GetTarget(TargetIndex.A).HasThing) { filtered.Add(pawn.CurJob.GetTarget(TargetIndex.A).Thing); } } bool ignoreEntirelyForbiddenRegions = !allowForbidden && ForbidUtility.CaresAboutForbidden(getter, true) && getter.playerSettings?.EffectiveAreaRestrictionInPawnCurrentMap != null; var validator = (Predicate <Thing>)(t => FoodValidator(t) && !filtered.Contains(t) && (t is Building_NutrientPasteDispenser || t.def.ingestible.preferability > FoodPreferability.DesperateOnly) && !t.IsNotFresh()); bestThing = GenClosest.ClosestThingReachable(getter.Position, getter.Map, thingRequest, PathEndMode.ClosestTouch, TraverseParms.For(getter), 9999f, validator, null, 0, maxRegionsToScan, false, RegionType.Set_Passable, ignoreEntirelyForbiddenRegions); filtered.Clear(); if (bestThing == null) { desperate = true; bestThing = GenClosest.ClosestThingReachable(getter.Position, getter.Map, thingRequest, PathEndMode.ClosestTouch, TraverseParms.For(getter), 9999f, FoodValidator, null, 0, maxRegionsToScan, false, RegionType.Set_Passable, ignoreEntirelyForbiddenRegions); } if (bestThing != null) { foodDef = FoodUtility.GetFinalIngestibleDef(bestThing); } } return(bestThing); }
// Token: 0x060000F1 RID: 241 RVA: 0x00008A58 File Offset: 0x00006C58 public static void TryFindBestFoodSourceFor_Prefix(ref bool __result, Pawn getter, Pawn eater, bool desperate, out Thing foodSource, out ThingDef foodDef, bool canRefillDispenser = true, bool canUseInventory = true, bool allowForbidden = false, bool allowCorpse = true, bool allowSociallyImproper = false, bool allowHarvest = false) { bool flag = getter.RaceProps.ToolUser && getter.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation); bool animal = getter.RaceProps.Animal; bool flag2 = !eater.IsTeetotaler(); Thing thing = null; if (canUseInventory) { bool flag3 = animal; if (flag3) { thing = FoodUtility.BestFoodInInventory(getter, eater, FoodPreferability.MealAwful, FoodPreferability.MealLavish, 0f, false); } } bool flag4 = getter == eater; ThingDef thingDef; Thing thing2 = FoodUtility.BestFoodSourceOnMap(getter, eater, desperate, out thingDef, FoodPreferability.MealLavish, flag4, flag2, allowCorpse, true, canRefillDispenser, allowForbidden, allowSociallyImproper, allowHarvest, false); bool flag5 = thing == null && thing2 == null; if (flag5) { bool flag6 = canUseInventory && animal; if (flag6) { FoodPreferability minFoodPref = FoodPreferability.DesperateOnly; bool allowDrug = flag2; thing = FoodUtility.BestFoodInInventory(getter, eater, minFoodPref, FoodPreferability.MealLavish, 0f, allowDrug); bool flag7 = thing != null; if (flag7) { foodSource = thing; foodDef = FoodUtility.GetFinalIngestibleDef(foodSource, false); __result = true; } } foodSource = null; foodDef = null; __result = false; } bool flag8 = thing == null && thing2 != null; if (flag8) { foodSource = thing2; foodDef = thingDef; __result = true; } ThingDef finalIngestibleDef = FoodUtility.GetFinalIngestibleDef(thing, false); bool flag9 = thing2 == null; if (flag9) { foodSource = thing; foodDef = finalIngestibleDef; __result = true; } float num = FoodUtility.FoodOptimality(eater, thing2, thingDef, (float)(getter.Position - thing2.Position).LengthManhattan, false); float num2 = FoodUtility.FoodOptimality(eater, thing, finalIngestibleDef, 0f, false); num2 -= 32f; bool flag10 = num > num2; if (flag10) { foodSource = thing2; foodDef = thingDef; __result = true; } foodSource = thing; foodDef = FoodUtility.GetFinalIngestibleDef(foodSource, false); __result = true; }
public float Ingested(Pawn ingester, float nutritionWanted) { if (Destroyed) { Log.Error(string.Concat(ingester, " ingested destroyed thing ", this)); return(0f); } if (!IngestibleNow) { Log.Error(string.Concat(ingester, " ingested IngestibleNow=false thing ", this)); return(0f); } ingester.mindState.lastIngestTick = Find.TickManager.TicksGame; if (ingester.needs.mood != null) { List <ThoughtDef> list = FoodUtility.ThoughtsFromIngesting(ingester, this, def); for (int i = 0; i < list.Count; i++) { ingester.needs.mood.thoughts.memories.TryGainMemory(list[i]); } } if (ingester.needs.drugsDesire != null) { ingester.needs.drugsDesire.Notify_IngestedDrug(this); } if (ingester.IsColonist && FoodUtility.IsHumanlikeMeatOrHumanlikeCorpse(this)) { TaleRecorder.RecordTale(TaleDefOf.AteRawHumanlikeMeat, ingester); } IngestedCalculateAmounts(ingester, nutritionWanted, out var numTaken, out var nutritionIngested); if (!ingester.Dead && ingester.needs.joy != null && Mathf.Abs(def.ingestible.joy) > 0.0001f && numTaken > 0) { JoyKindDef joyKind = ((def.ingestible.joyKind != null) ? def.ingestible.joyKind : JoyKindDefOf.Gluttonous); ingester.needs.joy.GainJoy((float)numTaken * def.ingestible.joy, joyKind); } if (ingester.RaceProps.Humanlike && Rand.Chance(this.GetStatValue(StatDefOf.FoodPoisonChanceFixedHuman) * FoodUtility.GetFoodPoisonChanceFactor(ingester))) { FoodUtility.AddFoodPoisoningHediff(ingester, this, FoodPoisonCause.DangerousFoodType); } bool flag = false; if (numTaken > 0) { if (stackCount == 0) { Log.Error(string.Concat(this, " stack count is 0.")); } if (numTaken == stackCount) { flag = true; } else { SplitOff(numTaken); } } PrePostIngested(ingester); if (flag) { ingester.carryTracker.innerContainer.Remove(this); } if (def.ingestible.outcomeDoers != null) { for (int j = 0; j < def.ingestible.outcomeDoers.Count; j++) { def.ingestible.outcomeDoers[j].DoIngestionOutcome(ingester, this); } } if (flag) { Destroy(); } PostIngested(ingester); return(nutritionIngested); }
public static void GenerateIngredients(Thing meal, Pawn eater) { CompIngredients compIngredients = meal.TryGetComp <CompIngredients>(); if (compIngredients != null) { // Stage 1: Generate random ingredients according to recipe // 1.1: Find recipe Func <RecipeDef, bool> validator = delegate(RecipeDef r) { bool directMatch = r.ProducedThingDef == meal.def; // Add compatibility for VCE Soups and Stews, whose original recipes only makes uncooked versions bool indirectMatch = (r.ProducedThingDef != null) ? (r.ProducedThingDef.ToString().Replace("Uncooked", "Cooked") == meal.def.ToString()) : false; return(directMatch || indirectMatch); }; RecipeDef mealRecipe = DefDatabase <RecipeDef> .AllDefsListForReading.First(validator); if (mealRecipe != null) { // 1.2: Generate ingredients from recipe List <string> ingredientCategoryOptions = new List <string>(); List <ThingDef> ingredientThingDefs = new List <ThingDef>(); // 1.3: Find ingredient categories and/or fixed thingDefs foreach (IngredientCount currIngredientCount in mealRecipe.ingredients) { if (currIngredientCount.filter.categories != null) { // Limit to 3 instances of an ingredient category int ingredientCatInstances = Math.Min((int)Math.Ceiling(currIngredientCount.count / 0.5f), 3); for (int i = 0; i < ingredientCatInstances; i++) { // Max limit of one condiment from Vanilla Cooking Expanded if (currIngredientCount.filter.categories.Contains("VCE_Condiments") && ingredientCategoryOptions.Contains("VCE_Condiments")) { continue; } else { ingredientCategoryOptions.Add(currIngredientCount.filter.categories.RandomElement()); } } } if (currIngredientCount.filter.thingDefs != null) { ingredientThingDefs.AddRange(currIngredientCount.filter.thingDefs); } } // 1.4: Generate random ingredient thingDefs based on categories, and add them to the existing list of fixed thingDefs // // By default, we ignore ingredients that are: // - Permanently disallowed by the Computer // - Disallowed specifically by the pawn's food restriction policy // - Humanlike and insect meats // - Fertilized eggs List <ThingDef> allowedIngredients = ThingCategoryDef.Named("FoodRaw").DescendantThingDefs.Where(x => !replimatRestrictions.disallowedIngredients.Contains(x) && eater.foodRestriction.CurrentFoodRestriction.Allows(x) && FoodUtility.GetMeatSourceCategory(x) != MeatSourceCategory.Humanlike && FoodUtility.GetMeatSourceCategory(x) != MeatSourceCategory.Insect && !x.thingCategories.Contains(ThingCategoryDefOf.EggsFertilized) ).ToList(); // Also check allowed condiments if Vanilla Cooking Expanded mod is active if (ModCompatibility.VanillaCookingExpandedIsActive) { allowedIngredients.AddRange(ThingCategoryDef.Named("VCE_Condiments").DescendantThingDefs.Where(x => !replimatRestrictions.disallowedIngredients.Contains(x) && eater.foodRestriction.CurrentFoodRestriction.Allows(x) )); } foreach (string currentIngredientCatOption in ingredientCategoryOptions) { List <ThingDef> ingredients = ThingCategoryDef.Named(currentIngredientCatOption).DescendantThingDefs.Where((ThingDef d) => allowedIngredients.Contains(d)).ToList(); ThingDef ingredient = (ingredients.Count > 0) ? ingredients.RandomElement() : null; // Avoid empty or duplicate ingredients if (ingredient != null && !ingredientThingDefs.Contains(ingredient)) { ingredientThingDefs.Add(ingredient); } } // Stage 2: Ideo replacements Ideo ideo = eater.Ideo; // 2.1 Human cannibalism for meals containing meat if (ideo?.HasHumanMeatEatingRequiredPrecept() == true) { List <ThingDef> existingMeats = ingredientThingDefs.FindAll((ThingDef d) => d.thingCategories.Contains(ThingCategoryDefOf.MeatRaw)); // Replace existing meats with a single instance of human meat if (existingMeats.Count > 0) { ingredientThingDefs = ingredientThingDefs.Except(existingMeats).ToList(); ingredientThingDefs.Add(ThingDefOf.Meat_Human); } } // 2.2 Insect meat loved for meals containing meat if (ideo?.HasPrecept(ReplimatDef.InsectMeatEating_Loved) == true) { List <ThingDef> existingMeats = ingredientThingDefs.FindAll((ThingDef d) => d.thingCategories.Contains(ThingCategoryDefOf.MeatRaw)); // Replace existing meats with a single instance of insect meat if (existingMeats.Count > 0) { ingredientThingDefs = ingredientThingDefs.Except(existingMeats).ToList(); ingredientThingDefs.Add(ReplimatDef.Meat_Megaspider); } } // 2.3 Fungus preferred for meals containing raw plant food if (ideo?.HasPrecept(ReplimatDef.FungusEating_Preferred) == true) { List <ThingDef> existingPlantFoodRaws = ingredientThingDefs.FindAll((ThingDef d) => d.thingCategories.Contains(ThingCategoryDefOf.PlantFoodRaw) || d.ingestible.foodType == FoodTypeFlags.VegetableOrFruit); // todo - fix // Replace existing raw plant food with a single instance of fungus if (existingPlantFoodRaws.Count > 0) { ingredientThingDefs = ingredientThingDefs.Except(existingPlantFoodRaws).ToList(); ingredientThingDefs.Add(ReplimatDef.RawFungus); } } // 2.4 Fungus despised for meals containing raw plant food if (ideo?.HasPrecept(ReplimatDef.FungusEating_Despised) == true) { ingredientThingDefs.Remove(ReplimatDef.RawFungus); } // Stage 3: Assign final ingredients to meal compIngredients.ingredients.AddRange(ingredientThingDefs); } } }
static void Postfix(Job __result, Thing ingestible, Pawn pawn) { //used to be a prefix, but something prevented new job from being taken if (!Settings.pick_proper_amount) { return; } __result.count = Mathf.Min(__result.count, FoodUtility.WillIngestStackCountOf(pawn, ingestible.def, FoodUtility.GetNutrition(ingestible, ingestible.def))); }
private static void _Draw(Rect rect, Pawn pawn) { Policy policy = pawn.GetPolicyAssignedTo(); Text.Anchor = TextAnchor.MiddleLeft; // -------------------- Top left -------------------------- Rect topRect = new Rect(rect.position.x + horizontalMargin, rect.position.y + verticalMargin, topRectSize.x - horizontalMargin * 2, topRectSize.y); Listing_Standard listing = new Listing_Standard(); listing.Begin(topRect); listing.ColumnWidth = topRect.width / 2; listing.verticalSpacing = 4; Text.Anchor = TextAnchor.MiddleCenter; //listingLeft.Label("PawnPolicyCard_Policy".Translate()); string readable = pawn.GetPolicyAssignedTo().label; var flag = pawn.HasHardcodedPolicy(); if (flag) { listing.Label(string.Format("{0} ({1})", "PawnPolicyCard_CannotSetPolicy".Translate(), policy.label)); } else { if (listing.ButtonTextLabeled("PawnPolicyCard_Policy".Translate(), readable)) { var floatOptions = new List <FloatMenuOption>(); var policies = Policies.GetAllPoliciesForPawn(pawn) #if !DEBUG .Where(arg => arg.Visible) #endif ; foreach (var item in policies) { floatOptions.Add(new FloatMenuOption(item.label, () => WorldDataStore_PawnPolicies.SetPolicyForPawn(pawn, item), MenuOptionPriority.Default, delegate { //TODO: policy tooltip })); } Find.WindowStack.Add(new FloatMenu(floatOptions)); } } listing.NewColumn(); // -------------------- Top right -------------------------- Thing bestFood; ThingDef bestFoodDef; string bestFoodInfo; if (FoodUtility.TryFindBestFoodSourceFor(pawn, pawn, true, out bestFood, out bestFoodDef)) { bestFoodInfo = bestFood.Label; if (pawn.inventory != null && pawn.inventory.innerContainer.Contains(bestFood)) { bestFoodInfo += " " + "PawnPolicyCard_Inventory".Translate(); } } else { bestFoodInfo = "PawnPolicyCard_NoFoodFound".Translate(); } listing.Label(string.Format("PawnPolicyCard_CurrentBestFood".Translate(), bestFoodInfo)); //var mask = PawnMask.MakeCompleteMaskFromPawn(pawn); //listing.Label(mask.ToString()); listing.End(); // -------------------- Top end -------------------------- Widgets.DrawLineHorizontal(rect.x + horizontalMargin, rect.y + topRectSize.y - verticalMargin, rect.width - horizontalMargin * 2); // ---------------------------- Middle ------------------------------- Rect policyRectMiddle = new Rect(rect.x + horizontalMargin, rect.y + topRectSize.y, middleRectSize.x - horizontalMargin, middleRectSize.y); // ---------------------------- Middle left ------------------------------- Listing_Standard listingMiddleLeft = new Listing_Standard(GameFont.Small); listingMiddleLeft.Begin(policyRectMiddle.LeftPart(middleLeftColumnSize / policyRectMiddle.width)); listingMiddleLeft.verticalSpacing = verticalMargin; //listingMiddleLeft.ColumnWidth = middleLeftColumnSize; //Rect policyRectMiddleLeft = policyRectMiddle.LeftHalf(); //string policyDesc = ""; //Rect policyRectMiddleLeft_inner = new Rect(0, 0, policyRectMiddleLeft.width, policyRectMiddleLeft.height * 2); //Widgets.BeginScrollView(policyRectMiddleLeft, ref scrollposition, policyRectMiddleLeft_inner); //var listingMiddleLeft_inner = new Listing_Standard(policyRectMiddleLeft); Text.Anchor = TextAnchor.UpperLeft; if (policy.description != null && policy.description.Any()) { listingMiddleLeft.Label(policy.description); } else { listingMiddleLeft.Label("(No description)"); //TODO: lang file } { var font = Text.Font; Text.Font = GameFont.Tiny; listingMiddleLeft.Label(policy.GetDietForPawn(pawn).ToString()); Text.Font = font; } listingMiddleLeft.End(); //Widgets.EndScrollView(); // ----------------------------- Middle right ---------------------------------- var rectMiddleRight = policyRectMiddle.RightPart((middleRightColumnSize - horizontalMargin * 4) / policyRectMiddle.width); rectMiddleRight.x -= horizontalMargin; Listing_Standard listingMiddleRight = new Listing_Standard(); listingMiddleRight.Begin(rectMiddleRight); listingMiddleRight.verticalSpacing = verticalMargin; if (!flag) { Text.Anchor = TextAnchor.MiddleCenter; listingMiddleRight.verticalSpacing = verticalMargin; if (listingMiddleRight.ButtonText("PawnPolicyCard_ResetPolicy".Translate())) { WorldDataStore_PawnPolicies.SetPolicyForPawn(pawn, null); } //if (listingRight.ButtonText(string.Format("PawnPolicyCard_AssignToAll".Translate(), pawn.def.label))) //{ // WorldDataStore_PawnPolicies.AssignToAllPawnsOfRaces(policy,pawn.def); //} { string targetGroupName = ""; Func <Pawn, bool> validator = null; if (pawn.IsColonist) { validator = (arg) => arg.IsColonist; targetGroupName = "colonists".Translate(); } else if (pawn.IsPrisonerOfColony) { validator = (arg) => arg.IsPrisonerOfColony; targetGroupName = "prisoners".Translate(); } //TODO: setter for rescued pawns //else if (pawn.HostFaction != null && pawn.HostFaction.IsPlayer) //{ // validator = (arg) => (pawn.HostFaction != null && pawn.HostFaction.IsPlayer); // targetGroupName = "guests".Translate(); //} else if (pawn.Faction.IsPlayer && pawn.RaceProps.Animal) { validator = (arg) => (pawn.Faction.IsPlayer && arg.RaceProps.Animal && arg.def == pawn.def); targetGroupName = pawn.def.label; } if (validator != null) { if (listingMiddleRight.ButtonText(string.Format("PawnPolicyCard_AssignToAllOnMap".Translate(), targetGroupName))) { WorldDataStore_PawnPolicies.AssignToAllPawnsMatchingOnMap(policy, validator); } if (listingMiddleRight.ButtonText(string.Format("PawnPolicyCard_ResetAllOnMap".Translate(), targetGroupName))) { WorldDataStore_PawnPolicies.AssignToAllPawnsMatchingOnMap(null, validator); } } } } listingMiddleRight.End(); }
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); }