private static void DrawRangedStatRows(List <TSPWQuality> pairList, Rect startRect, int from, int to) { List <List <StatDrawInfo> > listHolder = new List <List <StatDrawInfo> >(); List <List <StatDrawInfo> > transposedLists = new List <List <StatDrawInfo> >(); // listHolder[0] listHolder[1] // | stuff1 | | stuff2 | // | Damage | | Damage | // | AP | | AP | /* stuff1 stuff2 * transposedLists[0] Damage Damage * transposedLists[1] AP AP */ for (int i = from; i < to && i < pairList.Count; i++) { TSPWQuality pair = pairList[i]; List <StatDrawInfo> infoList = new List <StatDrawInfo>(); infoList.AddRange(pair.thing.SpecialDisplayStats(StatRequest.For(pair.thing, pair.stuff, pair.Quality)) .Where(r => _rangedWeaponStats.Any(s => s.label.CapitalizeFirst() == r.LabelCap)) .Select(r => (StatDrawInfo)r) .ToList()); listHolder.Add(infoList); } // Transpose lists for (int i = 0; i < _rangedWeaponStats.Count; i++) { List <StatDrawInfo> newList = new List <StatDrawInfo>(); foreach (List <StatDrawInfo> list in listHolder) { newList.Add( list.Find(s => s.LabelCap == _rangedWeaponStats[i].label.CapitalizeFirst()) ?? new StatDrawInfo() { ValueString = "-", Tip = string.Empty, }); } if (newList.Count > 1) { List <StatDrawInfo> orderedList = newList.OrderByDescending(t => t.Value).ToList(); foreach (StatDrawInfo statDrawInfo in orderedList) { if (statDrawInfo.Value == orderedList[0].Value) { statDrawInfo.Color = Color.green; } } } transposedLists.Add(newList); } DrawStatRows(_rangedWeaponStats, null, startRect, from, to, out _, transposedLists, true); }
protected override bool LongSearchMatch(ThingDef thing) { if (!base.LongSearchMatch(thing)) { return(false); } if (!fromCategory.NullOrEmpty()) { if (thing.thingCategories.NullOrEmpty() || !thing.thingCategories.Exists(cat => fromCategory.Contains(cat))) { return(false); } } if (!fromRessource.NullOrEmpty()) { if (!fromRessource.Exists(ress => ress.stuffProps.CanMake(thing))) { return(false); } } if (!neededStats.NullOrEmpty()) { if (thing.statBases.NullOrEmpty()) { return(false); } QualityCategory quality; List <ThingDef> stuffs; for (int i = 0; i < neededStats.Count; i++) { if (!thing.statBases.StatListContains(neededStats[i].def)) { return(false); } quality = thing.HasComp(typeof(CompQuality)) ? QualityCategory.Legendary : QualityCategory.Normal; if (thing.MadeFromStuff) { stuffs = fromRessource.NullOrEmpty() ? DefDatabase <ThingDef> .AllDefsListForReading.FindAll(def => def.IsStuff && def.stuffProps.CanMake(thing)) : fromRessource.FindAll(def => def.stuffProps.CanMake(thing)); for (int j = 0; j < stuffs.Count; j++) { if (neededStats[i].def.Worker.GetValue(StatRequest.For(thing, stuffs[i], quality)) < neededStats[i].minValue) { return(false); } } } else if (neededStats[i].def.Worker.GetValue(StatRequest.For(thing, null, quality)) < neededStats[i].minValue) { return(false); } } } return(true); }
public static float GetBestValue(ThingDef td) { float val = StatDefOf.MarketValue.Worker.GetValue(StatRequest.For(td, null, QualityCategory.Legendary), true); if (td.stackLimit == 1 || td.BaseMarketValue >= forceSingleThreshold) { return(val); } return(ShardMaker.stackSize * val); }
//ctor to populate lists. public MainTabWindow_Numbers() { optionsMaker = new OptionsMaker(this); MethodInfo statsToDraw = typeof(StatsReportUtility).GetMethod("StatsToDraw", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.InvokeMethod, null, new[] { typeof(Thing) }, null); Pawn tmpPawn = PawnGenerator.GeneratePawn(PawnKindDefOf.AncientSoldier, Faction.OfPlayerSilentFail); if (statsToDraw != null) { pawnHumanlikeStatDef = ((IEnumerable <StatDrawEntry>)statsToDraw.Invoke(null, new[] { tmpPawn })) .Concat(tmpPawn.def.SpecialDisplayStats(StatRequest.For(tmpPawn))) .Where(s => s.stat != null && s.ShouldDisplay && s.stat.Worker != null) .Select(s => s.stat) .OrderBy(stat => stat.LabelCap.RawText); tmpPawn = PawnGenerator.GeneratePawn(PawnKindDefOf.Thrumbo); pawnAnimalNeedDef = tmpPawn.needs.AllNeeds.Where(x => x.def.showOnNeedList).Select(x => x.def); pawnAnimalStatDef = ((IEnumerable <StatDrawEntry>)statsToDraw.Invoke(null, new[] { tmpPawn })) .Where(s => s.stat != null && s.ShouldDisplay && s.stat.Worker != null) .Select(s => s.stat) .OrderBy(stat => stat.LabelCap.RawText); Corpse corpse = (Corpse)ThingMaker.MakeThing(tmpPawn.RaceProps.corpseDef); corpse.InnerPawn = tmpPawn; corpseStatDef = ((IEnumerable <StatDrawEntry>)statsToDraw.Invoke(null, new[] { corpse })) .Concat(tmpPawn.def.SpecialDisplayStats(StatRequest.For(tmpPawn))) .Where(s => s.stat != null && s.ShouldDisplay && s.stat.Worker != null) .Select(s => s.stat) .OrderBy(stat => stat.LabelCap.RawText); } else { Log.Error("ReflectionTypeLoadException in Numbers: statsToDraw was null. Please contact mod author."); } pawnHumanlikeNeedDef = DefDatabase <NeedDef> .AllDefsListForReading; PawnTableDef defaultTable = WorldComponent_Numbers.PrimaryFilter.First().Key; if (Find.World.GetComponent <WorldComponent_Numbers>().sessionTable.TryGetValue(defaultTable, out List <PawnColumnDef> list)) { pawnTableDef.columns = list; } UpdateFilter(); }
public double GetAnimalCost(Thing thing) { if (statWorker == null) { StatDef marketValueStatDef = StatDefOf.MarketValue; statWorker = marketValueStatDef.Worker; } float value = statWorker.GetValue(StatRequest.For(thing)); return(value); }
public static void DefsLoaded() { var smallCorpses = ThingCategoryDefOf.Corpses.ThisAndChildCategoryDefs.SelectMany(x => x.childThingDefs).Where( x => x.ingestible?.sourceDef != null && StatDefOf.MeatAmount.Worker.ShouldShowFor(StatRequest.For(x.ingestible.sourceDef, null)) && x.ingestible.sourceDef.GetStatValueAbstract(StatDefOf.MeatAmount) > 0 && x.ingestible.sourceDef.GetStatValueAbstract(StatDefOf.MeatAmount) <= 75); // second parameter is "exceptedFilters" but it's actually the filters to disallow apparently?? ConvenientButcherRecipes.COAA_ButcherSmallCreatureFlesh.fixedIngredientFilter.SetDisallowAll(smallCorpses, new[] { SpecialFilter.AllowRotten }); }
public override bool CanBeAppliedToThing(ThingWithComps thing) { // ShouldShowFor doesn't show Max HP, so force it in if (affectedStat == StatDefOf.MaxHitPoints) { return(thing.def.useHitPoints); } StatRequest req = StatRequest.For(thing); return(affectedStat.Worker.ShouldShowFor(req)); }
public override IEnumerable <StatDrawEntry> SpecialDisplayStats() { var props = Props; if (props != null) { if (props.damageDef != null) { var damageTypeStr = props.damageDef.LabelCap; yield return(new StatDrawEntry(CompSlotLoadableDefOf.SlotLoadable, StringOf.OverrideDamageType, damageTypeStr, string.Format(StringOf.OverrideDamageTypeExplanation, damageTypeStr), 99)); // TODO: armorPenStr should somehow be calculated via equivalent logic in ThingDef.SpecialDisplayStats. var armorPenStr = props.armorPenetration.ToStringPercent(); yield return(new StatDrawEntry(CompSlotLoadableDefOf.SlotLoadable, StringOf.OverrideArmorPenetration, armorPenStr, string.Format("ArmorPenetrationExplanation".Translate(), armorPenStr), 98)); } var statModifiers = props.statModifiers; if (statModifiers != null) { var statReq = StatRequest.For(parent); foreach (var mod in statModifiers) { var stat = mod.stat; yield return(new StatDrawEntry(CompSlotLoadableDefOf.SlotLoadable, stat, stat.Worker.GetValue(statReq), statReq, ToStringNumberSense.Offset)); } } var defHealChance = props.defensiveHealChance; if (defHealChance != null) { var chanceStr = defHealChance.chance.ToStringPercent(); var woundLimitStr = defHealChance.woundLimit == int.MaxValue ? StringOf.all : defHealChance.woundLimit.ToString(); yield return(new StatDrawEntry(CompSlotLoadableDefOf.SlotLoadable, StringOf.DefensiveHeal, string.Format(StringOf.DefensiveHealShort, chanceStr, woundLimitStr, defHealChance.amountRange), string.Format(StringOf.DefensiveHealExplanation, chanceStr, woundLimitStr, defHealChance.amountRange), 90)); } var vampHealChance = props.vampiricHealChance; if (vampHealChance != null) { var chanceStr = vampHealChance.chance.ToStringPercent(); var woundLimitStr = vampHealChance.woundLimit == int.MaxValue ? StringOf.all : vampHealChance.woundLimit.ToString(); var armorPenStr = vampHealChance.armorPenetration.ToStringPercent(); yield return(new StatDrawEntry(CompSlotLoadableDefOf.SlotLoadable, StringOf.VampiricHeal, string.Format(StringOf.VampiricHealShort, chanceStr, woundLimitStr, vampHealChance.amountRange, vampHealChance.damageDef, armorPenStr), string.Format(StringOf.VampiricHealExplanation, chanceStr, woundLimitStr, vampHealChance.amountRange, vampHealChance.damageDef, armorPenStr), 89)); } } }
private List <StatDef> GetHumanLikeStatDefs() { Pawn tmpPawn = PawnGenerator.GeneratePawn(PawnKindDefOf.AncientSoldier, Faction.OfPlayerSilentFail); var source = ((IEnumerable <StatDrawEntry>)StatsToDraw?.Invoke(null, new[] { tmpPawn })) ?? Enumerable.Empty <StatDrawEntry>(); var pawnHumanlikeStatDef = source .Concat(tmpPawn.def.SpecialDisplayStats(StatRequest.For(tmpPawn))) .Where(s => s.stat != null && s.ShouldDisplay && s.stat.Worker != null) .Select(s => s.stat); tmpPawn.Destroy(DestroyMode.KillFinalize); return(pawnHumanlikeStatDef.OrderBy(stat => stat.LabelCap.Resolve()).ToList()); }
static StatThingInfo CreateInstance(StatDef statDef) { float?min = null, max = null; var foundFraction = false; var thingDefValues = new Dictionary <ThingDef, float>(); foreach (var thingDef in DefDatabase <ThingDef> .AllDefsListForReading) { if (!statDef.Worker.ShouldShowFor(StatRequest.For(thingDef, null))) { continue; } // https://github.com/CombatExtendedRWMod/CombatExtended/blob/7768f94edae4ffffdce16cb3bb7b10db0e541a79/Source/CombatExtended/CombatExtended/StatWorkers/StatWorker_MeleeDamageAverage.cs#L31 if (CeToolCeType != null && thingDef.tools != null && thingDef.tools.Any(x => x.GetType() != CeToolCeType)) { continue; } var value = thingDef.GetStatValueAbstract(statDef); if (Mathf.Approximately(value, statDef.hideAtValue)) { continue; } if (!foundFraction && !Mathf.Approximately(value % 1, 0)) { foundFraction = true; } min = Math.Min(min ?? value, value); max = Math.Max(max ?? value, value); thingDefValues.Add(thingDef, value); } if (min == null || float.IsNaN((float)min) || min.Equals(max)) { return(null); } //Debug.WriteLine($"{statDef} \"{statDef.label}\" {min} {max} {statDef.toStringStyle} \"{string.Join(", ", thingDefValues.Select(x => x.ToString()).ToArray())}\""); if (statDef.toStringStyle == default && !explicitlyIntegers.Contains(statDef) && foundFraction) { statDef.toStringStyle = ToStringStyle.FloatTwo; } var result = new StatThingInfo(statDef, thingDefValues, (float)min, (float)max); return(result); }
public static void Postfix(BuildingProperties __instance, ref IEnumerable <StatDrawEntry> __result, ThingDef parentDef, StatRequest req) { var turretGunDef = __instance.turretGunDef; if (turretGunDef != null) { var statRequestGun = StatRequest.For(turretGunDef, null); var newStats1 = DefDatabase <StatDef> .AllDefs .Where(x => x.category == StatCategoryDefOf.Weapon && x.Worker.ShouldShowFor(statRequestGun) && !x.Worker.IsDisabledFor(req.Thing) && !(x.Worker is StatWorker_MeleeStats)) .Select(x => new StatDrawEntry(StatCategoryDefOf.Weapon, x, turretGunDef.GetStatValueAbstract(x), statRequestGun, ToStringNumberSense.Undefined)) .Where(x => x.ShouldDisplay) .Concat(turretGunDef.SpecialDisplayStats(statRequestGun)); __result = __result.Concat(newStats1); } }
static public void PostAffixCleanup(this CompLootAffixableThing comp, bool fixLabel = true) { ThingWithComps thing = comp.parent; comp.ClearAffixCaches(); if (fixLabel) { comp.affixRules.Clear(); comp.fullStuffLabel = null; string name = thing.LabelNoCount; name = comp.TransformLabel(name); } thing.def.SpecialDisplayStats(StatRequest.For(thing)); foreach (LootAffixDef affix in comp.affixes) { affix.PostApplyAffix(thing); } }
public virtual float GetStatOffset(StatDef stat) { var statModifiers = Props?.statModifiers; if (statModifiers != null) { var statOffset = statModifiers.GetStatOffsetFromList(stat); //Log.Message("adding in stat " + stat + " offset: " + statOffset); if (!stat.parts.NullOrEmpty()) { var statReq = StatRequest.For(parent); for (var i = 0; i < stat.parts.Count; i++) { //Log.Message("adding in parts " + stat.parts[i]); stat.parts[i].TransformValue(statReq, ref statOffset); } //Log.Message("added in parts of a stat for result " + statOffset); } return(statOffset); } return(0f); }
public static void Postfix(ThingDef __instance, ref IEnumerable <StatDrawEntry> __result, StatRequest req) { var turretGunDef = __instance.building?.turretGunDef ?? null; if (turretGunDef != null) { var statRequestGun = StatRequest.For(turretGunDef, null); var cache = __result; var newStats1 = DefDatabase <StatDef> .AllDefs .Where(x => x.category == StatCategoryDefOf.Weapon && x.Worker.ShouldShowFor(statRequestGun) && !x.Worker.IsDisabledFor(req.Thing) && !(x.Worker is StatWorker_MeleeStats)) .Where(x => !cache.Any(y => y.stat == x)) .Select(x => new StatDrawEntry(StatCategoryDefOf.Weapon, x, turretGunDef.GetStatValueAbstract(x), statRequestGun, ToStringNumberSense.Undefined)) .Where(x => x.ShouldDisplay); __result = __result.Concat(newStats1); } }
public override IEnumerable <StatDrawEntry> SpecialDisplayStatsForThing(ThingWithComps parentThing, string preLabel) { // Add additional Equipped Stat Offsets modifiers var statDrawEntry = new StatDrawEntry( category: StatCategoryDefOf.EquippedStatOffsets, label: affectedStat.LabelCap, valueString: ModifierChangeString, // much more flexible than value reportText: affectedStat.description, displayPriorityWithinCategory: 10 ); StatRequest req = StatRequest.For(parentThing); // Extra properties, since we're overriding the typical stat value display statDrawEntry.stat = affectedStat; statDrawEntry.hasOptionalReq = true; statDrawEntry.optionalReq = req; // Calculate an example value StatWorker worker = affectedStat.Worker; float exampleValue = parentThing.ParentHolder != null && parentThing.ParentHolder is Pawn pawn? worker.GetValueUnfinalized(StatRequest.For(pawn)) : affectedStat.defaultBaseValue ; // Use the Thing-tied StatRequest to hit our StatPart worker.FinalizeValue(req, ref exampleValue, true); // And finally, another private we need to dodge around to install both kinds of StatDrawEntry fields. // [Reflection] statDrawEntry.value = exampleValue; FieldInfo valueField = AccessTools.Field(typeof(StatDrawEntry), "value"); valueField.SetValue(statDrawEntry, exampleValue); yield return(statDrawEntry); }
public static float DetermineSlottableStatAugment(Thing slottable, StatDef stat) { float retval = 0.0f; CompSlottedBonus slotBonus = slottable.TryGetComp <CompSlottedBonus>(); if (slotBonus != null) { if (slotBonus.Props != null) { if (slotBonus.Props.statModifiers != null && slotBonus.Props.statModifiers.Count > 0) { foreach (StatModifier thisStat in slotBonus.Props.statModifiers) { //Log.Message("Check for modding "+stat+" against "+thisStat.stat); if (thisStat.stat == stat) { //Log.Message("adding in stat "+thisStat.stat+":"+thisStat.value+" to result "+retval); retval += thisStat.value; // apply stats parts from Slottable if (stat.parts != null && stat.parts.Count > 0) { StatRequest req = StatRequest.For(slottable); for (int i = 0; i < stat.parts.Count; i++) { //Log.Message("adding in parts "+stat.parts[i]); stat.parts[i].TransformValue(req, ref retval); } //Log.Message("added in parts of a stat for result "+retval); } } } } } } return(retval); }
/// Changed into a transpiler. /// <summary> /// Replaces the plant harvest toil of a cutebold to allow them to harvest over 100%. /// </summary> /// <param name="__result">The previous output from the original toil generator.</param> /// <param name="__instance">The plant job.</param> /// <returns>A headache. (The new toils)</returns> private static IEnumerable <Toil> CuteboldMakeNewToilsPlantWorkPostfix(IEnumerable <Toil> __result, JobDriver_PlantWork __instance) { //Log.Message("CuteboldMakeNewToilsPlantWorkPostfix"); foreach (Toil toil in __result) { if (toil.tickAction != null && __instance.pawn?.def.defName == Cutebold_Assemblies.RaceName) { //Log.Message(" Edit Toil"); // Shamelessly taken from the base code and modified to allow cutebolds to harvest just that little bit more with their small, delicate hands. // Two Traverses are used to access protected methods that are overwritten by classes that overwrite the defaults. toil.tickAction = delegate() { Pawn actor = toil.actor; Map map = actor.Map; float xpPerTick = (float)Traverse.Create(__instance).Field("xpPerTick").GetValue(); if (actor.skills != null) { actor.skills.Learn(SkillDefOf.Plants, xpPerTick); } float workSpeed = actor.GetStatValue(StatDefOf.PlantWorkSpeed, true); Plant plant = (Plant)__instance.job.targetA.Thing; workSpeed *= UnityEngine.Mathf.Lerp(3.3f, 1f, plant.Growth); var workDoneVariable = Traverse.Create(__instance).Field("workDone"); float workDone = (float)workDoneVariable.GetValue() + workSpeed; workDoneVariable.SetValue(workDone); if ((workDone) >= plant.def.plant.harvestWork) { if (plant.def.plant.harvestedThingDef != null) { StatDef stat = (plant.def.plant.harvestedThingDef.IsDrug ? StatDefOf.DrugHarvestYield : StatDefOf.PlantHarvestYield); // 1.1 StatDef stat = StatDefOf.PlantHarvestYield; float yieldMultiplier = (1f + CuteboldCalculateExtraPercent(stat, StatRequest.For(actor))); if (actor.RaceProps.Humanlike && plant.def.plant.harvestFailable && !plant.Blighted && Rand.Value > yieldMultiplier) { MoteMaker.ThrowText((__instance.pawn.DrawPos + plant.DrawPos) / 2f, map, "TextMote_HarvestFailed".Translate(), 3.65f); } else { int currentYield = GenMath.RoundRandom(plant.YieldNow() * yieldMultiplier); //Log.Message(" Pawn Additional Harvest Percent=" + calculateExtraPercent(StatDefOf.PlantHarvestYield, StatRequest.For(actor))); //Log.Message(" Plant Yield Before=" + plant.YieldNow() + " Plant Yield After=" + currentYield); if (currentYield > 0) { Thing product = ThingMaker.MakeThing(plant.def.plant.harvestedThingDef, null); product.stackCount = currentYield; if (actor.Faction != Faction.OfPlayer) { product.SetForbidden(true); } Find.QuestManager.Notify_PlantHarvested(actor, product); GenPlace.TryPlaceThing(product, actor.Position, map, ThingPlaceMode.Near); actor.records.Increment(RecordDefOf.PlantsHarvested); } } } plant.def.plant.soundHarvestFinish.PlayOneShot(actor); plant.PlantCollected(__instance.pawn); // 1.1 plant.PlantCollected(); workDoneVariable.SetValue(0f); __instance.ReadyForNextToil(); return; } }; } yield return(toil); } }
public static IEnumerable <StatDrawEntry> Postfix(IEnumerable <StatDrawEntry> original, Thing thing) { foreach (StatDrawEntry entry in original) { Pawn pawn = thing as Pawn; StatDef statDef = entry.stat; if (pawn != null && pawn.InBed() && (statDef == StatDefOf.ComfyTemperatureMin || statDef == StatDefOf.ComfyTemperatureMax)) { if (!statDef.Worker.IsDisabledFor(thing)) { //sneak transform: float statValue = statDef.Worker.GetValueUnfinalized(StatRequest.For(thing), true); bool subtract = statDef == StatDefOf.ComfyTemperatureMin; StatDef modifier = subtract ? BedInsulationCold.Bed_Insulation_Cold : BedInsulationHeat.Bed_Insulation_Heat; float bedStatValue = pawn.CurrentBed().GetStatValue(modifier, true); float bedOffset = subtract ? bedStatValue * -1 : bedStatValue; statValue += bedOffset; // if (statDef.showOnDefaultValue || statValue != statDef.defaultBaseValue) { yield return(new StatDrawEntry(statDef.category, statDef, statValue, StatRequest.For(thing), ToStringNumberSense.Undefined, null, false)); } } else { yield return(new StatDrawEntry(statDef.category, statDef)); } } else { yield return(entry); } } }
private static void DrawStatRows(List <StatDef> stats, List <TSPWQuality> pairs, Rect startRect, int from, int to, out float rollingY, List <List <StatDrawInfo> > listHolder = null, bool specialStats = false) { float startX = startRect.x; for (int i = 0; i < stats.Count; i++) { List <StatDrawInfo> statInfoList = new List <StatDrawInfo>(); if (!specialStats) { statInfoList = new List <StatDrawInfo>(); // Retrieve stat value and create a view model, StatDrawInfo, for drawing. for (int j = from; j < to && j < pairs.Count; j++) { TSPWQuality pair = pairs[j]; StatDrawInfo drawInfo = new StatDrawInfo(); Thing tempThing = pair.MakeThingWithoutID(); StatRequest statRequest = StatRequest.For(tempThing); if ((stats[i].Worker.ShouldShowFor(statRequest) && !stats[i].Worker.IsDisabledFor(tempThing)) || stats[i] == StatDefOf.MaxHitPoints || stats[i] == StatDefOf.MeleeWeapon_CooldownMultiplier) { drawInfo.StatRequest = statRequest; drawInfo.Value = GetCachedValue(_statCache, () => stats[i].Worker.GetValue(drawInfo.StatRequest), pair, stats[i]); drawInfo.Tip = GetCachedValue(_statTipCache, () => stats[i].Worker.GetExplanationFull(drawInfo.StatRequest, stats[i].toStringNumberSense, drawInfo.Value), pair, stats[i]); } else { drawInfo.Value = -1; drawInfo.Tip = string.Empty; } statInfoList.Add(drawInfo); } if (statInfoList.Count > 1) { // Highlight highest stat value. List <StatDrawInfo> orderedList = statInfoList.OrderByDescending(t => t.Value).ToList(); foreach (StatDrawInfo statDrawInfo in orderedList) { if (statDrawInfo.Value == orderedList[0].Value) { statDrawInfo.Color = Color.green; } } } } else { statInfoList = listHolder[i]; } #pragma warning disable SA1118 // Parameter should not span multiple lines // Draw stat for each stuff choice. Text.Anchor = TextAnchor.MiddleCenter; foreach (StatDrawInfo info in statInfoList) { GUI.color = info.Color; Widgets.Label( startRect, specialStats ? info.ValueString : info.Value == -1 ? "-" : stats[i].Worker.ValueToString(info.Value, true, stats[i].toStringNumberSense)); Widgets.DrawHighlightIfMouseover(startRect); Text.Anchor = TextAnchor.MiddleLeft; TooltipHandler.TipRegion(startRect, info.Tip); Text.Anchor = TextAnchor.MiddleCenter; startRect = startRect.ReplaceX(startRect.xMax); } #pragma warning restore SA1118 // Parameter should not span multiple lines startRect = new Rect(startX, startRect.yMax, startRect.width, startRect.height); } rollingY = startRect.y; Text.Anchor = TextAnchor.UpperLeft; GUI.color = Color.white; }
public static void DoSkillsAnalysis(this Pawn p) { var stringBuilder = new StringBuilder(); stringBuilder.AppendLine("Beginning skills analysis."); foreach (var skill in p.skills.skills) { stringBuilder.AppendLine(skill.def + ": " + skill.levelInt + " Disabled: " + skill.TotallyDisabled); } stringBuilder.AppendLine("Beginning food poison test."); /* * foreach (var stat in DefDatabase<StatDef>.AllDefs) * { * try * { * stringBuilder.AppendLine(stat.defName + ": " + p.GetStatValue(stat)); * } * catch * { * stringBuilder.AppendLine(stat.defName + ": ERROR"); * } * } */ stringBuilder.AppendLine(StatDefOf.FoodPoisonChance.Worker.GetExplanation(StatRequest.For(p), ToStringNumberSense.Absolute)); Log.Message(stringBuilder.ToString()); }
private void DrawForagedFoodPerDay(Rect rect, TransferableOneWay trad) { if (!trad.HasAnyThing) { return; } if (!(trad.AnyThing is Pawn p)) { return; } float foragedNutritionPerDay = ForagedFoodPerDayCalculator.GetBaseForagedNutritionPerDay(p, out bool flag); if (flag) { return; } Widgets.DrawHighlightIfMouseover(rect); GUI.color = ((foragedNutritionPerDay == 0f) ? Color.gray : Color.green); Widgets.Label(rect, "+" + foragedNutritionPerDay.ToString("0.##")); GUI.color = Color.white; if (Mouse.IsOver(rect)) { TooltipHandler.TipRegion(rect, () => "NutritionForagedPerDayTip".Translate(StatDefOf.ForagedNutritionPerDay.Worker.GetExplanationFull(StatRequest.For(p), StatDefOf.ForagedNutritionPerDay.toStringNumberSense, foragedNutritionPerDay)), trad.GetHashCode() ^ 1958671422); } }
public static float PaperclipAmount(this ThingDef tDef, ThingDef stuff = null) { return(StatDefOf.Mass.Worker.GetValue(StatRequest.For(tDef, stuff)) * 1000); }
public static float GetEnergyAmount(ThingDef def, ThingDef stuffDef) { return(ConvertEnergyAmount(StatDefOf.MarketValue.Worker.GetValue(StatRequest.For(def, stuffDef)))); }
public override IEnumerable <StatDrawEntry> SpecialDisplayStats() { foreach (StatDrawEntry s in this.< SpecialDisplayStats > __BaseCallProxy0()) { yield return(s); } if (this.GetRotStage() == RotStage.Fresh) { StatDef meatAmount = StatDefOf.MeatAmount; yield return(new StatDrawEntry(meatAmount.category, meatAmount, this.InnerPawn.GetStatValue(meatAmount, true), StatRequest.For(this.InnerPawn), ToStringNumberSense.Undefined)); StatDef leatherAmount = StatDefOf.LeatherAmount; yield return(new StatDrawEntry(leatherAmount.category, leatherAmount, this.InnerPawn.GetStatValue(leatherAmount, true), StatRequest.For(this.InnerPawn), ToStringNumberSense.Undefined)); } yield break; }
private static RecipeDef CreateMiningRecipe(ThingDefCountClass defCount, EffecterDef effecter) { RecipeDef r = new RecipeDef(); r.defName = "Recipe_AutoMachineTool_Mine_" + defCount.thingDef.defName; r.label = "PRF.AutoMachineTool.AutoMiner.MineOre".Translate(defCount.thingDef.label); r.jobString = "PRF.AutoMachineTool.AutoMiner.MineOre".Translate(defCount.thingDef.label); r.workAmount = Mathf.Max(10000f, StatDefOf.MarketValue.Worker.GetValue(StatRequest.For(defCount.thingDef, null)) * defCount.count * 1000); r.workSpeedStat = StatDefOf.WorkToMake; r.efficiencyStat = StatDefOf.WorkToMake; r.workSkill = SkillDefOf.Mining; r.workSkillLearnFactor = 0; r.products = new List <ThingDefCountClass>().Append(defCount); r.defaultIngredientFilter = new ThingFilter(); r.effectWorking = effecter; // ChunkStone が Recipe の WorkAmount 経由で価値を設定されてしまうため、BaseMarketValue に0を設定して、計算されないようにする。 // <see cref="StatWorker_MarketValue.CalculatedBaseMarketValue(BuildableDef, ThingDef)"/> if (!defCount.thingDef.statBases.StatListContains(StatDefOf.MarketValue) && defCount.count == 1) { defCount.thingDef.BaseMarketValue = 0; } return(r); }
static void SpecialDisplayStats_PostFix(Corpse __instance, ref IEnumerable <StatDrawEntry> __result) { // Create a modifyable list List <StatDrawEntry> NewList = new List <StatDrawEntry>(); // copy vanilla entries into the new list foreach (StatDrawEntry entry in __result) { // it's possible to discard entries here if needed NewList.Add(entry); } // custom code to modify list contents StatDef BoneAmount = DefDatabase <StatDef> .GetNamed("BoneAmount", true); float pawnBoneCount = __instance.InnerPawn.GetStatValue(BoneAmount, true) * BoneModSettings.boneFactor; NewList.Add(new StatDrawEntry(BoneAmount.category, BoneAmount, pawnBoneCount, StatRequest.For(__instance.InnerPawn), ToStringNumberSense.Undefined)); // convert list to IEnumerable to match the caller's expectations IEnumerable <StatDrawEntry> output = NewList; // make caller use the list __result = output; }
private static RecipeDef CreateMiningRecipe(ThingDefCountClass defCount) { RecipeDef r = new RecipeDef(); r.defName = "Recipe_NR_AutoMachineTool_Mine_" + defCount.thingDef.defName; r.label = "NR_AutoMachineTool.AutoMiner.MineOre".Translate(defCount.thingDef.label); r.jobString = "NR_AutoMachineTool.AutoMiner.MineOre".Translate(defCount.thingDef.label); r.workAmount = Mathf.Max(10000f, StatDefOf.MarketValue.Worker.GetValue(StatRequest.For(defCount.thingDef, null)) * defCount.count * 1000); r.workSpeedStat = StatDefOf.WorkToMake; r.efficiencyStat = StatDefOf.WorkToMake; r.workSkill = SkillDefOf.Mining; r.workSkillLearnFactor = 0; r.products = new List <ThingDefCountClass>().Append(defCount); r.defaultIngredientFilter = new ThingFilter(); r.effectWorking = EffecterDefOf.Drill; return(r); }
public static bool FUUUCK(Rect rect, Thing thing) { if (!Active) { return(true); } Profiler prof = null; if (StatsReportUtility.cachedDrawEntries.NullOrEmpty <StatDrawEntry>()) { prof = ProfileController.Start("SpecialDisplayStats"); StatsReportUtility.cachedDrawEntries.AddRange(thing.def.SpecialDisplayStats(StatRequest.For(thing))); prof.Stop(); prof = ProfileController.Start("StatsToDraw"); StatsReportUtility.cachedDrawEntries.AddRange(StatsReportUtility.StatsToDraw(thing).Where(s => s.ShouldDisplay)); prof.Stop(); prof = ProfileController.Start("RemoveAll"); StatsReportUtility.cachedDrawEntries.RemoveAll((StatDrawEntry de) => de.stat != null && !de.stat.showNonAbstract); prof.Stop(); prof = ProfileController.Start("FinalizeCachedDrawEntries"); StatsReportUtility.FinalizeCachedDrawEntries(StatsReportUtility.cachedDrawEntries); prof.Stop(); } prof = ProfileController.Start("DrawStatsWorker"); StatsReportUtility.DrawStatsWorker(rect, thing, null); prof.Stop(); return(false); }
private void DrawStatsWorker(Rect rect) { Rect rect2 = new Rect(rect); rect2.width *= 0.5f; Rect rect3 = new Rect(rect); rect3.x = rect2.xMax; rect3.width = rect.xMax - rect3.x; Text.Font = GameFont.Small; Rect viewRect = new Rect(0f, 0f, rect2.width - 16f, listHeight); Widgets.BeginScrollView(rect2, ref scrollPosition, viewRect, true); float num = 0f; string b = null; cachedDrawEntries = this.StatsToDraw(this.thing).ToList(); this.FinalizeCachedDrawEntries(); mousedOverEntry = null; foreach (StatDrawEntry stat in cachedDrawEntries) { if (stat.category.LabelCap != b) { Widgets.ListSeparator(ref num, viewRect.width, stat.category.LabelCap); b = stat.category.LabelCap; } num += stat.Draw(8f, num, viewRect.width - 8f, selectedEntry == stat, delegate { selectedEntry = stat; SoundDefOf.Tick_High.PlayOneShotOnCamera(null); }, delegate { mousedOverEntry = stat; }, scrollPosition, rect2); } listHeight = num + 100f; Widgets.EndScrollView(); Rect rect4 = rect3.ContractedBy(10f); GUI.BeginGroup(rect4); StatDrawEntry statDrawEntry; if ((statDrawEntry = selectedEntry) is null) { statDrawEntry = mousedOverEntry ?? cachedDrawEntries.FirstOrDefault <StatDrawEntry>(); } StatDrawEntry statDrawEntry2 = statDrawEntry; if (statDrawEntry2 != null) { StatRequest optionalReq; if (statDrawEntry2.hasOptionalReq) { optionalReq = statDrawEntry2.optionalReq; } else if (this.thing != null) { optionalReq = StatRequest.For(this.thing); } else { optionalReq = StatRequest.ForEmpty(); } string explanation = statDrawEntry2.GetExplanationText(optionalReq); Rect rect5 = rect4.AtZero(); Widgets.Label(rect5, explanation); } GUI.EndGroup(); }
/// Convered into a transpiler. /// <summary> /// Adds extra materials to mined rock when the yield is over the default max. /// </summary> /// <param name="__instance">What was mined</param> /// <param name="___yieldPct">The max yield percentage</param> /// <param name="map">The map we are on</param> /// <param name="yieldChance">The chance to yield something (Ignored)</param> /// <param name="moteOnWaste">If we should do a mote on waste (Ignored)</param> /// <param name="pawn">The pawn mining</param> private static void CuteboldTrySpawnYieldMiningPostfix(Mineable __instance, float ___yieldPct, Map map, float yieldChance, bool moteOnWaste, Pawn pawn) { //Log.Message("CuteboldTrySapwnYieldMiningPostfix"); if (pawn?.def.defName != Cutebold_Assemblies.RaceName || __instance == null || __instance.def.building.mineableThing == null || __instance.def.building.mineableDropChance < 1f || !__instance.def.building.mineableYieldWasteable) { return; } //if (pawn == null || pawn.def.defName != Cutebold_Assemblies.RaceName || __instance == null || __instance.def.building.mineableThing == null || __instance.def.building.mineableDropChance < 1f || !__instance.def.building.mineableYieldWasteable) return; //Log.Message(" Effective Mineable Yield="+ __instance.def.building.EffectiveMineableYield.ToString()); //Log.Message(" Yield Percent=" + ___yieldPct.ToString()); //Log.Message(" Mineable Thing=" + __instance.def.building.mineableThing.ToString()); float extraPercent = CuteboldCalculateExtraPercent(StatDefOf.MiningYield, StatRequest.For(pawn)); //Log.Message(" Pawn Additional Mining Percent=" + extraPercent); // Based on the RimWorld base code to allow for mining yield over 100% cause cutebolds are just that good at mining. if (___yieldPct >= 1f && extraPercent > 0f) { Thing minedMaterial = ThingMaker.MakeThing(__instance.def.building.mineableThing); minedMaterial.stackCount = GenMath.RoundRandom(__instance.def.building.EffectiveMineableYield * extraPercent); // 1.1 minedMaterial.stackCount = GenMath.RoundRandom(__instance.def.building.mineableYield * extraPercent); GenPlace.TryPlaceThing(minedMaterial, __instance.Position, map, ThingPlaceMode.Near, ForbidIfNecessary); } void ForbidIfNecessary(Thing minedMaterial, int count) { if ((pawn == null || !pawn.IsColonist) && minedMaterial != null && minedMaterial.def.EverHaulable && !minedMaterial.def.designateHaulable) { minedMaterial.SetForbidden(value: true, warnOnFail: false); } } }