public static Job FeedJob(Pawn pawn) { Need_Blood blood = pawn.needs.TryGetNeed <Need_Blood>(); if (blood == null) { return(null); } bool desperate = blood.CurCategory == HungerCategory.Starving; bool isHuntHuman = blood.preferredFeedMode == PreferredFeedMode.HumanoidLethal || blood.preferredFeedMode == PreferredFeedMode.HumanoidNonLethal; bool isHuntLethal = blood.preferredFeedMode == PreferredFeedMode.HumanoidLethal || blood.preferredFeedMode == PreferredFeedMode.AnimalLethal; Thing thing; ThingDef def; if (!BloodUtility.TryFindBestBloodSourceFor(pawn, pawn, desperate, out thing, out def)) { return(null); } if (thing != null && thing != pawn && thing.Spawned) { Pawn pawn2 = thing as Pawn; if (pawn2 != null) { return(new Job(VampDefOf.ROMV_Feed, pawn2) { killIncappedTarget = isHuntLethal }); } return(new Job(VampDefOf.ROMV_ConsumeBlood, thing) { count = BloodUtility.WillConsumeStackCountOf(pawn, def) }); } return(null); }
// RimWorld.FoodUtility public static int WillConsumeStackCountOf(Pawn ingester, ThingDef def) { int num = Mathf.Min(10, BloodUtility.StackCountForBlood(def, ingester.VampComp().BloodPool.BloodWanted)); if (num < 1) { num = 1; } return(num); }
// RimWorld.FoodUtility public static Thing BestBloodSourceOnMap(Pawn getter, Pawn eater, bool desperate, BloodPreferabilty maxPref = BloodPreferabilty.Highblood, bool allowForbidden = false) { bool getterCanManipulate = getter.RaceProps.ToolUser && getter.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation); if (!getterCanManipulate && getter != eater) { Log.Error(string.Concat(new object[] { getter, " tried to find blood to bring to ", eater, " but ", getter, " is incapable of Manipulation." })); return(null); } BloodPreferabilty minPref = eater?.VampComp()?.Bloodline?.minBloodPref ?? BloodPreferabilty.Any; if (desperate) { minPref = eater?.VampComp()?.Bloodline?.desperateBloodPref ?? BloodPreferabilty.Any; } Predicate <Thing> foodValidator = delegate(Thing t) { if (t.TryGetComp <CompBloodItem>() is CompBloodItem bl) { if (!allowForbidden && t.IsForbidden(getter)) { return(false); } if ((int)bl.Props.bloodType < (int)minPref) { return(false); } if ((int)bl.Props.bloodType > (int)maxPref) { return(false); } if (t.IsBurning() || (!desperate && t.IsNotFresh()) || !getter.CanReserve(t, 1, -1, null, false)) { return(false); } return(true); } return(false); }; Thing thing; Predicate <Thing> validator = foodValidator; thing = BloodUtility.SpawnedBloodItemScan(eater, getter.Position, getter.Map.listerThings.ThingsInGroup(ThingRequestGroup.FoodSourceNotPlantOrTree), PathEndMode.ClosestTouch, TraverseParms.For(getter, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, validator); return(thing); }
// RimWorld.FoodUtility private static Pawn BestPawnToHuntForVampire(Pawn predator, bool desperate = false) { //if (predator.meleeVerbs.TryGetMeleeVerb() == null) //{ // return null; //} //bool flag = false; //float summaryHealthPercent = predator.health.summaryHealth.SummaryHealthPercent; //if (summaryHealthPercent < 0.25f) //{ // flag = true; //} List <Pawn> allPawnsSpawned = predator.Map.mapPawns.AllPawnsSpawned; Pawn pawn = null; float num = 0f; bool tutorialMode = TutorSystem.TutorialMode; for (int i = 0; i < allPawnsSpawned.Count; i++) { Pawn pawn2 = allPawnsSpawned[i]; if (predator.GetRoom(RegionType.Set_Passable) == pawn2.GetRoom(RegionType.Set_Passable)) { if (predator != pawn2) { if (BloodUtility.IsAcceptableVictimFor(predator, pawn2, desperate)) { if (predator.CanReach(pawn2, PathEndMode.ClosestTouch, Danger.Deadly, false, TraverseMode.ByPawn)) { if (!pawn2.IsForbidden(predator)) { if (!tutorialMode || pawn2.Faction != Faction.OfPlayer) { float preyScoreFor = FoodUtility.GetPreyScoreFor(predator, pawn2); if (preyScoreFor > num || pawn == null) { num = preyScoreFor; pawn = pawn2; } } } } } } } } return(pawn); }
// RimWorld.FoodUtility public static bool TryFindBestBloodSourceFor(Pawn getter, Pawn eater, bool desperate, out Thing bloodSource, out ThingDef bloodDef, bool canUseInventory = true, bool allowForbidden = false) { bool flag = getter.RaceProps.ToolUser && getter.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation); Thing thing = null; if (canUseInventory) { if (flag) { thing = BloodUtility.BestBloodInInventory(getter, null, 0); } if (thing != null) { if (getter.Faction != Faction.OfPlayer) { bloodSource = thing; bloodDef = thing.def; return(true); } CompRottable compRottable = thing.TryGetComp <CompRottable>(); if (compRottable != null && compRottable.Stage == RotStage.Fresh && compRottable.TicksUntilRotAtCurrentTemp < 30000) { bloodSource = thing; bloodDef = thing.def; return(true); } } } Thing thing2 = BloodUtility.BestBloodSourceOnMap(getter, eater, desperate, BloodPreferabilty.Highblood, allowForbidden); if (thing == null && thing2 == null) { if (canUseInventory && flag) { thing = BloodUtility.BestBloodInInventory(getter, null, 0); if (thing != null) { bloodSource = thing; bloodDef = thing.def; return(true); } } if (thing2 == null && getter == eater) { Pawn pawn = BloodUtility.BestPawnToHuntForVampire(getter); if (pawn != null) { bloodSource = pawn; bloodDef = pawn.def; return(true); } } bloodSource = null; bloodDef = null; return(false); } if (thing == null && thing2 != null) { bloodSource = thing2; bloodDef = thing2.def; return(true); } if (thing2 == null && thing != null) { bloodSource = thing; bloodDef = thing.def; return(true); } bloodSource = thing; bloodDef = thing.def; return(false); }
// RimWorld.FloatMenuMakerMap private static void Vamp_FloatMenus_Consume(Vector3 clickPos, Pawn pawn, ref List <FloatMenuOption> opts) { IntVec3 c = IntVec3.FromVector3(clickPos); CompVampire selVampComp = pawn.VampComp(); bool pawnIsVampire = pawn.IsVampire(); if (selVampComp != null && pawnIsVampire) { //Hide food consumption from menus. Thing food = c.GetThingList(pawn.Map) .FirstOrDefault(t => t.GetType() != typeof(Pawn) && t?.def?.ingestible != null); if (food != null) { //string text = (!food.def.ingestible.ingestCommandString.NullOrEmpty()) ? string.Format(food.def.ingestible.ingestCommandString, food.LabelShort) : ((string)"ConsumeThing".Translate(food.LabelShort, food)); string text = ""; if (food?.def?.ingestible?.ingestCommandString == null || food.def.ingestible.ingestCommandString == "") { text = ((string)"ConsumeThing".Translate(food.LabelShort, food)); } else { text = string.Format(food.def.ingestible.ingestCommandString, food.LabelShort); } FloatMenuOption o = opts.FirstOrDefault(x => x.Label.Contains(text)); if (o != null) { opts.Remove(o); } } //Hide corpse consumption from menus. Thing corpse = c.GetThingList(pawn.Map).FirstOrDefault(t => t is Corpse); if (corpse != null) { string text; if (corpse.def.ingestible.ingestCommandString.NullOrEmpty()) { text = "ConsumeThing".Translate(new object[] { corpse.LabelShort }); } else { text = string.Format(corpse.def.ingestible.ingestCommandString, corpse.LabelShort); } FloatMenuOption o = opts.FirstOrDefault(x => x.Label.Contains(text)); if (o != null) { opts.Remove(o); } } //Add blood consumption Thing bloodItem = c.GetThingList(pawn.Map) .FirstOrDefault(t => t.def.GetCompProperties <CompProperties_BloodItem>() != null); if (bloodItem != null) { string text = ""; if (bloodItem.def.ingestible.ingestCommandString.NullOrEmpty()) { text = "ConsumeThing".Translate(new object[] { bloodItem.LabelShort }); } else { text = string.Format(bloodItem.def.ingestible.ingestCommandString, bloodItem.LabelShort); } if (!bloodItem.IsSociallyProper(pawn)) { text = text + " (" + "ReservedForPrisoners".Translate() + ")"; } FloatMenuOption item5; if (bloodItem.def.IsPleasureDrug && pawn.IsTeetotaler()) { item5 = new FloatMenuOption(text + " (" + TraitDefOf.DrugDesire.DataAtDegree(-1).label + ")", null); } else if (!pawn.CanReach(bloodItem, PathEndMode.OnCell, Danger.Deadly)) { item5 = new FloatMenuOption(text + " (" + "NoPath".Translate() + ")", null); } else { MenuOptionPriority priority = !(bloodItem is Corpse) ? MenuOptionPriority.Default : MenuOptionPriority.Low; item5 = FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(text, delegate { bloodItem.SetForbidden(false); Job job = new Job(VampDefOf.ROMV_ConsumeBlood, bloodItem); job.count = BloodUtility.WillConsumeStackCountOf(pawn, bloodItem.def); pawn.jobs.TryTakeOrderedJob(job); }, priority), pawn, bloodItem); } opts.Add(item5); } } }