private void DrawRequirementRow(ThingDefCount thingCount, Rect listHolder, int listPos, bool canDrawToolTips) { float yPosition = listPos * listElementRectHeight; Rect highlightRect = new Rect(0f, yPosition, listHolder.width, listElementRectHeight); bool rowShouldBeRed = Find.CurrentMap.GetCountOnMapDifference(thingCount) > 0; // Do tool tips and background. if (listPos % 2 == 0 && rowShouldBeRed) { GUI.DrawTexture(highlightRect, redAltTexture); } else if (listPos % 2 == 0) { Widgets.DrawAltRect(highlightRect); } if (canDrawToolTips) { TooltipHandler.TipRegion(highlightRect, new TipSignal(GetReqRowTooltip(thingCount))); } // Draw thingdef icon Rect mainElementsRect = highlightRect.WidthContractedBy(listElementsMargin); Rect iconRect = new Rect(mainElementsRect.x, yPosition, listElementRectHeight, listElementRectHeight); Widgets.ThingIcon(iconRect, thingCount.ThingDef); // Do text labels Rect labelsRect = new Rect(listElementRectHeight, yPosition, listHolder.width - listElementRectHeight, listElementRectHeight).WidthContractedBy(2 * listElementsMargin); if (rowShouldBeRed) { GUI.color = Color.red; } DoTextLabel(labelsRect, thingCount.ThingDef.LabelCap); DoNumberLabel(labelsRect, thingCount); GUI.color = Color.white; }
private float GetFillFraction(ThingDefCount tc) { float needed = tc.Count; float available = Find.CurrentMap.resourceCounter.GetCount(tc.ThingDef); return(Mathf.Clamp(available / needed, 0, 1)); }
private void DoRowTooltip(Rect tooltipRegion, ThingDefCount count, int difference) { int present = -difference + count.Count; string tipLabel = (modInstance.CountInStorage) ? "ReqRowTip_Storage".Translate(count.Count, present) : "ReqRowTip_All".Translate(count.Count, present); TooltipHandler.TipRegion(tooltipRegion, new TipSignal(tipLabel)); }
private void DrawToolTip() { List <ThingDefCount> trackedRequirements = Tracker.TotalCosts; float maxCountWidth = (trackedRequirements.Count > 0) ? Text.CalcSize(trackedRequirements[0].Count.ToString()).x : 0f; float workLeftWidth = Text.CalcSize(Tracker.WorkLeft.ToString()).x; float toolTipWidth = Mathf.Max(maxCountWidth, workLeftWidth); toolTipWidth += (listElementsMargin * 2 + xOffsetFromContainer * 2) + listElementsHeight; float toolTipHeight = (trackedRequirements.Count + 1) * listElementsHeight; toolTipHeight += listElementsMargin * 2; Rect tooltipRect = new Rect(0f, 0f, toolTipWidth, toolTipHeight); PositionTipRect(ref tooltipRect); if (modInstance.ClampTipToScreen) { tooltipRect = tooltipRect.ClampRectInRect(new Rect(0, 0, UI.screenWidth, UI.screenHeight).ContractedBy(modInstance.TooltipClampMargin)); } Rect innerTipRect = tooltipRect.ContractedBy(listElementsMargin).WidthContractedBy(xOffsetFromContainer); int indexOffset = 0; if (Find.Selector.NumSelected > 0) { DrawTrackingModeIndicator(innerTipRect, indexOffset); indexOffset = 1; } for (int i = 0; i < trackedRequirements.Count; i++) { ThingDefCount count = trackedRequirements[i]; DrawRequirementRow(count, innerTipRect, i + indexOffset); } DrawWorkLeftRow(innerTipRect, trackedRequirements.Count + indexOffset); }
public List <ThingDefCount> GetRequirementsTotals(TotalsSortModes modeToSortCountsBy = TotalsSortModes.Absolute, bool ascending = false) { if (!cachedTotalsAreUpdated) { List <ThingDefCount> protoRequirementsTotals = new List <ThingDefCount>(); foreach (IConstructible tracked in trackedConstructibles) { foreach (ThingDefCount requirements in tracked.GetMaterialsNeededSafely()) { int thingCountWithSameThingDefIndex = protoRequirementsTotals.FindIndex(x => x.ThingDef == requirements.ThingDef); if (thingCountWithSameThingDefIndex == -1) { protoRequirementsTotals.Add(requirements); } else { ThingDefCount tcWithSameThingDef = protoRequirementsTotals[thingCountWithSameThingDefIndex]; protoRequirementsTotals[thingCountWithSameThingDefIndex] = BlueprintReportUtility.AddThingCounts(tcWithSameThingDef, requirements); } } } cachedRequirementsTotals = protoRequirementsTotals; cachedTotalsAreUpdated = true; } SortTotalsIfNecessary(modeToSortCountsBy, ascending); return(cachedRequirementsTotals); }
private string GetReqRowTooltip(ThingDefCount rowTC) { // First line string tipString = "ReqRowTipLine1".Translate(new object[] { rowTC.Count, rowTC.ThingDef.label }); // Second line int amountPresent; int difference = Find.CurrentMap.GetCountOnMapDifference(rowTC, out amountPresent); if (difference < 0) { tipString += "ReqRowTipLine2Excess".Translate(new object[] { -difference, rowTC.ThingDef.label, amountPresent }); } else if (difference > 0) { tipString += "ReqRowTipLine2Lack".Translate(new object[] { difference, rowTC.ThingDef.label, amountPresent }); } return(tipString); }
// Takes two ThingCounts and returns a new one with the counts added public static ThingDefCount AddThingCounts(ThingDefCount tc1, ThingDefCount tc2) { if (tc1.ThingDef != tc2.ThingDef) { Log.Warning("Added two ThingCounts of different ThingDefs. New ThingCount will have ThingDef of first ThingCount."); } return(new ThingDefCount(tc1.ThingDef, tc1.Count + tc2.Count)); }
// Get difference between count and the number present on map public static int GetCountOnMapDifference(this Map map, ThingDefCount count) { if (count.ThingDef.IsBlueprint) { return(0); } return(count.Count - map.GetCountAll(count.ThingDef)); }
public static int GetCountInStorageDifference(this Map map, ThingDefCount count) { if (count.ThingDef.IsBlueprint) { return(0); } return(count.Count - map.resourceCounter.GetCount(count.ThingDef)); }
public static ThingDefCount AddThingDefCounts(ThingDefCount lhs, ThingDefCount rhs) { if (lhs.ThingDef != rhs.ThingDef) { Log.Warning("Adding ThingDefCounts with different ThingDefs - New ThingDefCount will have ThingDef of first ThingDefCount"); } return(new ThingDefCount(lhs.ThingDef, lhs.Count + rhs.Count)); }
// Same as above, but can pass amount present on map through out paramater. public static int GetCountOnMapDifference(this Map map, ThingDefCount count, out int numOnMap) { if (count.ThingDef.IsBlueprint) { numOnMap = count.Count; return(0); } numOnMap = map.GetCountAll(count.ThingDef); return(count.Count - numOnMap); }
private void DoNumberLabel(Rect rowRect, ThingDefCount tc) { Rect textRect = new Rect(rowRect.x + rowRect.width - largestNumberWidth, rowRect.y, largestNumberWidth, rowRect.height); switch (currentSortMode) { case TotalsSortModes.Absolute: Widgets.Label(textRect, tc.Count.ToString()); break; case TotalsSortModes.Difference: string strToDisplay = Find.CurrentMap.GetCountOnMapDifference(tc).ToStringWithSign(); Widgets.Label(textRect, strToDisplay); break; } }
public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false) { if (t is ThingWithComps thing) { if (!pawn.Dead && !pawn.Downed && !pawn.IsBurning() && !thing.Destroyed && !thing.IsBurning() && pawn.CanReserveAndReach(thing, PathEndMode.InteractionCell, Danger.Deadly)) { CompUpgrade comp = null; foreach (var c in thing.AllComps.OfType <CompUpgrade>()) { if (c.beginUpgrade) { comp = c; break; } } if (comp == null) { return(null); } ThingDefCount needThingCount = comp.TryGetOneMissingMaterial(); if (!comp.PawnMeetsSkillRequirement(pawn)) { JobFailReason.Is("ConstructionSkillTooLow"); return(null); } if (needThingCount.Count > 0) { Thing foundRes = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForDef(needThingCount.ThingDef), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly), 9999f, (Thing r) => { return(r.def == needThingCount.ThingDef && !r.IsForbidden(pawn) && pawn.CanReserve(r)); }); if (foundRes == null) { JobFailReason.Is("Upgrade_missingMaterial"); return(null); } } return(new Job(PESDefOf.PES_Job_InstallUpgrade, t)); } } return(null); }
private void DrawRequirementRow(ThingDefCount count, Rect toolTipRect, int posInList) { Rect rowRect = new Rect(toolTipRect.x, toolTipRect.y + posInList * listElementsHeight, toolTipRect.width, listElementsHeight); Rect iconRect = new Rect(rowRect.x, rowRect.y, listElementsHeight, listElementsHeight).ContractedBy(1.5f); Widgets.ThingIcon(iconRect, count.ThingDef); Rect labelRect = new Rect(rowRect.x + listElementsHeight, rowRect.y, rowRect.width - listElementsHeight, rowRect.height); Text.Anchor = TextAnchor.MiddleLeft; int difference = (modInstance.CountInStorage) ? Find.CurrentMap.GetCountInStorageDifference(count) : Find.CurrentMap.GetCountOnMapDifference(count, modInstance.CountForbidden); if (difference > 0) { GUI.color = Color.red; } Widgets.Label(labelRect, count.Count.ToString()); GUI.color = Color.white; Text.Anchor = TextAnchor.UpperLeft; if (modInstance.ShowRowToolTips) { DoRowTooltip(rowRect, count, difference); } }
private static bool Prefix(Pawn_InventoryTracker __instance, ref ThingCount __result) { if (__instance.innerContainer.Count == 0) { __result = default; return(false); } tmpDrugsToKeep.Clear(); if (__instance.pawn.drugs?.CurrentPolicy != null) { var currentPolicy = __instance.pawn.drugs.CurrentPolicy; for (var i = 0; i < currentPolicy.Count; i++) { if (currentPolicy[i].takeToInventory > 0) { tmpDrugsToKeep.Add(new ThingDefCount(currentPolicy[i].drug, currentPolicy[i].takeToInventory)); } } } Thing bestInstrument = null; if (!__instance.pawn.NonHumanlikeOrWildMan() && !__instance.pawn.WorkTagIsDisabled(WorkTags.Artistic)) { var artSkill = __instance.pawn.skills.GetSkill(SkillDefOf.Artistic).levelInt; IEnumerable <Thing> heldInstruments = __instance.innerContainer .Where(PerformanceManager.IsInstrument) .Where(x => !x.TryGetComp <CompMusicalInstrument>().Props.isBuilding) .OrderByDescending(x => x.TryGetComp <CompMusicalInstrument>().WeightedSuitability(artSkill)); if (heldInstruments.Any()) { bestInstrument = heldInstruments.FirstOrDefault(); } } if (tmpDrugsToKeep.Any() || bestInstrument != null) { foreach (var thing in __instance.innerContainer) { if (thing.def.IsDrug) { var num = -1; for (var k = 0; k < tmpDrugsToKeep.Count; k++) { if (thing.def != tmpDrugsToKeep[k].ThingDef) { continue; } num = k; break; } if (num < 0) { __result = new ThingCount(thing, thing.stackCount); return(false); } if (thing.stackCount > tmpDrugsToKeep[num].Count) { __result = new ThingCount(thing, thing.stackCount - tmpDrugsToKeep[num].Count); return(false); } tmpDrugsToKeep[num] = new ThingDefCount(tmpDrugsToKeep[num].ThingDef, tmpDrugsToKeep[num].Count - thing.stackCount); } else if (PerformanceManager.IsInstrument(thing)) { if (bestInstrument == null) { __result = new ThingCount(thing, thing.stackCount); return(false); } if (bestInstrument.GetHashCode() == thing.GetHashCode()) { continue; } __result = new ThingCount(thing, thing.stackCount); return(false); } else { __result = new ThingCount(thing, thing.stackCount); return(false); } } __result = default; return(false); } __result = new ThingCount(__instance.innerContainer[0], __instance.innerContainer[0].stackCount); return(false); }
protected override IEnumerable <Toil> MakeNewToils() { CompUpgrade comp = FindOneComp(); if (comp == null) { EndJobWith(JobCondition.Incompletable); yield break; } AddFailCondition(() => comp == null || !comp.parent.Spawned || !comp.beginUpgrade); this.FailOnDestroyedNullOrForbidden(TargetIndex.A); Toil gotoBuilding = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell); Toil findMaterial = new Toil { initAction = delegate() { ThingDefCount thingDefCount = comp.TryGetOneMissingMaterial(); job.count = thingDefCount.Count; if (thingDefCount.Count > 0) { Thing foundRes = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForDef(thingDefCount.ThingDef), PathEndMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly), 9999f, (Thing r) => { return(r.def == thingDefCount.ThingDef && !r.IsForbidden(pawn) && pawn.CanReserve(r)); }); if (foundRes == null) { EndJobWith(JobCondition.Incompletable); } else { job.SetTarget(TargetIndex.B, foundRes); } } else { JumpToToil(gotoBuilding); } } }; //Haul things to building yield return(findMaterial); yield return(Toils_Reserve.Reserve(TargetIndex.B, 1, job.count)); yield return(Toils_Goto.GotoCell(TargetIndex.B, PathEndMode.Touch).FailOnDestroyedNullOrForbidden(TargetIndex.B)); yield return(Toils_Haul.StartCarryThing(TargetIndex.B)); yield return(Toils_Goto.GotoCell(TargetIndex.A, PathEndMode.InteractionCell)); yield return(new Toil { initAction = delegate() { var tracker = pawn.carryTracker; if (tracker.CarriedThing != null) { tracker.innerContainer.TryTransferToContainer(tracker.CarriedThing, comp.GetDirectlyHeldThings(), tracker.CarriedThing.stackCount, true); pawn.Map.reservationManager.ReleaseAllForTarget(TargetThingB); job.SetTarget(TargetIndex.B, null); JumpToToil(findMaterial); } } }); //Do upgrade yield return(gotoBuilding); yield return(new Toil { tickAction = delegate() { Pawn actor = GetActor(); comp.Work(actor, actor.GetStatValue(StatDefOf.ConstructionSpeed)); if (comp.complete) { EndJobWith(JobCondition.Succeeded); } }, defaultCompleteMode = ToilCompleteMode.Never }.WithEffect(EffecterDefOf.ConstructMetal, TargetIndex.A).WithProgressBar(TargetIndex.A, () => comp.FinishPercentage)); yield break; }
private static float ApproxDaysWorthOfFood(List <Pawn> pawns, List <ThingDefCount> extraFood, int tile, IgnorePawnsInventoryMode ignoreInventory, Faction faction, WorldPath path = null, float nextTileCostLeft = 0f, int caravanTicksPerMove = 3300, bool assumeCaravanMoving = true) { if (!AnyFoodEatingPawn(pawns)) { return(600f); } if (!assumeCaravanMoving) { path = null; } tmpFood.Clear(); if (extraFood != null) { int i = 0; for (int count = extraFood.Count; i < count; i++) { ThingDefCount item = extraFood[i]; if (item.ThingDef.IsNutritionGivingIngestible && item.Count > 0) { tmpFood.Add(item); } } } int j = 0; for (int count2 = pawns.Count; j < count2; j++) { Pawn pawn = pawns[j]; if (InventoryCalculatorsUtility.ShouldIgnoreInventoryOf(pawn, ignoreInventory)) { continue; } ThingOwner <Thing> innerContainer = pawn.inventory.innerContainer; int k = 0; for (int count3 = innerContainer.Count; k < count3; k++) { Thing thing = innerContainer[k]; if (thing.def.IsNutritionGivingIngestible) { tmpFood.Add(new ThingDefCount(thing.def, thing.stackCount)); } } } tmpFood2.Clear(); tmpFood2.AddRange(tmpFood); tmpFood.Clear(); int l = 0; for (int count4 = tmpFood2.Count; l < count4; l++) { ThingDefCount item2 = tmpFood2[l]; bool flag = false; int m = 0; for (int count5 = tmpFood.Count; m < count5; m++) { ThingDefCount thingDefCount = tmpFood[m]; if (thingDefCount.ThingDef == item2.ThingDef) { tmpFood[m] = thingDefCount.WithCount(thingDefCount.Count + item2.Count); flag = true; break; } } if (!flag) { tmpFood.Add(item2); } } tmpDaysWorthOfFoodForPawn.Clear(); int n = 0; for (int count6 = pawns.Count; n < count6; n++) { tmpDaysWorthOfFoodForPawn.Add(0f); } int ticksAbs = Find.TickManager.TicksAbs; tmpTicksToArrive.Clear(); if (path != null && path.Found) { CaravanArrivalTimeEstimator.EstimatedTicksToArriveToEvery(tile, path.LastNode, path, nextTileCostLeft, caravanTicksPerMove, ticksAbs, tmpTicksToArrive); } cachedNutritionBetweenHungryAndFed.Clear(); cachedTicksUntilHungryWhenFed.Clear(); cachedMaxFoodLevel.Clear(); int num = 0; for (int count7 = pawns.Count; num < count7; num++) { Pawn pawn2 = pawns[num]; if (pawn2.RaceProps.EatsFood) { Need_Food food = pawn2.needs.food; cachedNutritionBetweenHungryAndFed.Add(food.NutritionBetweenHungryAndFed); cachedTicksUntilHungryWhenFed.Add(food.TicksUntilHungryWhenFedIgnoringMalnutrition); cachedMaxFoodLevel.Add(food.MaxLevel); } else { cachedNutritionBetweenHungryAndFed.Add(0f); cachedTicksUntilHungryWhenFed.Add(0); cachedMaxFoodLevel.Add(0f); } } float num2 = 0f; float num3 = 0f; float num4 = 0f; bool flag2 = false; WorldGrid worldGrid = Find.WorldGrid; bool flag3; do { flag3 = false; int num5 = ticksAbs + (int)(num3 * 60000f); int num6 = ((path != null) ? CaravanArrivalTimeEstimator.TileIllBeInAt(num5, tmpTicksToArrive, ticksAbs) : tile); bool flag4 = CaravanNightRestUtility.WouldBeRestingAt(num6, num5); float progressPerTick = ForagedFoodPerDayCalculator.GetProgressPerTick(assumeCaravanMoving && !flag4, flag4); float num7 = 1f / progressPerTick; bool flag5 = VirtualPlantsUtility.EnvironmentAllowsEatingVirtualPlantsAt(num6, num5); float num8 = num3 - num2; if (num8 > 0f) { num4 += num8 * 60000f; if (num4 >= num7) { BiomeDef biome = worldGrid[num6].biome; int num9 = Mathf.RoundToInt(ForagedFoodPerDayCalculator.GetForagedFoodCountPerInterval(pawns, biome, faction)); ThingDef foragedFood = biome.foragedFood; while (num4 >= num7) { num4 -= num7; if (num9 <= 0) { continue; } bool flag6 = false; for (int num10 = tmpFood.Count - 1; num10 >= 0; num10--) { ThingDefCount thingDefCount2 = tmpFood[num10]; if (thingDefCount2.ThingDef == foragedFood) { tmpFood[num10] = thingDefCount2.WithCount(thingDefCount2.Count + num9); flag6 = true; break; } } if (!flag6) { tmpFood.Add(new ThingDefCount(foragedFood, num9)); } } } } num2 = num3; int num11 = 0; for (int count8 = pawns.Count; num11 < count8; num11++) { Pawn pawn3 = pawns[num11]; if (!pawn3.RaceProps.EatsFood) { continue; } if (flag5 && VirtualPlantsUtility.CanEverEatVirtualPlants(pawn3)) { if (tmpDaysWorthOfFoodForPawn[num11] < num3) { tmpDaysWorthOfFoodForPawn[num11] = num3; } else { tmpDaysWorthOfFoodForPawn[num11] += 0.45f; } flag3 = true; } else { float num12 = cachedNutritionBetweenHungryAndFed[num11]; int num13 = cachedTicksUntilHungryWhenFed[num11]; do { int num14 = BestEverEdibleFoodIndexFor(pawn3, tmpFood); if (num14 < 0) { if (tmpDaysWorthOfFoodForPawn[num11] < num3) { flag2 = true; } break; } ThingDefCount thingDefCount3 = tmpFood[num14]; float num15 = Mathf.Min(thingDefCount3.ThingDef.ingestible.CachedNutrition, num12); float num16 = num15 / num12 * (float)num13 / 60000f; int num17 = Mathf.Min(Mathf.CeilToInt(Mathf.Min(0.2f, cachedMaxFoodLevel[num11]) / num15), thingDefCount3.Count); tmpDaysWorthOfFoodForPawn[num11] += num16 * (float)num17; tmpFood[num14] = thingDefCount3.WithCount(thingDefCount3.Count - num17); flag3 = true; }while (tmpDaysWorthOfFoodForPawn[num11] < num3); } if (flag2) { break; } num3 = Mathf.Max(num3, tmpDaysWorthOfFoodForPawn[num11]); } }while (!(!flag3 || flag2) && !(num3 > 601f)); float num18 = 600f; int num19 = 0; for (int count9 = pawns.Count; num19 < count9; num19++) { if (pawns[num19].RaceProps.EatsFood) { num18 = Mathf.Min(num18, tmpDaysWorthOfFoodForPawn[num19]); } } return(num18); }
public override void DrawPanelReadout(ref float curY, float width) { // we need the window's size to be able to do a scrollbar, but are not directly given that size. Rect outRect = ArchitectCategoryTab.InfoRect.AtZero(); // our window actually starts from curY outRect.yMin = curY; // our contents height is given by final curY - which we conveniently saved Rect viewRect = new Rect(0f, 0f, width, _panelHeight); // if contents are larger than available canvas, leave some room for scrollbar if (viewRect.height > outRect.height) { outRect.width -= 16f; width -= 16f; } // since we're going to work in new GUI group (through the scrollview), we'll need to keep track of // our own relative Y position. float oldY = curY; curY = 0f; // start scrollrect Widgets.BeginScrollView(outRect, ref _scrollPosition, viewRect); // list of objects to be build Text.Font = GameFont.Tiny; foreach (var buildables in Blueprint.GroupedBuildables) { // count float curX = 5f; Widgets.Label(new Rect(5f, curY, width * .2f, 100f), buildables.Value.Count + "x"); curX += width * .2f; // stuff selector float height = 0f; if (buildables.Value.First().Stuff != null) { string label = buildables.Value.First().Stuff.LabelAsStuff.CapitalizeFirst() + " " + buildables.Key.label; Rect iconRect = new Rect(curX, curY, 12f, 12f); curX += 16f; height = Text.CalcHeight(label, width - curX) + _lineOffset; Rect labelRect = new Rect(curX, curY, width - curX, height); Rect buttonRect = new Rect(curX - 16f, curY, width - curX + 16f, height + _lineOffset); if (Mouse.IsOver(buttonRect)) { GUI.DrawTexture(buttonRect, TexUI.HighlightTex); GUI.color = GenUI.MouseoverColor; } GUI.DrawTexture(iconRect, Resources.Icon_Edit); GUI.color = Color.white; Widgets.Label(labelRect, label); if (Widgets.ButtonInvisible(buttonRect)) { Blueprint.DrawStuffMenu(buildables.Key); } } else { // label float labelWidth = width - curX; string label = buildables.Key.LabelCap; height = Text.CalcHeight(label, labelWidth) + _lineOffset; Widgets.Label(new Rect(curX, curY, labelWidth, height), label); } // next line curY += height + _lineOffset; } // complete cost list curY += 12f; Text.Font = GameFont.Small; Widgets.Label(new Rect(0f, curY, width, 24f), "Fluffy.Blueprint.Cost".Translate()); curY += 24f; Text.Font = GameFont.Tiny; List <ThingDefCount> costlist = Blueprint.CostListAdjusted; for (int i = 0; i < costlist.Count; i++) { ThingDefCount thingCount = costlist[i]; Texture2D image; if (thingCount.ThingDef == null) { image = BaseContent.BadTex; } else { image = thingCount.ThingDef.uiIcon; } GUI.DrawTexture(new Rect(0f, curY, 20f, 20f), image); if (thingCount.ThingDef != null && thingCount.ThingDef.resourceReadoutPriority != ResourceCountPriority.Uncounted && Find.CurrentMap.resourceCounter.GetCount(thingCount.ThingDef) < thingCount.Count) { GUI.color = Color.red; } Widgets.Label(new Rect(26f, curY + 2f, 50f, 100f), thingCount.Count.ToString()); GUI.color = Color.white; string text; if (thingCount.ThingDef == null) { text = "(" + "UnchosenStuff".Translate() + ")"; } else { text = thingCount.ThingDef.LabelCap; } float height = Text.CalcHeight(text, width - 60f) - 2f; Widgets.Label(new Rect(60f, curY + 2f, width - 60f, height), text); curY += height + _lineOffset; } Widgets.EndScrollView(); _panelHeight = curY; // need to give some extra offset to properly align description. // also, add back in our internal offset curY += 28f + oldY; }
private static float ApproxDaysWorthOfFood(List <Pawn> pawns, List <ThingDefCount> extraFood, int tile, IgnorePawnsInventoryMode ignoreInventory, Faction faction, WorldPath path = null, float nextTileCostLeft = 0f, int caravanTicksPerMove = 3500, bool assumeCaravanMoving = true) { float result; if (!DaysWorthOfFoodCalculator.AnyFoodEatingPawn(pawns)) { result = 600f; } else { if (!assumeCaravanMoving) { path = null; } DaysWorthOfFoodCalculator.tmpFood.Clear(); if (extraFood != null) { int i = 0; int count = extraFood.Count; while (i < count) { ThingDefCount item = extraFood[i]; if (item.ThingDef.IsNutritionGivingIngestible && item.Count > 0) { DaysWorthOfFoodCalculator.tmpFood.Add(item); } i++; } } int j = 0; int count2 = pawns.Count; while (j < count2) { Pawn pawn = pawns[j]; if (!InventoryCalculatorsUtility.ShouldIgnoreInventoryOf(pawn, ignoreInventory)) { ThingOwner <Thing> innerContainer = pawn.inventory.innerContainer; int k = 0; int count3 = innerContainer.Count; while (k < count3) { Thing thing = innerContainer[k]; if (thing.def.IsNutritionGivingIngestible) { DaysWorthOfFoodCalculator.tmpFood.Add(new ThingDefCount(thing.def, thing.stackCount)); } k++; } } j++; } DaysWorthOfFoodCalculator.tmpFood2.Clear(); DaysWorthOfFoodCalculator.tmpFood2.AddRange(DaysWorthOfFoodCalculator.tmpFood); DaysWorthOfFoodCalculator.tmpFood.Clear(); int l = 0; int count4 = DaysWorthOfFoodCalculator.tmpFood2.Count; while (l < count4) { ThingDefCount item2 = DaysWorthOfFoodCalculator.tmpFood2[l]; bool flag = false; int m = 0; int count5 = DaysWorthOfFoodCalculator.tmpFood.Count; while (m < count5) { ThingDefCount thingDefCount = DaysWorthOfFoodCalculator.tmpFood[m]; if (thingDefCount.ThingDef == item2.ThingDef) { DaysWorthOfFoodCalculator.tmpFood[m] = thingDefCount.WithCount(thingDefCount.Count + item2.Count); flag = true; break; } m++; } if (!flag) { DaysWorthOfFoodCalculator.tmpFood.Add(item2); } l++; } DaysWorthOfFoodCalculator.tmpDaysWorthOfFoodForPawn.Clear(); int n = 0; int count6 = pawns.Count; while (n < count6) { DaysWorthOfFoodCalculator.tmpDaysWorthOfFoodForPawn.Add(0f); n++; } int ticksAbs = Find.TickManager.TicksAbs; DaysWorthOfFoodCalculator.tmpTicksToArrive.Clear(); if (path != null && path.Found) { CaravanArrivalTimeEstimator.EstimatedTicksToArriveToEvery(tile, path.LastNode, path, nextTileCostLeft, caravanTicksPerMove, ticksAbs, DaysWorthOfFoodCalculator.tmpTicksToArrive); } DaysWorthOfFoodCalculator.cachedNutritionBetweenHungryAndFed.Clear(); DaysWorthOfFoodCalculator.cachedTicksUntilHungryWhenFed.Clear(); DaysWorthOfFoodCalculator.cachedMaxFoodLevel.Clear(); int num = 0; int count7 = pawns.Count; while (num < count7) { Pawn pawn2 = pawns[num]; Need_Food food = pawn2.needs.food; DaysWorthOfFoodCalculator.cachedNutritionBetweenHungryAndFed.Add(food.NutritionBetweenHungryAndFed); DaysWorthOfFoodCalculator.cachedTicksUntilHungryWhenFed.Add(food.TicksUntilHungryWhenFed); DaysWorthOfFoodCalculator.cachedMaxFoodLevel.Add(food.MaxLevel); num++; } float num2 = 0f; float num3 = 0f; float num4 = 0f; bool flag2 = false; WorldGrid worldGrid = Find.WorldGrid; bool flag3; do { flag3 = false; int num5 = ticksAbs + (int)(num3 * 60000f); int num6 = (path == null) ? tile : CaravanArrivalTimeEstimator.TileIllBeInAt(num5, DaysWorthOfFoodCalculator.tmpTicksToArrive, ticksAbs); bool flag4 = CaravanRestUtility.WouldBeRestingAt(num6, (long)num5); float progressPerTick = ForagedFoodPerDayCalculator.GetProgressPerTick(assumeCaravanMoving && !flag4, flag4, null); float num7 = 1f / progressPerTick; bool flag5 = VirtualPlantsUtility.EnvironmentAllowsEatingVirtualPlantsAt(num6, num5); float num8 = num3 - num2; if (num8 > 0f) { num4 += num8 * 60000f; if (num4 >= num7) { BiomeDef biome = worldGrid[num6].biome; int num9 = Mathf.RoundToInt(ForagedFoodPerDayCalculator.GetForagedFoodCountPerInterval(pawns, biome, faction, null)); ThingDef foragedFood = biome.foragedFood; while (num4 >= num7) { num4 -= num7; if (num9 > 0) { bool flag6 = false; for (int num10 = DaysWorthOfFoodCalculator.tmpFood.Count - 1; num10 >= 0; num10--) { ThingDefCount thingDefCount2 = DaysWorthOfFoodCalculator.tmpFood[num10]; if (thingDefCount2.ThingDef == foragedFood) { DaysWorthOfFoodCalculator.tmpFood[num10] = thingDefCount2.WithCount(thingDefCount2.Count + num9); flag6 = true; break; } } if (!flag6) { DaysWorthOfFoodCalculator.tmpFood.Add(new ThingDefCount(foragedFood, num9)); } } } } } num2 = num3; int num11 = 0; int count8 = pawns.Count; while (num11 < count8) { Pawn pawn3 = pawns[num11]; if (pawn3.RaceProps.EatsFood) { if (flag5 && VirtualPlantsUtility.CanEverEatVirtualPlants(pawn3)) { if (DaysWorthOfFoodCalculator.tmpDaysWorthOfFoodForPawn[num11] < num3) { DaysWorthOfFoodCalculator.tmpDaysWorthOfFoodForPawn[num11] = num3; } else { List <float> list; int index; (list = DaysWorthOfFoodCalculator.tmpDaysWorthOfFoodForPawn)[index = num11] = list[index] + 0.45f; } flag3 = true; } else { float num12 = DaysWorthOfFoodCalculator.cachedNutritionBetweenHungryAndFed[num11]; int num13 = DaysWorthOfFoodCalculator.cachedTicksUntilHungryWhenFed[num11]; do { int num14 = DaysWorthOfFoodCalculator.BestEverEdibleFoodIndexFor(pawn3, DaysWorthOfFoodCalculator.tmpFood); if (num14 < 0) { goto Block_27; } ThingDefCount thingDefCount3 = DaysWorthOfFoodCalculator.tmpFood[num14]; float num15 = Mathf.Min(thingDefCount3.ThingDef.ingestible.CachedNutrition, num12); float num16 = num15 / num12 * (float)num13 / 60000f; int num17 = Mathf.Min(Mathf.CeilToInt(Mathf.Min(0.2f, DaysWorthOfFoodCalculator.cachedMaxFoodLevel[num11]) / num15), thingDefCount3.Count); List <float> list; int index2; (list = DaysWorthOfFoodCalculator.tmpDaysWorthOfFoodForPawn)[index2 = num11] = list[index2] + num16 * (float)num17; DaysWorthOfFoodCalculator.tmpFood[num14] = thingDefCount3.WithCount(thingDefCount3.Count - num17); flag3 = true; }while (DaysWorthOfFoodCalculator.tmpDaysWorthOfFoodForPawn[num11] < num3); goto IL_633; Block_27: if (DaysWorthOfFoodCalculator.tmpDaysWorthOfFoodForPawn[num11] < num3) { flag2 = true; } } IL_633: if (flag2) { break; } num3 = Mathf.Max(num3, DaysWorthOfFoodCalculator.tmpDaysWorthOfFoodForPawn[num11]); } num11++; } }while (flag3 && !flag2 && num3 <= 601f); float num18 = 600f; int num19 = 0; int count9 = pawns.Count; while (num19 < count9) { if (pawns[num19].RaceProps.EatsFood) { num18 = Mathf.Min(num18, DaysWorthOfFoodCalculator.tmpDaysWorthOfFoodForPawn[num19]); } num19++; } result = num18; } return(result); }