static TransformerUtility() { PossiblePawnKinds = new[] { PawnKindDefOf.Slave, PawnKindDefOf.Colonist, PawnKindDefOf.SpaceRefugee, PawnKindDefOf.Villager, PawnKindDefOf.Drifter, PawnKindDefOf.AncientSoldier }; DefaultDamageValues = new MutagenDamageProperties(); }
/// <summary> /// applies damage to all apparel the pawn is wearing based on /// </summary> /// <param name="pawn">The pawn.</param> /// <param name="newRace">The new race.</param> /// <param name="mutagen">the mutagen that caused the transformation, if null uses default values for <see cref="MutagenDamageProperties"/></param> /// <exception cref="System.ArgumentNullException"> /// pawn /// or /// newRace /// </exception> public static void ApplyTfDamageToApparel([NotNull] Pawn pawn, [NotNull] ThingDef newRace, [CanBeNull] MutagenDef mutagen) { if (pawn == null) { throw new ArgumentNullException(nameof(pawn)); } if (newRace == null) { throw new ArgumentNullException(nameof(newRace)); } Pawn_ApparelTracker apparelTracker = pawn.apparel; List <Apparel> cachedApparel = apparelTracker?.WornApparel?.ToList(); //make a copy of all worn apparel if (cachedApparel == null || cachedApparel.Count == 0) { return; } MutagenDamageProperties damageProps = mutagen?.damageProperties ?? DefaultDamageValues; float oldSize = pawn.RaceProps.baseBodySize; float newSize = newRace.race.baseBodySize; float percentDiff; if (oldSize < EPSILON && newSize < EPSILON) //prevent division by zero { percentDiff = 0; //if they're both really small say no change } else if (oldSize < EPSILON) { percentDiff = MAX_APPAREL_PDIFF; //if just old size is small then completely destroy the apparel } else { percentDiff = (newSize - oldSize) / oldSize; //signed percent difference between percentDiff += APPAREL_PDIFF_OFFSET; //add a little offset so if the body size is the same or slightly smaller we still apply some damage //trying to account for differences in 'body shape' } float percentDamage = Mathf.Clamp(percentDiff, 0, MAX_APPAREL_PDIFF); //clamp pDiff between [0, Max], if they shrink don't damage apparel percentDamage /= MAX_APPAREL_PDIFF; //normalize the percentDifference to get a percentage to damage apparel by int totalStuffProduced = 0; foreach (Apparel apparel in cachedApparel) { int damage = Mathf.CeilToInt(apparel.MaxHitPoints * percentDamage * damageProps.apparelDamageMultiplier) + damageProps.apparelDamageOffset; int newHitPoints = Mathf.Max(apparel.HitPoints - damage, 0); var damageDone = apparel.HitPoints - newHitPoints; //save the actual damage done apparel.HitPoints = newHitPoints; if (apparel.HitPoints == 0) { apparelTracker.Remove(apparel); apparelTracker.Notify_ApparelRemoved(apparel); apparel.Destroy(); } var stuffProduced = Mathf.FloorToInt(damageDone * damageProps.spawnedBiproductMult); totalStuffProduced += Mathf.Min(stuffProduced, MAX_APPAREL_DAMAGE_PRODUCT_PER_APPAREL); } if (damageProps.biproduct != null && damageProps.spawnedBiproductMult > EPSILON) { Thing thing = ThingMaker.MakeThing(damageProps.biproduct); thing.stackCount = totalStuffProduced; if (pawn.Spawned) { GenPlace.TryPlaceThing(thing, pawn.PositionHeld, pawn.MapHeld, ThingPlaceMode.Near); } else { Caravan caravan = pawn.GetCaravan(); caravan?.AddPawnOrItem(thing, false); } } }