private static float GetComparativeChanceAgainst(Pawn attacker, Pawn defender, StatDef stat, float baseChance, float defenderSkillMult = 1) { if (attacker == null || defender == null) { return(0); } var offSkill = stat.Worker.IsDisabledFor(attacker) ? 0 : attacker.GetStatValue(stat); var defSkill = stat.Worker.IsDisabledFor(defender) ? 0 : defender.GetStatValue(stat) * defenderSkillMult; var chance = Mathf.Clamp01(baseChance + offSkill - defSkill); return(chance); }
internal static void GenerateStartingOutfits(OutfitDatabase db, bool vanilla = true) { if (vanilla) { ConfigureWorkerOutfit(MakeOutfit(db, "Anything"), new Dictionary <StatDef, float> { { StatDefOf.MoveSpeed, Priority.Desired }, { StatDefOf.WorkSpeedGlobal, Priority.Wanted }, { StatDefOf.ArmorRating_Blunt, Priority.Desired }, { StatDefOf.ArmorRating_Sharp, Priority.Desired }, }); ConfigureWorkerOutfit(MakeOutfit(db, "Worker"), new Dictionary <StatDef, float> { { StatDefOf.MoveSpeed, Priority.Neutral }, { StatDefOf.WorkSpeedGlobal, Priority.Desired }, }); } ConfigureWorkerOutfit(MakeOutfit(db, "Doctor"), new Dictionary <StatDef, float> { { StatDefOf.MedicalSurgerySuccessChance, Priority.Wanted }, { StatDef.Named("MedicalOperationSpeed"), Priority.Wanted }, { StatDefOf.MedicalTendQuality, Priority.Wanted }, { StatDefOf.MedicalTendSpeed, Priority.Desired }, { StatDefOf.WorkSpeedGlobal, Priority.Desired }, }); ConfigureWorkerOutfit(MakeOutfit(db, "Warden"), new Dictionary <StatDef, float> { { StatDefOf.NegotiationAbility, Priority.Wanted }, { StatDefOf.SocialImpact, Priority.Desired }, { StatDefOf.TradePriceImprovement, Priority.Wanted }, }); ConfigureWorkerOutfit(MakeOutfit(db, "Handler"), new Dictionary <StatDef, float> { { StatDefOf.TrainAnimalChance, Priority.Wanted }, { StatDefOf.TameAnimalChance, Priority.Wanted }, { StatDefOf.ArmorRating_Sharp, Priority.Neutral }, { StatDefOf.MeleeDodgeChance, Priority.Desired }, { StatDefOf.MeleeHitChance, Priority.Neutral }, { StatDefOf.MoveSpeed, Priority.Neutral }, { StatDefOf.MeleeDPS, Priority.Neutral }, { StatDefOf.AccuracyTouch, Priority.Neutral }, { StatDefOf.MeleeWeapon_CooldownMultiplier, Priority.Unwanted }, { StatDefOf.MeleeWeapon_DamageMultiplier, Priority.Neutral }, { StatDefOf.PainShockThreshold, Priority.Wanted }, { StatDefOf.AnimalGatherYield, Priority.Wanted }, { StatDefOf.AnimalGatherSpeed, Priority.Wanted }, }); ConfigureWorkerOutfit(MakeOutfit(db, "Cook"), new Dictionary <StatDef, float> { { StatDef.Named("DrugCookingSpeed"), Priority.Wanted }, { StatDef.Named("ButcheryFleshSpeed"), Priority.Wanted }, { StatDef.Named("ButcheryFleshEfficiency"), Priority.Wanted }, { StatDef.Named("CookSpeed"), Priority.Wanted }, { StatDefOf.FoodPoisonChance, Priority.Unwanted }, { StatDefOf.MoveSpeed, Priority.Desired }, { StatDefOf.WorkSpeedGlobal, Priority.Desired }, }); ConfigureSoldierOutfit(MakeOutfit(db, "Hunter"), new Dictionary <StatDef, float> { { StatDefOf.ShootingAccuracyPawn, Priority.Wanted }, { StatDefOf.MoveSpeed, Priority.Desired }, { StatDefOf.AccuracyShort, Priority.Desired }, { StatDefOf.AccuracyMedium, Priority.Desired }, { StatDefOf.AccuracyLong, Priority.Desired }, { StatDefOf.MeleeDPS, Priority.Neutral }, { StatDefOf.MeleeHitChance, Priority.Neutral }, { StatDefOf.ArmorRating_Blunt, Priority.Neutral }, { StatDefOf.ArmorRating_Sharp, Priority.Neutral }, { StatDefOf.RangedWeapon_Cooldown, Priority.Unwanted }, { StatDefOf.AimingDelayFactor, Priority.Unwanted }, { StatDefOf.PainShockThreshold, Priority.Wanted }, }); ConfigureWorkerOutfit(MakeOutfit(db, "Builder"), new Dictionary <StatDef, float> { { StatDefOf.FixBrokenDownBuildingSuccessChance, Priority.Wanted }, { StatDefOf.ConstructionSpeed, Priority.Wanted }, { StatDefOf.ConstructSuccessChance, Priority.Wanted }, { StatDefOf.SmoothingSpeed, Priority.Wanted }, { StatDefOf.MoveSpeed, Priority.Neutral }, { StatDefOf.WorkSpeedGlobal, Priority.Neutral }, }); ConfigureWorkerOutfit(MakeOutfit(db, "Grower"), new Dictionary <StatDef, float> { { StatDefOf.PlantHarvestYield, Priority.Wanted }, { StatDefOf.PlantWorkSpeed, Priority.Wanted }, { StatDefOf.MoveSpeed, Priority.Neutral }, { StatDefOf.WorkSpeedGlobal, Priority.Desired }, }); ConfigureWorkerOutfit(MakeOutfit(db, "Miner"), new Dictionary <StatDef, float> { { StatDefOf.MiningYield, Priority.Wanted }, { StatDefOf.MiningSpeed, Priority.Wanted }, { StatDefOf.MoveSpeed, Priority.Neutral }, { StatDefOf.WorkSpeedGlobal, Priority.Desired }, }); ConfigureWorkerOutfit(MakeOutfit(db, "Smith"), new Dictionary <StatDef, float> { { StatDef.Named("SmithingSpeed"), Priority.Wanted }, { StatDefOf.WorkSpeedGlobal, Priority.Desired }, }); ConfigureWorkerOutfit(MakeOutfit(db, "Tailor"), new Dictionary <StatDef, float> { { StatDef.Named("TailoringSpeed"), Priority.Wanted }, { StatDefOf.WorkSpeedGlobal, Priority.Desired }, }); ConfigureWorkerOutfit(MakeOutfit(db, "Artist"), new Dictionary <StatDef, float> { { StatDef.Named("SculptingSpeed"), Priority.Wanted }, { StatDefOf.WorkSpeedGlobal, Priority.Desired }, }); ConfigureWorkerOutfit(MakeOutfit(db, "Crafter"), new Dictionary <StatDef, float> { { StatDef.Named("SmeltingSpeed"), Priority.Wanted }, { StatDef.Named("ButcheryMechanoidSpeed"), Priority.Wanted }, { StatDef.Named("ButcheryMechanoidEfficiency"), Priority.Wanted }, { StatDefOf.WorkSpeedGlobal, Priority.Wanted }, }); ConfigureWorkerOutfit(MakeOutfit(db, "Hauler"), new Dictionary <StatDef, float> { { StatDefOf.MoveSpeed, Priority.Wanted }, { StatDefOf.CarryingCapacity, Priority.Wanted }, }); ConfigureWorkerOutfit(MakeOutfit(db, "Cleaner"), new Dictionary <StatDef, float> { { StatDefOf.MoveSpeed, Priority.Wanted }, { StatDefOf.WorkSpeedGlobal, Priority.Wanted }, }); ConfigureWorkerOutfit(MakeOutfit(db, "Researcher"), new Dictionary <StatDef, float> { { StatDefOf.ResearchSpeed, Priority.Wanted }, { StatDefOf.WorkSpeedGlobal, Priority.Desired }, }); ConfigureSoldierOutfit(MakeOutfit(db, "Brawler"), new Dictionary <StatDef, float> { { StatDefOf.MoveSpeed, Priority.Wanted }, { StatDefOf.AimingDelayFactor, Priority.Unwanted }, { StatDefOf.MeleeDPS, Priority.Wanted }, { StatDefOf.MeleeHitChance, Priority.Wanted }, { StatDefOf.MeleeDodgeChance, Priority.Wanted }, { StatDefOf.ArmorRating_Blunt, Priority.Neutral }, { StatDefOf.ArmorRating_Sharp, Priority.Desired }, { StatDefOf.AccuracyTouch, Priority.Wanted }, { StatDefOf.MeleeWeapon_DamageMultiplier, Priority.Wanted }, { StatDefOf.MeleeWeapon_CooldownMultiplier, Priority.Unwanted }, { StatDefOf.PainShockThreshold, Priority.Wanted }, }); if (vanilla) { ConfigureSoldierOutfit(MakeOutfit(db, "Soldier"), new Dictionary <StatDef, float> { { StatDefOf.ShootingAccuracyPawn, Priority.Wanted }, { StatDefOf.AccuracyShort, Priority.Desired }, { StatDefOf.AccuracyMedium, Priority.Desired }, { StatDefOf.AccuracyLong, Priority.Desired }, { StatDefOf.MoveSpeed, Priority.Desired }, { StatDefOf.ArmorRating_Blunt, Priority.Neutral }, { StatDefOf.ArmorRating_Sharp, Priority.Desired }, { StatDefOf.MeleeDodgeChance, Priority.Neutral }, { StatDefOf.AimingDelayFactor, Priority.Unwanted }, { StatDefOf.RangedWeapon_Cooldown, Priority.Unwanted }, { StatDefOf.PainShockThreshold, Priority.Wanted }, }); ConfigureNudistOutfit(MakeOutfit(db, "Nudist"), new Dictionary <StatDef, float> { { StatDefOf.MoveSpeed, Priority.Desired }, { StatDefOf.WorkSpeedGlobal, Priority.Wanted }, }); } }
public static readonly DamageDef absorbDamageDef = DamageDefOf.Blunt; //The damage def to convert absorbed shots into /// <summary> /// Calculates deflection chance and damage through armor /// </summary> public static int GetAfterArmorDamage(Pawn pawn, int amountInt, BodyPartRecord part, DamageInfo dinfo, bool damageArmor, ref bool deflected) { DamageDef damageDef = dinfo.Def; if (damageDef.armorCategory == DamageArmorCategory.IgnoreArmor) { return(amountInt); } float damageAmount = (float)amountInt; StatDef deflectionStat = damageDef.armorCategory.DeflectionStat(); float pierceAmount = 0f; //Check if the projectile has the armor-piercing comp CompProperties_AP props = null; if (dinfo.Source != null) { VerbProperties verbProps = dinfo.Source.Verbs.Where(x => x.isPrimary).First(); if (verbProps != null) { ThingDef projectile = verbProps.projectileDef; if (projectile != null && projectile.HasComp(typeof(CompAP))) { props = (CompProperties_AP)projectile.GetCompProperties(typeof(CompAP)); } } //Check weapon for comp if projectile doesn't have it if (props == null && dinfo.Source.HasComp(typeof(CompAP))) { props = (CompProperties_AP)dinfo.Source.GetCompProperties(typeof(CompAP)); } } if (props != null) { pierceAmount = props.armorPenetration; } //Run armor calculations on all apparel if (pawn.apparel != null) { List <Apparel> wornApparel = new List <Apparel>(pawn.apparel.WornApparel); for (int i = wornApparel.Count - 1; i >= 0; i--) { if (wornApparel[i].def.apparel.CoversBodyPart(part)) { Thing armorThing = damageArmor ? wornApparel[i] : null; //Check for deflection if (Utility.ApplyArmor(ref damageAmount, ref pierceAmount, wornApparel[i].GetStatValue(deflectionStat, true), armorThing, damageDef)) { deflected = true; if (damageDef != absorbDamageDef) { damageDef = absorbDamageDef; deflectionStat = damageDef.armorCategory.DeflectionStat(); i++; } } if (damageAmount < 0.001) { return(0); } } } } //Check for pawn racial armor if (Utility.ApplyArmor(ref damageAmount, ref pierceAmount, pawn.GetStatValue(deflectionStat, true), null, damageDef)) { deflected = true; if (damageAmount < 0.001) { return(0); } damageDef = absorbDamageDef; deflectionStat = damageDef.armorCategory.DeflectionStat(); Utility.ApplyArmor(ref damageAmount, ref pierceAmount, pawn.GetStatValue(deflectionStat, true), pawn, damageDef); } return(Mathf.RoundToInt(damageAmount)); }
static string AgregateApparelBreakDown(IEnumerable <BodyPartRecord> bodyParts, IEnumerable <Apparel> apparels, StatDef stat, float natValue, string unit) { string text = ""; foreach (BodyPartRecord bodyPartRecord in bodyParts) { float num = bodyPartRecord.isNaturalArmor() ? natValue : 0f; if (bodyPartRecord.depth == BodyPartDepth.Outside && (bodyPartRecord.coverage >= 0.1 || bodyPartRecord.def == BodyPartDefOf.Eye || bodyPartRecord.def == BodyPartDefOf.Neck)) { text = text + bodyPartRecord.LabelCap + ": "; if (!apparels.EnumerableNullOrEmpty()) { foreach (Apparel apparel in apparels) { if (apparel.def.apparel.CoversBodyPart(bodyPartRecord)) { num += apparel.GetStatValue(stat, true); } } } text = text + FormatArmorValue(num, unit) + "\n"; } } return(text); }
public static float?GetStatOffsetValue(this ThingDef stuff, StatDef statDef) { StatModifier?factorFromDef = stuff.stuffProps?.statOffsets?.FirstOrDefault(fa => fa.stat == statDef); return(factorFromDef?.value); }
static bool Prefix(StatWorker __instance, StatRequest req, ref bool __result, ref StatDef ___stat) { if (___stat.category == WTH_DefOf.WTH_StatCategory_HackedMechanoid && req.Thing is Pawn pawn) { __result = pawn.IsHacked(); return(false); } if (___stat.category == WTH_DefOf.WTH_StatCategory_Colonist && req.Thing is Pawn pawn2) { __result = pawn2.IsColonistPlayerControlled; return(false); } if (___stat.category == WTH_DefOf.WTH_StatCategory_Platform && req.Thing is Building_BaseMechanoidPlatform) { __result = true; return(false); } if (___stat.category == WTH_DefOf.WTH_StatCategory_HackedMechanoid || ___stat.category == WTH_DefOf.WTH_StatCategory_Colonist || ___stat.category == WTH_DefOf.WTH_StatCategory_Platform) { __result = false; return(false); } return(true); }
public Jumps() { Definition = StatDef.Register(token, recordType, dataType, 0, null); FullText = fullText; }
public static string GetName(Thing thing, StatDef stat) { return(GetValDetour ? null : ByDef ? $"{stat.defName} for {thing.def.defName}" : stat.defName); }
public static bool UserEffect(this Verb verb, out float Chance, out HediffDef Effect, out StatDef ResistStat, out List <string> ImmuneList) { Chance = 0; Effect = null; ResistStat = null; ImmuneList = new List <string>(); bool result = verb.SpecialRules() != null && verb.SpecialRules().EffectsUser&& AMSettings.Instance.AllowUserEffects; if (result) { Effect = verb.SpecialRules().UserEffect; ResistStat = verb.SpecialRules().ResistEffectStat; Chance = verb.SpecialRules().EffectsUserChance; ImmuneList = verb.SpecialRules().UserEffectImmuneList; if (verb.SpecialRules().UserEffectImmuneList.Contains(verb.caster.def.defName) || verb.caster == null || !verb.CasterIsPawn) { return(false); } } return(result); }
/// <summary> /// Fires a projectile using the new aiming system /// </summary> /// <returns>True for successful shot, false otherwise</returns> public override bool TryCastShot() { if (!TryFindCEShootLineFromTo(caster.Position, currentTarget, out var shootLine)) { return(false); } if (projectilePropsCE.pelletCount < 1) { Log.Error(EquipmentSource.LabelCap + " tried firing with pelletCount less than 1."); return(false); } bool instant = false; float spreadDegrees = 0; float aperatureSize = 0; if (Projectile.projectile is ProjectilePropertiesCE pprop) { instant = pprop.isInstant; spreadDegrees = (EquipmentSource?.GetStatValue(StatDef.Named("ShotSpread")) ?? 0) * pprop.spreadMult; aperatureSize = 0.03f; } ShiftVecReport report = ShiftVecReportFor(currentTarget); bool pelletMechanicsOnly = false; for (int i = 0; i < projectilePropsCE.pelletCount; i++) { ProjectileCE projectile = (ProjectileCE)ThingMaker.MakeThing(Projectile, null); GenSpawn.Spawn(projectile, shootLine.Source, caster.Map); ShiftTarget(report, pelletMechanicsOnly, instant); //New aiming algorithm projectile.canTargetSelf = false; var targetDistance = (sourceLoc - currentTarget.Cell.ToIntVec2.ToVector2Shifted()).magnitude; projectile.minCollisionDistance = GetMinCollisionDistance(targetDistance); projectile.intendedTarget = currentTarget; projectile.mount = caster.Position.GetThingList(caster.Map).FirstOrDefault(t => t is Pawn && t != caster); projectile.AccuracyFactor = report.accuracyFactor * report.swayDegrees * ((numShotsFired + 1) * 0.75f); if (instant) { var shotHeight = ShotHeight; float tsa = AdjustShotHeight(caster, currentTarget, ref shotHeight); projectile.RayCast( Shooter, verbProps, sourceLoc, shotAngle + tsa, shotRotation, shotHeight, ShotSpeed, spreadDegrees, aperatureSize, EquipmentSource); } else { projectile.Launch( Shooter, //Shooter instead of caster to give turret operators' records the damage/kills obtained sourceLoc, shotAngle, shotRotation, ShotHeight, ShotSpeed, EquipmentSource); } pelletMechanicsOnly = true; } /* * Notify the lighting tracker that shots fired with muzzle flash value of VerbPropsCE.muzzleFlashScale */ LightingTracker.Notify_ShotsFiredAt(caster.Position, intensity: VerbPropsCE.muzzleFlashScale); pelletMechanicsOnly = false; numShotsFired++; if (CompAmmo != null && !CompAmmo.CanBeFiredNow) { CompAmmo?.TryStartReload(); } if (CompReloadable != null) { CompReloadable.UsedOnce(); } return(true); }
public StatPriority(StatDef stat, float priority, StatAssignment assignment = StatAssignment.Automatic) { Stat = stat; Weight = priority; Assignment = assignment; }
private static string FinalValue(StatDef stat, float value) { return("StatsReport_FinalValue".Translate() + ": " + stat.ValueToString(val: value, numberSense: stat.toStringNumberSense) + "\n\n"); }
public StatPriority( StatDef stat, float priority, StatAssignment assignment = StatAssignment.Automatic ) { Stat = stat; Weight = priority; Assignment = assignment; }
public static void Patch_StatWorker_GetExplanationUnfinalized(StatWorker __instance, ref string __result, ref StatRequest req, ToStringNumberSense numberSense, StatDef ___stat) { Pawn pawn = req.Thing as Pawn; if (pawn != null && pawn.GetJobsComp() is DivineJobsComp jobsComp) { StringBuilder builder = new StringBuilder(__result); if (jobsComp.StatOffsets.FirstOrDefault(mod => mod.stat == ___stat) is StatModifier statModifer) { builder.AppendLine(); builder.AppendLine(); builder.AppendLine("DivineJobs_Stats_JobTitle".Translate()); builder.AppendLine(" " + "DivineJobs_Stats_FromJobs".Translate() + ": " + statModifer.value.ToStringByStyle(statModifer.stat.ToStringStyleUnfinalized, ToStringNumberSense.Offset)); __result = builder.ToString().TrimEndNewlines(); } } }
public DamageBlocked() { Definition = StatDef.Register(token, StatRecordType.Sum, StatDataType.ULong, 0, null); FullText = fullText; }
public static float GetStatValue(this Thing thing, StatDef stat, bool applyPostProcess = true) { return stat.Worker.GetValue(thing, applyPostProcess); }
public static string Postfix(string __result, StatRequest req, StatDef ___stat) { if (!req.HasThing || !PsiTechCachingUtility.CachedAffectedStats.Contains(___stat)) { return(__result); } if (req.Thing is Pawn pawn) { var sb = new StringBuilder(); var abilities = pawn.PsiTracker().Abilities; if (abilities.Count > 0) { sb.AppendLine("PsiTech.PsionicAbilitiesReport".Translate() + ":"); } var didHaveEffect = false; foreach (var ability in abilities) { var offset = ability.GetOffsetOfStat(___stat); var factor = ability.GetFactorOfStat(___stat); if (offset != 0) { didHaveEffect = true; sb.AppendLine(" " + ability.Def.label + ": " + offset.ToStringByStyle(___stat.ToStringStyleUnfinalized, ToStringNumberSense.Offset)); } if (factor != 1) { didHaveEffect = true; sb.AppendLine(" " + ability.Def.label + ": " + factor.ToStringByStyle(___stat.ToStringStyleUnfinalized, ToStringNumberSense.Factor)); } } if (didHaveEffect) { __result += "\n\n" + sb; } if (___stat != StatDefOf.PsychicSensitivity) { return(__result); } var field = pawn.Map?.GetComponent <SuppressionFieldManager>().GetEffectOnCell(pawn.Position) ?? 0f; if (field == 0f) { return(__result); } __result += "\n" + "PsiTech.SuppressionFieldEffect".Translate( field.ToStringByStyle(___stat.ToStringStyleUnfinalized, ToStringNumberSense.Offset)); } else if (req.Thing.PsiEquipmentTracker()?.IsPsychic ?? false) { var equip = req.Thing.TryGetComp <CompEquippable>(); if (equip == null || !(equip.PrimaryVerb.caster is Pawn caster)) { return(__result); } var factor = req.Thing.PsiEquipmentTracker().GetTotalFactorOfStat(___stat, caster); if (factor != 1) { __result += "\n\n" + "PsiTech.PsychicWeaponReport".Translate() + factor.ToStringByStyle(___stat.toStringStyle, ToStringNumberSense.Factor); } } return(__result); }
public static void PrefixAbility(MethodBase __originalMethod, AbilityDef def, StatDef stat, ref Profiler __state) { if (Active && !GetValDetour) { string state = string.Empty; if (ByDef) { state = $"{stat.defName} abstract for {def.defName}"; } else { state = $"{stat.defName} abstract"; } __state = ProfileController.Start(state, null, null, __originalMethod); } }
public static readonly DamageDef absorbDamageDef = DamageDefOf.Blunt; //The damage def to convert absorbed shots into /// <summary> /// Calculates deflection chance and damage through armor /// </summary> public static int GetAfterArmorDamage(Pawn pawn, int damAmountInt, BodyPartRecord part, DamageInfo dinfo, bool damageArmor, ref bool deflected) { DamageDef damageDef = dinfo.Def; if (damageDef.armorCategory == DamageArmorCategory.IgnoreArmor) { return(damAmountInt); } float damageAmount = (float)damAmountInt; StatDef deflectionStat = damageDef.armorCategory.DeflectionStat(); // Get armor penetration value float pierceAmount = 0f; if (dinfo.Source != null) { ProjectilePropertiesCR projectileProps = dinfo.Source.projectile as ProjectilePropertiesCR; if (projectileProps != null) { pierceAmount = projectileProps.armorPenetration; } else if (dinfo.Instigator != null) { Pawn instigatorPawn = dinfo.Instigator as Pawn; if (instigatorPawn != null) { if (instigatorPawn.equipment != null && instigatorPawn.equipment.Primary != null) { pierceAmount = instigatorPawn.equipment.Primary.GetStatValue(StatDef.Named("ArmorPenetration")); } else { pierceAmount = instigatorPawn.GetStatValue(StatDef.Named("ArmorPenetration")); } } } } // Run armor calculations on all apparel if (pawn.apparel != null) { List <Apparel> wornApparel = new List <Apparel>(pawn.apparel.WornApparel); for (int i = wornApparel.Count - 1; i >= 0; i--) { if (wornApparel[i].def.apparel.CoversBodyPart(part)) { Thing armorThing = damageArmor ? wornApparel[i] : null; //Check for deflection if (Utility.ApplyArmor(ref damageAmount, ref pierceAmount, wornApparel[i].GetStatValue(deflectionStat, true), armorThing, damageDef)) { deflected = true; if (damageDef != absorbDamageDef) { damageDef = absorbDamageDef; deflectionStat = damageDef.armorCategory.DeflectionStat(); i++; } } if (damageAmount < 0.001) { return(0); } } } } float pawnArmorAmount = 0f; bool partCoveredByArmor = false; if (part.IsInGroup(DefDatabase <BodyPartGroupDef> .GetNamed("CoveredByNaturalArmor"))) { partCoveredByArmor = true; } else { BodyPartRecord outerPart = part; while (outerPart.parent != null && outerPart.depth != BodyPartDepth.Outside) { outerPart = outerPart.parent; } partCoveredByArmor = outerPart != part && outerPart.IsInGroup(DefDatabase <BodyPartGroupDef> .GetNamed("CoveredByNaturalArmor")); } if (partCoveredByArmor) { pawnArmorAmount = pawn.GetStatValue(deflectionStat); } if (pawnArmorAmount > 0 && Utility.ApplyArmor(ref damageAmount, ref pierceAmount, pawnArmorAmount, null, damageDef)) { deflected = true; if (damageAmount < 0.001) { return(0); } damageDef = absorbDamageDef; deflectionStat = damageDef.armorCategory.DeflectionStat(); Utility.ApplyArmor(ref damageAmount, ref pierceAmount, pawn.GetStatValue(deflectionStat, true), pawn, damageDef); } return(Mathf.RoundToInt(damageAmount)); }
public static float GetValueFromComp(Pawn pawn, StatDef stat) => pawn.TryGetComp <CompHybrid>()?.GetStatFactor(stat) ?? 1f;
public override string GetStatDrawEntryLabel(StatDef stat, float value, ToStringNumberSense numberSense, StatRequest optionalReq) { var ammoProps = (optionalReq.Def as ThingDef)?.GetCompProperties <CompProperties_AmmoUser>(); return(ammoProps.magazineSize + " / " + GenText.ToStringByStyle((ammoProps.reloadTime), ToStringStyle.FloatTwo) + " s"); }
// Modified PathGrid.CalculatedCostAt() public static int PathGrid_CalculatedCostAt(Pawn Pawn, IntVec3 c) { IntVec3 prevCell = Pawn.Position; // Modified beahaviour: // - Apply CountersIcePenalty and CountersSnowPenalty stats // - When snow it's medium or thicker, terrain does not apply anymore. TerrainDef terrainDef = Pawn.Map.terrainGrid.TerrainAt(c); if (terrainDef == null || terrainDef.passability == Traversability.Impassable) { return(10000); } // Get terrain path cost int pcTerrain = terrainDef.pathCost; if (terrainDef == TerrainDefOf.Ice) { // Apply counter ice penalty pcTerrain = (int)Math.Ceiling((double)((float)pcTerrain * (1f - Pawn.GetStatValue(StatDef.Named("CountersIcePenalty"), true)))); } // Get snow path cost int pcSnow = SnowUtility.MovementTicksAddOn(Pawn.Map.snowGrid.GetCategory(c)); // Apply counter snow penalty pcSnow = (int)Math.Ceiling((double)((float)pcSnow * (1f - Pawn.GetStatValue(StatDef.Named("CountersSnowPenalty"), true)))); int pc = 0; if (Pawn.Map.snowGrid.GetCategory(c) >= SnowCategory.Medium) { // Snow is thick, we don't consider terrain path cost pc = pcSnow; } else { // Snow is thin, we apply the highest path cost pc = pcTerrain > pcSnow ? pcTerrain : pcSnow; } bool flagDoor = false; List <Thing> list = Pawn.Map.thingGrid.ThingsListAt(c); for (int i = 0; i < list.Count; i++) { Thing thing = list[i]; if (thing.def.passability == Traversability.Impassable) { return(10000); } if (!PathGrid_IsPathCostIgnoreRepeater(thing.def) || !prevCell.IsValid || !PathGrid_ContainsPathCostIgnoreRepeater(Pawn.Map, prevCell)) { int pcThing = thing.def.pathCost; if (pcThing > pc) { pc = pcThing; } } if (thing is Building_Door && prevCell.IsValid) { Building edifice = prevCell.GetEdifice(Pawn.Map); if (edifice != null && edifice is Building_Door) { flagDoor = true; } } } if (flagDoor) { pc += 45; } return(pc); }
/// <summary> /// Refreshes the cached bulk and weight. Call this whenever items are added/removed from inventory /// </summary> public void UpdateInventory() { if (parentPawn == null) { Log.Error("CompInventory on non-pawn " + this.parent.ToString()); return; } float newBulk = 0f; float newWeight = 0f; // Add equipped weapon if (parentPawn.equipment != null && parentPawn.equipment.Primary != null) { GetEquipmentStats(parentPawn.equipment.Primary, out newWeight, out newBulk); } // Add apparel if (parentPawn.apparel != null && parentPawn.apparel.WornApparelCount > 0) { foreach (Thing apparel in parentPawn.apparel.WornApparel) { float apparelBulk = apparel.GetStatValue(StatDef.Named("WornBulk")); float apparelWeight = apparel.GetStatValue(StatDef.Named("WornWeight")); newBulk += apparelBulk; newWeight += apparelWeight; } } // Add inventory items if (parentPawn.inventory != null && parentPawn.inventory.container != null) { ammoListCached.Clear(); meleeWeaponListCached.Clear(); rangedWeaponListCached.Clear(); foreach (Thing thing in parentPawn.inventory.container) { // Check for weapons ThingWithComps eq = thing as ThingWithComps; CompEquippable compEq = thing.TryGetComp <CompEquippable>(); if (eq != null && compEq != null) { if (compEq.PrimaryVerb != null) { rangedWeaponListCached.Add(eq); } else { meleeWeaponListCached.Add(eq); } // Calculate equipment weight float eqWeight; float eqBulk; GetEquipmentStats(eq, out eqWeight, out eqBulk); newWeight += eqWeight * thing.stackCount; newBulk += eqBulk * thing.stackCount; } else { // Add item weight newBulk += thing.GetStatValue(StatDef.Named("Bulk")) * thing.stackCount; newWeight += thing.GetStatValue(StatDef.Named("Weight")) * thing.stackCount; } // Update ammo list if (thing.def is AmmoDef) { ammoListCached.Add(thing); } } } this.currentBulkCached = newBulk; this.currentWeightCached = newWeight; }
static void TryDrawOverallArmor1(object tab, ref float top, float left, float width, StatDef stat, string label, string unit, Texture image) { Pawn pawn = (Pawn)LSelPawnForGear.GetValue(tab); // float statValue = pawn.GetStatValue(stat, true); float num = statValue; Pawn_ApparelTracker apparel = pawn.apparel; List <Apparel> list = pawn?.apparel.WornApparel; num += AgregateApparelStat(list, stat); // if (num > 0.0001f) { float statIconSize = (float)LstatIconSize.GetValue(null); float stdThingIconSize = (float)LstdThingIconSize.GetValue(null); float stdThingRowHeight = (float)LstdThingRowHeight.GetValue(null); string text = AgregateApparelBreakDown(pawn.RaceProps.body.AllParts, list, stat, statValue, unit); Rect rect = new Rect(left, top, width, statIconSize); Sandy_Utility.LabelWithIcon(rect, image, statIconSize, statIconSize, label, FormatArmorValue(num, unit), text); top += stdThingRowHeight; } }
public RandomNumber() { random = new Random(); Definition = StatDef.Register(token, StatRecordType.Newest, StatDataType.ULong, 0); FullText = fulltext; }
public static IEnumerable <Dialog_InfoCard.Hyperlink> Postfix(IEnumerable <Dialog_InfoCard.Hyperlink> original, StatRequest req, StatDef ___apparelStat) { if (req.HasThing && req.Thing != null) { Pawn pawn = req.Thing as Pawn; if (pawn != null && pawn.InBed()) { yield return(new Dialog_InfoCard.Hyperlink(pawn.CurrentBed(), -1)); } } yield break; }
public Seed() { Definition = StatDef.Register(token, StatRecordType.Newest, StatDataType.ULong, 0); FullText = fulltext; }
public void Draw(Rect rect, ThingWithComps ownerPawn) { Text.Font = GameFont.Small; string value = "-"; switch (oType) { case objectType.Stat: Text.Anchor = TextAnchor.MiddleCenter; StatDef stat = (StatDef)displayObject; string statValue = (stat.ValueToString(ownerPawn.GetStatValue((StatDef)displayObject, true))); Widgets.Label(rect, statValue); if (Mouse.IsOver(rect)) { GUI.DrawTexture(rect, TexUI.HighlightTex); } StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine(stat.LabelCap); stringBuilder.AppendLine(); stringBuilder.AppendLine(stat.description); TooltipHandler.TipRegion(rect, new TipSignal(stringBuilder.ToString(), rect.GetHashCode())); break; case objectType.Skill: if ((ownerPawn is Pawn) && (ownerPawn as Pawn).RaceProps.Humanlike) { DrawSkill(rect, ownerPawn as Pawn); } break; case objectType.Need: if (ownerPawn is Pawn) { DrawNeed(rect, ownerPawn as Pawn); } break; case objectType.Capacity: Text.Anchor = TextAnchor.MiddleCenter; if (ownerPawn is Pawn) { Pawn p = (Pawn)ownerPawn; PawnCapacityDef cap = (PawnCapacityDef)displayObject; Pair <string, Color> effLabel = HealthCardUtility.GetEfficiencyLabel(p, cap); string pawnCapTip = HealthCardUtility.GetPawnCapacityTip(p, cap); // I stole this one line from Fluffy's Medical Tab. THANKS FLUFFY! string capValue = (p.health.capacities.GetEfficiency(cap) * 100f).ToString("F0") + "%"; GUI.color = effLabel.Second; Widgets.Label(rect, capValue); GUI.color = Color.white; if (Mouse.IsOver(rect)) { GUI.DrawTexture(rect, TexUI.HighlightTex); } StringBuilder stringBuilder2 = new StringBuilder(); stringBuilder2.AppendLine(cap.LabelCap); stringBuilder2.AppendLine(); stringBuilder2.AppendLine(cap.description); TooltipHandler.TipRegion(rect, new TipSignal(stringBuilder2.ToString(), rect.GetHashCode())); } break; case objectType.MentalState: Text.Font = GameFont.Tiny; Text.Anchor = TextAnchor.MiddleCenter; if (ownerPawn is Pawn && (ownerPawn as Pawn).MentalState != null) { string ms = ((ownerPawn as Pawn).MentalState.InspectLine); Widgets.Label(rect, ms); if (Mouse.IsOver(rect)) { GUI.DrawTexture(rect, TexUI.HighlightTex); } } Text.Font = GameFont.Medium; break; case objectType.Age: Text.Anchor = TextAnchor.MiddleCenter; string ageValue = ((ownerPawn as Pawn).ageTracker.AgeBiologicalYears.ToString()); Widgets.Label(rect, ageValue); if (Mouse.IsOver(rect)) { GUI.DrawTexture(rect, TexUI.HighlightTex); } break; case objectType.Gear: DrawGear(rect, ownerPawn); break; case objectType.ControlPrisonerGetsFood: if (ownerPawn is Pawn) { if (Mouse.IsOver(rect)) { GUI.DrawTexture(rect, TexUI.HighlightTex); } bool getsFood = (ownerPawn as Pawn).guest.GetsFood; Widgets.CheckboxLabeled(new Rect(rect.x + 8f, rect.y + 3f, 27f, 27f), "", ref getsFood, false); (ownerPawn as Pawn).guest.GetsFood = getsFood; } break; case objectType.ControlPrisonerInteraction: if (ownerPawn is Pawn) { if (Mouse.IsOver(rect)) { GUI.DrawTexture(rect, TexUI.HighlightTex); } float x = 8f; GUI.BeginGroup(rect); IEnumerator enumerator = Enum.GetValues(typeof(PrisonerInteractionMode)).GetEnumerator(); try { while (enumerator.MoveNext()) { PrisonerInteractionMode prisonerInteractionMode = (PrisonerInteractionMode)((byte)enumerator.Current); if (Widgets.RadioButton(new Vector2(x, 3f), (ownerPawn as Pawn).guest.interactionMode == prisonerInteractionMode)) { (ownerPawn as Pawn).guest.interactionMode = prisonerInteractionMode; } TooltipHandler.TipRegion(new Rect(x, 0f, 30f, 30f), new TipSignal(prisonerInteractionMode.GetLabel())); x += 30f; } } finally { IDisposable disposable = enumerator as IDisposable; if (disposable != null) { disposable.Dispose(); } } GUI.EndGroup(); } break; case objectType.ControlMedicalCare: if (ownerPawn is Pawn) { MedicalCareSetter(rect, ref (ownerPawn as Pawn).playerSettings.medCare); } break; case objectType.AnimalMilkFullness: Text.Anchor = TextAnchor.MiddleCenter; if (ownerPawn is Pawn && ((Pawn)ownerPawn).ageTracker.CurLifeStage.milkable) { var comp = ((Pawn)ownerPawn).AllComps.Where <ThingComp>(x => x is CompMilkable).FirstOrDefault(); if (comp != null) { value = ((CompMilkable)comp).Fullness.ToStringPercent(); } } Widgets.Label(rect, value); break; case objectType.AnimalWoolGrowth: Text.Anchor = TextAnchor.MiddleCenter; if (ownerPawn is Pawn && ((Pawn)ownerPawn).ageTracker.CurLifeStage.shearable) { var comp = ((Pawn)ownerPawn).AllComps.Where <ThingComp>(x => x is CompShearable).FirstOrDefault(); if (comp != null) { value = ((CompShearable)comp).Fullness.ToStringPercent(); } } Widgets.Label(rect, value); break; case objectType.CurrentJob: if (ownerPawn is Pawn && ((Pawn)ownerPawn).jobs.curDriver != null) { string text = ((Pawn)ownerPawn).jobs.curDriver.GetReport(); Text.Anchor = TextAnchor.MiddleLeft; Rect tRect = new Rect(rect.xMin + 2, rect.yMin + 3, rect.width - 2, rect.height); GenText.SetTextSizeToFit(text, tRect); if (Text.Font == GameFont.Tiny) { Widgets.Label(tRect, text); } else { Rect sRect = new Rect(rect.xMin + 2, rect.yMin, rect.width - 2, rect.height); Widgets.Label(sRect, text); } if (Mouse.IsOver(rect)) { GUI.DrawTexture(rect, TexUI.HighlightTex); } } break; } }
/// <summary> /// Inserts the extra mining yield multiplier into the mining yield detailed description /// </summary> /// <param name="__result">The description we are adding onto.</param> /// <param name="__instance">The StatWorker</param> /// <param name="___stat">The StatDef of the StatWorker</param> /// <param name="req">The item requesting the stat.</param> /// <param name="numberSense">Unused</param> private static void CuteboldGetExplanationUnfinalizedPostfix(ref string __result, StatDef ___stat, StatRequest req, ToStringNumberSense numberSense) { Pawn pawn = req.Pawn ?? (req.Thing is Pawn ? (Pawn)req.Thing : null); if (pawn?.def != Cutebold_Assemblies.AlienRaceDef || ___stat != StatDefOf.MiningYield) { return; } float rawPercent = CuteboldCalculateExtraPercent(___stat, req, false); float multiplier = MiningMultiplier(pawn); StringBuilder stringBuilder = new StringBuilder(__result); stringBuilder.AppendLine("Cutebold_DarkAdaptation_StatString".Translate()); stringBuilder.AppendLine("Cutebold_DarkAdaptation_StatPercentString".Translate(rawPercent.ToStringPercent(), multiplier.ToStringPercent(), (rawPercent * multiplier).ToStringPercent())); __result = stringBuilder.ToString(); }
public static void Patch_StatWorker_GetValueUnfinalized(StatWorker __instance, ref float __result, ref StatRequest req, bool applyPostProcess, StatDef ___stat) { Pawn pawn = req.Thing as Pawn; if (pawn != null && pawn.GetJobsComp() is DivineJobsComp jobsComp) { if (jobsComp.StatOffsets.FirstOrDefault(mod => mod.stat == ___stat) is StatModifier statModifer) { __result += statModifer.value; } } }
/// 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 override void DoWindowContents(Rect canvas) { // fix weird zooming bug Text.Font = GameFont.Small; // SET UP RECTS // top buttons Rect selectRect = new Rect(0f, 0f, canvas.width * .2f, _topAreaHeight); Rect newRect = new Rect(selectRect.xMax + _margin, 0f, canvas.width * .2f, _topAreaHeight); Rect deleteRect = new Rect(newRect.xMax + _margin, 0f, canvas.width * .2f, _topAreaHeight); // main areas Rect nameRect = new Rect( 0f, _topAreaHeight + _margin * 2, (canvas.width - _margin) / 2f, 24f); Rect slotListRect = new Rect( 0f, nameRect.yMax + _margin, (canvas.width - _margin) / 2f, canvas.height - _topAreaHeight - nameRect.height - _barHeight * 2 - _margin * 5); Rect weightBarRect = new Rect(slotListRect.xMin, slotListRect.yMax + _margin, slotListRect.width, _barHeight); Rect bulkBarRect = new Rect(weightBarRect.xMin, weightBarRect.yMax + _margin, weightBarRect.width, _barHeight); Rect sourceButtonRect = new Rect( slotListRect.xMax + _margin, _topAreaHeight + _margin * 2, (canvas.width - _margin) / 2f, 24f); Rect selectionRect = new Rect( slotListRect.xMax + _margin, sourceButtonRect.yMax + _margin, (canvas.width - _margin) / 2f, canvas.height - 24f - _topAreaHeight - _margin * 3); var loadouts = LoadoutManager.Loadouts; // DRAW CONTENTS // buttons // select loadout if (Widgets.ButtonText(selectRect, "CR.SelectLoadout".Translate())) { List <FloatMenuOption> options = new List <FloatMenuOption>(); if (loadouts.Count == 0) { options.Add(new FloatMenuOption("CR.NoLoadouts".Translate(), null)); } else { for (int i = 0; i < loadouts.Count; i++) { int local_i = i; options.Add(new FloatMenuOption(loadouts[i].LabelCap, delegate { CurrentLoadout = loadouts[local_i]; })); } } Find.WindowStack.Add(new FloatMenu(options)); } // create loadout if (Widgets.ButtonText(newRect, "CR.NewLoadout".Translate())) { var loadout = new Loadout(); LoadoutManager.AddLoadout(loadout); CurrentLoadout = loadout; } // delete loadout if (loadouts.Any(l => l.canBeDeleted) && Widgets.ButtonText(deleteRect, "CR.DeleteLoadout".Translate())) { List <FloatMenuOption> options = new List <FloatMenuOption>(); for (int i = 0; i < loadouts.Count; i++) { int local_i = i; // don't allow deleting the default loadout if (!loadouts[i].canBeDeleted) { continue; } options.Add(new FloatMenuOption(loadouts[i].LabelCap, delegate { if (CurrentLoadout == loadouts[local_i]) { CurrentLoadout = null; } loadouts.Remove(loadouts[local_i]); })); } Find.WindowStack.Add(new FloatMenu(options)); } // draw notification if no loadout selected if (CurrentLoadout == null) { Text.Anchor = TextAnchor.MiddleCenter; GUI.color = Color.grey; Widgets.Label(canvas, "CR.NoLoadoutSelected".Translate()); GUI.color = Color.white; Text.Anchor = TextAnchor.UpperLeft; // and stop further drawing return; } // name DrawNameField(nameRect); // source selection DrawSourceSelection(sourceButtonRect); // selection area DrawSlotSelection(selectionRect); // current slots DrawSlotList(slotListRect); // bars if (CurrentLoadout != null) { Utility_Loadouts.DrawBar(weightBarRect, CurrentLoadout.Weight, StatDef.Named("CarryWeight").defaultBaseValue, "CR.Weight".Translate(), CurrentLoadout.GetWeightTip()); Utility_Loadouts.DrawBar(bulkBarRect, CurrentLoadout.Bulk, StatDef.Named("CarryBulk").defaultBaseValue, "CR.Bulk".Translate(), CurrentLoadout.GetBulkTip()); } // done! }
public static void DoApparelScoreRawStatsHandlers(Pawn pawn, Apparel apparel, StatDef statDef, ref float num) { if (PawnCalcForApparel.ApparelScoreRawStatsHandlers != null) PawnCalcForApparel.ApparelScoreRawStatsHandlers(pawn, apparel, statDef, ref num); }